pub trait Feature<G>: Sized {
fn get_support(runtime: &RuntimeSupport) -> Option<Self>;
}
pub trait FeatureSet<G>: Sized {
fn get_support(runtime: &RuntimeSupport) -> Option<Self>;
}
impl<G> FeatureSet<G> for () {
fn get_support(_: &RuntimeSupport) -> Option<Self> {
Some(())
}
}
impl<G, H, T> FeatureSet<G> for (H, T)
where H: Feature<G>, T: FeatureSet<G> {
fn get_support(runtime: &RuntimeSupport) -> Option<Self> {
Some((H::get_support(runtime)?, T::get_support(runtime)?))
}
}
#[marker]
pub unsafe trait HasFeature<G, F: Feature<G>>: FeatureSet<G> {}
unsafe impl<G, H, T> HasFeature<G, H> for (H, T)
where H: Feature<G>, T: FeatureSet<G> {}
unsafe impl<G, F, H, T> HasFeature<G, F> for (H, T)
where F: Feature<G>, H: Feature<G>, T: HasFeature<G, F> {}
unsafe impl<G, F> HasFeature<G, F> for ()
where F: Feature<G> {}
pub struct RuntimeSupport {
sse: bool,
sse2: bool,
sse3: bool,
ssse3: bool,
sse4_1: bool,
sse4_2: bool,
avx: bool,
f16c: bool,
fma: bool,
avx2: bool,
}
impl RuntimeSupport {
pub fn detect() -> Self {
use raw_cpuid::CpuId;
let cpuid = CpuId::new();
let feats = cpuid.get_feature_info();
let feats = feats.as_ref();
let efeats = cpuid.get_extended_feature_info();
let efeats = efeats.as_ref();
Self {
sse: feats.is_some_and(|x| x.has_sse()),
sse2: feats.is_some_and(|x| x.has_sse2()),
sse3: feats.is_some_and(|x| x.has_sse3()),
ssse3: feats.is_some_and(|x| x.has_ssse3()),
sse4_1: feats.is_some_and(|x| x.has_sse41()),
sse4_2: feats.is_some_and(|x| x.has_sse42()),
avx: feats.is_some_and(|x| x.has_avx()),
f16c: feats.is_some_and(|x| x.has_f16c()),
fma: feats.is_some_and(|x| x.has_fma()),
avx2: efeats.is_some_and(|x| x.has_avx2()),
}
}
pub fn sse(&self) -> bool {
self.sse
}
pub fn sse2(&self) -> bool {
self.sse2
}
pub fn sse3(&self) -> bool {
self.sse3
}
pub fn ssse3(&self) -> bool {
self.ssse3
}
pub fn sse4_1(&self) -> bool {
self.sse4_1
}
pub fn sse4_2(&self) -> bool {
self.sse4_2
}
pub fn avx(&self) -> bool {
self.avx
}
pub fn f16c(&self) -> bool {
self.f16c
}
pub fn fma(&self) -> bool {
self.fma
}
pub fn avx2(&self) -> bool {
self.avx2
}
}