template <typename SIMD_T> using Integer = typename SIMD_T::Integer;
template <typename SIMD_T> using Vec4 = typename SIMD_T::Vec4;
template <typename SIMD_T> using Mask = typename SIMD_T::Mask;
+
+template <typename SIMD_T>
+struct SIMDVecEqual
+{
+ INLINE bool operator () (Integer<SIMD_T> a, Integer<SIMD_T> b) const
+ {
+ Integer<SIMD_T> c = SIMD_T::xor_si(a, b);
+ return SIMD_T::testz_si(c, c);
+ }
+
+ INLINE bool operator () (Float<SIMD_T> a, Float<SIMD_T> b) const
+ {
+ return this->operator()(SIMD_T::castps_si(a), SIMD_T::castps_si(b));
+ }
+
+ INLINE bool operator () (Double<SIMD_T> a, Double<SIMD_T> b) const
+ {
+ return this->operator()(SIMD_T::castpd_si(a), SIMD_T::castpd_si(b));
+ }
+};
+
+template <typename SIMD_T>
+struct SIMDVecHash
+{
+ INLINE uint32_t operator ()(Integer<SIMD_T> val) const
+ {
+#if defined(_WIN64) || !defined(_WIN32) // assume non-Windows is always 64-bit
+ static_assert(sizeof(void*) == 8, "This path only meant for 64-bit code");
+
+ uint64_t crc32 = 0;
+ const uint64_t *pData = reinterpret_cast<const uint64_t*>(&val);
+ static const uint32_t loopIterations = sizeof(val) / sizeof(void*);
+ static_assert(loopIterations * sizeof(void*) == sizeof(val), "bad vector size");
+
+ for (uint32_t i = 0; i < loopIterations; ++i)
+ {
+ crc32 = _mm_crc32_u64(crc32, pData[i]);
+ }
+
+ return static_cast<uint32_t>(crc32);
+#else
+ static_assert(sizeof(void*) == 4, "This path only meant for 32-bit code");
+
+ uint32_t crc32 = 0;
+ const uint32_t *pData = reinterpret_cast<const uint32_t*>(&val);
+ static const uint32_t loopIterations = sizeof(val) / sizeof(void*);
+ static_assert(loopIterations * sizeof(void*) == sizeof(val), "bad vector size");
+
+ for (uint32_t i = 0; i < loopIterations; ++i)
+ {
+ crc32 = _mm_crc32_u32(crc32, pData[i]);
+ }
+
+ return crc32;
+#endif
+ };
+
+ INLINE uint32_t operator ()(Float<SIMD_T> val) const
+ {
+ return operator()(SIMD_T::castps_si(val));
+ };
+ INLINE uint32_t operator ()(Double<SIMD_T> val) const
+ {
+ return operator()(SIMD_T::castpd_si(val));
+ }
+};