mirror of
https://github.com/g-truc/glm.git
synced 2024-11-26 10:14:35 +00:00
Fixed findMSB generic path
This commit is contained in:
parent
a2ba0ea86f
commit
8a7d6080d1
@ -522,39 +522,9 @@ namespace glm
|
||||
}
|
||||
|
||||
// findMSB
|
||||
/*
|
||||
#if((GLM_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_VC))
|
||||
|
||||
template <typename genIUType>
|
||||
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 <typename genIUType>
|
||||
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 <typename genIUType>
|
||||
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 <typename genIUType>
|
||||
GLM_FUNC_QUALIFIER int findMSB
|
||||
(
|
||||
genIUType const & Value
|
||||
)
|
||||
{
|
||||
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::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 <typename genIUType>
|
||||
GLM_FUNC_QUALIFIER int findMSB
|
||||
(
|
||||
genIUType const & Value
|
||||
)
|
||||
{
|
||||
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::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 <typename T>
|
||||
GLM_FUNC_QUALIFIER detail::tvec2<int> findMSB
|
||||
|
@ -125,6 +125,87 @@ namespace bitfieldReverse
|
||||
}
|
||||
}//bitRevert
|
||||
|
||||
namespace findMSB
|
||||
{
|
||||
template <typename genType>
|
||||
struct type
|
||||
{
|
||||
genType Value;
|
||||
genType Return;
|
||||
};
|
||||
|
||||
type<int> 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<int>); ++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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user