OGRE
1.9.0
Main Page
Related Pages
Topics
Namespaces
Classes
Files
File List
File Members
OgreMain
include
OgreRadixSort.h
Go to the documentation of this file.
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
(Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#ifndef __RadixSort_H__
29
#define __RadixSort_H__
30
31
#include "
OgrePrerequisites.h
"
32
33
namespace
Ogre
{
34
87
template
<
class
TContainer,
class
TContainerValueType,
typename
TCompValueType>
88
class
RadixSort
89
{
90
public
:
91
typedef
typename
TContainer::iterator
ContainerIter
;
92
protected
:
95
int
mCounters
[4][256];
97
int
mOffsets
[256];
99
int
mSortSize
;
101
int
mNumPasses
;
102
103
struct
SortEntry
104
{
105
TCompValueType
key
;
106
ContainerIter
iter
;
107
SortEntry
() {}
108
SortEntry
(TCompValueType k,
ContainerIter
it)
109
:
key
(k),
iter
(it) {}
110
111
};
112
113
typedef
std::vector<SortEntry, STLAllocator<SortEntry, GeneralAllocPolicy> >
SortVector
;
114
SortVector
mSortArea1
;
115
SortVector
mSortArea2
;
116
SortVector
*
mSrc
;
117
SortVector
*
mDest
;
118
TContainer
mTmpContainer
;
// initial copy
119
120
121
void
sortPass
(
int
byteIndex)
122
{
123
// Calculate offsets
124
// Basically this just leaves gaps for duplicate entries to fill
125
mOffsets
[0] = 0;
126
for
(
int
i = 1; i < 256; ++i)
127
{
128
mOffsets
[i] =
mOffsets
[i-1] +
mCounters
[byteIndex][i-1];
129
}
130
131
// Sort pass
132
for
(
int
i = 0; i <
mSortSize
; ++i)
133
{
134
unsigned
char
byteVal =
getByte
(byteIndex, (*
mSrc
)[i].key);
135
(*mDest)[
mOffsets
[byteVal]++] = (*mSrc)[i];
136
}
137
138
}
139
template
<
typename
T>
140
void
finalPass
(
int
byteIndex, T val)
141
{
142
// default is to do normal pass
143
sortPass
(byteIndex);
144
}
145
146
// special case signed int
147
void
finalPass
(
int
byteIndex,
int
val)
148
{
149
int
numNeg = 0;
150
// all negative values are in entries 128+ in most significant byte
151
for
(
int
i = 128; i < 256; ++i)
152
{
153
numNeg +=
mCounters
[byteIndex][i];
154
}
155
// Calculate offsets - positive ones start at the number of negatives
156
// do positive numbers
157
mOffsets
[0] = numNeg;
158
for
(
int
i = 1; i < 128; ++i)
159
{
160
mOffsets
[i] =
mOffsets
[i-1] +
mCounters
[byteIndex][i-1];
161
}
162
// Do negative numbers (must start at zero)
163
// No need to invert ordering, already correct (-1 is highest number)
164
mOffsets
[128] = 0;
165
for
(
int
i = 129; i < 256; ++i)
166
{
167
mOffsets
[i] =
mOffsets
[i-1] +
mCounters
[byteIndex][i-1];
168
}
169
170
// Sort pass
171
for
(
int
i = 0; i <
mSortSize
; ++i)
172
{
173
unsigned
char
byteVal =
getByte
(byteIndex, (*
mSrc
)[i].key);
174
(*mDest)[
mOffsets
[byteVal]++] = (*mSrc)[i];
175
}
176
}
177
178
179
// special case float
180
void
finalPass
(
int
byteIndex,
float
val)
181
{
182
// floats need to be special cased since negative numbers will come
183
// after positives (high bit = sign) and will be in reverse order
184
// (no ones-complement of the +ve value)
185
int
numNeg = 0;
186
// all negative values are in entries 128+ in most significant byte
187
for
(
int
i = 128; i < 256; ++i)
188
{
189
numNeg +=
mCounters
[byteIndex][i];
190
}
191
// Calculate offsets - positive ones start at the number of negatives
192
// do positive numbers normally
193
mOffsets
[0] = numNeg;
194
for
(
int
i = 1; i < 128; ++i)
195
{
196
mOffsets
[i] =
mOffsets
[i-1] +
mCounters
[byteIndex][i-1];
197
}
198
// Do negative numbers (must start at zero)
199
// Also need to invert ordering
200
// In order to preserve the stability of the sort (essential since
201
// we rely on previous bytes already being sorted) we have to count
202
// backwards in our offsets from
203
mOffsets
[255] =
mCounters
[byteIndex][255];
204
for
(
int
i = 254; i > 127; --i)
205
{
206
mOffsets
[i] =
mOffsets
[i+1] +
mCounters
[byteIndex][i];
207
}
208
209
// Sort pass
210
for
(
int
i = 0; i <
mSortSize
; ++i)
211
{
212
unsigned
char
byteVal =
getByte
(byteIndex, (*
mSrc
)[i].key);
213
if
(byteVal > 127)
214
{
215
// -ve; pre-decrement since offsets set to count
216
(*mDest)[--
mOffsets
[byteVal]] = (*mSrc)[i];
217
}
218
else
219
{
220
// +ve
221
(*mDest)[
mOffsets
[byteVal]++] = (*mSrc)[i];
222
}
223
}
224
}
225
226
inline
unsigned
char
getByte
(
int
byteIndex, TCompValueType val)
227
{
228
#if OGRE_ENDIAN == OGRE_ENDIAN_LITTLE
229
return
((
unsigned
char
*)(&val))[byteIndex];
230
#else
231
return
((
unsigned
char
*)(&val))[
mNumPasses
- byteIndex - 1];
232
#endif
233
}
234
235
public
:
236
237
RadixSort
() {}
238
~RadixSort
() {}
239
245
template
<
class
TFunction>
246
void
sort
(TContainer& container, TFunction func)
247
{
248
if
(container.empty())
249
return
;
250
251
// Set up the sort areas
252
mSortSize
=
static_cast<
int
>
(container.size());
253
mSortArea1
.resize(container.size());
254
mSortArea2
.resize(container.size());
255
256
// Copy data now (we need constant iterators for sorting)
257
mTmpContainer
= container;
258
259
mNumPasses
=
sizeof
(TCompValueType);
260
261
// Counter pass
262
// Initialise the counts
263
int
p;
264
for
(p = 0; p <
mNumPasses
; ++p)
265
memset(
mCounters
[p], 0,
sizeof
(
int
) * 256);
266
267
// Perform alpha pass to count
268
ContainerIter
i =
mTmpContainer
.begin();
269
TCompValueType prevValue = func.operator()(*i);
270
bool
needsSorting =
false
;
271
for
(
int
u = 0; i !=
mTmpContainer
.end(); ++i, ++u)
272
{
273
// get sort value
274
TCompValueType val = func.operator()(*i);
275
// cheap check to see if needs sorting (temporal coherence)
276
if
(!needsSorting && val < prevValue)
277
needsSorting =
true
;
278
279
// Create a sort entry
280
mSortArea1
[u].key = val;
281
mSortArea1
[u].iter = i;
282
283
// increase counters
284
for
(p = 0; p <
mNumPasses
; ++p)
285
{
286
unsigned
char
byteVal =
getByte
(p, val);
287
mCounters
[p][byteVal]++;
288
}
289
290
prevValue = val;
291
292
}
293
294
// early exit if already sorted
295
if
(!needsSorting)
296
return
;
297
298
299
// Sort passes
300
mSrc
= &
mSortArea1
;
301
mDest
= &
mSortArea2
;
302
303
for
(p = 0; p <
mNumPasses
- 1; ++p)
304
{
305
sortPass
(p);
306
// flip src/dst
307
SortVector
* tmp =
mSrc
;
308
mSrc
=
mDest
;
309
mDest
= tmp;
310
}
311
// Final pass may differ, make polymorphic
312
finalPass
(p, prevValue);
313
314
// Copy everything back
315
int
c = 0;
316
for
(i = container.begin();
317
i != container.end(); ++i, ++c)
318
{
319
*i = *((*mDest)[c].iter);
320
}
321
}
322
323
};
324
327
328
}
329
#endif
330
OgrePrerequisites.h
Ogre::RadixSort::mNumPasses
int mNumPasses
Number of passes for this type.
Definition
OgreRadixSort.h:101
Ogre::RadixSort::mOffsets
int mOffsets[256]
Beta-pass offsets.
Definition
OgreRadixSort.h:97
Ogre::RadixSort::sortPass
void sortPass(int byteIndex)
Definition
OgreRadixSort.h:121
Ogre::RadixSort::mSortArea1
SortVector mSortArea1
Definition
OgreRadixSort.h:114
Ogre::RadixSort::RadixSort
RadixSort()
Definition
OgreRadixSort.h:237
Ogre::RadixSort::sort
void sort(TContainer &container, TFunction func)
Main sort function.
Definition
OgreRadixSort.h:246
Ogre::RadixSort::mDest
SortVector * mDest
Definition
OgreRadixSort.h:117
Ogre::RadixSort::~RadixSort
~RadixSort()
Definition
OgreRadixSort.h:238
Ogre::RadixSort::SortVector
std::vector< SortEntry, STLAllocator< SortEntry, GeneralAllocPolicy > > SortVector
Temp sort storage.
Definition
OgreRadixSort.h:113
Ogre::RadixSort::finalPass
void finalPass(int byteIndex, float val)
Definition
OgreRadixSort.h:180
Ogre::RadixSort::mTmpContainer
TContainer mTmpContainer
Definition
OgreRadixSort.h:118
Ogre::RadixSort::mSortSize
int mSortSize
Sort area size.
Definition
OgreRadixSort.h:99
Ogre::RadixSort::finalPass
void finalPass(int byteIndex, int val)
Definition
OgreRadixSort.h:147
Ogre::RadixSort::getByte
unsigned char getByte(int byteIndex, TCompValueType val)
Definition
OgreRadixSort.h:226
Ogre::RadixSort::mCounters
int mCounters[4][256]
Alpha-pass counters of values (histogram) 4 of them so we can radix sort a maximum of a 32bit value.
Definition
OgreRadixSort.h:95
Ogre::RadixSort::finalPass
void finalPass(int byteIndex, T val)
Definition
OgreRadixSort.h:140
Ogre::RadixSort::mSortArea2
SortVector mSortArea2
Definition
OgreRadixSort.h:115
Ogre::RadixSort::ContainerIter
TContainer::iterator ContainerIter
Definition
OgreRadixSort.h:91
Ogre::RadixSort::mSrc
SortVector * mSrc
Definition
OgreRadixSort.h:116
Ogre
Definition
OgreAndroidLogListener.h:35
Ogre::RadixSort::SortEntry::SortEntry
SortEntry(TCompValueType k, ContainerIter it)
Definition
OgreRadixSort.h:108
Ogre::RadixSort::SortEntry::SortEntry
SortEntry()
Definition
OgreRadixSort.h:107
Ogre::RadixSort::SortEntry::key
TCompValueType key
Definition
OgreRadixSort.h:105
Ogre::RadixSort::SortEntry::iter
ContainerIter iter
Definition
OgreRadixSort.h:106
Generated on Sun Jun 1 2025 13:08:47 for OGRE by
1.13.2