use std::io::Error;
#[cfg(target_os = "linux")]
use procfs::{CpuInfo, Current};
#[cfg(target_os = "linux")]
pub(crate) fn detect_hardware_floating_point_support() -> Result<bool, Error> {
let cpu_info = CpuInfo::current().map_err(Error::other)?;
if let Some(features) = cpu_info.fields.get("Features") {
if has_hardware_float_features(features) {
return Ok(true);
}
}
Ok(false) }
#[cfg(target_os = "linux")]
fn has_hardware_float_features(features: &str) -> bool {
features
.split_whitespace()
.any(|feature| feature == "vfp" || feature == "fp")
}
#[cfg(not(target_os = "linux"))]
#[expect(clippy::unnecessary_wraps)]
pub(crate) fn detect_hardware_floating_point_support() -> Result<bool, Error> {
Ok(false) }
#[cfg(test)]
mod tests {
#[cfg(target_os = "linux")]
use super::has_hardware_float_features;
#[test]
#[cfg(target_os = "linux")]
fn arm32_native_hard_float() {
let features = "half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32";
assert!(has_hardware_float_features(features));
}
#[test]
#[cfg(target_os = "linux")]
fn aarch64_kernel_with_arm32_userspace() {
let features =
"fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm";
assert!(has_hardware_float_features(features));
}
#[test]
#[cfg(target_os = "linux")]
fn arm32_soft_float() {
let features = "swp half thumb fastmult edsp";
assert!(!has_hardware_float_features(features));
}
#[test]
#[cfg(target_os = "linux")]
fn fp_only_matches_as_discrete_token() {
let features = "asimd fphp asimdhp";
assert!(!has_hardware_float_features(features));
}
}