From 09ee14ad4c0d80479862c8396f23e36f1ebc28fc Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Tue, 11 Oct 2011 15:31:16 +0100 Subject: [PATCH] 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; +}