17#ifndef PACS_ENCODING_SIMD_CONFIG_HPP
18#define PACS_ENCODING_SIMD_CONFIG_HPP
25 #define PACS_COMPILER_MSVC 1
26#elif defined(__clang__)
27 #define PACS_COMPILER_CLANG 1
28#elif defined(__GNUC__)
29 #define PACS_COMPILER_GCC 1
33#if defined(__x86_64__) || defined(_M_X64)
34 #define PACS_ARCH_X64 1
35#elif defined(__i386__) || defined(_M_IX86)
36 #define PACS_ARCH_X86 1
37#elif defined(__aarch64__) || defined(_M_ARM64)
38 #define PACS_ARCH_ARM64 1
39#elif defined(__arm__) || defined(_M_ARM)
40 #define PACS_ARCH_ARM32 1
44#if defined(PACS_ARCH_X64) || defined(PACS_ARCH_X86)
45 #if defined(__AVX512F__)
46 #define PACS_SIMD_AVX512 1
49 #define PACS_SIMD_AVX2 1
52 #define PACS_SIMD_AVX 1
54 #if defined(__SSE4_1__)
55 #define PACS_SIMD_SSE41 1
57 #if defined(__SSSE3__)
58 #define PACS_SIMD_SSSE3 1
60 #if defined(__SSE2__) || defined(_M_X64)
61 #define PACS_SIMD_SSE2 1
63#elif defined(PACS_ARCH_ARM64) || defined(PACS_ARCH_ARM32)
64 #if defined(__ARM_NEON) || defined(__ARM_NEON__)
65 #define PACS_SIMD_NEON 1
70#if defined(PACS_SIMD_AVX512) || defined(PACS_SIMD_AVX2) || \
71 defined(PACS_SIMD_AVX) || defined(PACS_SIMD_SSE41) || \
72 defined(PACS_SIMD_SSSE3) || defined(PACS_SIMD_SSE2)
73 #if defined(PACS_COMPILER_MSVC)
76 #include <x86intrin.h>
78#elif defined(PACS_SIMD_NEON)
103 return static_cast<simd_feature>(
static_cast<uint32_t
>(a) |
104 static_cast<uint32_t
>(b));
112 return static_cast<simd_feature>(
static_cast<uint32_t
>(a) &
113 static_cast<uint32_t
>(b));
121 return (features & check) == check;
126#if defined(PACS_ARCH_X64) || defined(PACS_ARCH_X86)
131inline void cpuid(
int info[4],
int function_id)
noexcept {
132#if defined(PACS_COMPILER_MSVC)
133 __cpuid(info, function_id);
135 __asm__ __volatile__(
137 :
"=a"(info[0]),
"=b"(info[1]),
"=c"(info[2]),
"=d"(info[3])
138 :
"a"(function_id),
"c"(0));
145inline void cpuid_ex(
int info[4],
int function_id,
int sub_function)
noexcept {
146#if defined(PACS_COMPILER_MSVC)
147 __cpuidex(info, function_id, sub_function);
149 __asm__ __volatile__(
151 :
"=a"(info[0]),
"=b"(info[1]),
"=c"(info[2]),
"=d"(info[3])
152 :
"a"(function_id),
"c"(sub_function));
167#if defined(PACS_ARCH_X64) || defined(PACS_ARCH_X86)
171 detail::cpuid(info, 0);
172 int max_function = info[0];
174 if (max_function >= 1) {
175 detail::cpuid(info, 1);
178 if (info[3] & (1 << 26)) {
183 if (info[2] & (1 << 0)) {
186 if (info[2] & (1 << 19)) {
189 if (info[2] & (1 << 28)) {
194 if (max_function >= 7) {
195 detail::cpuid_ex(info, 7, 0);
198 if (info[1] & (1 << 5)) {
201 if (info[1] & (1 << 16)) {
206#elif defined(PACS_ARCH_ARM64)
210#elif defined(PACS_ARCH_ARM32)
213#if defined(PACS_SIMD_NEON)
size_t optimal_vector_width() noexcept
Get optimal vector width in bytes for current CPU.
bool has_neon() noexcept
Check if NEON is available.
bool has_sse2() noexcept
Check if SSE2 is available.
constexpr bool has_feature(simd_feature features, simd_feature check) noexcept
Check if a specific feature is set.
simd_feature detect_features() noexcept
Detect available SIMD features at runtime.
constexpr simd_feature operator&(simd_feature a, simd_feature b) noexcept
Bitwise AND for simd_feature flags.
bool has_avx2() noexcept
Check if AVX2 is available.
bool has_ssse3() noexcept
Check if SSSE3 is available.
simd_feature get_features() noexcept
Get cached SIMD features (singleton pattern)
bool has_avx() noexcept
Check if AVX is available.
bool has_avx512f() noexcept
Check if AVX-512F is available.
constexpr simd_feature operator|(simd_feature a, simd_feature b) noexcept
Bitwise OR for simd_feature flags.
bool has_sse41() noexcept
Check if SSE4.1 is available.
simd_feature
SIMD feature flags for runtime detection.