mod activations;
mod argmax;
#[cfg(feature = "binary_plasma")]
pub mod binary;
mod dot;
mod elementwise;
mod horizontal;
mod maxsim;
mod research;
mod sparse;
mod ternary;
#[cfg(test)]
mod tests;
#[cfg(test)]
mod tests_sense;
#[cfg(test)]
use dot::{scalar_dot_f32, scalar_outer_product_acc};
#[cfg(test)]
use elementwise::{
scalar_add_inplace, scalar_add_into, scalar_add_scalar_inplace, scalar_fused_decay_write,
scalar_max_f32, scalar_scale_inplace, scalar_sum_f32,
};
#[cfg(test)]
use research::scalar_l_inf_distance_f32;
#[cfg(test)]
use research::scalar_sum_sq_quartic;
#[cfg(test)]
use sparse::scalar_sparse_dot_f32;
pub use activations::{
cephes_exp_scalar, fast_exp, fast_sigmoid, fast_tanh, simd_exp_inplace, simd_exp_sum_inplace,
simd_reciprocal_inplace, simd_sigmoid_inplace, simd_sigmoid_tanh_clamp_inplace,
simd_tanh_inplace,
};
pub use argmax::simd_argmax_f32;
pub use dot::{
simd_dot_f16_f16, simd_dot_f16_f32, simd_dot_f32, simd_fma_row, simd_matmul_f16_f16_rows,
simd_matmul_f16_f16_rows_parallel, simd_matmul_f16_f32_rows, simd_matmul_f16_f32_rows_parallel,
simd_matmul_relu_rows, simd_matmul_rows, simd_matmul_rows_parallel, simd_matvec,
simd_outer_product_acc, simd_outer_product_acc_scaled,
};
pub use elementwise::{
simd_add_inplace, simd_add_into, simd_add_scalar_inplace, simd_fused_decay_write,
simd_fused_sub_scale_inplace, simd_masked_sum_count_f32, simd_max_f32, simd_scale_inplace,
simd_scale_mul_inplace, simd_sum_f32,
};
#[cfg(feature = "binary_plasma")]
pub use binary::{binary_matvec_scalar, simd_binary_matmul_batch, simd_binary_matvec};
#[cfg(feature = "maxsim")]
pub use maxsim::{maxsim_score, maxsim_score_packed};
pub use research::{
coincidence_score, entropy_f32, simd_dist_sq, simd_fused_scale_acc, simd_fused_scale_acc_f16,
simd_fused_sub_acc, simd_gram_f32, simd_l_inf_distance_f32, simd_sum_abs_f32, simd_sum_sq,
simd_sum_sq_quartic,
};
#[cfg(feature = "sigmoid_margin")]
pub use research::{compute_retrieval_margin, dim_sufficiency_bound, sigmoid_margin_loss};
pub use sparse::{simd_sparse_dot_f32, simd_sparse_matmul_rows};
pub use ternary::simd_ternary_dot_f32;
#[cfg(feature = "plasma_path")]
pub use ternary::{
project_ternary_simd, project_ternary_simd_scalar, simd_ternary_matmul_batch,
simd_ternary_matvec, ternary_matvec_scalar,
};
#[cfg(all(
feature = "plasma_path",
target_arch = "wasm32",
target_feature = "simd128"
))]
pub use ternary::project_ternary_simd_wasm32;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SimdLevel {
Scalar,
Neon,
Avx2,
WasmSimd128,
}
#[inline]
pub fn simd_level() -> SimdLevel {
#[cfg(target_arch = "aarch64")]
{
SimdLevel::Neon
}
#[cfg(target_arch = "x86_64")]
{
if is_avx2_fma_available() {
SimdLevel::Avx2
} else {
SimdLevel::Scalar
}
}
#[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
{
SimdLevel::WasmSimd128
}
#[cfg(not(any(
target_arch = "aarch64",
target_arch = "x86_64",
all(target_arch = "wasm32", target_feature = "simd128")
)))]
{
SimdLevel::Scalar
}
}
#[cfg(target_arch = "x86_64")]
pub(super) fn is_avx2_fma_available() -> bool {
#[cfg(target_feature = "avx2")]
{
true
}
#[cfg(not(target_feature = "avx2"))]
{
use std::sync::atomic::{AtomicBool, Ordering};
static CACHED: AtomicBool = AtomicBool::new(false);
static INIT: std::sync::Once = std::sync::Once::new();
#[allow(unused_unsafe)]
INIT.call_once(|| {
let cpuid1 = unsafe { core::arch::x86_64::__cpuid(1) };
let has_avx = (cpuid1.ecx & (1 << 28)) != 0;
let has_fma = (cpuid1.ecx & (1 << 12)) != 0;
let cpuid7 = unsafe { core::arch::x86_64::__cpuid(7) };
let has_avx2 = (cpuid7.ebx & (1 << 5)) != 0;
CACHED.store(has_avx && has_fma && has_avx2, Ordering::Relaxed);
});
CACHED.load(Ordering::Relaxed)
}
}