From 07098606b9490499a29da09decfcba5918ccf1f7 Mon Sep 17 00:00:00 2001 From: Ash Vardanian <1983160+ashvardanian@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:43:28 +0000 Subject: [PATCH 1/5] Fix: Gating `core::fmt` in Rust --- rust/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rust/lib.rs b/rust/lib.rs index 3ace87d9..8e1f1956 100644 --- a/rust/lib.rs +++ b/rust/lib.rs @@ -72,7 +72,7 @@ //! - `kullbackleibler(a: &[Self], b: &[Self]) -> Option`: Computes Kullback-Leibler divergence between two slices. //! #![allow(non_camel_case_types)] -#![cfg_attr(not(test), no_std)] +#![cfg_attr(all(not(test), not(feature = "std")), no_std)] pub type Distance = f64; pub type ComplexProduct = (f64, f64); @@ -289,8 +289,8 @@ impl f16 { } #[cfg(feature = "std")] -impl std::fmt::Display for f16 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for f16 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", self.to_f32()) } } @@ -463,8 +463,8 @@ impl bf16 { } #[cfg(feature = "std")] -impl std::fmt::Display for bf16 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for bf16 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", self.to_f32()) } } From f473b2b09b0ce96e6b08e9fdcf36eaf0815c1bd9 Mon Sep 17 00:00:00 2001 From: Ash Vardanian <1983160+ashvardanian@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:46:38 +0000 Subject: [PATCH 2/5] Make: 32-bit cross-compilation for Rust --- .github/workflows/prerelease.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index e9e70899..877f7418 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -184,9 +184,28 @@ jobs: - name: Install Rust toolchain uses: moonrepo/setup-rust@v1 - - name: Build and Test + - name: Install 32-bit target and dependencies + run: | + rustup target add i686-unknown-linux-gnu + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y gcc-multilib g++-multilib libc6-dev-i386 + + - name: Test default build run: cargo test + - name: Test with all features + run: cargo test --all-features + + - name: Test no-std build (check only) + run: cargo check --no-default-features + + - name: Test i686 cross-compilation build + run: cargo build --target i686-unknown-linux-gnu --all-features + + - name: Test i686 cross-compilation (no-std) + run: cargo build --target i686-unknown-linux-gnu --no-default-features + # Temporary workaround to run Swift tests on Linux # Based on: https://github.com/swift-actions/setup-swift/issues/591#issuecomment-1685710678 test_ubuntu_swift: From 5a386f555896d8a5de2410a19ed029d58c09e54d Mon Sep 17 00:00:00 2001 From: Ash Vardanian <1983160+ashvardanian@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:50:27 +0000 Subject: [PATCH 3/5] Make: Stack-realign for `i386` builds Relates to #280 --- build.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build.rs b/build.rs index d513690e..741f43f8 100644 --- a/build.rs +++ b/build.rs @@ -13,10 +13,16 @@ fn main() -> Result<(), cc::Error> { .flag_if_supported("-pedantic") // Strict compliance when supported .warnings(false); + // On 32-bit x86, ensure proper stack alignment for floating-point operations + // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38534 + let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); + if target_arch == "x86" { + build.flag_if_supported("-mstackrealign"); + build.flag_if_supported("-mpreferred-stack-boundary=4"); + } + if let Err(e) = build.try_compile("simsimd") { print!("cargo:warning=Failed to compile with all SIMD backends..."); - - let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); let flags_to_try = match target_arch.as_str() { "arm" | "aarch64" => vec![ "SIMSIMD_TARGET_SVE2", From 31195e9aa8aef76f0471a5d2aa9259176a91c7e7 Mon Sep 17 00:00:00 2001 From: Ash Vardanian <1983160+ashvardanian@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:51:30 +0000 Subject: [PATCH 4/5] Fix: `u64size` in Rust to match the C ABI Closes #280 --- rust/lib.rs | 204 +++++++++++++++++++++++++++++----------------------- 1 file changed, 114 insertions(+), 90 deletions(-) diff --git a/rust/lib.rs b/rust/lib.rs index 8e1f1956..b38ad1a1 100644 --- a/rust/lib.rs +++ b/rust/lib.rs @@ -77,6 +77,14 @@ pub type Distance = f64; pub type ComplexProduct = (f64, f64); +/// Size type used in C FFI to match `simsimd_size_t` which is always `uint64_t`. +/// This is aliased to `u64` instead of `usize` to maintain ABI compatibility across +/// all platforms, including 32-bit architectures where `usize` is 32-bit but the +/// C library expects 64-bit size parameters. +/// +/// TODO: In v7, change the C library to use `size_t` and this to `usize`. +type u64size = u64; + /// Compatibility function for pre 1.85 Rust versions lacking `f32::abs`. #[inline(always)] fn f32_abs_compat(x: f32) -> f32 { @@ -86,65 +94,65 @@ fn f32_abs_compat(x: f32) -> f32 { #[link(name = "simsimd")] extern "C" { - fn simsimd_dot_i8(a: *const i8, b: *const i8, c: usize, d: *mut Distance); - fn simsimd_dot_f16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_dot_bf16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_dot_f32(a: *const f32, b: *const f32, c: usize, d: *mut Distance); - fn simsimd_dot_f64(a: *const f64, b: *const f64, c: usize, d: *mut Distance); - - fn simsimd_dot_f16c(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_dot_bf16c(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_dot_f32c(a: *const f32, b: *const f32, c: usize, d: *mut Distance); - fn simsimd_dot_f64c(a: *const f64, b: *const f64, c: usize, d: *mut Distance); - - fn simsimd_vdot_f16c(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_vdot_bf16c(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_vdot_f32c(a: *const f32, b: *const f32, c: usize, d: *mut Distance); - fn simsimd_vdot_f64c(a: *const f64, b: *const f64, c: usize, d: *mut Distance); - - fn simsimd_cos_i8(a: *const i8, b: *const i8, c: usize, d: *mut Distance); - fn simsimd_cos_f16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_cos_bf16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_cos_f32(a: *const f32, b: *const f32, c: usize, d: *mut Distance); - fn simsimd_cos_f64(a: *const f64, b: *const f64, c: usize, d: *mut Distance); - - fn simsimd_l2sq_i8(a: *const i8, b: *const i8, c: usize, d: *mut Distance); - fn simsimd_l2sq_f16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_l2sq_bf16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_l2sq_f32(a: *const f32, b: *const f32, c: usize, d: *mut Distance); - fn simsimd_l2sq_f64(a: *const f64, b: *const f64, c: usize, d: *mut Distance); - - fn simsimd_l2_i8(a: *const i8, b: *const i8, c: usize, d: *mut Distance); - fn simsimd_l2_f16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_l2_bf16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_l2_f32(a: *const f32, b: *const f32, c: usize, d: *mut Distance); - fn simsimd_l2_f64(a: *const f64, b: *const f64, c: usize, d: *mut Distance); - - fn simsimd_hamming_b8(a: *const u8, b: *const u8, c: usize, d: *mut Distance); - fn simsimd_jaccard_b8(a: *const u8, b: *const u8, c: usize, d: *mut Distance); - - fn simsimd_js_f16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_js_bf16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_js_f32(a: *const f32, b: *const f32, c: usize, d: *mut Distance); - fn simsimd_js_f64(a: *const f64, b: *const f64, c: usize, d: *mut Distance); - - fn simsimd_kl_f16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_kl_bf16(a: *const u16, b: *const u16, c: usize, d: *mut Distance); - fn simsimd_kl_f32(a: *const f32, b: *const f32, c: usize, d: *mut Distance); - fn simsimd_kl_f64(a: *const f64, b: *const f64, c: usize, d: *mut Distance); + fn simsimd_dot_i8(a: *const i8, b: *const i8, c: u64size, d: *mut Distance); + fn simsimd_dot_f16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_dot_bf16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_dot_f32(a: *const f32, b: *const f32, c: u64size, d: *mut Distance); + fn simsimd_dot_f64(a: *const f64, b: *const f64, c: u64size, d: *mut Distance); + + fn simsimd_dot_f16c(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_dot_bf16c(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_dot_f32c(a: *const f32, b: *const f32, c: u64size, d: *mut Distance); + fn simsimd_dot_f64c(a: *const f64, b: *const f64, c: u64size, d: *mut Distance); + + fn simsimd_vdot_f16c(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_vdot_bf16c(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_vdot_f32c(a: *const f32, b: *const f32, c: u64size, d: *mut Distance); + fn simsimd_vdot_f64c(a: *const f64, b: *const f64, c: u64size, d: *mut Distance); + + fn simsimd_cos_i8(a: *const i8, b: *const i8, c: u64size, d: *mut Distance); + fn simsimd_cos_f16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_cos_bf16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_cos_f32(a: *const f32, b: *const f32, c: u64size, d: *mut Distance); + fn simsimd_cos_f64(a: *const f64, b: *const f64, c: u64size, d: *mut Distance); + + fn simsimd_l2sq_i8(a: *const i8, b: *const i8, c: u64size, d: *mut Distance); + fn simsimd_l2sq_f16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_l2sq_bf16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_l2sq_f32(a: *const f32, b: *const f32, c: u64size, d: *mut Distance); + fn simsimd_l2sq_f64(a: *const f64, b: *const f64, c: u64size, d: *mut Distance); + + fn simsimd_l2_i8(a: *const i8, b: *const i8, c: u64size, d: *mut Distance); + fn simsimd_l2_f16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_l2_bf16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_l2_f32(a: *const f32, b: *const f32, c: u64size, d: *mut Distance); + fn simsimd_l2_f64(a: *const f64, b: *const f64, c: u64size, d: *mut Distance); + + fn simsimd_hamming_b8(a: *const u8, b: *const u8, c: u64size, d: *mut Distance); + fn simsimd_jaccard_b8(a: *const u8, b: *const u8, c: u64size, d: *mut Distance); + + fn simsimd_js_f16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_js_bf16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_js_f32(a: *const f32, b: *const f32, c: u64size, d: *mut Distance); + fn simsimd_js_f64(a: *const f64, b: *const f64, c: u64size, d: *mut Distance); + + fn simsimd_kl_f16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_kl_bf16(a: *const u16, b: *const u16, c: u64size, d: *mut Distance); + fn simsimd_kl_f32(a: *const f32, b: *const f32, c: u64size, d: *mut Distance); + fn simsimd_kl_f64(a: *const f64, b: *const f64, c: u64size, d: *mut Distance); fn simsimd_intersect_u16( a: *const u16, b: *const u16, - a_length: usize, - b_length: usize, + a_length: u64size, + b_length: u64size, d: *mut Distance, ); fn simsimd_intersect_u32( a: *const u32, b: *const u32, - a_length: usize, - b_length: usize, + a_length: u64size, + b_length: u64size, d: *mut Distance, ); @@ -750,7 +758,7 @@ impl BinarySimilarity for u8 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_hamming_b8(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_hamming_b8(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -760,7 +768,7 @@ impl BinarySimilarity for u8 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_jaccard_b8(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_jaccard_b8(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -772,7 +780,7 @@ impl SpatialSimilarity for i8 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_cos_i8(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_cos_i8(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -782,7 +790,7 @@ impl SpatialSimilarity for i8 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_dot_i8(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_dot_i8(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -792,7 +800,7 @@ impl SpatialSimilarity for i8 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2sq_i8(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_l2sq_i8(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -802,7 +810,7 @@ impl SpatialSimilarity for i8 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2_i8(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_l2_i8(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -811,7 +819,15 @@ impl Sparse for u16 { fn intersect(a: &[Self], b: &[Self]) -> Option { let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_intersect_u16(a.as_ptr(), b.as_ptr(), a.len(), b.len(), distance_ptr) }; + unsafe { + simsimd_intersect_u16( + a.as_ptr(), + b.as_ptr(), + a.len() as u64size, + b.len() as u64size, + distance_ptr, + ) + }; Some(distance_value) } } @@ -820,7 +836,15 @@ impl Sparse for u32 { fn intersect(a: &[Self], b: &[Self]) -> Option { let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_intersect_u32(a.as_ptr(), b.as_ptr(), a.len(), b.len(), distance_ptr) }; + unsafe { + simsimd_intersect_u32( + a.as_ptr(), + b.as_ptr(), + a.len() as u64size, + b.len() as u64size, + distance_ptr, + ) + }; Some(distance_value) } } @@ -836,7 +860,7 @@ impl SpatialSimilarity for f16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_cos_f16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_cos_f16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -850,7 +874,7 @@ impl SpatialSimilarity for f16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_dot_f16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_dot_f16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -864,7 +888,7 @@ impl SpatialSimilarity for f16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2sq_f16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_l2sq_f16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -877,7 +901,7 @@ impl SpatialSimilarity for f16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2_f16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_l2_f16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -893,7 +917,7 @@ impl SpatialSimilarity for bf16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_cos_bf16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_cos_bf16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -907,7 +931,7 @@ impl SpatialSimilarity for bf16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_dot_bf16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_dot_bf16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -921,7 +945,7 @@ impl SpatialSimilarity for bf16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2sq_bf16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_l2sq_bf16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -934,7 +958,7 @@ impl SpatialSimilarity for bf16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2_bf16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_l2_bf16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -946,7 +970,7 @@ impl SpatialSimilarity for f32 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_cos_f32(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_cos_f32(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -956,7 +980,7 @@ impl SpatialSimilarity for f32 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_dot_f32(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_dot_f32(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -966,7 +990,7 @@ impl SpatialSimilarity for f32 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2sq_f32(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_l2sq_f32(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -976,7 +1000,7 @@ impl SpatialSimilarity for f32 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2_f32(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_l2_f32(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -988,7 +1012,7 @@ impl SpatialSimilarity for f64 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_cos_f64(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_cos_f64(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -998,7 +1022,7 @@ impl SpatialSimilarity for f64 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_dot_f64(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_dot_f64(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -1008,7 +1032,7 @@ impl SpatialSimilarity for f64 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2sq_f64(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_l2sq_f64(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -1018,7 +1042,7 @@ impl SpatialSimilarity for f64 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_l2_f64(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_l2_f64(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -1034,7 +1058,7 @@ impl ProbabilitySimilarity for f16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_js_f16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_js_f16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -1048,7 +1072,7 @@ impl ProbabilitySimilarity for f16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_kl_f16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_kl_f16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -1064,7 +1088,7 @@ impl ProbabilitySimilarity for bf16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_js_bf16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_js_bf16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -1078,7 +1102,7 @@ impl ProbabilitySimilarity for bf16 { let b_ptr = b.as_ptr() as *const u16; let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_kl_bf16(a_ptr, b_ptr, a.len(), distance_ptr) }; + unsafe { simsimd_kl_bf16(a_ptr, b_ptr, a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -1090,7 +1114,7 @@ impl ProbabilitySimilarity for f32 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_js_f32(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_js_f32(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -1100,7 +1124,7 @@ impl ProbabilitySimilarity for f32 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_kl_f32(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_kl_f32(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -1112,7 +1136,7 @@ impl ProbabilitySimilarity for f64 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_js_f64(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_js_f64(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } @@ -1122,7 +1146,7 @@ impl ProbabilitySimilarity for f64 { } let mut distance_value: Distance = 0.0; let distance_ptr: *mut Distance = &mut distance_value as *mut Distance; - unsafe { simsimd_kl_f64(a.as_ptr(), b.as_ptr(), a.len(), distance_ptr) }; + unsafe { simsimd_kl_f64(a.as_ptr(), b.as_ptr(), a.len() as u64size, distance_ptr) }; Some(distance_value) } } @@ -1139,7 +1163,7 @@ impl ComplexProducts for f16 { let a_ptr = a.as_ptr() as *const u16; let b_ptr = b.as_ptr() as *const u16; // The C function expects the number of complex pairs, not the total number of f16 elements - unsafe { simsimd_dot_f16c(a_ptr, b_ptr, a.len() / 2, product_ptr) }; + unsafe { simsimd_dot_f16c(a_ptr, b_ptr, a.len() as u64size / 2, product_ptr) }; Some((product[0], product[1])) } @@ -1152,7 +1176,7 @@ impl ComplexProducts for f16 { let a_ptr = a.as_ptr() as *const u16; let b_ptr = b.as_ptr() as *const u16; // The C function expects the number of complex pairs, not the total number of f16 elements - unsafe { simsimd_vdot_f16c(a_ptr, b_ptr, a.len() / 2, product_ptr) }; + unsafe { simsimd_vdot_f16c(a_ptr, b_ptr, a.len() as u64size / 2, product_ptr) }; Some((product[0], product[1])) } } @@ -1169,7 +1193,7 @@ impl ComplexProducts for bf16 { let a_ptr = a.as_ptr() as *const u16; let b_ptr = b.as_ptr() as *const u16; // The C function expects the number of complex pairs, not the total number of bf16 elements - unsafe { simsimd_dot_bf16c(a_ptr, b_ptr, a.len() / 2, product_ptr) }; + unsafe { simsimd_dot_bf16c(a_ptr, b_ptr, a.len() as u64size / 2, product_ptr) }; Some((product[0], product[1])) } @@ -1184,7 +1208,7 @@ impl ComplexProducts for bf16 { let a_ptr = a.as_ptr() as *const u16; let b_ptr = b.as_ptr() as *const u16; // The C function expects the number of complex pairs, not the total number of bf16 elements - unsafe { simsimd_vdot_bf16c(a_ptr, b_ptr, a.len() / 2, product_ptr) }; + unsafe { simsimd_vdot_bf16c(a_ptr, b_ptr, a.len() as u64size / 2, product_ptr) }; Some((product[0], product[1])) } } @@ -1197,7 +1221,7 @@ impl ComplexProducts for f32 { let mut product: [Distance; 2] = [0.0, 0.0]; let product_ptr: *mut Distance = &mut product[0] as *mut _; // The C function expects the number of complex pairs, not the total number of floats - unsafe { simsimd_dot_f32c(a.as_ptr(), b.as_ptr(), a.len() / 2, product_ptr) }; + unsafe { simsimd_dot_f32c(a.as_ptr(), b.as_ptr(), a.len() as u64size / 2, product_ptr) }; Some((product[0], product[1])) } @@ -1208,7 +1232,7 @@ impl ComplexProducts for f32 { let mut product: [Distance; 2] = [0.0, 0.0]; let product_ptr: *mut Distance = &mut product[0] as *mut _; // The C function expects the number of complex pairs, not the total number of floats - unsafe { simsimd_vdot_f32c(a.as_ptr(), b.as_ptr(), a.len() / 2, product_ptr) }; + unsafe { simsimd_vdot_f32c(a.as_ptr(), b.as_ptr(), a.len() as u64size / 2, product_ptr) }; Some((product[0], product[1])) } } @@ -1221,7 +1245,7 @@ impl ComplexProducts for f64 { let mut product: [Distance; 2] = [0.0, 0.0]; let product_ptr: *mut Distance = &mut product[0] as *mut _; // The C function expects the number of complex pairs, not the total number of floats - unsafe { simsimd_dot_f64c(a.as_ptr(), b.as_ptr(), a.len() / 2, product_ptr) }; + unsafe { simsimd_dot_f64c(a.as_ptr(), b.as_ptr(), a.len() as u64size / 2, product_ptr) }; Some((product[0], product[1])) } @@ -1232,7 +1256,7 @@ impl ComplexProducts for f64 { let mut product: [Distance; 2] = [0.0, 0.0]; let product_ptr: *mut Distance = &mut product[0] as *mut _; // The C function expects the number of complex pairs, not the total number of floats - unsafe { simsimd_vdot_f64c(a.as_ptr(), b.as_ptr(), a.len() / 2, product_ptr) }; + unsafe { simsimd_vdot_f64c(a.as_ptr(), b.as_ptr(), a.len() as u64size / 2, product_ptr) }; Some((product[0], product[1])) } } From 108a8b5bd7eefebeba584da0134842e6bfd806dd Mon Sep 17 00:00:00 2001 From: Ash Vardanian <1983160+ashvardanian@users.noreply.github.com> Date: Thu, 13 Nov 2025 11:21:13 +0000 Subject: [PATCH 5/5] Fix: Avoid `sqrt(0)` in `probability.h` --- include/simsimd/probability.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/simsimd/probability.h b/include/simsimd/probability.h index 6c2b83e5..e24d07c2 100644 --- a/include/simsimd/probability.h +++ b/include/simsimd/probability.h @@ -108,7 +108,8 @@ SIMSIMD_PUBLIC void simsimd_js_f16_sapphire(simsimd_f16_t const* a, simsimd_f16_ d += ai * SIMSIMD_LOG((ai + epsilon) / (mi + epsilon)); \ d += bi * SIMSIMD_LOG((bi + epsilon) / (mi + epsilon)); \ } \ - *result = SIMSIMD_SQRT(((simsimd_distance_t)d / 2)); \ + simsimd_distance_t d_half = ((simsimd_distance_t)d / 2); \ + *result = d_half > 0 ? SIMSIMD_SQRT(d_half) : 0; \ } SIMSIMD_MAKE_KL(serial, f64, f64, SIMSIMD_DEREFERENCE, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_kl_f64_serial @@ -225,7 +226,7 @@ SIMSIMD_PUBLIC void simsimd_js_f32_neon(simsimd_f32_t const *a, simsimd_f32_t co simsimd_f32_t log2_normalizer = 0.693147181f; simsimd_f32_t sum = vaddvq_f32(sum_vec) * log2_normalizer / 2; - *result = _simsimd_sqrt_f32_neon(sum); + *result = sum > 0 ? _simsimd_sqrt_f32_neon(sum) : 0; } #pragma clang attribute pop @@ -298,7 +299,7 @@ SIMSIMD_PUBLIC void simsimd_js_f16_neon(simsimd_f16_t const *a, simsimd_f16_t co simsimd_f32_t log2_normalizer = 0.693147181f; simsimd_f32_t sum = vaddvq_f32(sum_vec) * log2_normalizer / 2; - *result = _simsimd_sqrt_f32_neon(sum); + *result = sum > 0 ? _simsimd_sqrt_f32_neon(sum) : 0; } #pragma clang attribute pop @@ -403,7 +404,7 @@ SIMSIMD_PUBLIC void simsimd_js_f16_haswell(simsimd_f16_t const *a, simsimd_f16_t simsimd_f32_t log2_normalizer = 0.693147181f; simsimd_f32_t sum = _simsimd_reduce_f32x8_haswell(sum_vec); sum *= log2_normalizer / 2; - *result = _simsimd_sqrt_f32_haswell(sum); + *result = sum > 0 ? _simsimd_sqrt_f32_haswell(sum) : 0; } #pragma clang attribute pop @@ -498,7 +499,7 @@ SIMSIMD_PUBLIC void simsimd_js_f32_skylake(simsimd_f32_t const *a, simsimd_f32_t simsimd_f32_t log2_normalizer = 0.693147181f; simsimd_f32_t sum = _mm512_reduce_add_ps(_mm512_add_ps(sum_a_vec, sum_b_vec)); sum *= log2_normalizer / 2; - *result = _simsimd_sqrt_f32_haswell(sum); + *result = sum > 0 ? _simsimd_sqrt_f32_haswell(sum) : 0; } #pragma clang attribute pop @@ -591,7 +592,7 @@ SIMSIMD_PUBLIC void simsimd_js_f16_sapphire(simsimd_f16_t const *a, simsimd_f16_ simsimd_f32_t log2_normalizer = 0.693147181f; simsimd_f32_t sum = _mm512_reduce_add_ph(_mm512_add_ph(sum_a_vec, sum_b_vec)); sum *= log2_normalizer / 2; - *result = _simsimd_sqrt_f32_haswell(sum); + *result = sum > 0 ? _simsimd_sqrt_f32_haswell(sum) : 0; } #pragma clang attribute pop