Repository: unum-cloud/usearch (language: rust)

Issue:
Bug: [Rust] all distances are zero
### Describe the bug

The computed `L2sq` distances seem to be always 0.

### Steps to reproduce

```rust
use usearch::ffi::{IndexOptions, MetricKind};
use usearch::new_index;

fn main() {
    let options = IndexOptions {
        dimensions: 3,
        metric: MetricKind::L2sq,
        ..Default::default()
    };

    let index = new_index(&options).unwrap();
    index.reserve(10).unwrap();
    index.add(0, &[0.4, 0.1, 0.1]).unwrap();
    index.add(1, &[0.5, 0.1, 0.1]).unwrap();
    index.add(2, &[0.6, 0.1, 0.1]).unwrap();
    println!("{:?}", index.search(&[0.05, 0.1, 0.1], 2).unwrap());
}
```
prints
```
Matches { keys: [2, 1], distances: [0.0, 0.0] }
```

### Expected behavior

Expected (and this is what `usearch` 2.9.2, which seems to be the last working version, outputs):
```
Matches { keys: [0, 1], distances: [0.122499995, 0.20249999] }
```

### USearch version

2.12.0

### Operating System

CentOS Stream 9

### Hardware architecture

x86

### Which interface are you using?

Other bindings

### Contact Details

_No response_

### Are you open to being tagged as a contributor?

- [X] I am open to being mentioned in the project `.git` history as a contributor

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct


Discussion / hints:
Interesting! Is it true for both `f32` and `f16` representations? Can you please share the exact model of the CPU printed from `lscpu` and the `index.hardware_acceleration()`. Thanks, @embe-pw 🤗 
`index.hardware_acceleration()` returns `"serial"`.
CPU model is `AMD EPYC 7413 24-Core Processor`.

`quantization: ScalarKind::F32` and `quantization: ScalarKind::F64` seem to work correctly.

I can also reproduce this on an M1 Mac (with `index.hardware_acceleration() == "neon"`

Fix patch:
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:<version>(\d+\.\d+\.\d+)</version>
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:<version>(\d+\.\d+\.\d+)</version>
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 +1,1 @@
-Subproject commit 91a76d1ac519b3b9dc8957734a3dabd985f00c26
+Subproject commit ff51434d90c66f916e94ff05b24530b127aa4cff


Test patch: