mirror of
https://github.com/bkaradzic/bx.git
synced 2026-02-17 20:52:37 +01:00
Added lower/upperBound, templatizes comparison functions.
This commit is contained in:
@@ -9,6 +9,92 @@
|
|||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
|
template<typename Ty>
|
||||||
|
inline int32_t compareAscending(const void* _lhs, const void* _rhs)
|
||||||
|
{
|
||||||
|
const Ty lhs = *static_cast<const Ty*>(_lhs);
|
||||||
|
const Ty rhs = *static_cast<const Ty*>(_rhs);
|
||||||
|
return (lhs > rhs) - (lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
inline int32_t compareDescending(const void* _lhs, const void* _rhs)
|
||||||
|
{
|
||||||
|
return compareAscending<Ty>(_rhs, _lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline int32_t compareAscending<const char*>(const void* _lhs, const void* _rhs)
|
||||||
|
{
|
||||||
|
return strCmp(*(const char**)_lhs, *(const char**)_rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline int32_t compareAscending<StringView>(const void* _lhs, const void* _rhs)
|
||||||
|
{
|
||||||
|
return strCmp(*(const StringView*)_lhs, *(const StringView*)_rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
void quickSort(Ty* _data, uint32_t _num, const ComparisonFn _fn)
|
||||||
|
{
|
||||||
|
quickSort( (void*)_data, _num, sizeof(Ty), _fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
void quickSort(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
|
||||||
|
{
|
||||||
|
quickSort(_data, _num, _stride, _fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return upperBound( (const void*)&_key, _data, _num, _stride, _fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return isSorted(_data, _num, _stride, _fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return binarySearch( (const void*)&_key, _data, _num, _stride, _fn);
|
||||||
|
}
|
||||||
|
|
||||||
namespace radix_sort_detail
|
namespace radix_sort_detail
|
||||||
{
|
{
|
||||||
constexpr uint32_t kBits = 11;
|
constexpr uint32_t kBits = 11;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#define BX_SORT_H_HEADER_GUARD
|
#define BX_SORT_H_HEADER_GUARD
|
||||||
|
|
||||||
#include "bx.h"
|
#include "bx.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
namespace bx
|
namespace bx
|
||||||
{
|
{
|
||||||
@@ -19,6 +21,26 @@ namespace bx
|
|||||||
///
|
///
|
||||||
typedef int32_t (*ComparisonFn)(const void* _lhs, const void* _rhs);
|
typedef int32_t (*ComparisonFn)(const void* _lhs, const void* _rhs);
|
||||||
|
|
||||||
|
/// The function compares the `_lhs` and `_rhs` values.
|
||||||
|
///
|
||||||
|
/// @returns Returns value:
|
||||||
|
/// - less than zero if `_lhs` is less than `_rhs`
|
||||||
|
/// - zero if `_lhs` is equivalent to `_rhs`
|
||||||
|
/// - greater than zero if `_lhs` is greater than `_rhs`
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
int32_t compareAscending(const void* _lhs, const void* _rhs);
|
||||||
|
|
||||||
|
/// The function compares the `_lhs` and `_rhs` values.
|
||||||
|
///
|
||||||
|
/// @returns Returns value:
|
||||||
|
/// - less than zero if `_lhs` is greated than `_rhs`
|
||||||
|
/// - zero if `_lhs` is equivalent to `_rhs`
|
||||||
|
/// - greater than zero if `_lhs` is less than `_rhs`
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
int32_t compareDescending(const void* _lhs, const void* _rhs);
|
||||||
|
|
||||||
/// Performs sort (Quick Sort algorithm).
|
/// Performs sort (Quick Sort algorithm).
|
||||||
///
|
///
|
||||||
/// @param _data Pointer to sorted array data.
|
/// @param _data Pointer to sorted array data.
|
||||||
@@ -33,39 +55,24 @@ namespace bx
|
|||||||
, const ComparisonFn _fn
|
, const ComparisonFn _fn
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Performs sort (Quick Sort algorithm).
|
||||||
///
|
///
|
||||||
void radixSort(
|
/// @param _data Pointer to sorted array data.
|
||||||
uint32_t* _keys
|
/// @param _num Number of elements.
|
||||||
, uint32_t* _tempKeys
|
/// @param _fn Comparison function.
|
||||||
, uint32_t _size
|
///
|
||||||
);
|
template<typename Ty>
|
||||||
|
void quickSort(Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
|
||||||
|
|
||||||
|
/// Performs sort (Quick Sort algorithm).
|
||||||
///
|
///
|
||||||
template <typename Ty>
|
/// @param _data Pointer to sorted array data.
|
||||||
void radixSort(
|
/// @param _num Number of elements.
|
||||||
uint32_t* _keys
|
/// @param _stride Element stride in bytes.
|
||||||
, uint32_t* _tempKeys
|
/// @param _fn Comparison function.
|
||||||
, Ty* _values
|
|
||||||
, Ty* _tempValues
|
|
||||||
, uint32_t _size
|
|
||||||
);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
void radixSort(
|
template<typename Ty>
|
||||||
uint64_t* _keys
|
void quickSort(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn = compareAscending<Ty>);
|
||||||
, uint64_t* _tempKeys
|
|
||||||
, uint32_t _size
|
|
||||||
);
|
|
||||||
|
|
||||||
///
|
|
||||||
template <typename Ty>
|
|
||||||
void radixSort(
|
|
||||||
uint64_t* _keys
|
|
||||||
, uint64_t* _tempKeys
|
|
||||||
, Ty* _values
|
|
||||||
, Ty* _tempValues
|
|
||||||
, uint32_t _size
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Performs check if array is sorted.
|
/// Performs check if array is sorted.
|
||||||
///
|
///
|
||||||
@@ -83,6 +90,115 @@ namespace bx
|
|||||||
, const ComparisonFn _fn
|
, 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.
|
||||||
|
/// @param _num Number of elements.
|
||||||
|
/// @param _stride Element stride in bytes.
|
||||||
|
/// @param _fn Comparison function.
|
||||||
|
///
|
||||||
|
/// @returns Returns `true` if array is sorted, otherwise returns `false`.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
bool isSorted(const void* _data, uint32_t _num, uint32_t _stride, 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.
|
||||||
|
/// @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 an index to the first element greater or equal than the `_key` value.
|
||||||
|
///
|
||||||
|
uint32_t lowerBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn);
|
||||||
|
|
||||||
|
/// Returns an index to the first element greater or equal than the `_key` value.
|
||||||
|
///
|
||||||
|
/// @param _key Pointer to the key to search for.
|
||||||
|
/// @param _data Pointer to sorted array data.
|
||||||
|
/// @param _num Number of elements.
|
||||||
|
/// @param _fn Comparison function.
|
||||||
|
///
|
||||||
|
/// @remarks Array must be sorted!
|
||||||
|
///
|
||||||
|
/// @returns Returns an index to the first element greater or equal than the `_key` value.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
uint32_t lowerBound(const Ty& _key, 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.
|
||||||
|
/// @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 an index to the first element greater or equal than the `_key` value.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
uint32_t lowerBound(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn = compareAscending<Ty>);
|
||||||
|
|
||||||
|
/// Returns an index to the first element greater than the `_key` value.
|
||||||
|
///
|
||||||
|
/// @param _key Pointer to the key to search for.
|
||||||
|
/// @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 an index to the first element greater than the `_key` value.
|
||||||
|
///
|
||||||
|
uint32_t upperBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn);
|
||||||
|
|
||||||
|
/// Returns an index to the first element greater than the `_key` value.
|
||||||
|
///
|
||||||
|
/// @param _key Pointer to the key to search for.
|
||||||
|
/// @param _data Pointer to sorted array data.
|
||||||
|
/// @param _num Number of elements.
|
||||||
|
/// @param _fn Comparison function.
|
||||||
|
///
|
||||||
|
/// @remarks Array must be sorted!
|
||||||
|
///
|
||||||
|
/// @returns Returns an index to the first element greater than the `_key` value.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
uint32_t upperBound(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
|
||||||
|
|
||||||
|
/// Returns an index to the first element greater than the `_key` value.
|
||||||
|
///
|
||||||
|
/// @param _key Pointer to the key to search for.
|
||||||
|
/// @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 an index to the first element greater than the `_key` value.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
uint32_t upperBound(const Ty& _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn = compareAscending<Ty>);
|
||||||
|
|
||||||
/// Performs binary search of a sorted array.
|
/// Performs binary search of a sorted array.
|
||||||
///
|
///
|
||||||
/// @param _key Pointer to the key to search for.
|
/// @param _key Pointer to the key to search for.
|
||||||
@@ -103,6 +219,69 @@ namespace bx
|
|||||||
, const ComparisonFn _fn
|
, const ComparisonFn _fn
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Performs binary search of a sorted array.
|
||||||
|
///
|
||||||
|
/// @param _key Pointer to the key to search for.
|
||||||
|
/// @param _data Pointer to sorted array data.
|
||||||
|
/// @param _num Number of elements.
|
||||||
|
/// @param _fn Comparison function.
|
||||||
|
///
|
||||||
|
/// @remarks Array must be sorted!
|
||||||
|
///
|
||||||
|
/// @returns Returns index of element or -1 if the key is not found in sorted array.
|
||||||
|
///
|
||||||
|
template<typename Ty>
|
||||||
|
int32_t binarySearch(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
|
||||||
|
|
||||||
|
/// Performs binary search of a sorted array.
|
||||||
|
///
|
||||||
|
/// @param _key Pointer to the key to search for.
|
||||||
|
/// @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 index of element or -1 if the key is not found in sorted array.
|
||||||
|
///
|
||||||
|
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>);
|
||||||
|
|
||||||
|
///
|
||||||
|
void radixSort(
|
||||||
|
uint32_t* _keys
|
||||||
|
, uint32_t* _tempKeys
|
||||||
|
, uint32_t _size
|
||||||
|
);
|
||||||
|
|
||||||
|
///
|
||||||
|
template <typename Ty>
|
||||||
|
void radixSort(
|
||||||
|
uint32_t* _keys
|
||||||
|
, uint32_t* _tempKeys
|
||||||
|
, Ty* _values
|
||||||
|
, Ty* _tempValues
|
||||||
|
, uint32_t _size
|
||||||
|
);
|
||||||
|
|
||||||
|
///
|
||||||
|
void radixSort(
|
||||||
|
uint64_t* _keys
|
||||||
|
, uint64_t* _tempKeys
|
||||||
|
, uint32_t _size
|
||||||
|
);
|
||||||
|
|
||||||
|
///
|
||||||
|
template <typename Ty>
|
||||||
|
void radixSort(
|
||||||
|
uint64_t* _keys
|
||||||
|
, uint64_t* _tempKeys
|
||||||
|
, Ty* _values
|
||||||
|
, Ty* _tempValues
|
||||||
|
, uint32_t _size
|
||||||
|
);
|
||||||
|
|
||||||
} // namespace bx
|
} // namespace bx
|
||||||
|
|
||||||
#include "inline/sort.inl"
|
#include "inline/sort.inl"
|
||||||
|
|||||||
48
src/sort.cpp
48
src/sort.cpp
@@ -68,6 +68,54 @@ namespace bx
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t lowerBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
|
||||||
|
{
|
||||||
|
uint32_t offset = 0;
|
||||||
|
const uint8_t* data = (uint8_t*)_data;
|
||||||
|
|
||||||
|
for (uint32_t ll = _num; offset < ll;)
|
||||||
|
{
|
||||||
|
const uint32_t idx = (offset + ll) / 2;
|
||||||
|
|
||||||
|
int32_t result = _fn(_key, &data[idx * _stride]);
|
||||||
|
|
||||||
|
if (result <= 0)
|
||||||
|
{
|
||||||
|
ll = idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset = idx + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t upperBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
|
||||||
|
{
|
||||||
|
uint32_t offset = 0;
|
||||||
|
const uint8_t* data = (uint8_t*)_data;
|
||||||
|
|
||||||
|
for (uint32_t ll = _num; offset < ll;)
|
||||||
|
{
|
||||||
|
const uint32_t idx = (offset + ll) / 2;
|
||||||
|
|
||||||
|
int32_t result = _fn(_key, &data[idx * _stride]);
|
||||||
|
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
ll = idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset = idx + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t binarySearch(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
|
int32_t binarySearch(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
|
||||||
{
|
{
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
|
|||||||
@@ -18,23 +18,16 @@ TEST_CASE("quickSort", "")
|
|||||||
"jagoda",
|
"jagoda",
|
||||||
};
|
};
|
||||||
|
|
||||||
auto strCmpFn = [](const void* _lhs, const void* _rhs)
|
REQUIRE(!bx::isSorted(str, BX_COUNTOF(str) ) );
|
||||||
{
|
|
||||||
const char* lhs = *(const char**)_lhs;
|
|
||||||
const char* rhs = *(const char**)_rhs;
|
|
||||||
return bx::strCmp(lhs, rhs);
|
|
||||||
};
|
|
||||||
|
|
||||||
REQUIRE(!bx::isSorted(str, BX_COUNTOF(str), sizeof(str[0]), strCmpFn) );
|
bx::quickSort(str, BX_COUNTOF(str) );
|
||||||
|
|
||||||
bx::quickSort(str, BX_COUNTOF(str), sizeof(str[0]), strCmpFn);
|
|
||||||
|
|
||||||
REQUIRE(0 == bx::strCmp(str[0], "jabuka") );
|
REQUIRE(0 == bx::strCmp(str[0], "jabuka") );
|
||||||
REQUIRE(0 == bx::strCmp(str[1], "jagoda") );
|
REQUIRE(0 == bx::strCmp(str[1], "jagoda") );
|
||||||
REQUIRE(0 == bx::strCmp(str[2], "kruska") );
|
REQUIRE(0 == bx::strCmp(str[2], "kruska") );
|
||||||
REQUIRE(0 == bx::strCmp(str[3], "malina") );
|
REQUIRE(0 == bx::strCmp(str[3], "malina") );
|
||||||
|
|
||||||
REQUIRE(bx::isSorted(str, BX_COUNTOF(str), sizeof(str[0]), strCmpFn) );
|
REQUIRE(bx::isSorted(str, BX_COUNTOF(str) ) );
|
||||||
|
|
||||||
auto bsearchStrCmpFn = [](const void* _lhs, const void* _rhs)
|
auto bsearchStrCmpFn = [](const void* _lhs, const void* _rhs)
|
||||||
{
|
{
|
||||||
@@ -50,12 +43,17 @@ TEST_CASE("quickSort", "")
|
|||||||
REQUIRE( 3 == bx::binarySearch("malina", 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(-1 == bx::binarySearch("kupina", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
|
||||||
|
|
||||||
auto byteCmpFn = [](const void* _lhs, const void* _rhs)
|
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) );
|
||||||
int8_t lhs = *(const int8_t*)_lhs;
|
|
||||||
int8_t rhs = *(const int8_t*)_rhs;
|
REQUIRE( 1 == bx::lowerBound("jagoda", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
|
||||||
return lhs - rhs;
|
REQUIRE( 2 == bx::upperBound("jagoda", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
|
||||||
};
|
|
||||||
|
REQUIRE( 2 == bx::lowerBound("kruska", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
|
||||||
|
REQUIRE( 3 == bx::upperBound("kruska", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
|
||||||
|
|
||||||
|
REQUIRE( 3 == bx::lowerBound("malina", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
|
||||||
|
REQUIRE( 4 == bx::upperBound("malina", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
|
||||||
|
|
||||||
int8_t byte[128];
|
int8_t byte[128];
|
||||||
bx::RngMwc rng;
|
bx::RngMwc rng;
|
||||||
@@ -64,14 +62,84 @@ TEST_CASE("quickSort", "")
|
|||||||
byte[ii] = rng.gen()&0xff;
|
byte[ii] = rng.gen()&0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(!bx::isSorted(byte, BX_COUNTOF(byte), sizeof(byte[0]), byteCmpFn) );
|
REQUIRE(!bx::isSorted(byte, BX_COUNTOF(byte) ) );
|
||||||
|
|
||||||
bx::quickSort(byte, BX_COUNTOF(byte), sizeof(byte[0]), byteCmpFn);
|
bx::quickSort(byte, BX_COUNTOF(byte) );
|
||||||
|
|
||||||
for (uint32_t ii = 1; ii < BX_COUNTOF(byte); ++ii)
|
for (uint32_t ii = 1; ii < BX_COUNTOF(byte); ++ii)
|
||||||
{
|
{
|
||||||
REQUIRE(byte[ii-1] <= byte[ii]);
|
REQUIRE(byte[ii-1] <= byte[ii]);
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(bx::isSorted(byte, BX_COUNTOF(byte), sizeof(byte[0]), byteCmpFn) );
|
REQUIRE(bx::isSorted(byte, BX_COUNTOF(byte) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("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 };
|
||||||
|
REQUIRE(bx::isSorted(test, BX_COUNTOF(test) ) );
|
||||||
|
|
||||||
|
const uint32_t resultLowerBound[] = { 0, 1, 4, 4, 5, 6, 9, 11, 12, 13 };
|
||||||
|
const uint32_t resultUpperBound[] = { 1, 4, 4, 5, 6, 9, 11, 12, 13, 14 };
|
||||||
|
|
||||||
|
static_assert(10 == BX_COUNTOF(resultLowerBound) );
|
||||||
|
static_assert(10 == BX_COUNTOF(resultUpperBound) );
|
||||||
|
|
||||||
|
for (int32_t key = test[0], keyMax = test[BX_COUNTOF(test)-1], ii = 0; key <= keyMax; ++key, ++ii)
|
||||||
|
{
|
||||||
|
REQUIRE(resultLowerBound[ii] == bx::lowerBound(key, test, BX_COUNTOF(test) ) );
|
||||||
|
REQUIRE(resultUpperBound[ii] == bx::upperBound(key, test, BX_COUNTOF(test) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
int32_t compareAscendingTest(const Ty& _lhs, const Ty& _rhs)
|
||||||
|
{
|
||||||
|
return bx::compareAscending<Ty>(&_lhs, &_rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
int32_t compareDescendingTest(const Ty& _lhs, const Ty& _rhs)
|
||||||
|
{
|
||||||
|
return bx::compareDescending<Ty>(&_lhs, &_rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ty>
|
||||||
|
void compareTest(const Ty& _min, const Ty& _max)
|
||||||
|
{
|
||||||
|
REQUIRE(_min < _max);
|
||||||
|
|
||||||
|
REQUIRE(-1 == compareAscendingTest<Ty>(std::numeric_limits<Ty>::min(), std::numeric_limits<Ty>::max() ) );
|
||||||
|
REQUIRE(-1 == compareAscendingTest<Ty>(Ty(0), std::numeric_limits<Ty>::max() ) );
|
||||||
|
REQUIRE( 0 == compareAscendingTest<Ty>(std::numeric_limits<Ty>::min(), std::numeric_limits<Ty>::min() ) );
|
||||||
|
REQUIRE( 0 == compareAscendingTest<Ty>(std::numeric_limits<Ty>::max(), std::numeric_limits<Ty>::max() ) );
|
||||||
|
REQUIRE( 1 == compareAscendingTest<Ty>(std::numeric_limits<Ty>::max(), Ty(0) ) );
|
||||||
|
REQUIRE( 1 == compareAscendingTest<Ty>(std::numeric_limits<Ty>::max(), std::numeric_limits<Ty>::min() ) );
|
||||||
|
|
||||||
|
REQUIRE(-1 == compareAscendingTest<Ty>(_min, _max) );
|
||||||
|
REQUIRE( 0 == compareAscendingTest<Ty>(_min, _min) );
|
||||||
|
REQUIRE( 0 == compareAscendingTest<Ty>(_max, _max) );
|
||||||
|
REQUIRE( 1 == compareAscendingTest<Ty>(_max, _min) );
|
||||||
|
|
||||||
|
REQUIRE( 1 == compareDescendingTest<Ty>(_min, _max) );
|
||||||
|
REQUIRE( 0 == compareDescendingTest<Ty>(_min, _min) );
|
||||||
|
REQUIRE( 0 == compareDescendingTest<Ty>(_max, _max) );
|
||||||
|
REQUIRE(-1 == compareDescendingTest<Ty>(_max, _min) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ComparisonFn", "")
|
||||||
|
{
|
||||||
|
compareTest< int8_t>( -13, 89);
|
||||||
|
compareTest<int16_t>(-1389, 1389);
|
||||||
|
compareTest<int32_t>(-1389, 1389);
|
||||||
|
compareTest<int64_t>(-1389, 1389);
|
||||||
|
|
||||||
|
compareTest< uint8_t>( 13, 89);
|
||||||
|
compareTest<uint16_t>( 13, 1389);
|
||||||
|
compareTest<uint32_t>( 13, 1389);
|
||||||
|
compareTest<uint64_t>( 13, 1389);
|
||||||
|
|
||||||
|
compareTest< float>(-13.89f, 1389.0f);
|
||||||
|
compareTest<double>(-13.89f, 1389.0f);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user