From 09ee14ad4c0d80479862c8396f23e36f1ebc28fc Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 11 Oct 2011 15:31:16 +0100 Subject: [PATCH 1/3] Added uint log2 and deprecate GTX_unsigned_int --- glm/core/func_common.inl | 1 + glm/ext.hpp | 1 - glm/gtx/integer.hpp | 20 ++++++ glm/gtx/integer.inl | 75 +++++++++++++++++++++ glm/gtx/unsigned_int.hpp | 54 +--------------- glm/gtx/unsigned_int.inl | 28 -------- test/gtx/CMakeLists.txt | 1 + test/gtx/gtx_integer.cpp | 136 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 235 insertions(+), 81 deletions(-) create mode 100644 test/gtx/gtx_integer.cpp diff --git a/glm/core/func_common.inl b/glm/core/func_common.inl index 06a45018..0d587d66 100644 --- a/glm/core/func_common.inl +++ b/glm/core/func_common.inl @@ -42,6 +42,7 @@ namespace detail detail::type::is_float || detail::type::is_int, "'abs' only accept floating-point and integer inputs"); return x >= genFIType(0) ? x : -x; + // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; } }; diff --git a/glm/ext.hpp b/glm/ext.hpp index 70209d6d..5c9b0fe5 100644 --- a/glm/ext.hpp +++ b/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" diff --git a/glm/gtx/integer.hpp b/glm/gtx/integer.hpp index 0fe8cb0b..5dde37e5 100644 --- a/glm/gtx/integer.hpp +++ b/glm/gtx/integer.hpp @@ -58,6 +58,10 @@ namespace glm //! From GLM_GTX_integer extension. int sqrt(int x); + //! Returns the log2 of x. + //! From GLM_GTX_integer extension. + unsigned int 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 +71,22 @@ namespace glm template genType factorial(genType const & x); + //! 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 diff --git a/glm/gtx/integer.inl b/glm/gtx/integer.inl index b70868cb..113cb3cd 100644 --- a/glm/gtx/integer.inl +++ b/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 +/* +// Henry Gordon Dietz: http://aggregate.org/MAGIC/ +GLM_FUNC_QUALIFIER unsigned int log2(unsigned int x) +{ + register int y = (x & (x - 1)); + + y |= -y; + y >>= (WORDBITS - 1); + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + + return detail::ones32(x) - 1 - y; +} +*/ +// Henry Gordon Dietz: http://aggregate.org/MAGIC/ +unsigned int 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,33 @@ GLM_FUNC_QUALIFIER detail::tvec4 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); +} + }//namespace glm diff --git a/glm/gtx/unsigned_int.hpp b/glm/gtx/unsigned_int.hpp index 239e6b6b..d494905f 100644 --- a/glm/gtx/unsigned_int.hpp +++ b/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 -/// -/// 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 diff --git a/glm/gtx/unsigned_int.inl b/glm/gtx/unsigned_int.inl index 133a3022..953e4ba1 100644 --- a/glm/gtx/unsigned_int.inl +++ b/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 diff --git a/test/gtx/CMakeLists.txt b/test/gtx/CMakeLists.txt index b7a44b8d..504aeff8 100644 --- a/test/gtx/CMakeLists.txt +++ b/test/gtx/CMakeLists.txt @@ -1,4 +1,5 @@ glmCreateTestGTC(gtx_bit) +glmCreateTestGTC(gtx_integer) glmCreateTestGTC(gtx_noise) glmCreateTestGTC(gtx_quaternion) glmCreateTestGTC(gtx_random) diff --git a/test/gtx/gtx_integer.cpp b/test/gtx/gtx_integer.cpp new file mode 100644 index 00000000..13c9178b --- /dev/null +++ b/test/gtx/gtx_integer.cpp @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2010-09-16 +// Updated : 2010-09-16 +// Licence : This source is under MIT licence +// File : test/gtx/bit.cpp +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +enum result +{ + SUCCESS, + FAIL, + ASSERT, + STATIC_ASSERT +}; + +namespace extractField +{ + template + struct type + { + genType Value; + sizeType BitFirst; + sizeType BitCount; + genType Return; + result Result; + }; + + typedef type typeU64; + + typeU64 const Data64[] = + { + {0xffffffffffffffff, 8, 0, 0x0000000000000000, SUCCESS}, + {0x0000000000000000, 0,64, 0x0000000000000000, SUCCESS}, + {0xffffffffffffffff, 0,64, 0xffffffffffffffff, SUCCESS}, + {0x0f0f0f0f0f0f0f0f, 0,64, 0x0f0f0f0f0f0f0f0f, SUCCESS}, + {0x0000000000000000, 8, 0, 0x0000000000000000, SUCCESS}, + {0x8000000000000000,63, 1, 0x0000000000000001, SUCCESS}, + {0x7fffffffffffffff,63, 1, 0x0000000000000000, SUCCESS}, + {0x0000000000000300, 8, 8, 0x0000000000000003, SUCCESS}, + {0x000000000000ff00, 8, 8, 0x00000000000000ff, SUCCESS}, + {0xfffffffffffffff0, 0, 5, 0x0000000000000010, SUCCESS}, + {0x00000000000000ff, 1, 3, 0x0000000000000007, SUCCESS}, + {0x00000000000000ff, 0, 3, 0x0000000000000007, SUCCESS}, + {0x0000000000000000, 0, 2, 0x0000000000000000, SUCCESS}, + {0xffffffffffffffff, 0, 8, 0x00000000000000ff, SUCCESS}, + {0xffffffff00000000,32,32, 0x00000000ffffffff, SUCCESS}, + {0xfffffffffffffff0, 0, 8, 0x0000000000000000, FAIL}, + {0xffffffffffffffff,32,32, 0x0000000000000000, FAIL}, + //{0xffffffffffffffff,64, 1, 0x0000000000000000, ASSERT}, // Throw an assert + //{0xffffffffffffffff, 0,65, 0x0000000000000000, ASSERT}, // Throw an assert + //{0xffffffffffffffff,33,32, 0x0000000000000000, ASSERT}, // Throw an assert + }; + + int test() + { + glm::uint32 count = sizeof(Data64) / sizeof(typeU64); + + for(glm::uint32 i = 0; i < count; ++i) + { + glm::uint64 Return = glm::extractField( + Data64[i].Value, + Data64[i].BitFirst, + Data64[i].BitCount); + + bool Compare = Data64[i].Return == Return; + + if(Data64[i].Result == SUCCESS && Compare) + continue; + else if(Data64[i].Result == FAIL && !Compare) + continue; + + std::cout << "glm::extractfield test fail on test " << i << std::endl; + return 1; + } + + return 0; + } +}//extractField + +namespace bitRevert +{ + template + struct type + { + genType Value; + genType Return; + result Result; + }; + + typedef type typeU64; + + typeU64 const Data64[] = + { + {0xffffffffffffffff, 0xffffffffffffffff, SUCCESS}, + {0x0000000000000000, 0x0000000000000000, SUCCESS}, + {0xf000000000000000, 0x000000000000000f, SUCCESS}, + }; + + int test() + { + glm::uint32 count = sizeof(Data64) / sizeof(typeU64); + + for(glm::uint32 i = 0; i < count; ++i) + { + glm::uint64 Return = glm::bitRevert( + Data64[i].Value); + + bool Compare = Data64[i].Return == Return; + + if(Data64[i].Result == SUCCESS && Compare) + continue; + else if(Data64[i].Result == FAIL && !Compare) + continue; + + std::cout << "glm::extractfield test fail on test " << i << std::endl; + return 1; + } + + return 0; + } +}//bitRevert + +int main() +{ + int Error = 0; + Error += ::extractField::test(); + Error += ::bitRevert::test(); + return Error; +} From 3c2882439f1d3668082a25b3cd694db8244fd7a2 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 11 Oct 2011 19:15:41 +0100 Subject: [PATCH 2/3] Added nlz, improved int log2, optimized findMSB with intrinsics --- glm/core/func_integer.inl | 32 +++++++++ glm/gtx/integer.hpp | 18 +++-- glm/gtx/integer.inl | 58 +++++++++++++-- test/gtx/gtx_integer.cpp | 148 ++++++++++---------------------------- 4 files changed, 138 insertions(+), 118 deletions(-) diff --git a/glm/core/func_integer.inl b/glm/core/func_integer.inl index fb91defc..31f9684f 100644 --- a/glm/core/func_integer.inl +++ b/glm/core/func_integer.inl @@ -26,6 +26,11 @@ /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// +#if(GLM_COMPILER & GLM_COMPILER_VC) +#include +#pragma intrinsic(_BitScanReverse) +#endif + namespace glm { // uaddCarry @@ -550,6 +555,32 @@ namespace glm } // findMSB +#if(GLM_COMPILER & GLM_COMPILER_VC) + + template + 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 + GLM_FUNC_QUALIFIER int findMSB + ( + genIUType const & Value + ) + { + return __builtin_clz(x); + } + +#else + template 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 GLM_FUNC_QUALIFIER detail::tvec2 findMSB diff --git a/glm/gtx/integer.hpp b/glm/gtx/integer.hpp index 5dde37e5..9369bd43 100644 --- a/glm/gtx/integer.hpp +++ b/glm/gtx/integer.hpp @@ -58,10 +58,14 @@ namespace glm //! From GLM_GTX_integer extension. int sqrt(int x); - //! Returns the log2 of 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); @@ -72,21 +76,25 @@ namespace glm genType factorial(genType const & x); //! 32bit signed integer. - //! From GLM_GTX_unsigned_int extension. + //! From GLM_GTX_integer extension. typedef signed int sint; //! Returns x raised to the y power. - //! From GLM_GTX_unsigned_int extension. + //! From GLM_GTX_integer extension. uint pow(uint x, uint y); //! Returns the positive square root of x. - //! From GLM_GTX_unsigned_int extension. + //! 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_unsigned_int extension. + //! 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 diff --git a/glm/gtx/integer.inl b/glm/gtx/integer.inl index 113cb3cd..6bcaaf80 100644 --- a/glm/gtx/integer.inl +++ b/glm/gtx/integer.inl @@ -54,10 +54,18 @@ namespace detail return(x & 0x0000003f); } }//namespace detail -/* -// Henry Gordon Dietz: http://aggregate.org/MAGIC/ + GLM_FUNC_QUALIFIER unsigned int log2(unsigned int x) { + return unsigned(32) - nlz(x - 1u); + //if(x <= 1) + // return 0; + //return unsigned(32) - findLSB(x) - 1u; + + +/* + // Henry Gordon Dietz: http://aggregate.org/MAGIC/ + register int y = (x & (x - 1)); y |= -y; @@ -69,10 +77,11 @@ GLM_FUNC_QUALIFIER unsigned int log2(unsigned int x) x |= (x >> 16); return detail::ones32(x) - 1 - y; -} */ +} + // Henry Gordon Dietz: http://aggregate.org/MAGIC/ -unsigned int log2(unsigned int x) +unsigned int floor_log2(unsigned int x) { x |= (x >> 1); x |= (x >> 2); @@ -159,4 +168,45 @@ 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 32u - 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 diff --git a/test/gtx/gtx_integer.cpp b/test/gtx/gtx_integer.cpp index 13c9178b..08350b52 100644 --- a/test/gtx/gtx_integer.cpp +++ b/test/gtx/gtx_integer.cpp @@ -1,136 +1,66 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// // OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net) /////////////////////////////////////////////////////////////////////////////////////////////////// -// Created : 2010-09-16 -// Updated : 2010-09-16 +// Created : 2011-10-11 +// Updated : 2011-10-11 // Licence : This source is under MIT licence -// File : test/gtx/bit.cpp +// File : test/gtx/gtx_integer.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// #include -#include -#include +#include +#include #include -enum result +int test_floor_log2() { - SUCCESS, - FAIL, - ASSERT, - STATIC_ASSERT -}; + int Error = 0; -namespace extractField -{ - template - struct type + for(std::size_t i = 1; i < 1000000; ++i) { - genType Value; - sizeType BitFirst; - sizeType BitCount; - genType Return; - result Result; - }; + 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 - typedef type typeU64; + Error += A == B ? 0 : 1; + assert(!Error); + } - typeU64 const Data64[] = - { - {0xffffffffffffffff, 8, 0, 0x0000000000000000, SUCCESS}, - {0x0000000000000000, 0,64, 0x0000000000000000, SUCCESS}, - {0xffffffffffffffff, 0,64, 0xffffffffffffffff, SUCCESS}, - {0x0f0f0f0f0f0f0f0f, 0,64, 0x0f0f0f0f0f0f0f0f, SUCCESS}, - {0x0000000000000000, 8, 0, 0x0000000000000000, SUCCESS}, - {0x8000000000000000,63, 1, 0x0000000000000001, SUCCESS}, - {0x7fffffffffffffff,63, 1, 0x0000000000000000, SUCCESS}, - {0x0000000000000300, 8, 8, 0x0000000000000003, SUCCESS}, - {0x000000000000ff00, 8, 8, 0x00000000000000ff, SUCCESS}, - {0xfffffffffffffff0, 0, 5, 0x0000000000000010, SUCCESS}, - {0x00000000000000ff, 1, 3, 0x0000000000000007, SUCCESS}, - {0x00000000000000ff, 0, 3, 0x0000000000000007, SUCCESS}, - {0x0000000000000000, 0, 2, 0x0000000000000000, SUCCESS}, - {0xffffffffffffffff, 0, 8, 0x00000000000000ff, SUCCESS}, - {0xffffffff00000000,32,32, 0x00000000ffffffff, SUCCESS}, - {0xfffffffffffffff0, 0, 8, 0x0000000000000000, FAIL}, - {0xffffffffffffffff,32,32, 0x0000000000000000, FAIL}, - //{0xffffffffffffffff,64, 1, 0x0000000000000000, ASSERT}, // Throw an assert - //{0xffffffffffffffff, 0,65, 0x0000000000000000, ASSERT}, // Throw an assert - //{0xffffffffffffffff,33,32, 0x0000000000000000, ASSERT}, // Throw an assert - }; + return Error; +} - int test() +int test_log2() +{ + int Error = 0; + + for(std::size_t i = 1; i < 1000000; ++i) { - glm::uint32 count = sizeof(Data64) / sizeof(typeU64); - - for(glm::uint32 i = 0; i < count; ++i) - { - glm::uint64 Return = glm::extractField( - Data64[i].Value, - Data64[i].BitFirst, - Data64[i].BitCount); - - bool Compare = Data64[i].Return == Return; - - if(Data64[i].Result == SUCCESS && Compare) - continue; - else if(Data64[i].Result == FAIL && !Compare) - continue; - - std::cout << "glm::extractfield test fail on test " << i << std::endl; - return 1; - } - - return 0; + 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); } -}//extractField -namespace bitRevert -{ - template - struct type - { - genType Value; - genType Return; - result Result; - }; + return Error; +} - typedef type typeU64; +int test_nlz() +{ + int Error = 0; - typeU64 const Data64[] = - { - {0xffffffffffffffff, 0xffffffffffffffff, SUCCESS}, - {0x0000000000000000, 0x0000000000000000, SUCCESS}, - {0xf000000000000000, 0x000000000000000f, SUCCESS}, - }; + for(std::size_t i = 1; i < 33; ++i) + printf("%d, %d\n", glm::nlz(i), 31 - glm::findMSB(i)); - int test() - { - glm::uint32 count = sizeof(Data64) / sizeof(typeU64); - - for(glm::uint32 i = 0; i < count; ++i) - { - glm::uint64 Return = glm::bitRevert( - Data64[i].Value); - - bool Compare = Data64[i].Return == Return; - - if(Data64[i].Result == SUCCESS && Compare) - continue; - else if(Data64[i].Result == FAIL && !Compare) - continue; - - std::cout << "glm::extractfield test fail on test " << i << std::endl; - return 1; - } - - return 0; - } -}//bitRevert + return Error; +} int main() { int Error = 0; - Error += ::extractField::test(); - Error += ::bitRevert::test(); + + Error += test_nlz(); + Error += test_floor_log2(); + Error += test_log2(); + return Error; } From 8864136e879337a21189a68ecf8d52d500120368 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 11 Oct 2011 20:05:08 +0100 Subject: [PATCH 3/3] Fixed log2 --- glm/gtx/integer.inl | 33 ++++++++++++--------------------- test/gtx/gtx_integer.cpp | 4 ++-- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/glm/gtx/integer.inl b/glm/gtx/integer.inl index 6bcaaf80..8c883728 100644 --- a/glm/gtx/integer.inl +++ b/glm/gtx/integer.inl @@ -55,31 +55,22 @@ namespace detail } }//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); - //if(x <= 1) - // return 0; - //return unsigned(32) - findLSB(x) - 1u; - - -/* - // Henry Gordon Dietz: http://aggregate.org/MAGIC/ - - register int y = (x & (x - 1)); - - y |= -y; - y >>= (WORDBITS - 1); - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - - return detail::ones32(x) - 1 - y; -*/ } +#endif + // Henry Gordon Dietz: http://aggregate.org/MAGIC/ unsigned int floor_log2(unsigned int x) { @@ -172,7 +163,7 @@ GLM_FUNC_QUALIFIER uint mod(uint x, uint y) GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) { - return 32u - findMSB(x); + return 31u - findMSB(x); } #else diff --git a/test/gtx/gtx_integer.cpp b/test/gtx/gtx_integer.cpp index 08350b52..a3429387 100644 --- a/test/gtx/gtx_integer.cpp +++ b/test/gtx/gtx_integer.cpp @@ -38,7 +38,7 @@ int test_log2() double B = glm::log2(double(i)); Error += glm::equalEpsilon(double(A), B, 1.0) ? 0 : 1; - assert(!Error); + //assert(!Error); } return Error; @@ -49,7 +49,7 @@ int test_nlz() int Error = 0; for(std::size_t i = 1; i < 33; ++i) - printf("%d, %d\n", glm::nlz(i), 31 - glm::findMSB(i)); + printf("%d, %d\n", glm::nlz(i), 31u - glm::findMSB(i)); return Error; }