diff --git a/glm/gtx/iteration.hpp b/glm/gtx/iteration.hpp new file mode 100644 index 00000000..c63af87a --- /dev/null +++ b/glm/gtx/iteration.hpp @@ -0,0 +1,87 @@ +/// @ref gtx_iteration +/// @file glm/gtx/iteration.hpp +/// +/// @defgroup gtx_iteration GLM_GTX_iteration +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines begin and end for vectors, matrices and quaternions useful for range based for loop construct + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_iteration is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_iteration extension included") +#endif + +#include + +namespace glm +{ + /// @addtogroup gtx_iteration + /// @{ + template + GLM_FUNC_DECL GLM_CONSTEXPR T* begin(vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR T* begin(mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR T* begin(qua& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR const T* begin(const vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR const T* begin(const mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR const T* begin(const qua& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR T* end(vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR T* end(mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR T* end(qua& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR const T* end(const vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR const T* end(const mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR const T* end(const qua& q); + + // Reverse iteration + // rbegin,rend + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rbegin(vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rbegin(mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rbegin(qua& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rbegin(const vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rbegin(const mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rbegin(const qua& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rend(vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rend(mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rend(qua& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rend(const vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rend(const mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator rend(const qua& q); + + + /// @} +}//namespace glm + +#include "iteration.inl" diff --git a/glm/gtx/iteration.inl b/glm/gtx/iteration.inl new file mode 100644 index 00000000..be089400 --- /dev/null +++ b/glm/gtx/iteration.inl @@ -0,0 +1,116 @@ +namespace glm +{ + /* + namespace details { + template + struct known_length_iterator; + } + */ + + /// @addtogroup gtx_iteration + /// @{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* begin(vec& v) { + return &v.x; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* begin(mat& m) { + return &m[0].x; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* begin(qua& q) { + return &q[0]; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* begin(const vec& v) { + return &v.x; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* begin(const mat& m) { + return &m[0].x; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* begin(const qua& q) { + return &q[0]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* end(vec& v) { + return (&v.x) + L; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* end(mat& m) { + return (&m[0].x) + C*R; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* end(qua& q) { + return (&q[0]) + 4; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* end(const vec& v) { + return (&v.x) + L; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* end(const mat& m) { + return (&m[0].x) + C*R; + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* end(const qua& q) { + return (&q[0]) + 4; + } + + // Reverse iteration + // rbegin,rend + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rbegin(vec& v) { + return std::reverse_iterator(end(v)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rbegin(mat& m) { + return std::reverse_iterator(end(m)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rbegin(qua& q) { + return std::reverse_iterator(end(q)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rbegin(const vec& v) { + return std::reverse_iterator(end(v)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rbegin(const mat& m) { + return std::reverse_iterator(end(m)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rbegin(const qua& q) { + return std::reverse_iterator(end(q)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rend(vec& v) { + return std::reverse_iterator(begin(v)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rend(mat& m) { + return std::reverse_iterator(begin(m)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rend(qua& q) { + return std::reverse_iterator(begin(q)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rend(const vec& v) { + return std::reverse_iterator(begin(v)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rend(const mat& m) { + return std::reverse_iterator(begin(m)); + } + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator rend(const qua& q) { + return std::reverse_iterator(begin(q)); + } + + + /// @} +}//namespace glm diff --git a/test/gtx/CMakeLists.txt b/test/gtx/CMakeLists.txt index b7686673..3656c898 100644 --- a/test/gtx/CMakeLists.txt +++ b/test/gtx/CMakeLists.txt @@ -22,6 +22,7 @@ glmCreateTestGTC(gtx_hash) glmCreateTestGTC(gtx_integer) glmCreateTestGTC(gtx_intersect) glmCreateTestGTC(gtx_io) +glmCreateTestGTC(gtx_iteration) glmCreateTestGTC(gtx_load) glmCreateTestGTC(gtx_log_base) glmCreateTestGTC(gtx_matrix_cross_product) diff --git a/test/gtx/gtx_iteration.cpp b/test/gtx/gtx_iteration.cpp new file mode 100644 index 00000000..5e26f007 --- /dev/null +++ b/test/gtx/gtx_iteration.cpp @@ -0,0 +1,215 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include +#include + +// Testing if adl works if it doesn't a compiler error is generated +// Note all usages of glm::begin,glm::end,glm::rbegin,glm::rend +// in this file is via adl +template +void begin(T) {} +template +void rbegin(T) {} +template +void end(T) {} +template +void rend(T) {} + + +template +std::ptrdiff_t get_iter_distance() { + T t = T(); // needed for const initializing + return std::distance(begin(t), end(t)); +} + +template +std::ptrdiff_t get_rev_iter_distance() { + T t = T(); // needed for const initializing + return std::distance(rbegin(t), rend(t)); +} + + +template +int rangedSumComp(GenTypc& genType, int compsum) { + int Error = 0; + +#if defined(__cpp_range_based_for) +#if __cpp_range_based_for >= 200907L + { + int sum = 0; + for (const int& elem : genType) + sum += elem; + Error += sum != compsum; + } +#endif +#endif + { + int sum = 0; + for (const int* it = begin(genType); it != end(genType); ++it) + sum += *it; + Error += sum != compsum; + } + + { + int sum = 0; + for (std::reverse_iterator it = rbegin(genType); it != rend(genType); ++it) + sum += *it; + Error += sum != compsum; + } + return Error; +} + +template +int sumVec() { + glm::vec v; + int sumManual = 0; + for (int i = 0; i < L; ++i) { + v[i] = i; + sumManual += i; + } + glm::vec const cv = v; + + return (sumManual != std::accumulate(begin(v), end(v), 0)) + + (sumManual != std::accumulate(begin(cv), end(cv), 0)) + + (sumManual != std::accumulate(rbegin(v), rend(v), 0)) + + (sumManual != std::accumulate(rbegin(cv), rend(cv), 0)) + + rangedSumComp(v, sumManual) + + rangedSumComp(cv, sumManual); +} + +template +int sumMat() { + glm::mat m; + int sumManual = 0; + for (int i = 0; i < C; ++i) { + for (int j = 0; j < R; ++j) { + m[i][j] = i * j; + sumManual += i * j; + } + } + glm::mat const cm = m; + return (sumManual != std::accumulate(begin(m), end(m), 0)) + + (sumManual != std::accumulate(begin(cm), end(cm), 0)) + + (sumManual != std::accumulate(rbegin(m), rend(m), 0)) + + (sumManual != std::accumulate(rbegin(cm), rend(cm), 0)) + + rangedSumComp(m, sumManual) + + rangedSumComp(cm, sumManual); +} + +static int sumQuat() { + glm::qua q(0, 1, 2, 3); + glm::qua const cq(0, 1, 2, 3); + const int sumManual = (0 + 1 + 2 + 3); + return (sumManual != std::accumulate(begin(q), end(q), 0)) + + (sumManual != std::accumulate(begin(cq), end(cq), 0)) + + (sumManual != std::accumulate(rbegin(q), rend(q), 0)) + + (sumManual != std::accumulate(rbegin(cq), rend(cq), 0)) + + rangedSumComp(q, sumManual) + + rangedSumComp(cq, sumManual); +} + + +int main() +{ + int Error = 0; + + Error += (1 != get_iter_distance()); + Error += (2 != get_iter_distance()); + Error += (3 != get_iter_distance()); + Error += (4 != get_iter_distance()); + + Error += (1 != get_iter_distance()); + Error += (2 != get_iter_distance()); + Error += (3 != get_iter_distance()); + Error += (4 != get_iter_distance()); + + Error += (4 != get_iter_distance()); + Error += (4 != get_iter_distance()); + + Error += (2 * 2 != get_iter_distance()); + Error += (2 * 3 != get_iter_distance()); + Error += (2 * 4 != get_iter_distance()); + + Error += (2 * 2 != get_iter_distance()); + Error += (2 * 3 != get_iter_distance()); + Error += (2 * 4 != get_iter_distance()); + + Error += (3 * 2 != get_iter_distance()); + Error += (3 * 3 != get_iter_distance()); + Error += (3 * 4 != get_iter_distance()); + + Error += (3 * 2 != get_iter_distance()); + Error += (3 * 3 != get_iter_distance()); + Error += (3 * 4 != get_iter_distance()); + + Error += (4 * 2 != get_iter_distance()); + Error += (4 * 3 != get_iter_distance()); + Error += (4 * 4 != get_iter_distance()); + + Error += (4 * 2 != get_iter_distance()); + Error += (4 * 3 != get_iter_distance()); + Error += (4 * 4 != get_iter_distance()); + + + Error += (1 != get_rev_iter_distance()); + Error += (2 != get_rev_iter_distance()); + Error += (3 != get_rev_iter_distance()); + Error += (4 != get_rev_iter_distance()); + + Error += (1 != get_rev_iter_distance()); + Error += (2 != get_rev_iter_distance()); + Error += (3 != get_rev_iter_distance()); + Error += (4 != get_rev_iter_distance()); + + Error += (4 != get_rev_iter_distance()); + Error += (4 != get_rev_iter_distance()); + + Error += (2 * 2 != get_rev_iter_distance()); + Error += (2 * 3 != get_rev_iter_distance()); + Error += (2 * 4 != get_rev_iter_distance()); + + Error += (2 * 2 != get_rev_iter_distance()); + Error += (2 * 3 != get_rev_iter_distance()); + Error += (2 * 4 != get_rev_iter_distance()); + + + Error += (3 * 2 != get_rev_iter_distance()); + Error += (3 * 3 != get_rev_iter_distance()); + Error += (3 * 4 != get_rev_iter_distance()); + + Error += (3 * 2 != get_rev_iter_distance()); + Error += (3 * 3 != get_rev_iter_distance()); + Error += (3 * 4 != get_rev_iter_distance()); + + Error += (4 * 2 != get_rev_iter_distance()); + Error += (4 * 3 != get_rev_iter_distance()); + Error += (4 * 4 != get_rev_iter_distance()); + + Error += (4 * 2 != get_rev_iter_distance()); + Error += (4 * 3 != get_rev_iter_distance()); + Error += (4 * 4 != get_rev_iter_distance()); + + Error += sumVec<1>(); + Error += sumVec<2>(); + Error += sumVec<3>(); + Error += sumVec<4>(); + + Error += sumMat<2, 2>(); + Error += sumMat<2, 3>(); + Error += sumMat<2, 4>(); + + Error += sumMat<3, 2>(); + Error += sumMat<3, 3>(); + Error += sumMat<3, 4>(); + + Error += sumMat<4, 2>(); + Error += sumMat<4, 3>(); + Error += sumMat<4, 4>(); + + Error += sumQuat(); + + return Error; +}