diff --git a/glm/gtc/bitfield.hpp b/glm/gtc/bitfield.hpp index 9dcec534..f8e952ae 100644 --- a/glm/gtc/bitfield.hpp +++ b/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 #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. diff --git a/glm/gtc/bitfield.inl b/glm/gtc/bitfield.inl index 97357408..0ccafb33 100644 --- a/glm/gtc/bitfield.inl +++ b/glm/gtc/bitfield.inl @@ -324,6 +324,34 @@ namespace detail return detail::bitfieldInterleave(x, y); } + GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(u8vec2 const& v) + { + return detail::bitfieldInterleave(v.x, v.y); + } + + GLM_FUNC_QUALIFIER u8vec2 bitfieldDeinterleave(glm::uint16 x) + { + uint16 REG1(x); + uint16 REG2(x >>= 1); + + REG1 = REG1 & static_cast(0x5555555555555555ull); + REG2 = REG2 & static_cast(0x5555555555555555ull); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x3333333333333333ull); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x3333333333333333ull); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF00FF00FF00FFull); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0x0000FFFF0000FFFFull); + REG2 = ((REG2 >> 8) | REG2) & static_cast(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(x, y); } + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(u16vec2 const& v) + { + return detail::bitfieldInterleave(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(0x5555555555555555ull); + REG2 = REG2 & static_cast(0x5555555555555555ull); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x3333333333333333ull); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x3333333333333333ull); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF00FF00FF00FFull); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0x0000FFFF0000FFFFull); + REG2 = ((REG2 >> 8) | REG2) & static_cast(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(x, y); } + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(u32vec2 const& v) + { + return detail::bitfieldInterleave(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(0x5555555555555555ull); + REG2 = REG2 & static_cast(0x5555555555555555ull); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x3333333333333333ull); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x3333333333333333ull); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF00FF00FF00FFull); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0x0000FFFF0000FFFFull); + REG2 = ((REG2 >> 8) | REG2) & static_cast(0x0000FFFF0000FFFFull); + + REG1 = ((REG1 >> 16) | REG1) & static_cast(0x00000000FFFFFFFFull); + REG2 = ((REG2 >> 16) | REG2) & static_cast(0x00000000FFFFFFFFull); + + return glm::u32vec2(REG1, REG2); + } + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z) { union sign8 diff --git a/readme.md b/readme.md index 099620bd..66ee1d3a 100644 --- a/readme.md +++ b/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 diff --git a/test/core/core_func_common.cpp b/test/core/core_func_common.cpp index 50492634..0a33382e 100644 --- a/test/core/core_func_common.cpp +++ b/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 A(Count); + std::vector 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(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(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; } diff --git a/test/gtc/gtc_bitfield.cpp b/test/gtc/gtc_bitfield.cpp index 93a0e385..19a09acf 100644 --- a/test/gtc/gtc_bitfield.cpp +++ b/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; + } + } - Error += D == E ? 0 : 1; - Error += D == F ? 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 += 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();