Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

OgreRadixSort.h

Go to the documentation of this file.
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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Mar 12 14:37:47 2006