diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index 7877777b..2f1d38f7 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -35,6 +35,7 @@ jobs: package.json:"version": "(\d+\.\d+\.\d+)" CITATION.cff:^version: (\d+\.\d+\.\d+) Cargo.toml:^version = "(\d+\.\d+\.\d+)" + Cargo.lock:name = "usearch"\nversion = "(\d+\.\d+\.\d+)" wasmer.toml:^version = "(\d+\.\d+\.\d+)" conanfile.py:version = "(\d+\.\d+\.\d+)" java/README.md:(\d+\.\d+\.\d+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c128da8a..6c6739c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: package.json:"version": "(\d+\.\d+\.\d+)" CITATION.cff:^version: (\d+\.\d+\.\d+) Cargo.toml:^version = "(\d+\.\d+\.\d+)" - Cargo.lock:^version = "(\d+\.\d+\.\d+)" + Cargo.lock:name = "usearch"\nversion = "(\d+\.\d+\.\d+)" wasmer.toml:^version = "(\d+\.\d+\.\d+)" conanfile.py:version = "(\d+\.\d+\.\d+)" java/README.md:(\d+\.\d+\.\d+) diff --git a/Cargo.lock b/Cargo.lock index 875876f4..b7b7a927 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "cc" -version = "2.13.3" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" [[package]] name = "codespan-reporting" @@ -135,7 +135,7 @@ checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "usearch" -version = "2.13.1" +version = "2.13.3" dependencies = [ "cxx", "cxx-build", diff --git a/Cargo.toml b/Cargo.toml index b26527a5..346e046c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,10 +18,10 @@ include = [ ] [features] -default = ["simsimd"] # SimSIMD is enabled by default -simsimd = [] # No need to do anything to enable SimSIMD by default -openmp = [] # Optional: Users can enable OpenMP -fp16lib = [] # Optional: Users can enable FP16 support +default = ["simsimd", "fp16lib"] # SimSIMD is enabled by default +simsimd = [] # No need to do anything to enable SimSIMD by default +fp16lib = [] # Without this FP16 we lose precision downcasting +openmp = [] # Optional: Users can enable OpenMP [lib] name = "usearch" diff --git a/build.rs b/build.rs index a6d09e82..0a1c96f3 100644 --- a/build.rs +++ b/build.rs @@ -23,15 +23,41 @@ fn main() { build.define("USEARCH_USE_FP16LIB", "0"); } + // Define all possible SIMD targets as 1 + 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_SVE_BF16", + "SIMSIMD_TARGET_SVE_F16", + "SIMSIMD_TARGET_SVE_I8", + "SIMSIMD_TARGET_SVE", + "SIMSIMD_TARGET_NEON_BF16", + "SIMSIMD_TARGET_NEON_F16", + "SIMSIMD_TARGET_NEON_I8", + "SIMSIMD_TARGET_NEON", + ], + _ => vec![ + "SIMSIMD_TARGET_SAPPHIRE", + "SIMSIMD_TARGET_GENOA", + "SIMSIMD_TARGET_ICE", + "SIMSIMD_TARGET_SKYLAKE", + "SIMSIMD_TARGET_HASWELL", + ], + }; + if cfg!(feature = "simsimd") { - build - .define("USEARCH_USE_SIMSIMD", "1") - .define("SIMSIMD_DYNAMIC_DISPATCH", "1") - .define("SIMSIMD_NATIVE_BF16", "0") - .define("SIMSIMD_NATIVE_F16", "0"); + build.define("USEARCH_USE_SIMSIMD", "1") + .define("SIMSIMD_DYNAMIC_DISPATCH", "1") + .define("SIMSIMD_NATIVE_BF16", "0") + .define("SIMSIMD_NATIVE_F16", "0"); + + for flag in &flags_to_try { + build.define(flag, "1"); + } } else { build.define("USEARCH_USE_SIMSIMD", "0"); } + // Conditional compilation depending on the target operating system. if cfg!(target_os = "linux") { @@ -60,28 +86,6 @@ fn main() { let mut result = build.try_compile("usearch"); if result.is_err() { 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_SVE_BF16", - "SIMSIMD_TARGET_SVE_F16", - "SIMSIMD_TARGET_SVE_I8", - "SIMSIMD_TARGET_SVE", - "SIMSIMD_TARGET_NEON_BF16", - "SIMSIMD_TARGET_NEON_F16", - "SIMSIMD_TARGET_NEON_I8", - "SIMSIMD_TARGET_NEON", - ], - _ => vec![ - "SIMSIMD_TARGET_SAPPHIRE", - "SIMSIMD_TARGET_GENOA", - "SIMSIMD_TARGET_ICE", - "SIMSIMD_TARGET_SKYLAKE", - "SIMSIMD_TARGET_HASWELL", - ], - }; - for flag in flags_to_try { build.define(flag, "0"); result = build.try_compile("usearch"); diff --git a/rust/lib.rs b/rust/lib.rs index 92c34b58..9637e710 100644 --- a/rust/lib.rs +++ b/rust/lib.rs @@ -1639,6 +1639,28 @@ mod tests { } #[test] + fn test_zero_distances() { + let options = IndexOptions { + dimensions: 8, + metric: MetricKind::L2sq, + quantization: ScalarKind::F16, + ..Default::default() + }; + + let index = new_index(&options).unwrap(); + index.reserve(10).unwrap(); + index.add(0, &[0.4, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0]).unwrap(); + index.add(1, &[0.5, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0]).unwrap(); + index.add(2, &[0.6, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0]).unwrap(); + + // Make sure non of the distances are zeros + let matches = index.search(&[0.05, 0.1, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0], 2).unwrap(); + for distance in matches.distances.iter() { + assert_ne!(*distance, 0.0); + } + } + + #[test] fn test_change_distance_function() { let mut options = IndexOptions::default(); options.dimensions = 2; // Adjusted for simplicity in creating test vectors diff --git a/simsimd b/simsimd index 91a76d1a..ff51434d 160000 --- a/simsimd +++ b/simsimd @@ -1 +1 @@ -Subproject commit 91a76d1ac519b3b9dc8957734a3dabd985f00c26 +Subproject commit ff51434d90c66f916e94ff05b24530b127aa4cff