#ifndef INCLUDED_C_SHELLSORT_H #define INCLUDED_C_SHELLSORT_H #ifndef INCLUDED_C_TYPES_H #include #endif /*INCLUDED_C_TYPES_H*/ #ifndef INCLUDED_C_MEMORY_H #include #endif /*INCLUDED_C_MEMORY_H*/ /* ------------------------------------------------------------------------------------------------------------------ */ /* */ C_STATIC_FORCE_INLINE void c_ShellSort(void* base, c_size_t num, c_size_t size, int (*compar)(const void*, const void*)) { if (base == NULL || num < 2 || size == 0) return; char* arr = (char*)base; // Stack optimization for memory swap space #define STACK_LIMIT 128 char stack_buf[STACK_LIMIT]; void* temp = NULL; if (size <= STACK_LIMIT) { temp = stack_buf; } else { temp = C_ALLOC(size); if (temp == NULL) return; } // Using Knuth's gap sequence: h = h * 3 + 1 (1, 4, 13, 40, 121, ...) c_size_t gap = 1; while (gap < num / 3) { gap = gap * 3 + 1; } // Start with the largest gap and work down to a gap of 1 while (gap > 0) { for (c_size_t i = gap; i < num; i++) { // temp = arr[i] memcpy(temp, arr + (i * size), size); c_size_t j = i; // Shift elements of the gap-sorted variant until the correct position is found // Loop guards prevent underflow on unsigned c_size_t subtraction (j >= gap) while (j >= gap && compar(arr + ((j - gap) * size), temp) > 0) { // arr[j] = arr[j - gap] memcpy(arr + (j * size), arr + ((j - gap) * size), size); j -= gap; } // arr[j] = temp memcpy(arr + (j * size), temp, size); } // Reduce the gap gap /= 3; } if (size > STACK_LIMIT) { C_FREE(temp); } #undef STACK_LIMIT } #endif /*INCLUDED_C_SHELLSORT_H*/