Added log2 for int types

This commit is contained in:
Christophe Riccio 2011-10-13 18:36:44 +01:00
parent c4af12634b
commit 16ef34f9c5
5 changed files with 124 additions and 17 deletions

View File

@ -345,6 +345,91 @@ namespace detail
typedef float float32;
typedef double float64;
//////////////////
// float_or_int_trait
struct float_or_int_value
{
enum
{
ERROR,
FLOAT,
INT
};
};
template <typename T>
struct float_or_int_trait
{
enum{ID = float_or_int_value::ERROR};
};
template <>
struct float_or_int_trait<int8>
{
enum{ID = float_or_int_value::INT};
};
template <>
struct float_or_int_trait<int16>
{
enum{ID = float_or_int_value::INT};
};
template <>
struct float_or_int_trait<int32>
{
enum{ID = float_or_int_value::INT};
};
template <>
struct float_or_int_trait<int64>
{
enum{ID = float_or_int_value::INT};
};
template <>
struct float_or_int_trait<uint8>
{
enum{ID = float_or_int_value::INT};
};
template <>
struct float_or_int_trait<uint16>
{
enum{ID = float_or_int_value::INT};
};
template <>
struct float_or_int_trait<uint32>
{
enum{ID = float_or_int_value::INT};
};
template <>
struct float_or_int_trait<uint64>
{
enum{ID = float_or_int_value::INT};
};
template <>
struct float_or_int_trait<float16>
{
enum{ID = float_or_int_value::FLOAT};
};
template <>
struct float_or_int_trait<float32>
{
enum{ID = float_or_int_value::FLOAT};
};
template <>
struct float_or_int_trait<float64>
{
enum{ID = float_or_int_value::FLOAT};
};
}//namespace detail
}//namespace glm

View File

@ -224,6 +224,30 @@ namespace glm
exp2(x.w));
}
namespace detail
{
template <int PATH = float_or_int_value::ERROR>
struct compute_log2
{
template <typename T>
T operator() (T const & Value) const
{
static_assert(0, "'log2' parameter has an invalid template parameter type");
return Value;
}
};
template <>
struct compute_log2<float_or_int_value::FLOAT>
{
template <typename T>
T operator() (T const & Value) const
{
return ::std::log(Value) / T(0.69314718055994530941723212145818);
}
};
}//namespace detail
// log2, ln2 = 0.69314718055994530941723212145818f
template <typename genType>
GLM_FUNC_QUALIFIER genType log2
@ -231,9 +255,7 @@ namespace glm
genType const & x
)
{
GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'log2' only accept floating-point input");
return ::std::log(x) / genType(0.69314718055994530941723212145818);
return detail::compute_log2<detail::float_or_int_trait<genType>::ID>()(x);
}
template <typename T>

View File

@ -84,6 +84,7 @@
#include <climits>
#include <cfloat>
#include <limits>
#include <type_traits>
#include "core/setup.hpp"
#if(defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_CORE_INCLUDED_DISPLAYED))

View File

@ -60,7 +60,8 @@ namespace glm
//! 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);
template <typename genType>
genType log2(genType const & x);
//! Returns the floor log2 of x.
//! From GLM_GTX_integer extension.

View File

@ -53,23 +53,21 @@ namespace detail
x += (x >> 16);
return(x & 0x0000003f);
}
}//namespace detail
template <>
struct compute_log2<float_or_int_value::INT>
{
template <typename T>
T operator() (T const & Value) const
{
#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);
}
return Value <= T(1) ? T(0) : T(32) - nlz(Value - T(1));
#else
GLM_FUNC_QUALIFIER unsigned int log2(unsigned int x)
{
return unsigned(32) - nlz(x - 1u);
}
return T(32) - nlz(Value - T(1));
#endif
}
};
}//namespace detail
// Henry Gordon Dietz: http://aggregate.org/MAGIC/
unsigned int floor_log2(unsigned int x)