#[cfg(target_os = "macos")]
#[allow(unused)]
pub mod macos {
pub(super) fn test_for_avx512_on_macos() -> bool {
use std::sync::OnceLock;
static AVX512_AVAILABLE: OnceLock<bool> = OnceLock::new();
*AVX512_AVAILABLE.get_or_init(|| {
sysctl_bool(c"hw.optional.avx512vl").unwrap_or(false)
&& sysctl_bool(c"hw.optional.avx512bw").unwrap_or(false)
&& sysctl_bool(c"hw.optional.avx512dq").unwrap_or(false)
})
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct SysctlError(i32);
pub fn sysctl_int(name: &std::ffi::CStr) -> Result<i64, SysctlError> {
use std::os::raw::{c_char, c_int, c_void};
#[link(name = "c")]
unsafe extern "C" {
fn sysctlbyname(
name: *const c_char,
oldp: *mut c_void,
oldlenp: *mut usize,
newp: *const c_void,
newlen: usize,
) -> c_int;
}
let mut result = 0i64;
let mut size = std::mem::size_of::<i64>();
let sysctl_ret = unsafe {
sysctlbyname(
name.as_ptr(),
&mut result as *mut i64 as *mut c_void,
&mut size,
std::ptr::null(),
0,
)
};
if sysctl_ret != 0 {
return Err(SysctlError(sysctl_ret));
}
Ok(result)
}
pub fn sysctl_bool(name: &std::ffi::CStr) -> Result<bool, SysctlError> {
sysctl_int(name).map(|val| val == 1)
}
}
#[cfg(target_arch = "x86_64")]
pub fn is_avx512_supported() -> bool {
if is_x86_feature_detected!("avx512f")
&& is_x86_feature_detected!("avx512vl")
&& is_x86_feature_detected!("avx512bw")
&& is_x86_feature_detected!("avx512dq")
{
true
} else {
#[cfg(target_os = "macos")]
{
macos::test_for_avx512_on_macos()
}
#[cfg(not(target_os = "macos"))]
{
false
}
}
}
#[cfg(test)]
mod tests {
#[cfg(target_arch = "x86_64")]
use super::is_avx512_supported;
#[cfg(target_arch = "x86_64")]
#[test]
fn test_is_avx512_supported() {
is_avx512_supported();
}
}