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