Browse Source

More constexpr experiments

Groove 7 years ago
parent
commit
c5386c05f9

+ 2 - 2
glm/common.hpp

@@ -30,7 +30,7 @@ namespace glm
 	/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
 	/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
 	/// @see qualifier
 	/// @see qualifier
 	template<typename genType>
 	template<typename genType>
-	GLM_FUNC_DECL genType abs(genType x);
+	GLM_FUNC_DECL GLM_CONSTEXPR_CXX11 genType abs(genType x);
 
 
 	/// Returns x if x >= 0; otherwise, it returns -x.
 	/// Returns x if x >= 0; otherwise, it returns -x.
 	///
 	///
@@ -41,7 +41,7 @@ namespace glm
 	/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/abs.xml">GLSL abs man page</a>
 	/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/abs.xml">GLSL abs man page</a>
 	/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
 	/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
 	template<length_t L, typename T, qualifier Q>
 	template<length_t L, typename T, qualifier Q>
-	GLM_FUNC_DECL vec<L, T, Q> abs(vec<L, T, Q> const& x);
+	GLM_FUNC_DECL GLM_CONSTEXPR_CXX11 vec<L, T, Q> abs(vec<L, T, Q> const& x);
 
 
 	/// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0.
 	/// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0.
 	///
 	///

+ 4 - 4
glm/detail/_vectorize.hpp

@@ -17,7 +17,7 @@ namespace detail
 	template<typename R, typename T, qualifier Q>
 	template<typename R, typename T, qualifier Q>
 	struct functor1<1, R, T, Q>
 	struct functor1<1, R, T, Q>
 	{
 	{
-		GLM_FUNC_QUALIFIER static vec<1, R, Q> call(R (*Func) (T x), vec<1, T, Q> const& v)
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static vec<1, R, Q> call(R (*Func) (T x), vec<1, T, Q> const& v)
 		{
 		{
 			return vec<1, R, Q>(Func(v.x));
 			return vec<1, R, Q>(Func(v.x));
 		}
 		}
@@ -26,7 +26,7 @@ namespace detail
 	template<typename R, typename T, qualifier Q>
 	template<typename R, typename T, qualifier Q>
 	struct functor1<2, R, T, Q>
 	struct functor1<2, R, T, Q>
 	{
 	{
-		GLM_FUNC_QUALIFIER static vec<2, R, Q> call(R (*Func) (T x), vec<2, T, Q> const& v)
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static vec<2, R, Q> call(R (*Func) (T x), vec<2, T, Q> const& v)
 		{
 		{
 			return vec<2, R, Q>(Func(v.x), Func(v.y));
 			return vec<2, R, Q>(Func(v.x), Func(v.y));
 		}
 		}
@@ -35,7 +35,7 @@ namespace detail
 	template<typename R, typename T, qualifier Q>
 	template<typename R, typename T, qualifier Q>
 	struct functor1<3, R, T, Q>
 	struct functor1<3, R, T, Q>
 	{
 	{
-		GLM_FUNC_QUALIFIER static vec<3, R, Q> call(R (*Func) (T x), vec<3, T, Q> const& v)
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static vec<3, R, Q> call(R (*Func) (T x), vec<3, T, Q> const& v)
 		{
 		{
 			return vec<3, R, Q>(Func(v.x), Func(v.y), Func(v.z));
 			return vec<3, R, Q>(Func(v.x), Func(v.y), Func(v.z));
 		}
 		}
@@ -44,7 +44,7 @@ namespace detail
 	template<typename R, typename T, qualifier Q>
 	template<typename R, typename T, qualifier Q>
 	struct functor1<4, R, T, Q>
 	struct functor1<4, R, T, Q>
 	{
 	{
-		GLM_FUNC_QUALIFIER static vec<4, R, Q> call(R (*Func) (T x), vec<4, T, Q> const& v)
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static vec<4, R, Q> call(R (*Func) (T x), vec<4, T, Q> const& v)
 		{
 		{
 			return vec<4, R, Q>(Func(v.x), Func(v.y), Func(v.z), Func(v.w));
 			return vec<4, R, Q>(Func(v.x), Func(v.y), Func(v.z), Func(v.w));
 		}
 		}

+ 60 - 0
glm/detail/compute_common.hpp

@@ -0,0 +1,60 @@
+#pragma once
+
+#include "setup.hpp"
+#include <cstring>
+#include <limits>
+
+namespace glm{
+namespace detail
+{
+	template<typename genFIType, bool /*signed*/>
+	struct compute_abs
+	{};
+
+	template<typename genFIType>
+	struct compute_abs<genFIType, true>
+	{
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static genFIType call(genFIType x)
+		{
+			GLM_STATIC_ASSERT(
+				std::numeric_limits<genFIType>::is_iec559 || std::numeric_limits<genFIType>::is_signed || GLM_UNRESTRICTED_GENTYPE,
+				"'abs' only accept floating-point and integer scalar or vector inputs");
+
+			return x >= genFIType(0) ? x : -x;
+			// TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff;
+		}
+	};
+
+#if GLM_COMPILER & GLM_COMPILER_CUDA
+	template<>
+	struct compute_abs<float, true>
+	{
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static float call(float x)
+		{
+			return fabsf(x);
+		}
+	};
+#endif
+
+	template<typename genFIType>
+	struct compute_abs<genFIType, false>
+	{
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static genFIType call(genFIType x)
+		{
+			GLM_STATIC_ASSERT(
+				(!std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer) || GLM_UNRESTRICTED_GENTYPE,
+				"'abs' only accept floating-point and integer scalar or vector inputs");
+			return x;
+		}
+	};
+
+	template<length_t L, typename T, qualifier Q, bool Aligned>
+	struct compute_abs_vector
+	{
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static vec<L, T, Q> call(vec<L, T, Q> const& x)
+		{
+			return detail::functor1<L, T, T, Q>::call(abs, x);
+		}
+	};
+}//namespace detail
+}//namespace glm

+ 5 - 3
glm/detail/compute_vector_relational.hpp

@@ -1,5 +1,6 @@
 #pragma once
 #pragma once
 
 
+#include "compute_common.hpp"
 #include "setup.hpp"
 #include "setup.hpp"
 #include <cstring>
 #include <cstring>
 #include <limits>
 #include <limits>
@@ -10,7 +11,7 @@ namespace detail
 	template <typename T, bool isFloat = std::numeric_limits<T>::is_iec559>
 	template <typename T, bool isFloat = std::numeric_limits<T>::is_iec559>
 	struct compute_equal
 	struct compute_equal
 	{
 	{
-		GLM_FUNC_QUALIFIER static bool call(T a, T b)
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static bool call(T a, T b)
 		{
 		{
 			return a == b;
 			return a == b;
 		}
 		}
@@ -19,9 +20,10 @@ namespace detail
 	template <typename T>
 	template <typename T>
 	struct compute_equal<T, true>
 	struct compute_equal<T, true>
 	{
 	{
-		GLM_FUNC_QUALIFIER static bool call(T a, T b)
+		GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 static bool call(T a, T b)
 		{
 		{
-			return std::memcmp(&a, &b, sizeof(T)) == 0;
+			return detail::compute_abs<T, std::numeric_limits<T>::is_signed>::call(b - a) <= static_cast<T>(0);
+			//return std::memcmp(&a, &b, sizeof(T)) == 0;
 		}
 		}
 	};
 	};
 }//namespace detail
 }//namespace detail

+ 3 - 52
glm/detail/func_common.inl

@@ -2,6 +2,7 @@
 /// @file glm/detail/func_common.inl
 /// @file glm/detail/func_common.inl
 
 
 #include "../vector_relational.hpp"
 #include "../vector_relational.hpp"
+#include "compute_common.hpp"
 #include "type_vec2.hpp"
 #include "type_vec2.hpp"
 #include "type_vec3.hpp"
 #include "type_vec3.hpp"
 #include "type_vec4.hpp"
 #include "type_vec4.hpp"
@@ -66,56 +67,6 @@ namespace glm
 namespace glm{
 namespace glm{
 namespace detail
 namespace detail
 {
 {
-	template<typename genFIType, bool /*signed*/>
-	struct compute_abs
-	{};
-
-	template<typename genFIType>
-	struct compute_abs<genFIType, true>
-	{
-		GLM_FUNC_QUALIFIER static genFIType call(genFIType x)
-		{
-			GLM_STATIC_ASSERT(
-				std::numeric_limits<genFIType>::is_iec559 || std::numeric_limits<genFIType>::is_signed || GLM_UNRESTRICTED_GENTYPE,
-				"'abs' only accept floating-point and integer scalar or vector inputs");
-
-			return x >= genFIType(0) ? x : -x;
-			// TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff;
-		}
-	};
-
-	#if GLM_COMPILER & GLM_COMPILER_CUDA
-	template<>
-	struct compute_abs<float, true>
-	{
-		GLM_FUNC_QUALIFIER static float call(float x)
-		{
-			return fabsf(x);
-		}
-	};
-	#endif
-
-	template<typename genFIType>
-	struct compute_abs<genFIType, false>
-	{
-		GLM_FUNC_QUALIFIER static genFIType call(genFIType x)
-		{
-			GLM_STATIC_ASSERT(
-				(!std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer) || GLM_UNRESTRICTED_GENTYPE,
-				"'abs' only accept floating-point and integer scalar or vector inputs");
-			return x;
-		}
-	};
-
-	template<length_t L, typename T, qualifier Q, bool Aligned>
-	struct compute_abs_vector
-	{
-		GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
-		{
-			return detail::functor1<L, T, T, Q>::call(abs, x);
-		}
-	};
-
 	template<length_t L, typename T, typename U, qualifier Q, bool Aligned>
 	template<length_t L, typename T, typename U, qualifier Q, bool Aligned>
 	struct compute_mix_vector
 	struct compute_mix_vector
 	{
 	{
@@ -306,13 +257,13 @@ namespace detail
 }//namespace detail
 }//namespace detail
 
 
 	template<typename genFIType>
 	template<typename genFIType>
-	GLM_FUNC_QUALIFIER genFIType abs(genFIType x)
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 genFIType abs(genFIType x)
 	{
 	{
 		return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x);
 		return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x);
 	}
 	}
 
 
 	template<length_t L, typename T, qualifier Q>
 	template<length_t L, typename T, qualifier Q>
-	GLM_FUNC_QUALIFIER vec<L, T, Q> abs(vec<L, T, Q> const& x)
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 vec<L, T, Q> abs(vec<L, T, Q> const& x)
 	{
 	{
 		return detail::compute_abs_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x);
 		return detail::compute_abs_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x);
 	}
 	}

+ 1 - 1
glm/detail/type_vec3.hpp

@@ -409,7 +409,7 @@ namespace glm
 	GLM_FUNC_DECL GLM_CONSTEXPR_CXX11 bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2);
 	GLM_FUNC_DECL GLM_CONSTEXPR_CXX11 bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2);
 
 
 	template<typename T, qualifier Q>
 	template<typename T, qualifier Q>
-	GLM_FUNC_DECL bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2);
+	GLM_FUNC_DECL GLM_CONSTEXPR_CXX11 bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2);
 
 
 	template<qualifier Q>
 	template<qualifier Q>
 	GLM_FUNC_DECL vec<3, bool, Q> operator&&(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2);
 	GLM_FUNC_DECL vec<3, bool, Q> operator&&(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2);

+ 1 - 4
glm/detail/type_vec3.inl

@@ -1023,17 +1023,14 @@ namespace glm
 	template<typename T, qualifier Q>
 	template<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2)
 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2)
 	{
 	{
-		return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
-/*
 		return
 		return
 			detail::compute_equal<T>::call(v1.x, v2.x) &&
 			detail::compute_equal<T>::call(v1.x, v2.x) &&
 			detail::compute_equal<T>::call(v1.y, v2.y) &&
 			detail::compute_equal<T>::call(v1.y, v2.y) &&
 			detail::compute_equal<T>::call(v1.z, v2.z);
 			detail::compute_equal<T>::call(v1.z, v2.z);
-*/
 	}
 	}
 
 
 	template<typename T, qualifier Q>
 	template<typename T, qualifier Q>
-	GLM_FUNC_QUALIFIER bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2)
+	GLM_FUNC_QUALIFIER GLM_CONSTEXPR_CXX11 bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2)
 	{
 	{
 		return !(v1 == v2);
 		return !(v1 == v2);
 	}
 	}

+ 1 - 1
glm/detail/type_vec4.hpp

@@ -42,7 +42,7 @@ namespace glm
 
 
 			union
 			union
 			{
 			{
-				struct { T x, y, z, w;};
+				struct { T x, y, z, w; };
 				struct { T r, g, b, a; };
 				struct { T r, g, b, a; };
 				struct { T s, t, p, q; };
 				struct { T s, t, p, q; };
 
 

+ 9 - 0
test/core/core_func_common.cpp

@@ -1289,10 +1289,19 @@ namespace ldexp_
 	}
 	}
 }//namespace ldexp_
 }//namespace ldexp_
 
 
+static int test_constexpr()
+{
+	static_assert(glm::abs(1.0f) > 0.0f, "GLM: Failed constexpr");
+	static_assert(glm::abs(glm::vec3(1.0f)) != glm::vec3(0.0f), "GLM: Failed constexpr");
+
+	return 0;
+}
+
 int main()
 int main()
 {
 {
 	int Error = 0;
 	int Error = 0;
 
 
+	Error += test_constexpr();
 	Error += sign::test();
 	Error += sign::test();
 	Error += floor_::test();
 	Error += floor_::test();
 	Error += mod_::test();
 	Error += mod_::test();