Blender V2.61 - r43446

gim_radixsort.h

Go to the documentation of this file.
00001 #ifndef GIM_RADIXSORT_H_INCLUDED
00002 #define GIM_RADIXSORT_H_INCLUDED
00003 
00008 /*
00009 -----------------------------------------------------------------------------
00010 This source file is part of GIMPACT Library.
00011 
00012 For the latest info, see http://gimpact.sourceforge.net/
00013 
00014 Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
00015 email: projectileman@yahoo.com
00016 
00017  This library is free software; you can redistribute it and/or
00018  modify it under the terms of EITHER:
00019    (1) The GNU Lesser General Public License as published by the Free
00020        Software Foundation; either version 2.1 of the License, or (at
00021        your option) any later version. The text of the GNU Lesser
00022        General Public License is included with this library in the
00023        file GIMPACT-LICENSE-LGPL.TXT.
00024    (2) The BSD-style license that is included with this library in
00025        the file GIMPACT-LICENSE-BSD.TXT.
00026    (3) The zlib/libpng license that is included with this library in
00027        the file GIMPACT-LICENSE-ZLIB.TXT.
00028 
00029  This library is distributed in the hope that it will be useful,
00030  but WITHOUT ANY WARRANTY; without even the implied warranty of
00031  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
00032  GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
00033 
00034 -----------------------------------------------------------------------------
00035 */
00036 
00037 #include "gim_memory.h"
00038 
00041 class less_comparator
00042 {
00043     public:
00044 
00045     template<class T,class Z>
00046     inline int operator() ( const T& a, const Z& b )
00047     {
00048         return ( a<b?-1:(a>b?1:0));
00049     }
00050 };
00051 
00053 class integer_comparator
00054 {
00055     public:
00056 
00057     template<class T>
00058     inline int operator() ( const T& a, const T& b )
00059     {
00060         return (int)(a-b);
00061     }
00062 };
00063 
00065 class uint_key_func
00066 {
00067 public:
00068     template<class T>
00069     inline GUINT operator()( const T& a)
00070     {
00071         return (GUINT)a;
00072     }
00073 };
00074 
00075 
00077 class copy_elements_func
00078 {
00079 public:
00080     template<class T>
00081     inline void operator()(T& a,T& b)
00082     {
00083         a = b;
00084     }
00085 };
00086 
00088 class memcopy_elements_func
00089 {
00090 public:
00091     template<class T>
00092     inline void operator()(T& a,T& b)
00093     {
00094         gim_simd_memcpy(&a,&b,sizeof(T));
00095     }
00096 };
00097 
00098 
00100 struct GIM_RSORT_TOKEN
00101 {
00102     GUINT m_key;
00103     GUINT m_value;
00104     GIM_RSORT_TOKEN()
00105     {
00106     }
00107     GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
00108     {
00109         m_key = rtoken.m_key;
00110         m_value = rtoken.m_value;
00111     }
00112 
00113     inline bool operator <(const GIM_RSORT_TOKEN& other) const
00114     {
00115         return (m_key < other.m_key);
00116     }
00117 
00118     inline bool operator >(const GIM_RSORT_TOKEN& other) const
00119     {
00120         return (m_key > other.m_key);
00121     }
00122 };
00123 
00125 class GIM_RSORT_TOKEN_COMPARATOR
00126 {
00127     public:
00128 
00129     inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b )
00130     {
00131         return (int)((a.m_key) - (b.m_key));
00132     }
00133 };
00134 
00135 
00136 
00137 #define kHist 2048
00138 // ---- utils for accessing 11-bit quantities
00139 #define D11_0(x)    (x & 0x7FF)
00140 #define D11_1(x)    (x >> 11 & 0x7FF)
00141 #define D11_2(x)    (x >> 22 )
00142 
00143 
00144 
00146 inline void gim_radix_sort_rtokens(
00147                 GIM_RSORT_TOKEN * array,
00148                 GIM_RSORT_TOKEN * sorted, GUINT element_count)
00149 {
00150     GUINT i;
00151     GUINT b0[kHist * 3];
00152     GUINT *b1 = b0 + kHist;
00153     GUINT *b2 = b1 + kHist;
00154     for (i = 0; i < kHist * 3; ++i)
00155     {
00156         b0[i] = 0;
00157     }
00158     GUINT fi;
00159     GUINT pos;
00160     for (i = 0; i < element_count; ++i)
00161     {
00162         fi = array[i].m_key;
00163         b0[D11_0(fi)] ++;
00164         b1[D11_1(fi)] ++;
00165         b2[D11_2(fi)] ++;
00166     }
00167     {
00168         GUINT sum0 = 0, sum1 = 0, sum2 = 0;
00169         GUINT tsum;
00170         for (i = 0; i < kHist; ++i)
00171         {
00172             tsum = b0[i] + sum0;
00173             b0[i] = sum0 - 1;
00174             sum0 = tsum;
00175             tsum = b1[i] + sum1;
00176             b1[i] = sum1 - 1;
00177             sum1 = tsum;
00178             tsum = b2[i] + sum2;
00179             b2[i] = sum2 - 1;
00180             sum2 = tsum;
00181         }
00182     }
00183     for (i = 0; i < element_count; ++i)
00184     {
00185         fi = array[i].m_key;
00186         pos = D11_0(fi);
00187         pos = ++b0[pos];
00188         sorted[pos].m_key = array[i].m_key;
00189         sorted[pos].m_value = array[i].m_value;
00190     }
00191     for (i = 0; i < element_count; ++i)
00192     {
00193         fi = sorted[i].m_key;
00194         pos = D11_1(fi);
00195         pos = ++b1[pos];
00196         array[pos].m_key = sorted[i].m_key;
00197         array[pos].m_value = sorted[i].m_value;
00198     }
00199     for (i = 0; i < element_count; ++i)
00200     {
00201         fi = array[i].m_key;
00202         pos = D11_2(fi);
00203         pos = ++b2[pos];
00204         sorted[pos].m_key = array[i].m_key;
00205         sorted[pos].m_value = array[i].m_value;
00206     }
00207 }
00208 
00209 
00210 
00211 
00213 
00219 template<typename T, class GETKEY_CLASS>
00220 void gim_radix_sort_array_tokens(
00221             T* array ,
00222             GIM_RSORT_TOKEN * sorted_tokens,
00223             GUINT element_count,GETKEY_CLASS uintkey_macro)
00224 {
00225     GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
00226     for (GUINT _i=0;_i<element_count;++_i)
00227     {
00228         _unsorted[_i].m_key = uintkey_macro(array[_i]);
00229         _unsorted[_i].m_value = _i;
00230     }
00231     gim_radix_sort_rtokens(_unsorted,sorted_tokens,element_count);
00232     gim_free(_unsorted);
00233     gim_free(_unsorted);
00234 }
00235 
00237 
00244 template<typename T, class GETKEY_CLASS, class COPY_CLASS>
00245 void gim_radix_sort(
00246     T * array, GUINT element_count,
00247     GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
00248 {
00249     GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN  *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
00250     gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro);
00251     T * _original_array = (T *) gim_alloc(sizeof(T)*element_count);
00252     gim_simd_memcpy(_original_array,array,sizeof(T)*element_count);
00253     for (GUINT _i=0;_i<element_count;++_i)
00254     {
00255         copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);
00256     }
00257     gim_free(_original_array);
00258     gim_free(_sorted);
00259 }
00260 
00262 
00272 template<class T, typename KEYCLASS, typename COMP_CLASS>
00273 bool  gim_binary_search_ex(
00274         const T* _array, GUINT _start_i,
00275         GUINT _end_i,GUINT & _result_index,
00276         const KEYCLASS & _search_key,
00277         COMP_CLASS _comp_macro)
00278 {
00279     GUINT _k;
00280     int _comp_result;
00281     GUINT _i = _start_i;
00282     GUINT _j = _end_i+1;
00283     while (_i < _j)
00284     {
00285         _k = (_j+_i-1)/2;
00286         _comp_result = _comp_macro(_array[_k], _search_key);
00287         if (_comp_result == 0)
00288         {
00289             _result_index = _k;
00290             return true;
00291         }
00292         else if (_comp_result < 0)
00293         {
00294             _i = _k+1;
00295         }
00296         else
00297         {
00298             _j = _k;
00299         }
00300     }
00301     _result_index = _i;
00302     return false;
00303 }
00304 
00305 
00306 
00308 
00317 template<class T>
00318 bool gim_binary_search(
00319     const T*_array,GUINT _start_i,
00320     GUINT _end_i,const T & _search_key,
00321     GUINT & _result_index)
00322 {
00323     GUINT _i = _start_i;
00324     GUINT _j = _end_i+1;
00325     GUINT _k;
00326     while(_i < _j)
00327     {
00328         _k = (_j+_i-1)/2;
00329         if(_array[_k]==_search_key)
00330         {
00331             _result_index = _k;
00332             return true;
00333         }
00334         else if (_array[_k]<_search_key)
00335         {
00336             _i = _k+1;
00337         }
00338         else
00339         {
00340             _j = _k;
00341         }
00342     }
00343     _result_index = _i;
00344     return false;
00345 }
00346 
00347 
00348 
00350 template <typename T, typename COMP_CLASS>
00351 void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
00352 {
00353     /*  PRE: a[k+1..N] is a heap */
00354     /* POST:  a[k..N]  is a heap */
00355 
00356     T temp = pArr[k - 1];
00357     /* k has child(s) */
00358     while (k <= n/2)
00359     {
00360         int child = 2*k;
00361 
00362         if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0)
00363         {
00364             child++;
00365         }
00366         /* pick larger child */
00367         if (CompareFunc(temp , pArr[child - 1])<0)
00368         {
00369             /* move child up */
00370             pArr[k - 1] = pArr[child - 1];
00371             k = child;
00372         }
00373         else
00374         {
00375             break;
00376         }
00377     }
00378     pArr[k - 1] = temp;
00379 } /*downHeap*/
00380 
00381 
00382 template <typename T, typename COMP_CLASS>
00383 void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc)
00384 {
00385     /* sort a[0..N-1],  N.B. 0 to N-1 */
00386     GUINT k;
00387     GUINT n = element_count;
00388     for (k = n/2; k > 0; k--)
00389     {
00390         gim_down_heap(pArr, k, n, CompareFunc);
00391     }
00392 
00393     /* a[1..N] is now a heap */
00394     while ( n>=2 )
00395     {
00396         gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */
00397         --n;
00398         /* restore a[1..i-1] heap */
00399         gim_down_heap(pArr, 1, n, CompareFunc);
00400     }
00401 }
00402 
00403 
00404 
00405 
00406 #endif // GIM_RADIXSORT_H_INCLUDED