From 8dd103ca543b38f24d8fd667b7cfa31d68d7d672 Mon Sep 17 00:00:00 2001 From: Richard Thier Date: Sat, 29 Apr 2023 19:14:03 +0200 Subject: [PATCH] apply and prepare operations - first version --- thiersort.h | 94 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/thiersort.h b/thiersort.h index 75d8faf..5738872 100644 --- a/thiersort.h +++ b/thiersort.h @@ -364,28 +364,6 @@ static inline void thiersort8_floatkey( TSTRUE); } -/** - * Create [key, index] pairs from your raw input data sequence. O(n) runtime. - * - * Useful if you have an seq/arr of elements to sort and what them prepared to be - * properly thiersorted as key, index pairs. Then you can apply that reordering - * later using thiersort_apply(..). Also useful for online data stream sources. - * - * BEWARE: The returned array must be freed by you - with a corresponding free. - * An alternative is to do a thiersort_apply(..) call (for the array case). - * - * @param askey The sequence that generates input. Gives the ith elem as key. - * @param length The length of input sequence. - * @param malloc The function to use for allocating the key-index array. - * @returns The array of keys and indices for that key to sort. - */ -static inline struct tselem *thiersort_prepare( - union tskey (askey)(TSU32 i), - TSU32 length, - void* (*malloc)(size_t size)) { - // TODO -} - /** * Create [key, index] pairs from your raw input data array. O(n) runtime. * @@ -396,30 +374,82 @@ static inline struct tselem *thiersort_prepare( * BEWARE: The returned array must be freed by you - with a corresponding free. * An alternative is to do a thiersort_apply(..) call (for the array case). * + * @param arr The input array. * @param askey The sequence that generates input. Gives the ith elem as key. - * @param length The length of input sequence. + * @param elemlen The size of a single elem, + * @param length The length of input sequence. Number of elements. * @param malloc The function to use for allocating the key-index array. - * @returns The array of keys and indices for that key to sort. + * @returns Created array of keys+indices for that key to sort. */ static inline struct tselem *thiersort_prepare_array( void *arr, union tskey (askey)(void *elem), - TSU32 length, TSU32 elemlen, + TSU32 length, void* (*malloc)(size_t size)) { - // TODO + /* Allocate */ + tselem *out = malloc(length * sizeof(tselem)); + + /* Fill */ + TSU32 j = 0; + for(size_t i = 0; i < (length * elemlen); i += elemlen, ++j) { + out[j].key = askey((void *)((TSU8 *)arr + i)); + out[j].i = j; + } + + /* Return */ + return out; } /** * Apply the given [key,index] sort result back to an array. + * + * Rem.: Also frees the sort result array! + * + * @param sortres A thiersort result on previously prepared arr. + * @param arr The original array which was prepared for sort and was sorted. + * @param length The number of element (both in sortres and arr) + * @param elemlen Size of a single element + * @param tmp An array of elemlen bytes to store values for swap! + * @param free The operation used for freeing the sort res array. */ static inline void thiersort_apply( - struct tselem *sortres, - void *arr, - TSU32 length, - TSU32 elemlen, - void (*free)(void *ptr)) { - // TODO + struct tselem *sortres, + void *arr, + TSU32 length, + TSU32 elemsize, + void *tmp, + void (*free)(void *ptr)) { + // Replace all positions + for(TSU32 i = 0; i < length; ++i) { + // Replace the whole chain starting at i (j for chain index) + // This works because we can easily check what does'nt need moves anymore. + TSU32 j = i; + TSU32 ni = sortres[j].i; + + // Until would move to its own position, chain + // This also solves "already at right place" originals. + while(ni != j) { + // xchg j and ni + memcpy(tmp, arr[(size_t)j * elemsize], elemsize); + memcpy( + arr[(size_t)j * elemsize], + arr[(size_t)ni * elemsize], + elemsize); + memcpy(arr[(size_t)ni * elemsize], tmp, elemsize); + + // Mark j index as done in sortres for outer loop. + // This is necessary for inner loop stopping early + // and outer catch up on already processed location. + sortres[j].i = j; + + // Update j and ni + // Now we must find what should be at new location j + // instead of what we swap in there from old j loc. + TSU32 j = ni; + TSU32 ni = sortres[j].i; + } + } } /**