/* ----------------------------------------------------------------------------- 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 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 *ByteSort(uint n, Array *a, Array *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 *tmp = b; b = a; a = tmp; } return a; } //---------------------------------------------------------------------- }; } // GS #endif