1 #pragma once
2
3 #ifndef SIMD_FUNCTIONS_H
4 #define SIMD_FUNCTIONS_H
5
6 #if defined(_MSC_VER) && !defined(__clang__)
7 #include <intrin.h>
8 #else
9 #include <emmintrin.h>
10 #include <xmmintrin.h>
11 #include <immintrin.h>
12 #include <stdint.h>
13
14 #if defined(__clang_major__) && !defined(__apple_build_version__) && __clang_major__ >= 8
15 # define Y_HAVE_NEW_INTRINSICS
16 #endif
17
18 #if !defined(Y_HAVE_NEW_INTRINSICS)
19 static __inline__ __m128i
_mm_loadu_si32(void const * __a)20 _mm_loadu_si32(void const* __a) {
21 struct __loadu_si32 {
22 int __v;
23 } __attribute__((__packed__, __may_alias__));
24 int __u = ((struct __loadu_si32*)__a)->__v;
25 return __extension__(__m128i)(__v4si){__u, 0, 0, 0};
26 }
27 #endif
28
29 #if !defined(__clang__) && __GNUC__ < 9
30 static __inline__ __m128i
_mm_loadu_si64(void const * __a)31 _mm_loadu_si64(void const* __a) {
32 struct __loadu_si64 {
33 long long __v;
34 } __attribute__((__packed__, __may_alias__));
35 long long __u = ((struct __loadu_si64*)__a)->__v;
36 return (__m128i){__u, 0L};
37 }
38 #endif
39
40 #if !defined(Y_HAVE_NEW_INTRINSICS)
41 static __inline__ void
_mm_storeu_si32(void const * __p,__m128i __b)42 _mm_storeu_si32(void const* __p, __m128i __b) {
43 struct __storeu_si32 {
44 int __v;
45 } __attribute__((__packed__, __may_alias__));
46 ((struct __storeu_si32*)__p)->__v = ((__v4si)__b)[0];
47 }
48
49 static __inline__ void
_mm_storeu_si64(void const * __p,__m128i __b)50 _mm_storeu_si64(void const* __p, __m128i __b) {
51 struct __storeu_si64 {
52 long long __v;
53 } __attribute__((__packed__, __may_alias__));
54 ((struct __storeu_si64*)__p)->__v = ((__v2di)__b)[0];
55 }
56
57 static __inline__ void
_mm_storeu_si16(void const * __p,__m128i __b)58 _mm_storeu_si16(void const* __p, __m128i __b) {
59 struct __storeu_si16 {
60 short __v;
61 } __attribute__((__packed__, __may_alias__));
62 ((struct __storeu_si16*)__p)->__v = ((__v8hi)__b)[0];
63 }
64 #endif
65 #endif
66
67 #ifdef _MSC_VER
68 #define FORCE_INLINE __forceinline
69 #else
70 #define FORCE_INLINE __attribute__((always_inline)) inline
71 #endif
72
73 #ifdef _MSC_VER
74 #include <stdint.h>
75 #endif
76
77 namespace NFastOps {
78 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
79 // Function returns a ymm register with all floats set to 1.f
80 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
YMMOneFloat()81 FORCE_INLINE __m256 YMMOneFloat() noexcept {
82 return _mm256_set1_ps(1.f);
83 }
YMMOneFloatSI()84 FORCE_INLINE __m256i YMMOneFloatSI() noexcept {
85 return _mm256_castps_si256(YMMOneFloat());
86 }
YMMOneDouble()87 FORCE_INLINE __m256d YMMOneDouble() noexcept {
88 return _mm256_set1_pd(1.);
89 }
YMMOneDoubleSI()90 FORCE_INLINE __m256i YMMOneDoubleSI() noexcept {
91 return _mm256_castpd_si256(YMMOneDouble());
92 }
93
94 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
95 // Function calculates horizontal sum of the YMM register. Assumes floats are stored.
96 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SumYMM(__m128 x)97 FORCE_INLINE __m128 SumYMM(__m128 x) noexcept {
98 const __m128 hi_dual = _mm_movehl_ps(x, x);
99 const __m128 sum_dual = _mm_add_ps(x, hi_dual);
100 const __m128 hi = _mm_shuffle_ps(sum_dual, sum_dual, 0x1);
101 return _mm_add_ss(sum_dual, hi);
102 }
SumYMM(__m256 x)103 FORCE_INLINE __m128 SumYMM(__m256 x) noexcept {
104 const __m128 hi_quad = _mm256_extractf128_ps(x, 1); // hi_quad = ( x7, x6, x5, x4 )
105 return SumYMM(_mm_add_ps(_mm256_castps256_ps128(x), hi_quad));
106 }
SumYMMR(__m128 x)107 FORCE_INLINE float SumYMMR(__m128 x) noexcept {
108 return _mm_cvtss_f32(SumYMM(x));
109 }
SumYMMR(__m256 x)110 FORCE_INLINE float SumYMMR(__m256 x) noexcept {
111 return _mm_cvtss_f32(SumYMM(x));
112 }
113
SumYMM(__m128d x)114 FORCE_INLINE __m128d SumYMM(__m128d x) noexcept {
115 const __m128d hi_dual = _mm_castps_pd(_mm_movehl_ps(_mm_castpd_ps(x), _mm_castpd_ps(x)));
116 return _mm_add_sd(x, hi_dual);
117 }
SumYMM(__m256d x)118 FORCE_INLINE __m128d SumYMM(__m256d x) noexcept {
119 const __m128d hi_quad = _mm256_extractf128_pd(x, 1);
120 return SumYMM(_mm_add_pd(_mm256_castpd256_pd128(x), hi_quad));
121 }
SumYMMR(__m128d x)122 FORCE_INLINE double SumYMMR(__m128d x) noexcept {
123 return _mm_cvtsd_f64(SumYMM(x));
124 }
SumYMMR(__m256d x)125 FORCE_INLINE double SumYMMR(__m256d x) noexcept {
126 return _mm_cvtsd_f64(SumYMM(x));
127 }
128
129 //#######################################################################################################################################################################
130 // Macro - no other good way :-(
131 #define OPERATE_SEPARATELY_I(op, v, param) \
132 _mm256_permute2f128_si256(_mm256_castsi128_si256(op(_mm256_castsi256_si128(v), param)), _mm256_castsi128_si256(op(_mm256_extractf128_si256(v, 1), param)), 32);
133
134 #define OPERATE_ELEMENTWISE_I(op, v1, v2) \
135 _mm256_permute2f128_si256( \
136 _mm256_castsi128_si256(op(_mm256_castsi256_si128(v1), _mm256_castsi256_si128(v2))), \
137 _mm256_castsi128_si256(op(_mm256_extractf128_si256(v1, 1), _mm256_extractf128_si256(v2, 1))), \
138 32);
139
140 #define FMADD_NO_AVX2() \
141 FORCE_INLINE static t_f FMADD(t_f v1, t_f v2, t_f v3) { \
142 return Add(Mul(v1, v2), v3); \
143 } \
144 FORCE_INLINE static t_f FMSUB(t_f v1, t_f v2, t_f v3) { \
145 return Sub(Mul(v1, v2), v3); \
146 } \
147 FORCE_INLINE static t_f FNMADD(t_f v1, t_f v2, t_f v3) { \
148 return Sub(v3, Mul(v1, v2)); \
149 }
150
151 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
152 // These functions only work for inputs in the range: [-2^51, 2^51]
153 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
double_to_int64(__m128d x)154 FORCE_INLINE __m128i double_to_int64(__m128d x) {
155 const __m256d magic_cvt_c = _mm256_set1_pd(0x0018000000000000);
156 x = _mm_add_pd(x, _mm256_castpd256_pd128(magic_cvt_c));
157 return _mm_sub_epi64(_mm_castpd_si128(x), _mm_castpd_si128(_mm256_castpd256_pd128(magic_cvt_c)));
158 }
double_to_int64(__m256d x)159 FORCE_INLINE __m256i double_to_int64(__m256d x) {
160 const __m256d magic_cvt_c = _mm256_set1_pd(0x0018000000000000);
161 x = _mm256_add_pd(x, magic_cvt_c);
162 #ifndef NO_AVX2
163 return _mm256_sub_epi64(_mm256_castpd_si256(x), _mm256_castpd_si256(magic_cvt_c));
164 #else
165 return OPERATE_SEPARATELY_I(_mm_sub_epi64, _mm256_castpd_si256(x), _mm256_castsi256_si128(_mm256_castpd_si256(magic_cvt_c)));
166 #endif
167 }
i64o_double(__m128i x)168 FORCE_INLINE __m128d i64o_double(__m128i x) {
169 const __m256d magic_cvt_c = _mm256_set1_pd(0x0018000000000000);
170 x = _mm_add_epi64(x, _mm_castpd_si128(_mm256_castpd256_pd128(magic_cvt_c)));
171 return _mm_sub_pd(_mm_castsi128_pd(x), _mm256_castpd256_pd128(magic_cvt_c));
172 }
i64o_double(__m256i x)173 FORCE_INLINE __m256d i64o_double(__m256i x) {
174 const __m256d magic_cvt_c = _mm256_set1_pd(0x0018000000000000);
175 #ifndef NO_AVX2
176 x = _mm256_add_epi64(x, _mm256_castpd_si256(magic_cvt_c));
177 #else
178 x = OPERATE_SEPARATELY_I(_mm_add_epi64, x, _mm256_castsi256_si128(_mm256_castpd_si256(magic_cvt_c)));
179 #endif
180 return _mm256_sub_pd(_mm256_castsi256_pd(x), magic_cvt_c);
181 }
182
183 //#######################################################################################################################################################################
184
185 template <size_t I_NOfElements, size_t I_ElemSize>
186 struct S_SIMDV;
187
188 struct S_SIMDSmallBaseF {
189 using t_i = __m128i;
190 using t_f = __m128;
191 using t_base_type = float;
192 //using t_type_d = __m128d;
193
CastS_SIMDSmallBaseF194 FORCE_INLINE static t_i Cast(__m256i v) noexcept {
195 return _mm256_castsi256_si128(v);
196 }
CastS_SIMDSmallBaseF197 FORCE_INLINE static t_f Cast(__m256 v) noexcept {
198 return _mm256_castps256_ps128(v);
199 }
200 //FORCE_INLINE static t_type_d Cast(__m256d v) noexcept { return _mm256_castpd256_pd128(v); }
CastS_SIMDSmallBaseF201 FORCE_INLINE static t_i Cast(t_i v) noexcept {
202 return v;
203 }
CastS_SIMDSmallBaseF204 FORCE_INLINE static t_f Cast(t_f v) noexcept {
205 return v;
206 }
207 //FORCE_INLINE static t_type_d Cast(t_type_d v) noexcept { return v; }
208
209 ///////////////////////////////////////////////////////////////////////////////////////////////////////
210
SetZeroIS_SIMDSmallBaseF211 FORCE_INLINE static t_i SetZeroI() {
212 return _mm_setzero_si128();
213 }
SetZeroFS_SIMDSmallBaseF214 FORCE_INLINE static t_f SetZeroF() {
215 return _mm_setzero_ps();
216 }
Set1S_SIMDSmallBaseF217 FORCE_INLINE static t_f Set1(float v) {
218 return _mm_set1_ps(v);
219 }
SetS_SIMDSmallBaseF220 FORCE_INLINE static t_f Set(float v1, float v2, float v3, float v4) {
221 return _mm_set_ps(v1, v2, v3, v4);
222 }
Set1S_SIMDSmallBaseF223 FORCE_INLINE static t_i Set1(int v) {
224 return _mm_set1_epi32(v);
225 }
SetS_SIMDSmallBaseF226 FORCE_INLINE static t_i Set(int v1, int v2, int v3, int v4) {
227 return _mm_set_epi32(v1, v2, v3, v4);
228 }
229
CastIS_SIMDSmallBaseF230 FORCE_INLINE static t_i CastI(t_f v) {
231 return _mm_castps_si128(v);
232 }
CastFS_SIMDSmallBaseF233 FORCE_INLINE static t_f CastF(t_i v) {
234 return _mm_castsi128_ps(v);
235 }
CVTI2FS_SIMDSmallBaseF236 FORCE_INLINE static t_f CVTI2F(t_i v) {
237 return _mm_cvtepi32_ps(v);
238 }
CVTF2IS_SIMDSmallBaseF239 FORCE_INLINE static t_i CVTF2I(t_f v) {
240 return _mm_cvtps_epi32(v);
241 }
242
CmpEqIS_SIMDSmallBaseF243 FORCE_INLINE static t_i CmpEqI(t_i v1, t_i v2) {
244 return _mm_cmpeq_epi32(v1, v2);
245 }
SRLIS_SIMDSmallBaseF246 FORCE_INLINE static t_i SRLI(t_i v, int i) {
247 return _mm_srli_epi32(v, i);
248 }
SLLIS_SIMDSmallBaseF249 FORCE_INLINE static t_i SLLI(t_i v, int i) {
250 return _mm_slli_epi32(v, i);
251 }
SRAI32S_SIMDSmallBaseF252 FORCE_INLINE static t_i SRAI32(t_i v, int i) {
253 return _mm_srai_epi32(v, i);
254 }
255
TestCFS_SIMDSmallBaseF256 FORCE_INLINE static int TestCF(t_f v1, t_f v2) {
257 return _mm_testc_ps(v1, v2);
258 }
TestZFS_SIMDSmallBaseF259 FORCE_INLINE static int TestZF(t_f v1, t_f v2) {
260 return _mm_testz_ps(v1, v2);
261 }
AndFS_SIMDSmallBaseF262 FORCE_INLINE static t_f AndF(t_f v1, t_f v2) {
263 return _mm_and_ps(v1, v2);
264 }
AndNotFS_SIMDSmallBaseF265 FORCE_INLINE static t_f AndNotF(t_f v1, t_f v2) {
266 return _mm_andnot_ps(v1, v2);
267 }
OrFS_SIMDSmallBaseF268 FORCE_INLINE static t_f OrF(t_f v1, t_f v2) {
269 return _mm_or_ps(v1, v2);
270 }
XorFS_SIMDSmallBaseF271 FORCE_INLINE static t_f XorF(t_f v1, t_f v2) {
272 return _mm_xor_ps(v1, v2);
273 }
274
SubS_SIMDSmallBaseF275 FORCE_INLINE static t_i Sub(t_i v1, t_i v2) {
276 return _mm_sub_epi32(v1, v2);
277 }
BlendVFS_SIMDSmallBaseF278 FORCE_INLINE static t_f BlendVF(t_f v1, t_f v2, t_f v3) {
279 return _mm_blendv_ps(v1, v2, v3);
280 }
281
282 template <int I_Mode>
CmpFMS_SIMDSmallBaseF283 FORCE_INLINE static t_f CmpFM(t_f v1, t_f v2) {
284 return _mm_cmp_ps(v1, v2, I_Mode);
285 }
AddS_SIMDSmallBaseF286 FORCE_INLINE static t_i Add(t_i v1, t_i v2) {
287 return _mm_add_epi32(v1, v2);
288 }
289 };
290
291 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
292
293 struct S_SIMDSmallMultiple: public S_SIMDSmallBaseF {
294 using S_SIMDSmallBaseF::Add;
295 using S_SIMDSmallBaseF::Sub;
296 template <int I_Mode>
CmpFS_SIMDSmallMultiple297 FORCE_INLINE static t_f CmpF(t_f v1, t_f v2) {
298 return _mm_cmp_ps(v1, v2, I_Mode);
299 }
CmpEqFS_SIMDSmallMultiple300 FORCE_INLINE static t_f CmpEqF(t_f v1, t_f v2) {
301 return _mm_cmpeq_ps(v1, v2);
302 }
303
MulS_SIMDSmallMultiple304 FORCE_INLINE static t_f Mul(t_f v1, t_f v2) {
305 return _mm_mul_ps(v1, v2);
306 }
DivS_SIMDSmallMultiple307 FORCE_INLINE static t_f Div(t_f v1, t_f v2) {
308 return _mm_div_ps(v1, v2);
309 }
AddS_SIMDSmallMultiple310 FORCE_INLINE static t_f Add(t_f v1, t_f v2) {
311 return _mm_add_ps(v1, v2);
312 }
SubS_SIMDSmallMultiple313 FORCE_INLINE static t_f Sub(t_f v1, t_f v2) {
314 return _mm_sub_ps(v1, v2);
315 }
SqrtS_SIMDSmallMultiple316 FORCE_INLINE static t_f Sqrt(t_f v) {
317 return _mm_sqrt_ps(v);
318 }
319
320 #ifndef NO_AVX2
FMADDS_SIMDSmallMultiple321 FORCE_INLINE static t_f FMADD(t_f v1, t_f v2, t_f v3) {
322 return _mm_fmadd_ps(v1, v2, v3);
323 }
FMSUBS_SIMDSmallMultiple324 FORCE_INLINE static t_f FMSUB(t_f v1, t_f v2, t_f v3) {
325 return _mm_fmsub_ps(v1, v2, v3);
326 }
FNMADDS_SIMDSmallMultiple327 FORCE_INLINE static t_f FNMADD(t_f v1, t_f v2, t_f v3) {
328 return _mm_fnmadd_ps(v1, v2, v3);
329 }
330 #else
331 FMADD_NO_AVX2();
332 #endif
333
MinS_SIMDSmallMultiple334 FORCE_INLINE static t_f Min(t_f v1, t_f v2) {
335 return _mm_min_ps(v1, v2);
336 }
MaxS_SIMDSmallMultiple337 FORCE_INLINE static t_f Max(t_f v1, t_f v2) {
338 return _mm_max_ps(v1, v2);
339 }
FloorS_SIMDSmallMultiple340 FORCE_INLINE static t_f Floor(t_f v) {
341 return _mm_floor_ps(v);
342 }
343 };
344
345 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
346
347 template <>
348 struct S_SIMDV<1, 4>: public S_SIMDSmallBaseF {
349 using S_SIMDSmallBaseF::Add;
350 using S_SIMDSmallBaseF::Sub;
351
352 FORCE_INLINE static t_f LoadU(const float* p) {
353 return _mm_load_ss(p);
354 }
355 FORCE_INLINE static t_f Load(const float* p) {
356 return _mm_load_ss(p);
357 }
358 FORCE_INLINE static t_i LoadU(const int* p) {
359 return _mm_loadu_si32(p);
360 }
361 FORCE_INLINE static t_i Load(const int* p) {
362 return _mm_loadu_si32(p);
363 }
364 FORCE_INLINE static void StoreU(float* p, t_f v) {
365 return _mm_store_ss(p, v);
366 }
367 FORCE_INLINE static void Store(float* p, t_f v) {
368 return _mm_store_ss(p, v);
369 }
370 FORCE_INLINE static void StoreU(int* p, t_i v) {
371 return _mm_storeu_si32(p, v);
372 }
373 FORCE_INLINE static void Store(int* p, t_i v) {
374 return _mm_storeu_si32(p, v);
375 }
376
377 template <int I_Mode>
378 FORCE_INLINE static t_f CmpF(t_f v1, t_f v2) {
379 return _mm_cmp_ss(v1, v2, I_Mode);
380 }
381 FORCE_INLINE static t_f CmpEqF(t_f v1, t_f v2) {
382 return _mm_cmpeq_ss(v1, v2);
383 }
384
385 FORCE_INLINE static t_f Mul(t_f v1, t_f v2) {
386 return _mm_mul_ss(v1, v2);
387 }
388 FORCE_INLINE static t_f Div(t_f v1, t_f v2) {
389 return _mm_div_ss(v1, v2);
390 }
391 FORCE_INLINE static t_f Add(t_f v1, t_f v2) {
392 return _mm_add_ss(v1, v2);
393 }
394 FORCE_INLINE static t_f Sub(t_f v1, t_f v2) {
395 return _mm_sub_ss(v1, v2);
396 }
397 FORCE_INLINE static t_f Sqrt(t_f v) {
398 return _mm_sqrt_ss(v);
399 }
400
401 #ifndef NO_AVX2
402 FORCE_INLINE static t_f FMADD(t_f v1, t_f v2, t_f v3) {
403 return _mm_fmadd_ss(v1, v2, v3);
404 }
405 FORCE_INLINE static t_f FMSUB(t_f v1, t_f v2, t_f v3) {
406 return _mm_fmsub_ss(v1, v2, v3);
407 }
408 FORCE_INLINE static t_f FNMADD(t_f v1, t_f v2, t_f v3) {
409 return _mm_fnmadd_ss(v1, v2, v3);
410 }
411 #else
412 FMADD_NO_AVX2();
413 #endif
414
415 FORCE_INLINE static t_f Min(t_f v1, t_f v2) {
416 return _mm_min_ss(v1, v2);
417 }
418 FORCE_INLINE static t_f Max(t_f v1, t_f v2) {
419 return _mm_max_ss(v1, v2);
420 }
421 FORCE_INLINE static t_f Floor(t_f v) {
422 return _mm_floor_ss(v, v);
423 }
424 };
425
426 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
427
428 template <>
429 struct S_SIMDV<2, 4>: public S_SIMDSmallMultiple {
430 FORCE_INLINE static t_f LoadU(const float* p) {
431 return _mm_castpd_ps(_mm_load_sd((const double*)p));
432 }
433 FORCE_INLINE static t_f Load(const float* p) {
434 return _mm_castpd_ps(_mm_load_sd((const double*)p));
435 }
436 FORCE_INLINE static t_i LoadU(const int* p) {
437 return _mm_loadu_si64(p);
438 }
439 FORCE_INLINE static t_i Load(const int* p) {
440 return _mm_loadu_si64(p);
441 }
442 FORCE_INLINE static void StoreU(float* p, t_f v) {
443 return _mm_store_sd((double*)p, _mm_castps_pd(v));
444 }
445 FORCE_INLINE static void Store(float* p, t_f v) {
446 return _mm_store_sd((double*)p, _mm_castps_pd(v));
447 }
448 FORCE_INLINE static void StoreU(int* p, t_i v) {
449 return _mm_storeu_si64(p, v);
450 }
451 FORCE_INLINE static void Store(int* p, t_i v) {
452 return _mm_storeu_si64(p, v);
453 }
454 };
455
456 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
457
458 template <>
459 struct S_SIMDV<4, 4>: public S_SIMDSmallMultiple {
460 FORCE_INLINE static t_f LoadU(const float* p) {
461 return _mm_loadu_ps(p);
462 }
463 FORCE_INLINE static t_f Load(const float* p) {
464 return _mm_load_ps(p);
465 }
466 FORCE_INLINE static t_i LoadU(const int* p) {
467 return _mm_loadu_si128((const t_i*)p);
468 }
469 FORCE_INLINE static t_i Load(const int* p) {
470 return _mm_load_si128((const t_i*)p);
471 }
472 FORCE_INLINE static void StoreU(float* p, t_f v) {
473 return _mm_storeu_ps(p, v);
474 }
475 FORCE_INLINE static void Store(float* p, t_f v) {
476 return _mm_store_ps(p, v);
477 }
478 FORCE_INLINE static void StoreU(int* p, t_i v) {
479 return _mm_storeu_si128((t_i*)p, v);
480 }
481 FORCE_INLINE static void Store(int* p, t_i v) {
482 return _mm_store_si128((t_i*)p, v);
483 }
484 };
485
486 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
487
488 template <>
489 struct S_SIMDV<8, 4> {
490 using t_i = __m256i;
491 using t_f = __m256;
492 using t_base_type = float;
493 //using t_type_d = __m256d;
494
495 FORCE_INLINE static t_i Cast(t_i v) noexcept {
496 return v;
497 }
498 FORCE_INLINE static t_f Cast(t_f v) noexcept {
499 return v;
500 }
501 //FORCE_INLINE static t_type_d Cast(t_type_d v) noexcept { return v; }
502
503 ///////////////////////////////////////////////////////////////////////////////////////////////////////
504
505 FORCE_INLINE static t_f LoadU(const float* p) {
506 return _mm256_loadu_ps(p);
507 }
508 FORCE_INLINE static t_f Load(const float* p) {
509 return _mm256_load_ps(p);
510 }
511 FORCE_INLINE static t_i LoadU(const int* p) {
512 return _mm256_loadu_si256((const t_i*)p);
513 }
514 FORCE_INLINE static t_i Load(const int* p) {
515 return _mm256_load_si256((const t_i*)p);
516 }
517 FORCE_INLINE static void StoreU(float* p, t_f v) {
518 return _mm256_storeu_ps(p, v);
519 }
520 FORCE_INLINE static void Store(float* p, t_f v) {
521 return _mm256_store_ps(p, v);
522 }
523 FORCE_INLINE static void StoreU(int* p, t_i v) {
524 return _mm256_storeu_si256((t_i*)p, v);
525 }
526 FORCE_INLINE static void Store(int* p, t_i v) {
527 return _mm256_store_si256((t_i*)p, v);
528 }
529
530 ///////////////////////////////////////////////////////////////////////////////////////////////////////
531
532 FORCE_INLINE static t_i SetZeroI() {
533 return _mm256_setzero_si256();
534 }
535 FORCE_INLINE static t_f SetZeroF() {
536 return _mm256_setzero_ps();
537 }
538 FORCE_INLINE static t_f Set1(float v) {
539 return _mm256_set1_ps(v);
540 }
541 FORCE_INLINE static t_i Set1(int v) {
542 return _mm256_set1_epi32(v);
543 }
544 FORCE_INLINE static t_f Set(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8) {
545 return _mm256_set_ps(v1, v2, v3, v4, v5, v6, v7, v8);
546 }
547 FORCE_INLINE static t_i Set(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) {
548 return _mm256_set_epi32(v1, v2, v3, v4, v5, v6, v7, v8);
549 }
550
551 FORCE_INLINE static t_i CastI(t_f v) {
552 return _mm256_castps_si256(v);
553 }
554 FORCE_INLINE static t_f CastF(t_i v) {
555 return _mm256_castsi256_ps(v);
556 }
557 FORCE_INLINE static t_f CVTI2F(t_i v) {
558 return _mm256_cvtepi32_ps(v);
559 }
560 FORCE_INLINE static t_i CVTF2I(t_f v) {
561 return _mm256_cvtps_epi32(v);
562 }
563
564 #ifndef NO_AVX2
565 FORCE_INLINE static t_i CmpEqI(t_i v1, t_i v2) {
566 return _mm256_cmpeq_epi32(v1, v2);
567 }
568 FORCE_INLINE static t_i SRLI(t_i v, int i) {
569 return _mm256_srli_epi32(v, i);
570 }
571 FORCE_INLINE static t_i SLLI(t_i v, int i) {
572 return _mm256_slli_epi32(v, i);
573 }
574 FORCE_INLINE static t_i SRAI32(t_i v, int i) {
575 return _mm256_srai_epi32(v, i);
576 }
577 FORCE_INLINE static t_i Add(t_i v1, t_i v2) {
578 return _mm256_add_epi32(v1, v2);
579 }
580 FORCE_INLINE static t_i Sub(t_i v1, t_i v2) {
581 return _mm256_sub_epi32(v1, v2);
582 }
583
584 FORCE_INLINE static t_f FMADD(t_f v1, t_f v2, t_f v3) {
585 return _mm256_fmadd_ps(v1, v2, v3);
586 }
587 FORCE_INLINE static t_f FMSUB(t_f v1, t_f v2, t_f v3) {
588 return _mm256_fmsub_ps(v1, v2, v3);
589 }
590 FORCE_INLINE static t_f FNMADD(t_f v1, t_f v2, t_f v3) {
591 return _mm256_fnmadd_ps(v1, v2, v3);
592 }
593 #else
594 FORCE_INLINE static t_i CmpEqI(t_i v1, t_i v2) {
595 return OPERATE_ELEMENTWISE_I(_mm_cmpeq_epi32, v1, v2);
596 }
597 FORCE_INLINE static t_i SRLI(t_i v, int i) {
598 return OPERATE_SEPARATELY_I(_mm_srli_epi32, v, i);
599 }
600 FORCE_INLINE static t_i SLLI(t_i v, int i) {
601 return OPERATE_SEPARATELY_I(_mm_slli_epi32, v, i);
602 }
603 FORCE_INLINE static t_i SRAI32(t_i v, int i) {
604 return OPERATE_SEPARATELY_I(_mm_srai_epi32, v, i);
605 }
606 FORCE_INLINE static t_i Add(t_i v1, t_i v2) {
607 return OPERATE_ELEMENTWISE_I(_mm_add_epi32, v1, v2);
608 }
609 FORCE_INLINE static t_i Sub(t_i v1, t_i v2) {
610 return OPERATE_ELEMENTWISE_I(_mm_sub_epi32, v1, v2);
611 }
612
613 FMADD_NO_AVX2();
614 #endif
615
616 FORCE_INLINE static int TestCF(t_f v1, t_f v2) {
617 return _mm256_testc_ps(v1, v2);
618 }
619 FORCE_INLINE static int TestZF(t_f v1, t_f v2) {
620 return _mm256_testz_ps(v1, v2);
621 }
622 FORCE_INLINE static t_f AndF(t_f v1, t_f v2) {
623 return _mm256_and_ps(v1, v2);
624 }
625 FORCE_INLINE static t_f AndNotF(t_f v1, t_f v2) {
626 return _mm256_andnot_ps(v1, v2);
627 }
628 FORCE_INLINE static t_f OrF(t_f v1, t_f v2) {
629 return _mm256_or_ps(v1, v2);
630 }
631 FORCE_INLINE static t_f XorF(t_f v1, t_f v2) {
632 return _mm256_xor_ps(v1, v2);
633 }
634
635 FORCE_INLINE static t_f BlendVF(t_f v1, t_f v2, t_f v3) {
636 return _mm256_blendv_ps(v1, v2, v3);
637 }
638
639 template <int I_Mode>
640 FORCE_INLINE static t_f CmpFM(t_f v1, t_f v2) {
641 return _mm256_cmp_ps(v1, v2, I_Mode);
642 }
643
644 ///////////////////////////////////////////////////////////////////////////////////////////////////////
645
646 template <int I_Mode>
647 FORCE_INLINE static t_f CmpF(t_f v1, t_f v2) {
648 return _mm256_cmp_ps(v1, v2, I_Mode);
649 }
650 FORCE_INLINE static t_f CmpEqF(t_f v1, t_f v2) {
651 return _mm256_cmp_ps(v1, v2, _CMP_EQ_OQ);
652 }
653
654 FORCE_INLINE static t_f Mul(t_f v1, t_f v2) {
655 return _mm256_mul_ps(v1, v2);
656 }
657 FORCE_INLINE static t_f Div(t_f v1, t_f v2) {
658 return _mm256_div_ps(v1, v2);
659 }
660 FORCE_INLINE static t_f Add(t_f v1, t_f v2) {
661 return _mm256_add_ps(v1, v2);
662 }
663 FORCE_INLINE static t_f Sub(t_f v1, t_f v2) {
664 return _mm256_sub_ps(v1, v2);
665 }
666 FORCE_INLINE static t_f Sqrt(t_f v) {
667 return _mm256_sqrt_ps(v);
668 }
669
670 FORCE_INLINE static t_f Min(t_f v1, t_f v2) {
671 return _mm256_min_ps(v1, v2);
672 }
673 FORCE_INLINE static t_f Max(t_f v1, t_f v2) {
674 return _mm256_max_ps(v1, v2);
675 }
676 FORCE_INLINE static t_f Floor(t_f v) {
677 return _mm256_floor_ps(v);
678 }
679 };
680
681 //############################################################################################################################################################
682
683 struct S_SIMDSmallBaseD {
684 using t_i = __m128i;
685 using t_f = __m128d;
686 using t_base_type = double;
687 //using t_type_d = __m128d;
688
689 FORCE_INLINE static t_i Cast(__m256i v) noexcept {
690 return _mm256_castsi256_si128(v);
691 }
692 FORCE_INLINE static t_f Cast(__m256d v) noexcept {
693 return _mm256_castpd256_pd128(v);
694 }
695 FORCE_INLINE static t_i Cast(t_i v) noexcept {
696 return v;
697 }
698 FORCE_INLINE static t_f Cast(t_f v) noexcept {
699 return v;
700 }
701
702 ///////////////////////////////////////////////////////////////////////////////////////////////////////
703
704 FORCE_INLINE static t_i SetZeroI() {
705 return _mm_setzero_si128();
706 }
707 FORCE_INLINE static t_f SetZeroF() {
708 return _mm_setzero_pd();
709 }
710 FORCE_INLINE static t_f Set1(double v) {
711 return _mm_set1_pd(v);
712 }
713 FORCE_INLINE static t_f Set(double v1, double v2) {
714 return _mm_set_pd(v1, v2);
715 }
716 FORCE_INLINE static t_i Set1(int64_t v) {
717 return _mm_set1_epi64x(v);
718 }
719 FORCE_INLINE static t_i Set(int64_t v1, int64_t v2) {
720 return _mm_set_epi64x(v1, v2);
721 }
722
723 FORCE_INLINE static t_i CastI(t_f v) {
724 return _mm_castpd_si128(v);
725 }
726 FORCE_INLINE static t_f CastF(t_i v) {
727 return _mm_castsi128_pd(v);
728 }
729 FORCE_INLINE static t_f CVTI2F(t_i v) {
730 return /*_mm_cvtepi64_pd(v);*/ i64o_double(v);
731 }
732 FORCE_INLINE static t_i CVTF2I(t_f v) {
733 return /*_mm_cvtpd_epi64(v);*/ double_to_int64(v);
734 }
735
736 FORCE_INLINE static t_i CmpEqI(t_i v1, t_i v2) {
737 return _mm_cmpeq_epi64(v1, v2);
738 }
739 FORCE_INLINE static t_i SRLI(t_i v, int i) {
740 return _mm_srli_epi64(v, i);
741 }
742 FORCE_INLINE static t_i SLLI(t_i v, int i) {
743 return _mm_slli_epi64(v, i);
744 }
745 FORCE_INLINE static t_i SRAI32(t_i v, int i) {
746 return _mm_srai_epi32(v, i);
747 }
748
749 FORCE_INLINE static int TestCF(t_f v1, t_f v2) {
750 return _mm_testc_pd(v1, v2);
751 }
752 FORCE_INLINE static int TestZF(t_f v1, t_f v2) {
753 return _mm_testz_pd(v1, v2);
754 }
755 FORCE_INLINE static t_f AndF(t_f v1, t_f v2) {
756 return _mm_and_pd(v1, v2);
757 }
758 FORCE_INLINE static t_f AndNotF(t_f v1, t_f v2) {
759 return _mm_andnot_pd(v1, v2);
760 }
761 FORCE_INLINE static t_f OrF(t_f v1, t_f v2) {
762 return _mm_or_pd(v1, v2);
763 }
764 FORCE_INLINE static t_f XorF(t_f v1, t_f v2) {
765 return _mm_xor_pd(v1, v2);
766 }
767
768 FORCE_INLINE static t_i Sub(t_i v1, t_i v2) {
769 return _mm_sub_epi64(v1, v2);
770 }
771 FORCE_INLINE static t_f BlendVF(t_f v1, t_f v2, t_f v3) {
772 return _mm_blendv_pd(v1, v2, v3);
773 }
774
775 template <int I_Mode>
776 FORCE_INLINE static t_f CmpFM(t_f v1, t_f v2) {
777 return _mm_cmp_pd(v1, v2, I_Mode);
778 }
779 FORCE_INLINE static t_i Add(t_i v1, t_i v2) {
780 return _mm_add_epi64(v1, v2);
781 }
782 };
783
784 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
785
786 struct S_SIMDSmallMultipleD: public S_SIMDSmallBaseD {
787 using S_SIMDSmallBaseD::Add;
788 using S_SIMDSmallBaseD::Sub;
789 template <int I_Mode>
790 FORCE_INLINE static t_f CmpF(t_f v1, t_f v2) {
791 return _mm_cmp_pd(v1, v2, I_Mode);
792 }
793 FORCE_INLINE static t_f CmpEqF(t_f v1, t_f v2) {
794 return _mm_cmpeq_pd(v1, v2);
795 }
796
797 FORCE_INLINE static t_f Mul(t_f v1, t_f v2) {
798 return _mm_mul_pd(v1, v2);
799 }
800 FORCE_INLINE static t_f Div(t_f v1, t_f v2) {
801 return _mm_div_pd(v1, v2);
802 }
803 FORCE_INLINE static t_f Add(t_f v1, t_f v2) {
804 return _mm_add_pd(v1, v2);
805 }
806 FORCE_INLINE static t_f Sub(t_f v1, t_f v2) {
807 return _mm_sub_pd(v1, v2);
808 }
809 FORCE_INLINE static t_f Sqrt(t_f v) {
810 return _mm_sqrt_pd(v);
811 }
812
813 #ifndef NO_AVX2
814 FORCE_INLINE static t_f FMADD(t_f v1, t_f v2, t_f v3) {
815 return _mm_fmadd_pd(v1, v2, v3);
816 }
817 FORCE_INLINE static t_f FMSUB(t_f v1, t_f v2, t_f v3) {
818 return _mm_fmsub_pd(v1, v2, v3);
819 }
820 FORCE_INLINE static t_f FNMADD(t_f v1, t_f v2, t_f v3) {
821 return _mm_fnmadd_pd(v1, v2, v3);
822 }
823 #else
824 FMADD_NO_AVX2();
825 #endif
826
827 FORCE_INLINE static t_f Min(t_f v1, t_f v2) {
828 return _mm_min_pd(v1, v2);
829 }
830 FORCE_INLINE static t_f Max(t_f v1, t_f v2) {
831 return _mm_max_pd(v1, v2);
832 }
833 FORCE_INLINE static t_f Floor(t_f v) {
834 return _mm_floor_pd(v);
835 }
836 };
837
838 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
839
840 template <>
841 struct S_SIMDV<1, 8>: public S_SIMDSmallBaseD {
842 using S_SIMDSmallBaseD::Add;
843 using S_SIMDSmallBaseD::Sub;
844
845 FORCE_INLINE static t_f LoadU(const double* p) {
846 return _mm_load_sd(p);
847 }
848 FORCE_INLINE static t_f Load(const double* p) {
849 return _mm_load_sd(p);
850 }
851 FORCE_INLINE static t_i LoadU(const int64_t* p) {
852 return _mm_loadu_si64(p);
853 }
854 FORCE_INLINE static t_i Load(const int64_t* p) {
855 return _mm_loadu_si64(p);
856 }
857 FORCE_INLINE static void StoreU(double* p, t_f v) {
858 return _mm_store_sd(p, v);
859 }
860 FORCE_INLINE static void Store(double* p, t_f v) {
861 return _mm_store_sd(p, v);
862 }
863 FORCE_INLINE static void StoreU(int64_t* p, t_i v) {
864 return _mm_storeu_si64(p, v);
865 }
866 FORCE_INLINE static void Store(int64_t* p, t_i v) {
867 return _mm_storeu_si64(p, v);
868 }
869
870 template <int I_Mode>
871 FORCE_INLINE static t_f CmpF(t_f v1, t_f v2) {
872 return _mm_cmp_sd(v1, v2, I_Mode);
873 }
874 FORCE_INLINE static t_f CmpEqF(t_f v1, t_f v2) {
875 return _mm_cmpeq_sd(v1, v2);
876 }
877
878 FORCE_INLINE static t_f Mul(t_f v1, t_f v2) {
879 return _mm_mul_sd(v1, v2);
880 }
881 FORCE_INLINE static t_f Div(t_f v1, t_f v2) {
882 return _mm_div_sd(v1, v2);
883 }
884 FORCE_INLINE static t_f Add(t_f v1, t_f v2) {
885 return _mm_add_sd(v1, v2);
886 }
887 FORCE_INLINE static t_f Sub(t_f v1, t_f v2) {
888 return _mm_sub_sd(v1, v2);
889 }
890 FORCE_INLINE static t_f Sqrt(t_f v) {
891 return _mm_sqrt_sd(v, v);
892 }
893
894 #ifndef NO_AVX2
895 FORCE_INLINE static t_f FMADD(t_f v1, t_f v2, t_f v3) {
896 return _mm_fmadd_sd(v1, v2, v3);
897 }
898 FORCE_INLINE static t_f FMSUB(t_f v1, t_f v2, t_f v3) {
899 return _mm_fmsub_sd(v1, v2, v3);
900 }
901 FORCE_INLINE static t_f FNMADD(t_f v1, t_f v2, t_f v3) {
902 return _mm_fnmadd_sd(v1, v2, v3);
903 }
904 #else
905 FMADD_NO_AVX2();
906 #endif
907
908 FORCE_INLINE static t_f Min(t_f v1, t_f v2) {
909 return _mm_min_sd(v1, v2);
910 }
911 FORCE_INLINE static t_f Max(t_f v1, t_f v2) {
912 return _mm_max_sd(v1, v2);
913 }
914 FORCE_INLINE static t_f Floor(t_f v) {
915 return _mm_floor_sd(v, v);
916 }
917 };
918
919 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
920
921 template <>
922 struct S_SIMDV<2, 8>: public S_SIMDSmallMultipleD {
923 FORCE_INLINE static t_f LoadU(const double* p) {
924 return _mm_castps_pd(_mm_loadu_ps((const float*)p));
925 }
926 FORCE_INLINE static t_f Load(const double* p) {
927 return _mm_castps_pd(_mm_load_ps((const float*)p));
928 }
929 FORCE_INLINE static t_i LoadU(const int64_t* p) {
930 return _mm_loadu_si128((const t_i*)p);
931 }
932 FORCE_INLINE static t_i Load(const int64_t* p) {
933 return _mm_load_si128((const t_i*)p);
934 }
935 FORCE_INLINE static void StoreU(double* p, t_f v) {
936 return _mm_storeu_ps((float*)p, _mm_castpd_ps(v));
937 }
938 FORCE_INLINE static void Store(double* p, t_f v) {
939 return _mm_store_ps((float*)p, _mm_castpd_ps(v));
940 }
941 FORCE_INLINE static void StoreU(int64_t* p, t_i v) {
942 return _mm_storeu_si128((t_i*)p, v);
943 }
944 FORCE_INLINE static void Store(int64_t* p, t_i v) {
945 return _mm_store_si128((t_i*)p, v);
946 }
947 };
948
949 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
950
951 template <>
952 struct S_SIMDV<4, 8> {
953 using t_i = __m256i;
954 using t_f = __m256d;
955 using t_base_type = double;
956
957 FORCE_INLINE static t_i Cast(t_i v) noexcept {
958 return v;
959 }
960 FORCE_INLINE static t_f Cast(t_f v) noexcept {
961 return v;
962 }
963
964 ///////////////////////////////////////////////////////////////////////////////////////////////////////
965
966 FORCE_INLINE static t_f LoadU(const double* p) {
967 return _mm256_loadu_pd(p);
968 }
969 FORCE_INLINE static t_f Load(const double* p) {
970 return _mm256_load_pd(p);
971 }
972 FORCE_INLINE static t_i LoadU(const int64_t* p) {
973 return _mm256_loadu_si256((const t_i*)p);
974 }
975 FORCE_INLINE static t_i Load(const int64_t* p) {
976 return _mm256_load_si256((const t_i*)p);
977 }
978 FORCE_INLINE static void StoreU(double* p, t_f v) {
979 return _mm256_storeu_pd(p, v);
980 }
981 FORCE_INLINE static void Store(double* p, t_f v) {
982 return _mm256_store_pd(p, v);
983 }
984 FORCE_INLINE static void StoreU(int64_t* p, t_i v) {
985 return _mm256_storeu_si256((t_i*)p, v);
986 }
987 FORCE_INLINE static void Store(int64_t* p, t_i v) {
988 return _mm256_store_si256((t_i*)p, v);
989 }
990
991 ///////////////////////////////////////////////////////////////////////////////////////////////////////
992
993 FORCE_INLINE static t_i SetZeroI() {
994 return _mm256_setzero_si256();
995 }
996 FORCE_INLINE static t_f SetZeroF() {
997 return _mm256_setzero_pd();
998 }
999 FORCE_INLINE static t_f Set1(double v) {
1000 return _mm256_set1_pd(v);
1001 }
1002 FORCE_INLINE static t_i Set1(int64_t v) {
1003 return _mm256_set1_epi64x(v);
1004 }
1005 FORCE_INLINE static t_f Set(double v1, double v2, double v3, double v4) {
1006 return _mm256_set_pd(v1, v2, v3, v4);
1007 }
1008 FORCE_INLINE static t_i Set(int64_t v1, int64_t v2, int64_t v3, int64_t v4) {
1009 return _mm256_set_epi64x(v1, v2, v3, v4);
1010 }
1011
1012 FORCE_INLINE static t_i CastI(t_f v) {
1013 return _mm256_castpd_si256(v);
1014 }
1015 FORCE_INLINE static t_f CastF(t_i v) {
1016 return _mm256_castsi256_pd(v);
1017 }
1018 FORCE_INLINE static t_f CVTI2F(t_i v) {
1019 return /*_mm256_cvtepi64_pd(v);*/ i64o_double(v);
1020 }
1021 FORCE_INLINE static t_i CVTF2I(t_f v) {
1022 return /*_mm256_cvtpd_epi64(v);*/ double_to_int64(v);
1023 }
1024
1025 #ifndef NO_AVX2
1026 FORCE_INLINE static t_i CmpEqI(t_i v1, t_i v2) {
1027 return _mm256_cmpeq_epi64(v1, v2);
1028 }
1029 FORCE_INLINE static t_i SRLI(t_i v, int i) {
1030 return _mm256_srli_epi64(v, i);
1031 }
1032 FORCE_INLINE static t_i SLLI(t_i v, int i) {
1033 return _mm256_slli_epi64(v, i);
1034 }
1035 FORCE_INLINE static t_i SRAI32(t_i v, int i) {
1036 return _mm256_srai_epi32(v, i);
1037 }
1038 FORCE_INLINE static t_i Add(t_i v1, t_i v2) {
1039 return _mm256_add_epi64(v1, v2);
1040 }
1041 FORCE_INLINE static t_i Sub(t_i v1, t_i v2) {
1042 return _mm256_sub_epi64(v1, v2);
1043 }
1044
1045 FORCE_INLINE static t_f FMADD(t_f v1, t_f v2, t_f v3) {
1046 return _mm256_fmadd_pd(v1, v2, v3);
1047 }
1048 FORCE_INLINE static t_f FMSUB(t_f v1, t_f v2, t_f v3) {
1049 return _mm256_fmsub_pd(v1, v2, v3);
1050 }
1051 FORCE_INLINE static t_f FNMADD(t_f v1, t_f v2, t_f v3) {
1052 return _mm256_fnmadd_pd(v1, v2, v3);
1053 }
1054 #else
1055 FORCE_INLINE static t_i CmpEqI(t_i v1, t_i v2) {
1056 return OPERATE_ELEMENTWISE_I(_mm_cmpeq_epi64, v1, v2);
1057 }
1058 FORCE_INLINE static t_i SRLI(t_i v, int i) {
1059 return OPERATE_SEPARATELY_I(_mm_srli_epi64, v, i);
1060 }
1061 FORCE_INLINE static t_i SLLI(t_i v, int i) {
1062 return OPERATE_SEPARATELY_I(_mm_slli_epi64, v, i);
1063 }
1064 FORCE_INLINE static t_i SRAI32(t_i v, int i) {
1065 return OPERATE_SEPARATELY_I(_mm_srai_epi32, v, i);
1066 }
1067 FORCE_INLINE static t_i Add(t_i v1, t_i v2) {
1068 return OPERATE_ELEMENTWISE_I(_mm_add_epi64, v1, v2);
1069 }
1070 FORCE_INLINE static t_i Sub(t_i v1, t_i v2) {
1071 return OPERATE_ELEMENTWISE_I(_mm_sub_epi64, v1, v2);
1072 }
1073
1074 FMADD_NO_AVX2();
1075 #endif
1076
1077 FORCE_INLINE static int TestCF(t_f v1, t_f v2) {
1078 return _mm256_testc_pd(v1, v2);
1079 }
1080 FORCE_INLINE static int TestZF(t_f v1, t_f v2) {
1081 return _mm256_testz_pd(v1, v2);
1082 }
1083 FORCE_INLINE static t_f AndF(t_f v1, t_f v2) {
1084 return _mm256_and_pd(v1, v2);
1085 }
1086 FORCE_INLINE static t_f AndNotF(t_f v1, t_f v2) {
1087 return _mm256_andnot_pd(v1, v2);
1088 }
1089 FORCE_INLINE static t_f OrF(t_f v1, t_f v2) {
1090 return _mm256_or_pd(v1, v2);
1091 }
1092 FORCE_INLINE static t_f XorF(t_f v1, t_f v2) {
1093 return _mm256_xor_pd(v1, v2);
1094 }
1095
1096 FORCE_INLINE static t_f BlendVF(t_f v1, t_f v2, t_f v3) {
1097 return _mm256_blendv_pd(v1, v2, v3);
1098 }
1099
1100 template <int I_Mode>
1101 FORCE_INLINE static t_f CmpFM(t_f v1, t_f v2) {
1102 return _mm256_cmp_pd(v1, v2, I_Mode);
1103 }
1104
1105 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1106
1107 template <int I_Mode>
1108 FORCE_INLINE static t_f CmpF(t_f v1, t_f v2) {
1109 return _mm256_cmp_pd(v1, v2, I_Mode);
1110 }
1111 FORCE_INLINE static t_f CmpEqF(t_f v1, t_f v2) {
1112 return _mm256_cmp_pd(v1, v2, _CMP_EQ_OQ);
1113 }
1114
1115 FORCE_INLINE static t_f Mul(t_f v1, t_f v2) {
1116 return _mm256_mul_pd(v1, v2);
1117 }
1118 FORCE_INLINE static t_f Div(t_f v1, t_f v2) {
1119 return _mm256_div_pd(v1, v2);
1120 }
1121 FORCE_INLINE static t_f Add(t_f v1, t_f v2) {
1122 return _mm256_add_pd(v1, v2);
1123 }
1124 FORCE_INLINE static t_f Sub(t_f v1, t_f v2) {
1125 return _mm256_sub_pd(v1, v2);
1126 }
1127 FORCE_INLINE static t_f Sqrt(t_f v) {
1128 return _mm256_sqrt_pd(v);
1129 }
1130
1131 FORCE_INLINE static t_f Min(t_f v1, t_f v2) {
1132 return _mm256_min_pd(v1, v2);
1133 }
1134 FORCE_INLINE static t_f Max(t_f v1, t_f v2) {
1135 return _mm256_max_pd(v1, v2);
1136 }
1137 FORCE_INLINE static t_f Floor(t_f v) {
1138 return _mm256_floor_pd(v);
1139 }
1140 };
1141
1142 template <size_t I_ElemSize>
1143 using S_MaxSIMD = S_SIMDV<32 / I_ElemSize, I_ElemSize>;
1144 }
1145
1146 #endif
1147