Blender V2.61 - r43446
|
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