NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
bitwise.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_SIMD_BITWISE_HPP__
2#define NEFORCE_CORE_SIMD_BITWISE_HPP__
3
10
12NEFORCE_BEGIN_NAMESPACE__
13NEFORCE_BEGIN_SIMD__
14
19
26NEFORCE_ALWAYS_INLINE_INLINE vec128_t bit_and(vec128_t a, vec128_t b) noexcept {
27#ifdef NEFORCE_SIMD_SSE2
28 return ::_mm_and_si128(a, b);
29#elif defined(NEFORCE_SIMD_NEON)
30 return ::vandq_u8(a, 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];
35 }
36 return result;
37#endif
38}
39
46NEFORCE_ALWAYS_INLINE_INLINE vec128_t bit_or(vec128_t a, vec128_t b) noexcept {
47#ifdef NEFORCE_SIMD_SSE2
48 return ::_mm_or_si128(a, b);
49#elif defined(NEFORCE_SIMD_NEON)
50 return ::vorrq_u8(a, b);
51#else
52 vec128_t result;
53 for (int i = 0; i < 16; ++i) {
54 result.data[i] = a.data[i] | b.data[i];
55 }
56 return result;
57#endif
58}
59
66NEFORCE_ALWAYS_INLINE_INLINE vec128_t bit_xor(vec128_t a, vec128_t b) noexcept {
67#ifdef NEFORCE_SIMD_SSE2
68 return ::_mm_xor_si128(a, b);
69#elif defined(NEFORCE_SIMD_NEON)
70 return ::veorq_u8(a, b);
71#else
72 vec128_t result;
73 for (int i = 0; i < 16; ++i) {
74 result.data[i] = a.data[i] ^ b.data[i];
75 }
76 return result;
77#endif
78}
79
85NEFORCE_ALWAYS_INLINE_INLINE vec128_t bit_not(vec128_t v) noexcept {
86#ifdef NEFORCE_SIMD_SSE2
87 return ::_mm_andnot_si128(v, ::_mm_set1_epi8(static_cast<char>(0xFF)));
88#elif defined(NEFORCE_SIMD_NEON)
89 return ::vmvnq_u8(v);
90#else
91 vec128_t result;
92 for (int i = 0; i < 16; ++i) {
93 result.data[i] = static_cast<byte_t>(~v.data[i]);
94 }
95 return result;
96#endif
97}
98
105NEFORCE_ALWAYS_INLINE_INLINE vec128_t bit_andnot(vec128_t a, vec128_t b) noexcept {
106#ifdef NEFORCE_SIMD_SSE2
107 return ::_mm_andnot_si128(b, a);
108#elif defined(NEFORCE_SIMD_NEON)
109 return ::vbicq_u8(a, b);
110#else
111 vec128_t result;
112 for (int i = 0; i < 16; ++i) {
113 result.data[i] = a.data[i] & static_cast<byte_t>(~b.data[i]);
114 }
115 return result;
116#endif
117}
118
125NEFORCE_ALWAYS_INLINE_INLINE vec256_t bit_and(vec256_t a, vec256_t b) noexcept {
126#if defined(NEFORCE_SIMD_AVX2)
127 return ::_mm256_and_si256(a, b);
128#else
129 vec256_t result;
130 for (int i = 0; i < 32; ++i) {
131 result.data[i] = a.data[i] & b.data[i];
132 }
133 return result;
134#endif
135}
136
143NEFORCE_ALWAYS_INLINE_INLINE vec256_t bit_or(vec256_t a, vec256_t b) noexcept {
144#if defined(NEFORCE_SIMD_AVX2)
145 return ::_mm256_or_si256(a, b);
146#else
147 vec256_t result;
148 for (int i = 0; i < 32; ++i) {
149 result.data[i] = a.data[i] | b.data[i];
150 }
151 return result;
152#endif
153}
154
161NEFORCE_ALWAYS_INLINE_INLINE vec256_t bit_xor(vec256_t a, vec256_t b) noexcept {
162#if defined(NEFORCE_SIMD_AVX2)
163 return ::_mm256_xor_si256(a, b);
164#else
165 vec256_t result;
166 for (int i = 0; i < 32; ++i) {
167 result.data[i] = a.data[i] ^ b.data[i];
168 }
169 return result;
170#endif
171}
172
179NEFORCE_ALWAYS_INLINE_INLINE vec512_t bit_and(vec512_t a, vec512_t b) noexcept {
180#ifdef NEFORCE_SIMD_AVX512F
181 return ::_mm512_and_si512(a, b);
182#else
183 vec512_t result;
184 for (int i = 0; i < 64; ++i) {
185 result.data[i] = a.data[i] & b.data[i];
186 }
187 return result;
188#endif
189}
190
197NEFORCE_ALWAYS_INLINE_INLINE vec512_t bit_or(vec512_t a, vec512_t b) noexcept {
198#ifdef NEFORCE_SIMD_AVX512F
199 return ::_mm512_or_si512(a, b);
200#else
201 vec512_t result;
202 for (int i = 0; i < 64; ++i) {
203 result.data[i] = a.data[i] | b.data[i];
204 }
205 return result;
206#endif
207}
208
215NEFORCE_ALWAYS_INLINE_INLINE vec512_t bit_xor(vec512_t a, vec512_t b) noexcept {
216#ifdef NEFORCE_SIMD_AVX512F
217 return ::_mm512_xor_si512(a, b);
218#else
219 vec512_t result;
220 for (int i = 0; i < 64; ++i) {
221 result.data[i] = a.data[i] ^ b.data[i];
222 }
223 return result;
224#endif
225}
226
233template <int Bytes>
234NEFORCE_ALWAYS_INLINE_INLINE vec128_t shift_left_bytes(vec128_t v) noexcept {
235 static_assert(Bytes >= 0 && Bytes <= 16, "shift_left_bytes: Bytes must be in [0, 16]");
236#ifdef NEFORCE_SIMD_SSE2
237 return _mm_bslli_si128(v, Bytes);
238#elif defined(NEFORCE_SIMD_NEON)
239 return vextq_u8(::vdupq_n_u8(0), v, static_cast<int>(16 - Bytes));
240#else
241 vec128_t result;
242 for (int i = 0; i < Bytes; ++i) {
243 result.data[i] = 0;
244 }
245 for (int i = Bytes; i < 16; ++i) {
246 result.data[i] = v.data[i - Bytes];
247 }
248 return result;
249#endif
250}
251
252template <>
253NEFORCE_ALWAYS_INLINE_INLINE vec128_t shift_left_bytes<0>(vec128_t v) noexcept {
254 return v;
255}
256
263template <int Bytes>
264NEFORCE_ALWAYS_INLINE_INLINE vec128_t shift_right_bytes(vec128_t v) noexcept {
265 static_assert(Bytes >= 0 && Bytes <= 16, "shift_right_bytes: Bytes must be in [0, 16]");
266#ifdef NEFORCE_SIMD_SSE2
267 return _mm_bsrli_si128(v, Bytes);
268#elif defined(NEFORCE_SIMD_NEON)
269 return vextq_u8(v, ::vdupq_n_u8(0), static_cast<int>(Bytes));
270#else
271 vec128_t result;
272 for (int i = 0; i < 16 - Bytes; ++i) {
273 result.data[i] = v.data[i + Bytes];
274 }
275 for (int i = 16 - Bytes; i < 16; ++i) {
276 result.data[i] = 0;
277 }
278 return result;
279#endif
280}
281
282template <>
283NEFORCE_ALWAYS_INLINE_INLINE vec128_t shift_right_bytes<0>(vec128_t v) noexcept {
284 return v;
285}
286
292NEFORCE_ALWAYS_INLINE_INLINE int popcount(vec128_t v) noexcept {
293#if defined(NEFORCE_SIMD_SSSE3) || defined(NEFORCE_SIMD_AVX2)
294 const ::__m128i low_nibble = ::_mm_and_si128(v, ::_mm_set1_epi8(0x0F));
295 const ::__m128i high_nibble = ::_mm_and_si128(::_mm_srli_epi16(v, 4), ::_mm_set1_epi8(0x0F));
296 const ::__m128i lookup = ::_mm_setr_epi8(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4);
297 const ::__m128i pop_low = ::_mm_shuffle_epi8(lookup, low_nibble);
298 const ::__m128i pop_high = ::_mm_shuffle_epi8(lookup, high_nibble);
299 const ::__m128i pop8 = ::_mm_add_epi8(pop_low, pop_high);
300 const ::__m128i sums = ::_mm_sad_epu8(pop8, ::_mm_setzero_si128());
301 return ::_mm_extract_epi16(sums, 0) + ::_mm_extract_epi16(sums, 4);
302#elif defined(NEFORCE_SIMD_SSE2)
303 const auto* raw = reinterpret_cast<const byte_t*>(&v);
304 int total = 0;
305 for (int i = 0; i < 16; ++i) {
306 byte_t b = raw[i];
307 total += (b & 1) + ((b >> 1) & 1) + ((b >> 2) & 1) + ((b >> 3) & 1) + ((b >> 4) & 1) + ((b >> 5) & 1) +
308 ((b >> 6) & 1) + ((b >> 7) & 1);
309 }
310 return total;
311#elif defined(NEFORCE_SIMD_NEON)
312 const ::uint8x16_t low_nibble = ::vandq_u8(v, ::vdupq_n_u8(0x0F));
313 const ::uint8x16_t high_nibble = vshrq_n_u8(v, 4);
314 const ::uint8x16_t lookup = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
315 ::uint8x16_t pop = ::vaddq_u8(::vqtbl1q_u8(lookup, low_nibble), ::vqtbl1q_u8(lookup, high_nibble));
316# ifdef NEFORCE_ARCH_ARM
317 return static_cast<int>(::vaddvq_u8(pop));
318# else
319 int total = 0;
320 const auto* bytes = reinterpret_cast<const byte_t*>(&pop);
321 for (int i = 0; i < 16; ++i) {
322 total += bytes[i];
323 }
324 return total;
325# endif
326#else
327 int total = 0;
328 for (int i = 0; i < 16; ++i) {
329 byte_t b = v.data[i];
330 total += (b & 1) + ((b >> 1) & 1) + ((b >> 2) & 1) + ((b >> 3) & 1) + ((b >> 4) & 1) + ((b >> 5) & 1) +
331 ((b >> 6) & 1) + ((b >> 7) & 1);
332 }
333 return total;
334#endif
335}
336 // SIMD
338
339NEFORCE_END_SIMD__
340NEFORCE_END_NAMESPACE__
341#endif // NEFORCE_CORE_SIMD_BITWISE_HPP__
unsigned char byte_t
字节类型,定义为无符号字符
vec128_t bit_andnot(vec128_t a, vec128_t b) noexcept
按位与非
vec128_t bit_xor(vec128_t a, vec128_t b) noexcept
按位异或
::__m128i vec128_t
128-bit 整型向量(16×i8 / 8×i16 / 4×i32 / 2×i64)
int popcount(vec128_t v) noexcept
统计 128-bit 向量中置位比特总数
::__m256i vec256_t
256-bit 整型向量(32×i8 / 16×i16 / 8×i32 / 4×i64,需 AVX2)
::__m512i vec512_t
512-bit 整型向量(64×i8 / 32×i16 / 16×i32 / 8×i64)
vec128_t bit_and(vec128_t a, vec128_t b) noexcept
按位与
vec128_t bit_not(vec128_t v) noexcept
按位取反
vec128_t bit_or(vec128_t a, vec128_t b) noexcept
按位或
vec128_t shift_left_bytes(vec128_t v) noexcept
将 128-bit 向量按字节左移
vec128_t shift_right_bytes(vec128_t v) noexcept
将 128-bit 向量按字节右移
SIMD 向量类型定义