Added bx::unique.

This commit is contained in:
Бранимир Караџић
2022-09-10 08:34:59 -07:00
parent 7f9fd5b8a5
commit a2dff8e0a0
4 changed files with 155 additions and 48 deletions

View File

@@ -36,63 +36,77 @@ namespace bx
}
template<typename Ty>
void quickSort(Ty* _data, uint32_t _num, const ComparisonFn _fn)
inline void quickSort(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
BX_STATIC_ASSERT(isTriviallyMoveAssignable<Ty>(), "Sort element type must be trivially move assignable");
quickSort( (void*)_data, _num, sizeof(Ty), _fn);
}
template<typename Ty>
void quickSort(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
BX_STATIC_ASSERT(isTriviallyMoveAssignable<Ty>(), "Sort element type must be trivially move assignable");
BX_STATIC_ASSERT(isTriviallyMoveAssignable<Ty>(), "Element type must be trivially move assignable");
quickSort(_data, _num, _stride, _fn);
}
template<typename Ty>
uint32_t lowerBound(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn)
inline void quickSort(Ty* _data, uint32_t _num, const ComparisonFn _fn)
{
BX_STATIC_ASSERT(isTriviallyMoveAssignable<Ty>(), "Element type must be trivially move assignable");
quickSort( (void*)_data, _num, sizeof(Ty), _fn);
}
template<typename Ty>
inline uint32_t unique(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
BX_STATIC_ASSERT(isTriviallyMoveAssignable<Ty>(), "Element type must be trivially move assignable");
return unique(_data, _num, _stride, _fn);
}
template<typename Ty>
inline uint32_t unique(Ty* _data, uint32_t _num, const ComparisonFn _fn)
{
BX_STATIC_ASSERT(isTriviallyMoveAssignable<Ty>(), "Element type must be trivially move assignable");
return unique( (void*)_data, _num, sizeof(Ty), _fn);
}
template<typename Ty>
inline uint32_t lowerBound(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn)
{
return lowerBound( (const void*)&_key, _data, _num, sizeof(Ty), _fn);
}
template<typename Ty>
uint32_t lowerBound(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
inline uint32_t lowerBound(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
return lowerBound( (const void*)&_key, _data, _num, _stride, _fn);
}
template<typename Ty>
uint32_t upperBound(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn)
inline uint32_t upperBound(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn)
{
return upperBound( (const void*)&_key, _data, _num, sizeof(Ty), _fn);
}
template<typename Ty>
uint32_t upperBound(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
inline uint32_t upperBound(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
return upperBound( (const void*)&_key, _data, _num, _stride, _fn);
}
template<typename Ty>
bool isSorted(const Ty* _data, uint32_t _num, const ComparisonFn _fn)
inline bool isSorted(const Ty* _data, uint32_t _num, const ComparisonFn _fn)
{
return isSorted(_data, _num, sizeof(Ty), _fn);
}
template<typename Ty>
bool isSorted(const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
inline bool isSorted(const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
return isSorted(_data, _num, _stride, _fn);
}
template<typename Ty>
int32_t binarySearch(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn)
inline int32_t binarySearch(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn)
{
return binarySearch( (const void*)&_key, _data, _num, sizeof(Ty), _fn);
}
template<typename Ty>
int32_t binarySearch(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
inline int32_t binarySearch(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
return binarySearch( (const void*)&_key, _data, _num, _stride, _fn);
}

View File

@@ -43,7 +43,7 @@ namespace bx
/// Performs sort (Quick Sort algorithm).
///
/// @param _data Pointer to sorted array data.
/// @param _data Pointer to array data.
/// @param _num Number of elements.
/// @param _stride Element stride in bytes.
/// @param _fn Comparison function.
@@ -57,16 +57,7 @@ namespace bx
/// Performs sort (Quick Sort algorithm).
///
/// @param _data Pointer to sorted array data.
/// @param _num Number of elements.
/// @param _fn Comparison function.
///
template<typename Ty>
void quickSort(Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
/// Performs sort (Quick Sort algorithm).
///
/// @param _data Pointer to sorted array data.
/// @param _data Pointer to array data.
/// @param _num Number of elements.
/// @param _stride Element stride in bytes.
/// @param _fn Comparison function.
@@ -74,6 +65,58 @@ namespace bx
template<typename Ty>
void quickSort(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn = compareAscending<Ty>);
/// Performs sort (Quick Sort algorithm).
///
/// @param _data Pointer to array data.
/// @param _num Number of elements.
/// @param _fn Comparison function.
///
template<typename Ty>
void quickSort(Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
/// Performs reordering of duplicate elements in the array in the way that unique elements
/// are sorted to the front of array, and duplicates are after the return value index.
///
/// @param _data Pointer to sorted array data.
/// @param _num Number of elements.
/// @param _stride Element stride in bytes.
/// @param _fn Comparison function.
///
/// @remarks Array must be sorted!
///
/// @returns Returns the count of unique elements.
///
uint32_t unique(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn);
/// Performs reordering of duplicate elements in the array in the way that unique elements
/// are sorted to the front of array, and duplicates are after the return value index.
///
/// @param _data Pointer to sorted array data.
/// @param _num Number of elements.
/// @param _stride Element stride in bytes.
/// @param _fn Comparison function.
///
/// @remarks Array must be sorted!
///
/// @returns Returns the count of unique elements.
///
template<typename Ty>
uint32_t unique(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn = compareAscending<Ty>);
/// Performs reordering of duplicate elements in the array in the way that unique elements
/// are sorted to the front of array, and duplicates are after the return value index.
///
/// @param _data Pointer to sorted array data.
/// @param _num Number of elements.
/// @param _fn Comparison function.
///
/// @remarks Array must be sorted!
///
/// @returns Returns the count of unique elements.
///
template<typename Ty>
uint32_t unique(Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
/// Performs check if array is sorted.
///
/// @param _data Pointer to sorted array data.
@@ -90,17 +133,6 @@ namespace bx
, const ComparisonFn _fn
);
/// Performs check if array is sorted.
///
/// @param _data Pointer to sorted array data.
/// @param _num Number of elements.
/// @param _fn Comparison function.
///
/// @returns Returns `true` if array is sorted, otherwise returns `false`.
///
template<typename Ty>
bool isSorted(const Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
/// Performs check if array is sorted.
///
/// @param _data Pointer to sorted array data.
@@ -113,6 +145,17 @@ namespace bx
template<typename Ty>
bool isSorted(const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn = compareAscending<Ty>);
/// Performs check if array is sorted.
///
/// @param _data Pointer to sorted array data.
/// @param _num Number of elements.
/// @param _fn Comparison function.
///
/// @returns Returns `true` if array is sorted, otherwise returns `false`.
///
template<typename Ty>
bool isSorted(const Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
/// Returns an index to the first element greater or equal than the `_key` value.
///
/// @param _key Pointer to the key to search for.
@@ -209,7 +252,8 @@ namespace bx
///
/// @remarks Array must be sorted!
///
/// @returns Returns index of element or -1 if the key is not found in sorted array.
/// @returns Returns positive value index of element if found, or negative number that is bitwise
/// complement (~) of the index of the next element that's larger than item.
///
int32_t binarySearch(
const void* _key
@@ -228,7 +272,8 @@ namespace bx
///
/// @remarks Array must be sorted!
///
/// @returns Returns index of element or -1 if the key is not found in sorted array.
/// @returns Returns positive value index of element if found, or negative number that is bitwise
/// complement (~) of the index of the next element that's larger than item.
///
template<typename Ty>
int32_t binarySearch(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
@@ -243,7 +288,8 @@ namespace bx
///
/// @remarks Array must be sorted!
///
/// @returns Returns index of element or -1 if the key is not found in sorted array.
/// @returns Returns positive value index of element if found, or negative number that is bitwise
/// complement (~) of the index of the next element that's larger than item.
///
template<typename Ty>
int32_t binarySearch(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride = sizeof(Ty), const ComparisonFn _fn = compareAscending<Ty>);

View File

@@ -68,6 +68,32 @@ namespace bx
return true;
}
uint32_t unique(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
if (0 == _num)
{
return 0;
}
uint8_t* data = (uint8_t*)_data;
uint32_t last = 0;
for (uint32_t ii = 1; ii < _num; ++ii)
{
int32_t result = _fn(&data[last*_stride], &data[ii*_stride]);
BX_ASSERT(0 >= result, "Performing unique on non-sorted array (ii %d, last %d)!", ii, last);
if (0 > result)
{
last++;
swap(&data[last*_stride], &data[ii*_stride], _stride);
}
}
return last+1;
}
uint32_t lowerBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
{
uint32_t offset = 0;
@@ -141,7 +167,7 @@ namespace bx
}
}
return -1;
return ~offset;
}
} // namespace bx

View File

@@ -9,7 +9,7 @@
#include <bx/string.h>
#include <bx/rng.h>
TEST_CASE("quickSort", "")
TEST_CASE("sort-quickSort", "")
{
const char* str[] =
{
@@ -37,12 +37,12 @@ TEST_CASE("quickSort", "")
return bx::strCmp(lhs, rhs);
};
REQUIRE(-1 == bx::binarySearch("sljiva", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE(~4 == bx::binarySearch("sljiva", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE( 0 == bx::binarySearch("jabuka", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE( 1 == bx::binarySearch("jagoda", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE( 2 == bx::binarySearch("kruska", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE( 3 == bx::binarySearch("malina", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE(-1 == bx::binarySearch("kupina", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE(~3 == bx::binarySearch("kupina", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE( 0 == bx::lowerBound("jabuka", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
REQUIRE( 1 == bx::upperBound("jabuka", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
@@ -75,7 +75,28 @@ TEST_CASE("quickSort", "")
REQUIRE(bx::isSorted(byte, BX_COUNTOF(byte) ) );
}
TEST_CASE("lower/upperBound int32_t", "")
TEST_CASE("sort-unique", "")
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | 14
int32_t test[] = { 100, 101, 101, 101, 103, 104, 105, 105, 105, 106, 106, 107, 108, 109 };
REQUIRE(bx::isSorted(test, BX_COUNTOF(test) ) );
REQUIRE(0 == bx::unique(test, 0) );
REQUIRE(1 == bx::unique(test, 1) );
REQUIRE(2 == bx::unique(test, 4) );
bx::quickSort(test, BX_COUNTOF(test) );
REQUIRE(3 == bx::unique(test, 5) );
bx::quickSort(test, BX_COUNTOF(test) );
uint32_t last = bx::unique(test, BX_COUNTOF(test) );
REQUIRE(9 == last);
REQUIRE(9 == bx::unique(test, last) );
}
TEST_CASE("sort-lower/upperBound int32_t", "")
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | 14
const int32_t test[] = { 100, 101, 101, 101, 103, 104, 105, 105, 105, 106, 106, 107, 108, 109 };
@@ -129,7 +150,7 @@ void compareTest(const Ty& _min, const Ty& _max)
REQUIRE(-1 == compareDescendingTest<Ty>(_max, _min) );
}
TEST_CASE("ComparisonFn", "")
TEST_CASE("sort-ComparisonFn", "")
{
compareTest< int8_t>( -13, 89);
compareTest<int16_t>(-1389, 1389);