#pragma once #define CTORSL(L, CTOR)\ CTOR(L, aligned_lowp)\ CTOR(L, aligned_mediump)\ CTOR(L, aligned_highp)\ namespace glm { namespace detail { template struct compute_vec_and : public compute_vec_and {}; template struct compute_vec_or: public compute_vec_or {}; template struct compute_vec_xor : public compute_vec_xor {}; template struct compute_vec_shift_left : public compute_vec_shift_left {}; template struct compute_vec_shift_right : public compute_vec_shift_right {}; template struct compute_vec_bitwise_not:public compute_vec_bitwise_not {}; template struct compute_vec_equal : public compute_vec_equal {}; template struct compute_vec_nequal : public compute_vec_nequal {}; template struct compute_vec_mod : public compute_vec_mod {}; template struct compute_vec_add : public compute_vec_add {}; template< length_t L, typename T, qualifier Q> struct compute_vec_sub : public compute_vec_sub {}; template< length_t L, typename T, qualifier Q> struct compute_vec_mul : public compute_vec_mul {}; template< length_t L, typename T, qualifier Q> struct compute_vec_div : public compute_vec_div {}; #if GLM_ARCH & GLM_ARCH_SSE2_BIT # if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR template struct _swizzle_base1 : public _swizzle_base0 { GLM_FUNC_QUALIFIER vec operator ()() const { __m128 data = *reinterpret_cast<__m128 const*>(&this->_buffer); vec Result; # if GLM_ARCH & GLM_ARCH_AVX_BIT Result.data = _mm_permute_ps(data, _MM_SHUFFLE(E3, E2, E1, E0)); # else Result.data = _mm_shuffle_ps(data, data, _MM_SHUFFLE(E3, E2, E1, E0)); # endif return Result; } }; template struct _swizzle_base1<2, float, Q, E0, E1, E2, E3, true> : public _swizzle_base1<2, float, Q, E0, E1, E2, E3, false> {}; template struct _swizzle_base1<2, int, Q, E0, E1, E2, E3, true> : public _swizzle_base1<2, int, Q, E0, E1, E2, E3, false> {}; template struct _swizzle_base1 : public _swizzle_base0 { GLM_FUNC_QUALIFIER vec operator ()() const { __m128i data = *reinterpret_cast<__m128i const*>(&this->_buffer); vec Result; Result.data = _mm_shuffle_epi32(data, _MM_SHUFFLE(E3, E2, E1, E0)); return Result; } }; template struct _swizzle_base1 : public _swizzle_base0 { GLM_FUNC_QUALIFIER vec operator ()() const { __m128i data = *reinterpret_cast<__m128i const*>(&this->_buffer); vec Result; Result.data = _mm_shuffle_epi32(data, _MM_SHUFFLE(E3, E2, E1, E0)); return Result; } }; # endif// GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR template struct compute_vec_add { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_add_ps(a.data, b.data); return Result; } }; template struct compute_vec_add { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_add_epi32(a.data, b.data); return Result; } }; template struct compute_vec_add { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; # if (GLM_ARCH & GLM_ARCH_AVX_BIT) Result.data = _mm256_add_pd(a.data, b.data); #else Result.data.setv(0, _mm_add_pd(a.data.getv(0), b.data.getv(0))); Result.data.setv(1, _mm_add_pd(a.data.getv(1), b.data.getv(1))); #endif return Result; } }; template struct compute_vec_sub { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_sub_ps(a.data, b.data); return Result; } }; template struct compute_vec_sub { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_sub_epi32(a.data, b.data); return Result; } }; template struct compute_vec_sub { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; #if (GLM_ARCH & GLM_ARCH_AVX_BIT) Result.data = _mm256_sub_pd(a.data, b.data); #else Result.data.setv(0, _mm_sub_pd(a.data.getv(0), b.data.getv(0))); Result.data.setv(1, _mm_sub_pd(a.data.getv(1), b.data.getv(1))); #endif return Result; } }; template struct compute_vec_mul { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_mul_ps(a.data, b.data); return Result; } }; template struct compute_vec_mul { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; #if (GLM_ARCH & GLM_ARCH_AVX_BIT) Result.data = _mm256_mul_pd(a.data, b.data); #else Result.data.setv(0, _mm_mul_pd(a.data.getv(0), b.data.getv(0))); Result.data.setv(1, _mm_mul_pd(a.data.getv(1), b.data.getv(1))); #endif return Result; } }; template struct compute_vec_mul { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; glm_i32vec4 ia = a.data; glm_i32vec4 ib = b.data; #ifdef __SSE4_1__ // modern CPU - use SSE 4.1 Result.data = _mm_mullo_epi32(ia, ib); #else // old CPU - use SSE 2 __m128i tmp1 = _mm_mul_epu32(ia, ib); /* mul 2,0*/ __m128i tmp2 = _mm_mul_epu32(_mm_srli_si128(ia, 4), _mm_srli_si128(ib, 4)); /* mul 3,1 */ Result.data = _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE(0, 0, 2, 0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE(0, 0, 2, 0))); /* shuffle results to [63..0] and pack */ #endif return Result; } }; template struct compute_vec_div { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_div_ps(a.data, b.data); return Result; } }; template struct compute_vec_div { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { #if defined(_MSC_VER) && _MSC_VER >= 1920 //_mm_div_epi32 only defined with VS >= 2019 vec Result; Result.data = _mm_div_epi32(a.data, b.data); return Result; #else return compute_vec_div::call(a, b); #endif } }; // note: div on uninitialized w can generate div by 0 exception template struct compute_vec_div<3, int, Q, true> { GLM_FUNC_QUALIFIER static vec<3, int, Q> call(vec<3, int, Q> const& a, vec<3, int, Q> const& b) { #if defined(_MSC_VER) && _MSC_VER >= 1920 //_mm_div_epi32 only defined with VS >= 2019 vec<3, int, Q> Result; glm_i32vec4 bv = b.data; bv = _mm_shuffle_epi32(bv, _MM_SHUFFLE(0, 2, 1, 0)); Result.data = _mm_div_epi32(a.data, bv); return Result; #else return compute_vec_div<3, int, Q, false>::call(a, b); #endif } }; template struct compute_vec_div { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; # if GLM_ARCH & GLM_ARCH_AVX_BIT Result.data = _mm256_div_pd(a.data, b.data); # else Result.data.setv(0, _mm_div_pd(a.data.getv(0), b.data.getv(0))); Result.data.setv(1, _mm_div_pd(a.data.getv(1), b.data.getv(1))); # endif return Result; } }; template struct compute_vec_div { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_mul_ps(a.data, _mm_rcp_ps(b.data)); return Result; } }; template struct compute_vec_and { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_and_si128(a.data, b.data); return Result; } }; template struct compute_vec_and { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; # if GLM_ARCH & GLM_ARCH_AVX2_BIT Result.data = _mm256_and_si256(a.data, b.data); # elif GLM_ARCH & GLM_ARCH_AVX_BIT Result.data = _mm256_and_pd(_mm256_castpd256_pd128(a.data), _mm256_castpd256_pd128(b.data)); # else Result.data.setv(0, _mm_and_si128(a.data.getv(0), b.data.getv(0))); Result.data.setv(1, _mm_and_si128(a.data.getv(1), b.data.getv(1))); # endif return Result; } }; template struct compute_vec_or { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_or_si128(a.data, b.data); return Result; } }; template struct compute_vec_or { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; # if GLM_ARCH & GLM_ARCH_AVX2_BIT Result.data = _mm256_or_si256(a.data, b.data); # else Result.data.setv(0, _mm_or_si128(a.data.getv(0), b.data.getv(0))); Result.data.setv(1, _mm_or_si128(a.data.getv(1), b.data.getv(1))); # endif return Result; } }; template struct compute_vec_xor { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = _mm_xor_si128(a.data, b.data); return Result; } }; template struct compute_vec_xor { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; # if GLM_ARCH & GLM_ARCH_AVX2_BIT Result.data = _mm256_xor_si256(a.data, b.data); # else Result.data.setv(0, _mm_xor_si128(a.data.getv(0), b.data.getv(0))); Result.data.setv(1, _mm_xor_si128(a.data.getv(1), b.data.getv(1))); # endif return Result; } }; //template //struct compute_vec_shift_left<3, T, Q, -1, 32, true> //{ // GLM_FUNC_QUALIFIER static vec<3, T, Q> call(vec<3, T, Q> const& a, vec<3, T, Q> const& b) // { // vec<3, T, Q> Result; // __m128 v2 = _mm_castsi128_ps(b.data); // v2 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(0, 0, 0, 0)); // note: shift is done with xmm[3] that correspond vec w that doesn't exist on vect3 // _mm_set1_epi64x(_w, _z, _y, _x); // __m128i vr = _mm_sll_epi32(a.data, _mm_castps_si128(v2)); // Result.data = vr; // return Result; // } //}; //template //struct compute_vec_shift_left //{ // GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) // { // vec Result; // Result.data = _mm_sll_epi32(a.data, b.data); // return Result; // } //}; // template // struct compute_vec_shift_left // { // GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) // { // vec Result; //# if GLM_ARCH & GLM_ARCH_AVX2_BIT // Result.data = _mm256_sll_epi64(a.data, b.data); //# else // Result.data.setv(0, _mm_sll_epi64(a.data.getv(0), b.data.getv(0))); // Result.data.setv(1, _mm_sll_epi64(a.data.getv(1), b.data.getv(1))); //# endif // return Result; // } // }; // template // struct compute_vec_shift_right // { // GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) // { // vec Result; // Result.data = _mm_srl_epi32(a.data, b.data); // return Result; // } // }; // // template // struct compute_vec_shift_right // { // GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) // { // vec Result; //# if GLM_ARCH & GLM_ARCH_AVX2_BIT // Result.data = _mm256_srl_epi64(a.data, b.data); //# else // Result.data.setv(0, _mm_srl_epi64(a.data.getv(0), b.data.getv(0))); // Result.data.setv(1, _mm_srl_epi64(a.data.getv(1), b.data.getv(1))); //# endif // return Result; // } // }; template struct compute_vec_bitwise_not { GLM_FUNC_QUALIFIER static vec call(vec const& v) { vec Result; Result.data = _mm_xor_si128(v.data, _mm_set1_epi32(-1)); return Result; } }; template struct compute_vec_bitwise_not { GLM_FUNC_QUALIFIER static vec call(vec const& v) { vec Result; # if GLM_ARCH & GLM_ARCH_AVX2_BIT Result.data = _mm256_xor_si256(v.data, _mm256_set1_epi32(-1)); # else Result.data.setv(0, _mm_xor_si128(v.data.getv(0), _mm_set1_epi32(-1))); Result.data.setv(1, _mm_xor_si128(v.data.getv(1), _mm_set1_epi32(-1))); # endif return Result; } }; template struct compute_vec_equal { GLM_FUNC_QUALIFIER static bool call(vec const& v1, vec const& v2) { return _mm_movemask_ps(_mm_cmpneq_ps(v1.data, v2.data)) == 0; } }; # if GLM_ARCH & GLM_ARCH_SSE41_BIT template struct compute_vec_equal { GLM_FUNC_QUALIFIER static bool call(vec const& v1, vec const& v2) { //return _mm_movemask_epi8(_mm_cmpeq_epi32(v1.data, v2.data)) != 0; __m128i neq = _mm_xor_si128(v1.data, v2.data); return _mm_test_all_zeros(neq, neq) == 0; } }; # endif template struct compute_vec_nequal { GLM_FUNC_QUALIFIER static bool call(vec const& v1, vec const& v2) { return _mm_movemask_ps(_mm_cmpneq_ps(v1.data, v2.data)) != 0; } }; # if GLM_ARCH & GLM_ARCH_SSE41_BIT template struct compute_vec_nequal { GLM_FUNC_QUALIFIER static bool call(vec const& v1, vec const& v2) { //return _mm_movemask_epi8(_mm_cmpneq_epi32(v1.data, v2.data)) != 0; __m128i neq = _mm_xor_si128(v1.data, v2.data); int v = _mm_test_all_zeros(neq, neq); return v != 1; } }; template struct compute_vec_nequal { GLM_FUNC_QUALIFIER static bool call(vec const& v1, vec const& v2) { //return _mm_movemask_epi8(_mm_cmpneq_epi32(v1.data, v2.data)) != 0; __m128i neq = _mm_xor_si128(v1.data, v2.data); return _mm_test_all_zeros(neq, neq) != 1; } }; # else template struct compute_vec_nequal { GLM_FUNC_QUALIFIER static bool call(vec const& v1, vec const& v2) { return compute_vec_nequal::call(v1, v2); } }; # endif }//namespace detail #define CTOR_FLOAT(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(float _s) :\ data(_mm_set1_ps(_s))\ {} #if GLM_ARCH & GLM_ARCH_AVX_BIT # define CTOR_DOUBLE(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(double _s) :\ data(_mm256_set1_pd(_s)){} #define CTOR_DOUBLE4(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(double _x, double _y, double _z, double _w):\ data(_mm256_set_pd(_w, _z, _y, _x)) {} #define CTOR_DOUBLE3(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(double _x, double _y, double _z):\ data(_mm256_set_pd(_z, _z, _y, _x)) {} # define CTOR_INT64(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(detail::int64 _s) :\ data(_mm256_set1_epi64x(_s)){} #define CTOR_DOUBLE_COPY3(L, Q)\ template<>\ template\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, double, Q>::vec(vec<3, double, P> const& v) :\ data(_mm256_setr_pd(v.x, v.y, v.z, v.z)){} #else # define CTOR_DOUBLE(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(double _v) \ {\ data.setv(0, _mm_set1_pd(_v)); \ data.setv(1, _mm_set1_pd(_v)); \ } #define CTOR_DOUBLE4(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(double _x, double _y, double _z, double _w)\ {\ data.setv(0, _mm_setr_pd(_x, _y)); \ data.setv(1, _mm_setr_pd(_z, _w)); \ } #define CTOR_DOUBLE3(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(double _x, double _y, double _z)\ {\ data.setv(0, _mm_setr_pd(_x, _y)); \ data.setv(1, _mm_setr_pd(_z, _z)); \ } # define CTOR_INT64(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(detail::int64 _s) :\ data(_mm256_set1_epi64x(_s)){} #define CTOR_DOUBLE_COPY3(L, Q)\ template<>\ template\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, double, Q>::vec(vec<3, double, P> const& v)\ {\ data.setv(0, _mm_setr_pd(v.x, v.y));\ data.setv(1, _mm_setr_pd(v.z, 1.0));\ } #endif //GLM_ARCH & GLM_ARCH_AVX_BIT #define CTOR_INT(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(int _s) :\ data(_mm_set1_epi32(_s))\ {} #define CTOR_FLOAT4(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(float _x, float _y, float _z, float _w) :\ data(_mm_set_ps(_w, _z, _y, _x))\ {} #define CTOR_FLOAT3(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(float _x, float _y, float _z) :\ data(_mm_set_ps(_z, _z, _y, _x)){} #define CTOR_INT4(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(int _x, int _y, int _z, int _w) :\ data(_mm_set_epi32(_w, _z, _y, _x)){} #define CTOR_INT3(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(int _x, int _y, int _z) :\ data(_mm_set_epi32(_z, _z, _y, _x)){} #define CTOR_VECF_INT4(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(int _x, int _y, int _z, int _w) :\ data(_mm_cvtepi32_ps(_mm_set_epi32(_w, _z, _y, _x)))\ {} #define CTOR_VECF_INT3(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(int _x, int _y, int _z) :\ data(_mm_cvtepi32_ps(_mm_set_epi32(_z, _z, _y, _x)))\ {} #define CTOR_DEFAULT(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec() :\ data(_mm_setzero_ps())\ {} #define CTOR_FLOAT_COPY3(L, Q)\ template<>\ template\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, float, Q>::vec(vec<3, float, P> const& v)\ :data(_mm_set_ps(v.z, v.z, v.y, v.x))\ {} }//namespace glm #endif//GLM_ARCH & GLM_ARCH_SSE2_BIT #if GLM_ARCH & GLM_ARCH_NEON_BIT #if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR // the functions below needs to be properly implemented, use unoptimized function fro now. template struct _swizzle_base1 : public _swizzle_base1{}; template struct _swizzle_base1 : public _swizzle_base1 {}; template struct _swizzle_base1 : public _swizzle_base1 {}; # endif// GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR template struct compute_vec_add { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = vaddq_f32(a.data, b.data); return Result; } }; template struct compute_vec_add { GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) { vec Result; Result.data = vaddq_u32(a.data, b.data); return Result; } }; template struct compute_vec_add { static vec call(vec const& a, vec const& b) { vec Result; Result.data = vaddq_s32(a.data, b.data); return Result; } }; template struct compute_vec_sub { static vec call(vec const& a, vec const& b) { vec Result; Result.data = vsubq_f32(a.data, b.data); return Result; } }; template struct compute_vec_sub { static vec call(vec const& a, vec const& b) { vec Result; Result.data = vsubq_u32(a.data, b.data); return Result; } }; template struct compute_vec_sub { static vec call(vec const& a, vec const& b) { vec Result; Result.data = vsubq_s32(a.data, b.data); return Result; } }; template struct compute_vec_mul { static vec call(vec const& a, vec const& b) { vec Result; Result.data = vmulq_f32(a.data, b.data); return Result; } }; template struct compute_vec_mul { static vec call(vec const& a, vec const& b) { vec Result; Result.data = vmulq_u32(a.data, b.data); return Result; } }; template struct compute_vec_mul { static vec call(vec const& a, vec const& b) { vec Result; Result.data = vmulq_s32(a.data, b.data); return Result; } }; template struct compute_vec_div { static vec call(vec const& a, vec const& b) { vec Result; #if GLM_ARCH & GLM_ARCH_ARMV8_BIT Result.data = vdivq_f32(a.data, b.data); #else /* Arm assembler reference: * * The Newton-Raphson iteration: x[n+1] = x[n] * (2 - d * x[n]) * converges to (1/d) if x0 is the result of VRECPE applied to d. * * Note: The precision usually improves with two interactions, but more than two iterations are not helpful. */ float32x4_t x = vrecpeq_f32(b.data); x = vmulq_f32(vrecpsq_f32(b.data, x), x); x = vmulq_f32(vrecpsq_f32(b.data, x), x); Result.data = vmulq_f32(a.data, x); #endif return Result; } }; template struct compute_vec_equal { static bool call(vec const& v1, vec const& v2) { uint32x4_t cmp = vceqq_f32(v1.data, v2.data); #if GLM_ARCH & GLM_ARCH_ARMV8_BIT cmp = vpminq_u32(cmp, cmp); cmp = vpminq_u32(cmp, cmp); uint32_t r = cmp[0]; #else uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp)); cmpx2 = vpmin_u32(cmpx2, cmpx2); uint32_t r = cmpx2[0]; #endif return r == ~0u; } }; template struct compute_vec_equal { static bool call(vec const& v1, vec const& v2) { uint32x4_t cmp = vceqq_u32(v1.data, v2.data); #if GLM_ARCH & GLM_ARCH_ARMV8_BIT cmp = vpminq_u32(cmp, cmp); cmp = vpminq_u32(cmp, cmp); uint32_t r = cmp[0]; #else uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp)); cmpx2 = vpmin_u32(cmpx2, cmpx2); uint32_t r = cmpx2[0]; #endif return r == ~0u; } }; template struct compute_vec_equal { static bool call(vec const& v1, vec const& v2) { uint32x4_t cmp = vceqq_s32(v1.data, v2.data); #if GLM_ARCH & GLM_ARCH_ARMV8_BIT cmp = vpminq_u32(cmp, cmp); cmp = vpminq_u32(cmp, cmp); uint32_t r = cmp[0]; #else uint32x2_t cmpx2 = vpmin_u32(vget_low_u32(cmp), vget_high_u32(cmp)); cmpx2 = vpmin_u32(cmpx2, cmpx2); uint32_t r = cmpx2[0]; #endif return r == ~0u; } }; template struct compute_vec_nequal { static bool call(vec const& v1, vec const& v2) { return !compute_vec_equal::call(v1, v2); } }; template struct compute_vec_nequal { static bool call(vec const& v1, vec const& v2) { return !compute_vec_equal::call(v1, v2); } }; template struct compute_vec_nequal { static bool call(vec const& v1, vec const& v2) { return !compute_vec_equal::call(v1, v2); } }; #if !GLM_CONFIG_XYZW_ONLY #define CTOR_FLOAT(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(float _s) :\ data(vdupq_n_f32(_s))\ {} #define CTOR_INT(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(int _s) :\ data(vdupq_n_s32(_s))\ {} #define CTOR_UINT(L, Q)\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(uint _s) :\ data(vdupq_n_u32(_s))\ {} #define CTOR_VECF_INT4(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(int _x, int _y, int _z, int _w) :\ data(vcvtq_f32_s32(vec(_x, _y, _z, _w).data))\ {} #define CTOR_VECF_UINT4(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(uint _x, uint _y, uint _z, uint _w) :\ data(vcvtq_f32_u32(vec(_x, _y, _z, _w).data))\ {} #define CTOR_VECF_INT3(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(int _x, int _y, int _z) :\ data(vcvtq_f32_s32(vec(_x, _y, _z).data))\ {} #define CTOR_VECF_UINT4(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(uint _x, uint _y, uint _z, uint _w) :\ data(vcvtq_f32_u32(vec(_x, _y, _z, _w).data))\ {} #define CTOR_VECF_UINT3(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(uint _x, uint _y, uint _z) :\ data(vcvtq_f32_u32(vec(_x, _y, _z).data))\ {} #define CTOR_VECF_VECF(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(const vec& rhs) :\ data(rhs.data)\ {} #define CTOR_VECF_VECI(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(const vec& rhs) :\ data(vcvtq_f32_s32(rhs.data))\ {} #define CTOR_VECF_VECU(L, Q)\ template<>\ template<>\ GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec::vec(const vec& rhs) :\ data(vcvtq_f32_u32(rhs.data))\ {} #endif }//namespace detail }//namespace glm #endif