diff --git a/glm/core/func_integer.inl b/glm/core/func_integer.inl index 62d5b920..d7da1c44 100644 --- a/glm/core/func_integer.inl +++ b/glm/core/func_integer.inl @@ -522,39 +522,9 @@ namespace glm } // findMSB +/* #if((GLM_ARCH != GLM_ARCH_PURE) && (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_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC40)) - - template - GLM_FUNC_QUALIFIER int findMSB - ( - genIUType const & Value - ) - { - /** - * clz returns the number or trailing 0-bits; see - * http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Other-Builtins.html - * - * NoteBecause __builtin_clz only works for unsigned ints, this - * implementation will not work for 64-bit integers. - */ - return 31 - __builtin_clz(Value); - } - -#else - template GLM_FUNC_QUALIFIER int findMSB ( @@ -565,11 +535,61 @@ namespace glm if(Value == 0) return -1; - genIUType bit = genIUType(-1); - for(genIUType tmp = Value; tmp; tmp >>= 1, ++bit){} - return bit; + unsigned long Result(0); + _BitScanReverse(&Result, Value); + return int(Result); } -#endif//(GLM_COMPILER) + +// __builtin_clz seems to be buggy as it crasks for some values, from 0x00200000 to 80000000 +#elif((GLM_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC40)) + + template + GLM_FUNC_QUALIFIER int findMSB + ( + genIUType const & Value + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + if(Value == 0) + return -1; + + // clz returns the number or trailing 0-bits; see + // http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Other-Builtins.html + // + // NoteBecause __builtin_clz only works for unsigned ints, this + // implementation will not work for 64-bit integers. + // + return 31 - __builtin_clzl(Value); + } +#else +*/ + template + GLM_FUNC_QUALIFIER int findMSB + ( + genIUType const & Value + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + if(Value == 0 || Value == -1) + return -1; + else if(Value > 0) + { + genIUType Bit = genIUType(-1); + for(genIUType tmp = Value; tmp > 0; tmp >>= 1, ++Bit){} + return Bit; + } + else //if(Value < 0) + { + int const BitCount(sizeof(genIUType) * 8); + int MostSignificantBit(-1); + for(int BitIndex(0); BitIndex < BitCount; ++BitIndex) + MostSignificantBit = (Value & (1 << BitIndex)) ? MostSignificantBit : BitIndex; + assert(MostSignificantBit >= 0); + return MostSignificantBit; + } + } +//#endif//(GLM_COMPILER) template GLM_FUNC_QUALIFIER detail::tvec2 findMSB diff --git a/test/core/core_func_integer.cpp b/test/core/core_func_integer.cpp index e931e6ae..9605ffaf 100644 --- a/test/core/core_func_integer.cpp +++ b/test/core/core_func_integer.cpp @@ -125,6 +125,87 @@ namespace bitfieldReverse } }//bitRevert +namespace findMSB +{ + template + struct type + { + genType Value; + genType Return; + }; + + type const DataI32[] = + { + {0x00000000, -1}, + {0x00000001, 0}, + {0x00000002, 1}, + {0x00000003, 1}, + {0x00000004, 2}, + {0x00000005, 2}, + {0x00000007, 2}, + {0x00000008, 3}, + {0x00000010, 4}, + {0x00000020, 5}, + {0x00000040, 6}, + {0x00000080, 7}, + {0x00000100, 8}, + {0x00000200, 9}, + {0x00000400, 10}, + {0x00000800, 11}, + {0x00001000, 12}, + {0x00002000, 13}, + {0x00004000, 14}, + {0x00008000, 15}, + {0x00010000, 16}, + {0x00020000, 17}, + {0x00040000, 18}, + {0x00080000, 19}, + {0x00100000, 20}, + {0x00200000, 21}, + {0x00400000, 22}, + {0x00800000, 23}, + {0x01000000, 24}, + {0x02000000, 25}, + {0x04000000, 26}, + {0x08000000, 27}, + {0x10000000, 28}, + {0x20000000, 29}, + {0x40000000, 30}, + {0x80000000, 30}, + {0xffffffff, -1}, + {0xfffffffe, 0}, + {0xfffffffd, 1}, + {0xfffffffc, 1}, + {0xfffffffb, 2}, + {0xfffffffa, 2}, + {0xfffffff0, 3} + }; + + int test() + { + int Error(0); + + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(type); ++i) + { + int Result = glm::findMSB(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + assert(!Error); + } + + return Error; + } +}//findMSB + +namespace findLSB +{ + int test() + { + int Error(0); + + return Error; + } +}//findLSB + int main() { int Error = 0; @@ -133,6 +214,8 @@ int main() Error += ::bitfieldExtract::test(); Error += ::bitfieldReverse::test(); + Error += ::findMSB::test(); + Error += ::findLSB::test(); return Error; }