@@ -38,6 +38,43 @@ extern void *malloc(size_t length);
38
38
#endif
39
39
#endif
40
40
41
+ // On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
42
+ #if defined(__APPLE__ ) && defined(__MACH__ )
43
+ #define SZ_APPLE 1
44
+ #include <sys/sysctl.h>
45
+ #endif
46
+
47
+ #if defined(__linux__ )
48
+ #define SZ_LINUX 1
49
+ #endif
50
+
51
+ SZ_INTERNAL sz_capability_t sz_capabilities_arm (void ) {
52
+ // https://github.com/ashvardanian/SimSIMD/blob/28e536083602f85ad0c59456782c8864463ffb0e/include/simsimd/simsimd.h#L434
53
+ // for documentation on how we detect capabilities across different ARM platforms.
54
+ #if defined(SZ_APPLE )
55
+
56
+ // On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
57
+ uint32_t supports_neon = 0 ;
58
+ size_t size = sizeof (supports_neon );
59
+ if (sysctlbyname ("hw.optional.neon" , & supports_neon , & size , NULL , 0 ) != 0 ) supports_neon = 0 ;
60
+
61
+ return (sz_capability_t )( //
62
+ (sz_cap_arm_neon_k * (supports_neon )) | //
63
+ (sz_cap_serial_k ));
64
+
65
+ #elif defined(SZ_LINUX )
66
+ unsigned supports_neon = 1 ; // NEON is always supported
67
+ __asm__ __volatile__("mrs %0, ID_AA64PFR0_EL1" : "=r" (id_aa64pfr0_el1 ));
68
+ unsigned supports_sve = ((id_aa64pfr0_el1 >> 32 ) & 0xF ) >= 1 ;
69
+ return (sz_capability_t )( //
70
+ (sz_cap_neon_k * (supports_neon )) | //
71
+ (sz_cap_sve_k * (supports_sve )) | //
72
+ (sz_cap_serial_k ));
73
+ #else // SIMSIMD_DEFINED_LINUX
74
+ return sz_cap_serial_k ;
75
+ #endif
76
+ }
77
+
41
78
SZ_DYNAMIC sz_capability_t sz_capabilities (void ) {
42
79
43
80
#if SZ_USE_X86_AVX512 || SZ_USE_X86_AVX2
@@ -96,22 +133,12 @@ SZ_DYNAMIC sz_capability_t sz_capabilities(void) {
96
133
97
134
#if SZ_USE_ARM_NEON || SZ_USE_ARM_SVE
98
135
99
- // Every 64-bit Arm CPU supports NEON
100
- unsigned supports_neon = 1 ;
101
- unsigned supports_sve = 0 ;
102
- unsigned supports_sve2 = 0 ;
103
- sz_unused (supports_sve );
104
- sz_unused (supports_sve2 );
105
-
106
- return (sz_capability_t )( //
107
- (sz_cap_arm_neon_k * supports_neon ) | //
108
- (sz_cap_serial_k ));
136
+ return sz_capabilities_arm ();
109
137
110
138
#endif // SIMSIMD_TARGET_ARM
111
139
112
140
return sz_cap_serial_k ;
113
141
}
114
-
115
142
typedef struct sz_implementations_t {
116
143
sz_equal_t equal ;
117
144
sz_order_t order ;
0 commit comments