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-2005 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #ifndef __RadixSort_H__ 00026 #define __RadixSort_H__ 00027 00028 #include "OgrePrerequisites.h" 00029 00030 namespace Ogre { 00031 00078 template <class TContainer, class TContainerValueType, typename TCompValueType> 00079 class RadixSort 00080 { 00081 public: 00082 typedef typename TContainer::iterator ContainerIter; 00083 protected: 00086 int mCounters[4][256]; 00088 int mOffsets[256]; 00090 int mSortSize; 00092 int mNumPasses; 00093 00094 struct SortEntry 00095 { 00096 TCompValueType key; 00097 ContainerIter iter; 00098 SortEntry() {} 00099 SortEntry(TCompValueType k, ContainerIter it) 00100 : key(k), iter(it) {} 00101 00102 }; 00104 std::vector<SortEntry> mSortArea1; 00105 std::vector<SortEntry> mSortArea2; 00106 std::vector<SortEntry>* mSrc; 00107 std::vector<SortEntry>* mDest; 00108 TContainer mTmpContainer; // initial copy 00109 00110 00111 void sortPass(int byteIndex) 00112 { 00113 // Calculate offsets 00114 // Basically this just leaves gaps for duplicate entries to fill 00115 mOffsets[0] = 0; 00116 for (int i = 1; i < 256; ++i) 00117 { 00118 mOffsets[i] = mOffsets[i-1] + mCounters[byteIndex][i-1]; 00119 } 00120 00121 // Sort pass 00122 for (int i = 0; i < mSortSize; ++i) 00123 { 00124 unsigned char byteVal = getByte(byteIndex, (*mSrc)[i].key); 00125 (*mDest)[mOffsets[byteVal]++] = (*mSrc)[i]; 00126 } 00127 00128 } 00129 template <typename T> 00130 void finalPass(int byteIndex, T val) 00131 { 00132 // default is to do normal pass 00133 sortPass(byteIndex); 00134 } 00135 00136 // special case signed int 00137 void finalPass(int byteIndex, int val) 00138 { 00139 int numNeg = 0; 00140 // all negative values are in entries 128+ in most significant byte 00141 for (int i = 128; i < 256; ++i) 00142 { 00143 numNeg += mCounters[byteIndex][i]; 00144 } 00145 // Calculate offsets - positive ones start at the number of negatives 00146 // do positive numbers 00147 mOffsets[0] = numNeg; 00148 for (int i = 1; i < 128; ++i) 00149 { 00150 mOffsets[i] = mOffsets[i-1] + mCounters[byteIndex][i-1]; 00151 } 00152 // Do negative numbers (must start at zero) 00153 // No need to invert ordering, already correct (-1 is highest number) 00154 mOffsets[128] = 0; 00155 for (int i = 129; i < 256; ++i) 00156 { 00157 mOffsets[i] = mOffsets[i-1] + mCounters[byteIndex][i-1]; 00158 } 00159 00160 // Sort pass 00161 for (int i = 0; i < mSortSize; ++i) 00162 { 00163 unsigned char byteVal = getByte(byteIndex, (*mSrc)[i].key); 00164 (*mDest)[mOffsets[byteVal]++] = (*mSrc)[i]; 00165 } 00166 } 00167 00168 00169 // special case float 00170 void finalPass(int byteIndex, float val) 00171 { 00172 // floats need to be special cased since negative numbers will come 00173 // after positives (high bit = sign) and will be in reverse order 00174 // (no ones-complement of the +ve value) 00175 int numNeg = 0; 00176 // all negative values are in entries 128+ in most significant byte 00177 for (int i = 128; i < 256; ++i) 00178 { 00179 numNeg += mCounters[byteIndex][i]; 00180 } 00181 // Calculate offsets - positive ones start at the number of negatives 00182 // do positive numbers normally 00183 mOffsets[0] = numNeg; 00184 for (int i = 1; i < 128; ++i) 00185 { 00186 mOffsets[i] = mOffsets[i-1] + mCounters[byteIndex][i-1]; 00187 } 00188 // Do negative numbers (must start at zero) 00189 // Also need to invert ordering 00190 // In order to preserve the stability of the sort (essential since 00191 // we rely on previous bytes already being sorted) we have to count 00192 // backwards in our offsets from 00193 mOffsets[255] = mCounters[byteIndex][255]; 00194 for (int i = 254; i > 127; --i) 00195 { 00196 mOffsets[i] = mOffsets[i+1] + mCounters[byteIndex][i]; 00197 } 00198 00199 // Sort pass 00200 for (int i = 0; i < mSortSize; ++i) 00201 { 00202 unsigned char byteVal = getByte(byteIndex, (*mSrc)[i].key); 00203 if (byteVal > 127) 00204 { 00205 // -ve; pre-decrement since offsets set to count 00206 (*mDest)[--mOffsets[byteVal]] = (*mSrc)[i]; 00207 } 00208 else 00209 { 00210 // +ve 00211 (*mDest)[mOffsets[byteVal]++] = (*mSrc)[i]; 00212 } 00213 } 00214 } 00215 00216 inline unsigned char getByte(int byteIndex, TCompValueType val) 00217 { 00218 #if OGRE_ENDIAN == OGRE_ENDIAN_LITTLE 00219 return ((unsigned char*)(&val))[byteIndex]; 00220 #else 00221 return ((unsigned char*)(&val))[mNumPasses - byteIndex - 1]; 00222 #endif 00223 } 00224 00225 public: 00226 00227 RadixSort() {} 00228 ~RadixSort() {} 00229 00235 template <class TFunction> 00236 void sort(TContainer& container, TFunction func) 00237 { 00238 if (container.empty()) 00239 return; 00240 00241 // Set up the sort areas 00242 mSortSize = static_cast<int>(container.size()); 00243 mSortArea1.resize(container.size()); 00244 mSortArea2.resize(container.size()); 00245 00246 // Copy data now (we need constant iterators for sorting) 00247 mTmpContainer = container; 00248 00249 mNumPasses = sizeof(TCompValueType); 00250 00251 // Counter pass 00252 // Initialise the counts 00253 int p; 00254 for (p = 0; p < mNumPasses; ++p) 00255 memset(mCounters[p], 0, sizeof(int) * 256); 00256 00257 // Perform alpha pass to count 00258 ContainerIter i = mTmpContainer.begin(); 00259 TCompValueType prevValue = func.operator()(*i); 00260 bool needsSorting = false; 00261 for (int u = 0; i != mTmpContainer.end(); ++i, ++u) 00262 { 00263 // get sort value 00264 TCompValueType val = func.operator()(*i); 00265 // cheap check to see if needs sorting (temporal coherence) 00266 if (!needsSorting && val < prevValue) 00267 needsSorting = true; 00268 00269 // Create a sort entry 00270 mSortArea1[u].key = val; 00271 mSortArea1[u].iter = i; 00272 00273 // increase counters 00274 for (p = 0; p < mNumPasses; ++p) 00275 { 00276 unsigned char byteVal = getByte(p, val); 00277 mCounters[p][byteVal]++; 00278 } 00279 00280 prevValue = val; 00281 00282 } 00283 00284 // early exit if already sorted 00285 if (!needsSorting) 00286 return; 00287 00288 00289 // Sort passes 00290 mSrc = &mSortArea1; 00291 mDest = &mSortArea2; 00292 00293 for (p = 0; p < mNumPasses - 1; ++p) 00294 { 00295 sortPass(p); 00296 // flip src/dst 00297 std::vector<SortEntry>* tmp = mSrc; 00298 mSrc = mDest; 00299 mDest = tmp; 00300 } 00301 // Final pass may differ, make polymorphic 00302 finalPass(p, prevValue); 00303 00304 // Copy everything back 00305 int c = 0; 00306 for (i = container.begin(); 00307 i != container.end(); ++i, ++c) 00308 { 00309 *i = *((*mDest)[c].iter); 00310 } 00311 } 00312 00313 }; 00314 00315 00316 } 00317 #endif 00318
Copyright © 2000-2005 by The OGRE Team
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Mar 12 14:37:47 2006