#ifndef INCLUDED_C_MERGESORTBU_H #define INCLUDED_C_MERGESORTBU_H #ifndef INCLUDED_C_BASE_H #include #endif /*INCLUDED_C_BASE_H*/ #ifndef INCLUDED_C_MEMORY_H #include #endif /*INCLUDED_C_MEMORY_H*/ /* ------------------------------------------------------------------------------------------------------------------ */ /* */ /** * Internal merging routine for iterative blocks. * Re-used from the top-down logic to guarantee stability. */ C_STATIC_FORCE_INLINE void c_MergeInternalBU(char* arr, c_size_t left, c_size_t mid, c_size_t right, c_size_t size, char* aux, int (*compar)(const void*, const void*)) { c_size_t i = left; c_size_t j = mid + 1; c_size_t k = left; // Snapshot target segment into tracking auxiliary zone memcpy(aux + (left * size), arr + (left * size), (right - left + 1) * size); // Merge operational slots back sequentially while (i <= mid && j <= right) { if (compar(aux + (i * size), aux + (j * size)) <= 0) { memcpy(arr + (k * size), aux + (i * size), size); i++; } else { memcpy(arr + (k * size), aux + (j * size), size); j++; } k++; } // Flush remaining items sitting on the left slice while (i <= mid) { memcpy(arr + (k * size), aux + (i * size), size); i++; k++; } } /** * Top-Level Iterative Framework Entry Point for Bottom-Up Merge Sort. * Time Complexity: O(n log n) | Space Complexity: O(n) | Stable: Yes | Call Stack: O(1) */ C_STATIC_FORCE_INLINE void c_MergeSortBottomUp(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; c_size_t total_bytes = num * size; // Optimization: Fallback to stack buffer allocation if memory payload fits locally #define MERGE_BU_STACK_LIMIT 512 char stack_buf[MERGE_BU_STACK_LIMIT]; char* aux = NULL; if (total_bytes <= MERGE_BU_STACK_LIMIT) { aux = stack_buf; } else { aux = (char*)C_ALLOC(total_bytes); if (aux == NULL) return; } // Step-wise sub-array size doubling loop: 1, 2, 4, 8, 16... for (c_size_t width = 1; width < num; width *= 2) { // Iterate through segments by blocks of 2 * width for (c_size_t left = 0; left < num - width; left += 2 * width) { c_size_t mid = left + width - 1; c_size_t right = C_MIN(left + (2 * width) - 1, num - 1); // Optimization: Skip merge phase if the adjacent sub-segments are already sequentially sorted if (compar(arr + (mid * size), arr + ((mid + 1) * size)) > 0) { c_MergeInternalBU(arr, left, mid, right, size, aux, compar); } } } if (total_bytes > MERGE_BU_STACK_LIMIT) { C_FREE(aux); } #undef MERGE_BU_STACK_LIMIT } #endif /*INCLUDED_C_MERGESORTBU_H*/