More constexpr experiments

master
Groove ago%!(EXTRA string=7 years)
parent 5ddfa3f8a9
commit c5386c05f9
  1. 4
      glm/common.hpp
  2. 8
      glm/detail/_vectorize.hpp
  3. 60
      glm/detail/compute_common.hpp
  4. 8
      glm/detail/compute_vector_relational.hpp
  5. 55
      glm/detail/func_common.inl
  6. 2
      glm/detail/type_vec3.hpp
  7. 5
      glm/detail/type_vec3.inl
  8. 9
      test/core/core_func_common.cpp

@ -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.
/// ///

@ -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));
} }

@ -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

@ -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

@ -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);
} }

@ -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);

@ -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);
} }

@ -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();

Loading…
Cancel
Save