Mercurial > foo_out_sdl
diff foosdk/sdk/pfc/sort.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/pfc/sort.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,282 @@ +#include "pfc-lite.h" +#include "sort.h" +#include "sort2.h" +#include "bit_array_impl.h" +#include "ref_counter.h" + +#if defined(_M_IX86) || defined(_M_IX64) +#include <intrin.h> +#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<width;n++) + { + temp = *ptr2; + *ptr2 = *ptr1; + *ptr1 = temp; + ptr1++; + ptr2++; + } +} + +void reorder(reorder_callback & p_callback,const t_size * p_order,t_size p_count) +{ + t_size done_size = bit_array_bittable::g_estimate_size(p_count); + pfc::array_hybrid_t<unsigned char,1024> done; + done.set_size(done_size); + pfc::memset_t(done,(unsigned char)0); + t_size n; + for(n=0;n<p_count;n++) + { + t_size next = p_order[n]; + if (next!=n && !bit_array_bittable::g_get(done,n)) + { + t_size prev = n; + do + { + PFC_ASSERT(!bit_array_bittable::g_get(done,next)); + PFC_ASSERT(next>n); + PFC_ASSERT(n<p_count); + p_callback.swap(prev,next); + bit_array_bittable::g_set(done,next,true); + prev = next; + next = p_order[next]; + } while(next!=n); + //bit_array_bittable::g_set(done,n,true); + } + } +} + +void reorder_void(void * data,t_size width,const t_size * order,t_size num,void (*swapfunc)(void * item1,void * item2,t_size width)) +{ + unsigned char * base = (unsigned char *) data; + t_size done_size = bit_array_bittable::g_estimate_size(num); + pfc::array_hybrid_t<unsigned char,1024> done; + done.set_size(done_size); + pfc::memset_t(done,(unsigned char)0); + t_size n; + for(n=0;n<num;n++) + { + t_size next = order[n]; + if (next!=n && !bit_array_bittable::g_get(done,n)) + { + t_size prev = n; + do + { + PFC_ASSERT(!bit_array_bittable::g_get(done,next)); + PFC_ASSERT(next>n); + PFC_ASSERT(n<num); + swapfunc(base+width*prev,base+width*next,width); + bit_array_bittable::g_set(done,next,true); + prev = next; + next = order[next]; + } while(next!=n); + //bit_array_bittable::g_set(done,n,true); + } + } +} + +namespace { + +class sort_callback_impl_legacy : public sort_callback +{ +public: + sort_callback_impl_legacy( + void * p_base,t_size p_width, + int (*p_comp)(const void *, const void *), + void (*p_swap)(void *, void *, t_size) + ) : + m_base((char*)p_base), m_width(p_width), + m_comp(p_comp), m_swap(p_swap) + { + } + + + int compare(t_size p_index1, t_size p_index2) const + { + return m_comp(m_base + p_index1 * m_width, m_base + p_index2 * m_width); + } + + void swap(t_size p_index1, t_size p_index2) + { + m_swap(m_base + p_index1 * m_width, m_base + p_index2 * m_width, m_width); + } + +private: + char * m_base; + t_size m_width; + int (*m_comp)(const void *, const void *); + void (*m_swap)(void *, void *, t_size); +}; +} + +void sort_void_ex ( + void *base, + t_size num, + t_size width, + int (*comp)(const void *, const void *), + void (*swap)(void *, void *, t_size) ) +{ + sort_callback_impl_legacy cb(base,width,comp,swap); + sort(cb,num); +} + +static void squaresort(pfc::sort_callback & p_callback,t_size const p_base,t_size const p_count) { + const t_size max = p_base + p_count; + for(t_size walk = p_base + 1; walk < max; ++walk) { + for(t_size prev = p_base; prev < walk; ++prev) { + p_callback.swap_check(prev,walk); + } + } +} + + +inline static void __sort_2elem_helper(pfc::sort_callback & p_callback,t_size & p_elem1,t_size & p_elem2) { + if (p_callback.compare(p_elem1,p_elem2) > 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<p_count;n++) m_order[n] = n; +} + +int sort_callback_stabilizer::compare(t_size p_index1, t_size p_index2) const +{ + int ret = m_chain.compare(p_index1,p_index2); + if (ret == 0) ret = pfc::sgn_t((t_ssize)m_order[p_index1] - (t_ssize)m_order[p_index2]); + return ret; +} + +void sort_callback_stabilizer::swap(t_size p_index1, t_size p_index2) +{ + m_chain.swap(p_index1,p_index2); + pfc::swap_t(m_order[p_index1],m_order[p_index2]); +} + + +void sort_stable(sort_callback & p_callback,t_size p_count) +{ + sort_callback_stabilizer cb(p_callback,p_count); + sort(cb,p_count); +} + + + +permutation_t make_identitiy(size_t count) { + permutation_t ret; ret.set_size_discard(count); + for (size_t walk = 0; walk < count; ++walk) { + ret[walk] = walk; + } + return ret; +} + +} +
