1 #ifndef GIM_RADIXSORT_H_INCLUDED
2 #define GIM_RADIXSORT_H_INCLUDED
3 /*! \file gim_radixsort.h
4 \author Francisco Leon Najera.
5 Based on the work of Michael Herf : "fast floating-point radix sort"
6 Avaliable on http://www.stereopsis.com/radix.html
9 -----------------------------------------------------------------------------
10 This source file is part of GIMPACT Library.
12 For the latest info, see http://gimpact.sourceforge.net/
14 Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
15 email: projectileman@yahoo.com
17 This library is free software; you can redistribute it and/or
18 modify it under the terms of EITHER:
19 (1) The GNU Lesser General Public License as published by the Free
20 Software Foundation; either version 2.1 of the License, or (at
21 your option) any later version. The text of the GNU Lesser
22 General Public License is included with this library in the
23 file GIMPACT-LICENSE-LGPL.TXT.
24 (2) The BSD-style license that is included with this library in
25 the file GIMPACT-LICENSE-BSD.TXT.
26 (3) The zlib/libpng license that is included with this library in
27 the file GIMPACT-LICENSE-ZLIB.TXT.
29 This library is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
32 GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
34 -----------------------------------------------------------------------------
37 #include "gim_memory.h"
39 ///Macros for sorting.
40 //! Prototype for comparators
44 template <class T, class Z>
45 inline int operator()(const T& a, const Z& b)
47 return (a < b ? -1 : (a > b ? 1 : 0));
51 //! Prototype for comparators
52 class integer_comparator
56 inline int operator()(const T& a, const T& b)
62 //!Prototype for getting the integer representation of an object
67 inline GUINT operator()(const T& a)
73 //!Prototype for copying elements
74 class copy_elements_func
78 inline void operator()(T& a, T& b)
84 //!Prototype for copying elements
85 class memcopy_elements_func
89 inline void operator()(T& a, T& b)
91 gim_simd_memcpy(&a, &b, sizeof(T));
96 struct GIM_RSORT_TOKEN
103 GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
105 m_key = rtoken.m_key;
106 m_value = rtoken.m_value;
109 inline bool operator<(const GIM_RSORT_TOKEN& other) const
111 return (m_key < other.m_key);
114 inline bool operator>(const GIM_RSORT_TOKEN& other) const
116 return (m_key > other.m_key);
120 //! Prototype for comparators
121 class GIM_RSORT_TOKEN_COMPARATOR
124 inline int operator()(const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b)
126 return (int)((a.m_key) - (b.m_key));
131 // ---- utils for accessing 11-bit quantities
132 #define D11_0(x) (x & 0x7FF)
133 #define D11_1(x) (x >> 11 & 0x7FF)
134 #define D11_2(x) (x >> 22)
136 ///Radix sort for unsigned integer keys
137 inline void gim_radix_sort_rtokens(
138 GIM_RSORT_TOKEN* array,
139 GIM_RSORT_TOKEN* sorted, GUINT element_count)
143 GUINT* b1 = b0 + kHist;
144 GUINT* b2 = b1 + kHist;
145 for (i = 0; i < kHist * 3; ++i)
151 for (i = 0; i < element_count; ++i)
159 GUINT sum0 = 0, sum1 = 0, sum2 = 0;
161 for (i = 0; i < kHist; ++i)
174 for (i = 0; i < element_count; ++i)
179 sorted[pos].m_key = array[i].m_key;
180 sorted[pos].m_value = array[i].m_value;
182 for (i = 0; i < element_count; ++i)
184 fi = sorted[i].m_key;
187 array[pos].m_key = sorted[i].m_key;
188 array[pos].m_value = sorted[i].m_value;
190 for (i = 0; i < element_count; ++i)
195 sorted[pos].m_key = array[i].m_key;
196 sorted[pos].m_value = array[i].m_value;
200 /// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
202 *\param array Array of elements to sort
203 *\param sorted_tokens Tokens of sorted elements
204 *\param element_count element count
205 *\param uintkey_macro Functor which retrieves the integer representation of an array element
207 template <typename T, class GETKEY_CLASS>
208 void gim_radix_sort_array_tokens(
210 GIM_RSORT_TOKEN* sorted_tokens,
211 GUINT element_count, GETKEY_CLASS uintkey_macro)
213 GIM_RSORT_TOKEN* _unsorted = (GIM_RSORT_TOKEN*)gim_alloc(sizeof(GIM_RSORT_TOKEN) * element_count);
214 for (GUINT _i = 0; _i < element_count; ++_i)
216 _unsorted[_i].m_key = uintkey_macro(array[_i]);
217 _unsorted[_i].m_value = _i;
219 gim_radix_sort_rtokens(_unsorted, sorted_tokens, element_count);
224 /// Sorts array in place. For generic use
226 \param type Type of the array
229 \param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
230 \param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
232 template <typename T, class GETKEY_CLASS, class COPY_CLASS>
234 T* array, GUINT element_count,
235 GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
237 GIM_RSORT_TOKEN* _sorted = (GIM_RSORT_TOKEN*)gim_alloc(sizeof(GIM_RSORT_TOKEN) * element_count);
238 gim_radix_sort_array_tokens(array, _sorted, element_count, get_uintkey_macro);
239 T* _original_array = (T*)gim_alloc(sizeof(T) * element_count);
240 gim_simd_memcpy(_original_array, array, sizeof(T) * element_count);
241 for (GUINT _i = 0; _i < element_count; ++_i)
243 copy_elements_macro(array[_i], _original_array[_sorted[_i].m_value]);
245 gim_free(_original_array);
249 //! Failsafe Iterative binary search,
251 If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
253 \param _start_i the beginning of the array
254 \param _end_i the ending index of the array
255 \param _search_key Value to find
256 \param _comp_macro macro for comparing elements
257 \param _found If true the value has found. Boolean
258 \param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
260 template <class T, typename KEYCLASS, typename COMP_CLASS>
261 bool gim_binary_search_ex(
262 const T* _array, GUINT _start_i,
263 GUINT _end_i, GUINT& _result_index,
264 const KEYCLASS& _search_key,
265 COMP_CLASS _comp_macro)
270 GUINT _j = _end_i + 1;
273 _k = (_j + _i - 1) / 2;
274 _comp_result = _comp_macro(_array[_k], _search_key);
275 if (_comp_result == 0)
280 else if (_comp_result < 0)
293 //! Failsafe Iterative binary search,Template version
295 If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
297 \param _start_i the beginning of the array
298 \param _end_i the ending index of the array
299 \param _search_key Value to find
300 \param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
301 \return true if found, else false
304 bool gim_binary_search(
305 const T* _array, GUINT _start_i,
306 GUINT _end_i, const T& _search_key,
307 GUINT& _result_index)
310 GUINT _j = _end_i + 1;
314 _k = (_j + _i - 1) / 2;
315 if (_array[_k] == _search_key)
320 else if (_array[_k] < _search_key)
333 ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
334 template <typename T, typename COMP_CLASS>
335 void gim_down_heap(T* pArr, GUINT k, GUINT n, COMP_CLASS CompareFunc)
337 /* PRE: a[k+1..N] is a heap */
338 /* POST: a[k..N] is a heap */
340 T temp = pArr[k - 1];
346 if ((child < (int)n) && CompareFunc(pArr[child - 1], pArr[child]) < 0)
350 /* pick larger child */
351 if (CompareFunc(temp, pArr[child - 1]) < 0)
354 pArr[k - 1] = pArr[child - 1];
365 template <typename T, typename COMP_CLASS>
366 void gim_heap_sort(T* pArr, GUINT element_count, COMP_CLASS CompareFunc)
368 /* sort a[0..N-1], N.B. 0 to N-1 */
370 GUINT n = element_count;
371 for (k = n / 2; k > 0; k--)
373 gim_down_heap(pArr, k, n, CompareFunc);
376 /* a[1..N] is now a heap */
379 gim_swap_elements(pArr, 0, n - 1); /* largest of a[0..n-1] */
381 /* restore a[1..i-1] heap */
382 gim_down_heap(pArr, 1, n, CompareFunc);
386 #endif // GIM_RADIXSORT_H_INCLUDED