Преглед на файлове

Merge branch '0.9.3' into swizzle

Christophe Riccio преди 14 години
родител
ревизия
c4af12634b
променени са 9 файла, в които са добавени 246 реда и са изтрити 81 реда
  1. 1 0
      glm/core/func_common.inl
  2. 32 0
      glm/core/func_integer.inl
  3. 0 1
      glm/ext.hpp
  4. 28 0
      glm/gtx/integer.hpp
  5. 116 0
      glm/gtx/integer.inl
  6. 2 52
      glm/gtx/unsigned_int.hpp
  7. 0 28
      glm/gtx/unsigned_int.inl
  8. 1 0
      test/gtx/CMakeLists.txt
  9. 66 0
      test/gtx/gtx_integer.cpp

+ 1 - 0
glm/core/func_common.inl

@@ -42,6 +42,7 @@ namespace detail
                 detail::type<genFIType>::is_float || 
                 detail::type<genFIType>::is_int, "'abs' only accept floating-point and integer inputs");
             return x >= genFIType(0) ? x : -x;
+			// TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff;
         }
     };
 

+ 32 - 0
glm/core/func_integer.inl

@@ -26,6 +26,11 @@
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 
+#if(GLM_COMPILER & GLM_COMPILER_VC)
+#include <intrin.h>
+#pragma intrinsic(_BitScanReverse)
+#endif
+
 namespace glm
 {
 	// uaddCarry
@@ -550,6 +555,32 @@ namespace glm
 	}
 
 	// findMSB
+#if(GLM_COMPILER & GLM_COMPILER_VC)
+
+	template <typename genIUType>
+	GLM_FUNC_QUALIFIER int findMSB
+	(
+		genIUType const & Value
+	)
+	{
+		unsigned long Result(0);
+		_BitScanReverse(&Result, Value); 
+		return int(Result);
+	}
+
+#elif((GLM_COMPILER & GLM_COMPILER_GCC) && __has_builtin(__builtin_clz))
+
+	template <typename genIUType>
+	GLM_FUNC_QUALIFIER int findMSB
+	(
+		genIUType const & Value
+	)
+	{
+		return __builtin_clz(x);
+	}
+
+#else
+
 	template <typename genIUType>
 	GLM_FUNC_QUALIFIER int findMSB
 	(
@@ -564,6 +595,7 @@ namespace glm
 		for(genIUType tmp = Value; tmp; tmp >>= 1, ++bit){}
 		return bit;
 	}
+#endif//(GLM_COMPILER)
 
 	template <typename T>
 	GLM_FUNC_QUALIFIER detail::tvec2<int> findMSB

+ 0 - 1
glm/ext.hpp

@@ -124,7 +124,6 @@
 #include "./gtx/transform.hpp"
 #include "./gtx/transform2.hpp"
 #include "./gtx/ulp.hpp"
-#include "./gtx/unsigned_int.hpp"
 #include "./gtx/vec1.hpp"
 #include "./gtx/vector_access.hpp"
 #include "./gtx/vector_angle.hpp"

+ 28 - 0
glm/gtx/integer.hpp

@@ -58,6 +58,14 @@ namespace glm
 	//! From GLM_GTX_integer extension.
 	int sqrt(int x);
 
+	//! Returns the log2 of x. Can be reliably using to compute mipmap count from the texture size.
+	//! From GLM_GTX_integer extension.
+	unsigned int log2(unsigned int x);
+
+	//! Returns the floor log2 of x.
+	//! From GLM_GTX_integer extension.
+	unsigned int floor_log2(unsigned int x);
+
 	//! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y.
 	//! From GLM_GTX_integer extension.
 	int mod(int x, int y);
@@ -67,6 +75,26 @@ namespace glm
 	template <typename genType> 
 	genType factorial(genType const & x);
 
+	//! 32bit signed integer. 
+	//! From GLM_GTX_integer extension.
+	typedef signed int					sint;
+
+	//! Returns x raised to the y power.
+	//! From GLM_GTX_integer extension.
+	uint pow(uint x, uint y);
+
+	//! Returns the positive square root of x. 
+	//! From GLM_GTX_integer extension.
+	uint sqrt(uint x);
+
+	//! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y.
+	//! From GLM_GTX_integer extension.
+	uint mod(uint x, uint y);
+
+	//! Returns the number of leading zeros.
+	//! From GLM_GTX_integer extension.
+	uint nlz(uint x);
+
 	/// @}
 }//namespace glm
 

+ 116 - 0
glm/gtx/integer.inl

@@ -37,6 +37,52 @@ GLM_FUNC_QUALIFIER int sqrt(int x)
     return CurrentAnswer;
 }
 
+// Henry Gordon Dietz: http://aggregate.org/MAGIC/
+namespace detail
+{
+	GLM_FUNC_QUALIFIER unsigned int ones32(unsigned int x)
+	{
+		/* 32-bit recursive reduction using SWAR...
+		but first step is mapping 2-bit values
+		into sum of 2 1-bit values in sneaky way
+		*/
+		x -= ((x >> 1) & 0x55555555);
+		x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
+		x = (((x >> 4) + x) & 0x0f0f0f0f);
+		x += (x >> 8);
+		x += (x >> 16);
+		return(x & 0x0000003f);
+	}
+}//namespace detail
+
+#if(GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_GCC))
+
+GLM_FUNC_QUALIFIER unsigned int log2(unsigned int x)
+{
+	return x <= 1 ? 0 : unsigned(32) - nlz(x - 1u);
+}
+
+#else
+
+GLM_FUNC_QUALIFIER unsigned int log2(unsigned int x)
+{
+	return unsigned(32) - nlz(x - 1u);
+}
+
+#endif
+
+// Henry Gordon Dietz: http://aggregate.org/MAGIC/
+unsigned int floor_log2(unsigned int x)
+{
+	x |= (x >> 1);
+	x |= (x >> 2);
+	x |= (x >> 4);
+	x |= (x >> 8);
+	x |= (x >> 16);
+
+	return(detail::ones32(x) - 1);
+}
+
 // mod
 GLM_FUNC_QUALIFIER int mod(int x, int y)
 {
@@ -84,4 +130,74 @@ GLM_FUNC_QUALIFIER detail::tvec4<valType> factorial(
         factorial(x.w));
 }
 
+GLM_FUNC_QUALIFIER uint pow(uint x, uint y)
+{
+    uint result = x;
+    for(uint i = 1; i < y; ++i)
+        result *= x;
+    return result;
+}
+
+GLM_FUNC_QUALIFIER uint sqrt(uint x)
+{
+    if(x <= 1) return x;
+
+    uint NextTrial = x >> 1;
+    uint CurrentAnswer;
+
+    do
+    {
+        CurrentAnswer = NextTrial;
+        NextTrial = (NextTrial + x / NextTrial) >> 1;
+    } while(NextTrial < CurrentAnswer);
+
+    return CurrentAnswer;
+}
+
+GLM_FUNC_QUALIFIER uint mod(uint x, uint y)
+{
+	return x - y * (x / y);
+}
+
+#if(GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_GCC))
+
+GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) 
+{
+	return 31u - findMSB(x);
+}
+
+#else
+
+// Hackers Delight: http://www.hackersdelight.org/HDcode/nlz.c.txt
+GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) 
+{
+   int y, m, n;
+
+   y = -int(x >> 16);      // If left half of x is 0,
+   m = (y >> 16) & 16;  // set n = 16.  If left half
+   n = 16 - m;          // is nonzero, set n = 0 and
+   x = x >> m;          // shift x right 16.
+                        // Now x is of the form 0000xxxx.
+   y = x - 0x100;       // If positions 8-15 are 0,
+   m = (y >> 16) & 8;   // add 8 to n and shift x left 8.
+   n = n + m;
+   x = x << m;
+
+   y = x - 0x1000;      // If positions 12-15 are 0,
+   m = (y >> 16) & 4;   // add 4 to n and shift x left 4.
+   n = n + m;
+   x = x << m;
+
+   y = x - 0x4000;      // If positions 14-15 are 0,
+   m = (y >> 16) & 2;   // add 2 to n and shift x left 2.
+   n = n + m;
+   x = x << m;
+
+   y = x >> 14;         // Set y = 0, 1, 2, or 3.
+   m = y & ~(y >> 1);   // Set m = 0, 1, 2, or 2 resp.
+   return unsigned(n + 2 - m);
+}
+
+#endif//(GLM_COMPILER)
+
 }//namespace glm

+ 2 - 52
glm/gtx/unsigned_int.hpp

@@ -19,58 +19,8 @@
 /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 /// THE SOFTWARE.
-///
-/// @ref gtx_unsigned_int
-/// @file glm/gtx/unsigned_int.hpp
-/// @date 2005-12-24 / 2011-06-07
-/// @author Christophe Riccio
-///
-/// @see core (dependence)
-/// @see gtx_integer (dependence)
-///
-/// @defgroup gtx_unsigned_int GLM_GTX_unsigned_int: Unsigned int
-/// @ingroup gtx
-/// 
-/// @brief Add support for unsigned integer for core functions
-/// 
-/// <glm/gtx/unsigned_int.hpp> need to be included to use these functionalities.
 ///////////////////////////////////////////////////////////////////////////////////
 
-#ifndef GLM_GTX_unsigned_int
-#define GLM_GTX_unsigned_int GLM_VERSION
-
-// Dependency:
-#include "../glm.hpp"
-#include "../gtx/integer.hpp"
-
-#if(defined(GLM_MESSAGES) && !defined(glm_ext))
-#	pragma message("GLM: GLM_GTX_unsigned_int extension included")
+#if(defined(GLM_MESSAGES))
+#	pragma message("GLM: GLM_GTX_unsigned_int extension is deprecated, include GLM_GTX_integer instead")
 #endif
-
-namespace glm
-{
-	/// @addtogroup gtx_unsigned_int
-	/// @{
-
-	//! 32bit signed integer. 
-	//! From GLM_GTX_unsigned_int extension.
-	typedef signed int					sint;
-
-	//! Returns x raised to the y power.
-	//! From GLM_GTX_unsigned_int extension.
-	uint pow(uint x, uint y);
-
-	//! Returns the positive square root of x. 
-	//! From GLM_GTX_unsigned_int extension.
-	uint sqrt(uint x);
-
-	//! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y.
-	//! From GLM_GTX_unsigned_int extension.
-	uint mod(uint x, uint y);
-
-	/// @}
-}//namespace glm
-
-#include "unsigned_int.inl"
-
-#endif//GLM_GTX_unsigned_int

+ 0 - 28
glm/gtx/unsigned_int.inl

@@ -9,33 +9,5 @@
 
 namespace glm{
 
-GLM_FUNC_QUALIFIER uint pow(uint x, uint y)
-{
-    uint result = x;
-    for(uint i = 1; i < y; ++i)
-        result *= x;
-    return result;
-}
-
-GLM_FUNC_QUALIFIER uint sqrt(uint x)
-{
-    if(x <= 1) return x;
-
-    uint NextTrial = x >> 1;
-    uint CurrentAnswer;
-
-    do
-    {
-        CurrentAnswer = NextTrial;
-        NextTrial = (NextTrial + x / NextTrial) >> 1;
-    } while(NextTrial < CurrentAnswer);
-
-    return CurrentAnswer;
-}
-
-GLM_FUNC_QUALIFIER uint mod(uint x, uint y)
-{
-	return x - y * (x / y);
-}
 
 }//namespace glm

+ 1 - 0
test/gtx/CMakeLists.txt

@@ -1,4 +1,5 @@
 glmCreateTestGTC(gtx_bit)
+glmCreateTestGTC(gtx_integer)
 glmCreateTestGTC(gtx_noise)
 glmCreateTestGTC(gtx_quaternion)
 glmCreateTestGTC(gtx_random)

+ 66 - 0
test/gtx/gtx_integer.cpp

@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Created : 2011-10-11
+// Updated : 2011-10-11
+// Licence : This source is under MIT licence
+// File    : test/gtx/gtx_integer.cpp
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include <glm/glm.hpp>
+#include <glm/gtx/integer.hpp>
+#include <glm/gtx/epsilon.hpp>
+#include <iostream>
+
+int test_floor_log2()
+{
+	int Error = 0;
+
+	for(std::size_t i = 1; i < 1000000; ++i)
+	{
+		glm::uint A = glm::floor_log2(glm::uint(i));
+		glm::uint B = glm::uint(glm::log2(double(i))); // Will fail with float, lack of accuracy
+
+		Error += A == B ? 0 : 1;
+		assert(!Error);
+	}
+
+	return Error;
+}
+
+int test_log2()
+{
+	int Error = 0;
+
+	for(std::size_t i = 1; i < 1000000; ++i)
+	{
+		glm::uint A = glm::log2(glm::uint(i));
+		double B = glm::log2(double(i));
+
+		Error += glm::equalEpsilon(double(A), B, 1.0) ? 0 : 1;
+		//assert(!Error);
+	}
+
+	return Error;
+}
+
+int test_nlz()
+{
+	int Error = 0;
+
+	for(std::size_t i = 1; i < 33; ++i)
+		printf("%d, %d\n", glm::nlz(i), 31u - glm::findMSB(i));
+
+	return Error;
+}
+
+int main()
+{
+	int Error = 0;
+
+	Error += test_nlz();
+	Error += test_floor_log2();
+	Error += test_log2();
+
+	return Error;
+}