#[cfg(target_arch = "x86_64")]
use super::has_avx512vpopcntdq;
use super::{simd_level, SimdLevel};
#[inline]
#[must_use]
pub fn hamming_distance_native(a: &[f32], b: &[f32]) -> f32 {
assert_eq!(
a.len(),
b.len(),
"Vector length mismatch: {} vs {}",
a.len(),
b.len()
);
hamming_simd(a, b)
}
#[inline]
#[must_use]
pub fn jaccard_similarity_native(a: &[f32], b: &[f32]) -> f32 {
assert_eq!(
a.len(),
b.len(),
"Vector length mismatch: {} vs {}",
a.len(),
b.len()
);
jaccard_simd(a, b)
}
#[inline]
fn hamming_simd(a: &[f32], b: &[f32]) -> f32 {
match simd_level() {
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if a.len() >= 512 => {
unsafe { crate::simd_native::hamming_avx512_4acc(a, b) }
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if a.len() >= 16 => {
unsafe { crate::simd_native::hamming_avx512(a, b) }
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 | SimdLevel::Avx2 if a.len() >= 8 => {
unsafe { crate::simd_native::hamming_avx2(a, b) }
}
#[cfg(target_arch = "aarch64")]
SimdLevel::Neon if a.len() >= 4 => crate::simd_native::hamming_neon(a, b),
_ => crate::simd_native::scalar::hamming_scalar(a, b),
}
}
#[inline]
fn jaccard_simd(a: &[f32], b: &[f32]) -> f32 {
match simd_level() {
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if a.len() >= 1024 => {
unsafe { crate::simd_native::jaccard_avx512_8acc(a, b) }
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if a.len() >= 512 => {
unsafe { crate::simd_native::jaccard_avx512_4acc(a, b) }
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if a.len() >= 16 => {
unsafe { crate::simd_native::jaccard_avx512(a, b) }
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 | SimdLevel::Avx2 if a.len() >= 8 => {
unsafe { crate::simd_native::jaccard_avx2(a, b) }
}
#[cfg(target_arch = "aarch64")]
SimdLevel::Neon if a.len() >= 4 => crate::simd_native::jaccard_neon(a, b),
_ => crate::simd_native::scalar::jaccard_scalar(a, b),
}
}
#[allow(unused_variables)]
pub(super) fn resolve_hamming(level: SimdLevel, dim: usize) -> fn(&[f32], &[f32]) -> f32 {
match level {
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if dim >= 512 => {
|a, b| {
unsafe { crate::simd_native::hamming_avx512_4acc(a, b) }
}
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if dim >= 16 => {
|a, b| {
unsafe { crate::simd_native::hamming_avx512(a, b) }
}
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 | SimdLevel::Avx2 if dim >= 8 => |a, b| {
unsafe { crate::simd_native::hamming_avx2(a, b) }
},
#[cfg(target_arch = "aarch64")]
SimdLevel::Neon if dim >= 4 => |a, b| crate::simd_native::hamming_neon(a, b),
_ => crate::simd_native::scalar::hamming_scalar,
}
}
#[allow(unused_variables)]
pub(super) fn resolve_jaccard(level: SimdLevel, dim: usize) -> fn(&[f32], &[f32]) -> f32 {
match level {
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if dim >= 1024 => {
|a, b| {
unsafe { crate::simd_native::jaccard_avx512_8acc(a, b) }
}
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if dim >= 512 => {
|a, b| {
unsafe { crate::simd_native::jaccard_avx512_4acc(a, b) }
}
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if dim >= 16 => {
|a, b| {
unsafe { crate::simd_native::jaccard_avx512(a, b) }
}
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 | SimdLevel::Avx2 if dim >= 8 => |a, b| {
unsafe { crate::simd_native::jaccard_avx2(a, b) }
},
#[cfg(target_arch = "aarch64")]
SimdLevel::Neon if dim >= 4 => |a, b| crate::simd_native::jaccard_neon(a, b),
_ => crate::simd_native::scalar::jaccard_scalar,
}
}
#[inline]
#[must_use]
#[allow(clippy::cast_possible_truncation)]
pub fn hamming_binary_native(a: &[u64], b: &[u64]) -> u32 {
assert_eq!(
a.len(),
b.len(),
"Binary vector length mismatch: {} vs {}",
a.len(),
b.len()
);
match simd_level() {
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if a.len() >= 8 && has_avx512vpopcntdq() => {
unsafe { crate::simd_native::hamming_binary_avx512_vpopcntdq(a, b) }
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 if a.len() >= 8 => {
unsafe { crate::simd_native::hamming_binary_avx512(a, b) }
}
#[cfg(target_arch = "x86_64")]
SimdLevel::Avx512 | SimdLevel::Avx2 if a.len() >= 4 => {
unsafe { crate::simd_native::hamming_binary_avx2(a, b) }
}
#[cfg(target_arch = "aarch64")]
SimdLevel::Neon if a.len() >= 2 => {
crate::simd_native::hamming_binary_neon(a, b)
}
_ => crate::simd_native::scalar::hamming_binary_scalar(a, b),
}
}
#[inline]
#[must_use]
pub fn batch_hamming_native(candidates: &[&[f32]], query: &[f32]) -> Vec<f32> {
super::batch_with_prefetch(candidates, query, hamming_distance_native)
}
#[inline]
#[must_use]
pub fn batch_jaccard_native(candidates: &[&[f32]], query: &[f32]) -> Vec<f32> {
super::batch_with_prefetch(candidates, query, jaccard_similarity_native)
}