Added constexpr isSorted with less function. (#469)

This commit is contained in:
Branimir Karadžić
2026-10-21 08:43:33 -07:00
committed by GitHub
parent 234f2fba71
commit c500a9228e
3 changed files with 87 additions and 0 deletions

View File

@@ -218,6 +218,21 @@ namespace bx
return isSorted(_data, _num, _stride, _fn);
}
template<typename Ty, typename LessFn>
requires (isSame<decltype(declVal<LessFn>()(declVal<const Ty&>(), declVal<const Ty&>() ) ), bool>() )
inline constexpr bool isSorted(const Ty* _data, uint32_t _num, LessFn _less)
{
for (uint32_t ii = 1; ii < _num; ++ii)
{
if (_less(_data[ii], _data[ii-1]) )
{
return false;
}
}
return true;
}
template<typename Ty>
inline int32_t binarySearch(const Ty& _key, const Ty* _data, uint32_t _num, const ComparisonFn _fn)
{

View File

@@ -203,6 +203,21 @@ namespace bx
template<typename Ty>
bool isSorted(const Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
/// Performs check if array is sorted. Usable in constant expressions, e.g. to `static_assert`
/// that a lookup table is in key order.
///
/// @param _data Pointer to array data.
/// @param _num Number of elements.
/// @param _less Comparison function returning true if `_lhs` sorts before `_rhs`. With `<=`
/// instead of `<` the check is for strictly ascending elements, no two equal.
///
/// @returns Returns `true` if no element sorts before the one ahead of it, otherwise returns
/// `false`.
///
template<typename Ty, typename LessFn>
requires (isSame<decltype(declVal<LessFn>()(declVal<const Ty&>(), declVal<const Ty&>() ) ), bool>() )
constexpr bool isSorted(const Ty* _data, uint32_t _num, LessFn _less);
/// Returns an index to the first element greater or equal than the `_key` value.
///
/// @param _key Pointer to the key to search for.

View File

@@ -49,6 +49,63 @@ TEST_CASE("quickSort", "[sort]")
REQUIRE(bx::isSorted(byte, BX_COUNTOF(byte) ) );
}
namespace
{
struct KeyedRow
{
uint32_t key;
uint32_t value;
};
constexpr KeyedRow s_dense[] =
{
{ 0, 10 },
{ 1, 11 },
{ 2, 12 },
{ 3, 13 },
};
constexpr KeyedRow s_repeated[] =
{
{ 0, 10 },
{ 1, 11 },
{ 1, 12 },
{ 3, 13 },
};
constexpr bool keyLess(const KeyedRow& _lhs, const KeyedRow& _rhs)
{
return _lhs.key < _rhs.key;
}
constexpr bool keyLessEqual(const KeyedRow& _lhs, const KeyedRow& _rhs)
{
return _lhs.key <= _rhs.key;
}
} // namespace
TEST_CASE("isSorted with a less function", "[sort]")
{
STATIC_REQUIRE( bx::isSorted(s_dense, BX_COUNTOF(s_dense), keyLess) );
STATIC_REQUIRE( bx::isSorted(s_repeated, BX_COUNTOF(s_repeated), keyLess) );
STATIC_REQUIRE( bx::isSorted(s_dense, BX_COUNTOF(s_dense), keyLessEqual) );
STATIC_REQUIRE(!bx::isSorted(s_repeated, BX_COUNTOF(s_repeated), keyLessEqual) );
STATIC_REQUIRE( bx::isSorted(s_dense, 0, keyLess) );
STATIC_REQUIRE( bx::isSorted(s_dense, 1, keyLess) );
int32_t data[] = { 3, 1, 2 };
const uint32_t num = BX_COUNTOF(data);
REQUIRE(!bx::isSorted(data, num, [](const int32_t& _lhs, const int32_t& _rhs) { return _lhs < _rhs; }) );
bx::quickSort(data, num);
REQUIRE( bx::isSorted(data, num, [](const int32_t& _lhs, const int32_t& _rhs) { return _lhs < _rhs; }) );
REQUIRE( bx::isSorted(data, num, bx::compareAscending<int32_t>) );
REQUIRE(!bx::isSorted(data, num, bx::compareDescending<int32_t>) );
}
TEST_CASE("binarySearch", "[sort]")
{
const char* str[] =