From 07c6d56b5fc7db66f98c56bf84db30846fffe2c1 Mon Sep 17 00:00:00 2001 From: Christophe Riccio Date: Fri, 26 Apr 2019 18:32:06 +0200 Subject: [PATCH] Added initial work for integer vector and scalar functions --- glm/ext/scalar_integer.hpp | 78 +++++ glm/ext/scalar_integer.inl | 194 ++++++++++++ glm/ext/vector_integer.hpp | 120 +++++++ glm/ext/vector_integer.inl | 343 ++++++++++++++++++++ glm/gtc/round.hpp | 2 +- test/ext/CMakeLists.txt | 2 + test/ext/ext_scalar_integer.cpp | 435 ++++++++++++++++++++++++++ test/ext/ext_vector_integer.cpp | 3 +- test/ext/ext_vector_integer_sized.cpp | 212 +++++++++++++ 9 files changed, 1386 insertions(+), 3 deletions(-) create mode 100644 glm/ext/scalar_integer.hpp create mode 100644 glm/ext/scalar_integer.inl create mode 100644 glm/ext/vector_integer.hpp create mode 100644 glm/ext/vector_integer.inl create mode 100644 test/ext/ext_scalar_integer.cpp create mode 100644 test/ext/ext_vector_integer_sized.cpp diff --git a/glm/ext/scalar_integer.hpp b/glm/ext/scalar_integer.hpp new file mode 100644 index 00000000..af29c8ac --- /dev/null +++ b/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 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 + +#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 + 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 + 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 + GLM_FUNC_DECL genIUType prevPowerOfTwo(genIUType v); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @see gtc_round + template + 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 + 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 + GLM_FUNC_DECL genIUType prevMultiple(genIUType v, genIUType Multiple); + + /// @} +} //namespace glm + +#include "scalar_integer.inl" diff --git a/glm/ext/scalar_integer.inl b/glm/ext/scalar_integer.inl new file mode 100644 index 00000000..35e457ee --- /dev/null +++ b/glm/ext/scalar_integer.inl @@ -0,0 +1,194 @@ +#include "../integer.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T) + { + return v; + } + }; + + template + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T Shift) + { + return v | (v >> Shift); + } + }; + + template + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec const Sign(sign(x)); + + vec v(abs(x)); + + 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_ceilShift= 2>::call(v, 8); + v = compute_ceilShift= 4>::call(v, 16); + v = compute_ceilShift= 8>::call(v, 32); + return (v + static_cast(1)) * Sign; + } + }; + + template + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec v(x); + + 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_ceilShift= 2>::call(v, 8); + v = compute_ceilShift= 4>::call(v, 16); + v = compute_ceilShift= 8>::call(v, 32); + return v + static_cast(1); + } + }; + + template + struct compute_ceilMultiple{}; + + template<> + struct compute_ceilMultiple + { + template + 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 + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + }; + + template<> + struct compute_ceilMultiple + { + template + 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 + struct compute_floorMultiple{}; + + template<> + struct compute_floorMultiple + { + template + 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 + { + template + 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 + { + template + 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 + GLM_FUNC_QUALIFIER bool isPowerOfTwo(genIUType Value) + { + genIUType const Result = glm::abs(Value); + return !(Result & (Result - 1)); + } + + template + GLM_FUNC_QUALIFIER genIUType nextPowerOfTwo(genIUType value) + { + return detail::compute_ceilPowerOfTwo<1, genIUType, defaultp, std::numeric_limits::is_signed>::call(vec<1, genIUType, defaultp>(value)).x; + } + + template + GLM_FUNC_QUALIFIER genIUType prevPowerOfTwo(genIUType value) + { + return isPowerOfTwo(value) ? value : static_cast(1) << findMSB(value); + } + + template + GLM_FUNC_QUALIFIER bool isMultiple(genIUType Value, genIUType Multiple) + { + return isMultiple(vec<1, genIUType>(Value), vec<1, genIUType>(Multiple)).x; + } + + template + GLM_FUNC_QUALIFIER genIUType nextMultiple(genIUType Source, genIUType Multiple) + { + return detail::compute_ceilMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER genIUType prevMultiple(genIUType Source, genIUType Multiple) + { + return detail::compute_floorMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } +}//namespace glm diff --git a/glm/ext/vector_integer.hpp b/glm/ext/vector_integer.hpp new file mode 100644 index 00000000..c5df1b81 --- /dev/null +++ b/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 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 + +#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 + GLM_FUNC_DECL vec isPowerOfTwo(vec 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 + GLM_FUNC_DECL vec nextPowerOfTwo(vec 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 + GLM_FUNC_DECL vec prevPowerOfTwo(vec 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 + GLM_FUNC_DECL vec isMultiple(vec 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 + GLM_FUNC_DECL vec isMultiple(vec const& v, vec 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 + GLM_FUNC_DECL vec nextMultiple(vec 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 + GLM_FUNC_DECL vec nextMultiple(vec const& v, vec 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 + GLM_FUNC_DECL vec prevMultiple(vec 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 + GLM_FUNC_DECL vec prevMultiple(vec const& v, vec const& Multiple); + + /// @} +} //namespace glm + +#include "vector_integer.inl" diff --git a/glm/ext/vector_integer.inl b/glm/ext/vector_integer.inl new file mode 100644 index 00000000..0d4d7d67 --- /dev/null +++ b/glm/ext/vector_integer.inl @@ -0,0 +1,343 @@ +/// @ref gtc_round + +#include "../integer.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T) + { + return v; + } + }; + + template + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T Shift) + { + return v | (v >> Shift); + } + }; + + template + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec const Sign(sign(x)); + + vec v(abs(x)); + + 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_ceilShift= 2>::call(v, 8); + v = compute_ceilShift= 4>::call(v, 16); + v = compute_ceilShift= 8>::call(v, 32); + return (v + static_cast(1)) * Sign; + } + }; + + template + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec v(x); + + 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_ceilShift= 2>::call(v, 8); + v = compute_ceilShift= 4>::call(v, 16); + v = compute_ceilShift= 8>::call(v, 32); + return v + static_cast(1); + } + }; + + template + struct compute_ceilMultiple{}; + + template<> + struct compute_ceilMultiple + { + template + 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 + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + }; + + template<> + struct compute_ceilMultiple + { + template + 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 + struct compute_floorMultiple{}; + + template<> + struct compute_floorMultiple + { + template + 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 + { + template + 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 + { + template + 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{}; + + template<> + struct compute_roundMultiple + { + template + 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 + { + template + 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 + { + template + 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 + GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value) + { + genType const Result = glm::abs(Value); + return !(Result & (Result - 1)); + } + + template + GLM_FUNC_QUALIFIER vec isPowerOfTwo(vec const& Value) + { + vec const Result(abs(Value)); + return equal(Result & (Result - 1), vec(0)); + } + + ////////////////// + // ceilPowerOfTwo + + template + GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value) + { + return detail::compute_ceilPowerOfTwo<1, genType, defaultp, std::numeric_limits::is_signed>::call(vec<1, genType, defaultp>(value)).x; + } + + template + GLM_FUNC_QUALIFIER vec ceilPowerOfTwo(vec const& v) + { + return detail::compute_ceilPowerOfTwo::is_signed>::call(v); + } + + /////////////////// + // floorPowerOfTwo + + template + GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value) + { + return isPowerOfTwo(value) ? value : static_cast(1) << findMSB(value); + } + + template + GLM_FUNC_QUALIFIER vec floorPowerOfTwo(vec const& v) + { + return detail::functor1::call(floorPowerOfTwo, v); + } + + /////////////////// + // roundPowerOfTwo + + template + GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value) + { + if(isPowerOfTwo(value)) + return value; + + genIUType const prev = static_cast(1) << findMSB(value); + genIUType const next = prev << static_cast(1); + return (next - value) < (value - prev) ? next : prev; + } + + template + GLM_FUNC_QUALIFIER vec roundPowerOfTwo(vec const& v) + { + return detail::functor1::call(roundPowerOfTwo, v); + } + + //////////////// + // isMultiple + + template + GLM_FUNC_QUALIFIER bool isMultiple(genType Value, genType Multiple) + { + return isMultiple(vec<1, genType>(Value), vec<1, genType>(Multiple)).x; + } + + template + GLM_FUNC_QUALIFIER vec isMultiple(vec const& Value, T Multiple) + { + return (Value % Multiple) == vec(0); + } + + template + GLM_FUNC_QUALIFIER vec isMultiple(vec const& Value, vec const& Multiple) + { + return (Value % Multiple) == vec(0); + } + + ////////////////////// + // ceilMultiple + + template + GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple) + { + return detail::compute_ceilMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec ceilMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(ceilMultiple, Source, Multiple); + } + + ////////////////////// + // floorMultiple + + template + GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple) + { + return detail::compute_floorMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec floorMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(floorMultiple, Source, Multiple); + } + + ////////////////////// + // roundMultiple + + template + GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple) + { + return detail::compute_roundMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec roundMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(roundMultiple, Source, Multiple); + } +}//namespace glm diff --git a/glm/gtc/round.hpp b/glm/gtc/round.hpp index fbbcdeb5..f1424c30 100644 --- a/glm/gtc/round.hpp +++ b/glm/gtc/round.hpp @@ -22,7 +22,7 @@ #include #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 diff --git a/test/ext/CMakeLists.txt b/test/ext/CMakeLists.txt index 9c04a239..639afe79 100644 --- a/test/ext/CMakeLists.txt +++ b/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) diff --git a/test/ext/ext_scalar_integer.cpp b/test/ext/ext_scalar_integer.cpp new file mode 100644 index 00000000..b6e27dcd --- /dev/null +++ b/test/ext/ext_scalar_integer.cpp @@ -0,0 +1,435 @@ +#include +#include +#include +#include +#include +#include + +namespace isPowerOfTwo +{ + template + struct type + { + genType Value; + bool Return; + }; + + int test_int16() + { + type 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); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uint16() + { + type 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); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_int32() + { + type 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); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uint32() + { + type 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); 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 + 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 + GLM_FUNC_QUALIFIER genType nextPowerOfTwo_loop(genType value) + { + return glm::isPowerOfTwo(value) ? value : highestBitValue(value) << 1; + } + + template + struct type + { + genType Value; + genType Return; + }; + + int test_int32() + { + type 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); i < n; ++i) + { + glm::int32 Result = glm::nextPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uint32() + { + type 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); 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 v; + v.resize(100000000); + + std::clock_t Timestramp0 = std::clock(); + + for(glm::uint32 i = 0, n = static_cast(v.size()); i < n; ++i) + v[i] = nextPowerOfTwo_loop(i); + + std::clock_t Timestramp1 = std::clock(); + + for(glm::uint32 i = 0, n = static_cast(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(Timestramp1 - Timestramp0)); + std::printf("glm::nextPowerOfTwo: %d clocks\n", static_cast(Timestramp2 - Timestramp1)); + + return Error; + } + + int test() + { + int Error(0); + + Error += test_int32(); + Error += test_uint32(); + + return Error; + } +}//namespace nextPowerOfTwo_advanced + +namespace prevPowerOfTwo +{ + template + int run() + { + int Error = 0; + + T const A = glm::prevPowerOfTwo(static_cast(7)); + Error += A == static_cast(4) ? 0 : 1; + + T const B = glm::prevPowerOfTwo(static_cast(15)); + Error += B == static_cast(8) ? 0 : 1; + + T const C = glm::prevPowerOfTwo(static_cast(31)); + Error += C == static_cast(16) ? 0 : 1; + + T const D = glm::prevPowerOfTwo(static_cast(32)); + Error += D == static_cast(32) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + return Error; + } +}//namespace prevPowerOfTwo + +namespace nextPowerOfTwo +{ + template + int run() + { + int Error = 0; + + T const A = glm::nextPowerOfTwo(static_cast(7)); + Error += A == static_cast(8) ? 0 : 1; + + T const B = glm::nextPowerOfTwo(static_cast(15)); + Error += B == static_cast(16) ? 0 : 1; + + T const C = glm::nextPowerOfTwo(static_cast(31)); + Error += C == static_cast(32) ? 0 : 1; + + T const D = glm::nextPowerOfTwo(static_cast(32)); + Error += D == static_cast(32) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + return Error; + } +}//namespace nextPowerOfTwo + +namespace prevMultiple +{ + template + struct type + { + genIUType Source; + genIUType Multiple; + genIUType Return; + }; + + template + int run() + { + type const Data[] = + { + {8, 3, 6}, + {7, 7, 7} + }; + + int Error = 0; + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); 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(); + Error += run(); + Error += run(); + Error += run(); + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + return Error; + } +}//namespace prevMultiple + +namespace nextMultiple +{ + template + struct type + { + genIUType Source; + genIUType Multiple; + genIUType Return; + }; + + template + int run() + { + type const Data[] = + { + { 8, 3, 6 }, + { 7, 7, 7 } + }; + + int Error = 0; + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); 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(); + Error += run(); + Error += run(); + Error += run(); + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + 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; +} diff --git a/test/ext/ext_vector_integer.cpp b/test/ext/ext_vector_integer.cpp index 39f11086..642499f7 100644 --- a/test/ext/ext_vector_integer.cpp +++ b/test/ext/ext_vector_integer.cpp @@ -1,10 +1,9 @@ +#include #include -#include #include #include #include #include -#include #include #include #include diff --git a/test/ext/ext_vector_integer_sized.cpp b/test/ext/ext_vector_integer_sized.cpp new file mode 100644 index 00000000..39f11086 --- /dev/null +++ b/test/ext/ext_vector_integer_sized.cpp @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +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 +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 +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 +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 +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(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + + return Error; +}