NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
simd/compare.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_SIMD_COMPARE_HPP__
2#define NEFORCE_CORE_SIMD_COMPARE_HPP__
3
10
12NEFORCE_BEGIN_NAMESPACE__
13NEFORCE_BEGIN_SIMD__
14
19
26NEFORCE_ALWAYS_INLINE_INLINE vec128_t cmpeq_i8(vec128_t a, vec128_t b) noexcept {
27#ifdef NEFORCE_SIMD_SSE2
28 return ::_mm_cmpeq_epi8(a, b);
29#elif defined(NEFORCE_SIMD_NEON)
30 return ::vceqq_s8(::vreinterpretq_s8_u8(a), ::vreinterpretq_s8_u8(b));
31#else
32 vec128_t result;
33 for (int i = 0; i < 16; ++i) {
34 result.data[i] = (a.data[i] == b.data[i]) ? 0xFF : 0x00;
35 }
36 return result;
37#endif
38}
39
46NEFORCE_ALWAYS_INLINE_INLINE vec128_t cmpeq_i16(vec128_t a, vec128_t b) noexcept {
47#ifdef NEFORCE_SIMD_SSE2
48 return ::_mm_cmpeq_epi16(a, b);
49#elif defined(NEFORCE_SIMD_NEON)
50 return ::vreinterpretq_u8_u16(::vceqq_s16(::vreinterpretq_s16_u8(a), ::vreinterpretq_s16_u8(b)));
51#else
52 const auto* sa = reinterpret_cast<const int16_t*>(a.data);
53 const auto* sb = reinterpret_cast<const int16_t*>(b.data);
54 vec128_t result;
55 auto* rd = reinterpret_cast<uint16_t*>(result.data);
56 for (int i = 0; i < 8; ++i) {
57 rd[i] = (sa[i] == sb[i]) ? 0xFFFF : 0;
58 }
59 return result;
60#endif
61}
62
69NEFORCE_ALWAYS_INLINE_INLINE vec128_t cmpeq_i32(vec128_t a, vec128_t b) noexcept {
70#ifdef NEFORCE_SIMD_SSE2
71 return ::_mm_cmpeq_epi32(a, b);
72#elif defined(NEFORCE_SIMD_NEON)
73 return ::vreinterpretq_u8_u32(::vceqq_s32(::vreinterpretq_s32_u8(a), ::vreinterpretq_s32_u8(b)));
74#else
75 const auto* sa = reinterpret_cast<const int32_t*>(a.data);
76 const auto* sb = reinterpret_cast<const int32_t*>(b.data);
77 vec128_t result;
78 auto* rd = reinterpret_cast<uint32_t*>(result.data);
79 for (int i = 0; i < 4; ++i) {
80 rd[i] = (sa[i] == sb[i]) ? 0xFFFFFFFF : 0;
81 }
82 return result;
83#endif
84}
85
92NEFORCE_ALWAYS_INLINE_INLINE vec128_t cmpeq_i64(vec128_t a, vec128_t b) noexcept {
93#if defined(__SSE4_1__) || defined(NEFORCE_SIMD_AVX2)
94 return ::_mm_cmpeq_epi64(a, b);
95#elif defined(NEFORCE_SIMD_SSE2)
96 const ::__m128i eq_lo = ::_mm_cmpeq_epi32(a, b);
97 const ::__m128i eq_hi = ::_mm_cmpeq_epi32(_mm_shuffle_epi32(a, _MM_SHUFFLE(2, 3, 0, 1)),
98 _mm_shuffle_epi32(b, _MM_SHUFFLE(2, 3, 0, 1)));
99 return ::_mm_and_si128(eq_lo, eq_hi);
100#elif defined(NEFORCE_SIMD_NEON)
101 return ::vreinterpretq_u8_u64(::vceqq_s64(::vreinterpretq_s64_u8(a), ::vreinterpretq_s64_u8(b)));
102#else
103 const auto* sa = reinterpret_cast<const int64_t*>(a.data);
104 const auto* sb = reinterpret_cast<const int64_t*>(b.data);
105 vec128_t result;
106 auto* rd = reinterpret_cast<uint64_t*>(result.data);
107 for (int i = 0; i < 2; ++i) {
108 rd[i] = (sa[i] == sb[i]) ? 0xFFFFFFFFFFFFFFFFULL : 0;
109 }
110 return result;
111#endif
112}
113
120NEFORCE_ALWAYS_INLINE_INLINE vec128_t cmpgt_i8(vec128_t a, vec128_t b) noexcept {
121#ifdef NEFORCE_SIMD_SSE2
122 return ::_mm_cmpgt_epi8(a, b);
123#elif defined(NEFORCE_SIMD_NEON)
124 return ::vcgtq_s8(::vreinterpretq_s8_u8(a), ::vreinterpretq_s8_u8(b));
125#else
126 vec128_t result;
127 for (int i = 0; i < 16; ++i) {
128 result.data[i] = (static_cast<int8_t>(a.data[i]) > static_cast<int8_t>(b.data[i])) ? 0xFF : 0x00;
129 }
130 return result;
131#endif
132}
133
140NEFORCE_ALWAYS_INLINE_INLINE vec128_t cmpgt_i16(vec128_t a, vec128_t b) noexcept {
141#ifdef NEFORCE_SIMD_SSE2
142 return ::_mm_cmpgt_epi16(a, b);
143#elif defined(NEFORCE_SIMD_NEON)
144 return ::vreinterpretq_u8_u16(::vcgtq_s16(::vreinterpretq_s16_u8(a), ::vreinterpretq_s16_u8(b)));
145#else
146 const auto* sa = reinterpret_cast<const int16_t*>(a.data);
147 const auto* sb = reinterpret_cast<const int16_t*>(b.data);
148 vec128_t result;
149 auto* rd = reinterpret_cast<uint16_t*>(result.data);
150 for (int i = 0; i < 8; ++i) {
151 rd[i] = (sa[i] > sb[i]) ? 0xFFFF : 0;
152 }
153 return result;
154#endif
155}
156
163NEFORCE_ALWAYS_INLINE_INLINE vec128_t cmpgt_i32(vec128_t a, vec128_t b) noexcept {
164#ifdef NEFORCE_SIMD_SSE2
165 return ::_mm_cmpgt_epi32(a, b);
166#elif defined(NEFORCE_SIMD_NEON)
167 return ::vreinterpretq_u8_u32(::vcgtq_s32(::vreinterpretq_s32_u8(a), ::vreinterpretq_s32_u8(b)));
168#else
169 const auto* sa = reinterpret_cast<const int32_t*>(a.data);
170 const auto* sb = reinterpret_cast<const int32_t*>(b.data);
171 vec128_t result;
172 auto* rd = reinterpret_cast<uint32_t*>(result.data);
173 for (int i = 0; i < 4; ++i) {
174 rd[i] = (sa[i] > sb[i]) ? 0xFFFFFFFF : 0;
175 }
176 return result;
177#endif
178}
179
186NEFORCE_ALWAYS_INLINE_INLINE vec128_t cmpgt_i64(vec128_t a, vec128_t b) noexcept {
187#if defined(__SSE4_2__) || defined(NEFORCE_SIMD_AVX2)
188 return ::_mm_cmpgt_epi64(a, b);
189#elif defined(NEFORCE_SIMD_SSE2)
190 const auto* sa = reinterpret_cast<const int64_t*>(&a);
191 const auto* sb = reinterpret_cast<const int64_t*>(&b);
192 alignas(16) int64_t rd[2];
193 rd[0] = sa[0] > sb[0] ? -1LL : 0LL;
194 rd[1] = sa[1] > sb[1] ? -1LL : 0LL;
195 return ::_mm_load_si128(reinterpret_cast<const ::__m128i*>(rd));
196#elif defined(NEFORCE_SIMD_NEON)
197 return ::vreinterpretq_u8_u64(::vcgtq_s64(::vreinterpretq_s64_u8(a), ::vreinterpretq_s64_u8(b)));
198#else
199 const auto* sa = reinterpret_cast<const int64_t*>(a.data);
200 const auto* sb = reinterpret_cast<const int64_t*>(b.data);
201 vec128_t result;
202 auto* rd = reinterpret_cast<uint64_t*>(result.data);
203 for (int i = 0; i < 2; ++i) {
204 rd[i] = (sa[i] > sb[i]) ? 0xFFFFFFFFFFFFFFFFULL : 0;
205 }
206 return result;
207#endif
208}
209
216NEFORCE_ALWAYS_INLINE_INLINE vec128f_t cmpeq_f32(vec128f_t a, vec128f_t b) noexcept {
217#ifdef NEFORCE_SIMD_SSE2
218 return ::_mm_cmpeq_ps(a, b);
219#elif defined(NEFORCE_SIMD_NEON)
220 return ::vreinterpretq_f32_u32(::vceqq_f32(a, b));
221#else
222 vec128f_t result;
223 for (int i = 0; i < 4; ++i) {
224 reinterpret_cast<uint32_t&>(result.data[i]) = (a.data[i] == b.data[i]) ? 0xFFFFFFFF : 0;
225 }
226 return result;
227#endif
228}
229
236NEFORCE_ALWAYS_INLINE_INLINE vec128f_t cmpgt_f32(vec128f_t a, vec128f_t b) noexcept {
237#ifdef NEFORCE_SIMD_SSE2
238 return ::_mm_cmpgt_ps(a, b);
239#elif defined(NEFORCE_SIMD_NEON)
240 return ::vreinterpretq_f32_u32(::vcgtq_f32(a, b));
241#else
242 vec128f_t result;
243 for (int i = 0; i < 4; ++i) {
244 reinterpret_cast<uint32_t&>(result.data[i]) = (a.data[i] > b.data[i]) ? 0xFFFFFFFF : 0;
245 }
246 return result;
247#endif
248}
249
256NEFORCE_ALWAYS_INLINE_INLINE vec128f_t cmpge_f32(vec128f_t a, vec128f_t b) noexcept {
257#ifdef NEFORCE_SIMD_SSE2
258 return ::_mm_cmpge_ps(a, b);
259#elif defined(NEFORCE_SIMD_NEON)
260 return ::vreinterpretq_f32_u32(::vcgeq_f32(a, b));
261#else
262 vec128f_t result;
263 for (int i = 0; i < 4; ++i) {
264 reinterpret_cast<uint32_t&>(result.data[i]) = (a.data[i] >= b.data[i]) ? 0xFFFFFFFF : 0;
265 }
266 return result;
267#endif
268}
269
276NEFORCE_ALWAYS_INLINE_INLINE vec128f_t cmplt_f32(vec128f_t a, vec128f_t b) noexcept {
277#ifdef NEFORCE_SIMD_SSE2
278 return ::_mm_cmplt_ps(a, b);
279#elif defined(NEFORCE_SIMD_NEON)
280 return ::vreinterpretq_f32_u32(::vcltq_f32(a, b));
281#else
282 vec128f_t result;
283 for (int i = 0; i < 4; ++i) {
284 reinterpret_cast<uint32_t&>(result.data[i]) = (a.data[i] < b.data[i]) ? 0xFFFFFFFF : 0;
285 }
286 return result;
287#endif
288}
289
296NEFORCE_ALWAYS_INLINE_INLINE vec128f_t cmple_f32(vec128f_t a, vec128f_t b) noexcept {
297#ifdef NEFORCE_SIMD_SSE2
298 return ::_mm_cmple_ps(a, b);
299#elif defined(NEFORCE_SIMD_NEON)
300 return ::vreinterpretq_f32_u32(::vcleq_f32(a, b));
301#else
302 vec128f_t result;
303 for (int i = 0; i < 4; ++i) {
304 reinterpret_cast<uint32_t&>(result.data[i]) = (a.data[i] <= b.data[i]) ? 0xFFFFFFFF : 0;
305 }
306 return result;
307#endif
308}
309
316NEFORCE_ALWAYS_INLINE_INLINE vec128d_t cmpeq_f64(vec128d_t a, vec128d_t b) noexcept {
317#ifdef NEFORCE_SIMD_SSE2
318 return ::_mm_cmpeq_pd(a, b);
319#elif defined(NEFORCE_SIMD_NEON)
320 return ::vreinterpretq_f64_u64(::vceqq_f64(a, b));
321#else
322 vec128d_t result;
323 for (int i = 0; i < 2; ++i) {
324 reinterpret_cast<uint64_t&>(result.data[i]) = (a.data[i] == b.data[i]) ? 0xFFFFFFFFFFFFFFFFULL : 0;
325 }
326 return result;
327#endif
328}
329
336NEFORCE_ALWAYS_INLINE_INLINE vec128d_t cmpgt_f64(vec128d_t a, vec128d_t b) noexcept {
337#ifdef NEFORCE_SIMD_SSE2
338 return ::_mm_cmpgt_pd(a, b);
339#elif defined(NEFORCE_SIMD_NEON)
340 return ::vreinterpretq_f64_u64(::vcgtq_f64(a, b));
341#else
342 vec128d_t result;
343 for (int i = 0; i < 2; ++i) {
344 reinterpret_cast<uint64_t&>(result.data[i]) = (a.data[i] > b.data[i]) ? 0xFFFFFFFFFFFFFFFFULL : 0;
345 }
346 return result;
347#endif
348}
349
356NEFORCE_ALWAYS_INLINE_INLINE vec128d_t cmpge_f64(vec128d_t a, vec128d_t b) noexcept {
357#ifdef NEFORCE_SIMD_SSE2
358 return ::_mm_cmpge_pd(a, b);
359#elif defined(NEFORCE_SIMD_NEON)
360 return ::vreinterpretq_f64_u64(::vcgeq_f64(a, b));
361#else
362 vec128d_t result;
363 for (int i = 0; i < 2; ++i) {
364 reinterpret_cast<uint64_t&>(result.data[i]) = (a.data[i] >= b.data[i]) ? 0xFFFFFFFFFFFFFFFFULL : 0;
365 }
366 return result;
367#endif
368}
369
376NEFORCE_ALWAYS_INLINE_INLINE vec128d_t cmplt_f64(vec128d_t a, vec128d_t b) noexcept {
377#ifdef NEFORCE_SIMD_SSE2
378 return ::_mm_cmplt_pd(a, b);
379#elif defined(NEFORCE_SIMD_NEON)
380 return ::vreinterpretq_f64_u64(::vcltq_f64(a, b));
381#else
382 vec128d_t result;
383 for (int i = 0; i < 2; ++i) {
384 reinterpret_cast<uint64_t&>(result.data[i]) = (a.data[i] < b.data[i]) ? 0xFFFFFFFFFFFFFFFFULL : 0;
385 }
386 return result;
387#endif
388}
389
396NEFORCE_ALWAYS_INLINE_INLINE vec128d_t cmple_f64(vec128d_t a, vec128d_t b) noexcept {
397#ifdef NEFORCE_SIMD_SSE2
398 return ::_mm_cmple_pd(a, b);
399#elif defined(NEFORCE_SIMD_NEON)
400 return ::vreinterpretq_f64_u64(::vcleq_f64(a, b));
401#else
402 vec128d_t result;
403 for (int i = 0; i < 2; ++i) {
404 reinterpret_cast<uint64_t&>(result.data[i]) = (a.data[i] <= b.data[i]) ? 0xFFFFFFFFFFFFFFFFULL : 0;
405 }
406 return result;
407#endif
408}
409 // SIMD
411
412NEFORCE_END_SIMD__
413NEFORCE_END_NAMESPACE__
414#endif // NEFORCE_CORE_SIMD_COMPARE_HPP__
long int64_t
64位有符号整数类型
unsigned int uint32_t
32位无符号整数类型
unsigned long uint64_t
64位无符号整数类型
int int32_t
32位有符号整数类型
unsigned short uint16_t
16位无符号整数类型
short int16_t
16位有符号整数类型
signed char int8_t
8位有符号整数类型
vec128_t cmpgt_i16(vec128_t a, vec128_t b) noexcept
8 路 16-bit 有符号大于比较
::__m128i vec128_t
128-bit 整型向量(16×i8 / 8×i16 / 4×i32 / 2×i64)
vec128f_t cmpge_f32(vec128f_t a, vec128f_t b) noexcept
4 路单精度浮点大于等于比较
vec128_t cmpgt_i64(vec128_t a, vec128_t b) noexcept
2 路 64-bit 有符号大于比较
::__m128 vec128f_t
128-bit 单精度浮点向量(4×f32)
::__m128d vec128d_t
128-bit 双精度浮点向量(2×f64)
vec128_t cmpgt_i8(vec128_t a, vec128_t b) noexcept
16 路 8-bit 有符号大于比较
vec128f_t cmplt_f32(vec128f_t a, vec128f_t b) noexcept
4 路单精度浮点小于比较
vec128d_t cmpeq_f64(vec128d_t a, vec128d_t b) noexcept
2 路双精度浮点相等比较
vec128_t cmpeq_i8(vec128_t a, vec128_t b) noexcept
16 路 8-bit 相等比较
vec128f_t cmple_f32(vec128f_t a, vec128f_t b) noexcept
4 路单精度浮点小于等于比较
vec128d_t cmple_f64(vec128d_t a, vec128d_t b) noexcept
2 路双精度浮点小于等于比较
vec128f_t cmpeq_f32(vec128f_t a, vec128f_t b) noexcept
4 路单精度浮点相等比较
vec128_t cmpeq_i64(vec128_t a, vec128_t b) noexcept
2 路 64-bit 相等比较
vec128d_t cmpgt_f64(vec128d_t a, vec128d_t b) noexcept
2 路双精度浮点大于比较
vec128_t cmpeq_i16(vec128_t a, vec128_t b) noexcept
8 路 16-bit 相等比较
vec128_t cmpgt_i32(vec128_t a, vec128_t b) noexcept
4 路 32-bit 有符号大于比较
vec128d_t cmpge_f64(vec128d_t a, vec128d_t b) noexcept
2 路双精度浮点大于等于比较
vec128f_t cmpgt_f32(vec128f_t a, vec128f_t b) noexcept
4 路单精度浮点大于比较
vec128d_t cmplt_f64(vec128d_t a, vec128d_t b) noexcept
2 路双精度浮点小于比较
vec128_t cmpeq_i32(vec128_t a, vec128_t b) noexcept
4 路 32-bit 相等比较
SIMD 向量类型定义