Browse Source

Added numeric min/max for type.

Бранимир Караџић 3 years ago
parent
commit
d4403099f9
6 changed files with 170 additions and 28 deletions
  1. 9 6
      include/bx/bx.h
  2. 70 0
      include/bx/constants.h
  3. 46 0
      include/bx/inline/bx.inl
  4. 0 16
      include/bx/math.h
  5. 38 0
      tests/math_test.cpp
  6. 7 6
      tests/sort_test.cpp

+ 9 - 6
include/bx/bx.h

@@ -14,6 +14,7 @@
 
 
 #include "platform.h"
 #include "platform.h"
 #include "config.h"
 #include "config.h"
+#include "constants.h"
 #include "macros.h"
 #include "macros.h"
 #include "debug.h"
 #include "debug.h"
 
 
@@ -32,12 +33,6 @@
 
 
 namespace bx
 namespace bx
 {
 {
-	/// Used to return successful execution of a program code.
-	constexpr int32_t kExitSuccess = 0;
-
-	/// Used to return unsuccessful execution of a program code.
-	constexpr int32_t kExitFailure = 1;
-
 	/// Returns true if type `Ty` is trivially copyable / POD type.
 	/// Returns true if type `Ty` is trivially copyable / POD type.
 	template<class Ty>
 	template<class Ty>
 	constexpr bool isTriviallyCopyable();
 	constexpr bool isTriviallyCopyable();
@@ -57,6 +52,14 @@ namespace bx
 	/// Swap memory.
 	/// Swap memory.
 	void swap(void* _a, void* _b, size_t _numBytes);
 	void swap(void* _a, void* _b, size_t _numBytes);
 
 
+	/// Returns numeric minimum of type.
+	template<typename Ty>
+	constexpr Ty min();
+
+	/// Returns numeric maximum of type.
+	template<typename Ty>
+	constexpr Ty max();
+
 	/// Returns minimum of two values.
 	/// Returns minimum of two values.
 	template<typename Ty>
 	template<typename Ty>
 	constexpr Ty min(const Ty& _a, const Ty& _b);
 	constexpr Ty min(const Ty& _a, const Ty& _b);

+ 70 - 0
include/bx/constants.h

@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011-2022 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
+ */
+
+#ifndef BX_CONSTANTS_H_HEADER_GUARD
+#define BX_CONSTANTS_H_HEADER_GUARD
+
+namespace bx
+{
+	/// Used to return successful execution of a program code.
+	constexpr int32_t  kExitSuccess    = 0;
+
+	/// Used to return unsuccessful execution of a program code.
+	constexpr int32_t  kExitFailure    = 1;
+
+	/// The ratio of a circle's circumference to its diameter,
+	constexpr float    kPi             = 3.1415926535897932384626433832795f;
+
+	/// The ratio of a circle's circumference to its radius. Pi multiplied by 2, or Tau. pi*2
+	constexpr float    kPi2            = 6.2831853071795864769252867665590f;
+
+	/// The reciprocal of pi. 1/pi
+	constexpr float    kInvPi          = 1.0f/kPi;
+
+	/// Pi divided by two. pi/2
+	constexpr float    kPiHalf         = 1.5707963267948966192313216916398f;
+
+	/// Pi divided by four. pi/4
+	constexpr float    kPiQuarter      = 0.7853981633974483096156608458199f;
+
+	/// The square root of two. sqrt(2)
+	constexpr float    kSqrt2          = 1.4142135623730950488016887242097f;
+
+	/// ln(10)
+	constexpr float    kLogNat10       = 2.3025850929940456840179914546844f;
+
+	/// The logarithm of the e to base 2. ln(kE) / ln(2)
+	constexpr float    kInvLogNat2     = 1.4426950408889634073599246810019f;
+
+	/// The natural logarithm of the 2. ln(2)
+	constexpr float    kLogNat2Hi      = 0.6931471805599453094172321214582f;
+
+	///
+	constexpr float    kLogNat2Lo      = 1.90821492927058770002e-10f;
+
+	/// The base of natural logarithms. e(1)
+	constexpr float    kE              = 2.7182818284590452353602874713527f;
+
+	///
+	constexpr float    kNearZero       = 1.0f/float(1 << 28);
+
+	/// Smallest normalized positive floating-point number.
+	constexpr float    kFloatSmallest  = 1.175494351e-38f;
+
+	/// Maximum representable floating-point number.
+	constexpr float    kFloatLargest   = 3.402823466e+38f;
+
+	/// Smallest normalized positive double-precision floating-point number.
+	constexpr double   kDoubleSmallest = 2.2250738585072014e-308;
+
+	/// Largest representable double-precision floating-point number.
+	constexpr double   kDoubleLargest  = 1.7976931348623158e+308;
+
+	///
+	extern const float kInfinity;
+
+} // namespace bx
+
+#endif // BX_CONSTANTS_H_HEADER_GUARD

+ 46 - 0
include/bx/inline/bx.inl

@@ -59,6 +59,52 @@ namespace bx
 		Ty tmp = _a; _a = _b; _b = tmp;
 		Ty tmp = _a; _a = _b; _b = tmp;
 	}
 	}
 
 
+	template<class Ty>
+	struct IsSignedT { static constexpr bool value = Ty(-1) < Ty(0); };
+
+	template<class Ty, bool SignT = IsSignedT<Ty>::value>
+	struct Limits;
+
+	template<class Ty>
+	struct Limits<Ty, true>
+	{
+		static constexpr Ty max = ( ( (Ty(1) << ( (sizeof(Ty) * 8) - 2) ) - Ty(1) ) << 1) | Ty(1);
+		static constexpr Ty min = -max - Ty(1);
+	};
+
+	template<class Ty>
+	struct Limits<Ty, false>
+	{
+		static constexpr Ty min = 0;
+		static constexpr Ty max = Ty(-1);
+	};
+
+	template<>
+	struct Limits<float, true>
+	{
+		static constexpr float min = -kFloatLargest;
+		static constexpr float max =  kFloatLargest;
+	};
+
+	template<>
+	struct Limits<double, true>
+	{
+		static constexpr double min = -kDoubleLargest;
+		static constexpr double max =  kDoubleLargest;
+	};
+
+	template<typename Ty>
+	inline constexpr Ty max()
+	{
+		return bx::Limits<Ty>::max;
+	}
+
+	template<typename Ty>
+	inline constexpr Ty min()
+	{
+		return bx::Limits<Ty>::min;
+	}
+
 	template<typename Ty>
 	template<typename Ty>
 	inline constexpr Ty min(const Ty& _a, const Ty& _b)
 	inline constexpr Ty min(const Ty& _a, const Ty& _b)
 	{
 	{

+ 0 - 16
include/bx/math.h

@@ -11,22 +11,6 @@
 
 
 namespace bx
 namespace bx
 {
 {
-	constexpr float kPi         = 3.1415926535897932384626433832795f;
-	constexpr float kPi2        = 6.2831853071795864769252867665590f;
-	constexpr float kInvPi      = 1.0f/kPi;
-	constexpr float kPiHalf     = 1.5707963267948966192313216916398f;
-	constexpr float kPiQuarter  = 0.7853981633974483096156608458199f;
-	constexpr float kSqrt2      = 1.4142135623730950488016887242097f;
-	constexpr float kLogNat10   = 2.3025850929940456840179914546844f;
-	constexpr float kInvLogNat2 = 1.4426950408889634073599246810019f;
-	constexpr float kLogNat2Hi  = 0.6931471805599453094172321214582f;
-	constexpr float kLogNat2Lo  = 1.90821492927058770002e-10f;
-	constexpr float kE          = 2.7182818284590452353602874713527f;
-	constexpr float kNearZero   = 1.0f/float(1 << 28);
-	constexpr float kFloatMin   = 1.175494e-38f;
-	constexpr float kFloatMax   = 3.402823e+38f;
-	extern const float kInfinity;
-
 	///
 	///
 	typedef float (*LerpFn)(float _a, float _b, float _t);
 	typedef float (*LerpFn)(float _a, float _b, float _t);
 
 

+ 38 - 0
tests/math_test.cpp

@@ -8,6 +8,8 @@
 #include <bx/file.h>
 #include <bx/file.h>
 
 
 #include <math.h>
 #include <math.h>
+#include <stdint.h> // intXX_t
+#include <limits.h> // UCHAR_*
 
 
 #if !BX_COMPILER_MSVC || BX_COMPILER_MSVC >= 1800
 #if !BX_COMPILER_MSVC || BX_COMPILER_MSVC >= 1800
 TEST_CASE("isFinite, isInfinite, isNan", "")
 TEST_CASE("isFinite, isInfinite, isNan", "")
@@ -334,3 +336,39 @@ TEST_CASE("quaternion", "")
 		REQUIRE(bx::isEqual(quat, q2, 0.001f) );
 		REQUIRE(bx::isEqual(quat, q2, 0.001f) );
 	}
 	}
 }
 }
+
+TEST_CASE("limits", "")
+{
+	STATIC_REQUIRE(bx::Limits<int8_t>::min == INT8_MIN);
+	STATIC_REQUIRE(bx::Limits<int8_t>::max == INT8_MAX);
+
+	STATIC_REQUIRE(bx::Limits<signed char>::min == CHAR_MIN);
+	STATIC_REQUIRE(bx::Limits<signed char>::max == CHAR_MAX);
+
+	STATIC_REQUIRE(bx::Limits<unsigned char>::min == 0);
+	STATIC_REQUIRE(bx::Limits<unsigned char>::max == UCHAR_MAX);
+
+	STATIC_REQUIRE(bx::Limits<int16_t>::min == INT16_MIN);
+	STATIC_REQUIRE(bx::Limits<int16_t>::max == INT16_MAX);
+
+	STATIC_REQUIRE(bx::Limits<uint16_t>::min == 0);
+	STATIC_REQUIRE(bx::Limits<uint16_t>::max == UINT16_MAX);
+
+	STATIC_REQUIRE(bx::Limits<int32_t>::min == INT32_MIN);
+	STATIC_REQUIRE(bx::Limits<int32_t>::max == INT32_MAX);
+
+	STATIC_REQUIRE(bx::Limits<uint32_t>::min == 0);
+	STATIC_REQUIRE(bx::Limits<uint32_t>::max == UINT32_MAX);
+
+	STATIC_REQUIRE(bx::Limits<int64_t>::min == INT64_MIN);
+	STATIC_REQUIRE(bx::Limits<int64_t>::max == INT64_MAX);
+
+	STATIC_REQUIRE(bx::Limits<uint64_t>::min == 0);
+	STATIC_REQUIRE(bx::Limits<uint64_t>::max == UINT64_MAX);
+
+	STATIC_REQUIRE(bx::Limits<float>::min == std::numeric_limits<float>::lowest() );
+	STATIC_REQUIRE(bx::Limits<float>::max == std::numeric_limits<float>::max() );
+
+	STATIC_REQUIRE(bx::Limits<double>::min == std::numeric_limits<double>::lowest() );
+	STATIC_REQUIRE(bx::Limits<double>::max == std::numeric_limits<double>::max() );
+}

+ 7 - 6
tests/sort_test.cpp

@@ -4,6 +4,7 @@
  */
  */
 
 
 #include "test.h"
 #include "test.h"
+#include <bx/bx.h>
 #include <bx/sort.h>
 #include <bx/sort.h>
 #include <bx/string.h>
 #include <bx/string.h>
 #include <bx/rng.h>
 #include <bx/rng.h>
@@ -110,12 +111,12 @@ void compareTest(const Ty& _min, const Ty& _max)
 {
 {
 	REQUIRE(_min < _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>(bx::min<Ty>(), bx::max<Ty>() ) );
+	REQUIRE(-1 == compareAscendingTest<Ty>(Ty(0),         bx::max<Ty>() ) );
+	REQUIRE( 0 == compareAscendingTest<Ty>(bx::min<Ty>(), bx::min<Ty>() ) );
+	REQUIRE( 0 == compareAscendingTest<Ty>(bx::max<Ty>(), bx::max<Ty>() ) );
+	REQUIRE( 1 == compareAscendingTest<Ty>(bx::max<Ty>(), Ty(0)         ) );
+	REQUIRE( 1 == compareAscendingTest<Ty>(bx::max<Ty>(), bx::min<Ty>() ) );
 
 
 	REQUIRE(-1 == compareAscendingTest<Ty>(_min, _max) );
 	REQUIRE(-1 == compareAscendingTest<Ty>(_min, _max) );
 	REQUIRE( 0 == compareAscendingTest<Ty>(_min, _min) );
 	REQUIRE( 0 == compareAscendingTest<Ty>(_min, _min) );