#include "pfc.h" #if defined(_M_IX86) || defined(_M_IX64) #include #define PFC_HAVE_RDTSC #endif namespace pfc { void swap_void(void * item1,void * item2,t_size width) { unsigned char * ptr1 = (unsigned char*)item1, * ptr2 = (unsigned char*)item2; t_size n; unsigned char temp; for(n=0;n done; done.set_size(done_size); pfc::memset_t(done,(unsigned char)0); t_size n; for(n=0;nn); PFC_ASSERT(n done; done.set_size(done_size); pfc::memset_t(done,(unsigned char)0); t_size n; for(n=0;nn); PFC_ASSERT(n 0) pfc::swap_t(p_elem1,p_elem2); } #ifdef PFC_HAVE_RDTSC static inline t_uint64 uniqueVal() {return __rdtsc();} #else static counter uniqueValCounter; static counter::t_val uniqueVal() { return ++uniqueValCounter; } #endif static t_size myrand(t_size count) { const uint64_t rm = (uint64_t)RAND_MAX + 1; uint64_t m = 1; uint64_t v = 0; for(;;) { v += rand() * m; m *= rm; if (m >= count) break; } v ^= uniqueVal(); return (t_size)(v % count); } inline static t_size __pivot_helper(pfc::sort_callback & p_callback,t_size const p_base,t_size const p_count) { PFC_ASSERT(p_count > 2); //t_size val1 = p_base, val2 = p_base + (p_count / 2), val3 = p_base + (p_count - 1); t_size val1 = myrand(p_count), val2 = myrand(p_count-1), val3 = myrand(p_count-2); if (val2 >= val1) val2++; if (val3 >= val1) val3++; if (val3 >= val2) val3++; val1 += p_base; val2 += p_base; val3 += p_base; __sort_2elem_helper(p_callback,val1,val2); __sort_2elem_helper(p_callback,val1,val3); __sort_2elem_helper(p_callback,val2,val3); return val2; } static void newsort(pfc::sort_callback & p_callback,t_size const p_base,t_size const p_count) { if (p_count <= 4) { squaresort(p_callback,p_base,p_count); return; } t_size pivot = __pivot_helper(p_callback,p_base,p_count); { const t_size target = p_base + p_count - 1; if (pivot != target) { p_callback.swap(pivot,target); pivot = target; } } t_size partition = p_base; { bool asdf = false; for(t_size walk = p_base; walk < pivot; ++walk) { const int comp = p_callback.compare(walk,pivot); bool trigger = false; if (comp == 0) { trigger = asdf; asdf = !asdf; } else if (comp < 0) { trigger = true; } if (trigger) { if (partition != walk) p_callback.swap(partition,walk); partition++; } } } if (pivot != partition) { p_callback.swap(pivot,partition); pivot = partition; } newsort(p_callback,p_base,pivot-p_base); newsort(p_callback,pivot+1,p_count-(pivot+1-p_base)); } void sort(pfc::sort_callback & p_callback,t_size p_num) { srand((unsigned int)(uniqueVal() ^ p_num)); newsort(p_callback,0,p_num); } void sort_void(void * base,t_size num,t_size width,int (*comp)(const void *, const void *) ) { sort_void_ex(base,num,width,comp,swap_void); } sort_callback_stabilizer::sort_callback_stabilizer(sort_callback & p_chain,t_size p_count) : m_chain(p_chain) { m_order.set_size(p_count); t_size n; for(n=0;n