diff --git a/src/guf_sort.h b/src/guf_sort.h index 495d089..29db5ed 100644 --- a/src/guf_sort.h +++ b/src/guf_sort.h @@ -11,8 +11,8 @@ typedef enum guf_sort_opt { #ifdef GUF_T -#ifndef GUF_T_NAME - #define GUF_T_NAME GUF_T +#ifndef GUF_FN_NAME_PREFIX + #define GUF_FN_NAME_PREFIX GUF_CAT(GUF_T, _arr) #endif #ifdef GUF_IMPL_STATIC @@ -21,9 +21,11 @@ typedef enum guf_sort_opt { #define GUF_FN_KEYWORDS #endif -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _insertion_sort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _merge_sort)(GUF_T *restrict arr, GUF_T *restrict arr_tmp, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _qsort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); +GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _insertion_sort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); +GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _merge_sort)(GUF_T *restrict arr, GUF_T *restrict arr_tmp, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); +GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); + +GUF_FN_KEYWORDS bool GUF_CAT(GUF_FN_NAME_PREFIX, _is_sorted)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)); #if defined(GUF_IMPL) || defined(GUF_IMPL_STATIC) @@ -36,7 +38,7 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _qsort)(GUF_T *arr, ptrdiff_t n, guf_ - time: worst O(n^2); average O(n^2); best O(n) (if arr is already sorted) - space: O(1) */ -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _insertion_sort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _insertion_sort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) { GUF_ASSERT_RELEASE(arr); GUF_ASSERT_RELEASE(n >= 0); @@ -57,7 +59,7 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _insertion_sort)(GUF_T *arr, ptrdiff_ - time: O(n * log n) (worst, average, and best) - space: always O(n) (for arr_tmp, allocated and freed by the caller) */ -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _merge_sort)(GUF_T *restrict arr, GUF_T *restrict arr_tmp, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _merge_sort)(GUF_T *restrict arr, GUF_T *restrict arr_tmp, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) { GUF_ASSERT_RELEASE(arr); GUF_ASSERT_RELEASE(n >= 0); @@ -98,7 +100,7 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _merge_sort)(GUF_T *restrict arr, GUF - time: worst O(n^2); average O(n * log n); best O(n * log n) - space: worst O(log n) (stack space used for the recursive function calls) */ -static GUF_T *GUF_CAT(GUF_T_NAME, _qsort_range)(GUF_T *arr, ptrdiff_t first_idx, ptrdiff_t last_idx, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +static GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort_range)(GUF_T *arr, ptrdiff_t first_idx, ptrdiff_t last_idx, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) { GUF_ASSERT(arr); GUF_ASSERT(sort_opt == GUF_SORT_ASCENDING || sort_opt == GUF_SORT_DESCENDING); @@ -138,17 +140,17 @@ static GUF_T *GUF_CAT(GUF_T_NAME, _qsort_range)(GUF_T *arr, ptrdiff_t first_idx, (Solution to exercise "II.7.4c. Stack depth for quicksort". In "Introduction to Algorithms" (3rd ed, p. 188)) */ if (pivot_idx <= mid_idx) { // a.) Left subarray is smaller or equal than the right subarray -> recur into the smaller left subarray first. - GUF_CAT(GUF_T_NAME, _qsort_range)(arr, first_idx, pivot_idx - 1, sort_opt, cmp); + GUF_CAT(GUF_FN_NAME_PREFIX, _qsort_range)(arr, first_idx, pivot_idx - 1, sort_opt, cmp); first_idx = pivot_idx + 1; } else { // b.) Right subarray is smaller than the left subarray -> recur into the smaller right subarray first. - GUF_CAT(GUF_T_NAME, _qsort_range)(arr, pivot_idx + 1, last_idx, sort_opt, cmp); + GUF_CAT(GUF_FN_NAME_PREFIX, _qsort_range)(arr, pivot_idx + 1, last_idx, sort_opt, cmp); last_idx = pivot_idx - 1; } } return arr; } -GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _qsort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_FN_NAME_PREFIX, _qsort)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) { GUF_ASSERT_RELEASE(arr); GUF_ASSERT_RELEASE(sort_opt == GUF_SORT_ASCENDING || sort_opt == GUF_SORT_DESCENDING); @@ -156,20 +158,31 @@ GUF_FN_KEYWORDS GUF_T *GUF_CAT(GUF_T_NAME, _qsort)(GUF_T *arr, ptrdiff_t n, guf_ if (n <= 1) { return arr; } else if (n <= 4) { - return GUF_CAT(GUF_T_NAME, _insertion_sort)(arr, n, sort_opt, cmp); + return GUF_CAT(GUF_FN_NAME_PREFIX, _insertion_sort)(arr, n, sort_opt, cmp); } else { - return GUF_CAT(GUF_T_NAME, _qsort_range)(arr, 0, n - 1, sort_opt, cmp); + return GUF_CAT(GUF_FN_NAME_PREFIX, _qsort_range)(arr, 0, n - 1, sort_opt, cmp); } } +GUF_FN_KEYWORDS bool GUF_CAT(GUF_FN_NAME_PREFIX, _is_sorted)(GUF_T *arr, ptrdiff_t n, guf_sort_opt sort_opt, int(*cmp)(const GUF_T *a, const GUF_T *b)) +{ + GUF_ASSERT_RELEASE(arr); + for (ptrdiff_t i = 0; i < n - 1; ++i) { + if (!guf_before_or_equal(arr + i, arr + (i+1))) { + return false; + } + } + return true; +} + #undef guf_before #undef guf_before_or_equal -#endif /* end #ifdef GUF_IMPL */ - -#undef GUF_T -#undef GUF_T_NAME -#endif /* end #ifdef GUF_T */ #undef GUF_IMPL #undef GUF_IMPL_STATIC #undef GUF_FN_KEYWORDS +#endif /* end #ifdef GUF_IMPL */ + +#undef GUF_T +#undef GUF_FN_NAME_PREFIX +#endif /* end #ifdef GUF_T */ diff --git a/src/guf_test.c b/src/guf_test.c index 1c1faae..b7d1800 100644 --- a/src/guf_test.c +++ b/src/guf_test.c @@ -53,11 +53,12 @@ int main(void) } // float *tmp = test_allocator.alloc(floats.size * sizeof(float), &test_allocator_ctx); - // float *res = float_merge_sort(floats.data, tmp, floats.size, GUF_SORT_ASCENDING, NULL); + // float *res = float_arr_merge_sort(floats.data, tmp, floats.size, GUF_SORT_ASCENDING, NULL); // test_allocator.free(tmp, floats.size * sizeof(float), &test_allocator_ctx); // GUF_ASSERT_RELEASE(res == floats.data); - float_qsort(floats.data, floats.size, GUF_SORT_ASCENDING, NULL); + float_arr_qsort(floats.data, floats.size, GUF_SORT_ASCENDING, NULL); + GUF_ASSERT_RELEASE(float_arr_is_sorted(floats.data, floats.size, GUF_SORT_ASCENDING, NULL)); GUF_CNT_FOREACH(&floats, dbuf_float, it) { printf("float: %f\n", (double)*it.ptr); diff --git a/src/guf_utils.h b/src/guf_utils.h index 71edee2..b13fc47 100644 --- a/src/guf_utils.h +++ b/src/guf_utils.h @@ -1,7 +1,7 @@ #ifndef GUF_UTILS_H #define GUF_UTILS_H -static inline bool guf_is_big_endian(void) +static inline bool guf_system_is_big_endian(void) { unsigned i = 1; const char *bytes = (const char*)&i;