Browse Source

Add begin,end support for glm

ZXShady 10 months ago
parent
commit
65a83c9025
4 changed files with 419 additions and 0 deletions
  1. 87 0
      glm/gtx/iteration.hpp
  2. 116 0
      glm/gtx/iteration.inl
  3. 1 0
      test/gtx/CMakeLists.txt
  4. 215 0
      test/gtx/gtx_iteration.cpp

+ 87 - 0
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 <glm/gtx/iteration.hpp> 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 <iterator>
+
+namespace glm
+{
+	/// @addtogroup gtx_iteration
+	/// @{
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR T* begin(vec<L, T, Q>& v);
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR T* begin(mat<C, R, T, Q>& m);
+	template<typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR T* begin(qua<T, Q>& q);
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR const T* begin(const vec<L, T, Q>& v);
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR const T* begin(const mat<C, R, T, Q>& m);
+	template<typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR const T* begin(const qua<T, Q>& q);
+
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR T* end(vec<L, T, Q>& v);
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR T* end(mat<C, R, T, Q>& m);
+	template<typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR T* end(qua<T, Q>& q);
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR const T* end(const vec<L, T, Q>& v);
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR const T* end(const mat<C, R, T, Q>& m);
+	template<typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR const T* end(const qua<T, Q>& q);
+
+	// Reverse iteration
+	// rbegin,rend
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<T*> rbegin(vec<L, T, Q>& v);
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<T*> rbegin(mat<C, R, T, Q>& m);
+	template<typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<T*> rbegin(qua<T, Q>& q);
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<const T*> rbegin(const vec<L, T, Q>& v);
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<const T*> rbegin(const mat<C, R, T, Q>& m);
+	template<typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<const T*> rbegin(const qua<T, Q>& q);
+
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<T*> rend(vec<L, T, Q>& v);
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<T*> rend(mat<C, R, T, Q>& m);
+	template<typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<T*> rend(qua<T, Q>& q);
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<const T*> rend(const vec<L, T, Q>& v);
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<const T*> rend(const mat<C, R, T, Q>& m);
+	template<typename T,qualifier Q>
+	GLM_FUNC_DECL GLM_CONSTEXPR std::reverse_iterator<const T*> rend(const qua<T, Q>& q);
+
+
+	/// @}
+}//namespace glm
+
+#include "iteration.inl"

+ 116 - 0
glm/gtx/iteration.inl

@@ -0,0 +1,116 @@
+namespace glm
+{
+	/*
+	namespace details {
+		template<typename T, glm::length_t L>
+		struct known_length_iterator;
+	}
+	*/
+
+	/// @addtogroup gtx_iteration
+	/// @{
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* begin(vec<L,T,Q>& v) {
+		return &v.x;
+	}
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* begin(mat<C,R,T,Q>& m) {
+		return &m[0].x;
+	}
+	template<typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* begin(qua<T,Q>& q) {
+		return &q[0];
+	}
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* begin(const vec<L,T,Q>& v) {
+		return &v.x;
+	}
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* begin(const mat<C,R,T,Q>& m) {
+		return &m[0].x;
+	}
+	template<typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* begin(const qua<T,Q>& q) {
+		return &q[0];
+	}
+
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* end(vec<L,T,Q>& v) {
+		return (&v.x) + L;
+	}
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* end(mat<C,R,T,Q>& m) {
+		return (&m[0].x) + C*R;
+	}
+	template<typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR T* end(qua<T,Q>& q) {
+		return (&q[0]) + 4;
+	}
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* end(const vec<L,T,Q>& v) {
+		return (&v.x) + L;
+	}
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* end(const mat<C,R,T,Q>& m) {
+		return (&m[0].x) + C*R;
+	}
+	template<typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR const T* end(const qua<T,Q>& q) {
+		return (&q[0]) + 4;
+	}
+
+	// Reverse iteration
+	// rbegin,rend
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<T*> rbegin(vec<L,T,Q>& v) {
+		return std::reverse_iterator<T*>(end(v));
+	}
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<T*> rbegin(mat<C,R,T,Q>& m) {
+		return std::reverse_iterator<T*>(end(m));
+	}
+	template<typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<T*> rbegin(qua<T,Q>& q) {
+		return std::reverse_iterator<T*>(end(q));
+	}
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<const T*> rbegin(const vec<L,T,Q>& v) {
+		return std::reverse_iterator<const T*>(end(v));
+	}
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<const T*> rbegin(const mat<C,R,T,Q>& m) {
+		return std::reverse_iterator<const T*>(end(m));
+	}
+	template<typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<const T*> rbegin(const qua<T,Q>& q) {
+		return std::reverse_iterator<const T*>(end(q));
+	}
+
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<T*> rend(vec<L,T,Q>& v) {
+		return std::reverse_iterator<T*>(begin(v));
+	}
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<T*> rend(mat<C,R,T,Q>& m) {
+		return std::reverse_iterator<T*>(begin(m));
+	}
+	template<typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<T*> rend(qua<T,Q>& q) {
+		return std::reverse_iterator<T*>(begin(q));
+	}
+	template<length_t L,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<const T*> rend(const vec<L,T,Q>& v) {
+		return std::reverse_iterator<const T*>(begin(v));
+	}
+	template<length_t C,length_t R,typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<const T*> rend(const mat<C,R,T,Q>& m) {
+		return std::reverse_iterator<const T*>(begin(m));
+	}
+	template<typename T,qualifier Q>
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR std::reverse_iterator<const T*> rend(const qua<T,Q>& q) {
+		return std::reverse_iterator<const T*>(begin(q));
+	}
+
+
+	/// @}
+}//namespace glm

+ 1 - 0
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)

+ 215 - 0
test/gtx/gtx_iteration.cpp

@@ -0,0 +1,215 @@
+#define GLM_ENABLE_EXPERIMENTAL
+#include <glm/gtx/iteration.hpp>
+#include <iterator>
+#include <algorithm>
+#include <numeric>
+#include <glm/glm.hpp>
+#include <glm/gtx/quaternion.hpp>
+
+// 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<typename T>
+void begin(T) {}
+template<typename T>
+void rbegin(T) {}
+template<typename T>
+void end(T) {}
+template<typename T>
+void rend(T) {}
+
+
+template<typename T>
+std::ptrdiff_t get_iter_distance() {
+	T t = T(); // needed for const initializing
+	return std::distance(begin(t), end(t));
+}
+
+template<typename T>
+std::ptrdiff_t get_rev_iter_distance() {
+	T t = T(); // needed for const initializing
+	return std::distance(rbegin(t), rend(t));
+}
+
+
+template<typename GenTypc>
+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<const int*> it = rbegin(genType); it != rend(genType); ++it)
+			sum += *it;
+		Error += sum != compsum;
+	}
+	return Error;
+}
+
+template<glm::length_t L>
+int sumVec() {
+	glm::vec<L, int> v;
+	int sumManual = 0;
+	for (int i = 0; i < L; ++i) {
+		v[i] = i;
+		sumManual += i;
+	}
+	glm::vec<L, int> 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<glm::length_t C, glm::length_t R>
+int sumMat() {
+	glm::mat<C, R, int> 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<C, R, int> 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<int> q(0, 1, 2, 3);
+	glm::qua<int> 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<glm::vec1>());
+	Error += (2 != get_iter_distance<glm::vec2>());
+	Error += (3 != get_iter_distance<glm::vec3>());
+	Error += (4 != get_iter_distance<glm::vec4>());
+
+	Error += (1 != get_iter_distance<const glm::vec1>());
+	Error += (2 != get_iter_distance<const glm::vec2>());
+	Error += (3 != get_iter_distance<const glm::vec3>());
+	Error += (4 != get_iter_distance<const glm::vec4>());
+
+	Error += (4 != get_iter_distance<glm::quat>());
+	Error += (4 != get_iter_distance<const glm::quat>());
+
+	Error += (2 * 2 != get_iter_distance<glm::mat2x2>());
+	Error += (2 * 3 != get_iter_distance<glm::mat2x3>());
+	Error += (2 * 4 != get_iter_distance<glm::mat2x4>());
+
+	Error += (2 * 2 != get_iter_distance<const glm::mat2x2>());
+	Error += (2 * 3 != get_iter_distance<const glm::mat2x3>());
+	Error += (2 * 4 != get_iter_distance<const glm::mat2x4>());
+
+	Error += (3 * 2 != get_iter_distance<glm::mat3x2>());
+	Error += (3 * 3 != get_iter_distance<glm::mat3x3>());
+	Error += (3 * 4 != get_iter_distance<glm::mat3x4>());
+
+	Error += (3 * 2 != get_iter_distance<const glm::mat3x2>());
+	Error += (3 * 3 != get_iter_distance<const glm::mat3x3>());
+	Error += (3 * 4 != get_iter_distance<const glm::mat3x4>());
+
+	Error += (4 * 2 != get_iter_distance<glm::mat4x2>());
+	Error += (4 * 3 != get_iter_distance<glm::mat4x3>());
+	Error += (4 * 4 != get_iter_distance<glm::mat4x4>());
+
+	Error += (4 * 2 != get_iter_distance<const glm::mat4x2>());
+	Error += (4 * 3 != get_iter_distance<const glm::mat4x3>());
+	Error += (4 * 4 != get_iter_distance<const glm::mat4x4>());
+
+
+	Error += (1 != get_rev_iter_distance<glm::vec1>());
+	Error += (2 != get_rev_iter_distance<glm::vec2>());
+	Error += (3 != get_rev_iter_distance<glm::vec3>());
+	Error += (4 != get_rev_iter_distance<glm::vec4>());
+
+	Error += (1 != get_rev_iter_distance<const glm::vec1>());
+	Error += (2 != get_rev_iter_distance<const glm::vec2>());
+	Error += (3 != get_rev_iter_distance<const glm::vec3>());
+	Error += (4 != get_rev_iter_distance<const glm::vec4>());
+
+	Error += (4 != get_rev_iter_distance<glm::quat>());
+	Error += (4 != get_rev_iter_distance<const glm::quat>());
+
+	Error += (2 * 2 != get_rev_iter_distance<glm::mat2x2>());
+	Error += (2 * 3 != get_rev_iter_distance<glm::mat2x3>());
+	Error += (2 * 4 != get_rev_iter_distance<glm::mat2x4>());
+
+	Error += (2 * 2 != get_rev_iter_distance<const glm::mat2x2>());
+	Error += (2 * 3 != get_rev_iter_distance<const glm::mat2x3>());
+	Error += (2 * 4 != get_rev_iter_distance<const glm::mat2x4>());
+
+
+	Error += (3 * 2 != get_rev_iter_distance<glm::mat3x2>());
+	Error += (3 * 3 != get_rev_iter_distance<glm::mat3x3>());
+	Error += (3 * 4 != get_rev_iter_distance<glm::mat3x4>());
+
+	Error += (3 * 2 != get_rev_iter_distance<const glm::mat3x2>());
+	Error += (3 * 3 != get_rev_iter_distance<const glm::mat3x3>());
+	Error += (3 * 4 != get_rev_iter_distance<const glm::mat3x4>());
+
+	Error += (4 * 2 != get_rev_iter_distance<glm::mat4x2>());
+	Error += (4 * 3 != get_rev_iter_distance<glm::mat4x3>());
+	Error += (4 * 4 != get_rev_iter_distance<glm::mat4x4>());
+
+	Error += (4 * 2 != get_rev_iter_distance<const glm::mat4x2>());
+	Error += (4 * 3 != get_rev_iter_distance<const glm::mat4x3>());
+	Error += (4 * 4 != get_rev_iter_distance<const glm::mat4x4>());
+
+	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;
+}