Browse Source

Further optimized glm::sign for signed and unsigned int #271

Christophe Riccio 11 years ago
parent
commit
38161f01f8
3 changed files with 37 additions and 2 deletions
  1. 34 2
      glm/detail/func_common.inl
  2. 1 0
      readme.txt
  3. 2 0
      test/core/core_func_common.cpp

+ 34 - 2
glm/detail/func_common.inl

@@ -128,6 +128,36 @@ namespace detail
 			return a ? y : x;
 		}
 	};
+
+	template <typename T, precision P, template <class, precision> class vecType, bool isFloat = true, bool isSigned = true>
+	struct compute_sign
+	{
+		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
+		{
+			return vecType<T, P>(glm::lessThan(vecType<T, P>(0), x)) - vecType<T, P>(glm::lessThan(x, vecType<T, P>(0)));
+		}
+	};
+
+	template <typename T, precision P, template <class, precision> class vecType>
+	struct compute_sign<T, P, vecType, false, false>
+	{
+		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
+		{
+			return glm::abs(x);
+		}
+	};
+
+	template <typename T, precision P, template <class, precision> class vecType>
+	struct compute_sign<T, P, vecType, false, true>
+	{
+		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
+		{
+			T const Shift(static_cast<T>(sizeof(T) * 8 - 1));
+			vecType<T, P> const y(vecType<typename make_unsigned<T>::type, P>(-x) >> typename make_unsigned<T>::type(Shift));
+
+			return (x >> Shift) | y;
+		}
+	};
 }//namespace detail
 
 	// abs
@@ -159,7 +189,7 @@ namespace detail
 			std::numeric_limits<genFIType>::is_iec559 || (std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer),
 			"'sign' only accept signed inputs");
 		
-		return static_cast<genFIType>(static_cast<genFIType>(0) < x) - static_cast<genFIType>(x < static_cast<genFIType>(0));
+		return detail::compute_sign<genFIType, defaultp, tvec1, std::numeric_limits<genFIType>::is_iec559>::call(tvec1<genFIType>(x)).x;
 	}
 
 	template <typename T, precision P, template <typename, precision> class vecType>
@@ -169,7 +199,9 @@ namespace detail
 			std::numeric_limits<T>::is_iec559 || (std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer),
 			"'sign' only accept signed inputs");
 
-		return vecType<T, P>(glm::lessThan(vecType<T, P>(0), x)) - vecType<T, P>(glm::lessThan(x, vecType<T, P>(0)));
+		return detail::compute_sign<T, P, vecType, std::numeric_limits<T>::is_iec559>::call(x);
+
+		//return vecType<T, P>(glm::lessThan(vecType<T, P>(0), x)) - vecType<T, P>(glm::lessThan(x, vecType<T, P>(0)));
 	}
 
 	// floor

+ 1 - 0
readme.txt

@@ -76,6 +76,7 @@ Improvements:
 - Removed <iostream> in GLM tests
 - Used std features within GLM without redeclaring
 - Optimized glm::cot #272
+- Optimized glm::sign #272
 
 Fixes:
 - Fixed std::nextafter not supported with C++11 on Android #217

+ 2 - 0
test/core/core_func_common.cpp

@@ -844,6 +844,8 @@ namespace sign
 	{
 		type<glm::int32> const Data[] =
 		{
+			{ std::numeric_limits<glm::int32>::max(),  1},
+			{ std::numeric_limits<glm::int32>::min(), -1},
 			{ 0, 0},
 			{ 1, 1},
 			{ 2, 1},