00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright (c) 2000-2012 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef __RadixSort_H__ 00029 #define __RadixSort_H__ 00030 00031 #include "OgrePrerequisites.h" 00032 00033 namespace Ogre { 00034 00087 template <class TContainer, class TContainerValueType, typename TCompValueType> 00088 class RadixSort 00089 { 00090 public: 00091 typedef typename TContainer::iterator ContainerIter; 00092 protected: 00095 int mCounters[4][256]; 00097 int mOffsets[256]; 00099 int mSortSize; 00101 int mNumPasses; 00102 00103 struct SortEntry 00104 { 00105 TCompValueType key; 00106 ContainerIter iter; 00107 SortEntry() {} 00108 SortEntry(TCompValueType k, ContainerIter it) 00109 : key(k), iter(it) {} 00110 00111 }; 00113 typedef std::vector<SortEntry, STLAllocator<SortEntry, GeneralAllocPolicy> > SortVector; 00114 SortVector mSortArea1; 00115 SortVector mSortArea2; 00116 SortVector* mSrc; 00117 SortVector* mDest; 00118 TContainer mTmpContainer; // initial copy 00119 00120 00121 void sortPass(int byteIndex) 00122 { 00123 // Calculate offsets 00124 // Basically this just leaves gaps for duplicate entries to fill 00125 mOffsets[0] = 0; 00126 for (int i = 1; i < 256; ++i) 00127 { 00128 mOffsets[i] = mOffsets[i-1] + mCounters[byteIndex][i-1]; 00129 } 00130 00131 // Sort pass 00132 for (int i = 0; i < mSortSize; ++i) 00133 { 00134 unsigned char byteVal = getByte(byteIndex, (*mSrc)[i].key); 00135 (*mDest)[mOffsets[byteVal]++] = (*mSrc)[i]; 00136 } 00137 00138 } 00139 template <typename T> 00140 void finalPass(int byteIndex, T val) 00141 { 00142 // default is to do normal pass 00143 sortPass(byteIndex); 00144 } 00145 00146 // special case signed int 00147 void finalPass(int byteIndex, int val) 00148 { 00149 int numNeg = 0; 00150 // all negative values are in entries 128+ in most significant byte 00151 for (int i = 128; i < 256; ++i) 00152 { 00153 numNeg += mCounters[byteIndex][i]; 00154 } 00155 // Calculate offsets - positive ones start at the number of negatives 00156 // do positive numbers 00157 mOffsets[0] = numNeg; 00158 for (int i = 1; i < 128; ++i) 00159 { 00160 mOffsets[i] = mOffsets[i-1] + mCounters[byteIndex][i-1]; 00161 } 00162 // Do negative numbers (must start at zero) 00163 // No need to invert ordering, already correct (-1 is highest number) 00164 mOffsets[128] = 0; 00165 for (int i = 129; i < 256; ++i) 00166 { 00167 mOffsets[i] = mOffsets[i-1] + mCounters[byteIndex][i-1]; 00168 } 00169 00170 // Sort pass 00171 for (int i = 0; i < mSortSize; ++i) 00172 { 00173 unsigned char byteVal = getByte(byteIndex, (*mSrc)[i].key); 00174 (*mDest)[mOffsets[byteVal]++] = (*mSrc)[i]; 00175 } 00176 } 00177 00178 00179 // special case float 00180 void finalPass(int byteIndex, float val) 00181 { 00182 // floats need to be special cased since negative numbers will come 00183 // after positives (high bit = sign) and will be in reverse order 00184 // (no ones-complement of the +ve value) 00185 int numNeg = 0; 00186 // all negative values are in entries 128+ in most significant byte 00187 for (int i = 128; i < 256; ++i) 00188 { 00189 numNeg += mCounters[byteIndex][i]; 00190 } 00191 // Calculate offsets - positive ones start at the number of negatives 00192 // do positive numbers normally 00193 mOffsets[0] = numNeg; 00194 for (int i = 1; i < 128; ++i) 00195 { 00196 mOffsets[i] = mOffsets[i-1] + mCounters[byteIndex][i-1]; 00197 } 00198 // Do negative numbers (must start at zero) 00199 // Also need to invert ordering 00200 // In order to preserve the stability of the sort (essential since 00201 // we rely on previous bytes already being sorted) we have to count 00202 // backwards in our offsets from 00203 mOffsets[255] = mCounters[byteIndex][255]; 00204 for (int i = 254; i > 127; --i) 00205 { 00206 mOffsets[i] = mOffsets[i+1] + mCounters[byteIndex][i]; 00207 } 00208 00209 // Sort pass 00210 for (int i = 0; i < mSortSize; ++i) 00211 { 00212 unsigned char byteVal = getByte(byteIndex, (*mSrc)[i].key); 00213 if (byteVal > 127) 00214 { 00215 // -ve; pre-decrement since offsets set to count 00216 (*mDest)[--mOffsets[byteVal]] = (*mSrc)[i]; 00217 } 00218 else 00219 { 00220 // +ve 00221 (*mDest)[mOffsets[byteVal]++] = (*mSrc)[i]; 00222 } 00223 } 00224 } 00225 00226 inline unsigned char getByte(int byteIndex, TCompValueType val) 00227 { 00228 #if OGRE_ENDIAN == OGRE_ENDIAN_LITTLE 00229 return ((unsigned char*)(&val))[byteIndex]; 00230 #else 00231 return ((unsigned char*)(&val))[mNumPasses - byteIndex - 1]; 00232 #endif 00233 } 00234 00235 public: 00236 00237 RadixSort() {} 00238 ~RadixSort() {} 00239 00245 template <class TFunction> 00246 void sort(TContainer& container, TFunction func) 00247 { 00248 if (container.empty()) 00249 return; 00250 00251 // Set up the sort areas 00252 mSortSize = static_cast<int>(container.size()); 00253 mSortArea1.resize(container.size()); 00254 mSortArea2.resize(container.size()); 00255 00256 // Copy data now (we need constant iterators for sorting) 00257 mTmpContainer = container; 00258 00259 mNumPasses = sizeof(TCompValueType); 00260 00261 // Counter pass 00262 // Initialise the counts 00263 int p; 00264 for (p = 0; p < mNumPasses; ++p) 00265 memset(mCounters[p], 0, sizeof(int) * 256); 00266 00267 // Perform alpha pass to count 00268 ContainerIter i = mTmpContainer.begin(); 00269 TCompValueType prevValue = func.operator()(*i); 00270 bool needsSorting = false; 00271 for (int u = 0; i != mTmpContainer.end(); ++i, ++u) 00272 { 00273 // get sort value 00274 TCompValueType val = func.operator()(*i); 00275 // cheap check to see if needs sorting (temporal coherence) 00276 if (!needsSorting && val < prevValue) 00277 needsSorting = true; 00278 00279 // Create a sort entry 00280 mSortArea1[u].key = val; 00281 mSortArea1[u].iter = i; 00282 00283 // increase counters 00284 for (p = 0; p < mNumPasses; ++p) 00285 { 00286 unsigned char byteVal = getByte(p, val); 00287 mCounters[p][byteVal]++; 00288 } 00289 00290 prevValue = val; 00291 00292 } 00293 00294 // early exit if already sorted 00295 if (!needsSorting) 00296 return; 00297 00298 00299 // Sort passes 00300 mSrc = &mSortArea1; 00301 mDest = &mSortArea2; 00302 00303 for (p = 0; p < mNumPasses - 1; ++p) 00304 { 00305 sortPass(p); 00306 // flip src/dst 00307 SortVector* tmp = mSrc; 00308 mSrc = mDest; 00309 mDest = tmp; 00310 } 00311 // Final pass may differ, make polymorphic 00312 finalPass(p, prevValue); 00313 00314 // Copy everything back 00315 int c = 0; 00316 for (i = container.begin(); 00317 i != container.end(); ++i, ++c) 00318 { 00319 *i = *((*mDest)[c].iter); 00320 } 00321 } 00322 00323 }; 00324 00328 } 00329 #endif 00330
Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:25 2012