112 lines
2.5 KiB
C++
112 lines
2.5 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#ifndef __NSORT__
|
|
#define __NSORT__
|
|
|
|
|
|
#include "ntypes.h"
|
|
#include "container/narray.h"
|
|
|
|
|
|
namespace GS {
|
|
|
|
/*!
|
|
Sort class.
|
|
|
|
Can sort floating point numbers using QuickSort.
|
|
Can also sort integer numbers using Radix sort (byte-sort).
|
|
|
|
Use T to specify the type of value to sort and O to track a user value in
|
|
the sorted array (for example an index into the unsorted array).
|
|
|
|
@author Emmanuel Julien (ejulien@gsworks.fr)
|
|
*/
|
|
template <typename T, typename O> struct Sort
|
|
{
|
|
//----------------------------------------------------------------------
|
|
struct Entry
|
|
{
|
|
T v;
|
|
O o;
|
|
};
|
|
//----------------------------------------------------------------------
|
|
|
|
protected:
|
|
|
|
static void inline SwapEntries(Entry &a, Entry &b)
|
|
{ Entry t = a; a = b; b = t; }
|
|
|
|
static void RecurseQuickSort(Entry *entries, int left, int right)
|
|
{
|
|
if (left >= right)
|
|
return;
|
|
|
|
int pivot = (left + right) >> 1;
|
|
SwapEntries(entries[left], entries[pivot]);
|
|
|
|
int ls = left;
|
|
for (int cr = left + 1; cr <= right; ++cr)
|
|
if (entries[cr].v < entries[left].v)
|
|
SwapEntries(entries[cr], entries[++ls]);
|
|
|
|
SwapEntries(entries[left], entries[ls]);
|
|
RecurseQuickSort(entries, left, ls - 1);
|
|
RecurseQuickSort(entries, ls + 1, right);
|
|
}
|
|
|
|
public:
|
|
|
|
/// Quicksort n entries in-place.
|
|
static void QuickSort(int n, Entry *entries)
|
|
{
|
|
RecurseQuickSort(entries, 0, n - 1);
|
|
}
|
|
|
|
/// Byte-sort sort n entries from in to out.
|
|
static Array <Entry> *ByteSort(uint n, Array <Entry> *a, Array <Entry> *b)
|
|
{
|
|
if (!a || !b)
|
|
return 0;
|
|
|
|
uint radix[257];
|
|
|
|
for (size_t pass = 0; pass < sizeof(T); ++pass)
|
|
{
|
|
// clear radix buffer
|
|
for (uint i = 0; i < 257; ++i)
|
|
radix[i] = 0;
|
|
|
|
// count radix
|
|
for (uint i = 0; i < n; ++i)
|
|
++radix[uint((*a)[i].v & 255) + 1];
|
|
|
|
// convert count to index
|
|
for (uint i = 0; i < 256; ++i)
|
|
radix[i + 1] += radix[i];
|
|
|
|
// insert values
|
|
for (uint i = 0; i < n; i++)
|
|
{
|
|
const uint p = radix[uint((*a)[i].v & 255)]++;
|
|
(*b)[p].v = (*a)[i].v >> 8; // transfer & shift radix
|
|
(*b)[p].o = (*a)[i].o;
|
|
}
|
|
|
|
// swap arrays
|
|
Array <Entry> *tmp = b; b = a; a = tmp;
|
|
}
|
|
return a;
|
|
}
|
|
//----------------------------------------------------------------------
|
|
};
|
|
|
|
} // GS
|
|
|
|
|
|
#endif
|
|
|