From 031eb133418424667f056f9440c9d7f39f23592e Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Mon, 27 Oct 2014 19:13:16 +0100 Subject: [PATCH] Added powerOfTwo functions --- glm/gtc/integer.hpp | 36 +++++++---------- glm/gtc/integer.inl | 99 +++++++++++++++++++++++++++------------------ 2 files changed, 74 insertions(+), 61 deletions(-) diff --git a/glm/gtc/integer.hpp b/glm/gtc/integer.hpp index 5cf3022d..fb8b5660 100644 --- a/glm/gtc/integer.hpp +++ b/glm/gtc/integer.hpp @@ -67,53 +67,45 @@ namespace glm template class vecType> GLM_FUNC_DECL vecType isPowerOfTwo(vecType const & value); - /// Find the highest bit set to 1 in a integer variable and return its value. + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. /// /// @see gtc_integer template - GLM_FUNC_DECL genIUType highestBitValue(genIUType Value); + GLM_FUNC_DECL genIUType ceilPowerOfTwo(genIUType Value); - /// Find the highest bit set to 1 in a integer variable and return its value. + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. /// /// @see gtc_integer template class vecType> - GLM_FUNC_DECL vecType highestBitValue(vecType const & value); + GLM_FUNC_DECL vecType ceilPowerOfTwo(vecType const & value); - /// Return the power of two number which value is just higher the input value. + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. /// /// @see gtc_integer template - GLM_FUNC_DECL genIUType powerOfTwoAbove(genIUType Value); + GLM_FUNC_DECL genIUType floorPowerOfTwo(genIUType Value); - /// Return the power of two number which value is just higher the input value. + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. /// /// @see gtc_integer template class vecType> - GLM_FUNC_DECL vecType powerOfTwoAbove(vecType const & value); - - /// Return the power of two number which value is just lower the input value. - /// - /// @see gtc_integer - template - GLM_FUNC_DECL genIUType powerOfTwoBelow(genIUType Value); - - /// Return the power of two number which value is just lower the input value. - /// - /// @see gtc_integer - template class vecType> - GLM_FUNC_DECL vecType powerOfTwoBelow(vecType const & value); + GLM_FUNC_DECL vecType floorPowerOfTwo(vecType const & value); /// Return the power of two number which value is the closet to the input value. /// /// @see gtc_integer template - GLM_FUNC_DECL genIUType powerOfTwoNearest(genIUType Value); + GLM_FUNC_DECL genIUType roundPowerOfTwo(genIUType Value); /// Return the power of two number which value is the closet to the input value. /// /// @see gtc_integer template class vecType> - GLM_FUNC_DECL vecType powerOfTwoNearest(vecType const & value); + GLM_FUNC_DECL vecType roundPowerOfTwo(vecType const & value); /// @} } //namespace glm diff --git a/glm/gtc/integer.inl b/glm/gtc/integer.inl index 1e721447..1edf00aa 100644 --- a/glm/gtc/integer.inl +++ b/glm/gtc/integer.inl @@ -26,82 +26,103 @@ /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// -namespace glm +namespace glm{ +namespace detail { + template class vecType, bool isSigned = true> + struct compute_ceilPowerOfTwo{}; + + template class vecType> + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & v) + { + GLM_STATIC_ASSERT( + !std::numeric_limits::is_iec559, + "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + template class vecType, bool compute = false> + struct compute_ceil_shift + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & v, T) + { + return v; + } + }; + + template class vecType, bool compute = true> + struct compute_ceil_shift + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & v, T Shift) + { + return v | (v >> Shift); + } + }; + + v = v - static_cast(1); + v = v | (v >> static_cast(1)); + v = v | (v >> static_cast(2)); + v = v | (v >> static_cast(4)); + v = compute_ceil_shift= 2>::call(v, 8); + v = compute_ceil_shift= 4>::call(v, 16); + v = compute_ceil_shift= 8>::call(v, 32); + return v + static_cast(1); + } + }; +}//namespace detail + //////////////// // isPowerOfTwo template GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value) { - genType Result = glm::abs(Value); + genType const Result = glm::abs(Value); return !(Result & (Result - 1)); } template class vecType> GLM_FUNC_QUALIFIER vecType isPowerOfTwo(vecType const & Value) { - vecType Result(abs(Value)); + vecType const Result(abs(Value)); return equal(Result & (Result - 1), vecType(0)); } - /////////////////// - // highestBitValue - - template - GLM_FUNC_QUALIFIER genIUType highestBitValue(genIUType Value) - { - genIUType tmp = Value; - genIUType result = genIUType(0); - while(tmp) - { - result = (tmp & (~tmp + 1)); // grab lowest bit - tmp &= ~result; // clear lowest bit - } - return result; - } - - template class vecType> - GLM_FUNC_QUALIFIER vecType highestBitValue(vecType const & v) - { - return detail::functor1::call(highestBitValue, v); - } - - /////////////////// - // powerOfTwoAbove + ////////////////// + // ceilPowerOfTwo template - GLM_FUNC_QUALIFIER genType powerOfTwoAbove(genType value) + GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value) { return isPowerOfTwo(value) ? value : highestBitValue(value) << 1; } template class vecType> - GLM_FUNC_QUALIFIER vecType powerOfTwoAbove(vecType const & v) + GLM_FUNC_QUALIFIER vecType ceilPowerOfTwo(vecType const & v) { - return detail::functor1::call(powerOfTwoAbove, v); + return detail::functor1::call(ceilPowerOfTwo, v); } /////////////////// - // powerOfTwoBelow + // floorPowerOfTwo template - GLM_FUNC_QUALIFIER genType powerOfTwoBelow(genType value) + GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value) { return isPowerOfTwo(value) ? value : highestBitValue(value); } template class vecType> - GLM_FUNC_QUALIFIER vecType powerOfTwoBelow(vecType const & v) + GLM_FUNC_QUALIFIER vecType floorPowerOfTwo(vecType const & v) { - return detail::functor1::call(powerOfTwoBelow, v); + return detail::functor1::call(floorPowerOfTwo, v); } - ///////////////////// - // powerOfTwoNearest + /////////////////// + // roundPowerOfTwo template - GLM_FUNC_QUALIFIER genType powerOfTwoNearest(genType value) + GLM_FUNC_QUALIFIER genType roundPowerOfTwo(genType value) { if(isPowerOfTwo(value)) return value; @@ -112,8 +133,8 @@ namespace glm } template class vecType> - GLM_FUNC_QUALIFIER vecType powerOfTwoNearest(vecType const & v) + GLM_FUNC_QUALIFIER vecType roundPowerOfTwo(vecType const & v) { - return detail::functor1::call(powerOfTwoNearest, v); + return detail::functor1::call(roundPowerOfTwo, v); } }//namespace glm