Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/BulletCollision/Gimpact/gim_radixsort.h @ 1963

Last change on this file since 1963 was 1963, checked in by rgrieder, 16 years ago

Added Bullet physics engine.

  • Property svn:eol-style set to native
File size: 9.4 KB
Line 
1#ifndef GIM_RADIXSORT_H_INCLUDED
2#define GIM_RADIXSORT_H_INCLUDED
3/*! \file gim_radixsort.h
4\author Francisco Len Nßjera.
5Based on the work of Michael Herf : "fast floating-point radix sort"
6Avaliable on http://www.stereopsis.com/radix.html
7*/
8/*
9-----------------------------------------------------------------------------
10This source file is part of GIMPACT Library.
11
12For the latest info, see http://gimpact.sourceforge.net/
13
14Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
15email: projectileman@yahoo.com
16
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.
28
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.
33
34-----------------------------------------------------------------------------
35*/
36
37#include "gim_memory.h"
38
39/*! \defgroup SORTING
40\brief
41Macros for sorting.
42*/
43
44//! Prototype for comparators
45class less_comparator
46{
47        public:
48
49        template<class T,class Z>
50        inline int operator() ( const T& a, const Z& b )
51        {
52                return ( a<b?-1:(a>b?1:0));
53        }
54};
55
56//! Prototype for comparators
57class integer_comparator
58{
59        public:
60
61        template<class T>
62        inline int operator() ( const T& a, const T& b )
63        {
64                return (int)(a-b);
65        }
66};
67
68//!Prototype for getting the integer representation of an object
69class uint_key_func
70{
71public:
72        template<class T>
73        inline GUINT operator()( const T& a)
74        {
75                return (GUINT)a;
76        }
77};
78
79
80//!Prototype for copying elements
81class copy_elements_func
82{
83public:
84        template<class T>
85        inline void operator()(T& a,T& b)
86        {
87                a = b;
88        }
89};
90
91//!Prototype for copying elements
92class memcopy_elements_func
93{
94public:
95        template<class T>
96        inline void operator()(T& a,T& b)
97        {
98                gim_simd_memcpy(&a,&b,sizeof(T));
99        }
100};
101
102
103//! @{
104struct GIM_RSORT_TOKEN
105{
106    GUINT m_key;
107    GUINT m_value;
108    GIM_RSORT_TOKEN()
109    {
110    }
111    GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
112    {
113        m_key = rtoken.m_key;
114        m_value = rtoken.m_value;
115    }
116
117    inline bool operator <(const GIM_RSORT_TOKEN& other) const
118        {
119                return (m_key < other.m_key);
120        }
121
122        inline bool operator >(const GIM_RSORT_TOKEN& other) const
123        {
124                return (m_key > other.m_key);
125        }
126};
127
128//! Prototype for comparators
129class GIM_RSORT_TOKEN_COMPARATOR
130{
131        public:
132
133        inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b )
134        {
135                return (int)((a.m_key) - (b.m_key));
136        }
137};
138
139
140
141#define kHist 2048
142// ---- utils for accessing 11-bit quantities
143#define D11_0(x)        (x & 0x7FF)
144#define D11_1(x)        (x >> 11 & 0x7FF)
145#define D11_2(x)        (x >> 22 )
146
147
148
149///Radix sort for unsigned integer keys
150inline void gim_radix_sort_rtokens(
151                                GIM_RSORT_TOKEN * array,
152                                GIM_RSORT_TOKEN * sorted, GUINT element_count)
153{
154        GUINT i;
155        GUINT b0[kHist * 3];
156        GUINT *b1 = b0 + kHist;
157        GUINT *b2 = b1 + kHist;
158        for (i = 0; i < kHist * 3; ++i)
159        {
160                b0[i] = 0;
161        }
162        GUINT fi;
163        GUINT pos;
164        for (i = 0; i < element_count; ++i)
165        {
166            fi = array[i].m_key;
167                b0[D11_0(fi)] ++;
168                b1[D11_1(fi)] ++;
169                b2[D11_2(fi)] ++;
170        }
171        {
172                GUINT sum0 = 0, sum1 = 0, sum2 = 0;
173                GUINT tsum;
174                for (i = 0; i < kHist; ++i)
175                {
176                        tsum = b0[i] + sum0;
177                        b0[i] = sum0 - 1;
178                        sum0 = tsum;
179                        tsum = b1[i] + sum1;
180                        b1[i] = sum1 - 1;
181                        sum1 = tsum;
182                        tsum = b2[i] + sum2;
183                        b2[i] = sum2 - 1;
184                        sum2 = tsum;
185                }
186        }
187        for (i = 0; i < element_count; ++i)
188        {
189        fi = array[i].m_key;
190                pos = D11_0(fi);
191                pos = ++b0[pos];
192                sorted[pos].m_key = array[i].m_key;
193                sorted[pos].m_value = array[i].m_value;
194        }
195        for (i = 0; i < element_count; ++i)
196        {
197        fi = sorted[i].m_key;
198                pos = D11_1(fi);
199                pos = ++b1[pos];
200                array[pos].m_key = sorted[i].m_key;
201                array[pos].m_value = sorted[i].m_value;
202        }
203        for (i = 0; i < element_count; ++i)
204        {
205        fi = array[i].m_key;
206                pos = D11_2(fi);
207                pos = ++b2[pos];
208                sorted[pos].m_key = array[i].m_key;
209                sorted[pos].m_value = array[i].m_value;
210        }
211}
212
213
214
215
216/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
217/*!
218*\param array Array of elements to sort
219*\param sorted_tokens Tokens of sorted elements
220*\param element_count element count
221*\param uintkey_macro Functor which retrieves the integer representation of an array element
222*/
223template<typename T, class GETKEY_CLASS>
224void gim_radix_sort_array_tokens(
225                        T* array ,
226                        GIM_RSORT_TOKEN * sorted_tokens,
227                        GUINT element_count,GETKEY_CLASS uintkey_macro)
228{
229        GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
230    for (GUINT _i=0;_i<element_count;++_i)
231    {
232        _unsorted[_i].m_key = uintkey_macro(array[_i]);
233        _unsorted[_i].m_value = _i;
234    }
235    gim_radix_sort_rtokens(_unsorted,sorted_tokens,element_count);
236    gim_free(_unsorted);
237    gim_free(_unsorted);
238}
239
240/// Sorts array in place. For generic use
241/*!
242\param type Type of the array
243\param array
244\param element_count
245\param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
246\param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
247*/
248template<typename T, class GETKEY_CLASS, class COPY_CLASS>
249void gim_radix_sort(
250        T * array, GUINT element_count,
251        GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
252{
253        GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN  *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
254    gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro);
255    T * _original_array = (T *) gim_alloc(sizeof(T)*element_count);
256    gim_simd_memcpy(_original_array,array,sizeof(T)*element_count);
257    for (GUINT _i=0;_i<element_count;++_i)
258    {
259        copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);
260    }
261    gim_free(_original_array);
262    gim_free(_sorted);
263}
264
265//! Failsafe Iterative binary search,
266/*!
267If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
268\param _array
269\param _start_i the beginning of the array
270\param _end_i the ending  index of the array
271\param _search_key Value to find
272\param _comp_macro macro for comparing elements
273\param _found If true the value has found. Boolean
274\param _result_index the index of the found element, or if not found then it will get the index of the  closest bigger value
275*/
276template<class T, typename KEYCLASS, typename COMP_CLASS>
277bool  gim_binary_search_ex(
278                const T* _array, GUINT _start_i,
279                GUINT _end_i,GUINT & _result_index,
280                const KEYCLASS & _search_key,
281                COMP_CLASS _comp_macro)
282{
283        GUINT _k;
284        int _comp_result;
285        GUINT _i = _start_i;
286        GUINT _j = _end_i+1;
287        while (_i < _j)
288        {
289                _k = (_j+_i-1)/2;
290                _comp_result = _comp_macro(_array[_k], _search_key);
291                if (_comp_result == 0)
292                {
293                        _result_index = _k;
294                        return true;
295                }
296                else if (_comp_result < 0)
297                {
298                        _i = _k+1;
299                }
300                else
301                {
302                        _j = _k;
303                }
304        }
305        _result_index = _i;
306        return false;
307}
308
309
310
311//! Failsafe Iterative binary search,Template version
312/*!
313If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
314\param _array
315\param _start_i the beginning of the array
316\param _end_i the ending  index of the array
317\param _search_key Value to find
318\param _result_index the index of the found element, or if not found then it will get the index of the  closest bigger value
319\return true if found, else false
320*/
321template<class T>
322bool gim_binary_search(
323        const T*_array,GUINT _start_i,
324        GUINT _end_i,const T & _search_key,
325        GUINT & _result_index)
326{
327        GUINT _i = _start_i;
328        GUINT _j = _end_i+1;
329        GUINT _k;
330        while(_i < _j)
331        {
332                _k = (_j+_i-1)/2;
333                if(_array[_k]==_search_key)
334                {
335                        _result_index = _k;
336                        return true;
337                }
338                else if (_array[_k]<_search_key)
339                {
340                        _i = _k+1;
341                }
342                else
343                {
344                        _j = _k;
345                }
346        }
347        _result_index = _i;
348        return false;
349}
350
351
352
353///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
354template <typename T, typename COMP_CLASS>
355void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
356{
357        /*  PRE: a[k+1..N] is a heap */
358        /* POST:  a[k..N]  is a heap */
359
360        T temp = pArr[k - 1];
361        /* k has child(s) */
362        while (k <= n/2)
363        {
364                int child = 2*k;
365
366                if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0)
367                {
368                        child++;
369                }
370                /* pick larger child */
371                if (CompareFunc(temp , pArr[child - 1])<0)
372                {
373                        /* move child up */
374                        pArr[k - 1] = pArr[child - 1];
375                        k = child;
376                }
377                else
378                {
379                        break;
380                }
381        }
382        pArr[k - 1] = temp;
383} /*downHeap*/
384
385
386template <typename T, typename COMP_CLASS>
387void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc)
388{
389        /* sort a[0..N-1],  N.B. 0 to N-1 */
390        GUINT k;
391        GUINT n = element_count;
392        for (k = n/2; k > 0; k--)
393        {
394                gim_down_heap(pArr, k, n, CompareFunc);
395        }
396
397        /* a[1..N] is now a heap */
398        while ( n>=2 )
399        {
400                gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */
401                --n;
402                /* restore a[1..i-1] heap */
403                gim_down_heap(pArr, 1, n, CompareFunc);
404        }
405}
406
407
408
409//! @}
410#endif // GIM_RADIXSORT_H_INCLUDED
Note: See TracBrowser for help on using the repository browser.