From 8c0cdc361bbddc3ad038d915ec21fb3fd947e894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sat, 11 Feb 2017 00:35:43 -0800 Subject: [PATCH] Added quickSort. --- include/bx/{radixsort.h => sort.h} | 19 +++++++-- include/bx/{radixsort.inl => sort.inl} | 6 +-- src/sort.cpp | 55 ++++++++++++++++++++++++++ tests/sort_test.cpp | 53 +++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 7 deletions(-) rename include/bx/{radixsort.h => sort.h} (72%) rename include/bx/{radixsort.inl => sort.inl} (98%) create mode 100644 src/sort.cpp create mode 100644 tests/sort_test.cpp diff --git a/include/bx/radixsort.h b/include/bx/sort.h similarity index 72% rename from include/bx/radixsort.h rename to include/bx/sort.h index 87bd3e3..98be6fa 100644 --- a/include/bx/radixsort.h +++ b/include/bx/sort.h @@ -3,13 +3,24 @@ * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ -#ifndef BX_RADIXSORT_H_HEADER_GUARD -#define BX_RADIXSORT_H_HEADER_GUARD +#ifndef BX_SORT_H_HEADER_GUARD +#define BX_SORT_H_HEADER_GUARD #include "bx.h" namespace bx { + /// + typedef int32_t (*ComparisonFn)(const void* _lhs, const void* _rhs); + + /// + void quickSort( + void* _data + , uint32_t _num + , uint32_t _stride + , const ComparisonFn _fn + ); + /// void radixSort( uint32_t* __restrict _keys @@ -46,6 +57,6 @@ namespace bx } // namespace bx -#include "radixsort.inl" +#include "sort.inl" -#endif // BX_RADIXSORT_H_HEADER_GUARD +#endif // BX_SORT_H_HEADER_GUARD diff --git a/include/bx/radixsort.inl b/include/bx/sort.inl similarity index 98% rename from include/bx/radixsort.inl rename to include/bx/sort.inl index 048ceb6..124290c 100644 --- a/include/bx/radixsort.inl +++ b/include/bx/sort.inl @@ -3,9 +3,9 @@ * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ -#ifndef BX_RADIXSORT_H_HEADER_GUARD -# error "Must be included from bx/radixsort.h!" -#endif // BX_RADIXSORT_H_HEADER_GUARD +#ifndef BX_SORT_H_HEADER_GUARD +# error "Must be included from bx/sort.h!" +#endif // BX_SORT_H_HEADER_GUARD namespace bx { diff --git a/src/sort.cpp b/src/sort.cpp new file mode 100644 index 0000000..9d8e4fb --- /dev/null +++ b/src/sort.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include + +namespace bx +{ + static void quickSortR(void* _pivot, void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn) + { + if (2 > _num) + { + return; + } + + memCopy(_pivot, _data, _stride); + + uint8_t* data = (uint8_t*)_data; + + uint32_t ll = 0; + uint32_t gg = 1; + + for (uint32_t ii = 1; ii < _num;) + { + int32_t result = _fn(&data[ii*_stride], _pivot); + if (0 > result) + { + xchg(&data[ll*_stride], &data[ii*_stride], _stride); + ++ll; + } + else if (0 == result) + { + xchg(&data[gg*_stride], &data[ii*_stride], _stride); + ++gg; + ++ii; + } + else + { + ++ii; + } + } + + quickSortR(_pivot, &data[0 ], ll, _stride, _fn); + quickSortR(_pivot, &data[gg*_stride], _num-gg, _stride, _fn); + } + + void quickSort(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn) + { + uint8_t pivot[_stride]; + quickSortR(pivot, _data, _num, _stride, _fn); + } + +} // namespace bx + diff --git a/tests/sort_test.cpp b/tests/sort_test.cpp new file mode 100644 index 0000000..d271a3f --- /dev/null +++ b/tests/sort_test.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include "test.h" +#include +#include +#include + +TEST_CASE("quickSort", "") +{ + const char* str[] = + { + "jabuka", + "kruska", + "malina", + "jagoda", + }; + + bx::quickSort(str, BX_COUNTOF(str), sizeof(void*) + , [](const void* _lhs, const void* _rhs) + { + const char* lhs = *(const char**)_lhs; + const char* rhs = *(const char**)_rhs; + return bx::strncmp(lhs, rhs); + }); + + REQUIRE(0 == bx::strncmp(str[0], "jabuka") ); + REQUIRE(0 == bx::strncmp(str[1], "jagoda") ); + REQUIRE(0 == bx::strncmp(str[2], "kruska") ); + REQUIRE(0 == bx::strncmp(str[3], "malina") ); + + int8_t byte[128]; + bx::RngMwc rng; + for (uint32_t ii = 0; ii < BX_COUNTOF(byte); ++ii) + { + byte[ii] = rng.gen()&0xff; + } + + bx::quickSort(byte, BX_COUNTOF(byte), 1 + , [](const void* _lhs, const void* _rhs) + { + int8_t lhs = *(const int8_t*)_lhs; + int8_t rhs = *(const int8_t*)_rhs; + return lhs - rhs; + }); + + for (uint32_t ii = 1; ii < BX_COUNTOF(byte); ++ii) + { + REQUIRE(byte[ii-1] <= byte[ii]); + } +}