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
45 template<class T,class Z>
46 inline int operator() ( const T& a, const Z& b )
48 return ( a<b?-1:(a>b?1:0));
52 //! Prototype for comparators
53 class integer_comparator
58 inline int operator() ( const T& a, const T& b )
64 //!Prototype for getting the integer representation of an object
69 inline GUINT operator()( const T& a)
76 //!Prototype for copying elements
77 class copy_elements_func
81 inline void operator()(T& a,T& b)
87 //!Prototype for copying elements
88 class memcopy_elements_func
92 inline void operator()(T& a,T& b)
94 gim_simd_memcpy(&a,&b,sizeof(T));
100 struct GIM_RSORT_TOKEN
107 GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
109 m_key = rtoken.m_key;
110 m_value = rtoken.m_value;
113 inline bool operator <(const GIM_RSORT_TOKEN& other) const
115 return (m_key < other.m_key);
118 inline bool operator >(const GIM_RSORT_TOKEN& other) const
120 return (m_key > other.m_key);
124 //! Prototype for comparators
125 class GIM_RSORT_TOKEN_COMPARATOR
129 inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b )
131 return (int)((a.m_key) - (b.m_key));
138 // ---- utils for accessing 11-bit quantities
139 #define D11_0(x) (x & 0x7FF)
140 #define D11_1(x) (x >> 11 & 0x7FF)
141 #define D11_2(x) (x >> 22 )
145 ///Radix sort for unsigned integer keys
146 inline void gim_radix_sort_rtokens(
147 GIM_RSORT_TOKEN * array,
148 GIM_RSORT_TOKEN * sorted, GUINT element_count)
152 GUINT *b1 = b0 + kHist;
153 GUINT *b2 = b1 + kHist;
154 for (i = 0; i < kHist * 3; ++i)
160 for (i = 0; i < element_count; ++i)
168 GUINT sum0 = 0, sum1 = 0, sum2 = 0;
170 for (i = 0; i < kHist; ++i)
183 for (i = 0; i < element_count; ++i)
188 sorted[pos].m_key = array[i].m_key;
189 sorted[pos].m_value = array[i].m_value;
191 for (i = 0; i < element_count; ++i)
193 fi = sorted[i].m_key;
196 array[pos].m_key = sorted[i].m_key;
197 array[pos].m_value = sorted[i].m_value;
199 for (i = 0; i < element_count; ++i)
204 sorted[pos].m_key = array[i].m_key;
205 sorted[pos].m_value = array[i].m_value;
212 /// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
214 *\param array Array of elements to sort
215 *\param sorted_tokens Tokens of sorted elements
216 *\param element_count element count
217 *\param uintkey_macro Functor which retrieves the integer representation of an array element
219 template<typename T, class GETKEY_CLASS>
220 void gim_radix_sort_array_tokens(
222 GIM_RSORT_TOKEN * sorted_tokens,
223 GUINT element_count,GETKEY_CLASS uintkey_macro)
225 GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
226 for (GUINT _i=0;_i<element_count;++_i)
228 _unsorted[_i].m_key = uintkey_macro(array[_i]);
229 _unsorted[_i].m_value = _i;
231 gim_radix_sort_rtokens(_unsorted,sorted_tokens,element_count);
236 /// Sorts array in place. For generic use
238 \param type Type of the array
241 \param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
242 \param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
244 template<typename T, class GETKEY_CLASS, class COPY_CLASS>
246 T * array, GUINT element_count,
247 GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
249 GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
250 gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro);
251 T * _original_array = (T *) gim_alloc(sizeof(T)*element_count);
252 gim_simd_memcpy(_original_array,array,sizeof(T)*element_count);
253 for (GUINT _i=0;_i<element_count;++_i)
255 copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);
257 gim_free(_original_array);
261 //! Failsafe Iterative binary search,
263 If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
265 \param _start_i the beginning of the array
266 \param _end_i the ending index of the array
267 \param _search_key Value to find
268 \param _comp_macro macro for comparing elements
269 \param _found If true the value has found. Boolean
270 \param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
272 template<class T, typename KEYCLASS, typename COMP_CLASS>
273 bool gim_binary_search_ex(
274 const T* _array, GUINT _start_i,
275 GUINT _end_i,GUINT & _result_index,
276 const KEYCLASS & _search_key,
277 COMP_CLASS _comp_macro)
286 _comp_result = _comp_macro(_array[_k], _search_key);
287 if (_comp_result == 0)
292 else if (_comp_result < 0)
307 //! Failsafe Iterative binary search,Template version
309 If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
311 \param _start_i the beginning of the array
312 \param _end_i the ending index of the array
313 \param _search_key Value to find
314 \param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
315 \return true if found, else false
318 bool gim_binary_search(
319 const T*_array,GUINT _start_i,
320 GUINT _end_i,const T & _search_key,
321 GUINT & _result_index)
329 if(_array[_k]==_search_key)
334 else if (_array[_k]<_search_key)
349 ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
350 template <typename T, typename COMP_CLASS>
351 void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
353 /* PRE: a[k+1..N] is a heap */
354 /* POST: a[k..N] is a heap */
356 T temp = pArr[k - 1];
362 if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0)
366 /* pick larger child */
367 if (CompareFunc(temp , pArr[child - 1])<0)
370 pArr[k - 1] = pArr[child - 1];
382 template <typename T, typename COMP_CLASS>
383 void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc)
385 /* sort a[0..N-1], N.B. 0 to N-1 */
387 GUINT n = element_count;
388 for (k = n/2; k > 0; k--)
390 gim_down_heap(pArr, k, n, CompareFunc);
393 /* a[1..N] is now a heap */
396 gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */
398 /* restore a[1..i-1] heap */
399 gim_down_heap(pArr, 1, n, CompareFunc);
406 #endif // GIM_RADIXSORT_H_INCLUDED