vuint8_avx2.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #define vboolf vboolf_impl
  5. #define vboold vboold_impl
  6. #define vint vint_impl
  7. #define vuint vuint_impl
  8. #define vllong vllong_impl
  9. #define vfloat vfloat_impl
  10. #define vdouble vdouble_impl
  11. namespace embree
  12. {
  13. /* 8-wide AVX integer type */
  14. template<>
  15. struct vuint<8>
  16. {
  17. ALIGNED_STRUCT_(32);
  18. typedef vboolf8 Bool;
  19. typedef vuint8 Int;
  20. typedef vfloat8 Float;
  21. enum { size = 8 }; // number of SIMD elements
  22. union { // data
  23. __m256i v;
  24. unsigned int i[8];
  25. };
  26. ////////////////////////////////////////////////////////////////////////////////
  27. /// Constructors, Assignment & Cast Operators
  28. ////////////////////////////////////////////////////////////////////////////////
  29. __forceinline vuint() {}
  30. __forceinline vuint(const vuint8& a) { v = a.v; }
  31. __forceinline vuint8& operator =(const vuint8& a) { v = a.v; return *this; }
  32. __forceinline vuint(__m256i a) : v(a) {}
  33. __forceinline operator const __m256i&() const { return v; }
  34. __forceinline operator __m256i&() { return v; }
  35. __forceinline explicit vuint(const vuint4& a) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
  36. __forceinline vuint(const vuint4& a, const vuint4& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
  37. __forceinline vuint(const __m128i& a, const __m128i& b) : v(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
  38. __forceinline explicit vuint(const unsigned int* a) : v(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
  39. __forceinline vuint(unsigned int a) : v(_mm256_set1_epi32(a)) {}
  40. __forceinline vuint(unsigned int a, unsigned int b) : v(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
  41. __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d) : v(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
  42. __forceinline vuint(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f, unsigned int g, unsigned int h) : v(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
  43. __forceinline explicit vuint(__m256 a) : v(_mm256_cvtps_epi32(a)) {}
  44. #if defined(__AVX512VL__)
  45. __forceinline explicit vuint(const vboolf8& a) : v(_mm256_movm_epi32(a)) {}
  46. #else
  47. __forceinline explicit vuint(const vboolf8& a) : v(_mm256_castps_si256((__m256)a)) {}
  48. #endif
  49. ////////////////////////////////////////////////////////////////////////////////
  50. /// Constants
  51. ////////////////////////////////////////////////////////////////////////////////
  52. __forceinline vuint(ZeroTy) : v(_mm256_setzero_si256()) {}
  53. __forceinline vuint(OneTy) : v(_mm256_set1_epi32(1)) {}
  54. __forceinline vuint(PosInfTy) : v(_mm256_set1_epi32(pos_inf)) {}
  55. __forceinline vuint(NegInfTy) : v(_mm256_set1_epi32(neg_inf)) {}
  56. __forceinline vuint(StepTy) : v(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
  57. __forceinline vuint(UndefinedTy) : v(_mm256_undefined_si256()) {}
  58. ////////////////////////////////////////////////////////////////////////////////
  59. /// Loads and Stores
  60. ////////////////////////////////////////////////////////////////////////////////
  61. static __forceinline vuint8 load(const unsigned char* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
  62. static __forceinline vuint8 loadu(const unsigned char* ptr) { return _mm256_cvtepu8_epi32(_mm_loadl_epi64((__m128i*)ptr)); }
  63. static __forceinline vuint8 load(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_load_si128((__m128i*)ptr)); }
  64. static __forceinline vuint8 loadu(const unsigned short* ptr) { return _mm256_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr)); }
  65. static __forceinline vuint8 load(const void* ptr) { return _mm256_load_si256((__m256i*)ptr); }
  66. static __forceinline vuint8 loadu(const void* ptr) { return _mm256_loadu_si256((__m256i*)ptr); }
  67. static __forceinline void store (void* ptr, const vuint8& v) { _mm256_store_si256((__m256i*)ptr,v); }
  68. static __forceinline void storeu(void* ptr, const vuint8& v) { _mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(v)); }
  69. #if defined(__AVX512VL__)
  70. static __forceinline vuint8 compact(const vboolf8& mask, vuint8 &v) {
  71. return _mm256_mask_compress_epi32(v, mask, v);
  72. }
  73. static __forceinline vuint8 compact(const vboolf8& mask, vuint8 &a, const vuint8& b) {
  74. return _mm256_mask_compress_epi32(a, mask, b);
  75. }
  76. static __forceinline vuint8 load (const vboolf8& mask, const void* ptr) { return _mm256_mask_load_epi32 (_mm256_setzero_si256(),mask,ptr); }
  77. static __forceinline vuint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_mask_loadu_epi32(_mm256_setzero_si256(),mask,ptr); }
  78. static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_mask_store_epi32 (ptr,mask,v); }
  79. static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_mask_storeu_epi32(ptr,mask,v); }
  80. #else
  81. static __forceinline vuint8 load (const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
  82. static __forceinline vuint8 loadu(const vboolf8& mask, const void* ptr) { return _mm256_castps_si256(_mm256_maskload_ps((float*)ptr,mask)); }
  83. static __forceinline void store (const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
  84. static __forceinline void storeu(const vboolf8& mask, void* ptr, const vuint8& v) { _mm256_maskstore_epi32((int*)ptr,mask,v); }
  85. #endif
  86. static __forceinline vuint8 load_nt(void* ptr) {
  87. return _mm256_stream_load_si256((__m256i*)ptr);
  88. }
  89. static __forceinline void store_nt(void* ptr, const vuint8& v) {
  90. _mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
  91. }
  92. static __forceinline void store(unsigned char* ptr, const vuint8& i)
  93. {
  94. for (size_t j=0; j<8; j++)
  95. ptr[j] = i[j];
  96. }
  97. static __forceinline void store(unsigned short* ptr, const vuint8& v) {
  98. for (size_t i=0;i<8;i++)
  99. ptr[i] = (unsigned short)v[i];
  100. }
  101. template<int scale = 4>
  102. static __forceinline vuint8 gather(const unsigned int *const ptr, const vint8& index) {
  103. return _mm256_i32gather_epi32((const int*) ptr, index, scale);
  104. }
  105. template<int scale = 4>
  106. static __forceinline vuint8 gather(const vboolf8& mask, const unsigned int *const ptr, const vint8& index) {
  107. vuint8 r = zero;
  108. #if defined(__AVX512VL__)
  109. return _mm256_mmask_i32gather_epi32(r, mask, index, (const int*) ptr, scale);
  110. #else
  111. return _mm256_mask_i32gather_epi32(r, (const int*) ptr, index, mask, scale);
  112. #endif
  113. }
  114. template<int scale = 4>
  115. static __forceinline void scatter(void* ptr, const vint8& ofs, const vuint8& v)
  116. {
  117. #if defined(__AVX512VL__)
  118. _mm256_i32scatter_epi32((int*)ptr, ofs, v, scale);
  119. #else
  120. *(unsigned int*)(((char*)ptr)+scale*ofs[0]) = v[0];
  121. *(unsigned int*)(((char*)ptr)+scale*ofs[1]) = v[1];
  122. *(unsigned int*)(((char*)ptr)+scale*ofs[2]) = v[2];
  123. *(unsigned int*)(((char*)ptr)+scale*ofs[3]) = v[3];
  124. *(unsigned int*)(((char*)ptr)+scale*ofs[4]) = v[4];
  125. *(unsigned int*)(((char*)ptr)+scale*ofs[5]) = v[5];
  126. *(unsigned int*)(((char*)ptr)+scale*ofs[6]) = v[6];
  127. *(unsigned int*)(((char*)ptr)+scale*ofs[7]) = v[7];
  128. #endif
  129. }
  130. template<int scale = 4>
  131. static __forceinline void scatter(const vboolf8& mask, void* ptr, const vint8& ofs, const vuint8& v)
  132. {
  133. #if defined(__AVX512VL__)
  134. _mm256_mask_i32scatter_epi32((int*)ptr, mask, ofs, v, scale);
  135. #else
  136. if (likely(mask[0])) *(unsigned int*)(((char*)ptr)+scale*ofs[0]) = v[0];
  137. if (likely(mask[1])) *(unsigned int*)(((char*)ptr)+scale*ofs[1]) = v[1];
  138. if (likely(mask[2])) *(unsigned int*)(((char*)ptr)+scale*ofs[2]) = v[2];
  139. if (likely(mask[3])) *(unsigned int*)(((char*)ptr)+scale*ofs[3]) = v[3];
  140. if (likely(mask[4])) *(unsigned int*)(((char*)ptr)+scale*ofs[4]) = v[4];
  141. if (likely(mask[5])) *(unsigned int*)(((char*)ptr)+scale*ofs[5]) = v[5];
  142. if (likely(mask[6])) *(unsigned int*)(((char*)ptr)+scale*ofs[6]) = v[6];
  143. if (likely(mask[7])) *(unsigned int*)(((char*)ptr)+scale*ofs[7]) = v[7];
  144. #endif
  145. }
  146. static __forceinline vuint8 broadcast64(const long long &a) { return _mm256_set1_epi64x(a); }
  147. ////////////////////////////////////////////////////////////////////////////////
  148. /// Array Access
  149. ////////////////////////////////////////////////////////////////////////////////
  150. __forceinline const unsigned int& operator [](size_t index) const { assert(index < 8); return i[index]; }
  151. __forceinline unsigned int& operator [](size_t index) { assert(index < 8); return i[index]; }
  152. };
  153. ////////////////////////////////////////////////////////////////////////////////
  154. /// Unary Operators
  155. ////////////////////////////////////////////////////////////////////////////////
  156. #if defined(__AVX512VL__)
  157. __forceinline vboolf8 asBool(const vuint8& a) { return _mm256_movepi32_mask(a); }
  158. #else
  159. __forceinline vboolf8 asBool(const vuint8& a) { return _mm256_castsi256_ps(a); }
  160. #endif
  161. __forceinline vuint8 operator +(const vuint8& a) { return a; }
  162. ////////////////////////////////////////////////////////////////////////////////
  163. /// Binary Operators
  164. ////////////////////////////////////////////////////////////////////////////////
  165. __forceinline vuint8 operator +(const vuint8& a, const vuint8& b) { return _mm256_add_epi32(a, b); }
  166. __forceinline vuint8 operator +(const vuint8& a, unsigned int b) { return a + vuint8(b); }
  167. __forceinline vuint8 operator +(unsigned int a, const vuint8& b) { return vuint8(a) + b; }
  168. __forceinline vuint8 operator -(const vuint8& a, const vuint8& b) { return _mm256_sub_epi32(a, b); }
  169. __forceinline vuint8 operator -(const vuint8& a, unsigned int b) { return a - vuint8(b); }
  170. __forceinline vuint8 operator -(unsigned int a, const vuint8& b) { return vuint8(a) - b; }
  171. //__forceinline vuint8 operator *(const vuint8& a, const vuint8& b) { return _mm256_mullo_epu32(a, b); }
  172. //__forceinline vuint8 operator *(const vuint8& a, unsigned int b) { return a * vuint8(b); }
  173. //__forceinline vuint8 operator *(unsigned int a, const vuint8& b) { return vuint8(a) * b; }
  174. __forceinline vuint8 operator &(const vuint8& a, const vuint8& b) { return _mm256_and_si256(a, b); }
  175. __forceinline vuint8 operator &(const vuint8& a, unsigned int b) { return a & vuint8(b); }
  176. __forceinline vuint8 operator &(unsigned int a, const vuint8& b) { return vuint8(a) & b; }
  177. __forceinline vuint8 operator |(const vuint8& a, const vuint8& b) { return _mm256_or_si256(a, b); }
  178. __forceinline vuint8 operator |(const vuint8& a, unsigned int b) { return a | vuint8(b); }
  179. __forceinline vuint8 operator |(unsigned int a, const vuint8& b) { return vuint8(a) | b; }
  180. __forceinline vuint8 operator ^(const vuint8& a, const vuint8& b) { return _mm256_xor_si256(a, b); }
  181. __forceinline vuint8 operator ^(const vuint8& a, unsigned int b) { return a ^ vuint8(b); }
  182. __forceinline vuint8 operator ^(unsigned int a, const vuint8& b) { return vuint8(a) ^ b; }
  183. __forceinline vuint8 operator <<(const vuint8& a, unsigned int n) { return _mm256_slli_epi32(a, n); }
  184. __forceinline vuint8 operator >>(const vuint8& a, unsigned int n) { return _mm256_srli_epi32(a, n); }
  185. __forceinline vuint8 operator <<(const vuint8& a, const vuint8& n) { return _mm256_sllv_epi32(a, n); }
  186. __forceinline vuint8 operator >>(const vuint8& a, const vuint8& n) { return _mm256_srlv_epi32(a, n); }
  187. __forceinline vuint8 sll(const vuint8& a, unsigned int b) { return _mm256_slli_epi32(a, b); }
  188. __forceinline vuint8 sra(const vuint8& a, unsigned int b) { return _mm256_srai_epi32(a, b); }
  189. __forceinline vuint8 srl(const vuint8& a, unsigned int b) { return _mm256_srli_epi32(a, b); }
  190. __forceinline vuint8 sll(const vuint8& a, const vuint8& b) { return _mm256_sllv_epi32(a, b); }
  191. __forceinline vuint8 sra(const vuint8& a, const vuint8& b) { return _mm256_srav_epi32(a, b); }
  192. __forceinline vuint8 srl(const vuint8& a, const vuint8& b) { return _mm256_srlv_epi32(a, b); }
  193. __forceinline vuint8 min(const vuint8& a, const vuint8& b) { return _mm256_min_epu32(a, b); }
  194. __forceinline vuint8 min(const vuint8& a, unsigned int b) { return min(a,vuint8(b)); }
  195. __forceinline vuint8 min(unsigned int a, const vuint8& b) { return min(vuint8(a),b); }
  196. __forceinline vuint8 max(const vuint8& a, const vuint8& b) { return _mm256_max_epu32(a, b); }
  197. __forceinline vuint8 max(const vuint8& a, unsigned int b) { return max(a,vuint8(b)); }
  198. __forceinline vuint8 max(unsigned int a, const vuint8& b) { return max(vuint8(a),b); }
  199. ////////////////////////////////////////////////////////////////////////////////
  200. /// Assignment Operators
  201. ////////////////////////////////////////////////////////////////////////////////
  202. __forceinline vuint8& operator +=(vuint8& a, const vuint8& b) { return a = a + b; }
  203. __forceinline vuint8& operator +=(vuint8& a, unsigned int b) { return a = a + b; }
  204. __forceinline vuint8& operator -=(vuint8& a, const vuint8& b) { return a = a - b; }
  205. __forceinline vuint8& operator -=(vuint8& a, unsigned int b) { return a = a - b; }
  206. //__forceinline vuint8& operator *=(vuint8& a, const vuint8& b) { return a = a * b; }
  207. //__forceinline vuint8& operator *=(vuint8& a, unsigned int b) { return a = a * b; }
  208. __forceinline vuint8& operator &=(vuint8& a, const vuint8& b) { return a = a & b; }
  209. __forceinline vuint8& operator &=(vuint8& a, unsigned int b) { return a = a & b; }
  210. __forceinline vuint8& operator |=(vuint8& a, const vuint8& b) { return a = a | b; }
  211. __forceinline vuint8& operator |=(vuint8& a, unsigned int b) { return a = a | b; }
  212. __forceinline vuint8& operator <<=(vuint8& a, const unsigned int b) { return a = a << b; }
  213. __forceinline vuint8& operator >>=(vuint8& a, const unsigned int b) { return a = a >> b; }
  214. ////////////////////////////////////////////////////////////////////////////////
  215. /// Comparison Operators + Select
  216. ////////////////////////////////////////////////////////////////////////////////
  217. #if defined(__AVX512VL__)
  218. __forceinline vboolf8 operator ==(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_EQ); }
  219. __forceinline vboolf8 operator !=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_NE); }
  220. __forceinline vboolf8 operator < (const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_LT); }
  221. __forceinline vboolf8 operator >=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_GE); }
  222. __forceinline vboolf8 operator > (const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_GT); }
  223. __forceinline vboolf8 operator <=(const vuint8& a, const vuint8& b) { return _mm256_cmp_epu32_mask(a,b,_MM_CMPINT_LE); }
  224. __forceinline vuint8 select(const vboolf8& m, const vuint8& t, const vuint8& f) {
  225. return _mm256_mask_blend_epi32(m, (__m256i)f, (__m256i)t);
  226. }
  227. #else
  228. __forceinline vboolf8 operator ==(const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b)); }
  229. __forceinline vboolf8 operator !=(const vuint8& a, const vuint8& b) { return !(a == b); }
  230. //__forceinline vboolf8 operator < (const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epu32(b, a)); }
  231. //__forceinline vboolf8 operator >=(const vuint8& a, const vuint8& b) { return !(a < b); }
  232. //__forceinline vboolf8 operator > (const vuint8& a, const vuint8& b) { return _mm256_castsi256_ps(_mm256_cmpgt_epu32(a, b)); }
  233. //__forceinline vboolf8 operator <=(const vuint8& a, const vuint8& b) { return !(a > b); }
  234. __forceinline vuint8 select(const vboolf8& m, const vuint8& t, const vuint8& f) {
  235. return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
  236. }
  237. #endif
  238. template<int mask>
  239. __forceinline vuint8 select(const vuint8& t, const vuint8& f) {
  240. return _mm256_blend_epi32(f, t, mask);
  241. }
  242. __forceinline vboolf8 operator ==(const vuint8& a, unsigned int b) { return a == vuint8(b); }
  243. __forceinline vboolf8 operator ==(unsigned int a, const vuint8& b) { return vuint8(a) == b; }
  244. __forceinline vboolf8 operator !=(const vuint8& a, unsigned int b) { return a != vuint8(b); }
  245. __forceinline vboolf8 operator !=(unsigned int a, const vuint8& b) { return vuint8(a) != b; }
  246. //__forceinline vboolf8 operator < (const vuint8& a, unsigned int b) { return a < vuint8(b); }
  247. //__forceinline vboolf8 operator < (unsigned int a, const vuint8& b) { return vuint8(a) < b; }
  248. //__forceinline vboolf8 operator >=(const vuint8& a, unsigned int b) { return a >= vuint8(b); }
  249. //__forceinline vboolf8 operator >=(unsigned int a, const vuint8& b) { return vuint8(a) >= b; }
  250. //__forceinline vboolf8 operator > (const vuint8& a, unsigned int b) { return a > vuint8(b); }
  251. //__forceinline vboolf8 operator > (unsigned int a, const vuint8& b) { return vuint8(a) > b; }
  252. //__forceinline vboolf8 operator <=(const vuint8& a, unsigned int b) { return a <= vuint8(b); }
  253. //__forceinline vboolf8 operator <=(unsigned int a, const vuint8& b) { return vuint8(a) <= b; }
  254. __forceinline vboolf8 eq(const vuint8& a, const vuint8& b) { return a == b; }
  255. __forceinline vboolf8 ne(const vuint8& a, const vuint8& b) { return a != b; }
  256. //__forceinline vboolf8 lt(const vuint8& a, const vuint8& b) { return a < b; }
  257. //__forceinline vboolf8 ge(const vuint8& a, const vuint8& b) { return a >= b; }
  258. //__forceinline vboolf8 gt(const vuint8& a, const vuint8& b) { return a > b; }
  259. //__forceinline vboolf8 le(const vuint8& a, const vuint8& b) { return a <= b; }
  260. #if defined(__AVX512VL__)
  261. __forceinline vboolf8 eq(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_EQ); }
  262. __forceinline vboolf8 ne(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_NE); }
  263. __forceinline vboolf8 lt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LT); }
  264. __forceinline vboolf8 ge(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GE); }
  265. __forceinline vboolf8 gt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_GT); }
  266. __forceinline vboolf8 le(const vboolf8& mask, const vuint8& a, const vuint8& b) { return _mm256_mask_cmp_epu32_mask(mask, a, b, _MM_CMPINT_LE); }
  267. #else
  268. __forceinline vboolf8 eq(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a == b); }
  269. __forceinline vboolf8 ne(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a != b); }
  270. //__forceinline vboolf8 lt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a < b); }
  271. //__forceinline vboolf8 ge(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a >= b); }
  272. //__forceinline vboolf8 gt(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a > b); }
  273. //__forceinline vboolf8 le(const vboolf8& mask, const vuint8& a, const vuint8& b) { return mask & (a <= b); }
  274. #endif
  275. ////////////////////////////////////////////////////////////////////////////////
  276. /// Movement/Shifting/Shuffling Functions
  277. ////////////////////////////////////////////////////////////////////////////////
  278. __forceinline vuint8 unpacklo(const vuint8& a, const vuint8& b) { return _mm256_unpacklo_epi32(a, b); }
  279. __forceinline vuint8 unpackhi(const vuint8& a, const vuint8& b) { return _mm256_unpackhi_epi32(a, b); }
  280. template<int i>
  281. __forceinline vuint8 shuffle(const vuint8& v) {
  282. return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i, i, i, i)));
  283. }
  284. template<int i0, int i1>
  285. __forceinline vuint8 shuffle4(const vuint8& v) {
  286. return _mm256_permute2f128_si256(v, v, (i1 << 4) | (i0 << 0));
  287. }
  288. template<int i0, int i1>
  289. __forceinline vuint8 shuffle4(const vuint8& a, const vuint8& b) {
  290. return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
  291. }
  292. template<int i0, int i1, int i2, int i3>
  293. __forceinline vuint8 shuffle(const vuint8& v) {
  294. return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(v), _MM_SHUFFLE(i3, i2, i1, i0)));
  295. }
  296. template<int i0, int i1, int i2, int i3>
  297. __forceinline vuint8 shuffle(const vuint8& a, const vuint8& b) {
  298. return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
  299. }
  300. template<> __forceinline vuint8 shuffle<0, 0, 2, 2>(const vuint8& v) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(v))); }
  301. template<> __forceinline vuint8 shuffle<1, 1, 3, 3>(const vuint8& v) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(v))); }
  302. template<> __forceinline vuint8 shuffle<0, 1, 0, 1>(const vuint8& v) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(v))))); }
  303. template<int i> __forceinline vuint8 insert4(const vuint8& a, const vuint4& b) { return _mm256_insertf128_si256(a, b, i); }
  304. template<int i> __forceinline vuint4 extract4(const vuint8& a) { return _mm256_extractf128_si256(a, i); }
  305. template<> __forceinline vuint4 extract4<0>(const vuint8& a) { return _mm256_castsi256_si128(a); }
  306. __forceinline int toScalar(const vuint8& v) { return _mm_cvtsi128_si32(_mm256_castsi256_si128(v)); }
  307. __forceinline vuint8 permute(const vuint8& v, const __m256i& index) {
  308. return _mm256_permutevar8x32_epi32(v, index);
  309. }
  310. __forceinline vuint8 shuffle(const vuint8& v, const __m256i& index) {
  311. return _mm256_castps_si256(_mm256_permutevar_ps(_mm256_castsi256_ps(v), index));
  312. }
  313. template<int i>
  314. __forceinline vuint8 align_shift_right(const vuint8& a, const vuint8& b) {
  315. #if defined(__AVX512VL__)
  316. return _mm256_alignr_epi32(a, b, i);
  317. #else
  318. return _mm256_alignr_epi8(a, b, 4*i);
  319. #endif
  320. }
  321. ////////////////////////////////////////////////////////////////////////////////
  322. /// Reductions
  323. ////////////////////////////////////////////////////////////////////////////////
  324. //__forceinline vuint8 vreduce_min2(const vuint8& v) { return min(v,shuffle<1,0,3,2>(v)); }
  325. //__forceinline vuint8 vreduce_min4(const vuint8& v) { vuint8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
  326. //__forceinline vuint8 vreduce_min (const vuint8& v) { vuint8 v1 = vreduce_min4(v); return min(v1,shuffle4<1,0>(v1)); }
  327. //__forceinline vuint8 vreduce_max2(const vuint8& v) { return max(v,shuffle<1,0,3,2>(v)); }
  328. //__forceinline vuint8 vreduce_max4(const vuint8& v) { vuint8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
  329. //__forceinline vuint8 vreduce_max (const vuint8& v) { vuint8 v1 = vreduce_max4(v); return max(v1,shuffle4<1,0>(v1)); }
  330. __forceinline vuint8 vreduce_add2(const vuint8& v) { return v + shuffle<1,0,3,2>(v); }
  331. __forceinline vuint8 vreduce_add4(const vuint8& v) { vuint8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
  332. __forceinline vuint8 vreduce_add (const vuint8& v) { vuint8 v1 = vreduce_add4(v); return v1 + shuffle4<1,0>(v1); }
  333. //__forceinline int reduce_min(const vuint8& v) { return toScalar(vreduce_min(v)); }
  334. //__forceinline int reduce_max(const vuint8& v) { return toScalar(vreduce_max(v)); }
  335. __forceinline int reduce_add(const vuint8& v) { return toScalar(vreduce_add(v)); }
  336. //__forceinline size_t select_min(const vuint8& v) { return bsf(movemask(v == vreduce_min(v))); }
  337. //__forceinline size_t select_max(const vuint8& v) { return bsf(movemask(v == vreduce_max(v))); }
  338. //__forceinline size_t select_min(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(pos_inf)); return bsf(movemask(valid & (a == vreduce_min(a)))); }
  339. //__forceinline size_t select_max(const vboolf8& valid, const vuint8& v) { const vuint8 a = select(valid,v,vuint8(neg_inf)); return bsf(movemask(valid & (a == vreduce_max(a)))); }
  340. ////////////////////////////////////////////////////////////////////////////////
  341. /// Output Operators
  342. ////////////////////////////////////////////////////////////////////////////////
  343. __forceinline embree_ostream operator <<(embree_ostream cout, const vuint8& a) {
  344. return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
  345. }
  346. }
  347. #undef vboolf
  348. #undef vboold
  349. #undef vint
  350. #undef vuint
  351. #undef vllong
  352. #undef vfloat
  353. #undef vdouble