Browse Source

Added lower/upperBound, templatizes comparison functions.

Бранимир Караџић 3 years ago
parent
commit
a8545d7b5b
4 changed files with 428 additions and 47 deletions
  1. 86 0
      include/bx/inline/sort.inl
  2. 207 28
      include/bx/sort.h
  3. 48 0
      src/sort.cpp
  4. 87 19
      tests/sort_test.cpp

+ 86 - 0
include/bx/inline/sort.inl

@@ -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;

+ 207 - 28
include/bx/sort.h

@@ -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(
-		  uint32_t* _keys
-		, uint32_t* _tempKeys
-		, uint32_t _size
-		);
-
+	/// @param _data Pointer to sorted array data.
+	/// @param _num Number of elements.
+	/// @param _fn Comparison function.
 	///
 	///
-	template <typename Ty>
-	void radixSort(
-		  uint32_t* _keys
-		, uint32_t* _tempKeys
-		, Ty* _values
-		, Ty* _tempValues
-		, uint32_t _size
-		);
+	template<typename Ty>
+	void quickSort(Ty* _data, uint32_t _num, const ComparisonFn _fn = compareAscending<Ty>);
 
 
+	/// Performs sort (Quick Sort algorithm).
 	///
 	///
-	void radixSort(
-		  uint64_t* _keys
-		, uint64_t* _tempKeys
-		, uint32_t _size
-		);
-
+	/// @param _data Pointer to sorted array data.
+	/// @param _num Number of elements.
+	/// @param _stride Element stride in bytes.
+	/// @param _fn Comparison function.
 	///
 	///
-	template <typename Ty>
-	void radixSort(
-		  uint64_t* _keys
-		, uint64_t* _tempKeys
-		, Ty* _values
-		, Ty* _tempValues
-		, uint32_t _size
-		);
+	template<typename Ty>
+	void quickSort(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn = compareAscending<Ty>);
 
 
 	/// 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 - 0
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;

+ 87 - 19
tests/sort_test.cpp

@@ -18,23 +18,16 @@ TEST_CASE("quickSort", "")
 		"jagoda",
 		"jagoda",
 	};
 	};
 
 
-	auto strCmpFn = [](const void* _lhs, const void* _rhs)
-	{
-		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) );
+	REQUIRE(!bx::isSorted(str, BX_COUNTOF(str) ) );
 
 
-	bx::quickSort(str, BX_COUNTOF(str), sizeof(str[0]), strCmpFn);
+	bx::quickSort(str, BX_COUNTOF(str) );
 
 
 	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)
-	{
-		int8_t lhs = *(const int8_t*)_lhs;
-		int8_t rhs = *(const int8_t*)_rhs;
-		return lhs - 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) );
+
+	REQUIRE( 1 == bx::lowerBound("jagoda", str, BX_COUNTOF(str), sizeof(str[0]), bsearchStrCmpFn) );
+	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);
 }
 }