use crate::simd_native::{cosine_similarity_native, DistanceEngine, SimdLevel};
use crate::sparse_index::{SparseInvertedIndex, SparseVector};
use crate::velesql::{ParseError, Query, QueryCache};
use std::hash::{BuildHasher, Hasher};
#[must_use]
pub fn cosine_scalar(a: &[f32], b: &[f32]) -> f32 {
crate::simd_native::scalar::cosine_scalar(a, b)
}
#[must_use]
pub fn cosine_dispatch(a: &[f32], b: &[f32]) -> f32 {
cosine_similarity_native(a, b)
}
#[must_use]
pub fn cosine_resolved(a: &[f32], b: &[f32]) -> f32 {
let engine = DistanceEngine::new(a.len());
engine.cosine_similarity(a, b)
}
#[must_use]
pub fn detected_simd_level() -> SimdLevel {
crate::simd_native::simd_level()
}
#[cfg(target_arch = "x86_64")]
#[must_use]
pub fn cosine_avx2_2acc(a: &[f32], b: &[f32]) -> Option<f32> {
if std::arch::is_x86_feature_detected!("avx2") && std::arch::is_x86_feature_detected!("fma") {
Some(unsafe { crate::simd_native::cosine_fused_avx2_2acc(a, b) })
} else {
None
}
}
#[cfg(target_arch = "x86_64")]
#[must_use]
pub fn cosine_avx2_4acc(a: &[f32], b: &[f32]) -> Option<f32> {
if std::arch::is_x86_feature_detected!("avx2") && std::arch::is_x86_feature_detected!("fma") {
Some(unsafe { crate::simd_native::cosine_fused_avx2(a, b) })
} else {
None
}
}
#[cfg(target_arch = "x86_64")]
#[must_use]
pub fn cosine_avx512(a: &[f32], b: &[f32]) -> Option<f32> {
if std::arch::is_x86_feature_detected!("avx512f") {
Some(unsafe { crate::simd_native::cosine_fused_avx512(a, b) })
} else {
None
}
}
pub fn sparse_insert_batch(index: &SparseInvertedIndex, docs: &[(u64, SparseVector)]) {
index.insert_batch_chunk(docs);
}
pub fn velesql_parse_without_stats(cache: &QueryCache, query: &str) -> Result<Query, ParseError> {
cache.parse_without_stats(query)
}
#[must_use]
pub fn velesql_canonical_hash(query: &str) -> u64 {
let canonical = query.split_whitespace().collect::<Vec<_>>().join(" ");
let mut hasher = rustc_hash::FxBuildHasher.build_hasher();
hasher.write(canonical.as_bytes());
hasher.finish()
}