mirror of
https://github.com/bkaradzic/bx.git
synced 2026-02-19 21:43:00 +01:00
Added bx::unique.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>);
|
||||
|
||||
28
src/sort.cpp
28
src/sort.cpp
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user