Browse Source

Added initial work for integer vector and scalar functions

Christophe Riccio 6 years ago
parent
commit
07c6d56b5f

+ 78 - 0
glm/ext/scalar_integer.hpp

@@ -0,0 +1,78 @@
+/// @ref ext_scalar_integer
+/// @file glm/ext/scalar_integer.hpp
+///
+/// @see core (dependence)
+/// @see ext_vector_integer (dependence)
+///
+/// @defgroup gtc_round GLM_EXT_scalar_integer
+/// @ingroup ext
+///
+/// Include <glm/ext/scalar_integer.hpp> to use the features of this extension.
+
+#pragma once
+
+// Dependencies
+#include "../detail/setup.hpp"
+#include "../detail/qualifier.hpp"
+#include "../detail/_vectorize.hpp"
+#include "../vector_relational.hpp"
+#include "../common.hpp"
+#include <limits>
+
+#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED)
+#	pragma message("GLM: GLM_EXT_scalar_integer extension included")
+#endif
+
+namespace glm
+{
+	/// @addtogroup ext_scalar_integer
+	/// @{
+
+	/// Return true if the value is a power of two number.
+	template<typename genIUType>
+	GLM_FUNC_DECL bool isPowerOfTwo(genIUType v);
+
+	/// Return the power of two number which value is just higher the input value,
+	/// round up to a power of two.
+	template<typename genIUType>
+	GLM_FUNC_DECL genIUType nextPowerOfTwo(genIUType v);
+
+	/// Return the power of two number which value is just lower the input value,
+	/// round down to a power of two.
+	///
+	/// @see gtc_round
+	template<typename genIUType>
+	GLM_FUNC_DECL genIUType prevPowerOfTwo(genIUType v);
+
+	/// Return true if the 'Value' is a multiple of 'Multiple'.
+	///
+	/// @see gtc_round
+	template<typename genIUType>
+	GLM_FUNC_DECL bool isMultiple(genIUType v, genIUType Multiple);
+
+	/// Higher multiple number of Source.
+	///
+	/// @tparam genType Floating-point or integer scalar or vector types.
+	///
+	/// @param v Source value to which is applied the function
+	/// @param Multiple Must be a null or positive value
+	///
+	/// @see gtc_round
+	template<typename genIUType>
+	GLM_FUNC_DECL genIUType nextMultiple(genIUType v, genIUType Multiple);
+
+	/// Lower multiple number of Source.
+	///
+	/// @tparam genType Floating-point or integer scalar or vector types.
+	///
+	/// @param v Source value to which is applied the function
+	/// @param Multiple Must be a null or positive value
+	///
+	/// @see gtc_round
+	template<typename genIUType>
+	GLM_FUNC_DECL genIUType prevMultiple(genIUType v, genIUType Multiple);
+
+	/// @}
+} //namespace glm
+
+#include "scalar_integer.inl"

+ 194 - 0
glm/ext/scalar_integer.inl

@@ -0,0 +1,194 @@
+#include "../integer.hpp"
+
+namespace glm{
+namespace detail
+{
+	template<length_t L, typename T, qualifier Q, bool compute = false>
+	struct compute_ceilShift
+	{
+		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T)
+		{
+			return v;
+		}
+	};
+
+	template<length_t L, typename T, qualifier Q>
+	struct compute_ceilShift<L, T, Q, true>
+	{
+		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T Shift)
+		{
+			return v | (v >> Shift);
+		}
+	};
+
+	template<length_t L, typename T, qualifier Q, bool isSigned = true>
+	struct compute_ceilPowerOfTwo
+	{
+		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
+		{
+			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
+
+			vec<L, T, Q> const Sign(sign(x));
+
+			vec<L, T, Q> v(abs(x));
+
+			v = v - static_cast<T>(1);
+			v = v | (v >> static_cast<T>(1));
+			v = v | (v >> static_cast<T>(2));
+			v = v | (v >> static_cast<T>(4));
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
+			return (v + static_cast<T>(1)) * Sign;
+		}
+	};
+
+	template<length_t L, typename T, qualifier Q>
+	struct compute_ceilPowerOfTwo<L, T, Q, false>
+	{
+		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
+		{
+			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
+
+			vec<L, T, Q> v(x);
+
+			v = v - static_cast<T>(1);
+			v = v | (v >> static_cast<T>(1));
+			v = v | (v >> static_cast<T>(2));
+			v = v | (v >> static_cast<T>(4));
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
+			return v + static_cast<T>(1);
+		}
+	};
+
+	template<bool is_float, bool is_signed>
+	struct compute_ceilMultiple{};
+
+	template<>
+	struct compute_ceilMultiple<true, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source > genType(0))
+				return Source + (Multiple - std::fmod(Source, Multiple));
+			else
+				return Source + std::fmod(-Source, Multiple);
+		}
+	};
+
+	template<>
+	struct compute_ceilMultiple<false, false>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			genType Tmp = Source - genType(1);
+			return Tmp + (Multiple - (Tmp % Multiple));
+		}
+	};
+
+	template<>
+	struct compute_ceilMultiple<false, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source > genType(0))
+			{
+				genType Tmp = Source - genType(1);
+				return Tmp + (Multiple - (Tmp % Multiple));
+			}
+			else
+				return Source + (-Source % Multiple);
+		}
+	};
+
+	template<bool is_float, bool is_signed>
+	struct compute_floorMultiple{};
+
+	template<>
+	struct compute_floorMultiple<true, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - std::fmod(Source, Multiple);
+			else
+				return Source - std::fmod(Source, Multiple) - Multiple;
+		}
+	};
+
+	template<>
+	struct compute_floorMultiple<false, false>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - Source % Multiple;
+			else
+			{
+				genType Tmp = Source + genType(1);
+				return Tmp - Tmp % Multiple - Multiple;
+			}
+		}
+	};
+
+	template<>
+	struct compute_floorMultiple<false, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - Source % Multiple;
+			else
+			{
+				genType Tmp = Source + genType(1);
+				return Tmp - Tmp % Multiple - Multiple;
+			}
+		}
+	};
+}//namespace detail
+
+	template<typename genIUType>
+	GLM_FUNC_QUALIFIER bool isPowerOfTwo(genIUType Value)
+	{
+		genIUType const Result = glm::abs(Value);
+		return !(Result & (Result - 1));
+	}
+
+	template<typename genIUType>
+	GLM_FUNC_QUALIFIER genIUType nextPowerOfTwo(genIUType value)
+	{
+		return detail::compute_ceilPowerOfTwo<1, genIUType, defaultp, std::numeric_limits<genIUType>::is_signed>::call(vec<1, genIUType, defaultp>(value)).x;
+	}
+
+	template<typename genIUType>
+	GLM_FUNC_QUALIFIER genIUType prevPowerOfTwo(genIUType value)
+	{
+		return isPowerOfTwo(value) ? value : static_cast<genIUType>(1) << findMSB(value);
+	}
+
+	template<typename genIUType>
+	GLM_FUNC_QUALIFIER bool isMultiple(genIUType Value, genIUType Multiple)
+	{
+		return isMultiple(vec<1, genIUType>(Value), vec<1, genIUType>(Multiple)).x;
+	}
+
+	template<typename genIUType>
+	GLM_FUNC_QUALIFIER genIUType nextMultiple(genIUType Source, genIUType Multiple)
+	{
+		return detail::compute_ceilMultiple<std::numeric_limits<genIUType>::is_iec559, std::numeric_limits<genIUType>::is_signed>::call(Source, Multiple);
+	}
+
+	template<typename genIUType>
+	GLM_FUNC_QUALIFIER genIUType prevMultiple(genIUType Source, genIUType Multiple)
+	{
+		return detail::compute_floorMultiple<std::numeric_limits<genIUType>::is_iec559, std::numeric_limits<genIUType>::is_signed>::call(Source, Multiple);
+	}
+}//namespace glm

+ 120 - 0
glm/ext/vector_integer.hpp

@@ -0,0 +1,120 @@
+/// @ref ext_vector_integer
+/// @file glm/ext/vector_integer.hpp
+///
+/// @see core (dependence)
+/// @see ext_vector_integer (dependence)
+///
+/// @defgroup gtc_round GLM_EXT_vector_integer
+/// @ingroup ext
+///
+/// Include <glm/ext/vector_integer.hpp> to use the features of this extension.
+
+#pragma once
+
+// Dependencies
+#include "../detail/setup.hpp"
+#include "../detail/qualifier.hpp"
+#include "../detail/_vectorize.hpp"
+#include "../vector_relational.hpp"
+#include "../common.hpp"
+#include <limits>
+
+#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED)
+#	pragma message("GLM: GLM_EXT_vector_integer extension included")
+#endif
+
+namespace glm
+{
+	/// @addtogroup ext_vector_integer
+	/// @{
+
+	/// Return true if the value is a power of two number.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, bool, Q> isPowerOfTwo(vec<L, T, Q> const& v);
+
+	/// Return the power of two number which value is just higher the input value,
+	/// round up to a power of two.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, T, Q> nextPowerOfTwo(vec<L, T, Q> const& v);
+
+	/// Return the power of two number which value is just lower the input value,
+	/// round down to a power of two.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, T, Q> prevPowerOfTwo(vec<L, T, Q> const& v);
+
+	/// Return true if the 'Value' is a multiple of 'Multiple'.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, bool, Q> isMultiple(vec<L, T, Q> const& v, T Multiple);
+
+	/// Return true if the 'Value' is a multiple of 'Multiple'.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, bool, Q> isMultiple(vec<L, T, Q> const& v, vec<L, T, Q> const& Multiple);
+
+	/// Higher multiple number of Source.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	///
+	/// @param v Source values to which is applied the function
+	/// @param Multiple Must be a null or positive value
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, T, Q> nextMultiple(vec<L, T, Q> const& v, T Multiple);
+
+	/// Higher multiple number of Source.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	///
+	/// @param v Source values to which is applied the function
+	/// @param Multiple Must be a null or positive value
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, T, Q> nextMultiple(vec<L, T, Q> const& v, vec<L, T, Q> const& Multiple);
+
+	/// Lower multiple number of Source.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	///
+	/// @param v Source values to which is applied the function
+	/// @param Multiple Must be a null or positive value
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, T, Q> prevMultiple(vec<L, T, Q> const& v, T const& Multiple);
+
+	/// Lower multiple number of Source.
+	///
+	/// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector
+	/// @tparam T Floating-point or integer scalar types
+	/// @tparam Q Value from qualifier enum
+	///
+	/// @param v Source values to which is applied the function
+	/// @param Multiple Must be a null or positive value
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_DECL vec<L, T, Q> prevMultiple(vec<L, T, Q> const& v, vec<L, T, Q> const& Multiple);
+
+	/// @}
+} //namespace glm
+
+#include "vector_integer.inl"

+ 343 - 0
glm/ext/vector_integer.inl

@@ -0,0 +1,343 @@
+/// @ref gtc_round
+
+#include "../integer.hpp"
+
+namespace glm{
+namespace detail
+{
+	template<length_t L, typename T, qualifier Q, bool compute = false>
+	struct compute_ceilShift
+	{
+		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T)
+		{
+			return v;
+		}
+	};
+
+	template<length_t L, typename T, qualifier Q>
+	struct compute_ceilShift<L, T, Q, true>
+	{
+		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T Shift)
+		{
+			return v | (v >> Shift);
+		}
+	};
+
+	template<length_t L, typename T, qualifier Q, bool isSigned = true>
+	struct compute_ceilPowerOfTwo
+	{
+		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
+		{
+			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
+
+			vec<L, T, Q> const Sign(sign(x));
+
+			vec<L, T, Q> v(abs(x));
+
+			v = v - static_cast<T>(1);
+			v = v | (v >> static_cast<T>(1));
+			v = v | (v >> static_cast<T>(2));
+			v = v | (v >> static_cast<T>(4));
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
+			return (v + static_cast<T>(1)) * Sign;
+		}
+	};
+
+	template<length_t L, typename T, qualifier Q>
+	struct compute_ceilPowerOfTwo<L, T, Q, false>
+	{
+		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
+		{
+			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
+
+			vec<L, T, Q> v(x);
+
+			v = v - static_cast<T>(1);
+			v = v | (v >> static_cast<T>(1));
+			v = v | (v >> static_cast<T>(2));
+			v = v | (v >> static_cast<T>(4));
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
+			v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
+			return v + static_cast<T>(1);
+		}
+	};
+
+	template<bool is_float, bool is_signed>
+	struct compute_ceilMultiple{};
+
+	template<>
+	struct compute_ceilMultiple<true, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source > genType(0))
+				return Source + (Multiple - std::fmod(Source, Multiple));
+			else
+				return Source + std::fmod(-Source, Multiple);
+		}
+	};
+
+	template<>
+	struct compute_ceilMultiple<false, false>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			genType Tmp = Source - genType(1);
+			return Tmp + (Multiple - (Tmp % Multiple));
+		}
+	};
+
+	template<>
+	struct compute_ceilMultiple<false, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source > genType(0))
+			{
+				genType Tmp = Source - genType(1);
+				return Tmp + (Multiple - (Tmp % Multiple));
+			}
+			else
+				return Source + (-Source % Multiple);
+		}
+	};
+
+	template<bool is_float, bool is_signed>
+	struct compute_floorMultiple{};
+
+	template<>
+	struct compute_floorMultiple<true, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - std::fmod(Source, Multiple);
+			else
+				return Source - std::fmod(Source, Multiple) - Multiple;
+		}
+	};
+
+	template<>
+	struct compute_floorMultiple<false, false>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - Source % Multiple;
+			else
+			{
+				genType Tmp = Source + genType(1);
+				return Tmp - Tmp % Multiple - Multiple;
+			}
+		}
+	};
+
+	template<>
+	struct compute_floorMultiple<false, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - Source % Multiple;
+			else
+			{
+				genType Tmp = Source + genType(1);
+				return Tmp - Tmp % Multiple - Multiple;
+			}
+		}
+	};
+
+	template<bool is_float, bool is_signed>
+	struct compute_roundMultiple{};
+
+	template<>
+	struct compute_roundMultiple<true, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - std::fmod(Source, Multiple);
+			else
+			{
+				genType Tmp = Source + genType(1);
+				return Tmp - std::fmod(Tmp, Multiple) - Multiple;
+			}
+		}
+	};
+
+	template<>
+	struct compute_roundMultiple<false, false>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - Source % Multiple;
+			else
+			{
+				genType Tmp = Source + genType(1);
+				return Tmp - Tmp % Multiple - Multiple;
+			}
+		}
+	};
+
+	template<>
+	struct compute_roundMultiple<false, true>
+	{
+		template<typename genType>
+		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
+		{
+			if(Source >= genType(0))
+				return Source - Source % Multiple;
+			else
+			{
+				genType Tmp = Source + genType(1);
+				return Tmp - Tmp % Multiple - Multiple;
+			}
+		}
+	};
+}//namespace detail
+
+	////////////////
+	// isPowerOfTwo
+
+	template<typename genType>
+	GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value)
+	{
+		genType const Result = glm::abs(Value);
+		return !(Result & (Result - 1));
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, bool, Q> isPowerOfTwo(vec<L, T, Q> const& Value)
+	{
+		vec<L, T, Q> const Result(abs(Value));
+		return equal(Result & (Result - 1), vec<L, T, Q>(0));
+	}
+
+	//////////////////
+	// ceilPowerOfTwo
+
+	template<typename genType>
+	GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value)
+	{
+		return detail::compute_ceilPowerOfTwo<1, genType, defaultp, std::numeric_limits<genType>::is_signed>::call(vec<1, genType, defaultp>(value)).x;
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, T, Q> ceilPowerOfTwo(vec<L, T, Q> const& v)
+	{
+		return detail::compute_ceilPowerOfTwo<L, T, Q, std::numeric_limits<T>::is_signed>::call(v);
+	}
+
+	///////////////////
+	// floorPowerOfTwo
+
+	template<typename genType>
+	GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value)
+	{
+		return isPowerOfTwo(value) ? value : static_cast<genType>(1) << findMSB(value);
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, T, Q> floorPowerOfTwo(vec<L, T, Q> const& v)
+	{
+		return detail::functor1<vec, L, T, T, Q>::call(floorPowerOfTwo, v);
+	}
+
+	///////////////////
+	// roundPowerOfTwo
+
+	template<typename genIUType>
+	GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value)
+	{
+		if(isPowerOfTwo(value))
+			return value;
+
+		genIUType const prev = static_cast<genIUType>(1) << findMSB(value);
+		genIUType const next = prev << static_cast<genIUType>(1);
+		return (next - value) < (value - prev) ? next : prev;
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, T, Q> roundPowerOfTwo(vec<L, T, Q> const& v)
+	{
+		return detail::functor1<vec, L, T, T, Q>::call(roundPowerOfTwo, v);
+	}
+
+	////////////////
+	// isMultiple
+
+	template<typename genType>
+	GLM_FUNC_QUALIFIER bool isMultiple(genType Value, genType Multiple)
+	{
+		return isMultiple(vec<1, genType>(Value), vec<1, genType>(Multiple)).x;
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, bool, Q> isMultiple(vec<L, T, Q> const& Value, T Multiple)
+	{
+		return (Value % Multiple) == vec<L, T, Q>(0);
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, bool, Q> isMultiple(vec<L, T, Q> const& Value, vec<L, T, Q> const& Multiple)
+	{
+		return (Value % Multiple) == vec<L, T, Q>(0);
+	}
+
+	//////////////////////
+	// ceilMultiple
+
+	template<typename genType>
+	GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple)
+	{
+		return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, T, Q> ceilMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
+	{
+		return detail::functor2<vec, L, T, Q>::call(ceilMultiple, Source, Multiple);
+	}
+
+	//////////////////////
+	// floorMultiple
+
+	template<typename genType>
+	GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple)
+	{
+		return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, T, Q> floorMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
+	{
+		return detail::functor2<vec, L, T, Q>::call(floorMultiple, Source, Multiple);
+	}
+
+	//////////////////////
+	// roundMultiple
+
+	template<typename genType>
+	GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple)
+	{
+		return detail::compute_roundMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
+	}
+
+	template<length_t L, typename T, qualifier Q>
+	GLM_FUNC_QUALIFIER vec<L, T, Q> roundMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
+	{
+		return detail::functor2<vec, L, T, Q>::call(roundMultiple, Source, Multiple);
+	}
+}//namespace glm

+ 1 - 1
glm/gtc/round.hpp

@@ -22,7 +22,7 @@
 #include <limits>
 
 #if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED)
-#	pragma message("GLM: GLM_GTC_integer extension included")
+#	pragma message("GLM: GLM_GTC_round extension included")
 #endif
 
 namespace glm

+ 2 - 0
test/ext/CMakeLists.txt

@@ -12,6 +12,7 @@ glmCreateTestGTC(ext_scalar_common)
 glmCreateTestGTC(ext_scalar_constants)
 glmCreateTestGTC(ext_scalar_int_sized)
 glmCreateTestGTC(ext_scalar_uint_sized)
+glmCreateTestGTC(ext_scalar_integer)
 glmCreateTestGTC(ext_scalar_ulp)
 glmCreateTestGTC(ext_scalar_relational)
 glmCreateTestGTC(ext_vec1)
@@ -19,6 +20,7 @@ glmCreateTestGTC(ext_vector_bool1)
 glmCreateTestGTC(ext_vector_common)
 glmCreateTestGTC(ext_vector_iec559)
 glmCreateTestGTC(ext_vector_integer)
+glmCreateTestGTC(ext_vector_integer_sized)
 glmCreateTestGTC(ext_vector_relational)
 glmCreateTestGTC(ext_vector_ulp)
 

+ 435 - 0
test/ext/ext_scalar_integer.cpp

@@ -0,0 +1,435 @@
+#include <glm/ext/scalar_integer.hpp>
+#include <glm/ext/scalar_int_sized.hpp>
+#include <glm/ext/scalar_uint_sized.hpp>
+#include <vector>
+#include <ctime>
+#include <cstdio>
+
+namespace isPowerOfTwo
+{
+	template<typename genType>
+	struct type
+	{
+		genType		Value;
+		bool		Return;
+	};
+
+	int test_int16()
+	{
+		type<glm::int16> const Data[] =
+		{
+			{0x0001, true},
+			{0x0002, true},
+			{0x0004, true},
+			{0x0080, true},
+			{0x0000, true},
+			{0x0003, false}
+		};
+
+		int Error = 0;
+
+		for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::int16>); i < n; ++i)
+		{
+			bool Result = glm::isPowerOfTwo(Data[i].Value);
+			Error += Data[i].Return == Result ? 0 : 1;
+		}
+
+		return Error;
+	}
+
+	int test_uint16()
+	{
+		type<glm::uint16> const Data[] =
+		{
+			{0x0001, true},
+			{0x0002, true},
+			{0x0004, true},
+			{0x0000, true},
+			{0x0000, true},
+			{0x0003, false}
+		};
+
+		int Error = 0;
+
+		for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::uint16>); i < n; ++i)
+		{
+			bool Result = glm::isPowerOfTwo(Data[i].Value);
+			Error += Data[i].Return == Result ? 0 : 1;
+		}
+
+		return Error;
+	}
+
+	int test_int32()
+	{
+		type<int> const Data[] =
+		{
+			{0x00000001, true},
+			{0x00000002, true},
+			{0x00000004, true},
+			{0x0000000f, false},
+			{0x00000000, true},
+			{0x00000003, false}
+		};
+
+		int Error = 0;
+
+		for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<int>); i < n; ++i)
+		{
+			bool Result = glm::isPowerOfTwo(Data[i].Value);
+			Error += Data[i].Return == Result ? 0 : 1;
+		}
+
+		return Error;
+	}
+
+	int test_uint32()
+	{
+		type<glm::uint> const Data[] =
+		{
+			{0x00000001, true},
+			{0x00000002, true},
+			{0x00000004, true},
+			{0x80000000, true},
+			{0x00000000, true},
+			{0x00000003, false}
+		};
+
+		int Error = 0;
+
+		for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::uint>); i < n; ++i)
+		{
+			bool Result = glm::isPowerOfTwo(Data[i].Value);
+			Error += Data[i].Return == Result ? 0 : 1;
+		}
+
+		return Error;
+	}
+
+	int test()
+	{
+		int Error = 0;
+
+		Error += test_int16();
+		Error += test_uint16();
+		Error += test_int32();
+		Error += test_uint32();
+
+		return Error;
+	}
+}//isPowerOfTwo
+
+namespace nextPowerOfTwo_advanced
+{
+	template<typename genIUType>
+	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<typename genType>
+	GLM_FUNC_QUALIFIER genType nextPowerOfTwo_loop(genType value)
+	{
+		return glm::isPowerOfTwo(value) ? value : highestBitValue(value) << 1;
+	}
+
+	template<typename genType>
+	struct type
+	{
+		genType		Value;
+		genType		Return;
+	};
+
+	int test_int32()
+	{
+		type<glm::int32> const Data[] =
+		{
+			{0x0000ffff, 0x00010000},
+			{-3, -4},
+			{-8, -8},
+			{0x00000001, 0x00000001},
+			{0x00000002, 0x00000002},
+			{0x00000004, 0x00000004},
+			{0x00000007, 0x00000008},
+			{0x0000fff0, 0x00010000},
+			{0x0000f000, 0x00010000},
+			{0x08000000, 0x08000000},
+			{0x00000000, 0x00000000},
+			{0x00000003, 0x00000004}
+		};
+
+		int Error(0);
+
+		for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::int32>); i < n; ++i)
+		{
+			glm::int32 Result = glm::nextPowerOfTwo(Data[i].Value);
+			Error += Data[i].Return == Result ? 0 : 1;
+		}
+
+		return Error;
+	}
+
+	int test_uint32()
+	{
+		type<glm::uint32> const Data[] =
+		{
+			{0x00000001, 0x00000001},
+			{0x00000002, 0x00000002},
+			{0x00000004, 0x00000004},
+			{0x00000007, 0x00000008},
+			{0x0000ffff, 0x00010000},
+			{0x0000fff0, 0x00010000},
+			{0x0000f000, 0x00010000},
+			{0x80000000, 0x80000000},
+			{0x00000000, 0x00000000},
+			{0x00000003, 0x00000004}
+		};
+
+		int Error(0);
+
+		for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<glm::uint32>); i < n; ++i)
+		{
+			glm::uint32 Result = glm::nextPowerOfTwo(Data[i].Value);
+			Error += Data[i].Return == Result ? 0 : 1;
+		}
+
+		return Error;
+	}
+
+	int perf()
+	{
+		int Error(0);
+
+		std::vector<glm::uint> v;
+		v.resize(100000000);
+
+		std::clock_t Timestramp0 = std::clock();
+
+		for(glm::uint32 i = 0, n = static_cast<glm::uint>(v.size()); i < n; ++i)
+			v[i] = nextPowerOfTwo_loop(i);
+
+		std::clock_t Timestramp1 = std::clock();
+
+		for(glm::uint32 i = 0, n = static_cast<glm::uint>(v.size()); i < n; ++i)
+			v[i] = glm::nextPowerOfTwo(i);
+
+		std::clock_t Timestramp2 = std::clock();
+
+		std::printf("nextPowerOfTwo_loop: %d clocks\n", static_cast<int>(Timestramp1 - Timestramp0));
+		std::printf("glm::nextPowerOfTwo: %d clocks\n", static_cast<int>(Timestramp2 - Timestramp1));
+
+		return Error;
+	}
+
+	int test()
+	{
+		int Error(0);
+
+		Error += test_int32();
+		Error += test_uint32();
+
+		return Error;
+	}
+}//namespace nextPowerOfTwo_advanced
+
+namespace prevPowerOfTwo
+{
+	template <typename T>
+	int run()
+	{
+		int Error = 0;
+
+		T const A = glm::prevPowerOfTwo(static_cast<T>(7));
+		Error += A == static_cast<T>(4) ? 0 : 1;
+
+		T const B = glm::prevPowerOfTwo(static_cast<T>(15));
+		Error += B == static_cast<T>(8) ? 0 : 1;
+
+		T const C = glm::prevPowerOfTwo(static_cast<T>(31));
+		Error += C == static_cast<T>(16) ? 0 : 1;
+
+		T const D = glm::prevPowerOfTwo(static_cast<T>(32));
+		Error += D == static_cast<T>(32) ? 0 : 1;
+
+		return Error;
+	}
+
+	int test()
+	{
+		int Error = 0;
+
+		Error += run<glm::int8>();
+		Error += run<glm::int16>();
+		Error += run<glm::int32>();
+		Error += run<glm::int64>();
+
+		Error += run<glm::uint8>();
+		Error += run<glm::uint16>();
+		Error += run<glm::uint32>();
+		Error += run<glm::uint64>();
+
+		return Error;
+	}
+}//namespace prevPowerOfTwo
+
+namespace nextPowerOfTwo
+{
+	template <typename T>
+	int run()
+	{
+		int Error = 0;
+
+		T const A = glm::nextPowerOfTwo(static_cast<T>(7));
+		Error += A == static_cast<T>(8) ? 0 : 1;
+
+		T const B = glm::nextPowerOfTwo(static_cast<T>(15));
+		Error += B == static_cast<T>(16) ? 0 : 1;
+
+		T const C = glm::nextPowerOfTwo(static_cast<T>(31));
+		Error += C == static_cast<T>(32) ? 0 : 1;
+
+		T const D = glm::nextPowerOfTwo(static_cast<T>(32));
+		Error += D == static_cast<T>(32) ? 0 : 1;
+
+		return Error;
+	}
+
+	int test()
+	{
+		int Error = 0;
+
+		Error += run<glm::int8>();
+		Error += run<glm::int16>();
+		Error += run<glm::int32>();
+		Error += run<glm::int64>();
+
+		Error += run<glm::uint8>();
+		Error += run<glm::uint16>();
+		Error += run<glm::uint32>();
+		Error += run<glm::uint64>();
+
+		return Error;
+	}
+}//namespace nextPowerOfTwo
+
+namespace prevMultiple
+{
+	template<typename genIUType>
+	struct type
+	{
+		genIUType Source;
+		genIUType Multiple;
+		genIUType Return;
+	};
+
+	template <typename T>
+	int run()
+	{
+		type<T> const Data[] =
+		{
+			{8, 3, 6},
+			{7, 7, 7}
+		};
+
+		int Error = 0;
+		
+		for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<T>); i < n; ++i)
+		{
+			T const Result = glm::prevMultiple(Data[i].Source, Data[i].Multiple);
+			Error += Data[i].Return == Result ? 0 : 1;
+		}
+
+		return Error;
+	}
+
+	int test()
+	{
+		int Error = 0;
+
+		Error += run<glm::int8>();
+		Error += run<glm::int16>();
+		Error += run<glm::int32>();
+		Error += run<glm::int64>();
+
+		Error += run<glm::uint8>();
+		Error += run<glm::uint16>();
+		Error += run<glm::uint32>();
+		Error += run<glm::uint64>();
+
+		return Error;
+	}
+}//namespace prevMultiple
+
+namespace nextMultiple
+{
+	template<typename genIUType>
+	struct type
+	{
+		genIUType Source;
+		genIUType Multiple;
+		genIUType Return;
+	};
+
+	template <typename T>
+	int run()
+	{
+		type<T> const Data[] =
+		{
+			{ 8, 3, 6 },
+			{ 7, 7, 7 }
+		};
+
+		int Error = 0;
+
+		for(std::size_t i = 0, n = sizeof(Data) / sizeof(type<T>); i < n; ++i)
+		{
+			T const Result = glm::nextMultiple(Data[i].Source, Data[i].Multiple);
+			Error += Data[i].Return == Result ? 0 : 1;
+		}
+
+		return Error;
+	}
+
+	int test()
+	{
+		int Error = 0;
+
+		Error += run<glm::int8>();
+		Error += run<glm::int16>();
+		Error += run<glm::int32>();
+		Error += run<glm::int64>();
+
+		Error += run<glm::uint8>();
+		Error += run<glm::uint16>();
+		Error += run<glm::uint32>();
+		Error += run<glm::uint64>();
+
+		return Error;
+	}
+}//namespace nextMultiple
+
+int main()
+{
+	int Error(0);
+
+	Error += isPowerOfTwo::test();
+	Error += prevPowerOfTwo::test();
+	Error += nextPowerOfTwo::test();
+	Error += nextPowerOfTwo_advanced::test();
+	
+#	ifdef NDEBUG
+		Error += nextPowerOfTwo_advanced::perf();
+#	endif//NDEBUG
+
+	Error += prevMultiple::test();
+	Error += nextMultiple::test();
+
+	return Error;
+}

+ 1 - 2
test/ext/ext_vector_integer.cpp

@@ -1,10 +1,9 @@
+#include <glm/ext/vector_integer.hpp>
 #include <glm/ext/vector_int1.hpp>
-#include <glm/ext/vector_int1_precision.hpp>
 #include <glm/ext/vector_int2.hpp>
 #include <glm/ext/vector_int3.hpp>
 #include <glm/ext/vector_int4.hpp>
 #include <glm/ext/vector_uint1.hpp>
-#include <glm/ext/vector_uint1_precision.hpp>
 #include <glm/ext/vector_uint2.hpp>
 #include <glm/ext/vector_uint3.hpp>
 #include <glm/ext/vector_uint4.hpp>

+ 212 - 0
test/ext/ext_vector_integer_sized.cpp

@@ -0,0 +1,212 @@
+#include <glm/ext/vector_int1.hpp>
+#include <glm/ext/vector_int1_precision.hpp>
+#include <glm/ext/vector_int2.hpp>
+#include <glm/ext/vector_int3.hpp>
+#include <glm/ext/vector_int4.hpp>
+#include <glm/ext/vector_uint1.hpp>
+#include <glm/ext/vector_uint1_precision.hpp>
+#include <glm/ext/vector_uint2.hpp>
+#include <glm/ext/vector_uint3.hpp>
+#include <glm/ext/vector_uint4.hpp>
+#include <glm/vector_relational.hpp>
+
+template <typename genType>
+static int test_operators()
+{
+	int Error = 0;
+
+	{
+		genType const A(1);
+		genType const B(1);
+
+		bool const R = A != B;
+		bool const S = A == B;
+		Error += (S && !R) ? 0 : 1;
+	}
+
+	{
+		genType const A(1);
+		genType const B(1);
+
+		genType const C = A + B;
+		Error += C == genType(2) ? 0 : 1;
+
+		genType const D = A - B;
+		Error += D == genType(0) ? 0 : 1;
+
+		genType const E = A * B;
+		Error += E == genType(1) ? 0 : 1;
+
+		genType const F = A / B;
+		Error += F == genType(1) ? 0 : 1;
+	}
+
+	{
+		genType const A(3);
+		genType const B(2);
+
+		genType const C = A % B;
+		Error += C == genType(1) ? 0 : 1;
+	}
+
+	{
+		genType const A(1);
+		genType const B(1);
+		genType const C(0);
+
+		genType const I = A & B;
+		Error += I == genType(1) ? 0 : 1;
+		genType const D = A & C;
+		Error += D == genType(0) ? 0 : 1;
+
+		genType const E = A | B;
+		Error += E == genType(1) ? 0 : 1;
+		genType const F = A | C;
+		Error += F == genType(1) ? 0 : 1;
+
+		genType const G = A ^ B;
+		Error += G == genType(0) ? 0 : 1;
+		genType const H = A ^ C;
+		Error += H == genType(1) ? 0 : 1;
+	}
+
+	{
+		genType const A(0);
+		genType const B(1);
+		genType const C(2);
+
+		genType const D = B << B;
+		Error += D == genType(2) ? 0 : 1;
+		genType const E = C >> B;
+		Error += E == genType(1) ? 0 : 1;
+	}
+
+	return Error;
+}
+
+template <typename genType>
+static int test_ctor()
+{
+	typedef typename genType::value_type T;
+	
+	int Error = 0;
+
+	genType const A = genType(1);
+
+	genType const E(genType(1));
+	Error += A == E ? 0 : 1;
+
+	genType const F(E);
+	Error += A == F ? 0 : 1;
+
+	genType const B = genType(1);
+	genType const G(glm::vec<2, T>(1));
+	Error += B == G ? 0 : 1;
+
+	genType const H(glm::vec<3, T>(1));
+	Error += B == H ? 0 : 1;
+
+	genType const I(glm::vec<4, T>(1));
+	Error += B == I ? 0 : 1;
+
+	return Error;
+}
+
+template <typename genType>
+static int test_size()
+{
+	int Error = 0;
+
+	Error += sizeof(typename genType::value_type) == sizeof(genType) ? 0 : 1;
+	Error += genType().length() == 1 ? 0 : 1;
+	Error += genType::length() == 1 ? 0 : 1;
+
+	return Error;
+}
+
+template <typename genType>
+static int test_relational()
+{
+	int Error = 0;
+
+	genType const A(1);
+	genType const B(1);
+	genType const C(0);
+
+	Error += A == B ? 0 : 1;
+	Error += A != C ? 0 : 1;
+	Error += all(equal(A, B)) ? 0 : 1;
+	Error += any(notEqual(A, C)) ? 0 : 1;
+
+	return Error;
+}
+
+template <typename genType>
+static int test_constexpr()
+{
+#	if GLM_CONFIG_CONSTEXP == GLM_ENABLE
+		static_assert(genType::length() == 1, "GLM: Failed constexpr");
+		static_assert(genType(1)[0] == 1, "GLM: Failed constexpr");
+		static_assert(genType(1) == genType(1), "GLM: Failed constexpr");
+		static_assert(genType(1) != genType(0), "GLM: Failed constexpr");
+#	endif
+
+	return 0;
+}
+
+int main()
+{
+	int Error = 0;
+
+	Error += test_operators<glm::ivec1>();
+	Error += test_operators<glm::lowp_ivec1>();
+	Error += test_operators<glm::mediump_ivec1>();
+	Error += test_operators<glm::highp_ivec1>();
+
+	Error += test_ctor<glm::ivec1>();
+	Error += test_ctor<glm::lowp_ivec1>();
+	Error += test_ctor<glm::mediump_ivec1>();
+	Error += test_ctor<glm::highp_ivec1>();
+
+	Error += test_size<glm::ivec1>();
+	Error += test_size<glm::lowp_ivec1>();
+	Error += test_size<glm::mediump_ivec1>();
+	Error += test_size<glm::highp_ivec1>();
+
+	Error += test_relational<glm::ivec1>();
+	Error += test_relational<glm::lowp_ivec1>();
+	Error += test_relational<glm::mediump_ivec1>();
+	Error += test_relational<glm::highp_ivec1>();
+
+	Error += test_constexpr<glm::ivec1>();
+	Error += test_constexpr<glm::lowp_ivec1>();
+	Error += test_constexpr<glm::mediump_ivec1>();
+	Error += test_constexpr<glm::highp_ivec1>();
+
+	Error += test_operators<glm::uvec1>();
+	Error += test_operators<glm::lowp_uvec1>();
+	Error += test_operators<glm::mediump_uvec1>();
+	Error += test_operators<glm::highp_uvec1>();
+	
+	Error += test_ctor<glm::uvec1>();
+	Error += test_ctor<glm::lowp_uvec1>();
+	Error += test_ctor<glm::mediump_uvec1>();
+	Error += test_ctor<glm::highp_uvec1>();
+	
+	Error += test_size<glm::uvec1>();
+	Error += test_size<glm::lowp_uvec1>();
+	Error += test_size<glm::mediump_uvec1>();
+	Error += test_size<glm::highp_uvec1>();
+	
+	Error += test_relational<glm::uvec1>();
+	Error += test_relational<glm::lowp_uvec1>();
+	Error += test_relational<glm::mediump_uvec1>();
+	Error += test_relational<glm::highp_uvec1>();
+	
+	Error += test_constexpr<glm::uvec1>();
+	Error += test_constexpr<glm::lowp_uvec1>();
+	Error += test_constexpr<glm::mediump_uvec1>();
+	Error += test_constexpr<glm::highp_uvec1>();
+	
+	return Error;
+}