Browse Source

Added bitfieldDeinterleave with tests

Christophe Riccio 7 years ago
parent
commit
b4981e56fa
5 changed files with 205 additions and 8 deletions
  1. 37 0
      glm/gtc/bitfield.hpp
  2. 87 0
      glm/gtc/bitfield.inl
  3. 4 0
      readme.md
  4. 58 0
      test/core/core_func_common.cpp
  5. 19 8
      test/gtc/gtc_bitfield.cpp

+ 37 - 0
glm/gtc/bitfield.hpp

@@ -19,6 +19,7 @@
 #include "../detail/qualifier.hpp"
 #include "../detail/type_int.hpp"
 #include "../detail/_vectorize.hpp"
+#include "type_precision.hpp"
 #include <limits>
 
 #if GLM_MESSAGES == GLM_MESSAGES_ENABLED && !defined(GLM_EXT_INCLUDED)
@@ -124,6 +125,18 @@ namespace glm
 	/// @see gtc_bitfield
 	GLM_FUNC_DECL uint16 bitfieldInterleave(uint8 x, uint8 y);
 
+	/// Interleaves the bits of x and y.
+	/// The first bit is the first bit of v.x followed by the first bit of v.y.
+	/// The other bits are interleaved following the previous sequence.
+	///
+	/// @see gtc_bitfield
+	GLM_FUNC_DECL uint16 bitfieldInterleave(u8vec2 const& v);
+
+	/// Deinterleaves the bits of x.
+	///
+	/// @see gtc_bitfield
+	GLM_FUNC_DECL glm::u8vec2 bitfieldDeinterleave(glm::uint16 x);
+
 	/// Interleaves the bits of x and y.
 	/// The first bit is the first bit of x followed by the first bit of y.
 	/// The other bits are interleaved following the previous sequence.
@@ -138,6 +151,18 @@ namespace glm
 	/// @see gtc_bitfield
 	GLM_FUNC_DECL uint32 bitfieldInterleave(uint16 x, uint16 y);
 
+	/// Interleaves the bits of x and y.
+	/// The first bit is the first bit of v.x followed by the first bit of v.y.
+	/// The other bits are interleaved following the previous sequence.
+	///
+	/// @see gtc_bitfield
+	GLM_FUNC_DECL uint32 bitfieldInterleave(u16vec2 const& v);
+
+	/// Deinterleaves the bits of x.
+	///
+	/// @see gtc_bitfield
+	GLM_FUNC_DECL glm::u16vec2 bitfieldDeinterleave(glm::uint32 x);
+
 	/// Interleaves the bits of x and y.
 	/// The first bit is the first bit of x followed by the first bit of y.
 	/// The other bits are interleaved following the previous sequence.
@@ -152,6 +177,18 @@ namespace glm
 	/// @see gtc_bitfield
 	GLM_FUNC_DECL uint64 bitfieldInterleave(uint32 x, uint32 y);
 
+	/// Interleaves the bits of x and y.
+	/// The first bit is the first bit of v.x followed by the first bit of v.y.
+	/// The other bits are interleaved following the previous sequence.
+	///
+	/// @see gtc_bitfield
+	GLM_FUNC_DECL uint64 bitfieldInterleave(u32vec2 const& v);
+
+	/// Deinterleaves the bits of x.
+	///
+	/// @see gtc_bitfield
+	GLM_FUNC_DECL glm::u32vec2 bitfieldDeinterleave(glm::uint64 x);
+
 	/// Interleaves the bits of x, y and z.
 	/// The first bit is the first bit of x followed by the first bit of y and the first bit of z.
 	/// The other bits are interleaved following the previous sequence.

+ 87 - 0
glm/gtc/bitfield.inl

@@ -324,6 +324,34 @@ namespace detail
 		return detail::bitfieldInterleave<uint8, uint16>(x, y);
 	}
 
+	GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(u8vec2 const& v)
+	{
+		return detail::bitfieldInterleave<uint8, uint16>(v.x, v.y);
+	}
+
+	GLM_FUNC_QUALIFIER u8vec2 bitfieldDeinterleave(glm::uint16 x)
+	{
+		uint16 REG1(x);
+		uint16 REG2(x >>= 1);
+
+		REG1 = REG1 & static_cast<uint16>(0x5555555555555555ull);
+		REG2 = REG2 & static_cast<uint16>(0x5555555555555555ull);
+
+		REG1 = ((REG1 >> 1) | REG1) & static_cast<uint16>(0x3333333333333333ull);
+		REG2 = ((REG2 >> 1) | REG2) & static_cast<uint16>(0x3333333333333333ull);
+
+		REG1 = ((REG1 >> 2) | REG1) & static_cast<uint16>(0x0F0F0F0F0F0F0F0Full);
+		REG2 = ((REG2 >> 2) | REG2) & static_cast<uint16>(0x0F0F0F0F0F0F0F0Full);
+
+		REG1 = ((REG1 >> 4) | REG1) & static_cast<uint16>(0x00FF00FF00FF00FFull);
+		REG2 = ((REG2 >> 4) | REG2) & static_cast<uint16>(0x00FF00FF00FF00FFull);
+
+		REG1 = ((REG1 >> 8) | REG1) & static_cast<uint16>(0x0000FFFF0000FFFFull);
+		REG2 = ((REG2 >> 8) | REG2) & static_cast<uint16>(0x0000FFFF0000FFFFull);
+
+		return glm::u8vec2(REG1, REG2);
+	}
+
 	GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int16 x, int16 y)
 	{
 		union sign16
@@ -350,6 +378,34 @@ namespace detail
 		return detail::bitfieldInterleave<uint16, uint32>(x, y);
 	}
 
+	GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(u16vec2 const& v)
+	{
+		return detail::bitfieldInterleave<uint16, uint32>(v.x, v.y);
+	}
+
+	GLM_FUNC_QUALIFIER glm::u16vec2 bitfieldDeinterleave(glm::uint32 x)
+	{
+		glm::uint32 REG1(x);
+		glm::uint32 REG2(x >>= 1);
+
+		REG1 = REG1 & static_cast<glm::uint32>(0x5555555555555555ull);
+		REG2 = REG2 & static_cast<glm::uint32>(0x5555555555555555ull);
+
+		REG1 = ((REG1 >> 1) | REG1) & static_cast<glm::uint32>(0x3333333333333333ull);
+		REG2 = ((REG2 >> 1) | REG2) & static_cast<glm::uint32>(0x3333333333333333ull);
+
+		REG1 = ((REG1 >> 2) | REG1) & static_cast<glm::uint32>(0x0F0F0F0F0F0F0F0Full);
+		REG2 = ((REG2 >> 2) | REG2) & static_cast<glm::uint32>(0x0F0F0F0F0F0F0F0Full);
+
+		REG1 = ((REG1 >> 4) | REG1) & static_cast<glm::uint32>(0x00FF00FF00FF00FFull);
+		REG2 = ((REG2 >> 4) | REG2) & static_cast<glm::uint32>(0x00FF00FF00FF00FFull);
+
+		REG1 = ((REG1 >> 8) | REG1) & static_cast<glm::uint32>(0x0000FFFF0000FFFFull);
+		REG2 = ((REG2 >> 8) | REG2) & static_cast<glm::uint32>(0x0000FFFF0000FFFFull);
+
+		return glm::u16vec2(REG1, REG2);
+	}
+
 	GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y)
 	{
 		union sign32
@@ -376,6 +432,37 @@ namespace detail
 		return detail::bitfieldInterleave<uint32, uint64>(x, y);
 	}
 
+	GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(u32vec2 const& v)
+	{
+		return detail::bitfieldInterleave<uint32, uint64>(v.x, v.y);
+	}
+
+	GLM_FUNC_QUALIFIER glm::u32vec2 bitfieldDeinterleave(glm::uint64 x)
+	{
+		glm::uint64 REG1(x);
+		glm::uint64 REG2(x >>= 1);
+
+		REG1 = REG1 & static_cast<glm::uint64>(0x5555555555555555ull);
+		REG2 = REG2 & static_cast<glm::uint64>(0x5555555555555555ull);
+
+		REG1 = ((REG1 >> 1) | REG1) & static_cast<glm::uint64>(0x3333333333333333ull);
+		REG2 = ((REG2 >> 1) | REG2) & static_cast<glm::uint64>(0x3333333333333333ull);
+
+		REG1 = ((REG1 >> 2) | REG1) & static_cast<glm::uint64>(0x0F0F0F0F0F0F0F0Full);
+		REG2 = ((REG2 >> 2) | REG2) & static_cast<glm::uint64>(0x0F0F0F0F0F0F0F0Full);
+
+		REG1 = ((REG1 >> 4) | REG1) & static_cast<glm::uint64>(0x00FF00FF00FF00FFull);
+		REG2 = ((REG2 >> 4) | REG2) & static_cast<glm::uint64>(0x00FF00FF00FF00FFull);
+
+		REG1 = ((REG1 >> 8) | REG1) & static_cast<glm::uint64>(0x0000FFFF0000FFFFull);
+		REG2 = ((REG2 >> 8) | REG2) & static_cast<glm::uint64>(0x0000FFFF0000FFFFull);
+
+		REG1 = ((REG1 >> 16) | REG1) & static_cast<glm::uint64>(0x00000000FFFFFFFFull);
+		REG2 = ((REG2 >> 16) | REG2) & static_cast<glm::uint64>(0x00000000FFFFFFFFull);
+
+		return glm::u32vec2(REG1, REG2);
+	}
+
 	GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z)
 	{
 		union sign8

+ 4 - 0
readme.md

@@ -51,6 +51,10 @@ glm::mat4 camera(float Translate, glm::vec2 const& Rotate)
 
 ## Release notes
 
+### [GLM 0.9.9.1](https://github.com/g-truc/glm/commits/master) - 2018-0X-XX
+#### Features:
+- Added bitfieldDeinterleave to GTC_bitfield
+
 ### [GLM 0.9.9.0](https://github.com/g-truc/glm/releases/tag/0.9.9.0) - 2018-05-22
 #### Features:
 - Added RGBM encoding in GTC_packing #420

+ 58 - 0
test/core/core_func_common.cpp

@@ -289,6 +289,62 @@ namespace min_
 
 		return Error;
 	}
+
+	int min_tern(int a, int b)
+	{
+		return a < b ? a : b;
+	}
+
+	int min_int(int x, int y)
+	{
+		return y ^ ((x ^ y) & -(x < y)); 
+	}
+
+	static int perf(int Count)
+	{
+		std::vector<int> A(Count);
+		std::vector<int> B(Count);
+
+		std::size_t const InternalCount = 200000;
+
+		for(std::size_t i = 0; i < Count; ++i)
+		{
+			A[i] = glm::linearRand(-1000, 1000);
+			B[i] = glm::linearRand(-1000, 1000);
+		}
+
+		int Error = 0;
+
+		glm::int32 SumA = 0;
+		{
+			std::clock_t Timestamp0 = std::clock();
+
+			for (std::size_t j = 0; j < InternalCount; ++j)
+			for (std::size_t i = 0; i < Count; ++i)
+				SumA += min_tern(A[i], B[i]);
+
+			std::clock_t Timestamp1 = std::clock();
+
+			std::printf("min_tern Time %d clocks\n", static_cast<unsigned int>(Timestamp1 - Timestamp0));
+		}
+
+		glm::int32 SumB = 0;
+		{
+			std::clock_t Timestamp0 = std::clock();
+
+			for (std::size_t j = 0; j < InternalCount; ++j)
+			for (std::size_t i = 0; i < Count; ++i)
+				SumB += min_int(A[i], B[i]);
+
+			std::clock_t Timestamp1 = std::clock();
+
+			std::printf("min_int Time %d clocks\n", static_cast<unsigned int>(Timestamp1 - Timestamp0));
+		}
+
+		Error += SumA == SumB ? 0 : 1;
+
+		return Error;
+	}
 }//namespace min_
 
 namespace max_
@@ -1262,6 +1318,8 @@ int main()
 #	endif
 	Error += sign::perf(Samples);
 
+	Error += min_::perf(Samples);
+
 	return Error;
 }
 

+ 19 - 8
test/gtc/gtc_bitfield.cpp

@@ -493,19 +493,29 @@ namespace bitfieldInterleave
 			for(glm::uint8 y = 0; y < 127; ++y)
 			for(glm::uint8 x = 0; x < 127; ++x)
 			{
-				glm::uint64 A(glm::bitfieldInterleave(glm::uint8(x), glm::uint8(y)));
-				glm::uint64 B(glm::bitfieldInterleave(glm::uint16(x), glm::uint16(y)));
-				glm::uint64 C(glm::bitfieldInterleave(glm::uint32(x), glm::uint32(y)));
+				glm::uint64 A(glm::bitfieldInterleave(glm::u8vec2(x, y)));
+				glm::uint64 B(glm::bitfieldInterleave(glm::u16vec2(x, y)));
+				glm::uint64 C(glm::bitfieldInterleave(glm::u32vec2(x, y)));
 
 				Error += A == B ? 0 : 1;
 				Error += A == C ? 0 : 1;
 
-				glm::int64 D(glm::bitfieldInterleave(glm::int8(x), glm::int8(y)));
-				glm::int64 E(glm::bitfieldInterleave(glm::int16(x), glm::int16(y)));
-				glm::int64 F(glm::bitfieldInterleave(glm::int32(x), glm::int32(y)));
+				glm::u32vec2 const& D = glm::bitfieldDeinterleave(C);
+				Error += D.x == x ? 0 : 1;
+				Error += D.y == y ? 0 : 1;
+			}
+		}
+
+		{
+			for(glm::uint8 y = 0; y < 127; ++y)
+			for(glm::uint8 x = 0; x < 127; ++x)
+			{
+				glm::int64 A(glm::bitfieldInterleave(glm::int8(x), glm::int8(y)));
+				glm::int64 B(glm::bitfieldInterleave(glm::int16(x), glm::int16(y)));
+				glm::int64 C(glm::bitfieldInterleave(glm::int32(x), glm::int32(y)));
 
-				Error += D == E ? 0 : 1;
-				Error += D == F ? 0 : 1;
+				Error += A == B ? 0 : 1;
+				Error += A == C ? 0 : 1;
 			}
 		}
 
@@ -888,6 +898,7 @@ namespace bitfieldInterleave5
 int main()
 {
 	int Error = 0;
+
 /* Tests for a faster and to reserve bitfieldInterleave
 	Error += ::bitfieldInterleave5::test();
 	Error += ::bitfieldInterleave5::perf();