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

Issue:
Bug: Slow index.add
### Describe the bug

Index creation, vector addition and search loop is 90x slower than identical loop for faiss.

Reproduced in Google colab.

### Steps to reproduce

```
import faiss
from usearch.index import Index

import numpy as np

# Set the seed for reproducibility
np.random.seed(42)

# Generate 500 random vectors of length 1024 with values between 0 and 1
vectors = np.random.rand(500, 1024)
vector=np.random.rand(1024)

%%timeit
# FAISS

indexf = faiss.IndexFlatL2(vectors.shape[-1])
indexf.add(np.array(vectors).astype(np.float32))
D, I = indexf.search(np.array([vector]), 50)
# 1.14 ms ± 4.34 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)


%%timeit

index = Index(
    ndim=vectors.shape[-1], # Define the number of dimensions in input vectors
    metric='l2_sq', # Choose 'cos', 'l2sq', 'haversine' or other metric, default = 'ip'
  
   )
index.add(labels= np.arange(len(vectors)), vectors=vectors)
matches, distances, count = index.search(vector, 50, exact=True)
  
# 94.7 ms ± 20.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
```


### Expected behavior

n/a

### USearch version

latest pip

### Operating System

ubuntu

### Hardware architecture

x86

### Which interface are you using?

Python bindings

### Contact Details

_No response_

### 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:

Fix patch:
diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml
index 55ed09a3..df06b94b 100644
--- a/.github/workflows/prerelease.yml
+++ b/.github/workflows/prerelease.yml
@@ -17,8 +17,8 @@ permissions:
 
 jobs:
 
-  build_test:
-    name: Test USearch
+  test_cpp:
+    name: Test C++
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v3
@@ -163,7 +163,7 @@ jobs:
     - name: Build USearch by Emscripten
       run: |
         ./emsdk/emsdk activate latest && source ./emsdk/emsdk_env.sh
-        emcmake cmake -B ./build -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -s TOTAL_MEMORY=64MB" && emmake make -C ./build
+        emcmake cmake -DUSEARCH_BUILD_BENCHMARK=0 -DUSEARCH_BUILD_WASM=1 -B ./build -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -s TOTAL_MEMORY=64MB" && emmake make -C ./build
     - name: Run tests
       run: node ./build/test.js
 
diff --git a/.releaserc b/.releaserc
index d5fe3ffd..70e5443b 100644
--- a/.releaserc
+++ b/.releaserc
@@ -69,10 +69,10 @@
                     "conanfile.py",
                     "package.json",
                     "Cargo.toml",
-                    "wasmer.toml",
+                    "wasmer.toml"
                 ],
                 "message": "Build: Released ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
             }
         ]
     ]
-}
+}
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
index d1900379..3d7d7725 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -22,16 +22,16 @@
             ],
             "stopAtEntry": false,
             "linux": {
-                "preLaunchTask": "Linux Build C++ Bench Debug",
+                "preLaunchTask": "Linux Build C++ Debug",
                 "MIMode": "gdb"
             },
             "osx": {
-                "preLaunchTask": "MacOS Build C++ Bench Debug",
+                "preLaunchTask": "MacOS Build C++ Debug",
                 "MIMode": "lldb"
             }
         },
         {
-            "name": "Debug C++ Bench on Wiki 1M @Cos",
+            "name": "Debug C++ on Wiki 1M @Cos",
             "type": "cppdbg",
             "request": "launch",
             "program": "${workspaceFolder}/build_debug/bench",
@@ -53,7 +53,7 @@
             ],
             "stopAtEntry": false,
             "linux": {
-                "preLaunchTask": "Linux Build C++ Bench Debug",
+                "preLaunchTask": "Linux Build C++ Debug",
                 "MIMode": "gdb",
                 "environment": [
                     {
@@ -63,12 +63,12 @@
                 ]
             },
             "osx": {
-                "preLaunchTask": "MacOS Build C++ Bench Debug",
+                "preLaunchTask": "MacOS Build C++ Debug",
                 "MIMode": "lldb"
             }
         },
         {
-            "name": "Debug C++ Bench on Text-to-Image 1B @Cos",
+            "name": "Debug C++ on Text-to-Image 1B @Cos",
             "type": "cppdbg",
             "request": "launch",
             "program": "${workspaceFolder}/build_debug/bench",
@@ -90,16 +90,16 @@
             ],
             "stopAtEntry": false,
             "linux": {
-                "preLaunchTask": "Linux Build C++ Bench Debug",
+                "preLaunchTask": "Linux Build C++ Debug",
                 "MIMode": "gdb"
             },
             "osx": {
-                "preLaunchTask": "MacOS Build C++ Bench Debug",
+                "preLaunchTask": "MacOS Build C++ Debug",
                 "MIMode": "lldb"
             }
         },
         {
-            "name": "Run C++ Bench on Text-to-Image 1M @Cos",
+            "name": "Run C++ on Text-to-Image 1M @Cos",
             "type": "cppdbg",
             "request": "launch",
             "program": "${workspaceFolder}/build_release/bench",
@@ -113,7 +113,7 @@
                 "datasets/t2i_1M/groundtruth.public.100K.ibin",
             ],
             "stopAtEntry": false,
-            "preLaunchTask": "Linux Build C++ Bench Release",
+            "preLaunchTask": "Linux Build C++ Release",
             "MIMode": "gdb"
         },
         {
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a4ad9b26..091ada10 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -153,6 +153,14 @@
     "python.testing.pytestArgs": [
         "python"
     ],
+    "python.analysis.diagnosticSeverityOverrides": {
+        "reportMissingImports": "none"
+    },
     "python.testing.unittestEnabled": false,
-    "python.testing.pytestEnabled": true
+    "python.testing.pytestEnabled": true,
+    "[go]": {
+        "editor.insertSpaces": true,
+        "editor.formatOnSave": true,
+        "editor.defaultFormatter": "golang.go"
+    },
 }
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index d5d09d4c..896774c7 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -2,7 +2,7 @@
     "version": "2.0.0",
     "tasks": [
         {
-            "label": "Linux Build C++ Bench Debug",
+            "label": "Linux Build C++ Debug",
             "command": "cmake -DCMAKE_CXX_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=Debug -B ./build_debug && make -C ./build_debug",
             "args": [],
             "type": "shell",
@@ -11,7 +11,7 @@
             ]
         },
         {
-            "label": "Linux Build C++ Bench Release",
+            "label": "Linux Build C++ Release",
             "command": "cmake -DCMAKE_CXX_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=RelWithDebInfo -B ./build_release && make -C ./build_release",
             "args": [],
             "type": "shell",
@@ -20,13 +20,13 @@
             ]
         },
         {
-            "label": "MacOS Build C++ Bench Debug",
+            "label": "MacOS Build C++ Debug",
             "command": "cmake -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_BUILD_TYPE=Debug -B ./build_debug && make -C ./build_debug",
             "args": [],
             "type": "shell",
         },
         {
-            "label": "MacOS Build C++ Bench Release",
+            "label": "MacOS Build C++ Release",
             "command": "cmake -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_BUILD_TYPE=RelWithDebInfo -B ./build_release && make -C ./build_release",
             "args": [],
             "type": "shell"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c4c17e2e..e6db76b5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 # This CMake file is heavily inspired by following `usearch` CMake:
 # https://github.com/nlohmann/json/blob/develop/CMakeLists.txt
 cmake_minimum_required(VERSION 3.1)
-project(usearch VERSION 0.6.0 LANGUAGES CXX)
+project(usearch VERSION 0.6.0 LANGUAGES C CXX)
 
 # Determine if USearch is built as a subproject (using `add_subdirectory`) or if it is the main project
 set(USEARCH_IS_MAIN_PROJECT OFF)
@@ -14,6 +14,7 @@ option(USEARCH_INSTALL "Install CMake targets" OFF)
 option(USEARCH_BUILD_TEST "Compile a native unit test in C++" ${USEARCH_IS_MAIN_PROJECT})
 option(USEARCH_BUILD_BENCHMARK "Compile a native benchmark in C++" ${USEARCH_IS_MAIN_PROJECT})
 option(USEARCH_BUILD_WOLFRAM "Compile Wolfram Language bindings" OFF)
+option(USEARCH_BUILD_CLIB "Compile a native library for the C 99 interface" OFF)
 
 # Includes
 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
@@ -122,3 +123,7 @@ endif()
 if(${USEARCH_BUILD_WASM})
     add_subdirectory(wasm)
 endif()
+
+if (${USEARCH_BUILD_CLIB})
+    add_subdirectory(c)
+endif()
diff --git a/Cargo.toml b/Cargo.toml
index 820d2a39..561ad644 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "usearch"
 version = "0.22.3"
-authors = ["Ashot Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
+authors = ["Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
 description = "Smaller & Faster Single-File Vector Search Engine from Unum"
 edition = "2021"
 license = "Apache-2.0"
diff --git a/README.md b/README.md
index 3ad204b2..21adf34f 100644
--- a/README.md
+++ b/README.md
@@ -38,15 +38,14 @@ Linux • MacOS • Windows • Docker • WebAssembly
 
 - ✅ Benchmark-topping performance.
 - ✅ Simple and extensible [single C++11 header][usearch-header] implementation.
-- ✅ SIMD-optimized and [user-defined metrics](#user-defined-functions) with JIT-compilation.
+- ✅ SIMD-optimized and [user-defined metrics](#user-defined-functions) with JIT compilation.
 - ✅ Variable dimensionality vectors for unique applications, including search over compressed data.
 - ✅ Bitwise Tanimoto and Sorensen coefficients for [Genomics and Chemistry applications](#usearch--rdkit--molecular-search).
-- ✅ Hardware-agmostic `f16` & `f8` - [half-precision & quarter-precision support](#memory-efficiency-downcasting-and-quantization).
+- ✅ Hardware-agnostic `f16` & `i8` - [half-precision & quarter-precision support](#memory-efficiency-downcasting-and-quantization).
 - ✅ [View large indexes from disk](#disk-based-indexes) without loading into RAM.
 - ✅ Space-efficient point-clouds with `uint40_t`, accommodating 4B+ size.
 - ✅ Compatible with OpenMP and custom "executors", for fine-grained control over CPU utilization.
-- ✅ Supports multiple vectors per label.
-- ✅ On-the-fly deletions.
+- ✅ Heterogeneous lookups, renaming/relabeling, and on-the-fly deletions.
 - ✅ [Semantic Search](#usearch--ai--multi-modal-semantic-search) and [Joins](#joins).
 
 [usearch-header]: https://github.com/unum-cloud/usearch/blob/main/include/usearch/index.hpp
@@ -69,7 +68,7 @@ USearch is compact and broadly compatible without sacrificing performance, with
 
 [sloc]: https://en.wikipedia.org/wiki/Source_lines_of_code
 
-Base functionality is identical to FAISS, and the interface must be familiar if you have ever investigated Approximate Nearest Neigbors search:
+Base functionality is identical to FAISS, and the interface must be familiar if you have ever investigated Approximate Nearest Neighbors search:
 
 ```py
 $ pip install usearch numpy
@@ -80,7 +79,7 @@ from usearch.index import Index
 index = Index(
     ndim=3, # Define the number of dimensions in input vectors
     metric='cos', # Choose 'l2sq', 'haversine' or other metric, default = 'ip'
-    dtype='f32', # Quantize to 'f16' or 'f8' if needed, default = 'f32'
+    dtype='f32', # Quantize to 'f16' or 'i8' if needed, default = 'f32'
     connectivity=16, # Optional: How frequent should the connections in the graph be
     expansion_add=128, # Optional: Control the recall of indexing
     expansion_search=64, # Optional: Control the quality of search
@@ -88,12 +87,12 @@ index = Index(
 
 vector = np.array([0.2, 0.6, 0.4])
 index.add(42, vector)
-matches, distances, count = index.search(vector, 10)
+matches: Matches = index.search(vector, 10)
 
 assert len(index) == 1
-assert count == 1
-assert matches[0] == 42
-assert distances[0] <= 0.001
+assert len(matches) == 1
+assert matches[0].key == 42
+assert matches[0].distance <= 0.001
 assert np.allclose(index[42], vector)
 ```
 
@@ -108,7 +107,7 @@ Unlike older approaches indexing high-dimensional spaces, like KD-Trees and Loca
 They only have to be comparable.
 So you can apply it in [obscure][obscure] applications, like searching for similar sets or fuzzy text matching, using [GZip][gzip-similarity] as a distance function.
 
-> Read more about [JIT and UDF in USearch Python SDK]().
+> Read more about [JIT and UDF in USearch Python SDK](https://unum-cloud.github.io/usearch/python#user-defined-metrics-and-jit-in-python).
 
 [haversine]: https://ashvardanian.com/posts/abusing-vector-search#geo-spatial-indexing
 [obscure]: https://ashvardanian.com/posts/abusing-vector-search
@@ -122,10 +121,10 @@ Those, however, are only sometimes reliable, can significantly affect the statis
 ![USearch uint40_t support](https://github.com/unum-cloud/usearch/blob/main/assets/usearch-neighbor-types.png?raw=true)
 
 Instead, we have focused on high-precision arithmetic over low-precision downcasted vectors.
-The same index, and `add` and `search` operations will automatically down-cast or up-cast between `f32_t`, `f16_t`, `f64_t`, and `f8_t` representations, even if the hardware doesn't natively support it.
-Continuing the topic of memory-efficiency, we provide a `uint40_t` to allow collection with over 4B+ vectors without allocating 8 bytes for every neighbor reference in the proximity graph.
+The same index, and `add` and `search` operations will automatically down-cast or up-cast between `f32_t`, `f16_t`, `f64_t`, and `i8_t` representations, even if the hardware doesn't natively support it.
+Continuing the topic of memory efficiency, we provide a `uint40_t` to allow collection with over 4B+ vectors without allocating 8 bytes for every neighbor reference in the proximity graph.
 
-|              | FAISS, `f32` | USearch, `f32` | USearch, `f16` |     USearch, `f8` |
+|              | FAISS, `f32` | USearch, `f32` | USearch, `f16` |     USearch, `i8` |
 | :----------- | -----------: | -------------: | -------------: | ----------------: |
 | Batch Insert |       16 K/s |         73 K/s |        100 K/s | 104 K/s **+550%** |
 | Batch Search |       82 K/s |        103 K/s |        113 K/s |  134 K/s **+63%** |
@@ -148,7 +147,7 @@ Continuing the topic of memory-efficiency, we provide a `uint40_t` to allow coll
 ## Disk-based Indexes
 
 With USearch, you can serve indexes from external memory, enabling you to optimize your server choices for indexing speed and serving costs.
-This can result in **20x costs reduction** on AWS and other public clouds.
+This can result in **20x cost reduction** on AWS and other public clouds.
 
 ```py
 index.save("index.usearch")
@@ -162,7 +161,7 @@ other_view.view("index.usearch")
 
 ## Joins
 
-One of the big questions these days is how will AI change the world of databases and data-management?
+One of the big questions these days is how will AI change the world of databases and data management.
 Most databases are still struggling to implement high-quality fuzzy search, and the only kind of joins they know are deterministic.
 A `join` is different from searching for every entry, as it requires a one-to-one mapping, banning collisions among separate search results.
 
@@ -171,7 +170,7 @@ A `join` is different from searching for every entry, as it requires a one-to-on
 |  Exact Join  | Fuzzy Join ? | Semantic Join ??  |
 
 Using USearch one can implement sub-quadratic complexity approximate, fuzzy, and semantic joins.
-This can come handy in any fuzzy-matching tasks, common to Database Management Software.
+This can come in handy in any fuzzy-matching tasks, common to Database Management Software.
 
 ```py
 men = Index(...)
@@ -183,17 +182,17 @@ pairs: dict = men.join(women, max_proposals=0, exact=False)
 
 ## Functionality
 
-By now, core functionality is supported across all bindings.
+By now, the core functionality is supported across all bindings.
 Broader functionality is ported per request.
 
-|                         |  C++  | Python | Java  | JavaScript | Rust  | GoLang | Swift |
-| :---------------------- | :---: | :----: | :---: | :--------: | :---: | :----: | :---: |
-| add/search/remove       |   ✅   |   ✅    |   ✅   |     ✅      |   ✅   |   ✅    |   ✅   |
-| save/load/view          |   ✅   |   ✅    |   ✅   |     ✅      |   ✅   |   ✅    |   ✅   |
-| join                    |   ✅   |   ✅    |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
-| user-defiend metrics    |   ✅   |   ✅    |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
-| variable-length vectors |   ✅   |   ✅    |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
-| 4B+ capacities          |   ✅   |   ❌    |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
+|                         | C++ 11 | Python 3 | C 99  | Java  | JavaScript | Rust  | GoLang | Swift |
+| :---------------------- | :----: | :------: | :---: | :---: | :--------: | :---: | :----: | :---: |
+| Add, search             |   ✅    |    ✅     |   ✅   |   ✅   |     ✅      |   ✅   |   ✅    |   ✅   |
+| Save, load, view        |   ✅    |    ✅     |   ✅   |   ✅   |     ✅      |   ✅   |   ✅    |   ✅   |
+| Join                    |   ✅    |    ✅     |   ✅   |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
+| User-defined metrics    |   ✅    |    ✅     |   ✅   |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
+| Variable-length vectors |   ✅    |    ✅     |   ❌   |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
+| 4B+ capacities          |   ✅    |    ❌     |   ❌   |   ❌   |     ❌      |   ❌   |   ❌    |   ❌   |
 
 ## Application Examples
 
@@ -215,22 +214,22 @@ model = uform.get_model('unum-cloud/uform-vl-multilingual')
 index = usearch.index.Index(ndim=256)
 
 @server
-def add(label: int, photo: pil.Image.Image):
+def add(key: int, photo: pil.Image.Image):
     image = model.preprocess_image(photo)
     vector = model.encode_image(image).detach().numpy()
-    index.add(label, vector.flatten(), copy=True)
+    index.add(key, vector.flatten(), copy=True)
 
 @server
 def search(query: str) -> np.ndarray:
     tokens = model.preprocess_text(query)
     vector = model.encode_text(tokens).detach().numpy()
     matches = index.search(vector.flatten(), 3)
-    return matches.labels
+    return matches.keys
 
 server.run()
 ```
 
-We have pre-processed some commonly used datasets, cleaning the images, producing the vectors, and pre-building the index.
+We have pre-processed some commonly used datasets, cleaned the images, produced the vectors, and pre-built the index.
 
 | Dataset                                |            Modalities | Images |                              Download |
 | :------------------------------------- | --------------------: | -----: | ------------------------------------: |
@@ -250,10 +249,10 @@ We have pre-processed some commonly used datasets, cleaning the images, producin
 
 Comparing molecule graphs and searching for similar structures is expensive and slow.
 It can be seen as a special case of the NP-Complete Subgraph Isomorphism problem.
-Luckily, domain-specific approximate methods exists.
+Luckily, domain-specific approximate methods exist.
 The one commonly used in Chemistry, is to generate structures from [SMILES][smiles], and later hash them into binary fingerprints.
-The later are searchable with bitwise similarity metrics, like the Tanimoto coefficient.
-Below is na example using the RDKit package.
+The latter are searchable with bitwise similarity metrics, like the Tanimoto coefficient.
+Below is an example using the RDKit package.
 
 ```python
 from usearch.index import Index, MetricKind
@@ -269,27 +268,22 @@ fingerprints = np.vstack([encoder.GetFingerprint(x) for x in molecules])
 fingerprints = np.packbits(fingerprints, axis=1)
 
 index = Index(ndim=2048, metric=MetricKind.Tanimoto)
-labels = np.arange(len(molecules))
+keys = np.arange(len(molecules))
 
-index.add(labels, fingerprints)
+index.add(keys, fingerprints)
 matches = index.search(fingerprints, 10)
 ```
 
 [smiles]: https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system
 [rdkit-fingerprints]: https://www.rdkit.org/docs/RDKit_Book.html#additional-information-about-the-fingerprints
 
-## TODO
-
-- JavaScript: Allow calling from "worker threads".
-- Rust: Allow passing a custom thread ID.
-- C# .NET bindings.
 
 ## Integrations
 
 - [x] GPT-Cache.
 - [ ] LangChain.
 - [ ] Microsoft Semantic Kernel.
-- [ ] PyTorch.
+- [ ] ClickHouse.
 
 ## Citations
 
diff --git a/build.rs b/build.rs
index 2c8a4cd4..951817cc 100644
--- a/build.rs
+++ b/build.rs
@@ -13,7 +13,7 @@ fn main() {
     println!("cargo:rerun-if-changed=rust/lib.rs");
     println!("cargo:rerun-if-changed=rust/lib.cpp");
     println!("cargo:rerun-if-changed=rust/lib.hpp");
-    println!("cargo:rerun-if-changed=include/index_punned_helpers.hpp");
-    println!("cargo:rerun-if-changed=include/index_punned_dense.hpp");
+    println!("cargo:rerun-if-changed=include/index_plugins.hpp");
+    println!("cargo:rerun-if-changed=include/index_dense.hpp");
     println!("cargo:rerun-if-changed=include/usearch/index.hpp");
 }
diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt
new file mode 100644
index 00000000..5315ec80
--- /dev/null
+++ b/c/CMakeLists.txt
@@ -0,0 +1,48 @@
+
+
+set(USEARCH_PUNNED_INCLUDE_DIRS
+    "${CMAKE_CURRENT_SOURCE_DIR}/../include"
+    "${CMAKE_CURRENT_SOURCE_DIR}/../fp16/include"
+    "${CMAKE_CURRENT_SOURCE_DIR}/../robin-map/include"
+    "${CMAKE_CURRENT_SOURCE_DIR}/../simsimd/include"
+    "${CMAKE_CURRENT_SOURCE_DIR}/"
+)
+
+# This article discusses a better way to allow building either static or shared libraries
+# https://alexreinking.com/blog/building-a-dual-shared-and-static-library-with-cmake.html
+if (${USEARCH_BUILD_STATIC})
+    set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -static-libstdc++")
+    add_library(usearch_c STATIC lib.cpp)
+else ()
+    add_library(usearch_c SHARED lib.cpp)
+endif()
+
+set_target_properties(usearch_c PROPERTIES POSITION_INDEPENDENT_CODE ON)
+set_target_properties(usearch_c PROPERTIES CXX_STANDARD 11)
+
+target_include_directories(usearch_c PRIVATE ${USEARCH_PUNNED_INCLUDE_DIRS})
+set_target_properties(usearch_c PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+set_target_properties(usearch_c PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+set_target_properties(usearch_c PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+
+
+target_include_directories(usearch_c PRIVATE ${USEARCH_PUNNED_INCLUDE_DIRS})
+
+if(${USEARCH_DEBUG_BUILD_ASAN})
+    # For ASAN in debug builds
+    target_link_libraries(usearch_c PRIVATE gcov)
+endif()
+
+if(${USEARCH_USE_SIMSIMD})
+    target_compile_definitions(usearch_c PRIVATE USEARCH_USE_SIMSIMD=1)
+endif()
+if (${USEARCH_LOOKUP_LABEL})
+    target_compile_definitions(usearch_c PRIVATE USEARCH_LOOKUP_LABEL=1)
+endif()
+
+if(${USEARCH_BUILD_TEST})
+    add_executable(test_c test.c external_retreival_testutils.c)
+    target_link_libraries(test_c usearch_c)
+    set_target_properties(test_c PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+
+endif()
diff --git a/c/Makefile b/c/Makefile
index b13bfe5d..5973f0e7 100644
--- a/c/Makefile
+++ b/c/Makefile
@@ -1,10 +1,10 @@
-CC = gcc-12
-CXX = g++-12
+CC = gcc
+CXX = g++
 
 C_FLAGS = -std=c99
-CXX_FLAGS = -std=c++17
+CXX_FLAGS = -std=c++11
 
-CXX_FLAGS += -Wall -Wextra -Wno-conversion -Wno-unknown-pragmas -O3 -march=native
+CXX_FLAGS += -Wall -Wextra -Wno-conversion -Wno-unknown-pragmas -O3 -march=native -pedantic
 
 HEADER_INCLUDES = -I.  -I ../include/  -I ../fp16/include/ -I ../robin-map/include/
 
diff --git a/c/README.md b/c/README.md
new file mode 100644
index 00000000..6eadeb4e
--- /dev/null
+++ b/c/README.md
@@ -0,0 +1,34 @@
+# USearch for C
+
+## Installation
+
+The simplest form to integrate is to copy the contents of `usearch/c/` into your project.
+To build the library `libusearch_c`, pass enable the `USEARCH_BUILD_CLIB` CMake option:
+
+```bash
+ cmake -DUSEARCH_BUILD_CLIB=1 -DUSEARCH_BUILD_STATIC=0 -DUSEARCH_BUILD_TEST=0 -DUSEARCH_BUILD_BENCHMARK=0 ..
+ ```
+
+You can choose between a static and dynamic library by setting `USEARCH_BUILD_STATIC`.
+
+## Quickstart
+
+```c
+usearch_error_t error = NULL;
+usearch_init_options_t opts = create_options(dimensions);
+usearch_index_t index = usearch_init(&opts, &error);
+usearch_reserve(index, vectors_count, &error);
+
+float vector[dimensions] = {...};
+usearch_add(index, 42, &vector[0], usearch_scalar_f32_k, &error);
+
+ASSERT(!error, error);
+ASSERT(usearch_size(index, &error) == vectors_count, error);
+ASSERT(usearch_capacity(index, &error) == vectors_count, error);
+
+usearch_key_t found_keys[10];
+float found_distances[10];
+size_t found_count = usearch_search(index, &vector[0], usearch_scalar_f32_k, 10, &found_keys[0], &found_distances[0], &error);
+
+usearch_free(index, &error);
+```
diff --git a/c/lib.cpp b/c/lib.cpp
index a3a283c3..76b9c703 100644
--- a/c/lib.cpp
+++ b/c/lib.cpp
@@ -1,6 +1,6 @@
 #include <cassert>
 
-#include <usearch/index_punned_dense.hpp>
+#include <usearch/index_dense.hpp>
 
 #ifndef USEARCH_EXPORT
 #define USEARCH_EXPORT
@@ -13,13 +13,12 @@ extern "C" {
 using namespace unum::usearch;
 using namespace unum;
 
-using label_t = usearch_label_t;
-using distance_t = usearch_distance_t;
-using index_t = index_punned_dense_gt<label_t>;
-using add_result_t = index_t::add_result_t;
-using search_result_t = index_t::search_result_t;
-using serialization_result_t = index_t::serialization_result_t;
-using vector_view_t = span_gt<float>;
+using add_result_t = typename index_dense_t::add_result_t;
+using search_result_t = typename index_dense_t::search_result_t;
+using labeling_result_t = typename index_dense_t::labeling_result_t;
+
+static_assert(std::is_same<usearch_key_t, index_dense_t::key_t>::value, "Type mismatch between C and C++");
+static_assert(std::is_same<usearch_distance_t, index_dense_t::distance_t>::value, "Type mismatch between C and C++");
 
 // helper functions that are not part of the C ABI
 metric_kind_t to_native_metric(usearch_metric_kind_t kind) {
@@ -42,133 +41,139 @@ scalar_kind_t to_native_scalar(usearch_scalar_kind_t kind) {
     case usearch_scalar_f32_k: return scalar_kind_t::f32_k;
     case usearch_scalar_f64_k: return scalar_kind_t::f64_k;
     case usearch_scalar_f16_k: return scalar_kind_t::f16_k;
-    case usearch_scalar_f8_k: return scalar_kind_t::f8_k;
+    case usearch_scalar_i8_k: return scalar_kind_t::i8_k;
     case usearch_scalar_b1_k: return scalar_kind_t::b1x8_k;
     default: return scalar_kind_t::unknown_k;
     }
 }
 
-add_result_t add_(index_t* index, usearch_label_t label, void const* vector, scalar_kind_t kind) {
+add_result_t add_(index_dense_t* index, usearch_key_t key, void const* vector, scalar_kind_t kind) {
     switch (kind) {
-    case scalar_kind_t::f32_k: return index->add(label, (f32_t const*)vector);
-    case scalar_kind_t::f64_k: return index->add(label, (f64_t const*)vector);
-    case scalar_kind_t::f16_k: return index->add(label, (f16_t const*)vector);
-    case scalar_kind_t::f8_k: return index->add(label, (f8_bits_t const*)vector);
-    case scalar_kind_t::b1x8_k: return index->add(label, (b1x8_t const*)vector);
+    case scalar_kind_t::f32_k: return index->add(key, (f32_t const*)vector);
+    case scalar_kind_t::f64_k: return index->add(key, (f64_t const*)vector);
+    case scalar_kind_t::f16_k: return index->add(key, (f16_t const*)vector);
+    case scalar_kind_t::i8_k: return index->add(key, (i8_bits_t const*)vector);
+    case scalar_kind_t::b1x8_k: return index->add(key, (b1x8_t const*)vector);
     default: return add_result_t{}.failed("Unknown scalar kind!");
     }
 }
 
-bool get_(index_t* index, label_t label, void* vector, scalar_kind_t kind) {
+bool get_(index_dense_t* index, usearch_key_t key, void* vector, scalar_kind_t kind) {
     switch (kind) {
-    case scalar_kind_t::f32_k: return index->get(label, (f32_t*)vector);
-    case scalar_kind_t::f64_k: return index->get(label, (f64_t*)vector);
-    case scalar_kind_t::f16_k: return index->get(label, (f16_t*)vector);
-    case scalar_kind_t::f8_k: return index->get(label, (f8_bits_t*)vector);
-    case scalar_kind_t::b1x8_k: return index->get(label, (b1x8_t*)vector);
-    default: return index->empty_search_result().failed("Unknown scalar kind!");
+    case scalar_kind_t::f32_k: return index->get(key, (f32_t*)vector);
+    case scalar_kind_t::f64_k: return index->get(key, (f64_t*)vector);
+    case scalar_kind_t::f16_k: return index->get(key, (f16_t*)vector);
+    case scalar_kind_t::i8_k: return index->get(key, (i8_bits_t*)vector);
+    case scalar_kind_t::b1x8_k: return index->get(key, (b1x8_t*)vector);
+    default: return search_result_t().failed("Unknown scalar kind!");
     }
 }
 
-search_result_t search_(index_t* index, void const* vector, scalar_kind_t kind, size_t n) {
+search_result_t search_(index_dense_t* index, void const* vector, scalar_kind_t kind, size_t n) {
     switch (kind) {
     case scalar_kind_t::f32_k: return index->search((f32_t const*)vector, n);
     case scalar_kind_t::f64_k: return index->search((f64_t const*)vector, n);
     case scalar_kind_t::f16_k: return index->search((f16_t const*)vector, n);
-    case scalar_kind_t::f8_k: return index->search((f8_bits_t const*)vector, n);
+    case scalar_kind_t::i8_k: return index->search((i8_bits_t const*)vector, n);
     case scalar_kind_t::b1x8_k: return index->search((b1x8_t const*)vector, n);
-    default: return index->empty_search_result().failed("Unknown scalar kind!");
+    default: return search_result_t().failed("Unknown scalar kind!");
     }
 }
 
-index_punned_dense_metric_t udf(metric_kind_t kind, usearch_metric_t raw_ptr) {
-    index_punned_dense_metric_t result;
-    result.kind_ = kind;
-    result.func_ = [raw_ptr](punned_vector_view_t a, punned_vector_view_t b) -> distance_t {
-        return raw_ptr((void const*)a.data(), (void const*)b.data());
-    };
-    return result;
-}
-
 extern "C" {
 
 USEARCH_EXPORT usearch_index_t usearch_init(usearch_init_options_t* options, usearch_error_t* error) {
 
     assert(options && error);
 
-    index_config_t config;
-    config.connectivity = options->connectivity;
-    index_t index =        //
-        options->metric ?  //
-            index_t::make( //
-                options->dimensions, udf(to_native_metric(options->metric_kind), options->metric), config,
-                to_native_scalar(options->quantization), options->expansion_add, options->expansion_search)
-                        :  //
-            index_t::make( //
-                options->dimensions, to_native_metric(options->metric_kind), config,
-                to_native_scalar(options->quantization), options->expansion_add, options->expansion_search);
-
-    index_t* result_ptr = new index_t(std::move(index));
+    index_dense_config_t config(options->connectivity, options->expansion_add, options->expansion_search);
+    metric_kind_t metric_kind = to_native_metric(options->metric_kind);
+    scalar_kind_t scalar_kind = to_native_scalar(options->quantization);
+
+    auto metric_lambda = [options](byte_t const* a, byte_t const* b) -> usearch_distance_t {
+        return options->metric((void const*)a, (void const*)b);
+    };
+    metric_punned_t metric = //
+        options->metric ? metric_punned_t(metric_lambda, options->dimensions, metric_kind, scalar_kind)
+                        : metric_punned_t(options->dimensions, metric_kind, scalar_kind);
+
+    index_dense_t index = index_dense_t::make(metric, config);
+    index_dense_t* result_ptr = new index_dense_t(std::move(index));
     return result_ptr;
 }
 
-USEARCH_EXPORT void usearch_free(usearch_index_t index, usearch_error_t*) { delete reinterpret_cast<index_t*>(index); }
+USEARCH_EXPORT void usearch_free(usearch_index_t index, usearch_error_t*) {
+    delete reinterpret_cast<index_dense_t*>(index);
+}
 
 USEARCH_EXPORT void usearch_save(usearch_index_t index, char const* path, usearch_error_t* error) {
-    serialization_result_t result = reinterpret_cast<index_t*>(index)->save(path);
+
+    assert(index && path && error);
+    serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->save(path);
     if (!result)
         *error = result.error.what();
 }
 
 USEARCH_EXPORT void usearch_load(usearch_index_t index, char const* path, usearch_error_t* error) {
-    serialization_result_t result = reinterpret_cast<index_t*>(index)->load(path);
+
+    assert(index && path && error);
+    serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->load(path);
     if (!result)
         *error = result.error.what();
 }
 
 USEARCH_EXPORT void usearch_view(usearch_index_t index, char const* path, usearch_error_t* error) {
-    serialization_result_t result = reinterpret_cast<index_t*>(index)->view(path);
+
+    assert(index && path && error);
+    serialization_result_t result = reinterpret_cast<index_dense_t*>(index)->view(path);
     if (!result)
         *error = result.error.what();
 }
 
 USEARCH_EXPORT size_t usearch_size(usearch_index_t index, usearch_error_t*) { //
-    return reinterpret_cast<index_t*>(index)->size();
+    return reinterpret_cast<index_dense_t*>(index)->size();
 }
 
 USEARCH_EXPORT size_t usearch_capacity(usearch_index_t index, usearch_error_t*) {
-    return reinterpret_cast<index_t*>(index)->capacity();
+    return reinterpret_cast<index_dense_t*>(index)->capacity();
 }
 
 USEARCH_EXPORT size_t usearch_dimensions(usearch_index_t index, usearch_error_t*) {
-    return reinterpret_cast<index_t*>(index)->dimensions();
+    return reinterpret_cast<index_dense_t*>(index)->dimensions();
 }
 
 USEARCH_EXPORT size_t usearch_connectivity(usearch_index_t index, usearch_error_t*) {
-    return reinterpret_cast<index_t*>(index)->connectivity();
+    return reinterpret_cast<index_dense_t*>(index)->connectivity();
 }
 
-USEARCH_EXPORT void usearch_reserve(usearch_index_t index, size_t capacity, usearch_error_t*) {
-    // TODO: Consider returning the new capacity.
-    reinterpret_cast<index_t*>(index)->reserve(capacity);
+USEARCH_EXPORT void usearch_reserve(usearch_index_t index, size_t capacity, usearch_error_t* error) {
+    assert(index && error);
+    if (!reinterpret_cast<index_dense_t*>(index)->reserve(capacity))
+        *error = "Out of memory!";
 }
 
-USEARCH_EXPORT void usearch_add(                                                                          //
-    usearch_index_t index, usearch_label_t label, void const* vector, usearch_scalar_kind_t kind, //
+USEARCH_EXPORT void usearch_add(                                                              //
+    usearch_index_t index, usearch_key_t key, void const* vector, usearch_scalar_kind_t kind, //
     usearch_error_t* error) {
-    add_result_t result = add_(reinterpret_cast<index_t*>(index), label, vector, to_native_scalar(kind));
+
+    assert(index && vector && error);
+    add_result_t result = add_(reinterpret_cast<index_dense_t*>(index), key, vector, to_native_scalar(kind));
     if (!result)
         *error = result.error.what();
 }
 
-USEARCH_EXPORT bool usearch_contains(usearch_index_t index, usearch_label_t label, usearch_error_t*) {
-    return reinterpret_cast<index_t*>(index)->contains(label);
+USEARCH_EXPORT bool usearch_contains(usearch_index_t index, usearch_key_t key, usearch_error_t*) {
+    assert(index);
+    return reinterpret_cast<index_dense_t*>(index)->contains(key);
 }
 
-USEARCH_EXPORT size_t usearch_search(                                                                    //
+USEARCH_EXPORT size_t usearch_search(                                                            //
     usearch_index_t index, void const* vector, usearch_scalar_kind_t kind, size_t results_limit, //
-    usearch_label_t* found_labels, usearch_distance_t* found_distances, usearch_error_t* error) {
-    search_result_t result = search_(reinterpret_cast<index_t*>(index), vector, to_native_scalar(kind), results_limit);
+    usearch_key_t* found_labels, usearch_distance_t* found_distances, usearch_error_t* error) {
+
+    assert(index && vector && error);
+    search_result_t result =
+        search_(reinterpret_cast<index_dense_t*>(index), vector, to_native_scalar(kind), results_limit);
     if (!result) {
         *error = result.error.what();
         return 0;
@@ -177,14 +182,20 @@ USEARCH_EXPORT size_t usearch_search(
     return result.dump_to(found_labels, found_distances);
 }
 
-USEARCH_EXPORT bool usearch_get(                          //
-    usearch_index_t index, usearch_label_t label, //
+USEARCH_EXPORT bool usearch_get(              //
+    usearch_index_t index, usearch_key_t key, //
     void* vector, usearch_scalar_kind_t kind, usearch_error_t*) {
-    return get_(reinterpret_cast<index_t*>(index), label, vector, to_native_scalar(kind));
+
+    assert(index && vector);
+    return get_(reinterpret_cast<index_dense_t*>(index), key, vector, to_native_scalar(kind));
 }
 
-USEARCH_EXPORT void usearch_remove(usearch_index_t, usearch_label_t, usearch_error_t* error) {
-    if (error != nullptr)
-        *error = "USearch does not support removal of elements yet.";
+USEARCH_EXPORT bool usearch_remove(usearch_index_t index, usearch_key_t key, usearch_error_t* error) {
+
+    assert(index && error);
+    labeling_result_t result = reinterpret_cast<index_dense_t*>(index)->remove(key);
+    if (!result)
+        *error = result.error.what();
+    return result.completed;
 }
 }
diff --git a/c/usearch.h b/c/usearch.h
index 7d10876d..6f9cf7a6 100644
--- a/c/usearch.h
+++ b/c/usearch.h
@@ -1,6 +1,6 @@
 #ifndef UNUM_USEARCH_H
 #define UNUM_USEARCH_H
-// in case the header is included from cpp code
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -11,79 +11,179 @@ extern "C" {
 #include <stdint.h>  // `size_t`
 
 USEARCH_EXPORT typedef void* usearch_index_t;
-USEARCH_EXPORT typedef uint32_t usearch_label_t;
+USEARCH_EXPORT typedef uint64_t usearch_key_t;
 USEARCH_EXPORT typedef float usearch_distance_t;
+
+/**
+ *  @brief  Pointer to a null-terminated error message.
+ *          Returned error messages @b don't need to be deallocated.
+ */
 USEARCH_EXPORT typedef char const* usearch_error_t;
 
+/**
+ *  @brief  Type-punned callback for "metrics" or "distance functions",
+ *          that accepts pointers to two vectors and measures their @b dis-similarity.
+ */
 USEARCH_EXPORT typedef usearch_distance_t (*usearch_metric_t)(void const*, void const*);
 
+/**
+ *  @brief  Enumerator for the most common kinds of `usearch_metric_t`.
+ *          Those are supported out of the box, with SIMD-optimizations for most common hardware.
+ */
 USEARCH_EXPORT typedef enum usearch_metric_kind_t {
-    usearch_metric_ip_k = 0,
-    usearch_metric_l2sq_k,
+    usearch_metric_unknown_k = 0,
     usearch_metric_cos_k,
+    usearch_metric_ip_k,
+    usearch_metric_l2sq_k,
     usearch_metric_haversine_k,
     usearch_metric_pearson_k,
     usearch_metric_jaccard_k,
     usearch_metric_hamming_k,
     usearch_metric_tanimoto_k,
     usearch_metric_sorensen_k,
-    usearch_metric_unknown_k,
 } usearch_metric_kind_t;
 
 USEARCH_EXPORT typedef enum usearch_scalar_kind_t {
-    usearch_scalar_f32_k = 0,
+    usearch_scalar_unknown_k = 0,
+    usearch_scalar_f32_k,
     usearch_scalar_f64_k,
     usearch_scalar_f16_k,
-    usearch_scalar_f8_k,
+    usearch_scalar_i8_k,
     usearch_scalar_b1_k,
-    usearch_scalar_unknown_k,
 } usearch_scalar_kind_t;
 
 USEARCH_EXPORT typedef struct usearch_init_options_t {
-
+    /**
+     *  @brief The metric kind used for distance calculation between vectors.
+     */
     usearch_metric_kind_t metric_kind;
+    /**
+     *  @brief The @b optional custom distance metric function used for distance calculation between vectors.
+     *  If the `metric_kind` is set to `usearch_metric_unknown_k`, this function pointer mustn't be `NULL`.
+     */
     usearch_metric_t metric;
-
+    /**
+     *  @brief The scalar kind used for quantization of vector data during indexing.
+     */
     usearch_scalar_kind_t quantization;
+    /**
+     *  @brief The number of dimensions in the vectors to be indexed.
+     *  Must be defined for most metrics, but can be avoided for `usearch_metric_haversine_k`.
+     */
     size_t dimensions;
+    /**
+     *  @brief The @b optional connectivity parameter that limits connections-per-node in graph.
+     */
     size_t connectivity;
+    /**
+     *  @brief The @b optional expansion factor used for index construction when adding vectors.
+     */
     size_t expansion_add;
+    /**
+     *  @brief The @b optional expansion factor used for index construction during search operations.
+     */
     size_t expansion_search;
 } usearch_init_options_t;
 
-USEARCH_EXPORT usearch_index_t usearch_init(usearch_init_options_t*, usearch_error_t*);
-USEARCH_EXPORT void usearch_free(usearch_index_t, usearch_error_t*);
+/**
+ *  @brief Initializes a new instance of the index.
+ *  @param options Pointer to the `usearch_init_options_t` structure containing initialization options.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ *  @return A handle to the initialized USearch index, or `NULL` on failure.
+ */
+USEARCH_EXPORT usearch_index_t usearch_init(usearch_init_options_t* options, usearch_error_t* error);
 
-USEARCH_EXPORT void usearch_save(usearch_index_t, char const* path, usearch_error_t*);
-USEARCH_EXPORT void usearch_load(usearch_index_t, char const* path, usearch_error_t*);
-USEARCH_EXPORT void usearch_view(usearch_index_t, char const* path, usearch_error_t*);
+/**
+ *  @brief Frees the resources associated with the index.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ */
+USEARCH_EXPORT void usearch_free(usearch_index_t, usearch_error_t* error);
 
-USEARCH_EXPORT size_t usearch_size(usearch_index_t, usearch_error_t*);
-USEARCH_EXPORT size_t usearch_capacity(usearch_index_t, usearch_error_t*);
-USEARCH_EXPORT size_t usearch_dimensions(usearch_index_t, usearch_error_t*);
-USEARCH_EXPORT size_t usearch_connectivity(usearch_index_t, usearch_error_t*);
+/**
+ *  @brief Saves the index to a file.
+ *  @param[in] path The file path where the index will be saved.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ */
+USEARCH_EXPORT void usearch_save(usearch_index_t, char const* path, usearch_error_t* error);
 
-USEARCH_EXPORT void usearch_reserve(usearch_index_t, size_t capacity, usearch_error_t*);
+/**
+ *  @brief Loads the index from a file.
+ *  @param[in] path The file path from where the index will be loaded.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ */
+USEARCH_EXPORT void usearch_load(usearch_index_t, char const* path, usearch_error_t* error);
 
-USEARCH_EXPORT void usearch_add(                                                                     //
-    usearch_index_t, usearch_label_t, void const* vector, usearch_scalar_kind_t vector_kind, //
-    usearch_error_t*);
+/**
+ *  @brief Creates a view of the index from a file without loading it into memory.
+ *  @param[in] path The file path from where the view will be created.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ */
+USEARCH_EXPORT void usearch_view(usearch_index_t, char const* path, usearch_error_t* error);
 
-USEARCH_EXPORT bool usearch_contains(usearch_index_t, usearch_label_t, usearch_error_t*);
+USEARCH_EXPORT size_t usearch_size(usearch_index_t, usearch_error_t* error);
+USEARCH_EXPORT size_t usearch_capacity(usearch_index_t, usearch_error_t* error);
+USEARCH_EXPORT size_t usearch_dimensions(usearch_index_t, usearch_error_t* error);
+USEARCH_EXPORT size_t usearch_connectivity(usearch_index_t, usearch_error_t* error);
 
 /**
- *  @brief      Performs k-Approximate Nearest Neighbors Search.
- *  @return     Number of found matches.
+ *  @brief Reserves memory for a specified number of incoming vectors.
+ *  @param[in] capacity The desired total capacity including current size.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
  */
-USEARCH_EXPORT size_t usearch_search(                                                                          //
+USEARCH_EXPORT void usearch_reserve(usearch_index_t, size_t capacity, usearch_error_t* error);
+
+/**
+ *  @brief Adds a vector with a key to the index.
+ *  @param[in] key The key associated with the vector.
+ *  @param[in] vector Pointer to the vector data.
+ *  @param[in] vector_kind The scalar type used in the vector data.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ */
+USEARCH_EXPORT void usearch_add(        //
+    usearch_index_t, usearch_key_t key, //
+    void const* vector, usearch_scalar_kind_t vector_kind, usearch_error_t* error);
+
+/**
+ *  @brief Checks if the index contains a vector with a specific key.
+ *  @param[in] key The key to be checked.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ *  @return `true` if the index contains the vector with the given key, `false` otherwise.
+ */
+USEARCH_EXPORT bool usearch_contains(usearch_index_t, usearch_key_t, usearch_error_t* error);
+
+/**
+ *  @brief Performs k-Approximate Nearest Neighbors (kANN) Search for closest vectors to query.
+ *  @param[in] query_vector Pointer to the query vector data.
+ *  @param[in] query_kind The scalar type used in the query vector data.
+ *  @param[in] results_limit Upper bound on the number of neighbors to search, the "k" in "kANN".
+ *  @param[out] found_keys Output buffer for up to `results_limit` nearest neighbors keys.
+ *  @param[out] found_distances Output buffer for up to `results_limit` distances to nearest neighbors.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ *  @return Number of found matches.
+ */
+USEARCH_EXPORT size_t usearch_search(                                                                  //
     usearch_index_t, void const* query_vector, usearch_scalar_kind_t query_kind, size_t results_limit, //
-    usearch_label_t* found_labels, usearch_distance_t* found_distances, usearch_error_t*);
+    usearch_key_t* found_keys, usearch_distance_t* found_distances, usearch_error_t* error);
 
-USEARCH_EXPORT bool usearch_get(              //
-    usearch_index_t, usearch_label_t, //
-    void* vector, usearch_scalar_kind_t vector_kind, usearch_error_t*);
+/**
+ *  @brief Retrieves the vector associated with the given key from the index.
+ *  @param[in] key The key of the vector to retrieve.
+ *  @param[out] vector Pointer to the memory where the vector data will be copied.
+ *  @param[in] vector_kind The scalar type used in the vector data.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ *  @return `true` if the vector is successfully retrieved, `false` if the vector is not found.
+ */
+USEARCH_EXPORT bool usearch_get(        //
+    usearch_index_t, usearch_key_t key, //
+    void* vector, usearch_scalar_kind_t vector_kind, usearch_error_t* error);
 
-USEARCH_EXPORT void usearch_remove(usearch_index_t, usearch_label_t, usearch_error_t*);
+/**
+ *  @brief Removes the vector associated with the given key from the index.
+ *  @param[in] key The key of the vector to be removed.
+ *  @param[out] error Pointer to a string where the error message will be stored, if an error occurs.
+ *  @return `true` if the vector is successfully removed, `false` if the vector is not found.
+ */
+USEARCH_EXPORT bool usearch_remove(usearch_index_t, usearch_key_t key, usearch_error_t* error);
 
 #ifdef __cplusplus
 }
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 44bb2ca0..e73a45ef 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -83,6 +83,7 @@ if(${USEARCH_BUILD_TEST})
     target_link_libraries(test PRIVATE Threads::Threads)
     target_include_directories(test PRIVATE ${USEARCH_PUNNED_INCLUDE_DIRS})
     set_target_properties(test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+    set_target_properties(test PROPERTIES CXX_STANDARD 17)
 
     if(${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13)
         include(CTest)
@@ -96,6 +97,7 @@ if(${USEARCH_BUILD_BENCHMARK})
     target_link_libraries(bench PRIVATE Threads::Threads)
     target_include_directories(bench PRIVATE ${USEARCH_PUNNED_INCLUDE_DIRS})
     set_target_properties(bench PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
+    set_target_properties(bench PROPERTIES CXX_STANDARD 17)
 
     if(${USEARCH_USE_SIMSIMD})
         target_compile_definitions(bench PRIVATE USEARCH_USE_SIMSIMD=1)
@@ -107,6 +109,6 @@ if(${USEARCH_BUILD_BENCHMARK})
     endif()
 
     if(${USEARCH_USE_JEMALLOC})
-        target_link_libraries(bench PRIVATE ${JEMALLOC_LIBRARIES})
+        target_link_libraries(bench PRIVATE ${JEMALLOC_LIBRARIES})        
     endif()
 endif()
diff --git a/cpp/README.md b/cpp/README.md
index 934cd51b..8ac1542b 100644
--- a/cpp/README.md
+++ b/cpp/README.md
@@ -1,4 +1,4 @@
-# USearch C++ Inteface
+# USearch for C++
 
 ## Installation
 
@@ -18,15 +18,15 @@ This covers 90% of use-cases.
 ```c++
 using namespace unum::usearch;
 
-index_gt<cos_gt<float>> index;
+index_gt<metric_cos_gt<float>> index;
 float vec[3] = {0.1, 0.3, 0.2};
 
 index.reserve(10);
-index.add(/* label: */ 42, /* vector: */ {&vec[0], 3});
+index.add(/* key: */ 42, /* vector: */ {&vec[0], 3});
 auto results = index.search(/* query: */ {&vec[0], 3}, 5 /* neighbors */);
 
 for (std::size_t i = 0; i != results.size(); ++i)
-    results[i].element.label, results[i].element.vector, results[i].distance;
+    results[i].element.key, results[i].element.vector, results[i].distance;
 ```
 
 The `add` is thread-safe for concurrent index construction.
@@ -44,8 +44,8 @@ index.view("index.usearch"); // Memory-mapping from disk
 For advanced users, more compile-time abstractions are available.
 
 ```cpp
-template <typename metric_at = ip_gt<float>,            //
-          typename label_at = std::size_t,              // `uint32_t`, `uuid_t`...
+template <typename metric_at = metric_ip_gt<float>,            //
+          typename key_at = std::size_t,              // `uint32_t`, `uuid_t`...
           typename id_at = std::uint32_t,               // `uint40_t`, `uint64_t`...
           typename scalar_at = float,                   // `double`, `half`, `char`...
           typename allocator_at = std::allocator<char>> //
@@ -63,15 +63,15 @@ struct custom_metric_t {
 
 The following distances are pre-packaged:
 
-- `cos_gt<scalar_t>` for "Cosine" or "Angular" distance.
-- `ip_gt<scalar_t>` for "Inner Product" or "Dot Product" distance.
-- `l2sq_gt<scalar_t>` for the squared "L2" or "Euclidean" distance.
-- `jaccard_gt<scalar_t>` for "Jaccard" distance between two ordered sets of unique elements.
-- `hamming_gt<scalar_t>` for "Hamming" distance, as the number of shared bits in hashes.
-- `tanimoto_gt<scalar_t>` for "Tanimoto" coefficient for bit-strings.
-- `sorensen_gt<scalar_t>` for "Dice-Sorensen" coefficient for bit-strings.
-- `pearson_correlation_gt<scalar_t>` for "Pearson" correlation between probability distributions.
-- `haversine_gt<scalar_t>` for "Haversine" or "Great Circle" distance between coordinates used in GIS applications.
+- `metric_cos_gt<scalar_t>` for "Cosine" or "Angular" distance.
+- `metric_ip_gt<scalar_t>` for "Inner Product" or "Dot Product" distance.
+- `metric_l2sq_gt<scalar_t>` for the squared "L2" or "Euclidean" distance.
+- `metric_jaccard_gt<scalar_t>` for "Jaccard" distance between two ordered sets of unique elements.
+- `metric_hamming_gt<scalar_t>` for "Hamming" distance, as the number of shared bits in hashes.
+- `metric_tanimoto_gt<scalar_t>` for "Tanimoto" coefficient for bit-strings.
+- `metric_sorensen_gt<scalar_t>` for "Dice-Sorensen" coefficient for bit-strings.
+- `metric_pearson_gt<scalar_t>` for "Pearson" correlation between probability distributions.
+- `metric_haversine_gt<scalar_t>` for "Haversine" or "Great Circle" distance between coordinates used in GIS applications.
 
 ## Multi-Threading
 
@@ -81,7 +81,7 @@ Instead of spawning additional threads within USearch, we focus on the thread sa
 ```cpp
 #pragma omp parallel for
     for (std::size_t i = 0; i < n; ++i)
-        native.add(label, span_t{vector, dims}, add_config_t { .thread = omp_get_thread_num() });
+        native.add(key, span_t{vector, dims}, index_update_config_t { .thread = omp_get_thread_num() });
 ```
 
 During initialization, we allocate enough temporary memory for all the cores on the machine.
diff --git a/cpp/bench.cpp b/cpp/bench.cpp
index 01808c4e..be9c21dc 100644
--- a/cpp/bench.cpp
+++ b/cpp/bench.cpp
@@ -1,6 +1,6 @@
 /**
  *  @brief A benchmark for the construction speed of the USearch index
- *  and the resulting accuracy (recall) of the Approximate Nearest Neighbors
+ *  and the resulting quantization (recall) of the Approximate Nearest Neighbors
  *  Search queries.
  */
 
@@ -44,14 +44,13 @@
 
 #include <simsimd/simsimd.h>
 
-#include <usearch/index_punned_dense.hpp>
+#include <usearch/index_dense.hpp>
 
 using namespace unum::usearch;
 using namespace unum;
 
-using label_t = std::int64_t;
-using vector_id_t = std::uint32_t;
-using vector_view_t = span_gt<float const>;
+using compressed_slot_t = std::uint32_t;
+using float_span_t = span_gt<float const>;
 
 template <typename element_at>
 std::size_t offset_of(element_at const* begin, element_at const* end, element_at v) noexcept {
@@ -151,10 +150,10 @@ struct vectors_view_gt {
 template <typename scalar_at, typename vector_id_at> //
 struct persisted_dataset_gt {
     using scalar_t = scalar_at;
-    using vector_id_t = vector_id_at;
+    using compressed_slot_t = vector_id_at;
     persisted_matrix_gt<scalar_t> vectors_;
     persisted_matrix_gt<scalar_t> queries_;
-    persisted_matrix_gt<vector_id_t> neighborhoods_;
+    persisted_matrix_gt<compressed_slot_t> neighborhoods_;
     std::size_t vectors_to_skip_{};
     std::size_t vectors_to_take_{};
 
@@ -174,7 +173,7 @@ struct persisted_dataset_gt {
     std::size_t neighborhood_size() const noexcept { return neighborhoods_.cols; }
     scalar_t const* vector(std::size_t i) const noexcept { return vectors_.row(i + vectors_to_skip_); }
     scalar_t const* query(std::size_t i) const noexcept { return queries_.row(i); }
-    vector_id_t const* neighborhood(std::size_t i) const noexcept { return neighborhoods_.row(i); }
+    compressed_slot_t const* neighborhood(std::size_t i) const noexcept { return neighborhoods_.row(i); }
 
     std::size_t vectors_count() const noexcept {
         return vectors_to_take_ ? vectors_to_take_ : (vectors_.rows - vectors_to_skip_);
@@ -187,11 +186,11 @@ struct persisted_dataset_gt {
 template <typename scalar_at, typename vector_id_at> //
 struct in_memory_dataset_gt {
     using scalar_t = scalar_at;
-    using vector_id_t = vector_id_at;
+    using compressed_slot_t = vector_id_at;
 
     std::vector<scalar_t> vectors_{};
     std::vector<scalar_t> queries_{};
-    std::vector<vector_id_t> neighborhoods_{};
+    std::vector<compressed_slot_t> neighborhoods_{};
     std::size_t dimensions_{};
     std::size_t vectors_count_{};
     std::size_t neighborhood_size_{};
@@ -210,13 +209,13 @@ struct in_memory_dataset_gt {
     std::size_t neighborhood_size() const noexcept { return 1; }
     scalar_t const* vector(std::size_t i) const noexcept { return vectors_.data() + i * dimensions_; }
     scalar_t const* query(std::size_t i) const noexcept { return queries_.data() + i * dimensions_; }
-    vector_id_t const* neighborhood(std::size_t i) const noexcept {
+    compressed_slot_t const* neighborhood(std::size_t i) const noexcept {
         return neighborhoods_.data() + i * neighborhood_size_;
     }
 
     scalar_t* vector(std::size_t i) noexcept { return vectors_.data() + i * dimensions_; }
     scalar_t* query(std::size_t i) noexcept { return queries_.data() + i * dimensions_; }
-    vector_id_t* neighborhood(std::size_t i) noexcept { return neighborhoods_.data() + i * neighborhood_size_; }
+    compressed_slot_t* neighborhood(std::size_t i) noexcept { return neighborhoods_.data() + i * neighborhood_size_; }
 
     vectors_view_gt<scalar_t> vectors_view() const noexcept { return {vector(0), vectors_count(), dimensions()}; }
 };
@@ -279,7 +278,7 @@ struct running_stats_printer_t {
 };
 
 template <typename index_at, typename vector_id_at, typename real_at>
-void index_many(index_at& native, std::size_t n, vector_id_at const* ids, real_at const* vectors, std::size_t dims) {
+void index_many(index_at& index, std::size_t n, vector_id_at const* ids, real_at const* vectors, std::size_t dims) {
 
     running_stats_printer_t printer{n, "Indexing"};
 
@@ -287,13 +286,12 @@ void index_many(index_at& native, std::size_t n, vector_id_at const* ids, real_a
 #pragma omp parallel for schedule(static, 32)
 #endif
     for (std::size_t i = 0; i < n; ++i) {
-        add_config_t config;
+        index_update_config_t config;
 #if USEARCH_USE_OPENMP
         config.thread = omp_get_thread_num();
 #endif
-        config.store_vector = true;
-        vector_view_t vector{vectors + dims * i, dims};
-        native.add(ids[i], vector, config);
+        float_span_t vector{vectors + dims * i, dims};
+        index.add(ids[i], vector, config);
         printer.progress++;
         if (config.thread == 0)
             printer.refresh();
@@ -302,7 +300,7 @@ void index_many(index_at& native, std::size_t n, vector_id_at const* ids, real_a
 
 template <typename index_at, typename vector_id_at, typename real_at>
 void search_many( //
-    index_at& native, std::size_t n, real_at const* vectors, std::size_t dims, std::size_t wanted, vector_id_at* ids,
+    index_at& index, std::size_t n, real_at const* vectors, std::size_t dims, std::size_t wanted, vector_id_at* ids,
     real_at* distances) {
 
     std::string name = "Search " + std::to_string(wanted);
@@ -312,12 +310,12 @@ void search_many( //
 #pragma omp parallel for schedule(static, 32)
 #endif
     for (std::size_t i = 0; i < n; ++i) {
-        search_config_t config;
+        index_search_config_t config;
 #if USEARCH_USE_OPENMP
         config.thread = omp_get_thread_num();
 #endif
-        vector_view_t vector{vectors + dims * i, dims};
-        native.search(vector, wanted, config).dump_to(ids + wanted * i, distances + wanted * i);
+        float_span_t vector{vectors + dims * i, dims};
+        index.search(vector, wanted, config).dump_to(ids + wanted * i, distances + wanted * i);
         printer.progress++;
         if (config.thread == 0)
             printer.refresh();
@@ -326,22 +324,20 @@ void search_many( //
 
 template <typename dataset_at, typename index_at> //
 static void single_shot(dataset_at& dataset, index_at& index, bool construct = true) {
-    using label_t = typename index_at::label_t;
     using distance_t = typename index_at::distance_t;
-    using join_result_t = typename index_at::join_result_t;
-    constexpr label_t missing_label = std::numeric_limits<label_t>::max();
+    constexpr default_key_t missing_key = std::numeric_limits<default_key_t>::max();
 
     std::printf("\n");
     std::printf("------------\n");
     if (construct) {
         // Perform insertions, evaluate speed
-        std::vector<label_t> ids(dataset.vectors_count());
+        std::vector<default_key_t> ids(dataset.vectors_count());
         std::iota(ids.begin(), ids.end(), 0);
         index_many(index, dataset.vectors_count(), ids.data(), dataset.vector(0), dataset.dimensions());
     }
 
     // Perform search, evaluate speed
-    std::vector<label_t> found_neighbors(dataset.queries_count() * dataset.neighborhood_size());
+    std::vector<default_key_t> found_neighbors(dataset.queries_count() * dataset.neighborhood_size());
     std::vector<distance_t> found_distances(dataset.queries_count() * dataset.neighborhood_size());
     search_many(index, dataset.queries_count(), dataset.query(0), dataset.dimensions(), dataset.neighborhood_size(),
                 found_neighbors.data(), found_distances.data());
@@ -352,39 +348,39 @@ static void single_shot(dataset_at& dataset, index_at& index, bool construct = t
         auto expected = dataset.neighborhood(i);
         auto received = found_neighbors.data() + i * dataset.neighborhood_size();
         recall_at_1 += expected[0] == received[0];
-        recall_full += contains(received, received + dataset.neighborhood_size(), label_t{expected[0]});
+        recall_full += contains(received, received + dataset.neighborhood_size(), default_key_t{expected[0]});
     }
 
     std::printf("Recall@1 %.2f %%\n", recall_at_1 * 100.f / dataset.queries_count());
     std::printf("Recall %.2f %%\n", recall_full * 100.f / dataset.queries_count());
 
     // Perform joins
-    std::vector<label_t> man_to_woman(dataset.vectors_count());
-    std::vector<label_t> woman_to_man(dataset.vectors_count());
+    std::vector<default_key_t> man_to_woman(dataset.vectors_count());
+    std::vector<default_key_t> woman_to_man(dataset.vectors_count());
     std::size_t join_attempts = 0;
     {
         index_at& men = index;
         index_at women = index.copy().index;
-        std::fill(man_to_woman.begin(), man_to_woman.end(), missing_label);
-        std::fill(woman_to_man.begin(), woman_to_man.end(), missing_label);
+        std::fill(man_to_woman.begin(), man_to_woman.end(), missing_key);
+        std::fill(woman_to_man.begin(), woman_to_man.end(), missing_key);
         {
             executor_default_t executor(index.limits().threads());
             running_stats_printer_t printer{1, "Join"};
-            join_result_t result = index_at::join(          //
-                men, women, join_config_t{executor.size()}, //
-                man_to_woman.data(), woman_to_man.data(),   //
+            join_result_t result = join(                          //
+                men, women, index_join_config_t{executor.size()}, //
+                man_to_woman.data(), woman_to_man.data(),         //
                 executor, [&](std::size_t progress, std::size_t total) {
                     if (progress % 1000 == 0)
                         printer.print(progress, total);
                 });
-            join_attempts = result.cycles;
+            join_attempts = result.visited_members;
         }
     }
     // Evaluate join quality
     std::size_t recall_join = 0, unmatched_count = 0;
     for (std::size_t i = 0; i != index.size(); ++i) {
-        recall_join += man_to_woman[i] == static_cast<label_t>(i);
-        unmatched_count += man_to_woman[i] == missing_label;
+        recall_join += man_to_woman[i] == static_cast<default_key_t>(i);
+        unmatched_count += man_to_woman[i] == missing_key;
     }
     std::printf("Recall Joins %.2f %%\n", recall_join * 100.f / index.size());
     std::printf("Unmatched %.2f %% (%zu items)\n", unmatched_count * 100.f / index.size(), unmatched_count);
@@ -453,10 +449,9 @@ struct args_t {
     bool help = false;
 
     bool big = false;
-    bool native = false;
 
     bool quantize_f16 = false;
-    bool quantize_f8 = false;
+    bool quantize_i8 = false;
     bool quantize_b1 = false;
 
     bool metric_ip = false;
@@ -483,11 +478,11 @@ struct args_t {
         return metric_kind_t::ip_k;
     }
 
-    scalar_kind_t accuracy() const noexcept {
+    scalar_kind_t quantization() const noexcept {
         if (quantize_f16)
             return scalar_kind_t::f16_k;
-        if (quantize_f8)
-            return scalar_kind_t::f8_k;
+        if (quantize_i8)
+            return scalar_kind_t::i8_k;
         if (quantize_b1)
             return scalar_kind_t::b1x8_k;
         return scalar_kind_t::f32_k;
@@ -497,15 +492,16 @@ struct args_t {
 template <typename index_at, typename dataset_at> //
 void run_punned(dataset_at& dataset, args_t const& args, index_config_t config, index_limits_t limits) {
 
-    scalar_kind_t accuracy = args.accuracy();
-    std::printf("-- Accuracy: %s\n", scalar_kind_name(accuracy));
+    scalar_kind_t quantization = args.quantization();
+    std::printf("-- Quantization: %s\n", scalar_kind_name(quantization));
 
     metric_kind_t kind = args.metric();
     std::printf("-- Metric: %s\n", metric_kind_name(kind));
 
-    index_at index = index_at::make(dataset.dimensions(), kind, config, accuracy);
+    metric_punned_t metric(dataset.dimensions(), kind, quantization);
+    index_at index = index_at::make(metric, config);
     index.reserve(limits);
-    std::printf("-- Hardware acceleration: %s\n", isa_name(index.metric().isa_));
+    std::printf("-- Hardware acceleration: %s\n", isa_name(index.metric().isa_kind()));
     std::printf("Will benchmark in-memory\n");
 
     single_shot(dataset, index, true);
@@ -535,74 +531,6 @@ void run_typed(dataset_at& dataset, args_t const& args, index_config_t config, i
     single_shot(dataset, index_view, false);
 }
 
-template <typename neighbor_id_at, typename dataset_at> //
-void run_big_or_small(dataset_at& dataset, args_t const& args, index_config_t config, index_limits_t limits) {
-    if (args.native) {
-        if (args.metric_cos) {
-            std::printf("-- Metric: Angular\n");
-            run_typed<index_gt<cos_gt<float>, label_t, neighbor_id_at>>(dataset, args, config, limits);
-        } else if (args.metric_l2) {
-            std::printf("-- Metric: Euclidean\n");
-            run_typed<index_gt<l2sq_gt<float>, label_t, neighbor_id_at>>(dataset, args, config, limits);
-        } else if (args.metric_haversine) {
-            std::printf("-- Metric: Haversine\n");
-            run_typed<index_gt<haversine_gt<float>, label_t, neighbor_id_at>>(dataset, args, config, limits);
-        } else {
-            std::printf("-- Metric: Inner Product\n");
-            run_typed<index_gt<ip_gt<float>, label_t, neighbor_id_at>>(dataset, args, config, limits);
-        }
-    } else
-        run_punned<index_punned_dense_gt<label_t, neighbor_id_at>>(dataset, args, config, limits);
-}
-
-void report_alternative_setups() {
-    using set_member_t = std::uint32_t;
-    using sets_index_t = index_gt<jaccard_gt<set_member_t>, label_t, std::uint32_t>;
-    set_member_t set_a[] = {10, 12, 15};
-    set_member_t set_b[] = {11, 12, 15, 16};
-    sets_index_t index;
-    index.reserve(100);
-    index.add(10, span_gt<set_member_t const>{&set_a[0], 3});
-    index.add(11, span_gt<set_member_t const>{&set_b[0], 4});
-    exit(0);
-}
-
-void report_expected_losses(persisted_dataset_gt<float, vector_id_t> const& dataset) {
-
-    auto vec1 = dataset.vector(0);
-    auto vec2 = dataset.query(0);
-    std::vector<f16_t> vec1f16(dataset.dimensions());
-    std::vector<f16_t> vec2f16(dataset.dimensions());
-    std::transform(vec1, vec1 + dataset.dimensions(), vec1f16.data(), [](float v) { return v; });
-    std::transform(vec2, vec2 + dataset.dimensions(), vec2f16.data(), [](float v) { return v; });
-    std::vector<f8_bits_t> vec1f8(dataset.dimensions());
-    std::vector<f8_bits_t> vec2f8(dataset.dimensions());
-    std::transform(vec1, vec1 + dataset.dimensions(), vec1f8.data(), [](float v) { return v; });
-    std::transform(vec2, vec2 + dataset.dimensions(), vec2f8.data(), [](float v) { return v; });
-
-#if 0
-    auto ip_default = ip_gt<float>{}(vec1, vec2, dataset.dimensions());
-    auto ip_f16 = ip_gt<f16_t, float>{}(vec1f16.data(), vec2f16.data(), dataset.dimensions());
-    auto ip_f8 = ip_gt<f8_bits_t, float>{}(vec1f8.data(), vec2f8.data(), dataset.dimensions());
-
-#if defined(__AVX512F__)
-    auto ip_f16avx512 = 1.f - simsimd_dot_f16x16avx512((simsimd_f16_t const*)vec1f16.data(),
-                                                       (simsimd_f16_t const*)vec2f16.data(), dataset.dimensions());
-#endif
-#if defined(__ARM_FEATURE_SVE)
-    auto ip_sve = 1.f - simsimd_dot_f32sve(vec1, vec2, dataset.dimensions());
-    auto ip_f16sve = 1.f - simsimd_dot_f16sve((simsimd_f16_t const*)vec1f16.data(),
-                                              (simsimd_f16_t const*)vec2f16.data(), dataset.dimensions());
-#endif
-#if defined(__ARM_NEON)
-    auto ip_neon = 1.f - simsimd_dot_f32x4neon(vec1, vec2, dataset.dimensions());
-    auto ip_f16neon = 1.f - simsimd_dot_f16x8neon((simsimd_f16_t const*)vec1f16.data(),
-                                                  (simsimd_f16_t const*)vec2f16.data(), dataset.dimensions());
-#endif
-    exit(0);
-#endif
-}
-
 int main(int argc, char** argv) {
 
     // Print backtrace if something goes wrong.
@@ -624,9 +552,8 @@ int main(int argc, char** argv) {
         (option("--rows-skip") & value("integer", args.vectors_to_skip)).doc("Number of vectors to skip"),
         (option("--rows-take") & value("integer", args.vectors_to_take)).doc("Number of vectors to take"),
         ( //
-            option("--native").set(args.native).doc("Use raw templates instead of type-punned classes") |
             option("-f16", "--f16quant").set(args.quantize_f16).doc("Enable `f16_t` quantization") |
-            option("-f8", "--f8quant").set(args.quantize_f8).doc("Enable `f8_t` quantization") |
+            option("-i8", "--i8quant").set(args.quantize_i8).doc("Enable `i8_t` quantization") |
             option("-b1", "--b1quant").set(args.quantize_b1).doc("Enable `b1x8_t` quantization")),
         ( //
             option("--ip").set(args.metric_ip).doc("Choose Inner Product metric") |
@@ -648,7 +575,7 @@ int main(int argc, char** argv) {
     }
 
 #if USEARCH_USE_OPENMP
-    // Instead of relying on `multithreaded` from "index_punned_dense.hpp" we will use OpenMP
+    // Instead of relying on `multithreaded` from "index_dense.hpp" we will use OpenMP
     // to better estimate statistics between tasks batches, without having to recreate
     // the threads.
     omp_set_dynamic(true);
@@ -661,7 +588,7 @@ int main(int argc, char** argv) {
     std::printf("-- Query vectors path: %s\n", args.path_queries.c_str());
     std::printf("-- Ground truth neighbors path: %s\n", args.path_neighbors.c_str());
 
-    persisted_dataset_gt<float, vector_id_t> dataset{
+    persisted_dataset_gt<float, compressed_slot_t> dataset{
         args.path_vectors.c_str(),   //
         args.path_queries.c_str(),   //
         args.path_neighbors.c_str(), //
@@ -676,27 +603,24 @@ int main(int argc, char** argv) {
     // report_alternative_setups();
     // report_expected_losses(dataset);
 
-    index_config_t config;
-    config.connectivity = args.connectivity;
-    // config.expansion_add = args.expansion_add;
-    // config.expansion_search = args.expansion_search;
+    index_dense_config_t config(args.connectivity, args.expansion_add, args.expansion_search);
     index_limits_t limits;
     limits.threads_add = limits.threads_search = args.threads;
     limits.members = dataset.vectors_count();
 
     std::printf("- Index: \n");
     std::printf("-- Connectivity: %zu\n", config.connectivity);
-    // std::printf("-- Expansion @ Add: %zu\n", config.expansion_add);
-    // std::printf("-- Expansion @ Search: %zu\n", config.expansion_search);
+    std::printf("-- Expansion @ Add: %zu\n", config.expansion_add);
+    std::printf("-- Expansion @ Search: %zu\n", config.expansion_search);
 
     if (args.big)
 #ifdef USEARCH_64BIT_ENV
-        run_big_or_small<uint40_t>(dataset, args, config, limits);
+        run_punned<index_dense_gt<default_key_t, uint40_t>>(dataset, args, config, limits);
 #else
         std::printf("Error: Don't use 40 bit identifiers in 32bit environment\n");
 #endif
     else
-        run_big_or_small<std::uint32_t>(dataset, args, config, limits);
+        run_punned<index_dense_gt<default_key_t, std::uint32_t>>(dataset, args, config, limits);
 
     return 0;
 }
\ No newline at end of file
diff --git a/docs/benchmarks.md b/docs/benchmarks.md
index 5eccd813..63d5880d 100644
--- a/docs/benchmarks.md
+++ b/docs/benchmarks.md
@@ -39,24 +39,24 @@ The main columns are:
 | `f32` x256 |      16      |   64   |   32   |   128'644    |     228'422     |         97.2% |
 | `f32` x256 |      16      |  256   |  128   |    39'981    |     69'065      |         99.2% |
 
-### Different vectors "accuracy"
+### Different vectors "quantization"
 
 | Vectors      | Connectivity | EF @ A | EF @ S | **Add**, QPS | **Search**, QPS | **Recall @1** |
 | :----------- | :----------: | :----: | :----: | :----------: | :-------------: | ------------: |
 | `f32` x256   |      16      |  128   |   64   |    87'995    |     171'856     |         99.1% |
 | `f16` x256   |      16      |  128   |   64   |    87'270    |     153'788     |         98.4% |
 | `f16` x256 ✳️ |      16      |  128   |   64   |    71'454    |     132'673     |         98.4% |
-| `f8` x256    |      16      |  128   |   64   |   115'923    |     274'653     |         98.9% |
+| `i8` x256    |      16      |  128   |   64   |   115'923    |     274'653     |         98.9% |
 
-As seen on the chart, for `f16` accuracy, performance may differ depending on native hardware support for that numeric type.
-Also worth noting, 8-bit quantization results in almost no accuracy loss and may perform better than `f16`.
+As seen on the chart, for `f16` quantization, performance may differ depending on native hardware support for that numeric type.
+Also worth noting, 8-bit quantization results in almost no quantization loss and may perform better than `f16`.
 
 ## Utilities
 
 Within this repository you will find two commonly used utilities:
 
 - `cpp/bench.cpp` the produces the `bench` binary for broad USearch benchmarks.
-- `python/bench.py` for simple benchmarks against FAISS.
+- `python/bench.py` and `python/bench.ipynb` for interactive charts against FAISS.
 
 To achieve best highest results we suggest compiling locally for the target architecture.
 
@@ -112,6 +112,27 @@ OPTIONS
         -h, --help  Print this help information on this tool and exit
 ```
 
+Here is an example of running the C++ benchmark:
+
+```sh
+./build_release/bench \
+    --vectors datasets/wiki_1M/base.1M.fbin \
+    --queries datasets/wiki_1M/query.public.100K.fbin \
+    --neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
+
+./build_release/bench \
+    --vectors datasets/t2i_1B/base.1B.fbin \
+    --queries datasets/t2i_1B/query.public.100K.fbin \
+    --neighbors datasets/t2i_1B/groundtruth.public.100K.ibin \
+    --output datasets/t2i_1B/index.usearch \
+    --cos
+```
+
+
+> Optional parameters include `connectivity`, `expansion_add`, `expansion_search`.
+
+For Python, jut open the Jupyter Notebook and start playing around.
+
 ## Datasets
 
 BigANN benchmark is a good starting point, if you are searching for large collections of high-dimensional vectors.
diff --git a/docs/c/reference.rst b/docs/c/reference.rst
index 753cb4a6..58bb89b4 100644
--- a/docs/c/reference.rst
+++ b/docs/c/reference.rst
@@ -1,7 +1,7 @@
 API Reference
 ===============
 
-===============
-usearch
-===============
+==================
+usearch/usearch.h
+==================
 .. doxygenfile:: usearch.h
diff --git a/docs/compilation.md b/docs/compilation.md
index 9b9df41c..6d00aff0 100644
--- a/docs/compilation.md
+++ b/docs/compilation.md
@@ -44,10 +44,10 @@ cmake -B ./build_release \
 Linting:
 
 ```sh
-cppcheck --enable=all --suppress=cstyleCast --suppress=unusedFunction \
+cppcheck --enable=all --force --suppress=cstyleCast --suppress=unusedFunction \
     include/usearch/index.hpp \
-    include/index_punned_dense.hpp \
-    include/index_punned_helpers.hpp
+    include/index_dense.hpp \
+    include/index_plugins.hpp
 ```
 
 Testing:
@@ -56,22 +56,6 @@ Testing:
 cmake -DCMAKE_CXX_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_BUILD_TYPE=Debug -B ./build_debug && make -C ./build_debug && ./build_debug/test
 ```
 
-Benchmarking:
-
-```sh
-./build_release/bench \
-    --vectors datasets/wiki_1M/base.1M.fbin \
-    --queries datasets/wiki_1M/query.public.100K.fbin \
-    --neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
-
-./build_release/bench \
-    --vectors datasets/t2i_1B/base.1B.fbin \
-    --queries datasets/t2i_1B/query.public.100K.fbin \
-    --neighbors datasets/t2i_1B/groundtruth.public.100K.ibin \
-    --output datasets/t2i_1B/index.usearch \
-    --cos
-```
-
 ## Python 3
 
 Use PyTest to validate the build.
@@ -96,25 +80,6 @@ pip install cibuildwheel
 cibuildwheel --platform linux
 ```
 
-Benchmarking:
-
-```sh
-pip install faiss-cpu
-python python/scripts/bench.py speed \
-    --vectors datasets/wiki_1M/base.1M.fbin \
-    --queries datasets/wiki_1M/query.public.100K.fbin \
-    --neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
-```
-
-> Optional parameters include `connectivity`, `expansion_add`, `expansion_search`.
-
-Checking the effect of different embedding dimensions on construction speed:
-
-```sh
-python python/scripts/bench.py dimensions ...
-python python/scripts/bench.py connectivity ...
-```
-
 ## JavaScript
 
 Node.JS:
@@ -178,34 +143,51 @@ java -cp . -Djava.library.path="$(pwd)/java/cloud/unum/usearch/" Index.java
 java -cp . -Djava.library.path="$(pwd)/java" cloud.unum.usearch.Index
 ```
 
-## Wolfram
+## Objective-C and Swift
 
 ```sh
-brew install --cask wolfram-engine
+swift build
+swift test -v
 ```
 
-## GoLang
+## C 99
+
+There are a few ways to compile the C 99 USearch SDK.
+Using the Makefile:
 
 ```sh
-cd golang
-go test -v
+make -C ./c build
 ```
 
-## Objective-C and Swift
+Using CMake:
 
 ```sh
-swift build
-swift test -v
+cmake -B ./build_release -DUSEARCH_BUILD_C=1 && make -C ./build_release -j
 ```
 
-## C99
-
 Linux:
 
 ```sh
-g++ -shared -fPIC lib.cpp -I ../include/  -I ../fp16/include/ -o libusearch.so
+g++ -std=c++11 -shared -fPIC c/lib.cpp -I ./include/  -I ./fp16/include/ -I ./robin-map/include/ -o libusearch.so
 ```
 
+
+## GoLang
+
+GoLang bindings are based on C.
+So one should first compile the C library, link it with GoLang, and only then run tests.
+
+```sh
+cd golang && make -C ../c build && mv ../c/libusearch.so libusearch.so && go test -v
+```
+
+## Wolfram
+
+```sh
+brew install --cask wolfram-engine
+```
+
+
 ## Docker
 
 ```sh
diff --git a/docs/cpp/index.rst b/docs/cpp/index.rst
index b3487c56..c76ef6f4 100644
--- a/docs/cpp/index.rst
+++ b/docs/cpp/index.rst
@@ -1,5 +1,5 @@
 =====================
-USearch for C++
+C++ SDK
 =====================
 
 
diff --git a/docs/cpp/reference.rst b/docs/cpp/reference.rst
index f314a68d..907ced76 100644
--- a/docs/cpp/reference.rst
+++ b/docs/cpp/reference.rst
@@ -7,11 +7,11 @@ usearch/index.hpp
 .. doxygenfile:: index.hpp
 
 =================================
-usearch/index_punned_helpers.hpp
+usearch/index_plugins.hpp
 =================================
-.. doxygenfile:: index_punned_helpers.hpp
+.. doxygenfile:: index_plugins.hpp
 
 =================================
-usearch/index_punned_dense.hpp
+usearch/index_dense.hpp
 =================================
-.. doxygenfile:: index_punned_dense.hpp
+.. doxygenfile:: index_dense.hpp
diff --git a/golang/lib.go b/golang/lib.go
index c115c6b5..08890f91 100644
--- a/golang/lib.go
+++ b/golang/lib.go
@@ -2,52 +2,66 @@ package usearch
 
 import (
 	"errors"
-	"fmt"
 	"unsafe"
 )
 
 /*
-#include "../c/usearch.h"
-
-#cgo CPPFLAGS: -I.
-#cgo LDFLAGS: -lusearch
+#cgo CFLAGS: -I${SRCDIR}/../c/
+#cgo LDFLAGS: -L./ -lusearch
+#include <usearch.h>
+#include <stdlib.h>
 */
 import "C"
 
-type DistMetric int8
+type Key = uint64
+
+type Metric uint8
 
 const (
-	L2_SQ DistMetric = iota
-	IP
-	COS
+	InnerProduct Metric = iota
+	Cosine
+	L2sq
 	Haversine
+	Pearson
+	Hamming
+	Tanimoto
+	Sorensen
 )
 
-func (m DistMetric) String() string {
+func (m Metric) String() string {
 	switch m {
-	case L2_SQ:
+	case L2sq:
 		return "l2sq"
-	case IP:
+	case InnerProduct:
 		return "ip"
-	case COS:
+	case Cosine:
 		return "cos"
 	case Haversine:
 		return "haversine"
+	case Pearson:
+		return "pearson"
+	case Hamming:
+		return "hamming"
+	case Tanimoto:
+		return "tanimoto"
+	case Sorensen:
+		return "sorensen"
 	default:
-		panic("unknown metric")
+		panic("Unknown metric")
 	}
 }
 
-type Accuracy int8
+type Quantization uint8
 
 const (
-	f32 Accuracy = iota
+	f32 Quantization = iota
 	f16
 	f64
-	f8
+	i8
+	b1
 )
 
-func (a Accuracy) String() string {
+func (a Quantization) String() string {
 	switch a {
 	case f16:
 		return "f16"
@@ -55,30 +69,38 @@ func (a Accuracy) String() string {
 		return "f32"
 	case f64:
 		return "f64"
-	case f8:
-		return "f8"
+	case i8:
+		return "i8"
+	case b1:
+		return "b1"
 	default:
-		panic("unknown accuracy")
+		panic("Unknown quantization")
 	}
 }
 
 type IndexConfig struct {
-	Accuracy        Accuracy
-	Metric          DistMetric
-	VecDimension    int
-	InitCapacity    int
-	Connectivity    int
-	ExpansionAdd    int
-	ExpansionSearch int
+	// The scalar kind used for quantization of vector data during indexing.
+	Quantization Quantization
+	// The metric kind used for distance calculation between vectors.
+	Metric Metric
+	// The number of dimensions in the vectors to be indexed.
+	Dimensions uint
+	// The @b optional connectivity parameter that limits connections-per-node in graph.
+	Connectivity uint
+	// The @b optional expansion factor used for index construction when adding vectors.
+	ExpansionAdd uint
+	// The @b optional expansion factor used for index construction during search operations.
+	ExpansionSearch uint
 }
 
-func DefaultConfig(dimension int) IndexConfig {
+func DefaultConfig(dimensions uint) IndexConfig {
 	c := IndexConfig{}
-	c.InitCapacity = 32
-	c.Connectivity = 16
-	c.VecDimension = dimension
-	c.ExpansionAdd = 128
-	c.ExpansionSearch = 64
+	c.Dimensions = dimensions
+	c.Metric = Cosine
+	// Zeros will be replaced by the underlying C implementation
+	c.Connectivity = 0
+	c.ExpansionAdd = 0
+	c.ExpansionSearch = 0
 	return c
 }
 
@@ -87,152 +109,264 @@ type Index struct {
 	config        IndexConfig
 }
 
-func NewIndex(conf IndexConfig) *Index {
-	ind := &Index{config: conf}
-	ind.init()
-	return ind
-}
+// Initializes a new instance of the index.
+func NewIndex(conf IndexConfig) (index *Index, err error) {
+	index = &Index{config: conf}
 
-func (ind *Index) init() {
-	conf := ind.config
-	metric_str := C.CString(conf.Metric.String())
-	defer C.free(unsafe.Pointer(metric_str))
-	metric_len := C.int(len(conf.Metric.String()))
-	accuracy_str := C.CString(conf.Accuracy.String())
-	defer C.free(unsafe.Pointer(accuracy_str))
-	accuracy_len := C.int(len(conf.Accuracy.String()))
-	dimensions := C.int(conf.VecDimension)
-	capacity := C.int(conf.InitCapacity)
-	connectivity := C.int(conf.Connectivity)
-	expansion_add := C.int(conf.ExpansionAdd)
-	expansion_search := C.int(conf.ExpansionSearch)
-	ptr := C.usearch_new(metric_str, metric_len,
-		accuracy_str, accuracy_len,
-		dimensions, capacity, connectivity,
-		expansion_add, expansion_search)
+	conf = index.config
+	dimensions := C.ulong(conf.Dimensions)
+	connectivity := C.ulong(conf.Connectivity)
+	expansion_add := C.ulong(conf.ExpansionAdd)
+	expansion_search := C.ulong(conf.ExpansionSearch)
 
-	ind.opaque_handle = (*C.void)(unsafe.Pointer(ptr))
-}
+	options := C.struct_usearch_init_options_t{}
+	options.dimensions = dimensions
+	options.connectivity = connectivity
+	options.expansion_add = expansion_add
+	options.expansion_search = expansion_search
 
-func (ind *Index) Destroy() {
-	if ind.opaque_handle == nil {
-		panic("index not initialized")
+	// Map the metric kind to a C enum
+	switch conf.Metric {
+	case L2sq:
+		options.metric_kind = C.usearch_metric_l2sq_k
+	case InnerProduct:
+		options.metric_kind = C.usearch_metric_ip_k
+	case Cosine:
+		options.metric_kind = C.usearch_metric_cos_k
+	case Haversine:
+		options.metric_kind = C.usearch_metric_haversine_k
+	case Pearson:
+		options.metric_kind = C.usearch_metric_pearson_k
+	case Hamming:
+		options.metric_kind = C.usearch_metric_hamming_k
+	case Tanimoto:
+		options.metric_kind = C.usearch_metric_tanimoto_k
+	case Sorensen:
+		options.metric_kind = C.usearch_metric_sorensen_k
+	default:
+		options.metric_kind = C.usearch_metric_unknown_k
 	}
-	C.usearch_free(unsafe.Pointer(ind.opaque_handle))
-	ind.opaque_handle = nil
-	ind.config = IndexConfig{}
-}
 
-func (ind *Index) fileOp(path string, op string) error {
-	if ind.opaque_handle == nil {
-		panic("index not initialized")
-	}
-	c_path := C.CString(path)
-	defer C.free(unsafe.Pointer(c_path))
-	var errStr *C.char
-	switch op {
-	case "load":
-		errStr = C.usearch_load(unsafe.Pointer(ind.opaque_handle), c_path)
-	case "save":
-		errStr = C.usearch_save(unsafe.Pointer(ind.opaque_handle), c_path)
-	case "view":
-		errStr = C.usearch_view(unsafe.Pointer(ind.opaque_handle), c_path)
+	// Map the quantization method
+	switch conf.Quantization {
+	case f16:
+		options.quantization = C.usearch_scalar_f16_k
+	case f32:
+		options.quantization = C.usearch_scalar_f32_k
+	case f64:
+		options.quantization = C.usearch_scalar_f64_k
+	case i8:
+		options.quantization = C.usearch_scalar_i8_k
+	case b1:
+		options.quantization = C.usearch_scalar_b1_k
 	default:
-		panic("unknown file operation")
+		options.quantization = C.usearch_scalar_unknown_k
+	}
+
+	var errorMessage *C.char
+	ptr := C.usearch_init(&options, (*C.usearch_error_t)(&errorMessage))
+	if errorMessage != nil {
+		return nil, errors.New(C.GoString(errorMessage))
 	}
-	var err error
-	if errStr != nil {
-		err = errors.New(C.GoString(errStr))
-		C.free(unsafe.Pointer(errStr))
+
+	index.opaque_handle = (*C.void)(unsafe.Pointer(ptr))
+	return index, nil
+}
+
+func (index *Index) Len() (len uint, err error) {
+	var errorMessage *C.char
+	len = uint(C.usearch_size((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (*C.usearch_error_t)(&errorMessage)))
+	if errorMessage != nil {
+		err = errors.New(C.GoString(errorMessage))
+	}
+	return len, err
+}
+
+func (index *Index) Connectivity() (con uint, err error) {
+	var errorMessage *C.char
+	con = uint(C.usearch_connectivity((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (*C.usearch_error_t)(&errorMessage)))
+	if errorMessage != nil {
+		err = errors.New(C.GoString(errorMessage))
 	}
-	return err
+	return con, err
 }
 
-func (ind *Index) Save(path string) error {
-	return ind.fileOp(path, "save")
+func (index *Index) Dimensions() (dim uint, err error) {
+	var errorMessage *C.char
+	dim = uint(C.usearch_dimensions((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (*C.usearch_error_t)(&errorMessage)))
+	if errorMessage != nil {
+		err = errors.New(C.GoString(errorMessage))
+	}
+	return dim, err
 }
 
-func (ind *Index) Load(path string) error {
-	return ind.fileOp(path, "load")
+func (index *Index) Capacity() (cap uint, err error) {
+	var errorMessage *C.char
+	cap = uint(C.usearch_capacity((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (*C.usearch_error_t)(&errorMessage)))
+	if errorMessage != nil {
+		err = errors.New(C.GoString(errorMessage))
+	}
+	return cap, err
 }
 
-func (ind *Index) View(path string) error {
-	return ind.fileOp(path, "view")
+// Frees the resources associated with the index.
+func (index *Index) Destroy() error {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
+	}
+
+	var errorMessage *C.char
+	C.usearch_free((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (*C.usearch_error_t)(&errorMessage))
+	if errorMessage != nil {
+		return errors.New(C.GoString(errorMessage))
+	}
+	index.opaque_handle = nil
+	index.config = IndexConfig{}
+	return nil
 }
 
-func (ind *Index) Len() int {
-	return int(C.usearch_size(unsafe.Pointer(ind.opaque_handle)))
+// Reserves memory for a specified number of incoming vectors.
+func (index *Index) Reserve(capacity uint) error {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
+	}
+
+	var errorMessage *C.char
+	C.usearch_reserve((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (C.size_t)(capacity), (*C.usearch_error_t)(&errorMessage))
+	if errorMessage != nil {
+		return errors.New(C.GoString(errorMessage))
+	}
+	return nil
 }
 
-func (ind *Index) Connectivity() int {
-	return int(C.usearch_connectivity(unsafe.Pointer(ind.opaque_handle)))
+// Adds a vector with a key to the index.
+func (index *Index) Add(key Key, vec []float32) error {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
+	}
+
+	var errorMessage *C.char
+	C.usearch_add((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (C.usearch_key_t)(key), unsafe.Pointer(&vec[0]), C.usearch_scalar_f32_k, (*C.usearch_error_t)(&errorMessage))
+	if errorMessage != nil {
+		return errors.New(C.GoString(errorMessage))
+	}
+	return nil
 }
 
-func (ind *Index) VecDimension() int {
-	return int(C.usearch_dimensions(unsafe.Pointer(ind.opaque_handle)))
+// Removes the vector associated with the given key from the index.
+func (index *Index) Remove(key Key) error {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
+	}
+
+	var errorMessage *C.char
+	C.usearch_remove((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (C.usearch_key_t)(key), (*C.usearch_error_t)(&errorMessage))
+	if errorMessage != nil {
+		return errors.New(C.GoString(errorMessage))
+	}
+	return nil
 }
 
-func (ind *Index) Capacity() int {
-	return int(C.usearch_capacity(unsafe.Pointer(ind.opaque_handle)))
+// Checks if the index contains a vector with a specific key.
+func (index *Index) Contains(key Key) (found bool, err error) {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
+	}
+
+	var errorMessage *C.char
+	found = bool(C.usearch_contains((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (C.usearch_key_t)(key), (*C.usearch_error_t)(&errorMessage)))
+	if errorMessage != nil {
+		return found, errors.New(C.GoString(errorMessage))
+	}
+	return found, nil
 }
 
-func (ind *Index) Reserve(capacity int) error {
-	if ind.opaque_handle == nil {
-		panic("index not initialized")
+func (index *Index) Get(key Key) (vector []float32, err error) {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
 	}
-	errStr := C.usearch_reserve(unsafe.Pointer(ind.opaque_handle), (C.int)(capacity))
-	var err error
-	if errStr != nil {
-		err = errors.New(C.GoString(errStr))
-		C.free(unsafe.Pointer(errStr))
+
+	vector = make([]float32, index.config.Dimensions)
+	var errorMessage *C.char
+	found := bool(C.usearch_get((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), (C.usearch_key_t)(key), unsafe.Pointer(&vector[0]), C.usearch_scalar_f32_k, (*C.usearch_error_t)(&errorMessage)))
+	if errorMessage != nil {
+		return nil, errors.New(C.GoString(errorMessage))
 	}
-	return err
+	if !found {
+		return nil, nil
+	}
+	return vector, nil
 }
 
-func (ind *Index) Add(label int, vec []float32) error {
-	if ind.opaque_handle == nil {
-		panic("index not initialized")
+// Performs k-Approximate Nearest Neighbors Search for closest vectors to query.
+func (index *Index) Search(query []float32, limit uint) (keys []Key, distances []float32, err error) {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
+	}
+	if len(query) != int(index.config.Dimensions) {
+		return nil, nil, errors.New("Number of dimensions doesn't match!")
 	}
-	errStr := C.usearch_add(unsafe.Pointer(ind.opaque_handle), (C.int)(label), (*C.float)(&vec[0]))
-	var err error
-	if errStr != nil {
-		err = errors.New(C.GoString(errStr))
-		C.free(unsafe.Pointer(errStr))
+
+	keys = make([]Key, limit)
+	distances = make([]float32, limit)
+	var errorMessage *C.char
+	count := uint(C.usearch_search((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), unsafe.Pointer(&query[0]), C.usearch_scalar_f32_k, (C.size_t)(limit), (*C.usearch_key_t)(&keys[0]), (*C.usearch_distance_t)(&distances[0]), (*C.usearch_error_t)(&errorMessage)))
+	if errorMessage != nil {
+		return nil, nil, errors.New(C.GoString(errorMessage))
 	}
-	return err
 
+	keys = keys[:count]
+	distances = distances[:count]
+	return keys, distances, nil
 }
 
-// return must be int32 because int is 64bit in golang and 32bit in C
-func (ind *Index) Search(query []float32, limit int) []int32 {
-	if ind.opaque_handle == nil {
-		panic("index not initialized")
+// Saves the index to a file.
+func (index *Index) Save(path string) error {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
 	}
-	if len(query) != ind.config.VecDimension {
-		panic(fmt.Sprintf("query vector dimension mismatch. expected %d, got %d",
-			ind.config.VecDimension, len(query)))
+
+	c_path := C.CString(path)
+	defer C.free(unsafe.Pointer(c_path))
+
+	var errorMessage *C.char
+	C.usearch_save((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), c_path, (*C.usearch_error_t)(&errorMessage))
+	if errorMessage != nil {
+		return errors.New(C.GoString(errorMessage))
 	}
-	if limit <= 0 {
-		panic("limit must be greater than 0")
+	return nil
+}
+
+// Loads the index from a file.
+func (index *Index) Load(path string) error {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
 	}
-	res := C.usearch_search(unsafe.Pointer(ind.opaque_handle),
-		(*C.float)(&query[0]), (C.int)(len(query)), (C.int)(limit))
 
-	// my understanding is that search panics in truly exceptional cases,
-	// none of which is every expected. so, not passing the error to the caller
-	if res.Error != nil {
-		defer C.free(unsafe.Pointer(res.Error))
-		panic(C.GoString(res.Error))
+	c_path := C.CString(path)
+	defer C.free(unsafe.Pointer(c_path))
+
+	var errorMessage *C.char
+	C.usearch_load((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), c_path, (*C.usearch_error_t)(&errorMessage))
+	if errorMessage != nil {
+		return errors.New(C.GoString(errorMessage))
 	}
-	var labs []int32
-	//q:: who free's this memory? will golang do it?
-	labs = unsafe.Slice((*int32)(unsafe.Pointer(res.Labels)), res.Len)
-	return labs
+	return nil
 }
 
-func (ind *Index) Size() int {
-	if ind.opaque_handle == nil {
-		panic("index not initialized")
+// Creates a view of the index from a file without loading it into memory.
+func (index *Index) View(path string) error {
+	if index.opaque_handle == nil {
+		panic("Index is uninitialized")
+	}
+
+	c_path := C.CString(path)
+	defer C.free(unsafe.Pointer(c_path))
+
+	var errorMessage *C.char
+	C.usearch_view((C.usearch_index_t)(unsafe.Pointer(index.opaque_handle)), c_path, (*C.usearch_error_t)(&errorMessage))
+	if errorMessage != nil {
+		return errors.New(C.GoString(errorMessage))
 	}
-	return int(C.usearch_size(unsafe.Pointer(ind.opaque_handle)))
+	return nil
 }
diff --git a/golang/usearch.h b/golang/usearch.h
deleted file mode 100644
index b18343d5..00000000
--- a/golang/usearch.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-#include <stdlib.h>
-
-typedef struct {
-    int* Labels;
-    float* Distances;
-    int Len;
-    char* Error;
-} SearchResults;
diff --git a/include/usearch/index.hpp b/include/usearch/index.hpp
index 11ade638..3be878f0 100644
--- a/include/usearch/index.hpp
+++ b/include/usearch/index.hpp
@@ -1,6 +1,6 @@
 /**
  *  @file index.hpp
- *  @author Ashot Vardanian
+ *  @author Ash Vardanian
  *  @brief Single-header Vector Search.
  *  @date 2023-04-26
  *
@@ -14,6 +14,7 @@
 #define USEARCH_VERSION_PATCH 0
 
 // Inferring C++ version
+// https://stackoverflow.com/a/61552074
 #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
 #define USEARCH_DEFINED_CPP17
 #endif
@@ -42,10 +43,13 @@
 #endif
 
 // Inferring hardware bitness: 32 vs 64
-#if __WORDSIZE == 64
+// https://stackoverflow.com/a/5273354
+#if INTPTR_MAX == INT64_MAX
 #define USEARCH_64BIT_ENV
-#else
+#elif INTPTR_MAX == INT32_MAX
 #define USEARCH_32BIT_ENV
+#else
+#error Unknown pointer size or missing size macros!
 #endif
 
 #if !defined(USEARCH_USE_OPENMP)
@@ -119,51 +123,7 @@
 namespace unum {
 namespace usearch {
 
-using f64_t = double;
-using f32_t = float;
 using byte_t = char;
-enum b1x8_t : unsigned char {};
-
-enum class metric_kind_t : std::uint8_t {
-    unknown_k = 0,
-    // Classics:
-    ip_k = 'i',
-    cos_k = 'c',
-    l2sq_k = 'e',
-
-    // Custom:
-    pearson_k = 'p',
-    haversine_k = 'h',
-
-    // Sets:
-    jaccard_k = 'j',
-    hamming_k = 'b',
-    tanimoto_k = 't',
-    sorensen_k = 's',
-};
-
-enum class scalar_kind_t : std::uint8_t {
-    unknown_k = 0,
-    f64_k,
-    f32_k,
-    f16_k,
-    f8_k,
-    b1x8_k,
-};
-
-template <typename scalar_at> scalar_kind_t common_scalar_kind() noexcept {
-    if (std::is_same<scalar_at, f32_t>())
-        return scalar_kind_t::f32_k;
-    if (std::is_same<scalar_at, f64_t>())
-        return scalar_kind_t::f64_k;
-    if (std::is_same<scalar_at, b1x8_t>())
-        return scalar_kind_t::b1x8_k;
-    return scalar_kind_t::unknown_k;
-}
-
-template <typename at> at angle_to_radians(at angle) noexcept { return angle * at(3.14159265358979323846) / at(180); }
-
-template <typename at> at square(at value) noexcept { return value * value; }
 
 template <std::size_t multiple_ak> std::size_t divide_round_up(std::size_t num) noexcept {
     return (num + multiple_ak - 1) / multiple_ak;
@@ -187,6 +147,7 @@ inline std::size_t ceil2(std::size_t v) noexcept {
     return v;
 }
 
+/// @brief  Simply dereferencing misaligned pointers can be dangerous.
 template <typename at> void misaligned_store(void* ptr, at v) noexcept {
     static_assert(!std::is_reference<at>::value, "Can't store a reference");
     std::memcpy(ptr, &v, sizeof(at));
@@ -207,54 +168,80 @@ template <typename at, typename other_at = at> at exchange(at& obj, other_at&& n
     return old_value;
 }
 
+/// @brief  The `std::destroy_at` alternative for C++11.
+template <typename at, typename sfinae_at = at>
+typename std::enable_if<std::is_pod<sfinae_at>::value>::type destroy_at(at*) {}
+template <typename at, typename sfinae_at = at>
+typename std::enable_if<!std::is_pod<sfinae_at>::value>::type destroy_at(at* obj) {
+    obj->~sfinae_at();
+}
+
+/// @brief  The `std::construct_at` alternative for C++11.
+template <typename at, typename sfinae_at = at>
+typename std::enable_if<std::is_pod<sfinae_at>::value>::type construct_at(at*) {}
+template <typename at, typename sfinae_at = at>
+typename std::enable_if<!std::is_pod<sfinae_at>::value>::type construct_at(at* obj) {
+    new (obj) at();
+}
+
+/**
+ *  @brief  A reference to a misaligned memory location with a specific type.
+ *          It is needed to avoid Undefined Behavior when dereferencing addresses
+ *          indivisible by `sizeof(at)`.
+ */
 template <typename at> class misaligned_ref_gt {
+    using element_t = at;
+    using mutable_t = typename std::remove_const<element_t>::type;
     byte_t* ptr_;
 
   public:
     misaligned_ref_gt(byte_t* ptr) noexcept : ptr_(ptr) {}
-    operator at() const noexcept { return misaligned_load<at>(ptr_); }
-    misaligned_ref_gt& operator=(at const& v) noexcept {
-        misaligned_store<at>(ptr_, v);
+    operator mutable_t() const noexcept { return misaligned_load<mutable_t>(ptr_); }
+    misaligned_ref_gt& operator=(mutable_t const& v) noexcept {
+        misaligned_store<mutable_t>(ptr_, v);
         return *this;
     }
 
     void reset(byte_t* ptr) noexcept { ptr_ = ptr; }
+    byte_t* ptr() const noexcept { return ptr_; }
 };
 
+/**
+ *  @brief  A pointer to a misaligned memory location with a specific type.
+ *          It is needed to avoid Undefined Behavior when dereferencing addresses
+ *          indivisible by `sizeof(at)`.
+ */
 template <typename at> class misaligned_ptr_gt {
+    using element_t = at;
+    using mutable_t = typename std::remove_const<element_t>::type;
     byte_t* ptr_;
 
   public:
     using iterator_category = std::random_access_iterator_tag;
-    using value_type = at;
+    using value_type = element_t;
     using difference_type = std::ptrdiff_t;
-    using pointer = misaligned_ptr_gt<at>;
-    using reference = misaligned_ref_gt<at>;
+    using pointer = misaligned_ptr_gt<element_t>;
+    using reference = misaligned_ref_gt<element_t>;
 
     reference operator*() const noexcept { return {ptr_}; }
+    reference operator[](std::size_t i) noexcept { return reference(ptr_ + i * sizeof(element_t)); }
+    value_type operator[](std::size_t i) const noexcept {
+        return misaligned_load<element_t>(ptr_ + i * sizeof(element_t));
+    }
 
     misaligned_ptr_gt(byte_t* ptr) noexcept : ptr_(ptr) {}
-    misaligned_ptr_gt operator++(int) noexcept { return misaligned_ptr_gt(ptr_ + sizeof(at)); }
-    misaligned_ptr_gt operator--(int) noexcept { return misaligned_ptr_gt(ptr_ - sizeof(at)); }
-    misaligned_ptr_gt operator+(difference_type d) noexcept { return misaligned_ptr_gt(ptr_ + d * sizeof(at)); }
-    misaligned_ptr_gt operator-(difference_type d) noexcept { return misaligned_ptr_gt(ptr_ - d * sizeof(at)); }
+    misaligned_ptr_gt operator++(int) noexcept { return misaligned_ptr_gt(ptr_ + sizeof(element_t)); }
+    misaligned_ptr_gt operator--(int) noexcept { return misaligned_ptr_gt(ptr_ - sizeof(element_t)); }
+    misaligned_ptr_gt operator+(difference_type d) noexcept { return misaligned_ptr_gt(ptr_ + d * sizeof(element_t)); }
+    misaligned_ptr_gt operator-(difference_type d) noexcept { return misaligned_ptr_gt(ptr_ - d * sizeof(element_t)); }
+
+    // clang-format off
+    misaligned_ptr_gt& operator++() noexcept { ptr_ += sizeof(element_t); return *this; }
+    misaligned_ptr_gt& operator--() noexcept { ptr_ -= sizeof(element_t); return *this; }
+    misaligned_ptr_gt& operator+=(difference_type d) noexcept { ptr_ += d * sizeof(element_t); return *this; }
+    misaligned_ptr_gt& operator-=(difference_type d) noexcept { ptr_ -= d * sizeof(element_t); return *this; }
+    // clang-format on
 
-    misaligned_ptr_gt& operator++() noexcept {
-        ptr_ += sizeof(at);
-        return *this;
-    }
-    misaligned_ptr_gt& operator--() noexcept {
-        ptr_ -= sizeof(at);
-        return *this;
-    }
-    misaligned_ptr_gt& operator+=(difference_type d) noexcept {
-        ptr_ += d * sizeof(at);
-        return *this;
-    }
-    misaligned_ptr_gt& operator-=(difference_type d) noexcept {
-        ptr_ -= d * sizeof(at);
-        return *this;
-    }
     bool operator==(misaligned_ptr_gt const& other) noexcept { return ptr_ == other.ptr_; }
     bool operator!=(misaligned_ptr_gt const& other) noexcept { return ptr_ != other.ptr_; }
 };
@@ -278,307 +265,56 @@ template <typename scalar_at> class span_gt {
 };
 
 /**
- *  @brief  Inner (Dot) Product distance.
- */
-template <typename scalar_at = float, typename result_at = scalar_at> struct ip_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::ip_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-    inline result_t operator()(view_t a, view_t b) const noexcept { return operator()(a.data(), b.data(), a.size()); }
-
-    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t dim) const noexcept {
-        result_type ab{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : ab)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != dim; ++i)
-            ab += result_t(a[i]) * result_t(b[i]);
-        return 1 - ab;
-    }
-};
-
-/**
- *  @brief  Cosine (Angular) distance.
- *          Identical to the Inner Product of normalized vectors.
- *          Unless you are running on an tiny embedded platform, this metric
- *          is recommended over `::ip_gt` for low-precision scalars.
- */
-template <typename scalar_at = float, typename result_at = scalar_at> struct cos_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::cos_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-    inline result_t operator()(view_t a, view_t b) const noexcept { return operator()(a.data(), b.data(), a.size()); }
-
-    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t dim) const noexcept {
-        result_t ab{}, a2{}, b2{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : ab, a2, b2)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != dim; ++i)
-            ab += result_t(a[i]) * result_t(b[i]), //
-                a2 += square<result_t>(a[i]),      //
-                b2 += square<result_t>(b[i]);
-        return (ab != 0) ? (1 - ab / (std::sqrt(a2) * std::sqrt(b2))) : 1;
-    }
-};
-
-/**
- *  @brief  Squared Euclidean (L2) distance.
- *          Square root is avoided at the end, as it won't affect the ordering.
+ *  @brief  Similar to `std::vector`, but doesn't support dynamic resizing.
+ *          On the bright side, this can't throw exceptions.
  */
-template <typename scalar_at = float, typename result_at = scalar_at> struct l2sq_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::l2sq_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-    inline result_t operator()(view_t a, view_t b) const noexcept { return operator()(a.data(), b.data(), a.size()); }
-
-    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t dim) const noexcept {
-        result_t ab_deltas_sq{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : ab_deltas_sq)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != dim; ++i)
-            ab_deltas_sq += square(result_t(a[i]) - result_t(b[i]));
-        return ab_deltas_sq;
-    }
-};
-
-/**
- *  @brief  Hamming distance computes the number of differing bits in
- *          two arrays of integers. An example would be a textual document,
- *          tokenized and hashed into a fixed-capacity bitset.
- */
-template <typename scalar_at = std::uint64_t, typename result_at = std::size_t> struct hamming_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-    static_assert( //
-        std::is_unsigned<scalar_t>::value ||
-            (std::is_enum<scalar_t>::value && std::is_unsigned<typename std::underlying_type<scalar_t>::type>::value),
-        "Hamming distance requires unsigned integral words");
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::hamming_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-    inline result_t operator()(view_t a, view_t b) const noexcept { return operator()(a.data(), b.data(), a.size()); }
-
-    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t words) const noexcept {
-        constexpr std::size_t bits_per_word_k = sizeof(scalar_t) * CHAR_BIT;
-        result_t matches{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : matches)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != words; ++i)
-            matches += std::bitset<bits_per_word_k>(a[i] ^ b[i]).count();
-        return matches;
-    }
-};
+template <typename scalar_at, typename allocator_at> class buffer_gt {
+    scalar_at* data_;
+    std::size_t size_;
 
-/**
- *  @brief  Tanimoto distance is the intersection over bitwise union.
- *          Often used in chemistry and biology to compare molecular fingerprints.
- */
-template <typename scalar_at = std::uint64_t, typename result_at = float> struct tanimoto_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-    static_assert( //
-        std::is_unsigned<scalar_t>::value ||
-            (std::is_enum<scalar_t>::value && std::is_unsigned<typename std::underlying_type<scalar_t>::type>::value),
-        "Tanimoto distance requires unsigned integral words");
-    static_assert(std::is_floating_point<result_t>::value, "Tanimoto distance will be a fraction");
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::tanimoto_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-    inline result_t operator()(view_t a, view_t b) const noexcept { return operator()(a.data(), b.data(), a.size()); }
-
-    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t words) const noexcept {
-        constexpr std::size_t bits_per_word_k = sizeof(scalar_t) * CHAR_BIT;
-        result_t and_count{};
-        result_t or_count{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : and_count, or_count)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != words; ++i)
-            and_count += std::bitset<bits_per_word_k>(a[i] & b[i]).count(),
-                or_count += std::bitset<bits_per_word_k>(a[i] | b[i]).count();
-        return 1 - result_t(and_count) / or_count;
+  public:
+    buffer_gt() noexcept : data_(nullptr), size_(0u) {}
+    buffer_gt(std::size_t size) noexcept : data_(allocator_at{}.allocate(size)), size_(data_ ? size : 0u) {
+        if (!std::is_trivially_default_constructible<scalar_at>::value)
+            for (std::size_t i = 0; i != size_; ++i)
+                construct_at(data_ + i);
+    }
+    ~buffer_gt() noexcept {
+        if (!std::is_trivially_destructible<scalar_at>::value)
+            for (std::size_t i = 0; i != size_; ++i)
+                destroy_at(data_ + i);
+        allocator_at{}.deallocate(data_, size_);
+        data_ = nullptr;
+        size_ = 0;
     }
-};
-
-/**
- *  @brief  Sorensen-Dice or F1 distance is the intersection over bitwise union.
- *          Often used in chemistry and biology to compare molecular fingerprints.
- */
-template <typename scalar_at = std::uint64_t, typename result_at = float> struct sorensen_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-    static_assert( //
-        std::is_unsigned<scalar_t>::value ||
-            (std::is_enum<scalar_t>::value && std::is_unsigned<typename std::underlying_type<scalar_t>::type>::value),
-        "Sorensen-Dice distance requires unsigned integral words");
-    static_assert(std::is_floating_point<result_t>::value, "Sorensen-Dice distance will be a fraction");
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::sorensen_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-    inline result_t operator()(view_t a, view_t b) const noexcept { return operator()(a.data(), b.data(), a.size()); }
-
-    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t words) const noexcept {
-        constexpr std::size_t bits_per_word_k = sizeof(scalar_t) * CHAR_BIT;
-        result_t and_count{};
-        result_t any_count{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : and_count, any_count)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != words; ++i)
-            and_count += std::bitset<bits_per_word_k>(a[i] & b[i]).count(),
-                any_count += std::bitset<bits_per_word_k>(a[i]).count() + std::bitset<bits_per_word_k>(b[i]).count();
-        return 1 - 2 * result_t(and_count) / any_count;
+    scalar_at* data() const noexcept { return data_; }
+    std::size_t size() const noexcept { return size_; }
+    scalar_at* begin() const noexcept { return data_; }
+    scalar_at* end() const noexcept { return data_ + size_; }
+    operator scalar_at*() const noexcept { return data(); }
+    scalar_at& operator[](std::size_t i) noexcept { return data_[i]; }
+    scalar_at const& operator[](std::size_t i) const noexcept { return data_[i]; }
+    explicit operator bool() const noexcept { return data_; }
+    scalar_at* release() noexcept {
+        size_ = 0;
+        return exchange(data_, nullptr);
     }
-};
 
-/**
- *  @brief  Counts the number of matching elements in two unique sorted sets.
- *          Can be used to compute the similarity between two textual documents
- *          using the IDs of tokens present in them.
- *          Similar to `tanimoto_gt` for dense representations.
- */
-template <typename scalar_at = std::int32_t, typename result_at = float> struct jaccard_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-    static_assert(!std::is_floating_point<scalar_t>::value, "Jaccard distance requires integral scalars");
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::jaccard_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-    inline result_t operator()(view_t a, view_t b) const noexcept {
-        return operator()(a.data(), b.data(), a.size(), b.size());
-    }
-
-    inline result_t operator()( //
-        scalar_t const* a, scalar_t const* b, std::size_t a_length, std::size_t b_length) const noexcept {
-        result_t intersection{};
-        std::size_t i{};
-        std::size_t j{};
-        while (i != a_length && j != b_length) {
-            intersection += a[i] == b[j];
-            i += a[i] < b[j];
-            j += a[i] >= b[j];
-        }
-        return 1 - intersection / (a_length + b_length - intersection);
-    }
-};
+    buffer_gt(buffer_gt const&) = delete;
+    buffer_gt& operator=(buffer_gt const&) = delete;
 
-/**
- *  @brief  Counts the number of matching elements in two unique sorted sets.
- *          Can be used to compute the similarity between two textual documents
- *          using the IDs of tokens present in them.
- */
-template <typename scalar_at = float, typename result_at = float> struct pearson_correlation_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::pearson_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-    inline result_t operator()(view_t a, view_t b) const noexcept { return operator()(a.data(), b.data(), a.size()); }
-
-    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t dim) const noexcept {
-        result_t a_sum{}, b_sum{}, ab_sum{};
-        result_t a_sq_sum{}, b_sq_sum{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : a_sum, b_sum, ab_sum, a_sq_sum, b_sq_sum)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != dim; ++i) {
-            a_sum += result_t(a[i]);
-            b_sum += result_t(b[i]);
-            ab_sum += result_t(a[i]) * result_t(b[i]);
-            a_sq_sum += result_t(a[i]) * result_t(a[i]);
-            b_sq_sum += result_t(b[i]) * result_t(b[i]);
-        }
-        result_t denom = std::sqrt((dim * a_sq_sum - a_sum * a_sum) * (dim * b_sq_sum - b_sum * b_sum));
-        result_t corr = (dim * ab_sum - a_sum * b_sum) / denom;
-        return -corr;
+    buffer_gt(buffer_gt&& other) noexcept : data_(exchange(other.data_, nullptr)), size_(exchange(other.size_, 0)) {}
+    buffer_gt& operator=(buffer_gt&& other) noexcept {
+        std::swap(data_, other.data_);
+        std::swap(size_, other.size_);
+        return *this;
     }
 };
 
 /**
- *  @brief  Haversine distance for the shortest distance between two nodes on
- *          the surface of a 3D sphere, defined with latitude and longitude.
+ *  @brief  A lightweight error class for handling error messages,
+ *          which are expected to be allocated in static memory.
  */
-template <typename scalar_at = float, typename result_at = scalar_at> struct haversine_gt {
-    using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using result_t = result_at;
-    using result_type = result_t;
-    static_assert(!std::is_integral<scalar_t>::value, "Latitude and longitude must be floating-node");
-
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::haversine_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return common_scalar_kind<scalar_t>(); }
-
-    inline result_t operator()(scalar_t const* a, scalar_t const* b) const noexcept {
-        result_t lat_a = a[0], lon_a = a[1];
-        result_t lat_b = b[0], lon_b = b[1];
-
-        result_t lat_delta = angle_to_radians<result_t>(lat_b - lat_a);
-        result_t lon_delta = angle_to_radians<result_t>(lon_b - lon_a);
-
-        result_t converted_lat_a = angle_to_radians<result_t>(lat_a);
-        result_t converted_lat_b = angle_to_radians<result_t>(lat_b);
-
-        result_t x = //
-            square(std::sin(lat_delta / 2.f)) +
-            std::cos(converted_lat_a) * std::cos(converted_lat_b) * square(std::sin(lon_delta / 2.f));
-
-        return std::atan2(std::sqrt(x), std::sqrt(1.f - x));
-    }
-};
-
 class error_t {
     char const* message_{};
 
@@ -596,11 +332,14 @@ class error_t {
     explicit operator bool() const noexcept { return message_ != nullptr; }
     char const* what() const noexcept { return message_; }
 
-#if defined(__cpp_exceptions) && (1 == __cpp_exceptions)
+#if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
     ~error_t() noexcept(false) {
-        if (message_)
-            if (!std::uncaught_exception())
-                raise();
+#if defined(USEARCH_DEFINED_CPP17)
+        if (message_ && std::uncaught_exceptions() == 0)
+#else
+        if (message_ && std::uncaught_exception() == 0)
+#endif
+            raise();
     }
     void raise() noexcept(false) {
         if (message_)
@@ -615,6 +354,13 @@ class error_t {
 #endif
 };
 
+/**
+ *  @brief  Similar to `std::expected` in C++23, wraps a statement evaluation result,
+ *          or an error. It's used to avoid raising exception, and gracefully propagate
+ *          the error.
+ *
+ * @tparam result_at The type of the expected result.
+ */
 template <typename result_at> struct expected_gt {
     result_at result;
     error_t error;
@@ -637,49 +383,41 @@ template <typename result_at> struct expected_gt {
 
 /**
  *  @brief  Light-weight bitset implementation to track visited nodes during graph traversal.
- *          Extends basic functionality with atomic operations.
+ *          Extends basic functionality with @b atomic operations.
  */
-template <typename allocator_at = std::allocator<char>> class visits_bitset_gt {
+template <typename allocator_at = std::allocator<byte_t>> class visits_bitset_gt {
     using allocator_t = allocator_at;
     using byte_t = typename allocator_t::value_type;
     static_assert(sizeof(byte_t) == 1, "Allocator must allocate separate addressable bytes");
 
-    using slot_t = unsigned long;
+    using compressed_slot_t = unsigned long;
 
-    static constexpr std::size_t bits_per_slot() { return sizeof(slot_t) * CHAR_BIT; }
-    static constexpr slot_t bits_mask() { return sizeof(slot_t) * CHAR_BIT - 1; }
+    static constexpr std::size_t bits_per_slot() { return sizeof(compressed_slot_t) * CHAR_BIT; }
+    static constexpr compressed_slot_t bits_mask() { return sizeof(compressed_slot_t) * CHAR_BIT - 1; }
+    static constexpr std::size_t slots(std::size_t bits) { return divide_round_up<bits_per_slot()>(bits); }
 
-    slot_t* slots_{};
+    compressed_slot_t* slots_{};
     /// @brief Number of slots.
     std::size_t count_{};
 
   public:
     visits_bitset_gt() noexcept {}
     ~visits_bitset_gt() noexcept { reset(); }
-    void clear() noexcept { std::memset(slots_, 0, count_ * sizeof(slot_t)); }
+
+    explicit operator bool() const noexcept { return slots_; }
+    void clear() noexcept { std::memset(slots_, 0, count_ * sizeof(compressed_slot_t)); }
 
     void reset() noexcept {
         if (slots_)
-            allocator_t{}.deallocate((byte_t*)slots_, count_ * sizeof(slot_t));
+            allocator_t{}.deallocate((byte_t*)slots_, count_ * sizeof(compressed_slot_t));
         slots_ = nullptr;
         count_ = 0;
     }
 
-    bool resize(std::size_t capacity) noexcept {
-
-        std::size_t count = divide_round_up<bits_per_slot()>(capacity);
-        if (count <= count_)
-            return true;
-
-        slot_t* slots = (slot_t*)allocator_t{}.allocate(count * sizeof(slot_t));
-        if (!slots)
-            return false;
-
-        reset();
-        count_ = count;
-        slots_ = slots;
+    visits_bitset_gt(std::size_t capacity) noexcept
+        : slots_((compressed_slot_t*)allocator_t{}.allocate(slots(capacity) * sizeof(compressed_slot_t))),
+          count_(slots_ ? slots(capacity) : 0u) {
         clear();
-        return true;
     }
 
     visits_bitset_gt(visits_bitset_gt&& other) noexcept {
@@ -697,33 +435,54 @@ template <typename allocator_at = std::allocator<char>> class visits_bitset_gt {
     visits_bitset_gt& operator=(visits_bitset_gt const&) = delete;
 
     inline bool test(std::size_t i) const noexcept { return slots_[i / bits_per_slot()] & (1ul << (i & bits_mask())); }
-    inline void set(std::size_t i) noexcept { slots_[i / bits_per_slot()] |= (1ul << (i & bits_mask())); }
+    inline bool set(std::size_t i) noexcept {
+        compressed_slot_t& slot = slots_[i / bits_per_slot()];
+        compressed_slot_t mask{1ul << (i & bits_mask())};
+        bool value = slot & mask;
+        slot |= mask;
+        return value;
+    }
 
 #if defined(USEARCH_DEFINED_WINDOWS)
 
     inline bool atomic_set(std::size_t i) noexcept {
-        slot_t mask{1ul << (i & bits_mask())};
+        compressed_slot_t mask{1ul << (i & bits_mask())};
         return InterlockedOr((long volatile*)&slots_[i / bits_per_slot()], mask) & mask;
     }
 
     inline void atomic_reset(std::size_t i) noexcept {
-        slot_t mask{1ul << (i & bits_mask())};
+        compressed_slot_t mask{1ul << (i & bits_mask())};
         InterlockedAnd((long volatile*)&slots_[i / bits_per_slot()], ~mask);
     }
 
 #else
 
     inline bool atomic_set(std::size_t i) noexcept {
-        slot_t mask{1ul << (i & bits_mask())};
+        compressed_slot_t mask{1ul << (i & bits_mask())};
         return __atomic_fetch_or(&slots_[i / bits_per_slot()], mask, __ATOMIC_ACQUIRE) & mask;
     }
 
     inline void atomic_reset(std::size_t i) noexcept {
-        slot_t mask{1ul << (i & bits_mask())};
+        compressed_slot_t mask{1ul << (i & bits_mask())};
         __atomic_fetch_and(&slots_[i / bits_per_slot()], ~mask, __ATOMIC_RELEASE);
     }
 
 #endif
+
+    class lock_t {
+        visits_bitset_gt& bitset_;
+        std::size_t bit_offset_;
+
+      public:
+        inline ~lock_t() noexcept { bitset_.atomic_reset(bit_offset_); }
+        inline lock_t(visits_bitset_gt& bitset, std::size_t bit_offset) noexcept
+            : bitset_(bitset), bit_offset_(bit_offset) {
+            while (bitset_.atomic_set(bit_offset_))
+                ;
+        }
+    };
+
+    inline lock_t lock(std::size_t i) noexcept { return {*this, i}; }
 };
 
 using visits_bitset_t = visits_bitset_gt<>;
@@ -1006,10 +765,10 @@ class usearch_pack_m uint40_t {
 
   public:
     inline uint40_t() noexcept { broadcast(0); }
-    inline uint40_t(std::uint32_t n) noexcept { std::memcpy(octets, (char*)&n, 4); }
-    inline uint40_t(std::uint64_t n) noexcept { std::memcpy(octets, (char*)&n, 5); }
-#if defined(USEARCH_DEFINED_CLANG) && defined(USEARCH_DEFINED_APPLE)
-    inline uint40_t(std::size_t n) noexcept { std::memcpy(octets, (char*)&n, 5); }
+    inline uint40_t(std::uint32_t n) noexcept { std::memcpy(&octets[1], &n, 4); }
+
+#ifdef USEARCH_64BIT_ENV
+    inline uint40_t(std::uint64_t n) noexcept { std::memcpy(octets, &n, 5); }
 #endif
 
     uint40_t(uint40_t&&) = default;
@@ -1017,47 +776,26 @@ class usearch_pack_m uint40_t {
     uint40_t& operator=(uint40_t&&) = default;
     uint40_t& operator=(uint40_t const&) = default;
 
-    inline uint40_t& operator+=(std::uint32_t n) noexcept {
-        std::uint32_t& tail = *reinterpret_cast<std::uint32_t*>(octets);
-        octets[4] += static_cast<unsigned char>((tail + n) < tail);
-        tail += n;
-        return *this;
-    }
-
-    inline uint40_t& operator+=(std::size_t n) noexcept {
-        unsigned char* n_octets = reinterpret_cast<unsigned char*>(&n);
-        std::uint32_t& n_tail = *reinterpret_cast<std::uint32_t*>(n_octets);
-        std::uint32_t& tail = *reinterpret_cast<std::uint32_t*>(octets);
-        octets[4] += static_cast<unsigned char>((tail + n_tail) < tail);
-        tail += n_tail;
-        octets[4] += n_octets[4];
-        return *this;
-    }
-
-    inline uint40_t operator+(std::size_t n) noexcept {
-        uint40_t other(*this);
-        other += n;
-        return other;
+#if defined(USEARCH_DEFINED_CLANG) && defined(USEARCH_DEFINED_APPLE)
+    inline uint40_t(std::size_t n) noexcept {
+#ifdef USEARCH_64BIT_ENV
+        std::memcpy(octets, &n, 5);
+#else
+        std::memcpy(octets, &n, 4);
+#endif
     }
+#endif
 
     inline operator std::size_t() const noexcept {
         std::size_t result = 0;
 #ifdef USEARCH_64BIT_ENV
-        std::memcpy((char*)&result + 3, octets, 5);
+        std::memcpy(&result, octets, 5);
 #else
-        std::memcpy((char*)&result, octets + 1, 4);
+        std::memcpy(&result, octets + 1, 4);
 #endif
         return result;
     }
 
-    inline uint40_t& operator++() noexcept { return *this += 1u; }
-
-    inline uint40_t operator++(int) noexcept {
-        uint40_t old = *this;
-        *this += 1u;
-        return old;
-    }
-
     inline static uint40_t max() noexcept { return uint40_t{}.broadcast(0xFF); }
     inline static uint40_t min() noexcept { return uint40_t{}.broadcast(0); }
 };
@@ -1068,6 +806,9 @@ class usearch_pack_m uint40_t {
 
 static_assert(sizeof(uint40_t) == 5, "uint40_t must be exactly 5 bytes");
 
+/**
+ *  @brief  Basic single-threaded @b ring class, used for all kinds of task queues.
+ */
 template <typename element_at, typename allocator_at = std::allocator<element_at>> //
 class ring_gt {
   public:
@@ -1202,12 +943,6 @@ constexpr std::size_t default_expansion_search() { return 64; }
 
 constexpr std::size_t default_allocator_entry_bytes() { return 64; }
 
-/**
- *  @brief  The "magic" sequence helps infer the type of the file.
- *          USearch indexes start with the "usearch" string.
- */
-constexpr char const* default_magic() { return "usearch"; }
-
 /**
  *  @brief  Configuration settings for the index construction.
  *          Includes the main `::connectivity` parameter (`M` in the paper)
@@ -1219,14 +954,16 @@ struct index_config_t {
     /// > It is called `M` in the paper.
     std::size_t connectivity = default_connectivity();
 
-    /// @brief Parameter controlling the physical layout of vectors
-    /// in memory. When using multi-byte scalar types, like `float`,
-    /// dereferencing at mis-aligned locations may cause UB. So you
-    /// should set it to at least the size of expected floats.
-    /// Moreover, when using SIMD-accelerated metrics, you may prefer
-    /// to align to SIMD register size for higher performance with
-    /// less split-loads.
-    std::size_t vector_alignment = 1;
+    /// @brief Number of neighbors per graph node in base level graph.
+    /// Defaults to double of the other levels, so 64 in FAISS and 32 in hnswlib.
+    /// > It is called `M0` in the paper.
+    std::size_t connectivity_base = default_connectivity() * 2;
+
+    inline index_config_t() = default;
+    inline index_config_t(std::size_t c) noexcept
+        : connectivity(c ? c : default_connectivity()), connectivity_base(c ? c * 2 : default_connectivity() * 2) {}
+    inline index_config_t(std::size_t c, std::size_t cb) noexcept
+        : connectivity(c), connectivity_base((std::max)(c, cb)) {}
 };
 
 struct index_limits_t {
@@ -1234,13 +971,13 @@ struct index_limits_t {
     std::size_t threads_add = std::thread::hardware_concurrency();
     std::size_t threads_search = std::thread::hardware_concurrency();
 
-    index_limits_t(std::size_t n, std::size_t t) noexcept : members(n), threads_add(t), threads_search(t) {}
-    index_limits_t(std::size_t n = 0) noexcept : index_limits_t(n, std::thread::hardware_concurrency()) {}
-    std::size_t threads() const noexcept { return (std::max)(threads_add, threads_search); }
-    std::size_t concurrency() const noexcept { return (std::min)(threads_add, threads_search); }
+    inline index_limits_t(std::size_t n, std::size_t t) noexcept : members(n), threads_add(t), threads_search(t) {}
+    inline index_limits_t(std::size_t n = 0) noexcept : index_limits_t(n, std::thread::hardware_concurrency()) {}
+    inline std::size_t threads() const noexcept { return (std::max)(threads_add, threads_search); }
+    inline std::size_t concurrency() const noexcept { return (std::min)(threads_add, threads_search); }
 };
 
-struct add_config_t {
+struct index_update_config_t {
     /// @brief Hyper-parameter controlling the quality of indexing.
     /// Defaults to 40 in FAISS and 200 in hnswlib.
     /// > It is called `efConstruction` in the paper.
@@ -1248,12 +985,9 @@ struct add_config_t {
 
     /// @brief Optional thread identifier for multi-threaded construction.
     std::size_t thread = 0;
-
-    /// @brief Don't copy the ::vector, if it's persisted elsewhere.
-    bool store_vector = true;
 };
 
-struct search_config_t {
+struct index_search_config_t {
     /// @brief Hyper-parameter controlling the quality of search.
     /// Defaults to 16 in FAISS and 10 in hnswlib.
     /// > It is called `ef` in the paper.
@@ -1266,133 +1000,21 @@ struct search_config_t {
     bool exact = false;
 };
 
-struct copy_config_t {
-    bool copy_vectors = true;
-};
+struct index_copy_config_t {};
 
-struct join_config_t {
+struct index_join_config_t {
     /// @brief Controls maximum number of proposals per man during stable marriage.
     std::size_t max_proposals = 0;
+
     /// @brief Hyper-parameter controlling the quality of search.
     /// Defaults to 16 in FAISS and 10 in hnswlib.
     /// > It is called `ef` in the paper.
     std::size_t expansion = default_expansion_search();
+
     /// @brief Brute-forces exhaustive search over all entries in the index.
     bool exact = false;
 };
 
-using file_header_t = byte_t[64];
-
-/**
- *  @brief  Serialized binary representations of the USearch index start with metadata.
- *          Metadata is parsed into a `file_head_t`, containing the USearch package version,
- *          and the properties of the index.
- *
- *  It uses: 13 bytes for file versioning, 22 bytes for structural information = 35 bytes.
- *  The following 24 bytes contain binary size of the graph, of the vectors, and the checksum,
- *  leaving 5 bytes at the end vacant.
- */
-struct file_head_t {
-
-    // Versioning: 7 + 2 * 3 = 13 bytes
-    using magic_t = char[7];
-    using version_major_t = std::uint16_t;
-    using version_minor_t = std::uint16_t;
-    using version_patch_t = std::uint16_t;
-
-    // Structural: 1 * 6 + 8 * 2 = 22 bytes
-    using connectivity_t = std::uint8_t;
-    using max_level_t = std::uint8_t;
-    using vector_alignment_t = std::uint8_t;
-    using bytes_per_label_t = std::uint8_t;
-    using bytes_per_id_t = std::uint8_t;
-    using size_t = std::uint64_t;
-    using entry_idx_t = std::uint64_t;
-
-    // Versioning:
-    char const* magic;
-    misaligned_ref_gt<version_major_t> version_major;
-    misaligned_ref_gt<version_minor_t> version_minor;
-    misaligned_ref_gt<version_patch_t> version_patch;
-
-    // Structural:
-    misaligned_ref_gt<metric_kind_t> metric;
-    misaligned_ref_gt<connectivity_t> connectivity;
-    misaligned_ref_gt<max_level_t> max_level;
-    misaligned_ref_gt<vector_alignment_t> vector_alignment;
-    misaligned_ref_gt<bytes_per_label_t> bytes_per_label;
-    misaligned_ref_gt<bytes_per_id_t> bytes_per_id;
-    misaligned_ref_gt<scalar_kind_t> scalar_kind;
-    misaligned_ref_gt<size_t> size;
-    misaligned_ref_gt<entry_idx_t> entry_idx;
-
-    // Additional:
-    misaligned_ref_gt<size_t> bytes_for_graphs;
-    misaligned_ref_gt<size_t> bytes_for_vectors;
-    misaligned_ref_gt<size_t> bytes_checksum;
-
-    file_head_t(byte_t* ptr) noexcept
-        : magic((char const*)exchange(ptr, ptr + sizeof(magic_t))),
-          version_major(exchange(ptr, ptr + sizeof(version_major_t))),
-          version_minor(exchange(ptr, ptr + sizeof(version_minor_t))),
-          version_patch(exchange(ptr, ptr + sizeof(version_patch_t))),
-          metric(exchange(ptr, ptr + sizeof(metric_kind_t))), connectivity(exchange(ptr, ptr + sizeof(connectivity_t))),
-          max_level(exchange(ptr, ptr + sizeof(max_level_t))),
-          vector_alignment(exchange(ptr, ptr + sizeof(vector_alignment_t))),
-          bytes_per_label(exchange(ptr, ptr + sizeof(bytes_per_label_t))),
-          bytes_per_id(exchange(ptr, ptr + sizeof(bytes_per_id_t))),
-          scalar_kind(exchange(ptr, ptr + sizeof(scalar_kind_t))), size(exchange(ptr, ptr + sizeof(size_t))),
-          entry_idx(exchange(ptr, ptr + sizeof(entry_idx_t))), bytes_for_graphs(exchange(ptr, ptr + sizeof(size_t))),
-          bytes_for_vectors(exchange(ptr, ptr + sizeof(size_t))), bytes_checksum(exchange(ptr, ptr + sizeof(size_t))) {}
-};
-
-struct file_head_result_t {
-
-    using magic_t = file_head_t::magic_t;
-    using version_major_t = file_head_t::version_major_t;
-    using version_minor_t = file_head_t::version_minor_t;
-    using version_patch_t = file_head_t::version_patch_t;
-
-    using connectivity_t = file_head_t::connectivity_t;
-    using max_level_t = file_head_t::max_level_t;
-    using vector_alignment_t = file_head_t::vector_alignment_t;
-    using bytes_per_label_t = file_head_t::bytes_per_label_t;
-    using bytes_per_id_t = file_head_t::bytes_per_id_t;
-    using size_t = file_head_t::size_t;
-    using entry_idx_t = file_head_t::entry_idx_t;
-
-    // Versioning:
-    version_major_t version_major;
-    version_minor_t version_minor;
-    version_patch_t version_patch;
-
-    // Structural:
-    metric_kind_t metric;
-    connectivity_t connectivity;
-    max_level_t max_level;
-    vector_alignment_t vector_alignment;
-    bytes_per_label_t bytes_per_label;
-    bytes_per_id_t bytes_per_id;
-    scalar_kind_t scalar_kind;
-    size_t size;
-    entry_idx_t entry_idx;
-
-    // Additional:
-    size_t bytes_for_graphs;
-    size_t bytes_for_vectors;
-    size_t bytes_checksum;
-
-    error_t error;
-
-    explicit operator bool() const noexcept { return !error; }
-    file_head_result_t failed(error_t message) noexcept {
-        error = std::move(message);
-        return std::move(*this);
-    }
-};
-
-static_assert(sizeof(file_header_t) == 64, "File header should be exactly 64 bytes");
-
 /// @brief  C++17 and newer version deprecate the `std::result_of`
 template <typename metric_at, typename... args_at>
 using return_type_gt =
@@ -1402,32 +1024,65 @@ using return_type_gt =
     typename std::result_of<metric_at(args_at...)>::type;
 #endif
 
-/// @brief  OS-specific to wrap open file-descriptors/handles.
-#if defined(USEARCH_DEFINED_WINDOWS)
-struct viewed_file_t {
-    HANDLE file_handle{};
-    HANDLE mapping_handle{};
-    void* ptr{};
-    size_t length{};
-    explicit operator bool() const noexcept { return mapping_handle != nullptr; }
-};
-#else
-struct viewed_file_t {
-    int file_descriptor{};
-    void* ptr{};
-    size_t length{};
-    explicit operator bool() const noexcept { return file_descriptor != 0; }
+/**
+ *  @brief  An example of what a USearch-compatible ad-hoc filter would look like.
+ *
+ *  A similar function object can be passed to search queries to further filter entries
+ *  on their auxiliary properties, such as some categorical labels stored in an external DBMS.
+ */
+struct dummy_predicate_t {
+    template <typename member_at> constexpr bool operator()(member_at&&) const noexcept { return true; }
 };
-#endif
 
-struct dummy_predicate_t {
-    template <typename match_at> constexpr bool operator()(match_at&&) const noexcept { return true; }
+/**
+ *  @brief  An example of what a USearch-compatible ad-hoc operation on in-flight entries.
+ *
+ *  This kind of callbacks is used when the engine is being updated and you want to patch
+ *  the entries, while their are still under locks - limiting concurrent access and providing
+ *  consistency.
+ */
+struct dummy_callback_t {
+    template <typename member_at> void operator()(member_at&&) const noexcept {}
 };
 
+/**
+ *  @brief  An example of what a USearch-compatible progress-bar should look like.
+ *
+ *  This is particularly helpful when handling long-running tasks, like serialization,
+ *  saving, and loading from disk, or index-level joins.
+ */
 struct dummy_progress_t {
     inline void operator()(std::size_t /*progress*/, std::size_t /*total*/) const noexcept {}
 };
 
+/**
+ *  @brief  An example of what a USearch-compatible values prefetching mechanism should look like.
+ *
+ *  USearch is designed to handle very large datasets, that may not fir into RAM. Fetching from
+ *  external memory is very expensive, so we've added a pre-fetching mechanism, that accepts
+ *  multiple objects at once, to cache in RAM ahead of the computation.
+ *  The received iterators support both `get_slot` and `get_key` operations.
+ *  An example usage may look like this:
+ *
+ *      template <typename member_citerator_like_at>
+ *      inline void operator()(member_citerator_like_at, member_citerator_like_at) const noexcept {
+ *          for (; begin != end; ++begin)
+ *              io_uring_prefetch(offset_in_file(get_key(begin)));
+ *      }
+ */
+struct dummy_prefetch_t {
+    template <typename member_citerator_like_at>
+    inline void operator()(member_citerator_like_at, member_citerator_like_at) const noexcept {}
+};
+
+/**
+ *  @brief  An example of what a USearch-compatible executor (thread-pool) should look like.
+ *
+ *  It's expected to have `execute_bulk(callback)` API to schedule one task per thread;
+ *  an identical `execute_bulk(count, callback)` overload that also accepts the number
+ *  of tasks, and somehow schedules them between threads; as well as `size()` to
+ *  determine the number of available threads.
+ */
 struct dummy_executor_t {
     dummy_executor_t() noexcept {}
     std::size_t size() const noexcept { return 1; }
@@ -1444,13 +1099,34 @@ struct dummy_executor_t {
     }
 };
 
+/**
+ *  @brief  An example of what a USearch-compatible label-to-label mapping should look like.
+ *
+ *  This is particularly helpful for "Semantic Joins", where we map entries of one collection
+ *  to entries of another. In assymetric setups, where A -> B is needed, but B -> A is not,
+ *  this can be passed to minimize memory usage.
+ */
 struct dummy_label_to_label_mapping_t {
     struct member_ref_t {
-        template <typename label_at> member_ref_t& operator=(label_at&&) noexcept { return *this; }
+        template <typename key_at> member_ref_t& operator=(key_at&&) noexcept { return *this; }
     };
-    template <typename label_at> member_ref_t operator[](label_at&&) const noexcept { return {}; }
+    template <typename key_at> member_ref_t operator[](key_at&&) const noexcept { return {}; }
 };
 
+/**
+ *  @brief  Checks if the provided object has a dummy type, emulating an interface,
+ *          but performaing no real computation.
+ */
+template <typename object_at> static constexpr bool is_dummy() {
+    using object_t = typename std::remove_all_extents<object_at>::type;
+    return std::is_same<object_t, dummy_predicate_t>::value || //
+           std::is_same<object_t, dummy_callback_t>::value ||  //
+           std::is_same<object_t, dummy_progress_t>::value ||  //
+           std::is_same<object_t, dummy_prefetch_t>::value ||  //
+           std::is_same<object_t, dummy_executor_t>::value ||  //
+           std::is_same<object_t, dummy_label_to_label_mapping_t>::value;
+}
+
 template <typename, typename at> struct has_reset_gt {
     static_assert(std::integral_constant<at, false>::value, "Second template parameter needs to be of function type.");
 };
@@ -1474,116 +1150,388 @@ struct has_reset_gt<check_at, return_at(args_at...)> {
  */
 template <typename at> constexpr bool has_reset() { return has_reset_gt<at, void()>::value; }
 
+struct serialization_result_t {
+    error_t error;
+
+    explicit operator bool() const noexcept { return !error; }
+    serialization_result_t failed(error_t message) noexcept {
+        error = std::move(message);
+        return std::move(*this);
+    }
+};
+
 /**
- *  @brief  Approximate Nearest Neighbors Search index using the
- *          Hierarchical Navigable Small World @b (HNSW) graphs algorithm.
- *
- *  @section Features
- *      - Thread-safe for concurrent construction.
- *      - Doesn't allocate new threads, and reuses the ones its called from.
- *      - Search for vectors of different dimensionality, if ::`metric_at` supports that.
- *
- *  @tparam metric_at
- *      A function responsible for computing the distance (dis-similarity) between two vectors.
- *      Can have following signatures:
- *          - `distance_t (*) (span_gt<scalar_t const>, span_gt<scalar_t const>)`
- *          - `distance_t (*) (scalar_t const *, scalar_t const *)`
- *
- *  @tparam label_at
- *      The type of unique labels to assign to vectors.
- *
- *  @tparam id_at
- *      The smallest unsigned integer type to address indexed elements.
- *      Can be a built-in `uint32_t`, `uint64_t`, or our custom `uint40_t`.
- *
- *  @tparam dynamic_allocator_at
- *      Dynamic memory allocator for temporary buffers, visits indicators, and
- *      priority queues, needed during construction and traversals of graphs.
- *      The allocated buffers may be uninitialized.
- *
- *  @tparam tape_allocator_at
- *      Potentially different memory allocator for primary allocations of nodes and vectors.
- *      It would never `deallocate` separate entries, and would only free all the space at once.
- *      The allocated buffers may be uninitialized.
- *
- *  @section Usage
- *
- *  @subsection Exceptions
- *
- *  None of the methods throw exceptions in the "Release" compilation mode.
- *  It may only `throw` if your memory ::dynamic_allocator_at or ::metric_at isn't
- *  safe to copy.
- *
- *  @section Implementation Details
- *
- *  Like every HNSW implementation, USearch builds levels of "Proximity Graphs".
- *  Every added vector forms a node in one or more levels of the graph.
- *  Every node is present in the base level. Every following level contains a smaller
- *  fraction of nodes. During search, the operation starts with the smaller levels
- *  and zooms-in on every following iteration of larger graph traversals.
- *
- *  Just one memory allocation is performed regardless of the number of levels.
- *  The adjacency lists across all levels are concatenated into that single buffer.
- *  That buffer starts with a "head", that stores the metadata, such as the
- *  tallest "level" of the graph that it belongs to, the external "label", and the
- *  number of "dimensions" in the vector.
- *
- *  @subsection Colocated Nodes
- *
- *  Every node contains some graph-related data, as well as the original vector.
- *  Assuming the vectors can get large, we allow separating the index from the vectors.
- *  They can either be stored in a single continuous block of memory, or in two separate
- *  locations. Vector storage can also be detached from `index_gt` and managed by the user.
- *  To properly serialize and deserialize, use the right `save()`, `load()`,  and `view()`
- *  overloads.
- *
- *  @subsection Missing Functionality
- *
- *  To simplify the implementation, the `index_gt` lacks endpoints to remove existing
- *  vectors. That, however, is solved by `index_punned_dense_gt`, which also adds automatic casting.
+ *  @brief Smart-pointer wrapping the LibC @b `FILE` for binary file @b outputs.
  *
+ * This class raises no exceptions and corresponds errors through `serialization_result_t`.
+ * The class automatically closes the file when the object is destroyed.
  */
-template <typename metric_at = ip_gt<float>,                    //
-          typename label_at = std::int64_t,                     //
-          typename id_at = std::uint32_t,                       //
-          typename dynamic_allocator_at = std::allocator<char>, //
-          typename tape_allocator_at = dynamic_allocator_at>    //
-class index_gt {
-  public:
-    using metric_t = metric_at;
-    using label_t = label_at;
-    using id_t = id_at;
-    using dynamic_allocator_t = dynamic_allocator_at;
-    using tape_allocator_t = tape_allocator_at;
-    static_assert(sizeof(label_t) >= sizeof(id_t), "Having tiny labels doesn't make sense.");
+class output_file_t {
+    char const* path_ = nullptr;
+    std::FILE* file_ = nullptr;
 
-    using scalar_t = typename metric_t::scalar_t;
-    using vector_view_t = span_gt<scalar_t const>;
-    using distance_t = return_type_gt<metric_t, vector_view_t, vector_view_t>;
+  public:
+    output_file_t(char const* path) noexcept : path_(path) {}
+    ~output_file_t() noexcept { close(); }
+    output_file_t(output_file_t&& other) noexcept
+        : path_(exchange(other.path_, nullptr)), file_(exchange(other.file_, nullptr)) {}
+    output_file_t& operator=(output_file_t&& other) noexcept {
+        std::swap(path_, other.path_);
+        std::swap(file_, other.file_);
+        return *this;
+    }
+    serialization_result_t open_if_not() noexcept {
+        serialization_result_t result;
+        if (!file_)
+            file_ = std::fopen(path_, "wb");
+        if (!file_)
+            return result.failed(std::strerror(errno));
+        return result;
+    }
+    serialization_result_t write(void* begin, std::size_t length) noexcept {
+        serialization_result_t result;
+        std::size_t written = std::fwrite(begin, length, 1, file_);
+        if (!written)
+            result.failed(std::strerror(errno));
+        return result;
+    }
+    void close() noexcept {
+        if (file_)
+            std::fclose(exchange(file_, nullptr));
+    }
+};
 
-    struct member_cref_t {
-        label_t label;
-        vector_view_t vector;
-        id_t id;
-    };
+/**
+ *  @brief  Smart-pointer wrapping the LibC @b `FILE` for binary files @b inputs.
+ *
+ * This class raises no exceptions and corresponds errors through `serialization_result_t`.
+ * The class automatically closes the file when the object is destroyed.
+ */
+class input_file_t {
+    char const* path_ = nullptr;
+    std::FILE* file_ = nullptr;
 
-    struct member_ref_t {
-        misaligned_ref_gt<label_t> label;
-        vector_view_t vector;
-        id_t id;
+  public:
+    input_file_t(char const* path) noexcept : path_(path) {}
+    ~input_file_t() noexcept { close(); }
+    input_file_t(input_file_t&& other) noexcept
+        : path_(exchange(other.path_, nullptr)), file_(exchange(other.file_, nullptr)) {}
+    input_file_t& operator=(input_file_t&& other) noexcept {
+        std::swap(path_, other.path_);
+        std::swap(file_, other.file_);
+        return *this;
+    }
 
-        inline operator member_cref_t() const noexcept { return {label, vector, id}; }
-    };
+    serialization_result_t open_if_not() noexcept {
+        serialization_result_t result;
+        if (!file_)
+            file_ = std::fopen(path_, "rb");
+        if (!file_)
+            return result.failed(std::strerror(errno));
+        return result;
+    }
+    serialization_result_t read(void* begin, std::size_t length) noexcept {
+        serialization_result_t result;
+        std::size_t read = std::fread(begin, length, 1, file_);
+        if (!read)
+            result.failed(std::feof(file_) ? "End of file reached!" : std::strerror(errno));
+        return result;
+    }
+    void close() noexcept {
+        if (file_)
+            std::fclose(exchange(file_, nullptr));
+    }
+
+    explicit operator bool() const noexcept { return file_; }
+    bool seek_to(std::size_t progress) noexcept { return std::fseek(file_, progress, SEEK_SET) == 0; }
+    bool seek_to_end() noexcept { return std::fseek(file_, 0L, SEEK_END) == 0; }
+    bool infer_progress(std::size_t& progress) noexcept {
+        long int result = std::ftell(file_);
+        if (result == -1L)
+            return false;
+        progress = static_cast<std::size_t>(result);
+        return true;
+    }
+};
+
+/**
+ *  @brief  Represents a memory-mapped file or a pre-allocated anonymous memory region.
+ *
+ *  This class provides a convenient way to memory-map a file and access its contents as a block of
+ *  memory. The class handles platform-specific memory-mapping operations on Windows, Linux, and MacOS.
+ *  The class automatically closes the file when the object is destroyed.
+ */
+class memory_mapped_file_t {
+    char const* path_{}; /**< The path to the file to be memory-mapped. */
+    void* ptr_{};        /**< A pointer to the memory-mapping. */
+    size_t length_{};    /**< The length of the memory-mapped file in bytes. */
+
+#if defined(USEARCH_DEFINED_WINDOWS)
+    HANDLE file_handle_{};    /**< The file handle on Windows. */
+    HANDLE mapping_handle_{}; /**< The mapping handle on Windows. */
+#else
+    int file_descriptor_{}; /**< The file descriptor on Linux and MacOS. */
+#endif
+
+  public:
+    explicit operator bool() const noexcept { return ptr_ != nullptr; }
+    byte_t const* data() const noexcept { return reinterpret_cast<byte_t const*>(ptr_); }
+    std::size_t size() const noexcept { return static_cast<std::size_t>(length_); }
+
+    memory_mapped_file_t() noexcept {}
+    memory_mapped_file_t(char const* path) noexcept : path_(path) {}
+    ~memory_mapped_file_t() noexcept { close(); }
+    memory_mapped_file_t(memory_mapped_file_t&& other) noexcept
+        : path_(exchange(other.path_, nullptr)), ptr_(exchange(other.ptr_, nullptr)),
+          length_(exchange(other.length_, 0)),
+#if defined(USEARCH_DEFINED_WINDOWS)
+          file_handle_(exchange(other.file_handle_, nullptr)), mapping_handle_(exchange(other.mapping_handle_, nullptr))
+#else
+          file_descriptor_(exchange(other.file_descriptor_, 0))
+#endif
+    {
+    }
+
+    memory_mapped_file_t(byte_t* data, std::size_t length) noexcept : ptr_(data), length_(length) {}
+
+    memory_mapped_file_t& operator=(memory_mapped_file_t&& other) noexcept {
+        std::swap(path_, other.path_);
+        std::swap(ptr_, other.ptr_);
+        std::swap(length_, other.length_);
+#if defined(USEARCH_DEFINED_WINDOWS)
+        std::swap(file_handle_, other.file_handle_);
+        std::swap(mapping_handle_, other.mapping_handle_);
+#else
+        std::swap(file_descriptor_, other.file_descriptor_);
+#endif
+        return *this;
+    }
+
+    serialization_result_t open_if_not() noexcept {
+        serialization_result_t result;
+        if (!path_ || ptr_)
+            return result;
+
+#if defined(USEARCH_DEFINED_WINDOWS)
+
+        HANDLE file_handle =
+            CreateFile(path_, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+        if (file_handle == INVALID_HANDLE_VALUE)
+            return result.failed("Opening file failed!");
+
+        std::size_t file_length = GetFileSize(file_handle, 0);
+        HANDLE mapping_handle = CreateFileMapping(file_handle, 0, PAGE_READONLY, 0, 0, 0);
+        if (mapping_handle == 0) {
+            CloseHandle(file_handle);
+            return result.failed("Mapping file failed!");
+        }
+
+        byte_t* file = (byte_t*)MapViewOfFile(mapping_handle, FILE_MAP_READ, 0, 0, file_length);
+        if (file == 0) {
+            CloseHandle(mapping_handle);
+            CloseHandle(file_handle);
+            return result.failed("View the map failed!");
+        }
+        file_handle_ = file_handle;
+        mapping_handle_ = mapping_handle;
+        ptr_ = file;
+        length_ = file_length;
+#else
+
+#if defined(USEARCH_DEFINED_LINUX)
+        int descriptor = open(path_, O_RDONLY | O_NOATIME);
+#else
+        int descriptor = open(path_, O_RDONLY);
+#endif
+
+        // Estimate the file size
+        struct stat file_stat;
+        int fstat_status = fstat(descriptor, &file_stat);
+        if (fstat_status < 0) {
+            ::close(descriptor);
+            return result.failed(std::strerror(errno));
+        }
+
+        // Map the entire file
+        byte_t* file = (byte_t*)mmap(NULL, file_stat.st_size, PROT_READ, MAP_SHARED, descriptor, 0);
+        if (file == MAP_FAILED) {
+            ::close(descriptor);
+            return result.failed(std::strerror(errno));
+        }
+        file_descriptor_ = descriptor;
+        ptr_ = file;
+        length_ = file_stat.st_size;
+#endif // Platform specific code
+        return result;
+    }
+
+    void close() noexcept {
+        if (!path_) {
+            ptr_ = nullptr;
+            length_ = 0;
+            return;
+        }
+#if defined(USEARCH_DEFINED_WINDOWS)
+        UnmapViewOfFile(ptr_);
+        CloseHandle(mapping_handle_);
+        CloseHandle(file_handle_);
+        mapping_handle_ = nullptr;
+        file_handle_ = nullptr;
+#else
+        munmap(ptr_, length_);
+        ::close(file_descriptor_);
+        file_descriptor_ = 0;
+#endif
+        ptr_ = nullptr;
+        length_ = 0;
+    }
+};
+
+struct index_serialized_header_t {
+    std::uint64_t size = 0;
+    std::uint64_t connectivity = 0;
+    std::uint64_t connectivity_base = 0;
+    std::uint64_t max_level = 0;
+    std::uint64_t entry_slot = 0;
+};
+
+using default_key_t = std::uint64_t;
+using default_slot_t = std::uint32_t;
+using default_distance_t = float;
+
+template <typename key_at = default_key_t> struct member_gt {
+    key_at key;
+    std::size_t slot;
+};
+
+template <typename key_at> inline std::size_t get_slot(member_gt<key_at> const& m) noexcept { return m.slot; }
+template <typename key_at> inline key_at get_key(member_gt<key_at> const& m) noexcept { return m.key; }
+
+template <typename key_at = default_key_t> struct member_cref_gt {
+    misaligned_ref_gt<key_at const> key;
+    std::size_t slot;
+};
+
+template <typename key_at> inline std::size_t get_slot(member_cref_gt<key_at> const& m) noexcept { return m.slot; }
+template <typename key_at> inline key_at get_key(member_cref_gt<key_at> const& m) noexcept { return m.key; }
+
+template <typename key_at = default_key_t> struct member_ref_gt {
+    misaligned_ref_gt<key_at> key;
+    std::size_t slot;
+
+    inline operator member_cref_gt<key_at>() const noexcept { return {key.ptr(), slot}; }
+};
+
+template <typename key_at> inline std::size_t get_slot(member_ref_gt<key_at> const& m) noexcept { return m.slot; }
+template <typename key_at> inline key_at get_key(member_ref_gt<key_at> const& m) noexcept { return m.key; }
+
+/**
+ *  @brief  Approximate Nearest Neighbors Search @b index-structure using the
+ *          Hierarchical Navigable Small World @b (HNSW) graphs algorithm.
+ *          If classical containers store @b Key->Value mappings, this one can
+ *          be seen as a network of keys, accelerating approximate @b Value~>Key visited_members.
+ *
+ *  Unlike most implementations, this one is generic anc can be used for any search,
+ *  not just within equi-dimensional vectors. Examples range from texts to similar Chess
+ *  positions.
+ *
+ *  @tparam key_at
+ *      The type of primary objects stored in the index.
+ *      The values, to which those map, are not managed by the same index structure.
+ *
+ *  @tparam compressed_slot_at
+ *      The smallest unsigned integer type to address indexed elements.
+ *      It is used internally to maximize space-efficiency and is generally
+ *      up-casted to @b `std::size_t` in public interfaces.
+ *      Can be a built-in @b `uint32_t`, `uint64_t`, or our custom @b `uint40_t`.
+ *      Which makes the most sense for 4B+ entry indexes.
+ *
+ *  @tparam dynamic_allocator_at
+ *      Dynamic memory allocator for temporary buffers, visits indicators, and
+ *      priority queues, needed during construction and traversals of graphs.
+ *      The allocated buffers may be uninitialized.
+ *
+ *  @tparam tape_allocator_at
+ *      Potentially different memory allocator for primary allocations of nodes and vectors.
+ *      It would never `deallocate` separate entries, and would only free all the space at once.
+ *      The allocated buffers may be uninitialized.
+ *
+ *  @section Features
+ *
+ *      - Thread-safe for concurrent construction, search, and updates.
+ *      - Doesn't allocate new threads, and reuses the ones its called from.
+ *      - Allows storing value externally, managing just the similarity index.
+ *      - Joins.
+
+ *  @section Usage
+ *
+ *  @subsection Exceptions
+ *
+ *  None of the methods throw exceptions in the "Release" compilation mode.
+ *  It may only `throw` if your memory ::dynamic_allocator_at or ::metric_at isn't
+ *  safe to copy.
+ *
+ *  @subsection Serialization
+ *
+ *  When serialized, doesn't include any additional metadata.
+ *  It is just the multi-level proximity-graph. You may want to store metadata about
+ *  the used metric and key types somewhere else.
+ *
+ *  @section Implementation Details
+ *
+ *  Like every HNSW implementation, USearch builds levels of "Proximity Graphs".
+ *  Every added vector forms a node in one or more levels of the graph.
+ *  Every node is present in the base level. Every following level contains a smaller
+ *  fraction of nodes. During search, the operation starts with the smaller levels
+ *  and zooms-in on every following iteration of larger graph traversals.
+ *
+ *  Just one memory allocation is performed regardless of the number of levels.
+ *  The adjacency lists across all levels are concatenated into that single buffer.
+ *  That buffer starts with a "head", that stores the metadata, such as the
+ *  tallest "level" of the graph that it belongs to, the external "key", and the
+ *  number of "dimensions" in the vector.
+ *
+ *  @section Metrics, Predicates and Callbacks
+ *
+ *
+ *  @section Smart References and Iterators
+ *
+ *      -   `member_citerator_t` and `member_iterator_t` have only slots, no indirections.
+ *
+ *      -   `member_cref_t` and `member_ref_t` contains the `slot` and a reference
+ *          to the key. So it passes through 1 level of visited_members in `nodes_`.
+ *          Retrieving the key via `get_key` will cause fetching yet another cache line.
+ *
+ *      -   `member_gt` contains an already prefetched copy of the key.
+ *
+ */
+template <typename distance_at = default_distance_t,              //
+          typename key_at = default_key_t,                        //
+          typename compressed_slot_at = default_slot_t,           //
+          typename dynamic_allocator_at = std::allocator<byte_t>, //
+          typename tape_allocator_at = dynamic_allocator_at>      //
+class index_gt {
+  public:
+    using distance_t = distance_at;
+    using key_t = key_at;
+    using compressed_slot_t = compressed_slot_at;
+    using dynamic_allocator_t = dynamic_allocator_at;
+    using tape_allocator_t = tape_allocator_at;
+    static_assert(sizeof(key_t) >= sizeof(compressed_slot_t), "Having tiny keys doesn't make sense.");
+
+    using member_cref_t = member_cref_gt<key_t>;
+    using member_ref_t = member_ref_gt<key_t>;
 
     template <typename ref_at, typename index_at> class member_iterator_gt {
         using ref_t = ref_at;
         using index_t = index_at;
-        index_t* index_{};
-        std::size_t offset_{};
 
         friend class index_gt;
         member_iterator_gt() noexcept {}
-        member_iterator_gt(index_t* index, std::size_t offset) noexcept : index_(index), offset_(offset) {}
+        member_iterator_gt(index_t* index, std::size_t slot) noexcept : index_(index), slot_(slot) {}
+
+        index_t* index_{};
+        std::size_t slot_{};
 
       public:
         using iterator_category = std::random_access_iterator_tag;
@@ -1592,45 +1540,32 @@ class index_gt {
         using pointer = void;
         using reference = ref_t;
 
-        reference operator*() const noexcept {
-            node_t node = index_->node_with_id_(offset_);
-            return {node.label(), node.vector_view(), static_cast<id_t>(offset_)};
-        }
-
-        member_iterator_gt operator++(int) noexcept { return member_iterator_gt(index_, offset_ + 1); }
-        member_iterator_gt operator--(int) noexcept { return member_iterator_gt(index_, offset_ - 1); }
-        member_iterator_gt operator+(difference_type d) noexcept { return member_iterator_gt(index_, offset_ + d); }
-        member_iterator_gt operator-(difference_type d) noexcept { return member_iterator_gt(index_, offset_ - d); }
-
-        member_iterator_gt& operator++() noexcept {
-            offset_ += 1;
-            return *this;
-        }
-        member_iterator_gt& operator--() noexcept {
-            offset_ -= 1;
-            return *this;
-        }
-        member_iterator_gt& operator+=(difference_type d) noexcept {
-            offset_ += d;
-            return *this;
-        }
-        member_iterator_gt& operator-=(difference_type d) noexcept {
-            offset_ -= d;
-            return *this;
-        }
-        bool operator==(member_iterator_gt const& other) const noexcept {
-            return index_ == other.index_ && offset_ == other.offset_;
-        }
-        bool operator!=(member_iterator_gt const& other) const noexcept {
-            return index_ != other.index_ || offset_ != other.offset_;
-        }
+        reference operator*() const noexcept { return {index_->node_at_(slot_).key(), slot_}; }
+        key_t key() const noexcept { return index_->node_at_(slot_).key(); }
+
+        friend inline std::size_t get_slot(member_iterator_gt const& it) noexcept { return it.slot_; }
+        friend inline key_t get_key(member_iterator_gt const& it) noexcept { return it.key(); }
+
+        member_iterator_gt operator++(int) noexcept { return member_iterator_gt(index_, slot_ + 1); }
+        member_iterator_gt operator--(int) noexcept { return member_iterator_gt(index_, slot_ - 1); }
+        member_iterator_gt operator+(difference_type d) noexcept { return member_iterator_gt(index_, slot_ + d); }
+        member_iterator_gt operator-(difference_type d) noexcept { return member_iterator_gt(index_, slot_ - d); }
+
+        // clang-format off
+        member_iterator_gt& operator++() noexcept { slot_ += 1; return *this; }
+        member_iterator_gt& operator--() noexcept { slot_ -= 1; return *this; }
+        member_iterator_gt& operator+=(difference_type d) noexcept { slot_ += d; return *this; }
+        member_iterator_gt& operator-=(difference_type d) noexcept { slot_ -= d; return *this; }
+        bool operator==(member_iterator_gt const& other) const noexcept { return index_ == other.index_ && slot_ == other.slot_; }
+        bool operator!=(member_iterator_gt const& other) const noexcept { return index_ != other.index_ || slot_ != other.slot_; }
+        // clang-format on
     };
 
     using member_iterator_t = member_iterator_gt<member_ref_t, index_gt>;
     using member_citerator_t = member_iterator_gt<member_cref_t, index_gt const>;
 
     // STL compatibility:
-    using value_type = std::pair<label_t, distance_t>;
+    using value_type = key_t;
     using allocator_type = dynamic_allocator_t;
     using size_type = std::size_t;
     using difference_type = std::ptrdiff_t;
@@ -1643,108 +1578,113 @@ class index_gt {
     using reverse_iterator = std::reverse_iterator<member_iterator_t>;
     using reverse_const_iterator = std::reverse_iterator<member_citerator_t>;
 
-  private:
-    using neighbors_count_t = std::uint32_t;
-    using dim_t = std::uint32_t;
-    using level_t = std::int32_t;
-
-    using allocator_traits_t = std::allocator_traits<dynamic_allocator_t>;
+    using dynamic_allocator_traits_t = std::allocator_traits<dynamic_allocator_t>;
     using byte_t = typename dynamic_allocator_t::value_type;
-    static_assert(sizeof(byte_t) == 1, //
-                  "Primary allocator must allocate separate addressable bytes");
+    static_assert(           //
+        sizeof(byte_t) == 1, //
+        "Primary allocator must allocate separate addressable bytes");
 
     using tape_allocator_traits_t = std::allocator_traits<tape_allocator_t>;
-    static_assert(sizeof(typename tape_allocator_traits_t::value_type) == 1, //
-                  "Tape allocator must allocate separate addressable bytes");
+    static_assert(                                                 //
+        sizeof(typename tape_allocator_traits_t::value_type) == 1, //
+        "Tape allocator must allocate separate addressable bytes");
 
+  private:
     /**
-     *  @brief  How much larger (number of neighbors per node) will
-     *          the base level be compared to other levels.
+     *  @brief  Integer for the number of node neighbors at a specific level of the
+     *          multi-level graph. It's selected to be `std::uint32_t` to improve the
+     *          alignment in most common cases.
      */
-    static constexpr std::size_t base_level_multiple_() { return 2; }
+    using neighbors_count_t = std::uint32_t;
+    using level_t = std::int16_t;
 
     /**
      *  @brief  How many bytes of memory are needed to form the "head" of the node.
      */
-    static constexpr std::size_t node_head_bytes_() { return sizeof(label_t) + sizeof(dim_t) + sizeof(level_t); }
+    static constexpr std::size_t node_head_bytes_() { return sizeof(key_t) + sizeof(level_t); }
 
     using visits_bitset_t = visits_bitset_gt<dynamic_allocator_t>;
 
     struct precomputed_constants_t {
         double inverse_log_connectivity{};
-        std::size_t connectivity_max_base{};
         std::size_t neighbors_bytes{};
         std::size_t neighbors_base_bytes{};
     };
+    /// @brief A space-efficient internal data-structure used in graph traversal queues.
     struct candidate_t {
         distance_t distance;
-        id_t id;
-    };
-    struct compare_by_distance_t {
-        inline bool operator()(candidate_t a, candidate_t b) const noexcept { return a.distance < b.distance; }
+        compressed_slot_t slot;
+        inline bool operator<(candidate_t other) const noexcept { return distance < other.distance; }
     };
 
     using candidates_view_t = span_gt<candidate_t const>;
-    using candidates_allocator_t = typename allocator_traits_t::template rebind_alloc<candidate_t>;
-    using top_candidates_t = sorted_buffer_gt<candidate_t, compare_by_distance_t, candidates_allocator_t>;
-    using next_candidates_t = max_heap_gt<candidate_t, compare_by_distance_t, candidates_allocator_t>;
+    using candidates_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<candidate_t>;
+    using top_candidates_t = sorted_buffer_gt<candidate_t, std::less<candidate_t>, candidates_allocator_t>;
+    using next_candidates_t = max_heap_gt<candidate_t, std::less<candidate_t>, candidates_allocator_t>;
 
     /**
-     *  @brief  A loosely-structured handle for every node. One such node is created for every vector.
+     *  @brief  A loosely-structured handle for every node. One such node is created for every member.
      *          To minimize memory usage and maximize the number of entries per cache-line, it only
-     *          stores to pointers. To reinterpret those into a structured `node_t` more
-     *          information is needed from the parent `index_gt`.
+     *          stores to pointers. The internal tape starts with a `key_t` @b key, then
+     *          a `level_t` for the number of graph @b levels in which this member appears,
+     *          then the { `neighbors_count_t`, `compressed_slot_t`, `compressed_slot_t` ... } sequences
+     *          for @b each-level.
      */
     class node_t {
         byte_t* tape_{};
-        scalar_t* vector_{};
 
       public:
-        explicit node_t(byte_t* tape, scalar_t* vector) noexcept : tape_(tape), vector_(vector) {}
+        explicit node_t(byte_t* tape) noexcept : tape_(tape) {}
         byte_t* tape() const noexcept { return tape_; }
-        scalar_t* vector() const noexcept { return vector_; }
         byte_t* neighbors_tape() const noexcept { return tape_ + node_head_bytes_(); }
+        explicit operator bool() const noexcept { return tape_; }
 
         node_t() = default;
         node_t(node_t const&) = default;
         node_t& operator=(node_t const&) = default;
 
-        misaligned_ref_gt<label_t> label() const noexcept { return {tape_}; }
-        misaligned_ref_gt<dim_t> dim() const noexcept { return {tape_ + sizeof(label_t)}; }
-        misaligned_ref_gt<level_t> level() const noexcept { return {tape_ + sizeof(label_t) + sizeof(dim_t)}; }
+        misaligned_ref_gt<key_t const> ckey() const noexcept { return {tape_}; }
+        misaligned_ref_gt<key_t> key() const noexcept { return {tape_}; }
+        misaligned_ref_gt<level_t> level() const noexcept { return {tape_ + sizeof(key_t)}; }
 
-        void label(label_t v) noexcept { return misaligned_store<label_t>(tape_, v); }
-        void dim(dim_t v) noexcept { return misaligned_store<dim_t>(tape_ + sizeof(label_t), v); }
-        void level(level_t v) noexcept { return misaligned_store<level_t>(tape_ + sizeof(label_t) + sizeof(dim_t), v); }
-
-        operator vector_view_t() const noexcept { return {vector(), dim()}; }
-        vector_view_t vector_view() const noexcept { return {vector(), dim()}; }
-        explicit operator bool() const noexcept { return tape_; }
+        void key(key_t v) noexcept { return misaligned_store<key_t>(tape_, v); }
+        void level(level_t v) noexcept { return misaligned_store<level_t>(tape_ + sizeof(key_t), v); }
     };
 
+    static_assert(std::is_trivially_copy_constructible<node_t>::value, "Nodes must be light!");
+    static_assert(std::is_trivially_destructible<node_t>::value, "Nodes must be light!");
+
     /**
      *  @brief  A slice of the node's tape, containing a the list of neighbors
      *          for a node in a single graph level. It's pre-allocated to fit
-     *          as many neighbors IDs, as may be needed at the target level,
+     *          as many neighbors "slots", as may be needed at the target level,
      *          and starts with a single integer `neighbors_count_t` counter.
      */
     class neighbors_ref_t {
         byte_t* tape_;
 
-        static constexpr std::size_t shift(std::size_t i = 0) { return sizeof(neighbors_count_t) + sizeof(id_t) * i; }
+        static constexpr std::size_t shift(std::size_t i = 0) {
+            return sizeof(neighbors_count_t) + sizeof(compressed_slot_t) * i;
+        }
 
       public:
         neighbors_ref_t(byte_t* tape) noexcept : tape_(tape) {}
-        misaligned_ptr_gt<id_t> begin() noexcept { return tape_ + shift(); }
-        misaligned_ptr_gt<id_t> end() noexcept { return begin() + size(); }
-        misaligned_ptr_gt<id_t const> begin() const noexcept { return tape_ + shift(); }
-        misaligned_ptr_gt<id_t const> end() const noexcept { return begin() + size(); }
-        id_t operator[](std::size_t i) const noexcept { return misaligned_load<id_t>(tape_ + shift(i)); }
+        misaligned_ptr_gt<compressed_slot_t> begin() noexcept { return tape_ + shift(); }
+        misaligned_ptr_gt<compressed_slot_t> end() noexcept { return begin() + size(); }
+        misaligned_ptr_gt<compressed_slot_t const> begin() const noexcept { return tape_ + shift(); }
+        misaligned_ptr_gt<compressed_slot_t const> end() const noexcept { return begin() + size(); }
+        compressed_slot_t operator[](std::size_t i) const noexcept {
+            return misaligned_load<compressed_slot_t>(tape_ + shift(i));
+        }
         std::size_t size() const noexcept { return misaligned_load<neighbors_count_t>(tape_); }
-        void clear() noexcept { misaligned_store<neighbors_count_t>(tape_, 0); }
-        void push_back(id_t id) noexcept {
+        void clear() noexcept {
+            neighbors_count_t n = misaligned_load<neighbors_count_t>(tape_);
+            std::memset(tape_, 0, shift(n));
+            // misaligned_store<neighbors_count_t>(tape_, 0);
+        }
+        void push_back(compressed_slot_t slot) noexcept {
             neighbors_count_t n = misaligned_load<neighbors_count_t>(tape_);
-            misaligned_store<id_t>(tape_ + shift(n), id);
+            misaligned_store<compressed_slot_t>(tape_ + shift(n), slot);
             misaligned_store<neighbors_count_t>(tape_, n + 1);
         }
     };
@@ -1759,44 +1699,72 @@ class index_gt {
         next_candidates_t next_candidates{};
         visits_bitset_t visits{};
         std::default_random_engine level_generator{};
-        metric_t metric{};
         std::size_t iteration_cycles{};
-        std::size_t measurements_count{};
+        std::size_t computed_distances_count{};
+
+        template <typename value_at, typename metric_at, typename entry_at> //
+        inline distance_t measure(value_at const& first, entry_at const& second, metric_at&& metric) noexcept {
+            static_assert( //
+                std::is_same<entry_at, member_cref_t>::value || std::is_same<entry_at, member_citerator_t>::value,
+                "Unexpected type");
+
+            computed_distances_count++;
+            return metric(first, second);
+        }
+
+        template <typename metric_at, typename entry_at> //
+        inline distance_t measure(entry_at const& first, entry_at const& second, metric_at&& metric) noexcept {
+            static_assert( //
+                std::is_same<entry_at, member_cref_t>::value || std::is_same<entry_at, member_citerator_t>::value,
+                "Unexpected type");
 
-        inline distance_t measure(vector_view_t a, vector_view_t b) noexcept {
-            measurements_count++;
-            return metric(a, b);
+            computed_distances_count++;
+            return metric(first, second);
         }
     };
 
     index_config_t config_{};
     index_limits_t limits_{};
-    metric_t metric_{};
+
     mutable dynamic_allocator_t dynamic_allocator_{};
     tape_allocator_t tape_allocator_{};
+
     precomputed_constants_t pre_{};
-    viewed_file_t viewed_file_{};
+    memory_mapped_file_t viewed_file_{};
 
-    usearch_align_m mutable std::atomic<std::size_t> capacity_{};
-    usearch_align_m mutable std::atomic<std::size_t> size_{};
+    /// @brief  Number of "slots" available for `node_t` objects. Equals to @b `limits_.members`.
+    usearch_align_m mutable std::atomic<std::size_t> nodes_capacity_{};
 
-    /// @brief  Controls access to `max_level_` and `entry_id_`.
+    /// @brief  Number of "slots" already storing non-null nodes.
+    usearch_align_m mutable std::atomic<std::size_t> nodes_count_{};
+
+    /// @brief  Controls access to `max_level_` and `entry_slot_`.
     ///         If any thread is updating those values, no other threads can `add()` or `search()`.
     std::mutex global_mutex_{};
+
+    /// @brief  The level of the top-most graph in the index. Grows as the logarithm of size, starts from zero.
     level_t max_level_{};
-    id_t entry_id_{};
 
-    using nodes_allocator_t = typename allocator_traits_t::template rebind_alloc<node_t>;
-    node_t* nodes_{};
+    /// @brief  The slot in which the only node of the top-level graph is stored.
+    std::size_t entry_slot_{};
+
+    using nodes_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<node_t>;
+
+    /// @brief  C-style array of `node_t` smart-pointers.
+    buffer_gt<node_t, nodes_allocator_t> nodes_{};
+
+    /// @brief  Mutex, that limits concurrent access to `nodes_`.
     mutable visits_bitset_t nodes_mutexes_{};
 
-    using contexts_allocator_t = typename allocator_traits_t::template rebind_alloc<context_t>;
-    context_t* contexts_{};
+    using contexts_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<context_t>;
+
+    /// @brief  Array of thread-specific buffers for temporary data.
+    mutable buffer_gt<context_t, contexts_allocator_t> contexts_{};
 
   public:
     std::size_t connectivity() const noexcept { return config_.connectivity; }
-    std::size_t capacity() const noexcept { return capacity_; }
-    std::size_t size() const noexcept { return size_; }
+    std::size_t capacity() const noexcept { return nodes_capacity_; }
+    std::size_t size() const noexcept { return nodes_count_; }
     std::size_t max_level() const noexcept { return static_cast<std::size_t>(max_level_); }
     index_config_t const& config() const noexcept { return config_; }
     index_limits_t const& limits() const noexcept { return limits_; }
@@ -1806,16 +1774,17 @@ class index_gt {
      *  @section Exceptions
      *      Doesn't throw, unless the ::metric's and ::allocators's throw on copy-construction.
      */
-    explicit index_gt(index_config_t config = {}, metric_t metric = {}, dynamic_allocator_t allocator = {},
-                      tape_allocator_t tape_allocator = {}) noexcept
-        : config_(config), limits_(0, 0), metric_(metric), dynamic_allocator_(std::move(allocator)),
-          tape_allocator_(std::move(tape_allocator)), pre_(precompute_(config)), size_(0u), max_level_(-1),
-          entry_id_(0u), nodes_(nullptr), nodes_mutexes_(), contexts_(nullptr) {}
+    explicit index_gt( //
+        index_config_t config = {}, dynamic_allocator_t dynamic_allocator = {},
+        tape_allocator_t tape_allocator = {}) noexcept
+        : config_(config), limits_(0, 0), dynamic_allocator_(std::move(dynamic_allocator)),
+          tape_allocator_(std::move(tape_allocator)), pre_(precompute_(config)), nodes_count_(0u), max_level_(-1),
+          entry_slot_(0u), nodes_(), nodes_mutexes_(), contexts_() {}
 
     /**
      *  @brief  Clones the structure with the same hyper-parameters, but without contents.
      */
-    index_gt fork() noexcept { return index_gt{config_, metric_, dynamic_allocator_}; }
+    index_gt fork() noexcept { return index_gt{config_, dynamic_allocator_, tape_allocator_}; }
 
     ~index_gt() noexcept { reset(); }
 
@@ -1837,21 +1806,21 @@ class index_gt {
         }
     };
 
-    copy_result_t copy(copy_config_t /*config*/ = {}) const noexcept {
+    copy_result_t copy(index_copy_config_t /*config*/ = {}) const noexcept {
         copy_result_t result;
         index_gt& other = result.index;
-        other = index_gt(config_, metric_, dynamic_allocator_, tape_allocator_);
+        other = index_gt(config_, dynamic_allocator_, tape_allocator_);
         if (!other.reserve(limits_))
             return result.failed("Failed to reserve the contexts");
 
         // Now all is left - is to allocate new `node_t` instances and populate
         // the `other.nodes_` array into it.
-        for (std::size_t i = 0; i != size_; ++i)
-            other.nodes_[i] = other.node_make_copy_(node_bytes_split_(nodes_[i]));
+        for (std::size_t i = 0; i != nodes_count_; ++i)
+            other.nodes_[i] = other.node_make_copy_(node_bytes_(nodes_[i]));
 
-        other.size_ = size_.load();
+        other.nodes_count_ = nodes_count_.load();
         other.max_level_ = max_level_;
-        other.entry_id_ = entry_id_;
+        other.entry_slot_ = entry_slot_;
         return result;
     }
 
@@ -1862,13 +1831,10 @@ class index_gt {
     member_iterator_t begin() noexcept { return {this, 0}; }
     member_iterator_t end() noexcept { return {this, size()}; }
 
-    member_ref_t at(std::size_t i) noexcept {
-        return {nodes_[i].label(), nodes_[i].vector_view(), static_cast<id_t>(i)};
-    }
-
-    member_cref_t at(std::size_t i) const noexcept {
-        return {nodes_[i].label(), nodes_[i].vector_view(), static_cast<id_t>(i)};
-    }
+    member_ref_t at(std::size_t slot) noexcept { return {nodes_[slot].key(), slot}; }
+    member_cref_t at(std::size_t slot) const noexcept { return {nodes_[slot].ckey(), slot}; }
+    member_iterator_t iterator_at(std::size_t slot) noexcept { return {this, slot}; }
+    member_citerator_t citerator_at(std::size_t slot) const noexcept { return {this, slot}; }
 
     dynamic_allocator_t const& dynamic_allocator() const noexcept { return dynamic_allocator_; }
     tape_allocator_t const& tape_allocator() const noexcept { return tape_allocator_; }
@@ -1876,40 +1842,40 @@ class index_gt {
 #pragma region Adjusting Configuration
 
     /**
-     *  @brief  Erases all the vectors from the index.
-     *          Will change `size()` to zero, but will keep the same `capacity()`.
-     *          Will keep the number of available threads/contexts the same as it was.
+     *  @brief Erases all the vectors from the index.
+     *
+     *  Will change `size()` to zero, but will keep the same `capacity()`.
+     *  Will keep the number of available threads/contexts the same as it was.
      */
     void clear() noexcept {
         if (!has_reset<tape_allocator_t>()) {
-            std::size_t n = size_;
+            std::size_t n = nodes_count_;
             for (std::size_t i = 0; i != n; ++i)
                 node_free_(i);
         } else
             tape_allocator_.deallocate(nullptr, 0);
-        size_ = 0;
+        nodes_count_ = 0;
         max_level_ = -1;
-        entry_id_ = 0u;
+        entry_slot_ = 0u;
     }
 
     /**
-     *  @brief  Erases all the vectors from the index, also deallocating the registry.
-     *          Will change both `size()` and `capacity()` to zero.
-     *          Will deallocate all threads/contexts.
+     *  @brief Erases all members from index, closing files, and returning RAM to OS.
+     *
+     *  Will change both `size()` and `capacity()` to zero.
+     *  Will deallocate all threads/contexts.
+     *  If the index is memory-mapped - releases the mapping and the descriptor.
      */
     void reset() noexcept {
         clear();
 
-        if (nodes_)
-            nodes_allocator_t{}.deallocate(exchange(nodes_, nullptr), limits_.members);
-        if (contexts_) {
-            for (std::size_t i = 0; i != limits_.threads(); ++i)
-                contexts_[i].~context_t();
-            contexts_allocator_t{}.deallocate(exchange(contexts_, nullptr), limits_.threads());
-        }
+        nodes_ = {};
+        contexts_ = {};
+        nodes_mutexes_ = {};
         limits_ = index_limits_t{0, 0};
-        capacity_ = 0;
-        reset_view_();
+        nodes_capacity_ = 0;
+        viewed_file_ = memory_mapped_file_t{};
+        tape_allocator_ = {};
     }
 
     /**
@@ -1918,24 +1884,23 @@ class index_gt {
     void swap(index_gt& other) noexcept {
         std::swap(config_, other.config_);
         std::swap(limits_, other.limits_);
-        std::swap(metric_, other.metric_);
         std::swap(dynamic_allocator_, other.dynamic_allocator_);
         std::swap(tape_allocator_, other.tape_allocator_);
         std::swap(pre_, other.pre_);
         std::swap(viewed_file_, other.viewed_file_);
         std::swap(max_level_, other.max_level_);
-        std::swap(entry_id_, other.entry_id_);
+        std::swap(entry_slot_, other.entry_slot_);
         std::swap(nodes_, other.nodes_);
         std::swap(nodes_mutexes_, other.nodes_mutexes_);
         std::swap(contexts_, other.contexts_);
 
         // Non-atomic parts.
-        std::size_t capacity_copy = capacity_;
-        std::size_t size_copy = size_;
-        capacity_ = other.capacity_.load();
-        size_ = other.size_.load();
-        other.capacity_ = capacity_copy;
-        other.size_ = size_copy;
+        std::size_t capacity_copy = nodes_capacity_;
+        std::size_t count_copy = nodes_count_;
+        nodes_capacity_ = other.nodes_capacity_.load();
+        nodes_count_ = other.nodes_count_.load();
+        other.nodes_capacity_ = capacity_copy;
+        other.nodes_count_ = count_copy;
     }
 
     /**
@@ -1949,72 +1914,30 @@ class index_gt {
             && limits.members <= limits_.members)
             return true;
 
-        if (!nodes_mutexes_.resize(limits.members))
-            return false;
-
-        nodes_allocator_t node_allocator;
-        node_t* new_nodes = node_allocator.allocate(limits.members);
-        if (!new_nodes)
+        visits_bitset_t new_mutexes(limits.members);
+        buffer_gt<node_t, nodes_allocator_t> new_nodes(limits.members);
+        buffer_gt<context_t, contexts_allocator_t> new_contexts(limits.threads());
+        if (!new_nodes || !new_contexts || !new_mutexes)
             return false;
 
-        std::size_t limits_threads = limits.threads();
-        contexts_allocator_t context_allocator;
-        context_t* new_contexts = context_allocator.allocate(limits_threads);
-        if (!new_contexts) {
-            node_allocator.deallocate(new_nodes, limits.members);
-            return false;
-        }
-        for (std::size_t i = 0; i != limits_threads; ++i) {
-            context_t& context = new_contexts[i];
-            new (&context) context_t();
-            context.metric = metric_;
-            if (!context.visits.resize(limits.members)) {
-                for (std::size_t j = 0; j != i; ++j)
-                    context.visits.reset();
-                node_allocator.deallocate(new_nodes, limits.members);
-                context_allocator.deallocate(new_contexts, limits_threads);
+        for (context_t& context : new_contexts) {
+            context.visits = visits_bitset_t(limits.members);
+            if (!context.visits)
                 return false;
-            }
-        }
-
-        // We have passed all the require memory allocations.
-        // The remaining code can't fail. Let's just reuse some of our existing buffers.
-        for (std::size_t i = 0; i != limits_.threads(); ++i) {
-            context_t& old_context = contexts_[i];
-            context_t& context = new_contexts[i];
-            std::swap(old_context.top_candidates, context.top_candidates);
-            std::swap(old_context.next_candidates, context.next_candidates);
-            std::swap(old_context.iteration_cycles, context.iteration_cycles);
-            std::swap(old_context.measurements_count, context.measurements_count);
-            old_context.visits.reset();
         }
 
         // Move the nodes info, and deallocate previous buffers.
         if (nodes_)
-            std::memcpy(new_nodes, nodes_, sizeof(node_t) * size()), node_allocator.deallocate(nodes_, limits_.members);
-        if (contexts_)
-            context_allocator.deallocate(contexts_, limits_.threads());
+            std::memcpy(new_nodes.data(), nodes_.data(), sizeof(node_t) * size());
 
         limits_ = limits;
-        capacity_ = limits.members;
-        nodes_ = new_nodes;
-        contexts_ = new_contexts;
+        nodes_capacity_ = limits.members;
+        nodes_ = std::move(new_nodes);
+        contexts_ = std::move(new_contexts);
+        nodes_mutexes_ = std::move(new_mutexes);
         return true;
     }
 
-    /**
-     *  @brief  Optimizes configuration options to fit the maximum number
-     *          of neighbors in CPU-cache-aligned buffers.
-     */
-    static index_config_t optimize(index_config_t config) noexcept {
-        precomputed_constants_t pre = precompute_(config);
-        std::size_t bytes_per_node_base = node_head_bytes_() + pre.neighbors_base_bytes;
-        std::size_t rounded_size = divide_round_up<64>(bytes_per_node_base) * 64;
-        std::size_t added_connections = (rounded_size - bytes_per_node_base) / sizeof(id_t);
-        config.connectivity = config.connectivity + added_connections / base_level_multiple_();
-        return config;
-    }
-
 #pragma endregion
 
 #pragma region Construction and Search
@@ -2022,9 +1945,9 @@ class index_gt {
     struct add_result_t {
         error_t error{};
         std::size_t new_size{};
-        std::size_t cycles{};
-        std::size_t measurements{};
-        id_t id{};
+        std::size_t visited_members{};
+        std::size_t computed_distances{};
+        std::size_t slot{};
 
         explicit operator bool() const noexcept { return !error; }
         add_result_t failed(error_t message) noexcept {
@@ -2033,29 +1956,31 @@ class index_gt {
         }
     };
 
+    /// @brief  Describes a matched search result, augmenting `member_cref_t`
+    ///         contents with `distance` to the query object.
     struct match_t {
         member_cref_t member;
         distance_t distance;
     };
 
     class search_result_t {
-        index_gt const& index_;
-        top_candidates_t& top_;
+        node_t const* nodes_{};
+        top_candidates_t const* top_{};
 
         friend class index_gt;
-        inline search_result_t(index_gt const& index, top_candidates_t& top) noexcept : index_(index), top_(top) {}
+        inline search_result_t(index_gt const& index, top_candidates_t& top) noexcept
+            : nodes_(index.nodes_), top_(&top) {}
 
       public:
+        /** @brief  Number of search results found. */
         std::size_t count{};
-        std::size_t cycles{};
-        std::size_t measurements{};
+        /** @brief  Number of graph nodes traversed. */
+        std::size_t visited_members{};
+        /** @brief  Number of times the distances were computed. */
+        std::size_t computed_distances{};
         error_t error{};
 
-        // todo: this is a hack to get a handle to a failed search_result_t without changing its member types
-        // given that search_result_t can represent a failed result (which implies no valid top_candidates_t &top_),
-        // the top_ probably needs to be a pointer.
-        inline search_result_t(index_gt const& index) noexcept
-            : index_(index), top_(index.contexts_[0].top_candidates) {}
+        inline search_result_t() noexcept {}
         inline search_result_t(search_result_t&&) = default;
         inline search_result_t& operator=(search_result_t&&) = default;
 
@@ -2071,46 +1996,88 @@ class index_gt {
         inline match_t operator[](std::size_t i) const noexcept { return at(i); }
         inline match_t front() const noexcept { return at(0); }
         inline match_t back() const noexcept { return at(count - 1); }
-        inline bool contains(label_t label) const noexcept {
+        inline bool contains(key_t key) const noexcept {
             for (std::size_t i = 0; i != count; ++i)
-                if (at(i).member.label == label)
+                if (at(i).member.key == key)
                     return true;
             return false;
         }
         inline match_t at(std::size_t i) const noexcept {
-            candidate_t const* top_ordered = top_.data();
+            candidate_t const* top_ordered = top_->data();
             candidate_t candidate = top_ordered[i];
-            node_t node = index_.node_with_id_(candidate.id);
-            return {member_cref_t{node.label(), node.vector_view(), candidate.id}, candidate.distance};
+            node_t node = nodes_[candidate.slot];
+            return {member_cref_t{node.ckey(), candidate.slot}, candidate.distance};
         }
-        inline std::size_t dump_to(label_t* labels, distance_t* distances) const noexcept {
+        inline std::size_t merge_into(          //
+            key_t* keys, distance_t* distances, //
+            std::size_t old_count, std::size_t max_count) const noexcept {
+
+            std::size_t merged_count = old_count;
             for (std::size_t i = 0; i != count; ++i) {
                 match_t result = operator[](i);
-                labels[i] = result.member.label;
+                distance_t* merged_end = distances + merged_count;
+                std::size_t offset = std::lower_bound(distances, merged_end, result.distance) - distances;
+                if (offset == max_count)
+                    continue;
+
+                std::size_t count_worse = merged_count - offset - (max_count == merged_count);
+                std::memmove(keys + offset + 1, keys + offset, count_worse * sizeof(key_t));
+                std::memmove(distances + offset + 1, distances + offset, count_worse * sizeof(distance_t));
+                keys[offset] = result.member.key;
+                distances[offset] = result.distance;
+                merged_count += merged_count != max_count;
+            }
+            return merged_count;
+        }
+        inline std::size_t dump_to(key_t* keys, distance_t* distances) const noexcept {
+            for (std::size_t i = 0; i != count; ++i) {
+                match_t result = operator[](i);
+                keys[i] = result.member.key;
                 distances[i] = result.distance;
             }
             return count;
         }
-        inline std::size_t dump_to(label_t* labels) const noexcept {
+        inline std::size_t dump_to(key_t* keys) const noexcept {
             for (std::size_t i = 0; i != count; ++i) {
                 match_t result = operator[](i);
-                labels[i] = result.member.label;
+                keys[i] = result.member.key;
             }
             return count;
         }
     };
 
     /**
-     *  @brief Inserts a new vector into the index. Thread-safe.
+     *  @brief  Inserts a new entry into the index. Thread-safe. Supports @b heterogeneous lookups.
+     *          Expects needed capacity to be reserved ahead of time: `size() < capacity()`.
+     *
+     *  @tparam metric_at
+     *      A function responsible for computing the distance @b (dis-similarity) between two objects.
+     *      It should be callable into distinctly different scenarios:
+     *          - `distance_t operator() (value_at, entry_at)` - from new object to existing entries.
+     *          - `distance_t operator() (entry_at, entry_at)` - between existing entries.
+     *      Where any possible `entry_at` has both two interfaces: `std::size_t slot()`, `key_t key()`.
      *
-     *  @param[in] label External identifier/name/descriptor for the vector.
-     *  @param[in] vector Contiguous range of scalars forming a vector view.
+     *  @param[in] key External identifier/name/descriptor for the new entry.
+     *  @param[in] value Content that will be compared against other entries to index.
+     *  @param[in] metric Callable object measuring distance between ::value and present objects.
      *  @param[in] config Configuration options for this specific operation.
+     *  @param[in] callback On-success callback, executed while the `member_ref_t` is still under lock.
      */
-    add_result_t add(label_t label, vector_view_t vector, add_config_t config = {}) usearch_noexcept_m {
+    template <                                   //
+        typename value_at,                       //
+        typename metric_at,                      //
+        typename callback_at = dummy_callback_t, //
+        typename prefetch_at = dummy_prefetch_t  //
+        >
+    add_result_t add(                                    //
+        key_t key, value_at&& value, metric_at&& metric, //
+        index_update_config_t config = {},               //
+        callback_at&& callback = callback_at{},          //
+        prefetch_at&& prefetch = prefetch_at{}) usearch_noexcept_m {
 
-        usearch_assert_m(!is_immutable(), "Can't add to an immutable index");
         add_result_t result;
+        if (is_immutable())
+            return result.failed("Can't add to an immutable index");
 
         // Make sure we have enough local memory to perform this request
         context_t& context = contexts_[config.thread];
@@ -2121,7 +2088,8 @@ class index_gt {
 
         // The top list needs one more slot than the connectivity of the base level
         // for the heuristic, that tries to squeeze one more element into saturated list.
-        std::size_t top_limit = (std::max)(base_level_multiple_() * config_.connectivity + 1, config.expansion);
+        std::size_t connectivity_max = (std::max)(config_.connectivity_base, config_.connectivity);
+        std::size_t top_limit = (std::max)(connectivity_max + 1, config.expansion);
         if (!top.reserve(top_limit))
             return result.failed("Out of memory!");
         if (!next.reserve(config.expansion))
@@ -2129,60 +2097,98 @@ class index_gt {
 
         // Determining how much memory to allocate for the node depends on the target level
         std::unique_lock<std::mutex> new_level_lock(global_mutex_);
-        level_t max_level_copy = max_level_; // Copy under lock
-        id_t entry_id_copy = entry_id_;      // Copy under lock
+        level_t max_level_copy = max_level_;      // Copy under lock
+        std::size_t entry_idx_copy = entry_slot_; // Copy under lock
         level_t target_level = choose_random_level_(context.level_generator);
-        if (target_level <= max_level_copy)
-            new_level_lock.unlock();
+
+        // Make sure we are not overflowing
+        std::size_t capacity = nodes_capacity_.load();
+        std::size_t new_slot = nodes_count_.fetch_add(1);
+        if (new_slot >= capacity) {
+            nodes_count_.fetch_sub(1);
+            return result.failed("Reserve capacity ahead of insertions!");
+        }
 
         // Allocate the neighbors
-        node_t node = node_make_(label, vector, target_level, config.store_vector);
-        if (!node)
+        node_t node = node_make_(key, target_level);
+        if (!node) {
+            nodes_count_.fetch_sub(1);
             return result.failed("Out of memory!");
-        std::size_t old_size = size_.fetch_add(1);
-        id_t new_id = static_cast<id_t>(old_size);
-        nodes_[old_size] = node;
-        result.new_size = old_size + 1;
-        result.id = new_id;
-        node_lock_t new_lock = node_lock_(old_size);
+        }
+        if (target_level <= max_level_copy)
+            new_level_lock.unlock();
+
+        nodes_[new_slot] = node;
+        result.new_size = new_slot + 1;
+        result.slot = new_slot;
+        callback(at(new_slot));
+        node_lock_t new_lock = node_lock_(new_slot);
 
         // Do nothing for the first element
-        if (!new_id) {
-            entry_id_ = new_id;
+        if (!new_slot) {
+            entry_slot_ = new_slot;
             max_level_ = target_level;
             return result;
         }
 
         // Pull stats
-        result.measurements = context.measurements_count;
-        result.cycles = context.iteration_cycles;
+        result.computed_distances = context.computed_distances_count;
+        result.visited_members = context.iteration_cycles;
 
-        connect_node_across_levels_(new_id, vector, entry_id_copy, max_level_copy, target_level, config, context);
+        connect_node_across_levels_(                                //
+            value, metric, prefetch,                                //
+            new_slot, entry_idx_copy, max_level_copy, target_level, //
+            config, context);
 
         // Normalize stats
-        result.measurements = context.measurements_count - result.measurements;
-        result.cycles = context.iteration_cycles - result.cycles;
+        result.computed_distances = context.computed_distances_count - result.computed_distances;
+        result.visited_members = context.iteration_cycles - result.visited_members;
 
         // Updating the entry point if needed
         if (target_level > max_level_copy) {
-            entry_id_ = new_id;
+            entry_slot_ = new_slot;
             max_level_ = target_level;
         }
         return result;
     }
 
     /**
-     *  @brief Update an existing entry, replacing a vector and a label. Thread-safe.
+     *  @brief  Update an existing entry. Thread-safe. Supports @b heterogeneous lookups.
      *
-     *  @param[in] old_id Existing internal identifier for a node to be replaced.
-     *  @param[in] label External identifier/name/descriptor for the vector.
-     *  @param[in] vector Contiguous range of scalars forming a vector view.
+     *  @tparam metric_at
+     *      A function responsible for computing the distance @b (dis-similarity) between two objects.
+     *      It should be callable into distinctly different scenarios:
+     *          - `distance_t operator() (value_at, entry_at)` - from new object to existing entries.
+     *          - `distance_t operator() (entry_at, entry_at)` - between existing entries.
+     *      For any possible `entry_at` following interfaces will work:
+     *          - `std::size_t get_slot(entry_at const &)`
+     *          - `key_t get_key(entry_at const &)`
+     *
+     *  @param[in] iterator Iterator pointing to an existing entry to be replaced.
+     *  @param[in] key External identifier/name/descriptor for the entry.
+     *  @param[in] value Content that will be compared against other entries in the index.
+     *  @param[in] metric Callable object measuring distance between ::value and present objects.
      *  @param[in] config Configuration options for this specific operation.
+     *  @param[in] callback On-success callback, executed while the `member_ref_t` is still under lock.
      */
-    add_result_t update(id_t old_id, label_t label, vector_view_t vector, add_config_t config = {}) usearch_noexcept_m {
+    template <                                   //
+        typename value_at,                       //
+        typename metric_at,                      //
+        typename callback_at = dummy_callback_t, //
+        typename prefetch_at = dummy_prefetch_t  //
+        >
+    add_result_t update(                        //
+        member_iterator_t iterator,             //
+        key_t key,                              //
+        value_at&& value,                       //
+        metric_at&& metric,                     //
+        index_update_config_t config = {},      //
+        callback_at&& callback = callback_at{}, //
+        prefetch_at&& prefetch = prefetch_at{}) usearch_noexcept_m {
 
         usearch_assert_m(!is_immutable(), "Can't add to an immutable index");
         add_result_t result;
+        std::size_t old_slot = iterator.slot_;
 
         // Make sure we have enough local memory to perform this request
         context_t& context = contexts_[config.thread];
@@ -2193,57 +2199,77 @@ class index_gt {
 
         // The top list needs one more slot than the connectivity of the base level
         // for the heuristic, that tries to squeeze one more element into saturated list.
-        std::size_t top_limit = (std::max)(base_level_multiple_() * config_.connectivity + 1, config.expansion);
+        std::size_t connectivity_max = (std::max)(config_.connectivity_base, config_.connectivity);
+        std::size_t top_limit = (std::max)(connectivity_max + 1, config.expansion);
         if (!top.reserve(top_limit))
             return result.failed("Out of memory!");
         if (!next.reserve(config.expansion))
             return result.failed("Out of memory!");
 
-        node_lock_t new_lock = node_lock_(old_id);
-        node_t node = node_with_id_(old_id);
+        node_lock_t new_lock = node_lock_(old_slot);
+        node_t node = node_at_(old_slot);
+
+        level_t node_level = node.level();
+        span_bytes_t node_bytes = node_bytes_(node);
+        std::memset(node_bytes.data(), 0, node_bytes.size());
+        node.level(node_level);
 
         // Pull stats
-        result.measurements = context.measurements_count;
-        result.cycles = context.iteration_cycles;
+        result.computed_distances = context.computed_distances_count;
+        result.visited_members = context.iteration_cycles;
 
-        connect_node_across_levels_(old_id, vector, entry_id_, max_level_, node.level(), config, context);
-        node.label(label);
+        connect_node_across_levels_(                       //
+            value, metric, prefetch,                       //
+            old_slot, entry_slot_, max_level_, node_level, //
+            config, context);
+        node.key(key);
 
         // Normalize stats
-        result.measurements = context.measurements_count - result.measurements;
-        result.cycles = context.iteration_cycles - result.cycles;
+        result.computed_distances = context.computed_distances_count - result.computed_distances;
+        result.visited_members = context.iteration_cycles - result.visited_members;
+        result.slot = old_slot;
 
+        callback(at(old_slot));
         return result;
     }
 
     /**
      *  @brief Searches for the closest elements to the given ::query. Thread-safe.
      *
-     *  @param[in] query Contiguous range of scalars forming a vector view.
+     *  @param[in] query Content that will be compared against other entries in the index.
      *  @param[in] wanted The upper bound for the number of results to return.
      *  @param[in] config Configuration options for this specific operation.
      *  @param[in] predicate Optional filtering predicate for `member_cref_t`.
      *  @return Smart object referencing temporary memory. Valid until next `search()` or `add()`.
      */
-    template <typename predicate_at = dummy_predicate_t>
-    search_result_t search( //
-        vector_view_t query, std::size_t wanted, search_config_t config = {},
-        predicate_at&& predicate = dummy_predicate_t{}) const noexcept {
+    template <                                     //
+        typename value_at,                         //
+        typename metric_at,                        //
+        typename predicate_at = dummy_predicate_t, //
+        typename prefetch_at = dummy_prefetch_t    //
+        >
+    search_result_t search(                        //
+        value_at&& query,                          //
+        std::size_t wanted,                        //
+        metric_at&& metric,                        //
+        index_search_config_t config = {},         //
+        predicate_at&& predicate = predicate_at{}, //
+        prefetch_at&& prefetch = prefetch_at{}) const noexcept {
 
         context_t& context = contexts_[config.thread];
         top_candidates_t& top = context.top_candidates;
         search_result_t result{*this, top};
-        if (!size_)
+        if (!nodes_count_)
             return result;
 
         // Go down the level, tracking only the closest match
-        result.measurements = context.measurements_count;
-        result.cycles = context.iteration_cycles;
+        result.computed_distances = context.computed_distances_count;
+        result.visited_members = context.iteration_cycles;
 
         if (config.exact) {
             if (!top.reserve(wanted))
                 return result.failed("Out of memory!");
-            search_exact_(query, wanted, context, std::forward<predicate_at>(predicate));
+            search_exact_(query, metric, predicate, wanted, context);
         } else {
             next_candidates_t& next = context.next_candidates;
             std::size_t expansion = (std::max)(config.expansion, wanted);
@@ -2252,9 +2278,10 @@ class index_gt {
             if (!top.reserve(expansion))
                 return result.failed("Out of memory!");
 
-            id_t closest_id = search_for_one_(entry_id_, query, max_level_, 0, context);
+            std::size_t closest_slot = search_for_one_(query, metric, prefetch, entry_slot_, max_level_, 0, context);
+
             // For bottom layer we need a more optimized procedure
-            if (!search_to_find_in_base_(closest_id, query, expansion, context, std::forward<predicate_at>(predicate)))
+            if (!search_to_find_in_base_(query, metric, predicate, prefetch, closest_slot, expansion, context))
                 return result.failed("Out of memory!");
         }
 
@@ -2262,8 +2289,8 @@ class index_gt {
         top.shrink(wanted);
 
         // Normalize stats
-        result.measurements = context.measurements_count - result.measurements;
-        result.cycles = context.iteration_cycles - result.cycles;
+        result.computed_distances = context.computed_distances_count - result.computed_distances;
+        result.visited_members = context.iteration_cycles - result.visited_members;
         result.count = top.size();
         return result;
     }
@@ -2283,13 +2310,13 @@ class index_gt {
         stats_t result{};
         result.nodes = size();
         for (std::size_t i = 0; i != result.nodes; ++i) {
-            node_t node = node_with_id_(i);
-            std::size_t max_edges = node.level() * config_.connectivity + base_level_multiple_() * config_.connectivity;
+            node_t node = node_at_(i);
+            std::size_t max_edges = node.level() * config_.connectivity + config_.connectivity_base;
             std::size_t edges = 0;
             for (level_t level = 0; level <= node.level(); ++level)
                 edges += neighbors_(node, level).size();
 
-            result.allocated_bytes += node_bytes_(node);
+            result.allocated_bytes += node_bytes_(node).size();
             result.edges += edges;
             result.max_edges += max_edges;
         }
@@ -2302,15 +2329,15 @@ class index_gt {
 
         std::size_t neighbors_bytes = !level ? pre_.neighbors_base_bytes : pre_.neighbors_bytes;
         for (std::size_t i = 0; i != result.nodes; ++i) {
-            node_t node = node_with_id_(i);
+            node_t node = node_at_(i);
             if (static_cast<std::size_t>(node.level()) < level)
                 continue;
 
             result.edges += neighbors_(node, level).size();
-            result.allocated_bytes += node_head_bytes_() + node_vector_bytes_(node) + neighbors_bytes;
+            result.allocated_bytes += node_head_bytes_() + neighbors_bytes;
         }
 
-        std::size_t max_edges_per_node = level ? config_.connectivity : base_level_multiple_() * config_.connectivity;
+        std::size_t max_edges_per_node = level ? config_.connectivity_base : config_.connectivity;
         result.max_edges = result.nodes * max_edges_per_node;
         return result;
     }
@@ -2318,6 +2345,8 @@ class index_gt {
     /**
      *  @brief  A relatively accurate lower bound on the amount of memory consumed by the system.
      *          In practice it's error will be below 10%.
+     *
+     *  @see    `stream_length` for the length of the binary serialized representation.
      */
     std::size_t memory_usage(std::size_t allocator_entry_bytes = default_allocator_entry_bytes()) const noexcept {
         std::size_t total = 0;
@@ -2335,367 +2364,297 @@ class index_gt {
         return total;
     }
 
-    std::size_t memory_usage_per_node(dim_t dim, level_t level) const noexcept { return node_bytes_(dim, level); }
-
-    void change_metric(metric_t const& m) noexcept {
-        metric_ = m;
-        for (std::size_t i = 0; i != limits_.threads(); ++i)
-            contexts_[i].metric = metric_;
-    }
+    std::size_t memory_usage_per_node(level_t level) const noexcept { return node_bytes_(level); }
 
 #pragma endregion
 
 #pragma region Serialization
 
-    struct serialization_result_t {
-        error_t error;
-
-        explicit operator bool() const noexcept { return !error; }
-        serialization_result_t failed(error_t message) noexcept {
-            error = std::move(message);
-            return std::move(*this);
-        }
-    };
-
     /**
-     *  @brief  Saves serialized binary index representation to disk,
-     *          co-locating vectors and neighbors lists.
-     *          Available on Linux, MacOS, Windows.
+     *  @brief  Saves serialized binary index representation to a file, generally on disk.
      */
     template <typename progress_at = dummy_progress_t>
-    serialization_result_t save(char const* file_path, progress_at&& progress = {}) const noexcept {
+    serialization_result_t save(output_file_t file, progress_at&& progress = {}) const noexcept {
+
+        serialization_result_t result = file.open_if_not();
+        if (result)
+            stream(
+                [&](void* buffer, std::size_t length) {
+                    result = file.write(buffer, length);
+                    return !!result;
+                },
+                std::forward<progress_at>(progress));
+        return result;
+    }
+
+    /**
+     *  @brief  Saves serialized binary index representation to a stream.
+     */
+    template <typename output_callback_at, typename progress_at = dummy_progress_t>
+    serialization_result_t stream(output_callback_at&& callback, progress_at&& progress = {}) const noexcept {
 
-        // Make sure we have right to write to that file
         serialization_result_t result;
-        std::FILE* file = std::fopen(file_path, "wb");
-        if (!file)
-            return result.failed(std::strerror(errno));
 
-        // Prepare the header with metadata
-        file_header_t state_buffer{};
-        std::memset(state_buffer, 0, sizeof(file_header_t));
-        file_head_t state{state_buffer};
-        std::memcpy(state_buffer, default_magic(), std::strlen(default_magic()));
-
-        // Mark compatibility
-        state.version_major = USEARCH_VERSION_MAJOR;
-        state.version_minor = USEARCH_VERSION_MINOR;
-        state.version_patch = USEARCH_VERSION_PATCH;
-        state.metric = metric_.kind();
-
-        // Describe state
-        state.connectivity = config_.connectivity;
-        state.max_level = max_level_;
-        state.vector_alignment = config_.vector_alignment;
-        state.bytes_per_label = sizeof(label_t);
-        state.bytes_per_id = sizeof(id_t);
-        state.scalar_kind = metric_.scalar_kind();
-        state.size = size_;
-        state.entry_idx = entry_id_;
-
-        // Augment with metadata
-        std::size_t graphs_bytes = 0;
-        std::size_t vectors_bytes = 0;
-        for (std::size_t i = 0; i != state.size; ++i) {
-            node_t node = node_with_id_(i);
-            std::size_t node_bytes = node_bytes_(node);
-            std::size_t node_vector_bytes = node_vector_bytes_(node);
-            graphs_bytes += node_bytes - node_vector_bytes;
-            vectors_bytes += node_vector_bytes;
+        // Export some basic metadata
+        index_serialized_header_t header;
+        header.size = nodes_count_;
+        header.connectivity = config_.connectivity;
+        header.connectivity_base = config_.connectivity_base;
+        header.max_level = max_level_;
+        header.entry_slot = entry_slot_;
+        if (!callback(&header, sizeof(header)))
+            return result.failed("Failed to serialize into stream");
+
+        // Export the number of levels per node
+        // That is both enough to estimate the overall memory consumption,
+        // and to be able to estimate the offsets of every entry in the file.
+        for (std::size_t i = 0; i != header.size; ++i) {
+            node_t node = node_at_(i);
+            level_t level = node.level();
+            if (!callback(&level, sizeof(level)))
+                return result.failed("Failed to serialize into stream");
         }
-        state.bytes_for_graphs = graphs_bytes;
-        state.bytes_for_vectors = vectors_bytes;
-        state.bytes_checksum = 0;
-
-        // Perform serialization
-        auto write_chunk = [&](void* begin, std::size_t length) {
-            std::size_t written = std::fwrite(begin, length, 1, file);
-            if (!written) {
-                std::fclose(file);
-                result.failed(std::strerror(errno));
-            }
-        };
 
-        // Write the header
-        write_chunk(&state_buffer[0], sizeof(file_header_t));
-        if (result.error)
-            return result;
-
-        // Serialize nodes one by one
-        for (std::size_t i = 0; i != state.size; ++i) {
-            node_t node = node_with_id_(i);
-            std::size_t node_bytes = node_bytes_(node);
-            std::size_t node_vector_bytes = node_vector_bytes_(node);
-            // Dump neighbors and vectors, as vectors may be in a disjoint location
-            write_chunk(node.tape(), node_bytes - node_vector_bytes);
-            if (result.error)
-                return result;
-            write_chunk(node.vector(), node_vector_bytes);
-            if (result.error)
-                return result;
-            progress(i, state.size);
+        // After that dump the nodes themselves
+        for (std::size_t i = 0; i != header.size; ++i) {
+            span_bytes_t node_bytes = node_bytes_(node_at_(i));
+            if (!callback(node_bytes.data(), node_bytes.size()))
+                return result.failed("Failed to serialize into stream");
+            progress(i, header.size);
         }
 
-        std::fclose(file);
         return {};
     }
 
     /**
-     *  @brief  Loads the serialized binary index representation from disk,
-     *          copying both vectors and neighbors lists into RAM.
-     *          Available on Linux, MacOS, Windows.
+     *  @brief  Estimate the binary length (in bytes) of the serialized index.
+     */
+    std::size_t stream_length() const noexcept {
+        std::size_t neighbors_length = 0;
+        for (std::size_t i = 0; i != size(); ++i)
+            neighbors_length += node_bytes_(node_at_(i).level());
+        return sizeof(index_serialized_header_t) + neighbors_length;
+    }
+
+    /**
+     *  @brief  Loads the serialized binary index representation from disk to RAM.
+     *          Adjusts the configuration properties of the constructed index to
+     *          match the settings in the file.
      */
     template <typename progress_at = dummy_progress_t>
-    serialization_result_t load(char const* file_path, progress_at&& progress = {}) noexcept {
+    serialization_result_t load(input_file_t file, progress_at&& progress = {}) noexcept {
 
         // Remove previously stored objects
         reset();
 
-        // Start parsing the files
-        serialization_result_t result;
-        file_header_t state_buffer{};
-        std::FILE* file = std::fopen(file_path, "rb");
-        if (!file)
-            return result.failed(std::strerror(errno));
-
-        auto read_chunk = [&](void* begin, std::size_t length) {
-            std::size_t read = std::fread(begin, length, 1, file);
-            if (!read) {
-                std::fclose(file);
-                result.failed(std::strerror(errno));
-            }
-        };
-
-        // Read the header
-        {
-            read_chunk(&state_buffer[0], sizeof(file_header_t));
-            if (result.error)
-                return result;
+        serialization_result_t result = file.open_if_not();
+        if (!result)
+            return result;
 
-            file_head_t state{state_buffer};
-            if (state.bytes_per_label != sizeof(label_t)) {
-                std::fclose(file);
-                return result.failed("Incompatible label type!");
-            }
-            if (state.bytes_per_id != sizeof(id_t)) {
-                std::fclose(file);
-                return result.failed("Incompatible ID type!");
-            }
+        // Pull basic metadata
+        index_serialized_header_t header;
+        result = file.read(&header, sizeof(header));
+        if (!result)
+            return result;
 
-            config_.connectivity = state.connectivity;
-            config_.vector_alignment = state.vector_alignment;
-            pre_ = precompute_(config_);
+        // Allocate some dynamic memory to read all the levels
+        using levels_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<level_t>;
+        buffer_gt<level_t, levels_allocator_t> levels(header.size);
+        if (!levels)
+            return result.failed("Out of memory");
+        result = file.read(levels, header.size * sizeof(level_t));
+        if (!result)
+            return result;
 
-            index_limits_t limits;
-            limits.members = state.size;
-            if (!reserve(limits)) {
-                std::fclose(file);
-                return result.failed("Out of memory");
-            }
-            size_ = state.size;
-            max_level_ = static_cast<level_t>(state.max_level);
-            entry_id_ = static_cast<id_t>(state.entry_idx);
+        // Submit metadata
+        config_.connectivity = header.connectivity;
+        config_.connectivity_base = header.connectivity_base;
+        pre_ = precompute_(config_);
+        index_limits_t limits;
+        limits.members = header.size;
+        if (!reserve(limits)) {
+            reset();
+            return result.failed("Out of memory");
         }
-
-        // Load nodes one by one
-        std::size_t const size = size_;
-        for (std::size_t i = 0; i != size; ++i) {
-            label_t label;
-            dim_t dim;
-            level_t level;
-            read_chunk(&label, sizeof(label));
-            if (result.error)
-                return result;
-            read_chunk(&dim, sizeof(dim));
-            if (result.error)
+        nodes_count_ = header.size;
+        max_level_ = static_cast<level_t>(header.max_level);
+        entry_slot_ = static_cast<compressed_slot_t>(header.entry_slot);
+
+        // Load the nodes
+        for (std::size_t i = 0; i != header.size; ++i) {
+            span_bytes_t node_bytes = node_malloc_(levels[i]);
+            result = file.read(node_bytes.data(), node_bytes.size());
+            if (!result) {
+                reset();
                 return result;
-            read_chunk(&level, sizeof(level));
-            if (result.error)
-                return result;
-
-            std::size_t node_bytes = node_bytes_(dim, level);
-            node_t node = node_malloc_(dim, level);
-            node.label(label);
-            node.dim(dim);
-            node.level(level);
-            read_chunk(node.tape() + node_head_bytes_(), node_bytes - node_head_bytes_());
-            if (result.error)
-                return result;
-            nodes_[i] = node;
-            progress(i, size);
+            }
+            nodes_[i] = node_t{node_bytes.data()};
+            progress(i, header.size);
         }
-
-        std::fclose(file);
-        reset_view_();
         return {};
     }
 
     /**
      *  @brief  Memory-maps the serialized binary index representation from disk,
-     *          @b without copying the vectors and neighbors lists into RAM.
-     *          Available on Linux, MacOS, but @b not on Windows.
+     *          @b without copying data into RAM, and fetching it on-demand.
      */
     template <typename progress_at = dummy_progress_t>
-    serialization_result_t view(char const* file_path, progress_at&& progress = {}) noexcept {
+    serialization_result_t view(memory_mapped_file_t file, std::size_t offset = 0,
+                                progress_at&& progress = {}) noexcept {
 
         // Remove previously stored objects
         reset();
 
-        // Start parsing the files
-        serialization_result_t result;
-
-#if defined(USEARCH_DEFINED_WINDOWS)
-
-        HANDLE file_handle =
-            CreateFile(file_path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
-        if (file_handle == INVALID_HANDLE_VALUE)
-            return result.failed("Opening file failed!");
+        serialization_result_t result = file.open_if_not();
+        if (!result)
+            return result;
 
-        size_t file_length = GetFileSize(file_handle, 0);
-        HANDLE mapping_handle = CreateFileMapping(file_handle, 0, PAGE_READONLY, 0, 0, 0);
-        if (mapping_handle == 0) {
-            CloseHandle(file_handle);
-            return result.failed("Mapping file failed!");
+        // Pull basic metadata
+        index_serialized_header_t header;
+        if (file.size() - offset < sizeof(header))
+            return result.failed("File is corrupted and lacks a header");
+        std::memcpy(&header, file.data() + offset, sizeof(header));
+
+        // Precompute offsets of every node, but before that we need to update the configs
+        // This could have been done with `std::exclusive_scan`, but it's only available from C++17.
+        using offsets_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<std::size_t>;
+        buffer_gt<std::size_t, offsets_allocator_t> offsets(header.size);
+        if (!offsets)
+            return result.failed("Out of memory");
+
+        config_.connectivity = header.connectivity;
+        config_.connectivity_base = header.connectivity_base;
+        pre_ = precompute_(config_);
+        misaligned_ptr_gt<level_t> levels{(byte_t*)file.data() + offset + sizeof(header)};
+        offsets[0] = offset + sizeof(header) + sizeof(level_t) * header.size;
+        for (std::size_t i = 1; i < header.size; ++i)
+            offsets[i] = offsets[i - 1] + node_bytes_(levels[i - 1]);
+
+        std::size_t total_bytes = offsets[header.size - 1] + node_bytes_(levels[header.size - 1]);
+        if (file.size() < total_bytes) {
+            reset();
+            return result.failed("File is corrupted and can't fit all the nodes");
         }
 
-        byte_t* file = (byte_t*)MapViewOfFile(mapping_handle, FILE_MAP_READ, 0, 0, file_length);
-        if (file == 0) {
-            CloseHandle(mapping_handle);
-            CloseHandle(file_handle);
-            return result.failed("View the map failed!");
+        // Submit metadata and reserve memory
+        index_limits_t limits;
+        limits.members = header.size;
+        if (!reserve(limits)) {
+            reset();
+            return result.failed("Out of memory");
         }
-        viewed_file_.file_handle = file_handle;
-        viewed_file_.mapping_handle = mapping_handle;
-        viewed_file_.ptr = file;
-        viewed_file_.length = file_length;
-#else
-
-#if defined(USEARCH_DEFINED_LINUX)
-        int descriptor = open(file_path, O_RDONLY | O_NOATIME);
-#else
-        int descriptor = open(file_path, O_RDONLY);
-#endif
-
-        // Estimate the file size
-        struct stat file_stat;
-        int fstat_status = fstat(descriptor, &file_stat);
-        if (fstat_status < 0) {
-            close(descriptor);
-            return result.failed(std::strerror(errno));
+        nodes_count_ = header.size;
+        max_level_ = static_cast<level_t>(header.max_level);
+        entry_slot_ = static_cast<compressed_slot_t>(header.entry_slot);
+
+        // Rapidly address all the nodes
+        for (std::size_t i = 0; i != header.size; ++i) {
+            nodes_[i] = node_t{(byte_t*)file.data() + offsets[i]};
+            progress(i, header.size);
         }
+        viewed_file_ = std::move(file);
+        return {};
+    }
 
-        // Map the entire file
-        byte_t* file = (byte_t*)mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, descriptor, 0);
-        if (file == MAP_FAILED) {
-            close(descriptor);
-            return result.failed(std::strerror(errno));
-        }
-        viewed_file_.file_descriptor = descriptor;
-        viewed_file_.ptr = file;
-        viewed_file_.length = file_stat.st_size;
-#endif // Platform specific code
+#pragma endregion
 
-        // Read the header
-        {
-            file_head_t state{file};
-            if (state.bytes_per_label != sizeof(label_t)) {
-                reset_view_();
-                return result.failed("Incompatible label type!");
-            }
-            if (state.bytes_per_id != sizeof(id_t)) {
-                reset_view_();
-                return result.failed("Incompatible ID type!");
-            }
+    /**
+     *  @brief  Performs compaction on the whole HNSW index, purging some entries
+     *          and links to them, while also generating a more efficient mapping,
+     *          putting the more frequently used entries closer together.
+     *
+     *
+     * Scans the whole collection, removing the links leading towards
+     *          banned entries. This essentially isolates some nodes from the rest
+     *          of the graph, while keeping their outgoing links, in case the node
+     *          is structurally relevant and has a crucial role in the index.
+     *          It won't reclaim the memory.
+     *
+     *  @param[in] allow_member Predicate to mark nodes for isolation.
+     *  @param[in] executor Thread-pool to execute the job in parallel.
+     *  @param[in] progress Callback to report the execution progress.
+     */
+    template <typename values_at, typename metric_at,                       //
+              typename slot_transition_at = dummy_label_to_label_mapping_t, //
+              typename executor_at = dummy_executor_t,                      //
+              typename progress_at = dummy_progress_t,                      //
+              typename prefetch_at = dummy_prefetch_t>
+    void compact(                             //
+        values_at&& values,                   //
+        metric_at&& metric,                   //
+        slot_transition_at&& slot_transition, //
 
-            config_.connectivity = state.connectivity;
-            config_.vector_alignment = state.vector_alignment;
-            pre_ = precompute_(config_);
+        executor_at&& executor = executor_at{}, //
+        progress_at&& progress = progress_at{}, //
+        prefetch_at&& prefetch = prefetch_at{}) noexcept {
+
+        // Export all the keys, slots, and levels.
+        // Partition them with the predicate.
+        // Sort the allowed entries in descending order of their level.
+        // Create a new array mapping old slots to the new ones (INT_MAX for deleted items).
+        struct slot_level_t {
+            compressed_slot_t old_slot;
+            compressed_slot_t cluster;
+            level_t level;
+        };
+        using slot_level_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<slot_level_t>;
+        buffer_gt<slot_level_t, slot_level_allocator_t> slots_and_levels(size());
+
+        // For every bottom level node, determine its parent cluster
+        executor.execute_bulk(slots_and_levels.size(), [&](std::size_t thread_idx, std::size_t old_slot) {
+            context_t& context = contexts_[thread_idx];
+            std::size_t cluster = search_for_one_( //
+                values[citerator_at(old_slot)],    //
+                metric, prefetch,                  //
+                entry_slot_, max_level_, 0, context);
+            slots_and_levels[old_slot] = {                                          //
+                                          static_cast<compressed_slot_t>(old_slot), //
+                                          static_cast<compressed_slot_t>(cluster),  //
+                                          node_at_(old_slot).level()};
+        });
 
-            index_limits_t limits;
-            limits.members = state.size;
-            limits.threads_add = 0;
-            if (!reserve(limits))
-                return result.failed("Out of memory!");
+        // Where the actual permutation happens:
+        std::sort(slots_and_levels.begin(), slots_and_levels.end(), [](slot_level_t const& a, slot_level_t const& b) {
+            return a.level == b.level ? a.cluster < b.cluster : a.level > b.level;
+        });
 
-            size_ = state.size;
-            max_level_ = static_cast<level_t>(state.max_level);
-            entry_id_ = static_cast<id_t>(state.entry_idx);
-        }
+        using size_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<std::size_t>;
+        buffer_gt<std::size_t, size_allocator_t> old_slot_to_new(slots_and_levels.size());
+        for (std::size_t new_slot = 0; new_slot != slots_and_levels.size(); ++new_slot)
+            old_slot_to_new[slots_and_levels[new_slot].old_slot] = new_slot;
 
-        // Locate every node packed into file
-        std::size_t progress_bytes = sizeof(file_header_t);
-        std::size_t const size = size_;
-        for (std::size_t i = 0; i != size; ++i) {
-            byte_t* tape = (byte_t*)(file + progress_bytes);
-            dim_t dim = misaligned_load<dim_t>(tape + sizeof(label_t));
-            level_t level = misaligned_load<level_t>(tape + sizeof(label_t) + sizeof(dim_t));
-
-            std::size_t node_bytes = node_bytes_(dim, level);
-            std::size_t node_vector_bytes = dim * sizeof(scalar_t);
-            nodes_[i] = node_t{tape, (scalar_t*)(tape + node_bytes - node_vector_bytes)};
-            progress_bytes += node_bytes;
-            progress(i, size);
-        }
+        // Erase all the incoming links
+        buffer_gt<node_t, nodes_allocator_t> reordered_nodes(slots_and_levels.size());
+        tape_allocator_t reordered_tape;
 
-        return {};
-    }
+        for (std::size_t new_slot = 0; new_slot != slots_and_levels.size(); ++new_slot) {
+            std::size_t old_slot = slots_and_levels[new_slot].old_slot;
+            node_t old_node = node_at_(old_slot);
 
-#pragma endregion
+            std::size_t node_bytes = node_bytes_(old_node.level());
+            byte_t* new_data = (byte_t*)reordered_tape.allocate(node_bytes);
+            node_t new_node{new_data};
+            std::memcpy(new_data, old_node.tape(), node_bytes);
 
-    struct join_result_t {
-        error_t error{};
-        std::size_t intersection_size{};
-        std::size_t engagements{};
-        std::size_t cycles{};
-        std::size_t measurements{};
+            for (level_t level = 0; level <= old_node.level(); ++level)
+                for (misaligned_ref_gt<compressed_slot_t> neighbor : neighbors_(new_node, level))
+                    neighbor = static_cast<compressed_slot_t>(old_slot_to_new[compressed_slot_t(neighbor)]);
 
-        explicit operator bool() const noexcept { return !error; }
-        join_result_t failed(error_t message) noexcept {
-            error = std::move(message);
-            return std::move(*this);
+            reordered_nodes[new_slot] = new_node;
+
+            progress(new_slot, slots_and_levels.size());
         }
-    };
 
-    /**
-     *  @brief  Adapts the Male-Optimal Stable Marriage algorithm for unequal sets
-     *          to perform fast one-to-one matching between two large collections
-     *          of vectors, using approximate nearest neighbors search.
-     *
-     *  @param[inout] first_to_second Container to map ::first labels to ::second.
-     *  @param[inout] second_to_first Container to map ::second labels to ::first.
-     *  @param[in] executor Thread-pool to execute the job in parallel.
-     *  @param[in] progress Callback to report the execution progress.
-     */
-    template <                                                        //
-        typename first_to_second_at = dummy_label_to_label_mapping_t, //
-        typename second_to_first_at = dummy_label_to_label_mapping_t, //
-        typename executor_at = dummy_executor_t,                      //
-        typename progress_at = dummy_progress_t                       //
-        >
-    static join_result_t join(                                       //
-        index_gt const& first, index_gt const& second,               //
-        join_config_t config = {},                                   //
-        first_to_second_at&& first_to_second = first_to_second_at{}, //
-        second_to_first_at&& second_to_first = second_to_first_at{}, //
-        executor_at&& executor = executor_at{},                      //
-        progress_at&& progress = progress_at{}) noexcept {
+        for (std::size_t new_slot = 0; new_slot != slots_and_levels.size(); ++new_slot) {
+            std::size_t old_slot = slots_and_levels[new_slot].old_slot;
+            slot_transition(node_at_(old_slot).ckey(),                //
+                            static_cast<compressed_slot_t>(old_slot), //
+                            static_cast<compressed_slot_t>(new_slot));
+        }
 
-        if (second.size() < first.size())
-            return join_small_and_big_(                            //
-                second, first,                                     //
-                config,                                            //
-                std::forward<second_to_first_at>(second_to_first), //
-                std::forward<first_to_second_at>(first_to_second), //
-                std::forward<executor_at>(executor),               //
-                std::forward<progress_at>(progress));
-        else
-            return join_small_and_big_(                            //
-                first, second,                                     //
-                config,                                            //
-                std::forward<first_to_second_at>(first_to_second), //
-                std::forward<second_to_first_at>(second_to_first), //
-                std::forward<executor_at>(executor),               //
-                std::forward<progress_at>(progress));
+        nodes_ = std::move(reordered_nodes);
+        tape_allocator_ = std::move(reordered_tape);
+        entry_slot_ = old_slot_to_new[entry_slot_];
     }
 
     /**
@@ -2720,293 +2679,80 @@ class index_gt {
         progress_at&& progress = progress_at{}) noexcept {
 
         // Erase all the incoming links
-        executor.execute_bulk(size(), [&](std::size_t, std::size_t node_idx) {
-            node_t node = node_with_id_(node_idx);
+        std::size_t nodes_count = size();
+        executor.execute_bulk(nodes_count, [&](std::size_t, std::size_t node_idx) {
+            node_t node = node_at_(node_idx);
             for (level_t level = 0; level <= node.level(); ++level) {
                 neighbors_ref_t neighbors = neighbors_(node, level);
                 std::size_t old_size = neighbors.size();
                 neighbors.clear();
                 for (std::size_t i = 0; i != old_size; ++i) {
-                    id_t neighbor_id = neighbors[i];
-                    node_t neighbor = node_with_id_(neighbor_id);
-                    if (allow_member(member_cref_t{neighbor.label(), neighbor.vector_view(), neighbor_id}))
-                        neighbors.push_back(neighbor_id);
+                    compressed_slot_t neighbor_slot = neighbors[i];
+                    node_t neighbor = node_at_(neighbor_slot);
+                    if (allow_member(member_cref_t{neighbor.ckey(), neighbor_slot}))
+                        neighbors.push_back(neighbor_slot);
                 }
             }
+            progress(node_idx, nodes_count);
         });
     }
 
   private:
-    template <typename first_to_second_at, typename second_to_first_at, typename executor_at, typename progress_at>
-    static join_result_t join_small_and_big_(       //
-        index_gt const& men, index_gt const& women, //
-        join_config_t config,                       //
-        first_to_second_at&& man_to_woman,          //
-        second_to_first_at&& woman_to_man,          //
-        executor_at&& executor,                     //
-        progress_at&& progress) noexcept {
-
-        join_result_t result;
-
-        // Sanity checks and argument validation:
-        if (&men == &women)
-            return result.failed("Can't join with itself, consider copying");
-        if (config.max_proposals == 0)
-            config.max_proposals = std::log(men.size()) + executor.size();
-        config.max_proposals = (std::min)(men.size(), config.max_proposals);
-
-        using proposals_count_t = std::uint16_t;
-        using ids_allocator_t = typename allocator_traits_t::template rebind_alloc<id_t>;
-        dynamic_allocator_t& alloc = men.dynamic_allocator_;
-
-        // Create an atomic queue, as a ring structure, from/to which
-        // free men will be added/pulled.
-        std::mutex free_men_mutex{};
-        ring_gt<id_t, ids_allocator_t> free_men;
-        free_men.reserve(men.size());
-        for (std::size_t i = 0; i != men.size(); ++i)
-            free_men.push(static_cast<id_t>(i));
-
-        // We are gonna need some temporary memory.
-        proposals_count_t* proposal_counts = (proposals_count_t*)alloc.allocate(sizeof(proposals_count_t) * men.size());
-        id_t* man_to_woman_ids = (id_t*)alloc.allocate(sizeof(id_t) * men.size());
-        id_t* woman_to_man_ids = (id_t*)alloc.allocate(sizeof(id_t) * women.size());
-        if (!proposal_counts || !man_to_woman_ids || !woman_to_man_ids)
-            return result.failed("Can't temporary mappings");
-
-        id_t missing_id;
-        std::memset((void*)&missing_id, 0xFF, sizeof(id_t));
-        std::memset((void*)man_to_woman_ids, 0xFF, sizeof(id_t) * men.size());
-        std::memset((void*)woman_to_man_ids, 0xFF, sizeof(id_t) * women.size());
-        std::memset(proposal_counts, 0, sizeof(proposals_count_t) * men.size());
-
-        // Define locks, to limit concurrent accesses to `man_to_woman_ids` and `woman_to_man_ids`.
-        visits_bitset_t men_locks, women_locks;
-        if (!men_locks.resize(men.size()) || !women_locks.resize(women.size()))
-            return result.failed("Can't allocate locks");
-
-        // Accumulate statistics from all the contexts,
-        // to have a baseline to compare with, by the time the `join` is finished.
-        std::size_t old_measurements{};
-        std::size_t old_cycles{};
-        for (std::size_t thread_idx = 0; thread_idx != executor.size(); ++thread_idx) {
-            old_measurements += women.contexts_[thread_idx].measurements_count;
-            old_cycles += women.contexts_[thread_idx].iteration_cycles;
-        }
-        std::atomic<std::size_t> rounds{0};
-        std::atomic<std::size_t> engagements{0};
-
-        // Concurrently process all the men
-        executor.execute_bulk([&](std::size_t thread_idx) {
-            context_t& context = women.contexts_[thread_idx];
-            search_config_t search_config;
-            search_config.expansion = config.expansion;
-            search_config.exact = config.exact;
-            search_config.thread = thread_idx;
-            id_t free_man_id;
-
-            // While there exist a free man who still has a woman to propose to.
-            while (true) {
-                std::size_t passed_rounds = 0;
-                std::size_t total_rounds = 0;
-                {
-                    std::unique_lock<std::mutex> pop_lock(free_men_mutex);
-                    if (!free_men.try_pop(free_man_id))
-                        // Primary exit path, we have exhausted the list of candidates
-                        break;
-                    passed_rounds = ++rounds;
-                    total_rounds = passed_rounds + free_men.size();
-                }
-                progress(passed_rounds, total_rounds);
-                while (men_locks.atomic_set(free_man_id))
-                    ;
-
-                node_t free_man = men.node_with_id_(free_man_id);
-                proposals_count_t& free_man_proposals = proposal_counts[free_man_id];
-                if (free_man_proposals >= config.max_proposals)
-                    continue;
-
-                // Find the closest woman, to whom this man hasn't proposed yet.
-                free_man_proposals++;
-                search_result_t candidates = women.search(free_man.vector_view(), free_man_proposals, search_config);
-                if (!candidates) {
-                    // TODO:
-                }
-
-                match_t match = candidates.back();
-                member_cref_t woman = match.member;
-                while (women_locks.atomic_set(woman.id))
-                    ;
-
-                id_t husband_id = woman_to_man_ids[woman.id];
-                bool woman_is_free = husband_id == missing_id;
-                if (woman_is_free) {
-                    // Engagement
-                    man_to_woman_ids[free_man_id] = woman.id;
-                    woman_to_man_ids[woman.id] = free_man_id;
-                    engagements++;
-                } else {
-                    distance_t distance_from_husband = context.measure(woman.vector, men.node_with_id_(husband_id));
-                    distance_t distance_from_candidate = match.distance;
-                    if (distance_from_husband > distance_from_candidate) {
-                        // Break-up
-                        while (men_locks.atomic_set(husband_id))
-                            ;
-                        man_to_woman_ids[husband_id] = missing_id;
-                        men_locks.atomic_reset(husband_id);
-
-                        // New Engagement
-                        man_to_woman_ids[free_man_id] = woman.id;
-                        woman_to_man_ids[woman.id] = free_man_id;
-                        engagements++;
-
-                        std::unique_lock<std::mutex> push_lock(free_men_mutex);
-                        free_men.push(husband_id);
-                    } else {
-                        std::unique_lock<std::mutex> push_lock(free_men_mutex);
-                        free_men.push(free_man_id);
-                    }
-                }
-
-                men_locks.atomic_reset(free_man_id);
-                women_locks.atomic_reset(woman.id);
-            }
-        });
-
-        // Export the IDs into labels:
-        std::size_t intersection_size = 0;
-        for (std::size_t i = 0; i != men.size(); ++i) {
-            id_t woman_id = man_to_woman_ids[i];
-            if (woman_id != missing_id) {
-                label_t man = men.node_with_id_(i).label();
-                label_t woman = women.node_with_id_(woman_id).label();
-                man_to_woman[man] = woman;
-                woman_to_man[woman] = man;
-                intersection_size++;
-            }
-        }
-
-        // Deallocate memory
-        alloc.deallocate((byte_t*)proposal_counts, sizeof(proposals_count_t) * men.size());
-        alloc.deallocate((byte_t*)man_to_woman_ids, sizeof(id_t) * men.size());
-        alloc.deallocate((byte_t*)woman_to_man_ids, sizeof(id_t) * women.size());
-
-        // Export stats
-        result.engagements = engagements;
-        result.intersection_size = intersection_size;
-        for (std::size_t thread_idx = 0; thread_idx != executor.size(); ++thread_idx) {
-            result.measurements += women.contexts_[thread_idx].measurements_count;
-            result.cycles += women.contexts_[thread_idx].iteration_cycles;
-        }
-        result.measurements -= old_measurements;
-        result.cycles -= old_cycles;
-        return result;
-    }
-
-    void reset_view_() noexcept {
-        if (!viewed_file_)
-            return;
-#if defined(USEARCH_DEFINED_WINDOWS)
-        UnmapViewOfFile(viewed_file_.ptr);
-        CloseHandle(viewed_file_.mapping_handle);
-        CloseHandle(viewed_file_.file_handle);
-
-#else
-        munmap(viewed_file_.ptr, viewed_file_.length);
-        close(viewed_file_.file_descriptor);
-#endif
-        viewed_file_ = {};
-    }
-
     inline static precomputed_constants_t precompute_(index_config_t const& config) noexcept {
         precomputed_constants_t pre;
-        pre.connectivity_max_base = config.connectivity * base_level_multiple_();
         pre.inverse_log_connectivity = 1.0 / std::log(static_cast<double>(config.connectivity));
-        pre.neighbors_bytes = config.connectivity * sizeof(id_t) + sizeof(neighbors_count_t);
-        pre.neighbors_base_bytes = pre.connectivity_max_base * sizeof(id_t) + sizeof(neighbors_count_t);
+        pre.neighbors_bytes = config.connectivity * sizeof(compressed_slot_t) + sizeof(neighbors_count_t);
+        pre.neighbors_base_bytes = config.connectivity_base * sizeof(compressed_slot_t) + sizeof(neighbors_count_t);
         return pre;
     }
 
-    inline std::size_t node_bytes_(node_t node) const noexcept { return node_bytes_(node.dim(), node.level()); }
-    inline std::size_t node_bytes_(dim_t dim, level_t level) const noexcept {
-        return node_head_bytes_() + pre_.neighbors_base_bytes + pre_.neighbors_bytes * level + sizeof(scalar_t) * dim;
-    }
-
     using span_bytes_t = span_gt<byte_t>;
-    struct node_bytes_split_t {
-        span_bytes_t tape{};
-        span_bytes_t vector{};
-
-        node_bytes_split_t() {}
-        node_bytes_split_t(span_bytes_t tape, span_bytes_t vector) noexcept : tape(tape), vector(vector) {}
 
-        std::size_t memory_usage() const noexcept { return tape.size() + vector.size(); }
-        bool colocated() const noexcept { return tape.end() == vector.begin(); }
-        operator node_t() const noexcept { return node_t{tape.begin(), reinterpret_cast<scalar_t*>(vector.begin())}; }
-    };
-
-    inline node_bytes_split_t node_bytes_split_(node_t node) const noexcept {
-        std::size_t levels_bytes = pre_.neighbors_base_bytes + pre_.neighbors_bytes * node.level();
-        std::size_t bytes_in_tape = node_head_bytes_() + levels_bytes;
-        return {{node.tape(), bytes_in_tape}, {(byte_t*)node.vector(), node_vector_bytes_(node)}};
+    inline span_bytes_t node_bytes_(node_t node) const noexcept { return {node.tape(), node_bytes_(node.level())}; }
+    inline std::size_t node_bytes_(level_t level) const noexcept {
+        return node_head_bytes_() + node_neighbors_bytes_(level);
+    }
+    inline std::size_t node_neighbors_bytes_(node_t node) const noexcept { return node_neighbors_bytes_(node.level()); }
+    inline std::size_t node_neighbors_bytes_(level_t level) const noexcept {
+        return pre_.neighbors_base_bytes + pre_.neighbors_bytes * level;
     }
 
-    inline std::size_t node_vector_bytes_(dim_t dim) const noexcept { return dim * sizeof(scalar_t); }
-    inline std::size_t node_vector_bytes_(node_t node) const noexcept { return node_vector_bytes_(node.dim()); }
-
-    node_bytes_split_t node_malloc_(dim_t dims_to_store, level_t level) noexcept {
-
-        std::size_t vector_bytes = node_vector_bytes_(dims_to_store);
-        std::size_t node_bytes = node_bytes_(dims_to_store, level);
-        std::size_t non_vector_bytes = node_bytes - vector_bytes;
-
+    span_bytes_t node_malloc_(level_t level) noexcept {
+        std::size_t node_bytes = node_bytes_(level);
         byte_t* data = (byte_t*)tape_allocator_.allocate(node_bytes);
-        if (!data)
-            return node_bytes_split_t{};
-        return {{data, non_vector_bytes}, {data + non_vector_bytes, vector_bytes}};
+        return data ? span_bytes_t{data, node_bytes} : span_bytes_t{};
     }
 
-    node_t node_make_(label_t label, vector_view_t vector, level_t level, bool store_vector) noexcept {
-        node_bytes_split_t node_bytes = node_malloc_(vector.size() * store_vector, level);
-        if (store_vector) {
-            std::memset(node_bytes.tape.data(), 0, node_bytes.tape.size());
-            std::memcpy(node_bytes.vector.data(), vector.data(), node_bytes.vector.size());
-        } else {
-            std::memset(node_bytes.tape.data(), 0, node_bytes.memory_usage());
-        }
-        node_t node = node_bytes;
-        node.label(label);
-        node.dim(static_cast<dim_t>(vector.size()));
+    node_t node_make_(key_t key, level_t level) noexcept {
+        span_bytes_t node_bytes = node_malloc_(level);
+        if (!node_bytes)
+            return {};
+
+        std::memset(node_bytes.data(), 0, node_bytes.size());
+        node_t node{(byte_t*)node_bytes.data()};
+        node.key(key);
         node.level(level);
         return node;
     }
 
-    node_t node_make_copy_(node_bytes_split_t old_bytes) noexcept {
-        if (old_bytes.colocated()) {
-            byte_t* data = (byte_t*)tape_allocator_.allocate(old_bytes.memory_usage());
-            std::memcpy(data, old_bytes.tape.data(), old_bytes.memory_usage());
-            return node_t{data, reinterpret_cast<scalar_t*>(data + old_bytes.tape.size())};
-        } else {
-            node_t old_node = old_bytes;
-            node_bytes_split_t node_bytes = node_malloc_(old_node.vector_view().size(), old_node.level());
-            std::memcpy(node_bytes.tape.data(), old_bytes.tape.data(), old_bytes.tape.size());
-            std::memcpy(node_bytes.vector.data(), old_bytes.vector.data(), old_bytes.vector.size());
-            return node_bytes;
-        }
+    node_t node_make_copy_(span_bytes_t old_bytes) noexcept {
+        byte_t* data = (byte_t*)tape_allocator_.allocate(old_bytes.size());
+        if (!data)
+            return {};
+        std::memcpy(data, old_bytes.data(), old_bytes.size());
+        return node_t{data};
     }
 
-    void node_free_(std::size_t id) noexcept {
-
+    void node_free_(std::size_t idx) noexcept {
         if (viewed_file_)
             return;
 
-        node_t& node = nodes_[id];
-        std::size_t node_bytes = node_bytes_(node) - node_vector_bytes_(node) * !node_bytes_split_(node).colocated();
-        tape_allocator_.deallocate(node.tape(), node_bytes);
+        node_t& node = nodes_[idx];
+        tape_allocator_.deallocate(node.tape(), node_bytes_(node).size());
         node = node_t{};
     }
 
-    inline node_t node_with_id_(std::size_t idx) const noexcept { return nodes_[idx]; }
+    inline node_t node_at_(std::size_t idx) const noexcept { return nodes_[idx]; }
     inline neighbors_ref_t neighbors_base_(node_t node) const noexcept { return {node.neighbors_tape()}; }
 
     inline neighbors_ref_t neighbors_non_base_(node_t node, level_t level) const noexcept {
@@ -3019,91 +2765,102 @@ class index_gt {
 
     struct node_lock_t {
         visits_bitset_t& bitset;
-        std::size_t idx;
-
-        inline ~node_lock_t() noexcept { bitset.atomic_reset(idx); }
+        std::size_t slot;
+        inline ~node_lock_t() noexcept { bitset.atomic_reset(slot); }
     };
 
-    inline node_lock_t node_lock_(std::size_t idx) const noexcept {
-        while (nodes_mutexes_.atomic_set(idx))
+    inline node_lock_t node_lock_(std::size_t slot) const noexcept {
+        while (nodes_mutexes_.atomic_set(slot))
             ;
-        return {nodes_mutexes_, idx};
+        return {nodes_mutexes_, slot};
     }
 
-    void connect_node_across_levels_(                           //
-        id_t node_id, vector_view_t vector,                     //
-        id_t entry_id, level_t max_level, level_t target_level, //
-        add_config_t const& config, context_t& context) usearch_noexcept_m {
+    template <typename value_at, typename metric_at, typename prefetch_at>
+    void connect_node_across_levels_(                                                           //
+        value_at&& value, metric_at&& metric, prefetch_at&& prefetch,                           //
+        std::size_t node_slot, std::size_t entry_slot, level_t max_level, level_t target_level, //
+        index_update_config_t const& config, context_t& context) usearch_noexcept_m {
 
         // Go down the level, tracking only the closest match
-        id_t closest_id = search_for_one_(entry_id, vector, max_level, target_level, context);
+        std::size_t closest_slot = search_for_one_( //
+            value, metric, prefetch,                //
+            entry_slot, max_level, target_level, context);
 
         // From `target_level` down perform proper extensive search
         for (level_t level = (std::min)(target_level, max_level); level >= 0; --level) {
             // TODO: Handle out of memory conditions
-            search_to_insert_(closest_id, vector, level, config.expansion, context);
-            closest_id = connect_new_node_(node_id, level, context);
-            reconnect_neighbor_nodes_(node_id, level, context);
+            search_to_insert_(value, metric, prefetch, closest_slot, node_slot, level, config.expansion, context);
+            closest_slot = connect_new_node_(metric, node_slot, level, context);
+            reconnect_neighbor_nodes_(metric, node_slot, value, level, context);
         }
     }
 
-    id_t connect_new_node_(id_t new_id, level_t level, context_t& context) usearch_noexcept_m {
+    template <typename metric_at>
+    std::size_t connect_new_node_( //
+        metric_at&& metric, std::size_t new_slot, level_t level, context_t& context) usearch_noexcept_m {
 
-        node_t new_node = node_with_id_(new_id);
+        node_t new_node = node_at_(new_slot);
         top_candidates_t& top = context.top_candidates;
 
-        // Outgoing links from `new_id`:
+        // Outgoing links from `new_slot`:
         neighbors_ref_t new_neighbors = neighbors_(new_node, level);
         {
             usearch_assert_m(!new_neighbors.size(), "The newly inserted element should have blank link list");
-            candidates_view_t top_view = refine_(top, config_.connectivity, context);
+            candidates_view_t top_view = refine_(metric, config_.connectivity, top, context);
 
             for (std::size_t idx = 0; idx != top_view.size(); idx++) {
                 usearch_assert_m(!new_neighbors[idx], "Possible memory corruption");
-                usearch_assert_m(level <= node_with_id_(top_view[idx].id).level(), "Linking to missing level");
-                new_neighbors.push_back(top_view[idx].id);
+                usearch_assert_m(level <= node_at_(top_view[idx].slot).level(), "Linking to missing level");
+                new_neighbors.push_back(top_view[idx].slot);
             }
         }
 
         return new_neighbors[0];
     }
 
-    void reconnect_neighbor_nodes_(id_t new_id, level_t level, context_t& context) usearch_noexcept_m {
+    template <typename value_at, typename metric_at>
+    void reconnect_neighbor_nodes_( //
+        metric_at&& metric, std::size_t new_slot, value_at&& value, level_t level,
+        context_t& context) usearch_noexcept_m {
 
-        node_t new_node = node_with_id_(new_id);
+        node_t new_node = node_at_(new_slot);
         top_candidates_t& top = context.top_candidates;
         neighbors_ref_t new_neighbors = neighbors_(new_node, level);
 
         // Reverse links from the neighbors:
-        std::size_t const connectivity_max = level ? config_.connectivity : pre_.connectivity_max_base;
-        for (id_t close_id : new_neighbors) {
-            node_t close_node = node_with_id_(close_id);
-            node_lock_t close_lock = node_lock_(close_id);
+        std::size_t const connectivity_max = level ? config_.connectivity : config_.connectivity_base;
+        for (compressed_slot_t close_slot : new_neighbors) {
+            if (close_slot == new_slot)
+                continue;
+            node_lock_t close_lock = node_lock_(close_slot);
+            node_t close_node = node_at_(close_slot);
 
             neighbors_ref_t close_header = neighbors_(close_node, level);
             usearch_assert_m(close_header.size() <= connectivity_max, "Possible corruption");
-            usearch_assert_m(close_id != new_id, "Self-loops are impossible");
+            usearch_assert_m(close_slot != new_slot, "Self-loops are impossible");
             usearch_assert_m(level <= close_node.level(), "Linking to missing level");
 
-            // If `new_id` is already present in the neighboring connections of `close_id`
+            // If `new_slot` is already present in the neighboring connections of `close_slot`
             // then no need to modify any connections or run the heuristics.
             if (close_header.size() < connectivity_max) {
-                close_header.push_back(new_id);
+                close_header.push_back(static_cast<compressed_slot_t>(new_slot));
                 continue;
             }
 
             // To fit a new connection we need to drop an existing one.
             top.clear();
             usearch_assert_m((top.reserve(close_header.size() + 1)), "The memory must have been reserved in `add`");
-            top.insert_reserved({context.measure(new_node, close_node), new_id});
-            for (id_t successor_id : close_header)
-                top.insert_reserved({context.measure(node_with_id_(successor_id), close_node), successor_id});
+            top.insert_reserved(
+                {context.measure(value, citerator_at(close_slot), metric), static_cast<compressed_slot_t>(new_slot)});
+            for (compressed_slot_t successor_slot : close_header)
+                top.insert_reserved(
+                    {context.measure(citerator_at(close_slot), citerator_at(successor_slot), metric), successor_slot});
 
             // Export the results:
             close_header.clear();
-            candidates_view_t top_view = refine_(top, connectivity_max, context);
+            candidates_view_t top_view = refine_(metric, connectivity_max, top, context);
             for (std::size_t idx = 0; idx != top_view.size(); idx++)
-                close_header.push_back(top_view[idx].id);
+                close_header.push_back(top_view[idx].slot);
         }
     }
 
@@ -3113,31 +2870,105 @@ class index_gt {
         return (level_t)r;
     }
 
-    id_t search_for_one_(                       //
-        id_t closest_id, vector_view_t query,   //
-        level_t begin_level, level_t end_level, //
-        context_t& context) const noexcept {
+    struct candidates_range_t;
+    class candidates_iterator_t {
+        friend struct candidates_range_t;
+
+        index_gt const& index_;
+        neighbors_ref_t neighbors_;
+        visits_bitset_t& visits_;
+        std::size_t current_;
+
+        candidates_iterator_t& skip_missing() noexcept {
+            while (current_ != neighbors_.size()) {
+                compressed_slot_t neighbor_slot = neighbors_[current_];
+                if (visits_.test(neighbor_slot))
+                    current_++;
+                else
+                    break;
+            }
+            return *this;
+        }
+
+      public:
+        using element_t = compressed_slot_t;
+        using iterator_category = std::forward_iterator_tag;
+        using value_type = element_t;
+        using difference_type = std::ptrdiff_t;
+        using pointer = misaligned_ptr_gt<element_t>;
+        using reference = misaligned_ref_gt<element_t>;
+
+        reference operator*() const noexcept { return slot(); }
+        candidates_iterator_t(index_gt const& index, neighbors_ref_t neighbors, visits_bitset_t& visits,
+                              std::size_t progress) noexcept
+            : index_(index), neighbors_(neighbors), visits_(visits), current_(progress) {}
+        candidates_iterator_t operator++(int) noexcept {
+            return candidates_iterator_t(index_, visits_, neighbors_, current_ + 1).skip_missing();
+        }
+        candidates_iterator_t& operator++() noexcept {
+            ++current_;
+            skip_missing();
+            return *this;
+        }
+        bool operator==(candidates_iterator_t const& other) noexcept { return current_ == other.current_; }
+        bool operator!=(candidates_iterator_t const& other) noexcept { return current_ != other.current_; }
+
+        key_t key() const noexcept { return index_->node_at_(slot()).key(); }
+        compressed_slot_t slot() const noexcept { return neighbors_[current_]; }
+        friend inline std::size_t get_slot(candidates_iterator_t const& it) noexcept { return it.slot(); }
+        friend inline key_t get_key(candidates_iterator_t const& it) noexcept { return it.key(); }
+    };
+
+    struct candidates_range_t {
+        index_gt const& index;
+        neighbors_ref_t neighbors;
+        visits_bitset_t& visits;
+
+        candidates_iterator_t begin() const noexcept {
+            return candidates_iterator_t{index, neighbors, visits, 0}.skip_missing();
+        }
+        candidates_iterator_t end() const noexcept { return {index, neighbors, visits, neighbors.size()}; }
+    };
+
+    template <typename value_at, typename metric_at, typename prefetch_at = dummy_prefetch_t>
+    std::size_t search_for_one_(                                      //
+        value_at&& query, metric_at&& metric, prefetch_at&& prefetch, //
+        std::size_t closest_slot, level_t begin_level, level_t end_level, context_t& context) const noexcept {
+
+        visits_bitset_t& visits = context.visits;
+        visits.clear();
 
-        distance_t closest_dist = context.measure(query, node_with_id_(closest_id));
+        // Optional prefetching
+        if (!std::is_same<prefetch_at, dummy_prefetch_t>::value)
+            prefetch(citerator_at(closest_slot), citerator_at(closest_slot + 1));
+
+        distance_t closest_dist = context.measure(query, citerator_at(closest_slot), metric);
         for (level_t level = begin_level; level > end_level; --level) {
             bool changed;
             do {
                 changed = false;
-                node_t closest_node = node_with_id_(closest_id);
-                node_lock_t closest_lock = node_lock_(closest_id);
-                neighbors_ref_t closest_neighbors = neighbors_non_base_(closest_node, level);
-                for (id_t candidate_id : closest_neighbors) {
-                    distance_t candidate_dist = context.measure(query, node_with_id_(candidate_id));
+                node_lock_t closest_lock = node_lock_(closest_slot);
+                neighbors_ref_t closest_neighbors = neighbors_non_base_(node_at_(closest_slot), level);
+
+                // Optional prefetching
+                if (!std::is_same<prefetch_at, dummy_prefetch_t>::value) {
+                    candidates_range_t missing_candidates{*this, closest_neighbors, visits};
+                    prefetch(missing_candidates.begin(), missing_candidates.end());
+                }
+
+                // Actual traversal
+                for (compressed_slot_t candidate_slot : closest_neighbors) {
+                    distance_t candidate_dist = context.measure(query, citerator_at(candidate_slot), metric);
                     if (candidate_dist < closest_dist) {
                         closest_dist = candidate_dist;
-                        closest_id = candidate_id;
+                        closest_slot = candidate_slot;
                         changed = true;
                     }
                 }
                 context.iteration_cycles++;
             } while (changed);
         }
-        return closest_id;
+        return closest_slot;
     }
 
     /**
@@ -3145,8 +2976,11 @@ class index_gt {
      *          Locks the nodes in the process, assuming other threads are updating neighbors lists.
      *  @return `true` if procedure succeeded, `false` if run out of memory.
      */
-    bool search_to_insert_( //
-        id_t start_id, vector_view_t query, level_t level, std::size_t top_limit, context_t& context) noexcept {
+    template <typename value_at, typename metric_at, typename prefetch_at = dummy_prefetch_t>
+    bool search_to_insert_(                                           //
+        value_at&& query, metric_at&& metric, prefetch_at&& prefetch, //
+        std::size_t start_slot, std::size_t new_slot, level_t level, std::size_t top_limit,
+        context_t& context) noexcept {
 
         visits_bitset_t& visits = context.visits;
         next_candidates_t& next = context.next_candidates; // pop min, push
@@ -3156,10 +2990,14 @@ class index_gt {
         next.clear();
         top.clear();
 
-        distance_t radius = context.measure(query, node_with_id_(start_id));
-        next.insert_reserved({-radius, start_id});
-        top.insert_reserved({radius, start_id});
-        visits.set(start_id);
+        // Optional prefetching
+        if (!std::is_same<prefetch_at, dummy_prefetch_t>::value)
+            prefetch(citerator_at(start_slot), citerator_at(start_slot + 1));
+
+        distance_t radius = context.measure(query, citerator_at(start_slot), metric);
+        next.insert_reserved({-radius, static_cast<compressed_slot_t>(start_slot)});
+        top.insert_reserved({radius, static_cast<compressed_slot_t>(start_slot)});
+        visits.set(start_slot);
 
         while (!next.empty()) {
 
@@ -3170,24 +3008,30 @@ class index_gt {
             next.pop();
             context.iteration_cycles++;
 
-            id_t candidate_id = candidacy.id;
-            node_t candidate_ref = node_with_id_(candidate_id);
-            node_lock_t candidate_lock = node_lock_(candidate_id);
+            compressed_slot_t candidate_slot = candidacy.slot;
+            if (new_slot == candidate_slot)
+                continue;
+            node_t candidate_ref = node_at_(candidate_slot);
+            node_lock_t candidate_lock = node_lock_(candidate_slot);
             neighbors_ref_t candidate_neighbors = neighbors_(candidate_ref, level);
 
-            prefetch_neighbors_(candidate_neighbors, visits);
-            for (id_t successor_id : candidate_neighbors) {
-                if (visits.test(successor_id))
-                    continue;
+            // Optional prefetching
+            if (!std::is_same<prefetch_at, dummy_prefetch_t>::value) {
+                candidates_range_t missing_candidates{*this, candidate_neighbors, visits};
+                prefetch(missing_candidates.begin(), missing_candidates.end());
+            }
 
-                visits.set(successor_id);
-                distance_t successor_dist = context.measure(query, node_with_id_(successor_id));
+            for (compressed_slot_t successor_slot : candidate_neighbors) {
+                if (visits.set(successor_slot))
+                    continue;
 
+                // node_lock_t successor_lock = node_lock_(successor_slot);
+                distance_t successor_dist = context.measure(query, citerator_at(successor_slot), metric);
                 if (top.size() < top_limit || successor_dist < radius) {
                     // This can substantially grow our priority queue:
-                    next.insert({-successor_dist, successor_id});
+                    next.insert({-successor_dist, successor_slot});
                     // This will automatically evict poor matches:
-                    top.insert({successor_dist, successor_id}, top_limit);
+                    top.insert({successor_dist, successor_slot}, top_limit);
                     radius = top.top().distance;
                 }
             }
@@ -3200,10 +3044,10 @@ class index_gt {
      *          Doesn't lock any nodes, assuming read-only simultaneous access.
      *  @return `true` if procedure succeeded, `false` if run out of memory.
      */
-    template <typename predicate_at>
-    bool search_to_find_in_base_( //
-        id_t start_id, vector_view_t query, std::size_t expansion, context_t& context,
-        predicate_at&& predicate) const noexcept {
+    template <typename value_at, typename metric_at, typename predicate_at, typename prefetch_at>
+    bool search_to_find_in_base_(                                                               //
+        value_at&& query, metric_at&& metric, predicate_at&& predicate, prefetch_at&& prefetch, //
+        std::size_t start_slot, std::size_t expansion, context_t& context) const noexcept {
 
         visits_bitset_t& visits = context.visits;
         next_candidates_t& next = context.next_candidates; // pop min, push
@@ -3214,10 +3058,14 @@ class index_gt {
         next.clear();
         top.clear();
 
-        distance_t radius = context.measure(query, node_with_id_(start_id));
-        next.insert_reserved({-radius, start_id});
-        top.insert_reserved({radius, start_id});
-        visits.set(start_id);
+        // Optional prefetching
+        if (!std::is_same<prefetch_at, dummy_prefetch_t>::value)
+            prefetch(citerator_at(start_slot), citerator_at(start_slot + 1));
+
+        distance_t radius = context.measure(query, citerator_at(start_slot), metric);
+        next.insert_reserved({-radius, static_cast<compressed_slot_t>(start_slot)});
+        top.insert_reserved({radius, static_cast<compressed_slot_t>(start_slot)});
+        visits.set(start_slot);
 
         while (!next.empty()) {
 
@@ -3228,28 +3076,29 @@ class index_gt {
             next.pop();
             context.iteration_cycles++;
 
-            id_t candidate_id = candidate.id;
-            neighbors_ref_t candidate_neighbors = neighbors_base_(node_with_id_(candidate_id));
+            neighbors_ref_t candidate_neighbors = neighbors_base_(node_at_(candidate.slot));
 
-            prefetch_neighbors_(candidate_neighbors, visits);
-            for (id_t successor_id : candidate_neighbors) {
-                if (visits.test(successor_id))
-                    continue;
+            // Optional prefetching
+            if (!std::is_same<prefetch_at, dummy_prefetch_t>::value) {
+                candidates_range_t missing_candidates{*this, candidate_neighbors, visits};
+                prefetch(missing_candidates.begin(), missing_candidates.end());
+            }
 
-                visits.set(successor_id);
-                node_t successor = node_with_id_(successor_id);
-                distance_t successor_dist = context.measure(query, successor);
+            for (compressed_slot_t successor_slot : candidate_neighbors) {
+                if (visits.set(successor_slot))
+                    continue;
 
+                distance_t successor_dist = context.measure(query, citerator_at(successor_slot), metric);
                 if (top.size() < top_limit || successor_dist < radius) {
                     // This can substantially grow our priority queue:
-                    next.insert({-successor_dist, successor_id});
-                    if (predicate( //
-                            match_t{member_cref_t{successor.label(), successor.vector_view(), successor_id},
-                                    successor_dist})) {
-                        // This will automatically evict poor matches:
-                        top.insert({successor_dist, successor_id}, top_limit);
-                        radius = top.top().distance;
-                    }
+                    next.insert({-successor_dist, successor_slot});
+                    if (!is_dummy<predicate_at>())
+                        if (!predicate(member_cref_t{node_at_(successor_slot).ckey(), successor_slot}))
+                            continue;
+
+                    // This will automatically evict poor matches:
+                    top.insert({successor_dist, successor_slot}, top_limit);
+                    radius = top.top().distance;
                 }
             }
         }
@@ -3258,33 +3107,35 @@ class index_gt {
     }
 
     /**
-     *  @brief  Iterates through all managed vectors, without actually touching the index.
+     *  @brief  Iterates through all members, without actually touching the index.
      */
-    template <typename predicate_at>
-    void search_exact_(                                             //
-        vector_view_t query, std::size_t count, context_t& context, //
-        predicate_at&& predicate) const noexcept {
+    template <typename value_at, typename metric_at, typename predicate_at>
+    void search_exact_(                                                 //
+        value_at&& query, metric_at&& metric, predicate_at&& predicate, //
+        std::size_t count, context_t& context) const noexcept {
 
         top_candidates_t& top = context.top_candidates;
         top.clear();
         top.reserve(count);
         for (std::size_t i = 0; i != size(); ++i) {
-            id_t id = static_cast<id_t>(i);
-            node_t node = node_with_id_(i);
-            distance_t distance = context.measure(query, node);
-            if (predicate(match_t{member_cref_t{node.label(), node.vector_view(), id}, distance}))
-                top.insert(candidate_t{distance, id}, count);
+            if (!is_dummy<predicate_at>())
+                if (!predicate(at(i)))
+                    continue;
+
+            distance_t distance = context.measure(query, citerator_at(i), metric);
+            top.insert(candidate_t{distance, static_cast<compressed_slot_t>(i)}, count);
         }
     }
 
-    void prefetch_neighbors_(neighbors_ref_t, visits_bitset_t const&) const noexcept {}
-
     /**
      *  @brief  This algorithm from the original paper implements a heuristic,
      *          that massively reduces the number of connections a point has,
      *          to keep only the neighbors, that are from each other.
      */
-    candidates_view_t refine_(top_candidates_t& top, std::size_t needed, context_t& context) const noexcept {
+    template <typename metric_at>
+    candidates_view_t refine_( //
+        metric_at&& metric,    //
+        std::size_t needed, top_candidates_t& top, context_t& context) const noexcept {
 
         top.sort_ascending();
         candidate_t* top_data = top.data();
@@ -3296,14 +3147,14 @@ class index_gt {
         std::size_t consumed_count = 1; /// Always equal or greater than `submitted_count`.
         while (submitted_count < needed && consumed_count < top_count) {
             candidate_t candidate = top_data[consumed_count];
-            node_t candidate_ref = node_with_id_(candidate.id);
-            distance_t candidate_dist = candidate.distance;
             bool good = true;
             for (std::size_t idx = 0; idx < submitted_count; idx++) {
                 candidate_t submitted = top_data[idx];
-                node_t submitted_node = node_with_id_(submitted.id);
-                distance_t inter_result_dist = context.measure(submitted_node, candidate_ref);
-                if (inter_result_dist < candidate_dist) {
+                distance_t inter_result_dist = context.measure( //
+                    citerator_at(candidate.slot),               //
+                    citerator_at(submitted.slot),               //
+                    metric);
+                if (inter_result_dist < candidate.distance) {
                     good = false;
                     break;
                 }
@@ -3321,44 +3172,218 @@ class index_gt {
     }
 };
 
+struct join_result_t {
+    error_t error{};
+    std::size_t intersection_size{};
+    std::size_t engagements{};
+    std::size_t visited_members{};
+    std::size_t computed_distances{};
+
+    explicit operator bool() const noexcept { return !error; }
+    join_result_t failed(error_t message) noexcept {
+        error = std::move(message);
+        return std::move(*this);
+    }
+};
+
 /**
- *  @brief  Extracts metadata from pre-constructed index on disk, without loading it
- *          or mapping the whole binary file.
+ *  @brief  Adapts the Male-Optimal Stable Marriage algorithm for unequal sets
+ *          to perform fast one-to-one matching between two large collections
+ *          of vectors, using approximate nearest neighbors search.
+ *
+ *  @param[inout] man_to_woman Container to map ::first keys to ::second.
+ *  @param[inout] woman_to_man Container to map ::second keys to ::first.
+ *  @param[in] executor Thread-pool to execute the job in parallel.
+ *  @param[in] progress Callback to report the execution progress.
  */
-inline file_head_result_t index_metadata(char const* file_path) noexcept {
-
-    file_head_result_t result;
-    file_header_t state_buffer{};
-    std::FILE* file = std::fopen(file_path, "rb");
-    if (!file)
-        return result.failed(std::strerror(errno));
-
-    // Read the header
-    std::size_t read = std::fread(&state_buffer[0], sizeof(file_header_t), 1, file);
-    std::fclose(file);
-    if (!read)
-        return result.failed(std::strerror(errno));
-
-    // Parse and validate the MIME type
-    file_head_t state{state_buffer};
-    if (std::strncmp(state.magic, default_magic(), std::strlen(default_magic())) != 0)
-        return result.failed("Wrong MIME type!");
-
-    result.version_major = state.version_major;
-    result.version_minor = state.version_minor;
-    result.version_patch = state.version_patch;
-    result.metric = state.metric;
-    result.connectivity = state.connectivity;
-    result.max_level = state.max_level;
-    result.vector_alignment = state.vector_alignment;
-    result.bytes_per_label = state.bytes_per_label;
-    result.bytes_per_id = state.bytes_per_id;
-    result.scalar_kind = state.scalar_kind;
-    result.size = state.size;
-    result.entry_idx = state.entry_idx;
-    result.bytes_for_graphs = state.bytes_for_graphs;
-    result.bytes_for_vectors = state.bytes_for_vectors;
-    result.bytes_checksum = state.bytes_checksum;
+template < //
+
+    typename men_at,          //
+    typename women_at,        //
+    typename men_values_at,   //
+    typename women_values_at, //
+    typename men_metric_at,   //
+    typename women_metric_at, //
+
+    typename man_to_woman_at = dummy_label_to_label_mapping_t, //
+    typename woman_to_man_at = dummy_label_to_label_mapping_t, //
+    typename executor_at = dummy_executor_t,                   //
+    typename progress_at = dummy_progress_t                    //
+    >
+static join_result_t join(               //
+    men_at const& men,                   //
+    women_at const& women,               //
+    men_values_at const& men_values,     //
+    women_values_at const& women_values, //
+    men_metric_at&& men_metric,          //
+    women_metric_at&& women_metric,      //
+
+    index_join_config_t config = {},                    //
+    man_to_woman_at&& man_to_woman = man_to_woman_at{}, //
+    woman_to_man_at&& woman_to_man = woman_to_man_at{}, //
+    executor_at&& executor = executor_at{},             //
+    progress_at&& progress = progress_at{}) noexcept {
+
+    if (women.size() < men.size())
+        return unum::usearch::join(                                                               //
+            women, men,                                                                           //
+            women_values, men_values,                                                             //
+            std::forward<women_metric_at>(women_metric), std::forward<men_metric_at>(men_metric), //
+
+            config,                                      //
+            std::forward<woman_to_man_at>(woman_to_man), //
+            std::forward<man_to_woman_at>(man_to_woman), //
+            std::forward<executor_at>(executor),         //
+            std::forward<progress_at>(progress));
+
+    join_result_t result;
+
+    // Sanity checks and argument validation:
+    if (&men == &women)
+        return result.failed("Can't join with itself, consider copying");
+
+    if (config.max_proposals == 0)
+        config.max_proposals = std::log(men.size()) + executor.size();
+
+    using proposals_count_t = std::uint16_t;
+    config.max_proposals = (std::min)(men.size(), config.max_proposals);
+
+    using distance_t = typename men_at::distance_t;
+    using dynamic_allocator_traits_t = typename men_at::dynamic_allocator_traits_t;
+    using man_key_t = typename men_at::key_t;
+    using woman_key_t = typename women_at::key_t;
+
+    // Use the `compressed_slot_t` type of the larger collection
+    using compressed_slot_t = typename women_at::compressed_slot_t;
+    using compressed_slot_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<compressed_slot_t>;
+    using proposals_count_allocator_t = typename dynamic_allocator_traits_t::template rebind_alloc<proposals_count_t>;
+
+    // Create an atomic queue, as a ring structure, from/to which
+    // free men will be added/pulled.
+    std::mutex free_men_mutex{};
+    ring_gt<compressed_slot_t, compressed_slot_allocator_t> free_men;
+    free_men.reserve(men.size());
+    for (std::size_t i = 0; i != men.size(); ++i)
+        free_men.push(static_cast<compressed_slot_t>(i));
+
+    // We are gonna need some temporary memory.
+    buffer_gt<proposals_count_t, proposals_count_allocator_t> proposal_counts(men.size());
+    buffer_gt<compressed_slot_t, compressed_slot_allocator_t> man_to_woman_slots(men.size());
+    buffer_gt<compressed_slot_t, compressed_slot_allocator_t> woman_to_man_slots(women.size());
+    if (!proposal_counts || !man_to_woman_slots || !woman_to_man_slots)
+        return result.failed("Can't temporary mappings");
+
+    compressed_slot_t missing_slot;
+    std::memset((void*)&missing_slot, 0xFF, sizeof(compressed_slot_t));
+    std::memset((void*)man_to_woman_slots.data(), 0xFF, sizeof(compressed_slot_t) * men.size());
+    std::memset((void*)woman_to_man_slots.data(), 0xFF, sizeof(compressed_slot_t) * women.size());
+    std::memset(proposal_counts.data(), 0, sizeof(proposals_count_t) * men.size());
+
+    // Define locks, to limit concurrent accesses to `man_to_woman_slots` and `woman_to_man_slots`.
+    visits_bitset_t men_locks(men.size()), women_locks(women.size());
+    if (!men_locks || !women_locks)
+        return result.failed("Can't allocate locks");
+
+    std::atomic<std::size_t> rounds{0};
+    std::atomic<std::size_t> engagements{0};
+    std::atomic<std::size_t> computed_distances{0};
+    std::atomic<std::size_t> visited_members{0};
+
+    // Concurrently process all the men
+    executor.execute_bulk([&](std::size_t thread_idx) {
+        index_search_config_t search_config;
+        search_config.expansion = config.expansion;
+        search_config.exact = config.exact;
+        search_config.thread = thread_idx;
+        compressed_slot_t free_man_slot;
+
+        // While there exist a free man who still has a woman to propose to.
+        while (true) {
+            std::size_t passed_rounds = 0;
+            std::size_t total_rounds = 0;
+            {
+                std::unique_lock<std::mutex> pop_lock(free_men_mutex);
+                if (!free_men.try_pop(free_man_slot))
+                    // Primary exit path, we have exhausted the list of candidates
+                    break;
+                passed_rounds = ++rounds;
+                total_rounds = passed_rounds + free_men.size();
+            }
+            progress(passed_rounds, total_rounds);
+            while (men_locks.atomic_set(free_man_slot))
+                ;
+
+            proposals_count_t& free_man_proposals = proposal_counts[free_man_slot];
+            if (free_man_proposals >= config.max_proposals)
+                continue;
+
+            // Find the closest woman, to whom this man hasn't proposed yet.
+            ++free_man_proposals;
+            auto candidates = women.search(men_values[free_man_slot], free_man_proposals, women_metric, search_config);
+            visited_members += candidates.visited_members;
+            computed_distances += candidates.computed_distances;
+            if (!candidates) {
+                // TODO:
+            }
+
+            auto match = candidates.back();
+            auto woman = match.member;
+            while (women_locks.atomic_set(woman.slot))
+                ;
+
+            compressed_slot_t husband_slot = woman_to_man_slots[woman.slot];
+            bool woman_is_free = husband_slot == missing_slot;
+            if (woman_is_free) {
+                // Engagement
+                man_to_woman_slots[free_man_slot] = woman.slot;
+                woman_to_man_slots[woman.slot] = free_man_slot;
+                engagements++;
+            } else {
+                distance_t distance_from_husband = women_metric(women_values[woman.slot], men_values[husband_slot]);
+                distance_t distance_from_candidate = match.distance;
+                if (distance_from_husband > distance_from_candidate) {
+                    // Break-up
+                    while (men_locks.atomic_set(husband_slot))
+                        ;
+                    man_to_woman_slots[husband_slot] = missing_slot;
+                    men_locks.atomic_reset(husband_slot);
+
+                    // New Engagement
+                    man_to_woman_slots[free_man_slot] = woman.slot;
+                    woman_to_man_slots[woman.slot] = free_man_slot;
+                    engagements++;
+
+                    std::unique_lock<std::mutex> push_lock(free_men_mutex);
+                    free_men.push(husband_slot);
+                } else {
+                    std::unique_lock<std::mutex> push_lock(free_men_mutex);
+                    free_men.push(free_man_slot);
+                }
+            }
+
+            men_locks.atomic_reset(free_man_slot);
+            women_locks.atomic_reset(woman.slot);
+        }
+    });
+
+    // Export the "slots" into keys:
+    std::size_t intersection_size = 0;
+    for (std::size_t man_slot = 0; man_slot != men.size(); ++man_slot) {
+        compressed_slot_t woman_slot = man_to_woman_slots[man_slot];
+        if (woman_slot != missing_slot) {
+            man_key_t man = men.at(man_slot).key;
+            woman_key_t woman = women.at(woman_slot).key;
+            man_to_woman[man] = woman;
+            woman_to_man[woman] = man;
+            intersection_size++;
+        }
+    }
+
+    // Export stats
+    result.engagements = engagements;
+    result.intersection_size = intersection_size;
+    result.computed_distances = computed_distances;
+    result.visited_members = visited_members;
     return result;
 }
 
diff --git a/include/usearch/index_dense.hpp b/include/usearch/index_dense.hpp
new file mode 100644
index 00000000..38c0ab23
--- /dev/null
+++ b/include/usearch/index_dense.hpp
@@ -0,0 +1,1400 @@
+#pragma once
+#include <stdlib.h> // `aligned_alloc`
+
+#include <functional>   // `std::function`
+#include <numeric>      // `std::iota`
+#include <shared_mutex> // `std::shared_mutex`
+#include <thread>       // `std::thread`
+#include <vector>       // `std::vector`
+
+#include <usearch/index.hpp>
+#include <usearch/index_plugins.hpp>
+
+#include <tsl/robin_set.h>
+
+namespace unum {
+namespace usearch {
+
+template <typename, typename> class index_dense_gt;
+
+// clang-format off
+template <typename key_at, typename std::enable_if<std::is_integral<key_at>::value>::type* = nullptr> key_at default_free_value() { return std::numeric_limits<key_at>::max(); }
+template <typename key_at, typename std::enable_if<std::is_same<key_at, uint40_t>::value>::type* = nullptr> uint40_t default_free_value() { return uint40_t::max(); }
+template <typename key_at, typename std::enable_if<!std::is_integral<key_at>::value && !std::is_same<key_at, uint40_t>::value>::type* = nullptr> key_at default_free_value() { return key_at(); }
+// clang-format on
+
+/**
+ *  @brief  The "magic" sequence helps infer the type of the file.
+ *          USearch indexes start with the "usearch" string.
+ */
+constexpr char const* default_magic() { return "usearch"; }
+
+using index_dense_head_buffer_t = byte_t[64];
+
+static_assert(sizeof(index_dense_head_buffer_t) == 64, "File header should be exactly 64 bytes");
+
+/**
+ *  @brief  Serialized binary representations of the USearch index start with metadata.
+ *          Metadata is parsed into a `index_dense_head_t`, containing the USearch package version,
+ *          and the properties of the index.
+ *
+ *  It uses: 13 bytes for file versioning, 22 bytes for structural information = 35 bytes.
+ *  The following 24 bytes contain binary size of the graph, of the vectors, and the checksum,
+ *  leaving 5 bytes at the end vacant.
+ */
+struct index_dense_head_t {
+
+    // Versioning:
+    using magic_t = char[7];
+    using version_t = std::uint16_t;
+
+    // Versioning: 7 + 2 * 3 = 13 bytes
+    char const* magic;
+    misaligned_ref_gt<version_t> version_major;
+    misaligned_ref_gt<version_t> version_minor;
+    misaligned_ref_gt<version_t> version_patch;
+
+    // Structural: 4 * 3 = 12 bytes
+    misaligned_ref_gt<metric_kind_t> kind_metric;
+    misaligned_ref_gt<scalar_kind_t> kind_scalar;
+    misaligned_ref_gt<scalar_kind_t> kind_key;
+    misaligned_ref_gt<scalar_kind_t> kind_compressed_slot;
+
+    // Population: 8 * 3 = 24 bytes
+    misaligned_ref_gt<std::uint64_t> count_present;
+    misaligned_ref_gt<std::uint64_t> count_deleted;
+    misaligned_ref_gt<std::uint64_t> dimensions;
+
+    index_dense_head_t(byte_t* ptr) noexcept
+        : magic((char const*)exchange(ptr, ptr + sizeof(magic_t))), //
+          version_major(exchange(ptr, ptr + sizeof(version_t))),    //
+          version_minor(exchange(ptr, ptr + sizeof(version_t))),    //
+          version_patch(exchange(ptr, ptr + sizeof(version_t))),    //
+          kind_metric(exchange(ptr, ptr + sizeof(metric_kind_t))),  //
+          kind_scalar(exchange(ptr, ptr + sizeof(scalar_kind_t))),  //
+          kind_key(exchange(ptr, ptr + sizeof(scalar_kind_t))),     //
+          kind_compressed_slot(exchange(ptr, ptr + sizeof(scalar_kind_t))),
+          count_present(exchange(ptr, ptr + sizeof(std::uint64_t))),
+          count_deleted(exchange(ptr, ptr + sizeof(std::uint64_t))),
+          dimensions(exchange(ptr, ptr + sizeof(std::uint64_t))) {}
+};
+
+struct index_dense_head_result_t {
+
+    index_dense_head_buffer_t buffer;
+    index_dense_head_t head;
+    error_t error;
+
+    explicit operator bool() const noexcept { return !error; }
+    index_dense_head_result_t failed(error_t message) noexcept {
+        error = std::move(message);
+        return std::move(*this);
+    }
+};
+
+struct index_dense_config_t : public index_config_t {
+    std::size_t expansion_add = default_expansion_add();
+    std::size_t expansion_search = default_expansion_search();
+    bool exclude_vectors = false;
+    bool allow_key_collisions = false;
+
+    index_dense_config_t(index_config_t base) noexcept : index_config_t(base) {}
+
+    index_dense_config_t(                                  //
+        std::size_t connectivity = default_connectivity(), //
+        std::size_t expansion_add = default_expansion_add(),
+        std::size_t expansion_search = default_expansion_search()) noexcept
+        : index_config_t(connectivity), //
+          expansion_add(expansion_add ? expansion_add : default_expansion_add()),
+          expansion_search(expansion_search ? expansion_search : default_expansion_search()) {}
+};
+
+struct index_dense_serialization_config_t {
+    bool exclude_vectors = false;
+    bool use_64_bit_dimensions = false;
+};
+
+struct index_dense_update_config_t : public index_update_config_t {
+    bool force_vector_copy = false;
+
+    index_dense_update_config_t() = default;
+    index_dense_update_config_t(index_update_config_t base) noexcept : index_update_config_t(base) {}
+};
+
+struct index_dense_copy_config_t : public index_copy_config_t {
+    bool force_vector_copy = true;
+
+    index_dense_copy_config_t() = default;
+    index_dense_copy_config_t(index_copy_config_t base) noexcept : index_copy_config_t(base) {}
+};
+
+struct index_dense_metadata_result_t {
+    index_dense_serialization_config_t config;
+    index_dense_head_buffer_t head_buffer;
+    index_dense_head_t head;
+    error_t error;
+
+    explicit operator bool() const noexcept { return !error; }
+    index_dense_metadata_result_t failed(error_t message) noexcept {
+        error = std::move(message);
+        return std::move(*this);
+    }
+
+    index_dense_metadata_result_t() noexcept : config(), head_buffer(), head(head_buffer), error() {}
+
+    index_dense_metadata_result_t(index_dense_metadata_result_t&& other) noexcept
+        : config(), head_buffer(), head(head_buffer), error(std::move(other.error)) {
+        std::memcpy(&config, &other.config, sizeof(other.config));
+        std::memcpy(&head_buffer, &other.head_buffer, sizeof(other.head_buffer));
+    }
+
+    index_dense_metadata_result_t& operator=(index_dense_metadata_result_t&& other) noexcept {
+        std::memcpy(&config, &other.config, sizeof(other.config));
+        std::memcpy(&head_buffer, &other.head_buffer, sizeof(other.head_buffer));
+        error = std::move(other.error);
+        return *this;
+    }
+};
+
+/**
+ *  @brief  Extracts metadata from pre-constructed index on disk,
+ *          without loading it or mapping the whole binary file.
+ */
+inline index_dense_metadata_result_t index_dense_metadata(char const* file_path) noexcept {
+    index_dense_metadata_result_t result;
+    std::unique_ptr<std::FILE, int (*)(std::FILE*)> file(std::fopen(file_path, "rb"), &std::fclose);
+    if (!file)
+        return result.failed(std::strerror(errno));
+
+    // Read the header
+    std::size_t read = std::fread(result.head_buffer, sizeof(index_dense_head_buffer_t), 1, file.get());
+    if (!read)
+        return result.failed(std::feof(file.get()) ? "End of file reached!" : std::strerror(errno));
+
+    // Check if the file immediately starts with the index, instead of vectors
+    result.config.exclude_vectors = true;
+    if (std::memcmp(result.head_buffer, default_magic(), std::strlen(default_magic())) == 0)
+        return result;
+
+    if (std::fseek(file.get(), 0L, SEEK_END) != 0)
+        return result.failed("Can't infer file size");
+
+    // Check if it starts with 32-bit
+    std::size_t const file_size = std::ftell(file.get());
+
+    std::uint32_t dimensions_u32[2]{0};
+    std::memcpy(dimensions_u32, result.head_buffer, sizeof(dimensions_u32));
+    std::size_t offset_if_u32 = std::size_t(dimensions_u32[0]) * dimensions_u32[1] + sizeof(dimensions_u32);
+
+    std::uint64_t dimensions_u64[2]{0};
+    std::memcpy(dimensions_u64, result.head_buffer, sizeof(dimensions_u64));
+    std::size_t offset_if_u64 = std::size_t(dimensions_u64[0]) * dimensions_u64[1] + sizeof(dimensions_u64);
+
+    // Check if it starts with 32-bit
+    if (offset_if_u32 + sizeof(index_dense_head_buffer_t) < file_size) {
+        if (std::fseek(file.get(), offset_if_u32, SEEK_SET) != 0)
+            return result.failed(std::strerror(errno));
+        read = std::fread(result.head_buffer, sizeof(index_dense_head_buffer_t), 1, file.get());
+        if (!read)
+            return result.failed(std::feof(file.get()) ? "End of file reached!" : std::strerror(errno));
+
+        result.config.exclude_vectors = false;
+        result.config.use_64_bit_dimensions = false;
+        if (std::memcmp(result.head_buffer, default_magic(), std::strlen(default_magic())) == 0)
+            return result;
+    }
+
+    // Check if it starts with 64-bit
+    if (offset_if_u64 + sizeof(index_dense_head_buffer_t) < file_size) {
+        if (std::fseek(file.get(), offset_if_u64, SEEK_SET) != 0)
+            return result.failed(std::strerror(errno));
+        read = std::fread(result.head_buffer, sizeof(index_dense_head_buffer_t), 1, file.get());
+        if (!read)
+            return result.failed(std::feof(file.get()) ? "End of file reached!" : std::strerror(errno));
+
+        // Check if it starts with 64-bit
+        result.config.exclude_vectors = false;
+        result.config.use_64_bit_dimensions = true;
+        if (std::memcmp(result.head_buffer, default_magic(), std::strlen(default_magic())) == 0)
+            return result;
+    }
+
+    return result.failed("Not a dense USearch index!");
+}
+
+/**
+ *  @brief  Oversimplified type-punned index for equidimensional vectors
+ *          with automatic @b down-casting, hardware-specific @b SIMD metrics,
+ *          and ability to @b remove existing vectors, common in Semantic Caching
+ *          applications.
+ *
+ *  @section Serialization
+ *
+ *  The serialized binary form of `index_dense_gt` is made up of three parts:
+ *      1. Binary matrix, aka the `.bbin` part,
+ *      2. Metadata about used metrics, number of used vs free slots,
+ *      3. The HNSW index in a binary form.
+ *  The first (1.) generally starts with 2 integers - number of rows (vectors) and @b single-byte columns.
+ *  The second (2.) starts with @b "usearch"-magic-string, used to infer the file type on open.
+ *  The third (3.) is implemented by the underlying `index_gt` class.
+ */
+template <typename key_at = default_key_t, typename compressed_slot_at = default_slot_t> //
+class index_dense_gt {
+  public:
+    using key_t = key_at;
+    using compressed_slot_t = compressed_slot_at;
+    using distance_t = distance_punned_t;
+    using metric_t = metric_punned_t;
+
+    using member_ref_t = member_ref_gt<key_t>;
+    using member_cref_t = member_cref_gt<key_t>;
+
+    using head_t = index_dense_head_t;
+    using head_buffer_t = index_dense_head_buffer_t;
+    using head_result_t = index_dense_head_result_t;
+
+    using serialization_config_t = index_dense_serialization_config_t;
+
+  private:
+    /// @brief Schema: input buffer, bytes in input buffer, output buffer.
+    using cast_t = std::function<bool(byte_t const*, std::size_t, byte_t*)>;
+    /// @brief Punned index.
+    using index_t = index_gt<                 //
+        distance_t, key_t, compressed_slot_t, //
+        aligned_allocator_gt<byte_t, 64>, memory_mapping_allocator_gt<64>>;
+    using index_allocator_t = aligned_allocator_gt<index_t, 64>;
+
+    using member_iterator_t = typename index_t::member_iterator_t;
+    using member_citerator_t = typename index_t::member_citerator_t;
+
+    /// @brief Punned metric object.
+    class metric_proxy_t {
+        index_dense_gt const* index_ = nullptr;
+
+      public:
+        metric_proxy_t(index_dense_gt const& index) noexcept : index_(&index) {}
+
+        inline distance_t operator()(byte_t const* a, member_cref_t b) const noexcept { return f(a, v(b)); }
+        inline distance_t operator()(member_cref_t a, member_cref_t b) const noexcept { return f(v(a), v(b)); }
+
+        inline distance_t operator()(byte_t const* a, member_citerator_t b) const noexcept { return f(a, v(b)); }
+        inline distance_t operator()(member_citerator_t a, member_citerator_t b) const noexcept {
+            return f(v(a), v(b));
+        }
+
+        inline distance_t operator()(byte_t const* a, byte_t const* b) const noexcept { return f(a, b); }
+
+        inline byte_t const* v(member_cref_t m) const noexcept { return index_->vectors_lookup_[get_slot(m)]; }
+        inline byte_t const* v(member_citerator_t m) const noexcept { return index_->vectors_lookup_[get_slot(m)]; }
+        inline distance_t f(byte_t const* a, byte_t const* b) const noexcept { return index_->metric_(a, b); }
+    };
+
+    index_dense_config_t config_;
+    index_t* typed_ = nullptr;
+
+    mutable std::vector<byte_t> cast_buffer_;
+    struct casts_t {
+        cast_t from_b1x8;
+        cast_t from_i8;
+        cast_t from_f16;
+        cast_t from_f32;
+        cast_t from_f64;
+
+        cast_t to_b1x8;
+        cast_t to_i8;
+        cast_t to_f16;
+        cast_t to_f32;
+        cast_t to_f64;
+    } casts_;
+
+    /// @brief An instance of a potentially stateful `metric_t` used to initialize copies and forks.
+    metric_t metric_;
+
+    using vectors_tape_allocator_t = memory_mapping_allocator_gt<8>;
+    /// @brief Allocator for the copied vectors, aligned to widest double-precision scalars.
+    vectors_tape_allocator_t vectors_tape_allocator_;
+
+    /// @brief For every managed `compressed_slot_t` stores a pointer to the allocated vector copy.
+    mutable std::vector<byte_t*> vectors_lookup_;
+
+    /// @brief Originally forms and array of integers [0, threads], marking all
+    mutable std::vector<std::size_t> available_threads_;
+
+    /// @brief Mutex, controlling concurrent access to `available_threads_`.
+    mutable std::mutex available_threads_mutex_;
+
+    using shared_mutex_t = std::mutex; // TODO: Find an OS-compatible solution
+    using shared_lock_t = std::unique_lock<shared_mutex_t>;
+    using unique_lock_t = std::unique_lock<shared_mutex_t>;
+
+    struct key_and_slot_t {
+        key_t key;
+        compressed_slot_t slot;
+    };
+
+    struct lookup_key_hash_t {
+        using is_transparent = void;
+        std::size_t operator()(key_and_slot_t const& k) const noexcept { return std::hash<key_t>{}(k.key); }
+        std::size_t operator()(key_t const& k) const noexcept { return std::hash<key_t>{}(k); }
+    };
+
+    struct lookup_key_same_t {
+        using is_transparent = void;
+        bool operator()(key_and_slot_t const& a, key_t const& b) const noexcept { return a.key == b; }
+        bool operator()(key_t const& a, key_and_slot_t const& b) const noexcept { return a == b.key; }
+        bool operator()(key_and_slot_t const& a, key_and_slot_t const& b) const noexcept {
+            return a.key == b.key && a.slot == b.slot;
+        }
+    };
+
+    /// @brief Multi-Map from keys to IDs, and allocated vectors.
+    tsl::robin_set<key_and_slot_t, lookup_key_hash_t, lookup_key_same_t> slot_lookup_;
+
+    /// @brief Mutex, controlling concurrent access to `slot_lookup_`.
+    mutable shared_mutex_t slot_lookup_mutex_;
+
+    /// @brief Ring-shaped queue of deleted entries, to be reused on future insertions.
+    ring_gt<compressed_slot_t> free_keys_;
+
+    /// @brief Mutex, controlling concurrent access to `free_keys_`.
+    mutable std::mutex free_keys_mutex_;
+
+    /// @brief A constant for the reserved key value, used to mark deleted entries.
+    key_t free_key_ = default_free_value<key_t>();
+
+  public:
+    using search_result_t = typename index_t::search_result_t;
+    using add_result_t = typename index_t::add_result_t;
+    using stats_t = typename index_t::stats_t;
+    using match_t = typename index_t::match_t;
+
+    index_dense_gt() = default;
+    index_dense_gt(index_dense_gt&& other)
+        : config_(std::move(other.config_)),
+
+          typed_(exchange(other.typed_, nullptr)),     //
+          cast_buffer_(std::move(other.cast_buffer_)), //
+          casts_(std::move(other.casts_)),             //
+          metric_(std::move(other.metric_)),           //
+
+          vectors_tape_allocator_(std::move(other.vectors_tape_allocator_)), //
+          vectors_lookup_(std::move(other.vectors_lookup_)),                 //
+
+          available_threads_(std::move(other.available_threads_)), //
+          slot_lookup_(std::move(other.slot_lookup_)),             //
+          free_keys_(std::move(other.free_keys_)),                 //
+          free_key_(std::move(other.free_key_)) {}                 //
+
+    index_dense_gt& operator=(index_dense_gt&& other) {
+        swap(other);
+        return *this;
+    }
+
+    /**
+     *  @brief Swaps the contents of this index with another index.
+     *  @param other The other index to swap with.
+     */
+    void swap(index_dense_gt& other) {
+        std::swap(config_, other.config_);
+
+        std::swap(typed_, other.typed_);
+        std::swap(cast_buffer_, other.cast_buffer_);
+        std::swap(casts_, other.casts_);
+        std::swap(metric_, other.metric_);
+
+        std::swap(vectors_tape_allocator_, other.vectors_tape_allocator_);
+        std::swap(vectors_lookup_, other.vectors_lookup_);
+
+        std::swap(available_threads_, other.available_threads_);
+        std::swap(slot_lookup_, other.slot_lookup_);
+        std::swap(free_keys_, other.free_keys_);
+        std::swap(free_key_, other.free_key_);
+    }
+
+    ~index_dense_gt() {
+        if (typed_)
+            typed_->~index_t();
+        index_allocator_t{}.deallocate(typed_, 1);
+        typed_ = nullptr;
+    }
+
+    /**
+     *  @brief Constructs an instance of ::index_dense_gt.
+     *  @param[in] metric One of the provided or an @b ad-hoc metric, type-punned.
+     *  @param[in] config The index configuration (optional).
+     *  @param[in] free_label The key used for freed vectors (optional).
+     *  @return An instance of ::index_dense_gt.
+     */
+    static index_dense_gt make(           //
+        metric_t metric,                  //
+        index_dense_config_t config = {}, //
+        key_t free_label = default_free_value<key_t>()) {
+
+        scalar_kind_t scalar_kind = metric.scalar_kind();
+        std::size_t hardware_threads = std::thread::hardware_concurrency();
+
+        index_dense_gt result;
+        result.config_ = config;
+        result.cast_buffer_.resize(hardware_threads * metric.bytes_per_vector());
+        result.casts_ = make_casts_(scalar_kind);
+        result.metric_ = metric;
+        result.free_key_ = free_label;
+
+        // Fill the thread IDs.
+        result.available_threads_.resize(hardware_threads);
+        std::iota(result.available_threads_.begin(), result.available_threads_.end(), 0ul);
+
+        // Available since C11, but only C++17, so we use the C version.
+        index_t* raw = index_allocator_t{}.allocate(1);
+        new (raw) index_t(config);
+        result.typed_ = raw;
+        return result;
+    }
+
+    static index_dense_gt make(char const* path, bool view = false) {
+        index_dense_metadata_result_t meta = index_dense_metadata(path);
+        if (!meta)
+            return {};
+        metric_punned_t metric(meta.head.dimensions, meta.head.kind_metric, meta.head.kind_scalar);
+        index_dense_gt result = make(metric);
+        if (!result)
+            return result;
+        if (view)
+            result.view(path);
+        else
+            result.load(path);
+        return result;
+    }
+
+    explicit operator bool() const { return typed_; }
+    std::size_t connectivity() const { return typed_->connectivity(); }
+    std::size_t size() const { return typed_->size() - free_keys_.size(); }
+    std::size_t capacity() const { return typed_->capacity(); }
+    std::size_t max_level() const noexcept { return typed_->max_level(); }
+    index_dense_config_t const& config() const { return config_; }
+    index_limits_t const& limits() const { return typed_->limits(); }
+
+    // The metric and its properties
+    metric_t const& metric() const { return metric_; }
+    void change_metric(metric_t metric) { metric_ = std::move(metric); }
+
+    scalar_kind_t scalar_kind() const noexcept { return metric_.scalar_kind(); }
+    std::size_t bytes_per_vector() const noexcept { return metric_.bytes_per_vector(); }
+    std::size_t scalar_words() const noexcept { return metric_.scalar_words(); }
+    std::size_t dimensions() const noexcept { return metric_.dimensions(); }
+
+    // Fetching and changing search criteria
+    std::size_t expansion_add() const { return config_.expansion_add; }
+    std::size_t expansion_search() const { return config_.expansion_search; }
+    void change_expansion_add(std::size_t n) { config_.expansion_add = n; }
+    void change_expansion_search(std::size_t n) { config_.expansion_search = n; }
+
+    member_citerator_t cbegin() const { return typed_->cbegin(); }
+    member_citerator_t cend() const { return typed_->cend(); }
+    member_citerator_t begin() const { return typed_->begin(); }
+    member_citerator_t end() const { return typed_->end(); }
+    member_iterator_t begin() { return typed_->begin(); }
+    member_iterator_t end() { return typed_->end(); }
+
+    stats_t stats() const { return typed_->stats(); }
+    stats_t stats(std::size_t level) const { return typed_->stats(level); }
+
+    /**
+     *  @brief  A relatively accurate lower bound on the amount of memory consumed by the system.
+     *          In practice it's error will be below 10%.
+     *
+     *  @see    `stream_length` for the length of the binary serialized representation.
+     */
+    std::size_t memory_usage() const {
+        return                                          //
+            typed_->memory_usage(0) +                   //
+            typed_->tape_allocator().total_wasted() +   //
+            typed_->tape_allocator().total_reserved() + //
+            vectors_tape_allocator_.total_allocated();
+    }
+
+    // clang-format off
+    add_result_t add(key_t key, b1x8_t const* vector) { return add_(key, vector, casts_.from_b1x8); }
+    add_result_t add(key_t key, i8_bits_t const* vector) { return add_(key, vector, casts_.from_i8); }
+    add_result_t add(key_t key, f16_t const* vector) { return add_(key, vector, casts_.from_f16); }
+    add_result_t add(key_t key, f32_t const* vector) { return add_(key, vector, casts_.from_f32); }
+    add_result_t add(key_t key, f64_t const* vector) { return add_(key, vector, casts_.from_f64); }
+
+    add_result_t add(key_t key, b1x8_t const* vector, index_dense_update_config_t config) { return add_(key, vector, config, casts_.from_b1x8); }
+    add_result_t add(key_t key, i8_bits_t const* vector, index_dense_update_config_t config) { return add_(key, vector, config, casts_.from_i8); }
+    add_result_t add(key_t key, f16_t const* vector, index_dense_update_config_t config) { return add_(key, vector, config, casts_.from_f16); }
+    add_result_t add(key_t key, f32_t const* vector, index_dense_update_config_t config) { return add_(key, vector, config, casts_.from_f32); }
+    add_result_t add(key_t key, f64_t const* vector, index_dense_update_config_t config) { return add_(key, vector, config, casts_.from_f64); }
+
+    search_result_t search(b1x8_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_b1x8); }
+    search_result_t search(i8_bits_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_i8); }
+    search_result_t search(f16_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_f16); }
+    search_result_t search(f32_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_f32); }
+    search_result_t search(f64_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_f64); }
+
+    search_result_t search(b1x8_t const* vector, std::size_t wanted, index_search_config_t config) const { return search_(vector, wanted, config, casts_.from_b1x8); }
+    search_result_t search(i8_bits_t const* vector, std::size_t wanted, index_search_config_t config) const { return search_(vector, wanted, config, casts_.from_i8); }
+    search_result_t search(f16_t const* vector, std::size_t wanted, index_search_config_t config) const { return search_(vector, wanted, config, casts_.from_f16); }
+    search_result_t search(f32_t const* vector, std::size_t wanted, index_search_config_t config) const { return search_(vector, wanted, config, casts_.from_f32); }
+    search_result_t search(f64_t const* vector, std::size_t wanted, index_search_config_t config) const { return search_(vector, wanted, config, casts_.from_f64); }
+
+    bool get(key_t key, b1x8_t* vector) const { return get_(key, vector, casts_.to_b1x8); }
+    bool get(key_t key, i8_bits_t* vector) const { return get_(key, vector, casts_.to_i8); }
+    bool get(key_t key, f16_t* vector) const { return get_(key, vector, casts_.to_f16); }
+    bool get(key_t key, f32_t* vector) const { return get_(key, vector, casts_.to_f32); }
+    bool get(key_t key, f64_t* vector) const { return get_(key, vector, casts_.to_f64); }
+    // clang-format on
+
+    /**
+     *  @brief Reserves memory for the index and the labeled lookup.
+     *  @return `true` if the memory reservation was successful, `false` otherwise.
+     */
+    bool reserve(index_limits_t limits) {
+        {
+            unique_lock_t lock(slot_lookup_mutex_);
+            slot_lookup_.reserve(limits.members);
+            vectors_lookup_.resize(limits.members);
+        }
+        return typed_->reserve(limits);
+    }
+
+    /**
+     *  @brief Erases all the vectors from the index.
+     *
+     *  Will change `size()` to zero, but will keep the same `capacity()`.
+     *  Will keep the number of available threads/contexts the same as it was.
+     */
+    void clear() {
+        unique_lock_t lookup_lock(slot_lookup_mutex_);
+
+        std::unique_lock<std::mutex> free_lock(free_keys_mutex_);
+        typed_->clear();
+        slot_lookup_.clear();
+        vectors_lookup_.clear();
+        free_keys_.clear();
+        vectors_tape_allocator_.reset();
+    }
+
+    /**
+     *  @brief Erases all members from index, closing files, and returning RAM to OS.
+     *
+     *  Will change both `size()` and `capacity()` to zero.
+     *  Will deallocate all threads/contexts.
+     *  If the index is memory-mapped - releases the mapping and the descriptor.
+     */
+    void reset() {
+        unique_lock_t lookup_lock(slot_lookup_mutex_);
+
+        std::unique_lock<std::mutex> free_lock(free_keys_mutex_);
+        std::unique_lock<std::mutex> available_threads_lock(available_threads_mutex_);
+        typed_->reset();
+        slot_lookup_.clear();
+        vectors_lookup_.clear();
+        free_keys_.clear();
+        vectors_tape_allocator_.reset();
+        available_threads_.clear();
+    }
+
+    /**
+     *  @brief Saves the index to a file.
+     *  @param[in] path The path to the file.
+     *  @param[in] config Configuration parameters for exports.
+     *  @return Outcome descriptor explicitly convertible to boolean.
+     */
+    serialization_result_t save(output_file_t file, serialization_config_t config = {}) const {
+        serialization_result_t result = file.open_if_not();
+        if (result)
+            stream(
+                [&](void* buffer, std::size_t length) {
+                    result = file.write(buffer, length);
+                    return !!result;
+                },
+                config);
+        return result;
+    }
+
+    /**
+     *  @brief  Saves serialized binary index representation to a stream.
+     */
+    template <typename output_callback_at, typename progress_at = dummy_progress_t>
+    serialization_result_t stream(output_callback_at&& callback, serialization_config_t config = {}) const noexcept {
+
+        serialization_result_t result;
+        std::uint64_t matrix_rows = 0;
+        std::uint64_t matrix_cols = 0;
+
+        // We may not want to put the vectors into the same file
+        if (!config.exclude_vectors) {
+            // Save the matrix size
+            if (!config.use_64_bit_dimensions) {
+                std::uint32_t dimensions[2];
+                dimensions[0] = static_cast<std::uint32_t>(typed_->size());
+                dimensions[1] = static_cast<std::uint32_t>(metric_.bytes_per_vector());
+                if (!callback(&dimensions, sizeof(dimensions)))
+                    return result.failed("Failed to serialize into stream");
+                matrix_rows = dimensions[0];
+                matrix_cols = dimensions[1];
+            } else {
+                std::uint64_t dimensions[2];
+                dimensions[0] = static_cast<std::uint64_t>(typed_->size());
+                dimensions[1] = static_cast<std::uint64_t>(metric_.bytes_per_vector());
+                if (!callback(&dimensions, sizeof(dimensions)))
+                    return result.failed("Failed to serialize into stream");
+                matrix_rows = dimensions[0];
+                matrix_cols = dimensions[1];
+            }
+
+            // Dump the vectors one after another
+            for (std::uint64_t i = 0; i != matrix_rows; ++i) {
+                byte_t* vector = vectors_lookup_[i];
+                if (!callback(vector, matrix_cols))
+                    return result.failed("Failed to serialize into stream");
+            }
+        }
+
+        // Augment metadata
+        {
+            index_dense_head_buffer_t buffer;
+            std::memset(buffer, 0, sizeof(buffer));
+            index_dense_head_t head{buffer};
+            std::memcpy(buffer, default_magic(), std::strlen(default_magic()));
+
+            // Describe software version
+            using version_t = index_dense_head_t::version_t;
+            head.version_major = static_cast<version_t>(USEARCH_VERSION_MAJOR);
+            head.version_minor = static_cast<version_t>(USEARCH_VERSION_MINOR);
+            head.version_patch = static_cast<version_t>(USEARCH_VERSION_PATCH);
+
+            // Describes types used
+            head.kind_metric = metric_.metric_kind();
+            head.kind_scalar = metric_.scalar_kind();
+            head.kind_key = unum::usearch::scalar_kind<key_t>();
+            head.kind_compressed_slot = unum::usearch::scalar_kind<compressed_slot_t>();
+
+            head.count_present = size();
+            head.count_deleted = typed_->size() - size();
+            head.dimensions = dimensions();
+
+            if (!callback(&buffer, sizeof(buffer)))
+                return result.failed("Failed to serialize into stream");
+        }
+
+        // Save the actual proximity graph
+        return typed_->stream(std::forward<output_callback_at>(callback));
+    }
+
+    /**
+     *  @brief  Estimate the binary length (in bytes) of the serialized index.
+     */
+    std::size_t stream_length(serialization_config_t config = {}) const noexcept {
+        std::size_t dimensions_length = 0;
+        std::size_t matrix_length = 0;
+        if (!config.exclude_vectors) {
+            dimensions_length = config.use_64_bit_dimensions ? sizeof(std::uint64_t) * 2 : sizeof(std::uint32_t) * 2;
+            matrix_length = typed_->size() * metric_.bytes_per_vector();
+        }
+        return dimensions_length + matrix_length + sizeof(index_dense_head_buffer_t) + typed_->stream_length();
+    }
+
+    /**
+     *  @brief Parses the index from file to RAM.
+     *  @param[in] path The path to the file.
+     *  @param[in] config Configuration parameters for imports.
+     *  @return Outcome descriptor explicitly convertible to boolean.
+     */
+    serialization_result_t load(input_file_t file, serialization_config_t config = {}) {
+
+        serialization_result_t result = file.open_if_not();
+        if (!result)
+            return result;
+
+        std::uint64_t matrix_rows = 0;
+        std::uint64_t matrix_cols = 0;
+
+        // We may not want to load the vectors from the same file, or allow attaching them afterwards
+        if (!config.exclude_vectors) {
+            // Save the matrix size
+            if (!config.use_64_bit_dimensions) {
+                std::uint32_t dimensions[2];
+                result = file.read(&dimensions, sizeof(dimensions));
+                if (!result)
+                    return result;
+                matrix_rows = dimensions[0];
+                matrix_cols = dimensions[1];
+            } else {
+                std::uint64_t dimensions[2];
+                result = file.read(&dimensions, sizeof(dimensions));
+                if (!result)
+                    return result;
+                matrix_rows = dimensions[0];
+                matrix_cols = dimensions[1];
+            }
+            // Load the vectors one after another
+            vectors_lookup_.resize(matrix_rows);
+            for (std::uint64_t slot = 0; slot != matrix_rows; ++slot) {
+                byte_t* vector = vectors_tape_allocator_.allocate(matrix_cols);
+                result = file.read(vector, matrix_cols);
+                if (!result)
+                    return result;
+                vectors_lookup_[slot] = vector;
+            }
+        }
+
+        // Load metadata and choose the right metric
+        {
+            index_dense_head_buffer_t buffer;
+            result = file.read(buffer, sizeof(buffer));
+            if (!result)
+                return result;
+
+            index_dense_head_t head{buffer};
+            if (std::memcmp(buffer, default_magic(), std::strlen(default_magic())) != 0)
+                return result.failed("Magic header mismatch - the file isn't an index");
+
+            // Validate the software version
+            if (head.version_major != USEARCH_VERSION_MAJOR)
+                return result.failed("File format may be different, please rebuild");
+
+            // Check the types used
+            if (head.kind_key != unum::usearch::scalar_kind<key_t>())
+                return result.failed("Key type doesn't match, consider rebuilding");
+            if (head.kind_compressed_slot != unum::usearch::scalar_kind<compressed_slot_t>())
+                return result.failed("Slot type doesn't match, consider rebuilding");
+
+            metric_ = metric_t(head.dimensions, head.kind_metric, head.kind_scalar);
+        }
+
+        // Pull the actual proximity graph
+        result = typed_->load(std::move(file));
+        if (!result)
+            return result;
+        if (typed_->size() != static_cast<std::size_t>(matrix_rows))
+            return result.failed("Index size and the number of vectors doesn't match");
+
+        reindex_labels_();
+        return result;
+    }
+
+    /**
+     *  @brief Parses the index from file, without loading it into RAM.
+     *  @param[in] path The path to the file.
+     *  @param[in] config Configuration parameters for imports.
+     *  @return Outcome descriptor explicitly convertible to boolean.
+     */
+    serialization_result_t view(memory_mapped_file_t file, std::size_t offset = 0, serialization_config_t config = {}) {
+
+        serialization_result_t result = file.open_if_not();
+        if (!result)
+            return result;
+
+        std::uint64_t matrix_rows = 0;
+        std::uint64_t matrix_cols = 0;
+        span_punned_t vectors_buffer;
+
+        // We may not want to fetch the vectors from the same file, or allow attaching them afterwards
+        if (!config.exclude_vectors) {
+            // Save the matrix size
+            if (!config.use_64_bit_dimensions) {
+                std::uint32_t dimensions[2];
+                if (file.size() - offset < sizeof(dimensions))
+                    return result.failed("File is corrupted and lacks matrix dimensions");
+                std::memcpy(&dimensions, file.data() + offset, sizeof(dimensions));
+                matrix_rows = dimensions[0];
+                matrix_cols = dimensions[1];
+                offset += sizeof(dimensions);
+            } else {
+                std::uint64_t dimensions[2];
+                if (file.size() - offset < sizeof(dimensions))
+                    return result.failed("File is corrupted and lacks matrix dimensions");
+                std::memcpy(&dimensions, file.data() + offset, sizeof(dimensions));
+                matrix_rows = dimensions[0];
+                matrix_cols = dimensions[1];
+                offset += sizeof(dimensions);
+            }
+            vectors_buffer = {file.data() + offset, static_cast<std::size_t>(matrix_rows * matrix_cols)};
+            offset += vectors_buffer.size();
+        }
+
+        // Load metadata and choose the right metric
+        {
+            index_dense_head_buffer_t buffer;
+            if (file.size() - offset < sizeof(buffer))
+                return result.failed("File is corrupted and lacks a header");
+
+            std::memcpy(buffer, file.data() + offset, sizeof(buffer));
+
+            index_dense_head_t head{buffer};
+            if (std::memcmp(buffer, default_magic(), std::strlen(default_magic())) != 0)
+                return result.failed("Magic header mismatch - the file isn't an index");
+
+            // Validate the software version
+            if (head.version_major != USEARCH_VERSION_MAJOR)
+                return result.failed("File format may be different, please rebuild");
+
+            // Check the types used
+            if (head.kind_key != unum::usearch::scalar_kind<key_t>())
+                return result.failed("Key type doesn't match, consider rebuilding");
+            if (head.kind_compressed_slot != unum::usearch::scalar_kind<compressed_slot_t>())
+                return result.failed("Slot type doesn't match, consider rebuilding");
+
+            metric_ = metric_t(head.dimensions, head.kind_metric, head.kind_scalar);
+            offset += sizeof(buffer);
+        }
+
+        // Pull the actual proximity graph
+        result = typed_->view(std::move(file), offset);
+        if (!result)
+            return result;
+        if (typed_->size() != static_cast<std::size_t>(matrix_rows))
+            return result.failed("Index size and the number of vectors doesn't match");
+
+        // Address the vectors
+        vectors_lookup_.resize(matrix_rows);
+        if (!config.exclude_vectors)
+            for (std::uint64_t slot = 0; slot != matrix_rows; ++slot)
+                vectors_lookup_[slot] = (byte_t*)vectors_buffer.data() + matrix_cols * slot;
+
+        reindex_labels_();
+        return result;
+    }
+
+    /**
+     *  @brief Checks if a vector with specified key is present.
+     *  @return `true` if the key is present in the index, `false` otherwise.
+     */
+    bool contains(key_t key) const {
+        shared_lock_t lock(slot_lookup_mutex_);
+        return slot_lookup_.contains(key);
+    }
+
+    /**
+     *  @brief Count the number of vectors with specified key present.
+     *  @return Zero if nothing is found, a positive integer otherwise.
+     */
+    std::size_t count(key_t key) const {
+        shared_lock_t lock(slot_lookup_mutex_);
+        return slot_lookup_.count(key);
+    }
+
+    struct labeling_result_t {
+        error_t error{};
+        std::size_t completed{};
+
+        explicit operator bool() const noexcept { return !error; }
+        labeling_result_t failed(error_t message) noexcept {
+            error = std::move(message);
+            return std::move(*this);
+        }
+    };
+
+    /**
+     *  @brief Removes an entry with the specified key from the index.
+     *  @param[in] key The key of the entry to remove.
+     *  @return The ::labeling_result_t indicating the result of the removal operation.
+     *          If the removal was successful, `result.completed` will be `true`.
+     *          If the key was not found in the index, `result.completed` will be `false`.
+     *          If an error occurred during the removal operation, `result.error` will contain an error message.
+     */
+    labeling_result_t remove(key_t key) {
+        labeling_result_t result;
+
+        unique_lock_t lookup_lock(slot_lookup_mutex_);
+        auto labeled_iterator = slot_lookup_.find(key);
+        if (labeled_iterator == slot_lookup_.end())
+            return result;
+
+        // Grow the removed entries ring, if needed
+        std::unique_lock<std::mutex> free_lock(free_keys_mutex_);
+        if (free_keys_.size() == free_keys_.capacity())
+            if (!free_keys_.reserve((std::max<std::size_t>)(free_keys_.capacity() * 2, 64ul)))
+                return result.failed("Can't allocate memory for a free-list");
+
+        // A removed entry would be:
+        // - present in `free_keys_`
+        // - missing in the `slot_lookup_`
+        // - marked in the `typed_` index with a `free_key_`
+        compressed_slot_t slot = (*labeled_iterator).slot;
+        free_keys_.push(slot);
+        slot_lookup_.erase(labeled_iterator);
+        typed_->at(slot).key = free_key_;
+        result.completed = true;
+
+        return result;
+    }
+
+    /**
+     *  @brief Removes multiple entries with the specified keys from the index.
+     *  @param[in] labels_begin The beginning of the keys range.
+     *  @param[in] labels_end The ending of the keys range.
+     *  @return The ::labeling_result_t indicating the result of the removal operation.
+     *          `result.completed` will contain the number of keys that were successfully removed.
+     *          `result.error` will contain an error message if an error occurred during the removal operation.
+     */
+    template <typename labels_iterator_at>
+    labeling_result_t remove(labels_iterator_at&& labels_begin, labels_iterator_at&& labels_end) {
+
+        labeling_result_t result;
+        unique_lock_t lookup_lock(slot_lookup_mutex_);
+        std::unique_lock<std::mutex> free_lock(free_keys_mutex_);
+
+        // Grow the removed entries ring, if needed
+        std::size_t count_requests = std::distance(labels_begin, labels_end);
+        if (!free_keys_.reserve(free_keys_.size() + count_requests))
+            return result.failed("Can't allocate memory for a free-list");
+
+        // Remove them one-by-one
+        for (auto label_it = labels_begin; label_it != labels_end; ++label_it) {
+            key_t key = *label_it;
+            auto labeled_iterator = slot_lookup_.find(key);
+            if (labeled_iterator == slot_lookup_.end())
+                continue;
+
+            // A removed entry would be:
+            // - present in `free_keys_`
+            // - missing in the `slot_lookup_`
+            // - marked in the `typed_` index with a `free_key_`
+            compressed_slot_t slot = (*labeled_iterator).slot;
+            free_keys_.push(slot);
+            slot_lookup_.erase(labeled_iterator);
+            typed_->at(slot).key = free_key_;
+            result.completed += 1;
+        }
+
+        return result;
+    }
+
+    /**
+     *  @brief Renames an entry with the specified key to a new key.
+     *  @param[in] from The current key of the entry to rename.
+     *  @param[in] to The new key to assign to the entry.
+     *  @return The ::labeling_result_t indicating the result of the rename operation.
+     *          If the rename was successful, `result.completed` will be `true`.
+     *          If the entry with the current key was not found, `result.completed` will be `false`.
+     */
+    labeling_result_t rename(key_t from, key_t to) {
+        labeling_result_t result;
+        unique_lock_t lookup_lock(slot_lookup_mutex_);
+        auto labeled_iterator = slot_lookup_.find(from);
+        if (labeled_iterator == slot_lookup_.end())
+            return result;
+
+        compressed_slot_t slot = (*labeled_iterator).slot;
+        key_and_slot_t key_and_slot{to, slot};
+        slot_lookup_.erase(labeled_iterator);
+        slot_lookup_.insert(key_and_slot);
+        typed_->at(slot).key = to;
+        result.completed = true;
+        return result;
+    }
+
+    /**
+     *  @brief Exports a range of keys for the vectors present in the index.
+     *  @param[out] keys Pointer to the array where the keys will be exported.
+     *  @param[in] offset The number of keys to skip. Useful for pagination.
+     *  @param[in] limit The maximum number of keys to export, that can fit in ::keys.
+     */
+    void export_keys(key_t* keys, std::size_t offset, std::size_t limit) const {
+        shared_lock_t lock(slot_lookup_mutex_);
+        auto it = slot_lookup_.begin();
+        offset = (std::min)(offset, slot_lookup_.size());
+        std::advance(it, offset);
+        for (; it != slot_lookup_.end() && limit; ++it, ++keys, --limit)
+            *keys = (*it).key;
+    }
+
+    struct copy_result_t {
+        index_dense_gt index;
+        error_t error;
+
+        explicit operator bool() const noexcept { return !error; }
+        copy_result_t failed(error_t message) noexcept {
+            error = std::move(message);
+            return std::move(*this);
+        }
+    };
+
+    /**
+     *  @brief Copies the ::index_dense_gt @b with all the data in it.
+     *  @param config The copy configuration (optional).
+     *  @return A copy of the ::index_dense_gt instance.
+     */
+    copy_result_t copy(index_dense_copy_config_t config = {}) const {
+        copy_result_t result = fork();
+        if (!result)
+            return result;
+
+        auto typed_result = typed_->copy(config);
+        if (!typed_result)
+            return result.failed(std::move(typed_result.error));
+
+        // Export the free (removed) slot numbers
+        index_dense_gt& copy = result.index;
+        if (!copy.free_keys_.reserve(free_keys_.size()))
+            return result.failed(std::move(typed_result.error));
+        for (std::size_t i = 0; i != free_keys_.size(); ++i)
+            copy.free_keys_.push(free_keys_[i]);
+
+        // Allocate buffers and move the vectors themselves
+        if (!config.force_vector_copy && copy.config_.exclude_vectors)
+            copy.vectors_lookup_ = vectors_lookup_;
+        else {
+            copy.vectors_lookup_.resize(vectors_lookup_.size());
+            for (std::size_t slot = 0; slot != vectors_lookup_.size(); ++slot)
+                copy.vectors_lookup_[slot] = copy.vectors_tape_allocator_.allocate(copy.metric_.bytes_per_vector());
+            if (std::count(copy.vectors_lookup_.begin(), copy.vectors_lookup_.end(), nullptr))
+                return result.failed("Out of memory!");
+            for (std::size_t slot = 0; slot != vectors_lookup_.size(); ++slot)
+                std::memcpy(copy.vectors_lookup_[slot], vectors_lookup_[slot], metric_.bytes_per_vector());
+        }
+
+        copy.slot_lookup_ = slot_lookup_;
+        *copy.typed_ = std::move(typed_result.index);
+        return result;
+    }
+
+    /**
+     *  @brief Copies the ::index_dense_gt model @b without any data.
+     *  @return A similarly configured ::index_dense_gt instance.
+     */
+    copy_result_t fork() const {
+        copy_result_t result;
+        index_dense_gt& other = result.index;
+
+        other.config_ = config_;
+        other.cast_buffer_ = cast_buffer_;
+        other.casts_ = casts_;
+
+        other.metric_ = metric_;
+        other.available_threads_ = available_threads_;
+        other.free_key_ = free_key_;
+
+        index_t* raw = index_allocator_t{}.allocate(1);
+        if (!raw)
+            return result.failed("Can't allocate the index");
+
+        new (raw) index_t(config());
+        other.typed_ = raw;
+        return result;
+    }
+
+    struct compaction_result_t {
+        error_t error{};
+        std::size_t pruned_edges{};
+
+        explicit operator bool() const noexcept { return !error; }
+        compaction_result_t failed(error_t message) noexcept {
+            error = std::move(message);
+            return std::move(*this);
+        }
+    };
+
+    /**
+     *  @brief Performs compaction on the index, pruning links to removed entries.
+     *  @param executor The executor parallel processing. Default ::dummy_executor_t single-threaded.
+     *  @param progress The progress tracker instance to use. Default ::dummy_progress_t reports nothing.
+     *  @return The ::compaction_result_t indicating the result of the compaction operation.
+     *          `result.pruned_edges` will contain the number of edges that were removed.
+     *          `result.error` will contain an error message if an error occurred during the compaction operation.
+     */
+    template <typename executor_at = dummy_executor_t, typename progress_at = dummy_progress_t>
+    compaction_result_t isolate(executor_at&& executor = executor_at{}, progress_at&& progress = progress_at{}) {
+        compaction_result_t result;
+        std::atomic<std::size_t> pruned_edges;
+        auto disallow = [&](member_cref_t const& member) noexcept {
+            bool freed = member.key == free_key_;
+            pruned_edges += freed;
+            return freed;
+        };
+        typed_->isolate(disallow, std::forward<executor_at>(executor), std::forward<progress_at>(progress));
+        result.pruned_edges = pruned_edges;
+        return result;
+    }
+
+    class values_proxy_t {
+        index_dense_gt const* index_;
+
+      public:
+        values_proxy_t(index_dense_gt const& index) noexcept : index_(&index) {}
+        byte_t const* operator[](compressed_slot_t slot) const noexcept { return index_->vectors_lookup_[slot]; }
+        byte_t const* operator[](member_citerator_t it) const noexcept { return index_->vectors_lookup_[get_slot(it)]; }
+    };
+
+    /**
+     *  @brief Performs compaction on the index, pruning links to removed entries.
+     *  @param executor The executor parallel processing. Default ::dummy_executor_t single-threaded.
+     *  @param progress The progress tracker instance to use. Default ::dummy_progress_t reports nothing.
+     *  @return The ::compaction_result_t indicating the result of the compaction operation.
+     *          `result.pruned_edges` will contain the number of edges that were removed.
+     *          `result.error` will contain an error message if an error occurred during the compaction operation.
+     */
+    template <typename executor_at = dummy_executor_t, typename progress_at = dummy_progress_t>
+    compaction_result_t compact(executor_at&& executor = executor_at{}, progress_at&& progress = progress_at{}) {
+        compaction_result_t result;
+
+        std::vector<byte_t*> new_vectors_lookup(vectors_lookup_.size());
+        vectors_tape_allocator_t new_vectors_allocator;
+
+        auto track_slot_change = [&](key_t, compressed_slot_t old_slot, compressed_slot_t new_slot) {
+            byte_t* new_vector = new_vectors_allocator.allocate(metric_.bytes_per_vector());
+            byte_t* old_vector = vectors_lookup_[old_slot];
+            std::memcpy(new_vector, old_vector, metric_.bytes_per_vector());
+            new_vectors_lookup[new_slot] = new_vector;
+        };
+        typed_->compact(values_proxy_t{*this}, metric_proxy_t{*this}, track_slot_change,
+                        std::forward<executor_at>(executor), std::forward<progress_at>(progress));
+        vectors_lookup_ = std::move(new_vectors_lookup);
+        vectors_tape_allocator_ = std::move(new_vectors_allocator);
+        return result;
+    }
+
+    template <                                                     //
+        typename man_to_woman_at = dummy_label_to_label_mapping_t, //
+        typename woman_to_man_at = dummy_label_to_label_mapping_t, //
+        typename executor_at = dummy_executor_t,                   //
+        typename progress_at = dummy_progress_t                    //
+        >
+    join_result_t join(                                     //
+        index_dense_gt const& women,                        //
+        index_join_config_t config = {},                    //
+        man_to_woman_at&& man_to_woman = man_to_woman_at{}, //
+        woman_to_man_at&& woman_to_man = woman_to_man_at{}, //
+        executor_at&& executor = executor_at{},             //
+        progress_at&& progress = progress_at{}) const {
+
+        index_dense_gt const& men = *this;
+        return unum::usearch::join(                      //
+            *men.typed_, *women.typed_,                  //
+            values_proxy_t{men}, values_proxy_t{women},  //
+            metric_proxy_t{men}, metric_proxy_t{women},  //
+            config,                                      //
+            std::forward<man_to_woman_at>(man_to_woman), //
+            std::forward<woman_to_man_at>(woman_to_man), //
+            std::forward<executor_at>(executor),         //
+            std::forward<progress_at>(progress));
+    }
+
+  private:
+    struct thread_lock_t {
+        index_dense_gt const& parent;
+        std::size_t thread_id;
+
+        ~thread_lock_t() { parent.thread_unlock_(thread_id); }
+    };
+
+    thread_lock_t thread_lock_() const {
+        available_threads_mutex_.lock();
+        std::size_t thread_id = available_threads_.back();
+        available_threads_.pop_back();
+        available_threads_mutex_.unlock();
+        return {*this, thread_id};
+    }
+
+    void thread_unlock_(std::size_t thread_id) const {
+        available_threads_mutex_.lock();
+        available_threads_.push_back(thread_id);
+        available_threads_mutex_.unlock();
+    }
+
+    template <typename scalar_at>
+    add_result_t add_(key_t key, scalar_at const* vector, index_dense_update_config_t config, cast_t const& cast) {
+
+        if (!config_.allow_key_collisions && contains(key))
+            return add_result_t{}.failed("Duplicate keys not allowed in high-level wrappers");
+
+        // Cast the vector, if needed for compatibility with `metric_`
+        bool copy_vector = !config_.exclude_vectors || config.force_vector_copy;
+        byte_t const* vector_data = reinterpret_cast<byte_t const*>(vector);
+        {
+            byte_t* casted_data = cast_buffer_.data() + metric_.bytes_per_vector() * config.thread;
+            bool casted = cast(vector_data, dimensions(), casted_data);
+            if (casted)
+                vector_data = casted_data, copy_vector = true;
+        }
+
+        // Check if there are some removed entries, whose nodes we can reuse
+        compressed_slot_t free_slot = default_free_value<compressed_slot_t>();
+        {
+            std::unique_lock<std::mutex> lock(free_keys_mutex_);
+            free_keys_.try_pop(free_slot);
+        }
+
+        // Perform the insertion or the update
+        bool reuse_node = free_slot != default_free_value<compressed_slot_t>();
+        auto on_success = [&](member_ref_t member) {
+            unique_lock_t slot_lock(slot_lookup_mutex_);
+            slot_lookup_.insert({key, static_cast<compressed_slot_t>(member.slot)});
+            if (copy_vector) {
+                if (!reuse_node)
+                    vectors_lookup_[member.slot] = vectors_tape_allocator_.allocate(metric_.bytes_per_vector());
+                std::memcpy(vectors_lookup_[member.slot], vector_data, metric_.bytes_per_vector());
+            } else
+                vectors_lookup_[member.slot] = (byte_t*)vector_data;
+        };
+
+        metric_proxy_t metric{*this};
+        return reuse_node //
+                   ? typed_->update(typed_->iterator_at(free_slot), key, vector_data, metric, config, on_success)
+                   : typed_->add(key, vector_data, metric, config, on_success);
+    }
+
+    template <typename scalar_at>
+    search_result_t search_(                         //
+        scalar_at const* vector, std::size_t wanted, //
+        index_search_config_t config, cast_t const& cast) const {
+
+        // Cast the vector, if needed for compatibility with `metric_`
+        byte_t const* vector_data = reinterpret_cast<byte_t const*>(vector);
+        {
+            byte_t* casted_data = cast_buffer_.data() + metric_.bytes_per_vector() * config.thread;
+            bool casted = cast(vector_data, dimensions(), casted_data);
+            if (casted)
+                vector_data = casted_data;
+        }
+
+        auto allow = [=](member_cref_t const& member) noexcept { return member.key != free_key_; };
+        return typed_->search(vector_data, wanted, metric_proxy_t{*this}, config, allow);
+    }
+
+    compressed_slot_t lookup_id_(key_t key) const {
+        shared_lock_t lock(slot_lookup_mutex_);
+        return slot_lookup_.at(key);
+    }
+
+    void reindex_labels_() {
+
+        // Estimate number of entries first
+        std::size_t count_total = typed_->size();
+        std::size_t count_removed = 0;
+        for (std::size_t i = 0; i != count_total; ++i) {
+            member_cref_t member = typed_->at(i);
+            count_removed += member.key == free_key_;
+        }
+
+        // Pull entries from the underlying `typed_` into either
+        // into `slot_lookup_`, or `free_keys_` if they are unused.
+        unique_lock_t lock(slot_lookup_mutex_);
+        slot_lookup_.clear();
+        slot_lookup_.reserve(count_total - count_removed);
+        free_keys_.clear();
+        free_keys_.reserve(count_removed);
+        for (std::size_t i = 0; i != typed_->size(); ++i) {
+            member_cref_t member = typed_->at(i);
+            if (member.key == free_key_)
+                free_keys_.push(static_cast<compressed_slot_t>(i));
+            else
+                slot_lookup_.insert(key_and_slot_t{key_t(member.key), static_cast<compressed_slot_t>(i)});
+        }
+    }
+
+    template <typename scalar_at> bool get_(key_t key, scalar_at* reconstructed, cast_t const& cast) const {
+        compressed_slot_t slot;
+        // Find the matching ID
+        {
+            shared_lock_t lock(slot_lookup_mutex_);
+            auto it = slot_lookup_.find(key);
+            if (it == slot_lookup_.end())
+                return false;
+            slot = (*it).slot;
+        }
+        // Export the entry
+        byte_t const* punned_vector = reinterpret_cast<byte_t const*>(vectors_lookup_[slot]);
+        bool casted = cast(punned_vector, dimensions(), (byte_t*)reconstructed);
+        if (!casted)
+            std::memcpy(reconstructed, punned_vector, metric_.bytes_per_vector());
+        return true;
+    }
+
+    template <typename scalar_at> add_result_t add_(key_t key, scalar_at const* vector, cast_t const& cast) {
+        thread_lock_t lock = thread_lock_();
+        index_dense_update_config_t update_config;
+        update_config.thread = lock.thread_id;
+        update_config.expansion = config_.expansion_add;
+        return add_(key, vector, update_config, cast);
+    }
+
+    template <typename scalar_at>
+    search_result_t search_(                         //
+        scalar_at const* vector, std::size_t wanted, //
+        cast_t const& cast) const {
+        thread_lock_t lock = thread_lock_();
+        index_search_config_t search_config;
+        search_config.thread = lock.thread_id;
+        search_config.expansion = config_.expansion_search;
+        return search_(vector, wanted, search_config, cast);
+    }
+
+    template <typename to_scalar_at> static casts_t make_casts_() {
+        casts_t result;
+
+        result.from_b1x8 = cast_gt<b1x8_t, to_scalar_at>{};
+        result.from_i8 = cast_gt<i8_bits_t, to_scalar_at>{};
+        result.from_f16 = cast_gt<f16_t, to_scalar_at>{};
+        result.from_f32 = cast_gt<f32_t, to_scalar_at>{};
+        result.from_f64 = cast_gt<f64_t, to_scalar_at>{};
+
+        result.to_b1x8 = cast_gt<to_scalar_at, b1x8_t>{};
+        result.to_i8 = cast_gt<to_scalar_at, i8_bits_t>{};
+        result.to_f16 = cast_gt<to_scalar_at, f16_t>{};
+        result.to_f32 = cast_gt<to_scalar_at, f32_t>{};
+        result.to_f64 = cast_gt<to_scalar_at, f64_t>{};
+
+        return result;
+    }
+
+    static casts_t make_casts_(scalar_kind_t scalar_kind) {
+        switch (scalar_kind) {
+        case scalar_kind_t::f64_k: return make_casts_<f64_t>();
+        case scalar_kind_t::f32_k: return make_casts_<f32_t>();
+        case scalar_kind_t::f16_k: return make_casts_<f16_t>();
+        case scalar_kind_t::i8_k: return make_casts_<i8_bits_t>();
+        case scalar_kind_t::b1x8_k: return make_casts_<b1x8_t>();
+        default: return {};
+        }
+    }
+};
+
+using index_dense_t = index_dense_gt<>;
+using index_dense_big_t = index_dense_gt<uuid_t, uint40_t>;
+
+/**
+ *  @brief  Adapts the Male-Optimal Stable Marriage algorithm for unequal sets
+ *          to perform fast one-to-one matching between two large collections
+ *          of vectors, using approximate nearest neighbors search.
+ *
+ *  @param[inout] man_to_woman Container to map ::first keys to ::second.
+ *  @param[inout] woman_to_man Container to map ::second keys to ::first.
+ *  @param[in] executor Thread-pool to execute the job in parallel.
+ *  @param[in] progress Callback to report the execution progress.
+ */
+template < //
+
+    typename men_label_at,   //
+    typename women_label_at, //
+    typename men_slot_at,    //
+    typename women_slot_at,  //
+
+    typename man_to_woman_at = dummy_label_to_label_mapping_t, //
+    typename woman_to_man_at = dummy_label_to_label_mapping_t, //
+    typename executor_at = dummy_executor_t,                   //
+    typename progress_at = dummy_progress_t                    //
+    >
+static join_result_t join(                                      //
+    index_dense_gt<men_label_at, men_slot_at> const& men,       //
+    index_dense_gt<women_label_at, women_slot_at> const& women, //
+
+    index_join_config_t config = {},                    //
+    man_to_woman_at&& man_to_woman = man_to_woman_at{}, //
+    woman_to_man_at&& woman_to_man = woman_to_man_at{}, //
+    executor_at&& executor = executor_at{},             //
+    progress_at&& progress = progress_at{}) noexcept {
+
+    return men.join(                                 //
+        women, config,                               //
+        std::forward<woman_to_man_at>(woman_to_man), //
+        std::forward<man_to_woman_at>(man_to_woman), //
+        std::forward<executor_at>(executor),         //
+        std::forward<progress_at>(progress));
+}
+
+} // namespace usearch
+} // namespace unum
diff --git a/include/usearch/index_plugins.hpp b/include/usearch/index_plugins.hpp
new file mode 100644
index 00000000..6d7e2b04
--- /dev/null
+++ b/include/usearch/index_plugins.hpp
@@ -0,0 +1,1263 @@
+#pragma once
+#include <stdlib.h> // `aligned_alloc`
+
+#include <cstring> // `std::strncmp`
+#include <numeric> // `std::iota`
+#include <thread>  // `std::thread`
+#include <vector>  // `std::vector`
+
+#include <usearch/index.hpp> // `expected_gt` and macros
+
+#if USEARCH_USE_OPENMP
+#include <omp.h> // `omp_get_num_threads()`
+#endif
+
+#if defined(USEARCH_DEFINED_LINUX)
+#include <sys/auxv.h> // `getauxval()`
+#endif
+
+#if defined(USEARCH_DEFINED_ARM)
+#include <arm_fp16.h> // `__fp16`
+#endif
+
+#if !defined(USEARCH_USE_NATIVE_F16)
+#if defined(__AVX512F__)
+#define USEARCH_USE_NATIVE_F16 1
+#elif defined(USEARCH_DEFINED_ARM)
+#define USEARCH_USE_NATIVE_F16 1
+#else
+#define USEARCH_USE_NATIVE_F16 0
+#include <fp16/fp16.h>
+#endif
+#else
+#define USEARCH_USE_NATIVE_F16 0
+#include <fp16/fp16.h>
+#endif
+
+#if !defined(USEARCH_USE_SIMSIMD)
+#define USEARCH_USE_SIMSIMD 0
+#endif
+
+#if USEARCH_USE_SIMSIMD
+#include <simsimd/simsimd.h>
+#endif
+
+namespace unum {
+namespace usearch {
+
+using u40_t = uint40_t;
+enum b1x8_t : unsigned char {};
+
+struct uuid_t {
+    std::uint8_t octets[16];
+};
+
+class i8_bits_t;
+class f16_bits_t;
+
+#if USEARCH_USE_NATIVE_F16
+#if defined(USEARCH_DEFINED_ARM)
+using f16_native_t = __fp16;
+#else
+using f16_native_t = _Float16;
+#endif
+using f16_t = f16_native_t;
+#else
+using f16_native_t = void;
+using f16_t = f16_bits_t;
+#endif
+
+using f64_t = double;
+using f32_t = float;
+
+using u64_t = std::uint64_t;
+using u32_t = std::uint32_t;
+using u16_t = std::uint16_t;
+using u8_t = std::uint8_t;
+
+using i64_t = std::int64_t;
+using i32_t = std::int32_t;
+using i16_t = std::int16_t;
+using i8_t = std::int8_t;
+
+enum class metric_kind_t : std::uint8_t {
+    unknown_k = 0,
+    // Classics:
+    ip_k = 'i',
+    cos_k = 'c',
+    l2sq_k = 'e',
+
+    // Custom:
+    pearson_k = 'p',
+    haversine_k = 'h',
+
+    // Sets:
+    jaccard_k = 'j',
+    hamming_k = 'b',
+    tanimoto_k = 't',
+    sorensen_k = 's',
+};
+
+enum class scalar_kind_t : std::uint8_t {
+    unknown_k = 0,
+    // Custom:
+    b1x8_k,
+    u40_k,
+    uuid_k,
+    // Common:
+    f64_k,
+    f32_k,
+    f16_k,
+    f8_k,
+    // Common Integral:
+    u64_k,
+    u32_k,
+    u16_k,
+    u8_k,
+    i64_k,
+    i32_k,
+    i16_k,
+    i8_k,
+};
+
+enum class isa_kind_t {
+    auto_k,
+    neon_k,
+    sve_k,
+    avx2_k,
+    avx512_k,
+};
+
+enum class prefetching_kind_t {
+    none_k,
+    cpu_k,
+    io_uring_k,
+};
+
+template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
+    if (std::is_same<scalar_at, b1x8_t>())
+        return scalar_kind_t::b1x8_k;
+    if (std::is_same<scalar_at, uint40_t>())
+        return scalar_kind_t::u40_k;
+    if (std::is_same<scalar_at, uuid_t>())
+        return scalar_kind_t::uuid_k;
+    if (std::is_same<scalar_at, f64_t>())
+        return scalar_kind_t::f64_k;
+    if (std::is_same<scalar_at, f32_t>())
+        return scalar_kind_t::f32_k;
+    if (std::is_same<scalar_at, f16_t>())
+        return scalar_kind_t::f16_k;
+    if (std::is_same<scalar_at, i8_bits_t>())
+        return scalar_kind_t::i8_k;
+    if (std::is_same<scalar_at, u64_t>())
+        return scalar_kind_t::u64_k;
+    if (std::is_same<scalar_at, u32_t>())
+        return scalar_kind_t::u32_k;
+    if (std::is_same<scalar_at, u16_t>())
+        return scalar_kind_t::u16_k;
+    if (std::is_same<scalar_at, u8_t>())
+        return scalar_kind_t::u8_k;
+    if (std::is_same<scalar_at, i64_t>())
+        return scalar_kind_t::i64_k;
+    if (std::is_same<scalar_at, i32_t>())
+        return scalar_kind_t::i32_k;
+    if (std::is_same<scalar_at, i16_t>())
+        return scalar_kind_t::i16_k;
+    if (std::is_same<scalar_at, i8_t>())
+        return scalar_kind_t::i8_k;
+    return scalar_kind_t::unknown_k;
+}
+
+template <typename at> at angle_to_radians(at angle) noexcept { return angle * at(3.14159265358979323846) / at(180); }
+
+template <typename at> at square(at value) noexcept { return value * value; }
+
+template <typename at, typename compare_at> inline at clamp(at v, at lo, at hi, compare_at comp) noexcept {
+    return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
+}
+template <typename at> inline at clamp(at v, at lo, at hi) noexcept {
+    return usearch::clamp(v, lo, hi, std::less<at>{});
+}
+
+inline bool str_equals(char const* begin, std::size_t len, char const* other_begin) noexcept {
+    std::size_t other_len = std::strlen(other_begin);
+    return len == other_len && std::strncmp(begin, other_begin, len) == 0;
+}
+
+inline char const* isa_name(isa_kind_t isa_kind) noexcept {
+    switch (isa_kind) {
+    case isa_kind_t::auto_k: return "auto";
+    case isa_kind_t::neon_k: return "neon";
+    case isa_kind_t::sve_k: return "sve";
+    case isa_kind_t::avx2_k: return "avx2";
+    case isa_kind_t::avx512_k: return "avx512";
+    default: return "";
+    }
+}
+
+inline bool hardware_supports(isa_kind_t isa_kind) noexcept {
+#if defined(USEARCH_DEFINED_ARM) && defined(USEARCH_DEFINED_LINUX)
+    unsigned long capabilities = getauxval(AT_HWCAP);
+    switch (isa_kind) {
+    case isa_kind_t::neon_k: return true; // Must be supported on 64-bit Arm
+    case isa_kind_t::sve_k: return capabilities & HWCAP_SVE;
+    default: return false;
+    }
+#endif
+
+#if defined(USEARCH_DEFINED_X86) && defined(USEARCH_DEFINED_GCC)
+    __builtin_cpu_init();
+    switch (isa_kind) {
+    case isa_kind_t::avx2_k: return __builtin_cpu_supports("avx2");
+    case isa_kind_t::avx512_k: return __builtin_cpu_supports("avx512f");
+    default: return false;
+    }
+#endif
+
+    (void)isa_kind;
+    return false;
+}
+
+inline std::size_t bits_per_scalar(scalar_kind_t scalar_kind) noexcept {
+    switch (scalar_kind) {
+    case scalar_kind_t::f64_k: return 64;
+    case scalar_kind_t::f32_k: return 32;
+    case scalar_kind_t::f16_k: return 16;
+    case scalar_kind_t::i8_k: return 8;
+    case scalar_kind_t::b1x8_k: return 1;
+    default: return 0;
+    }
+}
+
+inline std::size_t bits_per_scalar_word(scalar_kind_t scalar_kind) noexcept {
+    switch (scalar_kind) {
+    case scalar_kind_t::f64_k: return 64;
+    case scalar_kind_t::f32_k: return 32;
+    case scalar_kind_t::f16_k: return 16;
+    case scalar_kind_t::i8_k: return 8;
+    case scalar_kind_t::b1x8_k: return 8;
+    default: return 0;
+    }
+}
+
+inline char const* scalar_kind_name(scalar_kind_t scalar_kind) noexcept {
+    switch (scalar_kind) {
+    case scalar_kind_t::f32_k: return "f32";
+    case scalar_kind_t::f16_k: return "f16";
+    case scalar_kind_t::f64_k: return "f64";
+    case scalar_kind_t::i8_k: return "i8";
+    case scalar_kind_t::b1x8_k: return "b1x8";
+    default: return "";
+    }
+}
+
+inline char const* metric_kind_name(metric_kind_t metric) noexcept {
+    switch (metric) {
+    case metric_kind_t::unknown_k: return "unknown";
+    case metric_kind_t::ip_k: return "ip";
+    case metric_kind_t::cos_k: return "cos";
+    case metric_kind_t::l2sq_k: return "l2sq";
+    case metric_kind_t::pearson_k: return "pearson";
+    case metric_kind_t::haversine_k: return "haversine";
+    case metric_kind_t::jaccard_k: return "jaccard";
+    case metric_kind_t::hamming_k: return "hamming";
+    case metric_kind_t::tanimoto_k: return "tanimoto";
+    case metric_kind_t::sorensen_k: return "sorensen";
+    }
+    return "";
+}
+inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name, std::size_t len) {
+    expected_gt<scalar_kind_t> parsed;
+    if (str_equals(name, len, "f32"))
+        parsed.result = scalar_kind_t::f32_k;
+    else if (str_equals(name, len, "f64"))
+        parsed.result = scalar_kind_t::f64_k;
+    else if (str_equals(name, len, "f16"))
+        parsed.result = scalar_kind_t::f16_k;
+    else if (str_equals(name, len, "i8"))
+        parsed.result = scalar_kind_t::i8_k;
+    else
+        parsed.failed("Unknown type, choose: f32, f16, f64, i8");
+    return parsed;
+}
+
+inline expected_gt<metric_kind_t> metric_from_name(char const* name, std::size_t len) {
+    expected_gt<metric_kind_t> parsed;
+    if (str_equals(name, len, "l2sq") || str_equals(name, len, "euclidean_sq")) {
+        parsed.result = metric_kind_t::l2sq_k;
+    } else if (str_equals(name, len, "ip") || str_equals(name, len, "inner") || str_equals(name, len, "dot")) {
+        parsed.result = metric_kind_t::ip_k;
+    } else if (str_equals(name, len, "cos") || str_equals(name, len, "angular")) {
+        parsed.result = metric_kind_t::cos_k;
+    } else if (str_equals(name, len, "haversine")) {
+        parsed.result = metric_kind_t::haversine_k;
+    } else if (str_equals(name, len, "pearson")) {
+        parsed.result = metric_kind_t::pearson_k;
+    } else if (str_equals(name, len, "hamming")) {
+        parsed.result = metric_kind_t::hamming_k;
+    } else if (str_equals(name, len, "tanimoto")) {
+        parsed.result = metric_kind_t::tanimoto_k;
+    } else if (str_equals(name, len, "sorensen")) {
+        parsed.result = metric_kind_t::sorensen_k;
+    } else
+        parsed.failed(
+            "Unknown distance, choose: l2sq, ip, cos, haversine, jaccard, pearson, hamming, tanimoto, sorensen");
+    return parsed;
+}
+
+inline float f16_to_f32(std::uint16_t u16) noexcept {
+#if USEARCH_USE_NATIVE_F16
+    f16_native_t f16;
+    std::memcpy(&f16, &u16, sizeof(std::uint16_t));
+    return float(f16);
+#else
+    return fp16_ieee_to_fp32_value(u16);
+#endif
+}
+
+inline std::uint16_t f32_to_f16(float f32) noexcept {
+#if USEARCH_USE_NATIVE_F16
+    f16_native_t f16 = f16_native_t(f32);
+    std::uint16_t u16;
+    std::memcpy(&u16, &f16, sizeof(std::uint16_t));
+    return u16;
+#else
+    return fp16_ieee_from_fp32_value(f32);
+#endif
+}
+
+/**
+ *  @brief  Numeric type for the IEEE 754 half-precision floating point.
+ *          If hardware support isn't available, falls back to a hardware
+ *          agnostic in-software implementation.
+ */
+class f16_bits_t {
+    std::uint16_t uint16_{};
+
+  public:
+    inline f16_bits_t() noexcept : uint16_(0) {}
+    inline f16_bits_t(f16_bits_t&&) = default;
+    inline f16_bits_t& operator=(f16_bits_t&&) = default;
+    inline f16_bits_t(f16_bits_t const&) = default;
+    inline f16_bits_t& operator=(f16_bits_t const&) = default;
+
+    inline operator float() const noexcept { return f16_to_f32(uint16_); }
+    inline explicit operator bool() const noexcept { return f16_to_f32(uint16_) > 0.5f; }
+
+    inline f16_bits_t(i8_bits_t) noexcept;
+    inline f16_bits_t(bool v) noexcept : uint16_(f32_to_f16(v)) {}
+    inline f16_bits_t(float v) noexcept : uint16_(f32_to_f16(v)) {}
+    inline f16_bits_t(double v) noexcept : uint16_(f32_to_f16(v)) {}
+
+    inline f16_bits_t operator+(f16_bits_t other) const noexcept { return {float(*this) + float(other)}; }
+    inline f16_bits_t operator-(f16_bits_t other) const noexcept { return {float(*this) - float(other)}; }
+    inline f16_bits_t operator*(f16_bits_t other) const noexcept { return {float(*this) * float(other)}; }
+    inline f16_bits_t operator/(f16_bits_t other) const noexcept { return {float(*this) / float(other)}; }
+    inline f16_bits_t operator+(float other) const noexcept { return {float(*this) + other}; }
+    inline f16_bits_t operator-(float other) const noexcept { return {float(*this) - other}; }
+    inline f16_bits_t operator*(float other) const noexcept { return {float(*this) * other}; }
+    inline f16_bits_t operator/(float other) const noexcept { return {float(*this) / other}; }
+    inline f16_bits_t operator+(double other) const noexcept { return {float(*this) + other}; }
+    inline f16_bits_t operator-(double other) const noexcept { return {float(*this) - other}; }
+    inline f16_bits_t operator*(double other) const noexcept { return {float(*this) * other}; }
+    inline f16_bits_t operator/(double other) const noexcept { return {float(*this) / other}; }
+
+    inline f16_bits_t& operator+=(float v) noexcept {
+        uint16_ = f32_to_f16(v + f16_to_f32(uint16_));
+        return *this;
+    }
+
+    inline f16_bits_t& operator-=(float v) noexcept {
+        uint16_ = f32_to_f16(v - f16_to_f32(uint16_));
+        return *this;
+    }
+
+    inline f16_bits_t& operator*=(float v) noexcept {
+        uint16_ = f32_to_f16(v * f16_to_f32(uint16_));
+        return *this;
+    }
+
+    inline f16_bits_t& operator/=(float v) noexcept {
+        uint16_ = f32_to_f16(v / f16_to_f32(uint16_));
+        return *this;
+    }
+};
+
+/**
+ *  @brief  Numeric type for uniformly-distributed floating point
+ *          values within [-1,1] range, quantized to integers [-100,100].
+ */
+class i8_bits_t {
+    std::int8_t int8_{};
+
+  public:
+    constexpr static float divisor_k = 100.f;
+    constexpr static std::int8_t min_k = -100;
+    constexpr static std::int8_t max_k = 100;
+
+    inline i8_bits_t() noexcept : int8_(0) {}
+    inline i8_bits_t(bool v) noexcept : int8_(v ? max_k : 0) {}
+
+    inline i8_bits_t(i8_bits_t&&) = default;
+    inline i8_bits_t& operator=(i8_bits_t&&) = default;
+    inline i8_bits_t(i8_bits_t const&) = default;
+    inline i8_bits_t& operator=(i8_bits_t const&) = default;
+
+    inline operator float() const noexcept { return float(int8_) / divisor_k; }
+    inline operator f16_t() const noexcept { return float(int8_) / divisor_k; }
+    inline operator double() const noexcept { return double(int8_) / divisor_k; }
+    inline explicit operator bool() const noexcept { return int8_ > (max_k / 2); }
+    inline explicit operator std::int8_t() const noexcept { return int8_; }
+    inline explicit operator std::int16_t() const noexcept { return int8_; }
+    inline explicit operator std::int32_t() const noexcept { return int8_; }
+    inline explicit operator std::int64_t() const noexcept { return int8_; }
+
+    inline i8_bits_t(f16_t v)
+        : int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
+    inline i8_bits_t(float v)
+        : int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
+    inline i8_bits_t(double v)
+        : int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
+};
+
+inline f16_bits_t::f16_bits_t(i8_bits_t v) noexcept : f16_bits_t(float(v)) {}
+
+/**
+ *  @brief  An STL-based executor or a "thread-pool" for parallel execution.
+ *          Isn't efficient for small batches, as it recreates the threads on every call.
+ */
+class executor_stl_t {
+    std::size_t threads_count_{};
+
+  public:
+    /**
+     *  @param threads_count The number of threads to be used for parallel execution.
+     */
+    executor_stl_t(std::size_t threads_count = 0) noexcept
+        : threads_count_(threads_count ? threads_count : std::thread::hardware_concurrency()) {}
+
+    /**
+     *  @return Maximum number of threads available to the executor.
+     */
+    std::size_t size() const noexcept { return threads_count_; }
+
+    /**
+     *  @brief Executes tasks in bulk using the specified thread-aware function.
+     *  @param tasks                 The total number of tasks to be executed.
+     *  @param thread_aware_function The thread-aware function to be called for each thread index and task index.
+     *  @throws If an exception occurs during execution of the thread-aware function.
+     */
+    template <typename thread_aware_function_at>
+    void execute_bulk(std::size_t tasks, thread_aware_function_at&& thread_aware_function) noexcept(false) {
+        std::vector<std::thread> threads_pool;
+        std::size_t tasks_per_thread = tasks;
+        if (threads_count_ > 1) {
+            tasks_per_thread = (tasks / threads_count_) + ((tasks % threads_count_) != 0);
+            for (std::size_t thread_idx = 1; thread_idx < threads_count_; ++thread_idx) {
+                threads_pool.emplace_back([=]() {
+                    for (std::size_t task_idx = thread_idx * tasks_per_thread;
+                         task_idx < (std::min)(tasks, thread_idx * tasks_per_thread + tasks_per_thread); ++task_idx)
+                        thread_aware_function(thread_idx, task_idx);
+                });
+            }
+        }
+        for (std::size_t task_idx = 0; task_idx < (std::min)(tasks, tasks_per_thread); ++task_idx)
+            thread_aware_function(0, task_idx);
+        for (std::thread& thread : threads_pool)
+            thread.join();
+    }
+
+    /**
+     *  @brief Saturates every available thread with the given workload, until they finish.
+     *  @param thread_aware_function The thread-aware function to be called for each thread index.
+     *  @throws If an exception occurs during execution of the thread-aware function.
+     */
+    template <typename thread_aware_function_at>
+    void execute_bulk(thread_aware_function_at&& thread_aware_function) noexcept(false) {
+        if (threads_count_ == 1)
+            return thread_aware_function(0);
+        std::vector<std::thread> threads_pool;
+        for (std::size_t thread_idx = 1; thread_idx < threads_count_; ++thread_idx)
+            threads_pool.emplace_back([=]() { thread_aware_function(thread_idx); });
+        thread_aware_function(0);
+        for (std::thread& thread : threads_pool)
+            thread.join();
+    }
+};
+
+#if USEARCH_USE_OPENMP
+
+/**
+ *  @brief  An OpenMP-based executor or a "thread-pool" for parallel execution.
+ *          Is the preferred implementation, when available, and maximum performance is needed.
+ */
+class executor_openmp_t {
+  public:
+    /**
+     *  @param threads_count The number of threads to be used for parallel execution.
+     */
+    executor_openmp_t(std::size_t threads_count = 0) noexcept {
+        omp_set_num_threads(threads_count ? threads_count : std::thread::hardware_concurrency());
+    }
+
+    /**
+     *  @return Maximum number of threads available to the executor.
+     */
+    std::size_t size() const noexcept { return omp_get_num_threads(); }
+
+    /**
+     *  @brief Executes tasks in bulk using the specified thread-aware function.
+     *  @param tasks                 The total number of tasks to be executed.
+     *  @param thread_aware_function The thread-aware function to be called for each thread index and task index.
+     *  @throws If an exception occurs during execution of the thread-aware function.
+     */
+    template <typename thread_aware_function_at>
+    void execute_bulk(std::size_t tasks, thread_aware_function_at&& thread_aware_function) noexcept(false) {
+#pragma omp parallel for schedule(dynamic)
+        for (std::size_t i = 0; i != tasks; ++i) {
+            thread_aware_function(omp_get_thread_num(), i);
+        }
+    }
+
+    /**
+     *  @brief Saturates every available thread with the given workload, until they finish.
+     *  @param thread_aware_function The thread-aware function to be called for each thread index.
+     *  @throws If an exception occurs during execution of the thread-aware function.
+     */
+    template <typename thread_aware_function_at>
+    void execute_bulk(thread_aware_function_at&& thread_aware_function) noexcept(false) {
+#pragma omp parallel
+        { thread_aware_function(omp_get_thread_num()); }
+    }
+};
+
+using executor_default_t = executor_openmp_t;
+
+#else
+
+using executor_default_t = executor_stl_t;
+
+#endif
+
+/**
+ *  @brief Uses OS-specific APIs for aligned memory allocations.
+ */
+template <typename element_at = char, std::size_t alignment_ak = 64> //
+class aligned_allocator_gt {
+  public:
+    using value_type = element_at;
+    using size_type = std::size_t;
+    using pointer = element_at*;
+    using const_pointer = element_at const*;
+    template <typename other_element_at> struct rebind {
+        using other = aligned_allocator_gt<other_element_at>;
+    };
+
+    constexpr std::size_t alignment() const { return alignment_ak; }
+
+    pointer allocate(size_type length) const {
+        std::size_t length_bytes = alignment_ak * divide_round_up<alignment_ak>(length * sizeof(value_type));
+        std::size_t alignment = alignment_ak;
+        // void* result = nullptr;
+        // int status = posix_memalign(&result, alignment, length_bytes);
+        // return status == 0 ? (pointer)result : nullptr;
+#if defined(USEARCH_DEFINED_WINDOWS)
+        return (pointer)_aligned_malloc(length_bytes, alignment);
+#else
+        return (pointer)aligned_alloc(alignment, length_bytes);
+#endif
+    }
+
+    void deallocate(pointer begin, size_type) const {
+#if defined(USEARCH_DEFINED_WINDOWS)
+        _aligned_free(begin);
+#else
+        free(begin);
+#endif
+    }
+};
+
+using aligned_allocator_t = aligned_allocator_gt<>;
+
+/**
+ *  @brief  Memory-mapping allocator designed for "alloc many, free at once" usage patterns.
+ *          @b Thread-safe, @b except constructors and destructors.
+ *
+ *  Using this memory allocator won't affect your overall speed much, as that is not the bottleneck.
+ *  However, it can drastically improve memory usage especcially for huge indexes of small vectors.
+ */
+template <std::size_t alignment_ak = 1> class memory_mapping_allocator_gt {
+
+    static constexpr std::size_t min_capacity() { return 1024 * 1024 * 4; }
+    static constexpr std::size_t capacity_multiplier() { return 2; }
+    static constexpr std::size_t head_size() {
+        /// Pointer to the the previous arena and the size of the current one.
+        return divide_round_up<alignment_ak>(sizeof(byte_t*) + sizeof(std::size_t)) * alignment_ak;
+    }
+
+    std::mutex mutex_;
+    byte_t* last_arena_ = nullptr;
+    std::size_t last_usage_ = head_size();
+    std::size_t last_capacity_ = min_capacity();
+    std::size_t wasted_space_ = 0;
+
+  public:
+    using value_type = byte_t;
+    using size_type = std::size_t;
+    using pointer = byte_t*;
+    using const_pointer = byte_t const*;
+
+    memory_mapping_allocator_gt() = default;
+    memory_mapping_allocator_gt(memory_mapping_allocator_gt&& other) noexcept
+        : last_arena_(exchange(other.last_arena_, nullptr)), last_usage_(exchange(other.last_usage_, 0)),
+          last_capacity_(exchange(other.last_capacity_, 0)), wasted_space_(exchange(other.wasted_space_, 0)) {}
+
+    memory_mapping_allocator_gt& operator=(memory_mapping_allocator_gt&& other) noexcept {
+        std::swap(last_arena_, other.last_arena_);
+        std::swap(last_usage_, other.last_usage_);
+        std::swap(last_capacity_, other.last_capacity_);
+        std::swap(wasted_space_, other.wasted_space_);
+        return *this;
+    }
+
+    ~memory_mapping_allocator_gt() noexcept { reset(); }
+
+    /**
+     *  @brief Discards all previously allocated memory buffers.
+     */
+    void reset() noexcept {
+        byte_t* last_arena = last_arena_;
+        while (last_arena) {
+            byte_t* previous_arena;
+            std::memcpy(&previous_arena, last_arena, sizeof(byte_t*));
+            std::size_t last_cap;
+            std::memcpy(&last_cap, last_arena + sizeof(byte_t*), sizeof(std::size_t));
+#if defined(USEARCH_DEFINED_WINDOWS)
+            ::VirtualFree(last_arena, 0, MEM_RELEASE);
+#else
+            munmap(last_arena, last_cap);
+#endif
+            last_arena = previous_arena;
+        }
+
+        // Clear the references:
+        last_arena_ = nullptr;
+        last_usage_ = head_size();
+        last_capacity_ = min_capacity();
+        wasted_space_ = 0;
+    }
+
+    /**
+     *  @brief Copy constructor.
+     *  @note This is a no-op copy constructor since the allocator is not copyable.
+     */
+    memory_mapping_allocator_gt(memory_mapping_allocator_gt const&) noexcept {}
+
+    /**
+     *  @brief Copy assignment operator.
+     *  @note This is a no-op copy assignment operator since the allocator is not copyable.
+     *  @return Reference to the allocator after the assignment.
+     */
+    memory_mapping_allocator_gt& operator=(memory_mapping_allocator_gt const&) noexcept {
+        reset();
+        return *this;
+    }
+
+    /**
+     *  @brief Allocates an @b uninitialized block of memory of the specified size.
+     *  @param count_bytes The number of bytes to allocate.
+     *  @return A pointer to the allocated memory block, or `nullptr` if allocation fails.
+     */
+    inline byte_t* allocate(std::size_t count_bytes) noexcept {
+        std::size_t extended_bytes = divide_round_up<alignment_ak>(count_bytes) * alignment_ak;
+        // Check if the requested allocation size is absurd
+        if (extended_bytes > min_capacity())
+            return nullptr;
+
+        std::unique_lock<std::mutex> lock(mutex_);
+        if (!last_arena_ || (last_usage_ + extended_bytes > last_capacity_)) {
+            std::size_t new_cap = last_capacity_ * capacity_multiplier();
+#if defined(USEARCH_DEFINED_WINDOWS)
+            byte_t* new_arena = (byte_t*)(::VirtualAlloc(NULL, new_cap, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
+            if (new_arena == nullptr)
+                return nullptr;
+#else
+            byte_t* new_arena = (byte_t*)mmap(NULL, new_cap, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+            if (!new_arena)
+                return nullptr;
+#endif
+            std::memcpy(new_arena, &last_arena_, sizeof(byte_t*));
+            std::memcpy(new_arena + sizeof(byte_t*), &new_cap, sizeof(std::size_t));
+
+            wasted_space_ += total_reserved();
+            last_arena_ = new_arena;
+            last_capacity_ = new_cap;
+            last_usage_ = head_size();
+        }
+
+        wasted_space_ += extended_bytes - count_bytes;
+        return last_arena_ + exchange(last_usage_, last_usage_ + extended_bytes);
+    }
+
+    /**
+     *  @brief Returns the amount of memory used by the allocator across all arenas.
+     *  @return The amount of space in bytes.
+     */
+    std::size_t total_allocated() const noexcept {
+        if (!last_arena_)
+            return 0;
+        std::size_t total_used = 0;
+        std::size_t last_capacity = last_capacity_;
+        do {
+            total_used += last_capacity;
+            last_capacity /= capacity_multiplier();
+        } while (last_capacity >= min_capacity());
+        return total_used;
+    }
+
+    /**
+     *  @brief Returns the amount of wasted space due to alignment.
+     *  @return The amount of wasted space in bytes.
+     */
+    std::size_t total_wasted() const noexcept { return wasted_space_; }
+
+    /**
+     *  @brief Returns the amount of remaining memory already reserved but not yet used.
+     *  @return The amount of reserved memory in bytes.
+     */
+    std::size_t total_reserved() const noexcept { return last_arena_ ? last_capacity_ - last_usage_ : 0; }
+
+    /**
+     *  @warning The very first memory de-allocation discards all the arenas!
+     */
+    void deallocate(byte_t* = nullptr, std::size_t = 0) noexcept { reset(); }
+};
+
+using memory_mapping_allocator_t = memory_mapping_allocator_gt<>;
+
+/**
+ *  @brief  Utility class used to cast arrays of one scalar type to another,
+ *          avoiding unnecessary conversions.
+ */
+template <typename from_scalar_at, typename to_scalar_at> struct cast_gt {
+    inline bool operator()(byte_t const* input, std::size_t dim, byte_t* output) const {
+        from_scalar_at const* typed_input = reinterpret_cast<from_scalar_at const*>(input);
+        to_scalar_at* typed_output = reinterpret_cast<to_scalar_at*>(output);
+        auto converter = [](from_scalar_at from) { return to_scalar_at(from); };
+        std::transform(typed_input, typed_input + dim, typed_output, converter);
+        return true;
+    }
+};
+
+template <> struct cast_gt<f32_t, f32_t> {
+    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
+};
+
+template <> struct cast_gt<f64_t, f64_t> {
+    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
+};
+
+template <> struct cast_gt<f16_bits_t, f16_bits_t> {
+    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
+};
+
+template <> struct cast_gt<i8_bits_t, i8_bits_t> {
+    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
+};
+
+template <> struct cast_gt<b1x8_t, b1x8_t> {
+    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
+};
+
+template <typename from_scalar_at> struct cast_gt<from_scalar_at, b1x8_t> {
+    inline bool operator()(byte_t const* input, std::size_t dim, byte_t* output) const {
+        from_scalar_at const* typed_input = reinterpret_cast<from_scalar_at const*>(input);
+        unsigned char* typed_output = reinterpret_cast<unsigned char*>(output);
+        for (std::size_t i = 0; i != dim; ++i)
+            typed_output[i / CHAR_BIT] |= bool(typed_input[i]) ? (128 >> (i & (CHAR_BIT - 1))) : 0;
+        return true;
+    }
+};
+
+template <typename to_scalar_at> struct cast_gt<b1x8_t, to_scalar_at> {
+    inline bool operator()(byte_t const* input, std::size_t dim, byte_t* output) const {
+        unsigned char const* typed_input = reinterpret_cast<unsigned char const*>(input);
+        to_scalar_at* typed_output = reinterpret_cast<to_scalar_at*>(output);
+        for (std::size_t i = 0; i != dim; ++i)
+            typed_output[i] = bool(typed_input[i / CHAR_BIT] & (128 >> (i & (CHAR_BIT - 1))));
+        return true;
+    }
+};
+
+/**
+ *  @brief  Inner (Dot) Product distance.
+ */
+template <typename scalar_at = float, typename result_at = scalar_at> struct metric_ip_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+
+    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t dim) const noexcept {
+        result_t ab{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : ab)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != dim; ++i)
+            ab += result_t(a[i]) * result_t(b[i]);
+        return 1 - ab;
+    }
+};
+
+/**
+ *  @brief  Cosine (Angular) distance.
+ *          Identical to the Inner Product of normalized vectors.
+ *          Unless you are running on an tiny embedded platform, this metric
+ *          is recommended over `::metric_ip_gt` for low-precision scalars.
+ */
+template <typename scalar_at = float, typename result_at = scalar_at> struct metric_cos_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+
+    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t dim) const noexcept {
+        result_t ab{}, a2{}, b2{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : ab, a2, b2)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != dim; ++i)
+            ab += result_t(a[i]) * result_t(b[i]), //
+                a2 += square<result_t>(a[i]),      //
+                b2 += square<result_t>(b[i]);
+
+        result_t result_if_zero[2][2];
+        result_if_zero[0][0] = 1 - ab / (std::sqrt(a2) * std::sqrt(b2));
+        result_if_zero[0][1] = result_if_zero[1][0] = 1;
+        result_if_zero[1][1] = 0;
+        return result_if_zero[a2 == 0][b2 == 0];
+    }
+};
+
+/**
+ *  @brief  Squared Euclidean (L2) distance.
+ *          Square root is avoided at the end, as it won't affect the ordering.
+ */
+template <typename scalar_at = float, typename result_at = scalar_at> struct metric_l2sq_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+
+    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t dim) const noexcept {
+        result_t ab_deltas_sq{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : ab_deltas_sq)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != dim; ++i)
+            ab_deltas_sq += square(result_t(a[i]) - result_t(b[i]));
+        return ab_deltas_sq;
+    }
+};
+
+/**
+ *  @brief  Hamming distance computes the number of differing bits in
+ *          two arrays of integers. An example would be a textual document,
+ *          tokenized and hashed into a fixed-capacity bitset.
+ */
+template <typename scalar_at = std::uint64_t, typename result_at = std::size_t> struct metric_hamming_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+    static_assert( //
+        std::is_unsigned<scalar_t>::value ||
+            (std::is_enum<scalar_t>::value && std::is_unsigned<typename std::underlying_type<scalar_t>::type>::value),
+        "Hamming distance requires unsigned integral words");
+
+    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t words) const noexcept {
+        constexpr std::size_t bits_per_word_k = sizeof(scalar_t) * CHAR_BIT;
+        result_t matches{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : matches)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != words; ++i)
+            matches += std::bitset<bits_per_word_k>(a[i] ^ b[i]).count();
+        return matches;
+    }
+};
+
+/**
+ *  @brief  Tanimoto distance is the intersection over bitwise union.
+ *          Often used in chemistry and biology to compare molecular fingerprints.
+ */
+template <typename scalar_at = std::uint64_t, typename result_at = float> struct metric_tanimoto_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+    static_assert( //
+        std::is_unsigned<scalar_t>::value ||
+            (std::is_enum<scalar_t>::value && std::is_unsigned<typename std::underlying_type<scalar_t>::type>::value),
+        "Tanimoto distance requires unsigned integral words");
+    static_assert(std::is_floating_point<result_t>::value, "Tanimoto distance will be a fraction");
+
+    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t words) const noexcept {
+        constexpr std::size_t bits_per_word_k = sizeof(scalar_t) * CHAR_BIT;
+        result_t and_count{};
+        result_t or_count{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : and_count, or_count)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != words; ++i)
+            and_count += std::bitset<bits_per_word_k>(a[i] & b[i]).count(),
+                or_count += std::bitset<bits_per_word_k>(a[i] | b[i]).count();
+        return 1 - result_t(and_count) / or_count;
+    }
+};
+
+/**
+ *  @brief  Sorensen-Dice or F1 distance is the intersection over bitwise union.
+ *          Often used in chemistry and biology to compare molecular fingerprints.
+ */
+template <typename scalar_at = std::uint64_t, typename result_at = float> struct metric_sorensen_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+    static_assert( //
+        std::is_unsigned<scalar_t>::value ||
+            (std::is_enum<scalar_t>::value && std::is_unsigned<typename std::underlying_type<scalar_t>::type>::value),
+        "Sorensen-Dice distance requires unsigned integral words");
+    static_assert(std::is_floating_point<result_t>::value, "Sorensen-Dice distance will be a fraction");
+
+    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t words) const noexcept {
+        constexpr std::size_t bits_per_word_k = sizeof(scalar_t) * CHAR_BIT;
+        result_t and_count{};
+        result_t any_count{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : and_count, any_count)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != words; ++i)
+            and_count += std::bitset<bits_per_word_k>(a[i] & b[i]).count(),
+                any_count += std::bitset<bits_per_word_k>(a[i]).count() + std::bitset<bits_per_word_k>(b[i]).count();
+        return 1 - 2 * result_t(and_count) / any_count;
+    }
+};
+
+/**
+ *  @brief  Counts the number of matching elements in two unique sorted sets.
+ *          Can be used to compute the similarity between two textual documents
+ *          using the IDs of tokens present in them.
+ *          Similar to `metric_tanimoto_gt` for dense representations.
+ */
+template <typename scalar_at = std::int32_t, typename result_at = float> struct metric_jaccard_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+    static_assert(!std::is_floating_point<scalar_t>::value, "Jaccard distance requires integral scalars");
+
+    inline result_t operator()( //
+        scalar_t const* a, scalar_t const* b, std::size_t a_length, std::size_t b_length) const noexcept {
+        result_t intersection{};
+        std::size_t i{};
+        std::size_t j{};
+        while (i != a_length && j != b_length) {
+            intersection += a[i] == b[j];
+            i += a[i] < b[j];
+            j += a[i] >= b[j];
+        }
+        return 1 - intersection / (a_length + b_length - intersection);
+    }
+};
+
+/**
+ *  @brief  Measures Pearson Correlation between two sequences.
+ */
+template <typename scalar_at = float, typename result_at = float> struct metric_pearson_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+
+    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t dim) const noexcept {
+        result_t a_sum{}, b_sum{}, ab_sum{};
+        result_t a_sq_sum{}, b_sq_sum{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : a_sum, b_sum, ab_sum, a_sq_sum, b_sq_sum)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != dim; ++i) {
+            a_sum += result_t(a[i]);
+            b_sum += result_t(b[i]);
+            ab_sum += result_t(a[i]) * result_t(b[i]);
+            a_sq_sum += result_t(a[i]) * result_t(a[i]);
+            b_sq_sum += result_t(b[i]) * result_t(b[i]);
+        }
+        result_t denom = std::sqrt((dim * a_sq_sum - a_sum * a_sum) * (dim * b_sq_sum - b_sum * b_sum));
+        result_t corr = (dim * ab_sum - a_sum * b_sum) / denom;
+        return -corr;
+    }
+};
+
+struct cos_i8_t {
+    using scalar_t = i8_bits_t;
+    using result_t = f32_t;
+
+    inline result_t operator()(i8_bits_t const* a, i8_bits_t const* b, std::size_t dim) const noexcept {
+        std::int32_t ab{}, a2{}, b2{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : ab, a2, b2)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != dim; i++) {
+            std::int16_t ai{a[i]};
+            std::int16_t bi{b[i]};
+            ab += ai * bi;
+            a2 += square(ai);
+            b2 += square(bi);
+        }
+        return (ab != 0) ? (1.f - ab / (std::sqrt(a2) * std::sqrt(b2))) : 0;
+    }
+};
+
+struct l2sq_i8_t {
+    using scalar_t = i8_bits_t;
+    using result_t = f32_t;
+
+    inline result_t operator()(i8_bits_t const* a, i8_bits_t const* b, std::size_t dim) const noexcept {
+        std::int32_t ab_deltas_sq{};
+#if USEARCH_USE_OPENMP
+#pragma omp simd reduction(+ : ab_deltas_sq)
+#elif defined(USEARCH_DEFINED_CLANG)
+#pragma clang loop vectorize(enable)
+#elif defined(USEARCH_DEFINED_GCC)
+#pragma GCC ivdep
+#endif
+        for (std::size_t i = 0; i != dim; i++)
+            ab_deltas_sq += square(std::int16_t(a[i]) - std::int16_t(b[i]));
+        return ab_deltas_sq;
+    }
+};
+
+/**
+ *  @brief  Haversine distance for the shortest distance between two nodes on
+ *          the surface of a 3D sphere, defined with latitude and longitude.
+ */
+template <typename scalar_at = float, typename result_at = scalar_at> struct metric_haversine_gt {
+    using scalar_t = scalar_at;
+    using result_t = result_at;
+    static_assert(!std::is_integral<scalar_t>::value, "Latitude and longitude must be floating-node");
+
+    inline result_t operator()(scalar_t const* a, scalar_t const* b, std::size_t = 2) const noexcept {
+        result_t lat_a = a[0], lon_a = a[1];
+        result_t lat_b = b[0], lon_b = b[1];
+
+        result_t lat_delta = angle_to_radians<result_t>(lat_b - lat_a);
+        result_t lon_delta = angle_to_radians<result_t>(lon_b - lon_a);
+
+        result_t converted_lat_a = angle_to_radians<result_t>(lat_a);
+        result_t converted_lat_b = angle_to_radians<result_t>(lat_b);
+
+        result_t x = //
+            square(std::sin(lat_delta / 2.f)) +
+            std::cos(converted_lat_a) * std::cos(converted_lat_b) * square(std::sin(lon_delta / 2.f));
+
+        return std::atan2(std::sqrt(x), std::sqrt(1.f - x));
+    }
+};
+
+using distance_punned_t = float;
+using span_punned_t = span_gt<byte_t const>;
+
+/**
+ *  @brief  Type-punned metric class, that can wrap an existing STL `std::function`.
+ *          Additional annotation is useful for
+ */
+class metric_punned_t {
+  public:
+    using scalar_t = byte_t;
+    using result_t = distance_punned_t;
+    using stl_function_t = std::function<float(byte_t const*, byte_t const*)>;
+
+  private:
+    stl_function_t stl_function_;
+    std::size_t dimensions_ = 0;
+    metric_kind_t metric_kind_ = metric_kind_t::unknown_k;
+    scalar_kind_t scalar_kind_ = scalar_kind_t::unknown_k;
+    isa_kind_t isa_kind_ = isa_kind_t::auto_k;
+
+  public:
+    /**
+     *  @brief  Computes the distance between two vectors of fixed length.
+     *  ! The only relevant function in the object. Everything else is just dynamic dispatch.
+     */
+    inline result_t operator()(byte_t const* a, byte_t const* b) const noexcept { return stl_function_(a, b); }
+
+    inline metric_punned_t() = default;
+    inline metric_punned_t(metric_punned_t const&) = default;
+    inline metric_punned_t& operator=(metric_punned_t const&) = default;
+
+    inline metric_punned_t( //
+        stl_function_t stl_function, std::size_t dimensions = 0, metric_kind_t metric_kind = metric_kind_t::unknown_k,
+        scalar_kind_t scalar_kind = scalar_kind_t::unknown_k, isa_kind_t isa_kind = isa_kind_t::auto_k)
+        : stl_function_(stl_function), dimensions_(dimensions), metric_kind_(metric_kind), scalar_kind_(scalar_kind),
+          isa_kind_(isa_kind) {}
+
+    inline metric_punned_t( //
+        std::size_t dimensions, metric_kind_t metric_kind = metric_kind_t::cos_k,
+        scalar_kind_t scalar_kind = scalar_kind_t::f32_k) {
+        std::size_t bytes_per_vector = divide_round_up<CHAR_BIT>(dimensions * bits_per_scalar(scalar_kind));
+        *this = make_(bytes_per_vector, metric_kind, scalar_kind);
+        dimensions_ = dimensions;
+    }
+
+    std::size_t dimensions() const noexcept { return dimensions_; }
+    metric_kind_t metric_kind() const noexcept { return metric_kind_; }
+    scalar_kind_t scalar_kind() const noexcept { return scalar_kind_; }
+    isa_kind_t isa_kind() const noexcept { return isa_kind_; }
+
+    inline std::size_t bytes_per_vector() const noexcept {
+        return divide_round_up<CHAR_BIT>(dimensions_ * bits_per_scalar(scalar_kind_));
+    }
+
+    inline std::size_t scalar_words() const noexcept {
+        return divide_round_up(dimensions_ * bits_per_scalar(scalar_kind_), bits_per_scalar_word(scalar_kind_));
+    }
+
+  private:
+    static metric_punned_t make_(std::size_t bytes_per_vector, metric_kind_t metric_kind, scalar_kind_t scalar_kind) {
+
+        switch (metric_kind) {
+        case metric_kind_t::ip_k: return ip_metric_(bytes_per_vector, scalar_kind);
+        case metric_kind_t::cos_k: return cos_metric_(bytes_per_vector, scalar_kind);
+        case metric_kind_t::l2sq_k: return l2sq_metric_(bytes_per_vector, scalar_kind);
+        case metric_kind_t::pearson_k: return pearson_metric_(bytes_per_vector, scalar_kind);
+        case metric_kind_t::haversine_k: return haversine_metric_(scalar_kind);
+
+        case metric_kind_t::hamming_k:
+            return {to_stl_<metric_hamming_gt<b1x8_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::hamming_k,
+                    scalar_kind_t::b1x8_k, isa_kind_t::auto_k};
+
+        case metric_kind_t::jaccard_k: // Equivalent to Tanimoto
+        case metric_kind_t::tanimoto_k:
+            return {to_stl_<metric_tanimoto_gt<b1x8_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::tanimoto_k,
+                    scalar_kind_t::b1x8_k, isa_kind_t::auto_k};
+
+        case metric_kind_t::sorensen_k:
+            return {to_stl_<metric_sorensen_gt<b1x8_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::sorensen_k,
+                    scalar_kind_t::b1x8_k, isa_kind_t::auto_k};
+
+        default: return {};
+        }
+    }
+
+    template <typename typed_at> static stl_function_t to_stl_(std::size_t bytes) {
+        using scalar_t = typename typed_at::scalar_t;
+        return [=](byte_t const* a, byte_t const* b) -> result_t {
+            return typed_at{}((scalar_t const*)a, (scalar_t const*)b, bytes / sizeof(scalar_t));
+        };
+    }
+
+    template <typename scalar_at>
+    static stl_function_t pun_stl_(std::function<result_t(scalar_at const*, scalar_at const*)> typed) {
+        return [=](byte_t const* a, byte_t const* b) -> result_t {
+            return typed((scalar_at const*)a, (scalar_at const*)b);
+        };
+    }
+
+    // clang-format off
+    static metric_punned_t ip_metric_f32_(std::size_t bytes_per_vector) {
+        #if USEARCH_USE_SIMSIMD
+        if (hardware_supports(isa_kind_t::sve_k)) return {pun_stl_<f32_t>([=](f32_t const* a, f32_t const* b) { return simsimd_dot_f32_sve(a, b, bytes_per_vector / 4); }), bytes_per_vector, metric_kind_t::ip_k, scalar_kind_t::f32_k, isa_kind_t::sve_k};
+        if (hardware_supports(isa_kind_t::neon_k) && bytes_per_vector % 16 == 0) return {pun_stl_<f32_t>([=](f32_t const* a, f32_t const* b) { return simsimd_dot_f32x4_neon(a, b, bytes_per_vector / 4); }), bytes_per_vector, metric_kind_t::ip_k, scalar_kind_t::f32_k, isa_kind_t::neon_k};
+        if (hardware_supports(isa_kind_t::avx2_k) && bytes_per_vector % 16 == 0) return {pun_stl_<f32_t>([=](f32_t const* a, f32_t const* b) { return simsimd_dot_f32x4_avx2(a, b, bytes_per_vector / 4); }), bytes_per_vector, metric_kind_t::ip_k, scalar_kind_t::f32_k, isa_kind_t::avx2_k};
+        #endif
+        return {to_stl_<metric_ip_gt<f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::ip_k, scalar_kind_t::f32_k, isa_kind_t::auto_k};
+    }
+
+    static metric_punned_t cos_metric_f16_(std::size_t bytes_per_vector) {
+        #if USEARCH_USE_SIMSIMD
+        if (hardware_supports(isa_kind_t::avx512_k) && bytes_per_vector % 32 == 0) return {pun_stl_<simsimd_f16_t>([=](simsimd_f16_t const* a, simsimd_f16_t const* b) { return simsimd_cos_f16x16_avx512(a, b, bytes_per_vector / 2); }), bytes_per_vector, metric_kind_t::cos_k, scalar_kind_t::f16_k, isa_kind_t::avx512_k};
+        if (hardware_supports(isa_kind_t::neon_k) && bytes_per_vector % 8 == 0) return {pun_stl_<simsimd_f16_t>([=](simsimd_f16_t const* a, simsimd_f16_t const* b) { return simsimd_cos_f16x4_neon(a, b, bytes_per_vector / 2); }), bytes_per_vector, metric_kind_t::cos_k, scalar_kind_t::f16_k, isa_kind_t::neon_k};
+        #endif
+        return {to_stl_<metric_cos_gt<f16_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::cos_k, scalar_kind_t::f16_k, isa_kind_t::auto_k};
+    }
+
+    static metric_punned_t cos_metric_i8_(std::size_t bytes_per_vector) {
+        #if USEARCH_USE_SIMSIMD
+        if (hardware_supports(isa_kind_t::neon_k) && bytes_per_vector % 16 == 0) return {pun_stl_<int8_t>([=](int8_t const* a, int8_t const* b) { return simsimd_cos_i8x16_neon(a, b, bytes_per_vector); }), bytes_per_vector, metric_kind_t::cos_k, scalar_kind_t::i8_k, isa_kind_t::neon_k};
+        #endif
+        return {to_stl_<cos_i8_t>(bytes_per_vector), bytes_per_vector, metric_kind_t::cos_k, scalar_kind_t::i8_k, isa_kind_t::auto_k};
+    }
+
+    static metric_punned_t ip_metric_(std::size_t bytes_per_vector, scalar_kind_t scalar_kind) {        
+        switch (scalar_kind) { // The two most common numeric types for the most common metric have optimized versions
+        case scalar_kind_t::f32_k: return ip_metric_f32_(bytes_per_vector);
+        case scalar_kind_t::f16_k: return cos_metric_f16_(bytes_per_vector); // Dot-product accumulates error, Cosine-distance normalizes it
+        case scalar_kind_t::i8_k:  return cos_metric_i8_(bytes_per_vector);
+        case scalar_kind_t::f64_k: return {to_stl_<metric_ip_gt<f64_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::ip_k, scalar_kind_t::f64_k, isa_kind_t::auto_k};
+        default: return {};
+        }
+    }
+
+    static metric_punned_t l2sq_metric_(std::size_t bytes_per_vector, scalar_kind_t scalar_kind) {
+        switch (scalar_kind) {
+        case scalar_kind_t::i8_k: return {to_stl_<l2sq_i8_t>(bytes_per_vector), bytes_per_vector, metric_kind_t::l2sq_k, scalar_kind_t::i8_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f16_k: return {to_stl_<metric_l2sq_gt<f16_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::l2sq_k, scalar_kind_t::f16_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f32_k: return {to_stl_<metric_l2sq_gt<f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::l2sq_k, scalar_kind_t::f32_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f64_k: return {to_stl_<metric_l2sq_gt<f64_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::l2sq_k, scalar_kind_t::f64_k, isa_kind_t::auto_k};
+        default: return {};
+        }
+    }
+
+    static metric_punned_t cos_metric_(std::size_t bytes_per_vector, scalar_kind_t scalar_kind) {
+        switch (scalar_kind) {
+        case scalar_kind_t::i8_k: return cos_metric_i8_(bytes_per_vector);
+        case scalar_kind_t::f16_k: return cos_metric_f16_(bytes_per_vector);
+        case scalar_kind_t::f32_k: return {to_stl_<metric_cos_gt<f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::cos_k, scalar_kind_t::f32_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f64_k: return {to_stl_<metric_cos_gt<f64_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::cos_k, scalar_kind_t::f64_k, isa_kind_t::auto_k};
+        default: return {};
+        }
+    }
+
+    static metric_punned_t haversine_metric_(scalar_kind_t scalar_kind) {
+        std::size_t bytes_per_vector = 2u * bits_per_scalar(scalar_kind) / CHAR_BIT;
+        switch (scalar_kind) {
+        case scalar_kind_t::i8_k: return {to_stl_<metric_haversine_gt<i8_bits_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::haversine_k, scalar_kind_t::i8_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f16_k: return {to_stl_<metric_haversine_gt<f16_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::haversine_k, scalar_kind_t::f16_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f32_k: return {to_stl_<metric_haversine_gt<f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::haversine_k, scalar_kind_t::f32_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f64_k: return {to_stl_<metric_haversine_gt<f64_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::haversine_k, scalar_kind_t::f64_k, isa_kind_t::auto_k};
+        default: return {};
+        }
+    }
+
+    static metric_punned_t pearson_metric_(std::size_t bytes_per_vector, scalar_kind_t scalar_kind) {
+        switch (scalar_kind) {
+        case scalar_kind_t::i8_k: return {to_stl_<metric_pearson_gt<i8_bits_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::pearson_k, scalar_kind_t::i8_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f16_k: return {to_stl_<metric_pearson_gt<f16_t, f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::pearson_k, scalar_kind_t::f16_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f32_k: return {to_stl_<metric_pearson_gt<f32_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::pearson_k, scalar_kind_t::f32_k, isa_kind_t::auto_k};
+        case scalar_kind_t::f64_k: return {to_stl_<metric_pearson_gt<f64_t>>(bytes_per_vector), bytes_per_vector, metric_kind_t::pearson_k, scalar_kind_t::f64_k, isa_kind_t::auto_k};
+        default: return {};
+        }
+    }
+    // clang-format on
+};
+
+} // namespace usearch
+} // namespace unum
diff --git a/include/usearch/index_punned_dense.hpp b/include/usearch/index_punned_dense.hpp
deleted file mode 100644
index b2a19613..00000000
--- a/include/usearch/index_punned_dense.hpp
+++ /dev/null
@@ -1,1001 +0,0 @@
-#pragma once
-#include <stdlib.h> // `aligned_alloc`
-
-#include <functional>   // `std::function`
-#include <numeric>      // `std::iota`
-#include <shared_mutex> // `std::shared_mutex`
-#include <thread>       // `std::thread`
-#include <vector>       // `std::vector`
-
-#include <usearch/index.hpp>
-#include <usearch/index_punned_helpers.hpp>
-
-#include <tsl/robin_map.h>
-
-namespace unum {
-namespace usearch {
-
-struct cos_f8_t {
-    using scalar_t = f8_bits_t;
-    std::size_t dimensions;
-
-    inline cos_f8_t(std::size_t dims) noexcept : dimensions(dims) {}
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::cos_k; }
-    inline punned_distance_t operator()(f8_bits_t const* a, f8_bits_t const* b) const noexcept {
-        std::int32_t ab{}, a2{}, b2{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : ab, a2, b2)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != dimensions; i++) {
-            std::int16_t ai{a[i]};
-            std::int16_t bi{b[i]};
-            ab += ai * bi;
-            a2 += square(ai);
-            b2 += square(bi);
-        }
-        return (ab != 0) ? (1.f - ab / (std::sqrt(a2) * std::sqrt(b2))) : 0;
-    }
-};
-
-struct l2sq_f8_t {
-    using scalar_t = f8_bits_t;
-    std::size_t dimensions;
-
-    inline l2sq_f8_t(std::size_t dims) noexcept : dimensions(dims) {}
-    inline metric_kind_t kind() const noexcept { return metric_kind_t::l2sq_k; }
-    inline scalar_kind_t scalar_kind() const noexcept { return scalar_kind_t::f8_k; }
-    inline punned_distance_t operator()(f8_bits_t const* a, f8_bits_t const* b) const noexcept {
-        std::int32_t ab_deltas_sq{};
-#if USEARCH_USE_OPENMP
-#pragma omp simd reduction(+ : ab_deltas_sq)
-#elif defined(USEARCH_DEFINED_CLANG)
-#pragma clang loop vectorize(enable)
-#elif defined(USEARCH_DEFINED_GCC)
-#pragma GCC ivdep
-#endif
-        for (std::size_t i = 0; i != dimensions; i++)
-            ab_deltas_sq += square(std::int16_t(a[i]) - std::int16_t(b[i]));
-        return ab_deltas_sq;
-    }
-};
-
-struct index_punned_dense_metric_t {
-    using scalar_t = byte_t;
-    using result_t = punned_distance_t;
-    using view_t = punned_vector_view_t;
-    using stl_func_t = std::function<punned_distance_t(punned_vector_view_t, punned_vector_view_t)>;
-
-    stl_func_t func_;
-    metric_kind_t kind_ = metric_kind_t::unknown_k;
-    scalar_kind_t scalar_kind_ = scalar_kind_t::unknown_k;
-    isa_t isa_ = isa_t::auto_k;
-
-    index_punned_dense_metric_t() = default;
-
-    template <typename typed_at, typename scalar_at = typename typed_at::scalar_t>
-    index_punned_dense_metric_t(typed_at typed)
-        : index_punned_dense_metric_t(typed.kind(), isa_t::auto_k, scalar_at{}, typed) {}
-
-    template <typename typed_at, typename scalar_at>
-    index_punned_dense_metric_t(metric_kind_t kind, isa_t isa, scalar_at, typed_at metric) {
-        using scalar_t = scalar_at;
-        using typed_view_t = span_gt<scalar_t const>;
-        func_ = [=](view_t a, view_t b) -> result_t {
-            std::size_t dims = a.size() / sizeof(scalar_t);
-            typed_view_t a_typed{(scalar_t const*)a.data(), dims};
-            typed_view_t b_typed{(scalar_t const*)b.data(), dims};
-            return metric(a_typed, b_typed);
-        };
-        if (std::is_same<scalar_at, f8_bits_t>())
-            scalar_kind_ = scalar_kind_t::f8_k;
-        else if (std::is_same<scalar_at, f16_bits_t>())
-            scalar_kind_ = scalar_kind_t::f16_k;
-        else
-            scalar_kind_ = common_scalar_kind<scalar_at>();
-        kind_ = kind;
-        isa_ = isa;
-    }
-
-    inline metric_kind_t kind() const noexcept { return kind_; }
-    inline scalar_kind_t scalar_kind() const noexcept { return scalar_kind_; }
-    inline result_t operator()(view_t a, view_t b) const { return func_(a, b); }
-};
-
-constexpr std::size_t default_removals_cycle() { return 64; }
-
-template <typename label_at, typename std::enable_if<std::is_integral<label_at>::value>::type* = nullptr>
-label_at default_free_value() {
-    return std::numeric_limits<label_at>::max();
-}
-
-template <typename label_at, typename std::enable_if<std::is_same<label_at, uint40_t>::value>::type* = nullptr>
-uint40_t default_free_value() {
-    return uint40_t::max();
-}
-
-template <                                                        //
-    typename label_at,                                            //
-    typename std::enable_if<!std::is_integral<label_at>::value && //
-                            !std::is_same<label_at, uint40_t>::value>::type* = nullptr>
-label_at default_free_value() {
-    return label_at();
-}
-
-/**
- *  @brief  Oversimplified type-punned index for equidimensional vectors
- *          with automatic @b down-casting, hardware-specific @b SIMD metrics,
- *          and ability to @b remove existing vectors, common in Semantic Caching
- *          applications.
- */
-template <typename label_at = std::int64_t, typename id_at = std::uint32_t> //
-class index_punned_dense_gt {
-  public:
-    using label_t = label_at;
-    using id_t = id_at;
-    using distance_t = punned_distance_t;
-    /// @brief Punned metric object.
-    using metric_t = index_punned_dense_metric_t;
-
-  private:
-    /// @brief Schema: input buffer, bytes in input buffer, output buffer.
-    using cast_t = std::function<bool(byte_t const*, std::size_t, byte_t*)>;
-    /// @brief Punned index.
-    using index_t = index_gt<metric_t, label_t, id_t, aligned_allocator_t, memory_mapping_allocator_t>;
-    using index_allocator_t = aligned_allocator_gt<index_t, 64>;
-
-    using member_iterator_t = typename index_t::member_iterator_t;
-    using member_citerator_t = typename index_t::member_citerator_t;
-    using member_ref_t = typename index_t::member_ref_t;
-    using member_cref_t = typename index_t::member_cref_t;
-
-    /// @brief Number of unique dimensions in the vectors.
-    std::size_t dimensions_ = 0;
-    /// @brief Similar to `dimensions_`, but different for fraction byte-length scalars.
-    std::size_t scalar_words_ = 0;
-    std::size_t expansion_add_ = 0;
-    std::size_t expansion_search_ = 0;
-    index_t* typed_ = nullptr;
-
-    std::size_t casted_vector_bytes_ = 0;
-    mutable std::vector<byte_t> cast_buffer_;
-    struct casts_t {
-        cast_t from_b1x8;
-        cast_t from_f8;
-        cast_t from_f16;
-        cast_t from_f32;
-        cast_t from_f64;
-
-        cast_t to_b1x8;
-        cast_t to_f8;
-        cast_t to_f16;
-        cast_t to_f32;
-        cast_t to_f64;
-    } casts_;
-
-    metric_t root_metric_;
-
-    mutable std::vector<std::size_t> available_threads_;
-    mutable std::mutex available_threads_mutex_;
-
-    using shared_mutex_t = std::mutex; // TODO: Find an OS-compatible solution
-    using shared_lock_t = std::unique_lock<shared_mutex_t>;
-    using unique_lock_t = std::unique_lock<shared_mutex_t>;
-
-    mutable shared_mutex_t labeled_lookup_mutex_;
-    tsl::robin_map<label_t, id_t> labeled_lookup_;
-
-    mutable std::mutex free_ids_mutex_;
-    ring_gt<id_t> free_ids_;
-    label_t free_label_;
-
-  public:
-    using search_result_t = typename index_t::search_result_t;
-    using add_result_t = typename index_t::add_result_t;
-    using serialization_result_t = typename index_t::serialization_result_t;
-    using join_result_t = typename index_t::join_result_t;
-    using stats_t = typename index_t::stats_t;
-    using match_t = typename index_t::match_t;
-
-    index_punned_dense_gt() = default;
-    index_punned_dense_gt(index_punned_dense_gt&& other)
-        : dimensions_(std::move(other.dimensions_)),                   //
-          scalar_words_(std::move(other.scalar_words_)),               //
-          expansion_add_(std::move(other.expansion_add_)),             //
-          expansion_search_(std::move(other.expansion_search_)),       //
-          typed_(exchange(other.typed_, nullptr)),                     //
-          casted_vector_bytes_(std::move(other.casted_vector_bytes_)), //
-          cast_buffer_(std::move(other.cast_buffer_)),                 //
-          casts_(std::move(other.casts_)),                             //
-          root_metric_(std::move(other.root_metric_)),                 //
-          available_threads_(std::move(other.available_threads_)),     //
-          labeled_lookup_(std::move(other.labeled_lookup_)),           //
-          free_ids_(std::move(other.free_ids_)),                       //
-          free_label_(std::move(other.free_label_)) {}                 //
-
-    index_punned_dense_gt& operator=(index_punned_dense_gt&& other) {
-        swap(other);
-        return *this;
-    }
-
-    /**
-     *  @brief Swaps the contents of this index with another index.
-     *  @param other The other index to swap with.
-     */
-    void swap(index_punned_dense_gt& other) {
-        std::swap(dimensions_, other.dimensions_);
-        std::swap(scalar_words_, other.scalar_words_);
-        std::swap(expansion_add_, other.expansion_add_);
-        std::swap(expansion_search_, other.expansion_search_);
-        std::swap(typed_, other.typed_);
-        std::swap(casted_vector_bytes_, other.casted_vector_bytes_);
-        std::swap(cast_buffer_, other.cast_buffer_);
-        std::swap(casts_, other.casts_);
-        std::swap(root_metric_, other.root_metric_);
-        std::swap(available_threads_, other.available_threads_);
-        std::swap(labeled_lookup_, other.labeled_lookup_);
-        std::swap(free_ids_, other.free_ids_);
-        std::swap(free_label_, other.free_label_);
-    }
-
-    ~index_punned_dense_gt() {
-        if (typed_)
-            typed_->~index_t();
-        index_allocator_t{}.deallocate(typed_, 1);
-        typed_ = nullptr;
-    }
-
-    static index_config_t optimize(index_config_t config) { return index_t::optimize(config); }
-
-    /**
-     *  @brief Constructs an instance of ::index_punned_dense_gt.
-     *  @param[in] dimensions The of dimensions per vector.
-     *  @param[in] metric One of the default supported metric @b kinds for distance measurements.
-     *  @param[in] config The index configuration (optional).
-     *  @param[in] accuracy The scalar kind used for internal representations (optional).
-     *  @param[in] expansion_add The expansion factor for adding vectors (optional).
-     *  @param[in] expansion_search The expansion factor for searching vectors (optional).
-     *  @param[in] free_label The label used for freed vectors (optional).
-     *  @return An instance of ::index_punned_dense_gt.
-     */
-    static index_punned_dense_gt make(                             //
-        std::size_t dimensions, metric_kind_t metric,              //
-        index_config_t config = {},                                //
-        scalar_kind_t accuracy = scalar_kind_t::f32_k,             //
-        std::size_t expansion_add = default_expansion_add(),       //
-        std::size_t expansion_search = default_expansion_search(), //
-        label_t free_label = default_free_value<label_t>()) {
-
-        return make_(                                //
-            dimensions, accuracy,                    //
-            config, expansion_add, expansion_search, //
-            make_metric_(metric, dimensions, accuracy), make_casts_(accuracy), free_label);
-    }
-
-    /**
-     *  @brief Constructs an instance of ::index_punned_dense_gt.
-     *  @param[in] dimensions The of dimensions per vector.
-     *  @param[in] metric The @b ad-hoc metric wrapped for third-party distance measures.
-     *  @param[in] config The index configuration (optional).
-     *  @param[in] accuracy The scalar kind used for internal representations (optional).
-     *  @param[in] expansion_add The expansion factor for adding vectors (optional).
-     *  @param[in] expansion_search The expansion factor for searching vectors (optional).
-     *  @param[in] free_label The label used for freed vectors (optional).
-     *  @return An instance of ::index_punned_dense_gt.
-     */
-    static index_punned_dense_gt make(                             //
-        std::size_t dimensions, metric_t metric,                   //
-        index_config_t config = {},                                //
-        scalar_kind_t accuracy = scalar_kind_t::f32_k,             //
-        std::size_t expansion_add = default_expansion_add(),       //
-        std::size_t expansion_search = default_expansion_search(), //
-        label_t free_label = default_free_value<label_t>()) {
-
-        return make_(                                //
-            dimensions, accuracy,                    //
-            config, expansion_add, expansion_search, //
-            metric_t(metric), make_casts_(accuracy), free_label);
-    }
-
-    std::size_t dimensions() const { return dimensions_; }
-    std::size_t scalar_words() const { return scalar_words_; }
-    std::size_t connectivity() const { return typed_->connectivity(); }
-    std::size_t size() const { return typed_->size() - free_ids_.size(); }
-    std::size_t capacity() const { return typed_->capacity(); }
-    std::size_t max_level() const noexcept { return typed_->max_level(); }
-    index_config_t const& config() const { return typed_->config(); }
-    index_limits_t const& limits() const { return typed_->limits(); }
-
-    metric_t const& metric() const { return root_metric_; }
-    std::size_t expansion_add() const { return expansion_add_; }
-    std::size_t expansion_search() const { return expansion_search_; }
-    void change_expansion_add(std::size_t n) { expansion_add_ = n; }
-    void change_expansion_search(std::size_t n) { expansion_search_ = n; }
-
-    member_citerator_t cbegin() const { return typed_->cbegin(); }
-    member_citerator_t cend() const { return typed_->cend(); }
-    member_citerator_t begin() const { return typed_->begin(); }
-    member_citerator_t end() const { return typed_->end(); }
-    member_iterator_t begin() { return typed_->begin(); }
-    member_iterator_t end() { return typed_->end(); }
-
-    stats_t stats() const { return typed_->stats(); }
-    stats_t stats(std::size_t level) const { return typed_->stats(level); }
-
-    std::size_t memory_usage() const {
-        return typed_->memory_usage(0) +                 //
-               typed_->tape_allocator().total_wasted() + //
-               typed_->tape_allocator().total_reserved();
-    }
-
-    // clang-format off
-    add_result_t add(label_t label, b1x8_t const* vector) { return add_(label, vector, casts_.from_b1x8); }
-    add_result_t add(label_t label, f8_bits_t const* vector) { return add_(label, vector, casts_.from_f8); }
-    add_result_t add(label_t label, f16_t const* vector) { return add_(label, vector, casts_.from_f16); }
-    add_result_t add(label_t label, f32_t const* vector) { return add_(label, vector, casts_.from_f32); }
-    add_result_t add(label_t label, f64_t const* vector) { return add_(label, vector, casts_.from_f64); }
-
-    add_result_t add(label_t label, b1x8_t const* vector, add_config_t config) { return add_(label, vector, config, casts_.from_b1x8); }
-    add_result_t add(label_t label, f8_bits_t const* vector, add_config_t config) { return add_(label, vector, config, casts_.from_f8); }
-    add_result_t add(label_t label, f16_t const* vector, add_config_t config) { return add_(label, vector, config, casts_.from_f16); }
-    add_result_t add(label_t label, f32_t const* vector, add_config_t config) { return add_(label, vector, config, casts_.from_f32); }
-    add_result_t add(label_t label, f64_t const* vector, add_config_t config) { return add_(label, vector, config, casts_.from_f64); }
-
-    search_result_t search(b1x8_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_b1x8); }
-    search_result_t search(f8_bits_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_f8); }
-    search_result_t search(f16_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_f16); }
-    search_result_t search(f32_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_f32); }
-    search_result_t search(f64_t const* vector, std::size_t wanted) const { return search_(vector, wanted, casts_.from_f64); }
-
-    search_result_t search(b1x8_t const* vector, std::size_t wanted, search_config_t config) const { return search_(vector, wanted, config, casts_.from_b1x8); }
-    search_result_t search(f8_bits_t const* vector, std::size_t wanted, search_config_t config) const { return search_(vector, wanted, config, casts_.from_f8); }
-    search_result_t search(f16_t const* vector, std::size_t wanted, search_config_t config) const { return search_(vector, wanted, config, casts_.from_f16); }
-    search_result_t search(f32_t const* vector, std::size_t wanted, search_config_t config) const { return search_(vector, wanted, config, casts_.from_f32); }
-    search_result_t search(f64_t const* vector, std::size_t wanted, search_config_t config) const { return search_(vector, wanted, config, casts_.from_f64); }
-
-    bool get(label_t label, b1x8_t* vector) const { return get_(label, vector, casts_.to_b1x8); }
-    bool get(label_t label, f8_bits_t* vector) const { return get_(label, vector, casts_.to_f8); }
-    bool get(label_t label, f16_t* vector) const { return get_(label, vector, casts_.to_f16); }
-    bool get(label_t label, f32_t* vector) const { return get_(label, vector, casts_.to_f32); }
-    bool get(label_t label, f64_t* vector) const { return get_(label, vector, casts_.to_f64); }
-    // clang-format on
-
-    search_result_t empty_search_result() const { return search_result_t{*typed_}; }
-
-    /**
-     *  @brief Reserves memory for the index and the labeled lookup.
-     *  @return `true` if the memory reservation was successful, `false` otherwise.
-     */
-    bool reserve(index_limits_t limits) {
-        {
-            unique_lock_t lock(labeled_lookup_mutex_);
-            labeled_lookup_.reserve(limits.members);
-        }
-        return typed_->reserve(limits);
-    }
-
-    /**
-     *  @brief Clears the whole index, reclaiming the memory.
-     */
-    void clear() {
-        unique_lock_t lookup_lock(labeled_lookup_mutex_);
-        std::unique_lock<std::mutex> free_lock(free_ids_mutex_);
-        typed_->clear();
-        labeled_lookup_.clear();
-        free_ids_.clear();
-    }
-
-    /**
-     *  @brief Saves the index to a file.
-     *  @param[in] path The path to the file.
-     *  @return Outcome descriptor explictly convertable to boolean.
-     */
-    serialization_result_t save(char const* path) const { return typed_->save(path); }
-
-    /**
-     *  @brief Parses the index from file to RAM.
-     *  @param[in] path The path to the file.
-     *  @return Outcome descriptor explictly convertable to boolean.
-     */
-    serialization_result_t load(char const* path) {
-        serialization_result_t result = typed_->load(path);
-        if (result)
-            reindex_labels_();
-        return result;
-    }
-
-    /**
-     *  @brief Parses the index from file, without loading it into RAM.
-     *  @param[in] path The path to the file.
-     *  @return Outcome descriptor explictly convertable to boolean.
-     */
-    serialization_result_t view(char const* path) {
-        serialization_result_t result = typed_->view(path);
-        if (result)
-            reindex_labels_();
-        return result;
-    }
-
-    /**
-     *  @brief Checks if a vector with specidied label is present.
-     *  @return `true` if the label is present in the index, `false` otherwise.
-     */
-    bool contains(label_t label) const {
-        shared_lock_t lock(labeled_lookup_mutex_);
-        return labeled_lookup_.contains(label);
-    }
-
-    struct labeling_result_t {
-        error_t error{};
-        std::size_t completed{};
-
-        explicit operator bool() const noexcept { return !error; }
-        labeling_result_t failed(error_t message) noexcept {
-            error = std::move(message);
-            return std::move(*this);
-        }
-    };
-
-    /**
-     *  @brief Removes an entry with the specified label from the index.
-     *  @param[in] label The label of the entry to remove.
-     *  @return The ::labeling_result_t indicating the result of the removal operation.
-     *          If the removal was successful, `result.completed` will be `true`.
-     *          If the label was not found in the index, `result.completed` will be `false`.
-     *          If an error occurred during the removal operation, `result.error` will contain an error message.
-     */
-    labeling_result_t remove(label_t label) {
-        labeling_result_t result;
-
-        unique_lock_t lookup_lock(labeled_lookup_mutex_);
-        auto id_terator = labeled_lookup_.find(label);
-        if (id_terator == labeled_lookup_.end())
-            return result;
-
-        // Grow the removed entries ring, if needed
-        std::unique_lock<std::mutex> free_lock(free_ids_mutex_);
-        if (free_ids_.size() == free_ids_.capacity())
-            if (!free_ids_.reserve((std::max<std::size_t>)(free_ids_.capacity() * 2, 64ul)))
-                return result.failed("Can't allocate memory for a free-list");
-
-        // A removed entry would be:
-        // - present in `free_ids_`
-        // - missing in the `labeled_lookup_`
-        // - marked in the `typed_` index with a `free_label_`
-        id_t id = id_terator->second;
-        free_ids_.push(id);
-        labeled_lookup_.erase(id_terator);
-        typed_->at(id).label = free_label_;
-        result.completed = true;
-
-        return result;
-    }
-
-    /**
-     *  @brief Removes multiple entries with the specified labels from the index.
-     *  @param[in] labels_begin The beginning of the labels range.
-     *  @param[in] labels_end The ending of the labels range.
-     *  @return The ::labeling_result_t indicating the result of the removal operation.
-     *          `result.completed` will contain the number of labels that were successfully removed.
-     *          `result.error` will contain an error message if an error occurred during the removal operation.
-     */
-    template <typename labels_iterator_at>
-    labeling_result_t remove(labels_iterator_at&& labels_begin, labels_iterator_at&& labels_end) {
-
-        labeling_result_t result;
-        unique_lock_t lookup_lock(labeled_lookup_mutex_);
-        std::unique_lock<std::mutex> free_lock(free_ids_mutex_);
-
-        // Grow the removed entries ring, if needed
-        std::size_t count_requests = std::distance(labels_begin, labels_end);
-        if (!free_ids_.reserve(free_ids_.size() + count_requests))
-            return result.failed("Can't allocate memory for a free-list");
-
-        // Remove them one-by-one
-        for (auto label_it = labels_begin; label_it != labels_end; ++label_it) {
-            label_t label = *label_it;
-            auto id_terator = labeled_lookup_.find(label);
-            if (id_terator == labeled_lookup_.end())
-                continue;
-
-            // A removed entry would be:
-            // - present in `free_ids_`
-            // - missing in the `labeled_lookup_`
-            // - marked in the `typed_` index with a `free_label_`
-            id_t id = id_terator->second;
-            free_ids_.push(id);
-            labeled_lookup_.erase(id_terator);
-            typed_->at(id).label = free_label_;
-            result.completed += 1;
-        }
-
-        return result;
-    }
-
-    /**
-     *  @brief Renames an entry with the specified label to a new label.
-     *  @param[in] from The current label of the entry to rename.
-     *  @param[in] to The new label to assign to the entry.
-     *  @return The ::labeling_result_t indicating the result of the rename operation.
-     *          If the rename was successful, `result.completed` will be `true`.
-     *          If the entry with the current label was not found, `result.completed` will be `false`.
-     */
-    labeling_result_t rename(label_t from, label_t to) {
-        labeling_result_t result;
-        unique_lock_t lookup_lock(labeled_lookup_mutex_);
-        auto id_terator = labeled_lookup_.find(from);
-        if (id_terator == labeled_lookup_.end())
-            return result;
-
-        id_t id = id_terator->second;
-        labeled_lookup_.erase(id_terator);
-        labeled_lookup_.emplace(to, id);
-        typed_->at(id).label = to;
-        result.completed = true;
-        return result;
-    }
-
-    /**
-     *  @brief Exports a range of labels for the vectors present in the index.
-     *  @param[out] labels Pointer to the array where the labels will be exported.
-     *  @param[in] offset The number of labels to skip. Useful for pagination.
-     *  @param[in] limit The maximum number of labels to export, that can fit in ::labels.
-     */
-    void export_labels(label_t* labels, std::size_t offset, std::size_t limit) const {
-        shared_lock_t lock(labeled_lookup_mutex_);
-        auto it = labeled_lookup_.begin();
-        offset = (std::min)(offset, labeled_lookup_.size());
-        std::advance(it, offset);
-        for (; it != labeled_lookup_.end() && limit; ++it, ++labels, --limit)
-            *labels = it->first;
-    }
-
-    /**
-     *  @brief  Adapts the Male-Optimal Stable Marriage algorithm for unequal sets
-     *          to perform fast one-to-one matching between two large collections
-     *          of vectors, using approximate nearest neighbors search.
-     *
-     *  @param[inout] first_to_second Container to map ::first labels to ::second.
-     *  @param[inout] second_to_first Container to map ::second labels to ::first.
-     *  @param[in] executor Thread-pool to execute the job in parallel.
-     *  @param[in] progress Callback to report the execution progress.
-     */
-    template <                                                        //
-        typename first_to_second_at = dummy_label_to_label_mapping_t, //
-        typename second_to_first_at = dummy_label_to_label_mapping_t, //
-        typename executor_at = dummy_executor_t,                      //
-        typename progress_at = dummy_progress_t                       //
-        >
-    static join_result_t join(                                       //
-        index_punned_dense_gt const& first,                          //
-        index_punned_dense_gt const& second,                         //
-        join_config_t config = {},                                   //
-        first_to_second_at&& first_to_second = first_to_second_at{}, //
-        second_to_first_at&& second_to_first = second_to_first_at{}, //
-        executor_at&& executor = executor_at{},                      //
-        progress_at&& progress = progress_at{}) noexcept {
-
-        return index_t::join(                                  //
-            *first.typed_, *second.typed_, config,             //
-            std::forward<first_to_second_at>(first_to_second), //
-            std::forward<second_to_first_at>(second_to_first), //
-            std::forward<executor_at>(executor),               //
-            std::forward<progress_at>(progress));
-    }
-
-    struct copy_result_t {
-        index_punned_dense_gt index;
-        error_t error;
-
-        explicit operator bool() const noexcept { return !error; }
-        copy_result_t failed(error_t message) noexcept {
-            error = std::move(message);
-            return std::move(*this);
-        }
-    };
-
-    /**
-     *  @brief Copies the ::index_punned_dense_gt @b with all the data in it.
-     *  @param config The copy configuration (optional).
-     *  @return A copy of the ::index_punned_dense_gt instance.
-     */
-    copy_result_t copy(copy_config_t config = {}) const {
-        copy_result_t result = fork();
-        if (!result)
-            return result;
-        auto typed_result = typed_->copy(config);
-        if (!typed_result)
-            return result.failed(std::move(typed_result.error));
-        if (!result.index.free_ids_.reserve(free_ids_.size()))
-            return result.failed(std::move(typed_result.error));
-        for (std::size_t i = 0; i != free_ids_.size(); ++i)
-            result.index.free_ids_.push(free_ids_[i]);
-
-        result.index.labeled_lookup_ = labeled_lookup_;
-        *result.index.typed_ = std::move(typed_result.index);
-        return result;
-    }
-
-    /**
-     *  @brief Copies the ::index_punned_dense_gt model @b without any data.
-     *  @return A similarly configured ::index_punned_dense_gt instance.
-     */
-    copy_result_t fork() const {
-        copy_result_t result;
-        index_punned_dense_gt& other = result.index;
-
-        other.dimensions_ = dimensions_;
-        other.scalar_words_ = scalar_words_;
-        other.expansion_add_ = expansion_add_;
-        other.expansion_search_ = expansion_search_;
-        other.casted_vector_bytes_ = casted_vector_bytes_;
-        other.cast_buffer_ = cast_buffer_;
-        other.casts_ = casts_;
-
-        other.root_metric_ = root_metric_;
-        other.available_threads_ = available_threads_;
-
-        index_t* raw = index_allocator_t{}.allocate(1);
-        if (!raw)
-            return result.failed("Can't allocate the index");
-
-        new (raw) index_t(config(), root_metric_);
-        other.typed_ = raw;
-        return result;
-    }
-
-    struct compaction_result_t {
-        error_t error{};
-        std::size_t pruned_edges{};
-
-        explicit operator bool() const noexcept { return !error; }
-        compaction_result_t failed(error_t message) noexcept {
-            error = std::move(message);
-            return std::move(*this);
-        }
-    };
-
-    /**
-     *  @brief Performs compaction on the index, pruning links to removed entries.
-     *  @param executor The executor parallel processing. Default ::dummy_executor_t single-threaded.
-     *  @param progress The progress tracker instance to use. Default ::dummy_progress_t reports nothing.
-     *  @return The ::compaction_result_t indicating the result of the compaction operation.
-     *          `result.pruned_edges` will contain the number of edges that were removed.
-     *          `result.error` will contain an error message if an error occurred during the compaction operation.
-     */
-    template <typename executor_at = dummy_executor_t, typename progress_at = dummy_progress_t>
-    compaction_result_t compact(executor_at&& executor = executor_at{}, progress_at&& progress = progress_at{}) {
-        compaction_result_t result;
-        std::atomic<std::size_t> pruned_edges;
-        auto disallow = [&](member_cref_t const& member) noexcept {
-            bool freed = member.label == free_label_;
-            pruned_edges += freed;
-            return freed;
-        };
-        typed_->isolate(disallow, std::forward<executor_at>(executor), std::forward<progress_at>(progress));
-        result.pruned_edges = pruned_edges;
-        return result;
-    }
-
-  private:
-    struct thread_lock_t {
-        index_punned_dense_gt const& parent;
-        std::size_t thread_id;
-
-        ~thread_lock_t() { parent.thread_unlock_(thread_id); }
-    };
-
-    thread_lock_t thread_lock_() const {
-        available_threads_mutex_.lock();
-        std::size_t thread_id = available_threads_.back();
-        available_threads_.pop_back();
-        available_threads_mutex_.unlock();
-        return {*this, thread_id};
-    }
-
-    void thread_unlock_(std::size_t thread_id) const {
-        available_threads_mutex_.lock();
-        available_threads_.push_back(thread_id);
-        available_threads_mutex_.unlock();
-    }
-
-    template <typename scalar_at>
-    add_result_t add_(label_t label, scalar_at const* vector, add_config_t config, cast_t const& cast) {
-        byte_t const* vector_data = reinterpret_cast<byte_t const*>(vector);
-        std::size_t vector_bytes = dimensions_ * sizeof(scalar_at);
-
-        byte_t* casted_data = cast_buffer_.data() + casted_vector_bytes_ * config.thread;
-        bool casted = cast(vector_data, dimensions_, casted_data);
-        if (casted)
-            vector_data = casted_data, vector_bytes = casted_vector_bytes_, config.store_vector = true;
-
-        // Check if there are some removed entries, whose nodes we can reuse
-        id_t free_id = default_free_value<id_t>();
-        {
-            std::unique_lock<std::mutex> lock(free_ids_mutex_);
-            free_ids_.try_pop(free_id);
-        }
-
-        // Perform the insertion or the update
-        add_result_t result =                     //
-            free_id != default_free_value<id_t>() //
-                ? typed_->update(free_id, label, {vector_data, vector_bytes}, config)
-                : typed_->add(label, {vector_data, vector_bytes}, config);
-        {
-            unique_lock_t lock(labeled_lookup_mutex_);
-            labeled_lookup_.emplace(label, result.id);
-        }
-        return result;
-    }
-
-    template <typename scalar_at>
-    search_result_t search_(                         //
-        scalar_at const* vector, std::size_t wanted, //
-        search_config_t config, cast_t const& cast) const {
-
-        byte_t const* vector_data = reinterpret_cast<byte_t const*>(vector);
-        std::size_t vector_bytes = dimensions_ * sizeof(scalar_at);
-
-        byte_t* casted_data = cast_buffer_.data() + casted_vector_bytes_ * config.thread;
-        bool casted = cast(vector_data, dimensions_, casted_data);
-        if (casted)
-            vector_data = casted_data, vector_bytes = casted_vector_bytes_;
-
-        auto allow = [=](match_t const& match) noexcept { return match.member.label != free_label_; };
-        return typed_->search({vector_data, vector_bytes}, wanted, config, allow);
-    }
-
-    id_t lookup_id_(label_t label) const {
-        shared_lock_t lock(labeled_lookup_mutex_);
-        return labeled_lookup_.at(label);
-    }
-
-    void reindex_labels_() {
-
-        // Estimate number of entries first
-        std::size_t count_total = typed_->size();
-        std::size_t count_removed = 0;
-        for (std::size_t i = 0; i != count_total; ++i) {
-            member_cref_t member = typed_->at(i);
-            count_removed += member.label == free_label_;
-        }
-
-        unique_lock_t lock(labeled_lookup_mutex_);
-        labeled_lookup_.clear();
-        labeled_lookup_.reserve(count_total - count_removed);
-        free_ids_.clear();
-        free_ids_.reserve(count_removed);
-        for (std::size_t i = 0; i != typed_->size(); ++i) {
-            member_cref_t member = typed_->at(i);
-            if (member.label == free_label_)
-                free_ids_.push(static_cast<id_t>(i));
-            else
-                labeled_lookup_.emplace(member.label, static_cast<id_t>(i));
-        }
-    }
-
-    template <typename scalar_at> bool get_(label_t label, scalar_at* reconstructed, cast_t const& cast) const {
-        id_t id;
-        // Find the matching ID
-        {
-            shared_lock_t lock(labeled_lookup_mutex_);
-            auto it = labeled_lookup_.find(label);
-            if (it == labeled_lookup_.end())
-                return false;
-            id = it->second;
-        }
-        // Export the entry
-        member_cref_t member = typed_->at(id);
-        byte_t const* punned_vector = reinterpret_cast<byte_t const*>(member.vector.data());
-        bool casted = cast(punned_vector, dimensions_, (byte_t*)reconstructed);
-        if (!casted)
-            std::memcpy(reconstructed, punned_vector, casted_vector_bytes_);
-        return true;
-    }
-
-    template <typename scalar_at> add_result_t add_(label_t label, scalar_at const* vector, cast_t const& cast) {
-        thread_lock_t lock = thread_lock_();
-        add_config_t add_config;
-        add_config.thread = lock.thread_id;
-        return add_(label, vector, add_config, cast);
-    }
-
-    template <typename scalar_at>
-    search_result_t search_(                         //
-        scalar_at const* vector, std::size_t wanted, //
-        cast_t const& cast) const {
-        thread_lock_t lock = thread_lock_();
-        search_config_t search_config;
-        search_config.thread = lock.thread_id;
-        return search_(vector, wanted, search_config, cast);
-    }
-
-    static index_punned_dense_gt make_(                                                 //
-        std::size_t dimensions, scalar_kind_t scalar_kind,                              //
-        index_config_t config, std::size_t expansion_add, std::size_t expansion_search, //
-        metric_t metric, casts_t casts, label_t free_label) {
-
-        std::size_t hardware_threads = std::thread::hardware_concurrency();
-        index_punned_dense_gt result;
-        result.dimensions_ = dimensions;
-        result.scalar_words_ = count_scalar_words_(dimensions, scalar_kind);
-        result.expansion_add_ = expansion_add;
-        result.expansion_search_ = expansion_search;
-        result.casted_vector_bytes_ = bytes_per_scalar(scalar_kind) * result.scalar_words_;
-        result.cast_buffer_.resize(hardware_threads * result.casted_vector_bytes_);
-        result.casts_ = casts;
-        result.root_metric_ = metric;
-        result.free_label_ = free_label;
-
-        // Fill the thread IDs.
-        result.available_threads_.resize(hardware_threads);
-        std::iota(result.available_threads_.begin(), result.available_threads_.end(), 0ul);
-
-        // Available since C11, but only C++17, so we use the C version.
-        index_t* raw = index_allocator_t{}.allocate(1);
-        new (raw) index_t(config, metric);
-        result.typed_ = raw;
-        return result;
-    }
-
-    template <typename to_scalar_at> static casts_t make_casts_() {
-        casts_t result;
-
-        result.from_b1x8 = cast_gt<b1x8_t, to_scalar_at>{};
-        result.from_f8 = cast_gt<f8_bits_t, to_scalar_at>{};
-        result.from_f16 = cast_gt<f16_t, to_scalar_at>{};
-        result.from_f32 = cast_gt<f32_t, to_scalar_at>{};
-        result.from_f64 = cast_gt<f64_t, to_scalar_at>{};
-
-        result.to_b1x8 = cast_gt<to_scalar_at, b1x8_t>{};
-        result.to_f8 = cast_gt<to_scalar_at, f8_bits_t>{};
-        result.to_f16 = cast_gt<to_scalar_at, f16_t>{};
-        result.to_f32 = cast_gt<to_scalar_at, f32_t>{};
-        result.to_f64 = cast_gt<to_scalar_at, f64_t>{};
-
-        return result;
-    }
-
-    static casts_t make_casts_(scalar_kind_t accuracy) {
-        switch (accuracy) {
-        case scalar_kind_t::f64_k: return make_casts_<f64_t>();
-        case scalar_kind_t::f32_k: return make_casts_<f32_t>();
-        case scalar_kind_t::f16_k: return make_casts_<f16_t>();
-        case scalar_kind_t::f8_k: return make_casts_<f8_bits_t>();
-        case scalar_kind_t::b1x8_k: return make_casts_<b1x8_t>();
-        default: return {};
-        }
-    }
-
-    static std::size_t count_scalar_words_(std::size_t dimensions, scalar_kind_t accuracy) {
-        switch (accuracy) {
-        case scalar_kind_t::f64_k: return dimensions;
-        case scalar_kind_t::f32_k: return dimensions;
-        case scalar_kind_t::f16_k: return dimensions;
-        case scalar_kind_t::f8_k: return dimensions;
-        case scalar_kind_t::b1x8_k: return divide_round_up<CHAR_BIT>(dimensions);
-        default: return {};
-        }
-    }
-
-    static metric_t ip_metric_f32_(std::size_t dimensions) {
-        (void)dimensions;
-#if USEARCH_USE_SIMSIMD
-        if (hardware_supports(isa_t::avx2_k) && dimensions % 4 == 0)
-            return {metric_kind_t::ip_k, isa_t::avx2_k, 0.f,
-                    [=](f32_t const* a, f32_t const* b) { return 1.f - simsimd_dot_f32x4avx2(a, b, dimensions); }};
-        if (hardware_supports(isa_t::sve_k))
-            return {metric_kind_t::ip_k, isa_t::sve_k, 0.f,
-                    [=](f32_t const* a, f32_t const* b) { return 1.f - simsimd_dot_f32sve(a, b, dimensions); }};
-        if (hardware_supports(isa_t::neon_k) && dimensions % 4 == 0)
-            return {metric_kind_t::ip_k, isa_t::neon_k, 0.f,
-                    [=](f32_t const* a, f32_t const* b) { return 1.f - simsimd_dot_f32x4neon(a, b, dimensions); }};
-#endif
-        return ip_gt<f32_t>{};
-    }
-
-    static metric_t cos_metric_f16_(std::size_t dimensions) {
-        (void)dimensions;
-#if USEARCH_USE_SIMSIMD
-        if (hardware_supports(isa_t::avx512_k) && dimensions % 16 == 0)
-            return {metric_kind_t::cos_k, isa_t::avx512_k, simsimd_f16_t(0),
-                    [=](simsimd_f16_t const* a, simsimd_f16_t const* b) {
-                        return 1.f - simsimd_cos_f16x16avx512(a, b, dimensions);
-                    }};
-        if (hardware_supports(isa_t::neon_k) && dimensions % 4 == 0)
-            return {metric_kind_t::cos_k, isa_t::neon_k, simsimd_f16_t(0),
-                    [=](simsimd_f16_t const* a, simsimd_f16_t const* b) {
-                        return 1.f - simsimd_cos_f16x4neon(a, b, dimensions);
-                    }};
-#endif
-        return cos_gt<f16_t, f32_t>{};
-    }
-
-    static metric_t cos_metric_f8_(std::size_t dimensions) {
-#if USEARCH_USE_SIMSIMD
-        if (hardware_supports(isa_t::neon_k) && dimensions % 16 == 0)
-            return {metric_kind_t::cos_k, isa_t::neon_k, int8_t(0),
-                    [=](int8_t const* a, int8_t const* b) { return 1.f - simsimd_cos_i8x16neon(a, b, dimensions); }};
-#endif
-        return cos_f8_t{dimensions};
-    }
-
-    static metric_t ip_metric_(std::size_t dimensions, scalar_kind_t accuracy) {
-        switch (accuracy) {
-        case scalar_kind_t::f32_k:
-            // The two most common numeric types for the most common metric have optimized versions
-            return ip_metric_f32_(dimensions);
-        case scalar_kind_t::f16_k:
-            // Dot-product accumulates error, Cosine-distance normalizes it
-            return cos_metric_f16_(dimensions);
-
-        case scalar_kind_t::f8_k: return cos_metric_f8_(dimensions);
-        case scalar_kind_t::f64_k: return ip_gt<f64_t>{};
-        default: return {};
-        }
-    }
-
-    static metric_t l2sq_metric_(std::size_t dimensions, scalar_kind_t accuracy) {
-        switch (accuracy) {
-        case scalar_kind_t::f8_k: return l2sq_f8_t{dimensions};
-        case scalar_kind_t::f16_k: return l2sq_gt<f16_t, f32_t>{};
-        case scalar_kind_t::f32_k: return l2sq_gt<f32_t>{};
-        case scalar_kind_t::f64_k: return l2sq_gt<f64_t>{};
-        default: return {};
-        }
-    }
-
-    static metric_t cos_metric_(std::size_t dimensions, scalar_kind_t accuracy) {
-        switch (accuracy) {
-        case scalar_kind_t::f8_k: return cos_metric_f8_(dimensions);
-        case scalar_kind_t::f16_k: return cos_metric_f16_(dimensions);
-        case scalar_kind_t::f32_k: return cos_gt<f32_t>{};
-        case scalar_kind_t::f64_k: return cos_gt<f64_t>{};
-        default: return {};
-        }
-    }
-
-    static metric_t haversine_metric_(scalar_kind_t accuracy) {
-        switch (accuracy) {
-        case scalar_kind_t::f8_k: return haversine_gt<f8_bits_t, f32_t>{};
-        case scalar_kind_t::f16_k: return haversine_gt<f16_t, f32_t>{};
-        case scalar_kind_t::f32_k: return haversine_gt<f32_t>{};
-        case scalar_kind_t::f64_k: return haversine_gt<f64_t>{};
-        default: return {};
-        }
-    }
-
-    static metric_t pearson_metric_(scalar_kind_t accuracy) {
-        switch (accuracy) {
-        case scalar_kind_t::f8_k: return pearson_correlation_gt<f8_bits_t, f32_t>{};
-        case scalar_kind_t::f16_k: return pearson_correlation_gt<f16_t, f32_t>{};
-        case scalar_kind_t::f32_k: return pearson_correlation_gt<f32_t>{};
-        case scalar_kind_t::f64_k: return pearson_correlation_gt<f64_t>{};
-        default: return {};
-        }
-    }
-
-    static metric_t make_metric_(metric_kind_t kind, std::size_t dimensions, scalar_kind_t accuracy) {
-        switch (kind) {
-        case metric_kind_t::ip_k: return ip_metric_(dimensions, accuracy);
-        case metric_kind_t::cos_k: return cos_metric_(dimensions, accuracy);
-        case metric_kind_t::l2sq_k: return l2sq_metric_(dimensions, accuracy);
-        case metric_kind_t::pearson_k: return pearson_metric_(accuracy);
-        case metric_kind_t::haversine_k: return haversine_metric_(accuracy);
-        case metric_kind_t::hamming_k: return hamming_gt<b1x8_t>{};
-        case metric_kind_t::jaccard_k: // Equivalent to Tanimoto
-        case metric_kind_t::tanimoto_k: return tanimoto_gt<b1x8_t>{};
-        case metric_kind_t::sorensen_k: return sorensen_gt<b1x8_t>{};
-        default: return {};
-        }
-    }
-};
-
-using punned_small_t = index_punned_dense_gt<std::uint64_t, std::uint32_t>;
-using punned_big_t = index_punned_dense_gt<uuid_t, uint40_t>;
-
-} // namespace usearch
-} // namespace unum
diff --git a/include/usearch/index_punned_helpers.hpp b/include/usearch/index_punned_helpers.hpp
deleted file mode 100644
index 990f0eb6..00000000
--- a/include/usearch/index_punned_helpers.hpp
+++ /dev/null
@@ -1,676 +0,0 @@
-#pragma once
-#include <stdlib.h> // `aligned_alloc`
-
-#include <cstring> // `std::strncmp`
-#include <numeric> // `std::iota`
-#include <thread>  // `std::thread`
-#include <vector>  // `std::vector`
-
-#include <usearch/index.hpp> // `expected_gt` and macros
-
-#if USEARCH_USE_OPENMP
-#include <omp.h> // `omp_get_num_threads()`
-#endif
-
-#if defined(USEARCH_DEFINED_LINUX)
-#include <sys/auxv.h> // `getauxval()`
-#endif
-
-#if defined(USEARCH_DEFINED_ARM)
-#include <arm_fp16.h> // `__fp16`
-#endif
-
-#if !defined(USEARCH_USE_NATIVE_F16)
-#if defined(__AVX512F__)
-#define USEARCH_USE_NATIVE_F16 1
-#elif defined(USEARCH_DEFINED_ARM)
-#define USEARCH_USE_NATIVE_F16 1
-#else
-#define USEARCH_USE_NATIVE_F16 0
-#include <fp16/fp16.h>
-#endif
-#else
-#define USEARCH_USE_NATIVE_F16 0
-#include <fp16/fp16.h>
-#endif
-
-#if !defined(USEARCH_USE_SIMSIMD)
-#define USEARCH_USE_SIMSIMD 0
-#endif
-
-#if USEARCH_USE_SIMSIMD
-#include <simsimd/simsimd.h>
-#endif
-
-namespace unum {
-namespace usearch {
-
-template <typename at, typename compare_at> inline at clamp(at v, at lo, at hi, compare_at comp) noexcept {
-    return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
-}
-template <typename at> inline at clamp(at v, at lo, at hi) noexcept {
-    return usearch::clamp(v, lo, hi, std::less<at>{});
-}
-
-inline bool str_equals(char const* begin, std::size_t len, char const* other_begin) noexcept {
-    std::size_t other_len = std::strlen(other_begin);
-    return len == other_len && std::strncmp(begin, other_begin, len) == 0;
-}
-
-enum class isa_t {
-    auto_k,
-    neon_k,
-    sve_k,
-    avx2_k,
-    avx512_k,
-};
-
-inline char const* isa_name(isa_t isa) noexcept {
-    switch (isa) {
-    case isa_t::auto_k: return "auto";
-    case isa_t::neon_k: return "neon";
-    case isa_t::sve_k: return "sve";
-    case isa_t::avx2_k: return "avx2";
-    case isa_t::avx512_k: return "avx512";
-    default: return "";
-    }
-}
-
-inline bool hardware_supports(isa_t isa) noexcept {
-#if defined(USEARCH_DEFINED_ARM) && defined(USEARCH_DEFINED_LINUX)
-    unsigned long capabilities = getauxval(AT_HWCAP);
-    switch (isa) {
-    case isa_t::neon_k: return true; // Must be supported on 64-bit Arm
-    case isa_t::sve_k: return capabilities & HWCAP_SVE;
-    default: return false;
-    }
-#endif
-
-#if defined(USEARCH_DEFINED_X86) && defined(USEARCH_DEFINED_GCC)
-    __builtin_cpu_init();
-    switch (isa) {
-    case isa_t::avx2_k: return __builtin_cpu_supports("avx2");
-    case isa_t::avx512_k: return __builtin_cpu_supports("avx512f");
-    default: return false;
-    }
-#endif
-
-    (void)isa;
-    return false;
-}
-
-inline std::size_t bytes_per_scalar(scalar_kind_t accuracy) noexcept {
-    switch (accuracy) {
-    case scalar_kind_t::f32_k: return 4;
-    case scalar_kind_t::f16_k: return 2;
-    case scalar_kind_t::f64_k: return 8;
-    case scalar_kind_t::f8_k: return 1;
-    case scalar_kind_t::b1x8_k: return 1;
-    default: return 0;
-    }
-}
-
-inline char const* scalar_kind_name(scalar_kind_t accuracy) noexcept {
-    switch (accuracy) {
-    case scalar_kind_t::f32_k: return "f32";
-    case scalar_kind_t::f16_k: return "f16";
-    case scalar_kind_t::f64_k: return "f64";
-    case scalar_kind_t::f8_k: return "f8";
-    case scalar_kind_t::b1x8_k: return "b1x8";
-    default: return "";
-    }
-}
-
-inline char const* metric_kind_name(metric_kind_t metric) noexcept {
-    switch (metric) {
-    case metric_kind_t::unknown_k: return "unknown";
-    case metric_kind_t::ip_k: return "ip";
-    case metric_kind_t::cos_k: return "cos";
-    case metric_kind_t::l2sq_k: return "l2sq";
-    case metric_kind_t::pearson_k: return "pearson";
-    case metric_kind_t::haversine_k: return "haversine";
-    case metric_kind_t::jaccard_k: return "jaccard";
-    case metric_kind_t::hamming_k: return "hamming";
-    case metric_kind_t::tanimoto_k: return "tanimoto";
-    case metric_kind_t::sorensen_k: return "sorensen";
-    }
-    return "";
-}
-inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name, std::size_t len) {
-    expected_gt<scalar_kind_t> parsed;
-    if (str_equals(name, len, "f32"))
-        parsed.result = scalar_kind_t::f32_k;
-    else if (str_equals(name, len, "f64"))
-        parsed.result = scalar_kind_t::f64_k;
-    else if (str_equals(name, len, "f16"))
-        parsed.result = scalar_kind_t::f16_k;
-    else if (str_equals(name, len, "f8"))
-        parsed.result = scalar_kind_t::f8_k;
-    else
-        parsed.failed("Unknown type, choose: f32, f16, f64, f8");
-    return parsed;
-}
-
-inline expected_gt<metric_kind_t> metric_from_name(char const* name, std::size_t len) {
-    expected_gt<metric_kind_t> parsed;
-    if (str_equals(name, len, "l2sq") || str_equals(name, len, "euclidean_sq")) {
-        parsed.result = metric_kind_t::l2sq_k;
-    } else if (str_equals(name, len, "ip") || str_equals(name, len, "inner") || str_equals(name, len, "dot")) {
-        parsed.result = metric_kind_t::ip_k;
-    } else if (str_equals(name, len, "cos") || str_equals(name, len, "angular")) {
-        parsed.result = metric_kind_t::cos_k;
-    } else if (str_equals(name, len, "haversine")) {
-        parsed.result = metric_kind_t::haversine_k;
-    } else if (str_equals(name, len, "pearson")) {
-        parsed.result = metric_kind_t::pearson_k;
-    } else if (str_equals(name, len, "hamming")) {
-        parsed.result = metric_kind_t::hamming_k;
-    } else if (str_equals(name, len, "tanimoto")) {
-        parsed.result = metric_kind_t::tanimoto_k;
-    } else if (str_equals(name, len, "sorensen")) {
-        parsed.result = metric_kind_t::sorensen_k;
-    } else
-        parsed.failed(
-            "Unknown distance, choose: l2sq, ip, cos, haversine, jaccard, pearson, hamming, tanimoto, sorensen");
-    return parsed;
-}
-
-using punned_distance_t = float;
-using punned_vector_view_t = span_gt<byte_t const>;
-
-class f8_bits_t;
-class f16_bits_t;
-
-#if USEARCH_USE_NATIVE_F16
-#if defined(USEARCH_DEFINED_ARM)
-using f16_native_t = __fp16;
-#else
-using f16_native_t = _Float16;
-#endif
-using f16_t = f16_native_t;
-#else
-using f16_native_t = void;
-using f16_t = f16_bits_t;
-#endif
-
-inline float f16_to_f32(std::uint16_t u16) noexcept {
-#if USEARCH_USE_NATIVE_F16
-    f16_native_t f16;
-    std::memcpy(&f16, &u16, sizeof(std::uint16_t));
-    return float(f16);
-#else
-    return fp16_ieee_to_fp32_value(u16);
-#endif
-}
-
-inline std::uint16_t f32_to_f16(float f32) noexcept {
-#if USEARCH_USE_NATIVE_F16
-    f16_native_t f16 = f16_native_t(f32);
-    std::uint16_t u16;
-    std::memcpy(&u16, &f16, sizeof(std::uint16_t));
-    return u16;
-#else
-    return fp16_ieee_from_fp32_value(f32);
-#endif
-}
-
-/**
- *  @brief  Numeric type for the IEEE 754 half-precision floating point.
- *          If hardware support isn't available, falls back to a hardware
- *          agnostic in-software implementation.
- */
-class f16_bits_t {
-    std::uint16_t uint16_{};
-
-  public:
-    inline f16_bits_t() noexcept : uint16_(0) {}
-    inline f16_bits_t(f16_bits_t&&) = default;
-    inline f16_bits_t& operator=(f16_bits_t&&) = default;
-    inline f16_bits_t(f16_bits_t const&) = default;
-    inline f16_bits_t& operator=(f16_bits_t const&) = default;
-
-    inline operator float() const noexcept { return f16_to_f32(uint16_); }
-    inline explicit operator bool() const noexcept { return f16_to_f32(uint16_) > 0.5f; }
-
-    inline f16_bits_t(f8_bits_t) noexcept;
-    inline f16_bits_t(bool v) noexcept : uint16_(f32_to_f16(v)) {}
-    inline f16_bits_t(float v) noexcept : uint16_(f32_to_f16(v)) {}
-    inline f16_bits_t(double v) noexcept : uint16_(f32_to_f16(v)) {}
-
-    inline f16_bits_t operator+(f16_bits_t other) const noexcept { return {float(*this) + float(other)}; }
-    inline f16_bits_t operator-(f16_bits_t other) const noexcept { return {float(*this) - float(other)}; }
-    inline f16_bits_t operator*(f16_bits_t other) const noexcept { return {float(*this) * float(other)}; }
-    inline f16_bits_t operator/(f16_bits_t other) const noexcept { return {float(*this) / float(other)}; }
-    inline f16_bits_t operator+(float other) const noexcept { return {float(*this) + other}; }
-    inline f16_bits_t operator-(float other) const noexcept { return {float(*this) - other}; }
-    inline f16_bits_t operator*(float other) const noexcept { return {float(*this) * other}; }
-    inline f16_bits_t operator/(float other) const noexcept { return {float(*this) / other}; }
-    inline f16_bits_t operator+(double other) const noexcept { return {float(*this) + other}; }
-    inline f16_bits_t operator-(double other) const noexcept { return {float(*this) - other}; }
-    inline f16_bits_t operator*(double other) const noexcept { return {float(*this) * other}; }
-    inline f16_bits_t operator/(double other) const noexcept { return {float(*this) / other}; }
-
-    inline f16_bits_t& operator+=(float v) noexcept {
-        uint16_ = f32_to_f16(v + f16_to_f32(uint16_));
-        return *this;
-    }
-
-    inline f16_bits_t& operator-=(float v) noexcept {
-        uint16_ = f32_to_f16(v - f16_to_f32(uint16_));
-        return *this;
-    }
-
-    inline f16_bits_t& operator*=(float v) noexcept {
-        uint16_ = f32_to_f16(v * f16_to_f32(uint16_));
-        return *this;
-    }
-
-    inline f16_bits_t& operator/=(float v) noexcept {
-        uint16_ = f32_to_f16(v / f16_to_f32(uint16_));
-        return *this;
-    }
-};
-
-/**
- *  @brief  Numeric type for uniformly-distributed floating point
- *          values within [-1,1] range, quantized to integers [-100,100].
- */
-class f8_bits_t {
-    std::int8_t int8_{};
-
-  public:
-    constexpr static float divisor_k = 100.f;
-    constexpr static std::int8_t min_k = -100;
-    constexpr static std::int8_t max_k = 100;
-
-    inline f8_bits_t() noexcept : int8_(0) {}
-    inline f8_bits_t(bool v) noexcept : int8_(v ? max_k : 0) {}
-
-    inline f8_bits_t(f8_bits_t&&) = default;
-    inline f8_bits_t& operator=(f8_bits_t&&) = default;
-    inline f8_bits_t(f8_bits_t const&) = default;
-    inline f8_bits_t& operator=(f8_bits_t const&) = default;
-
-    inline operator float() const noexcept { return float(int8_) / divisor_k; }
-    inline operator f16_t() const noexcept { return float(int8_) / divisor_k; }
-    inline operator double() const noexcept { return double(int8_) / divisor_k; }
-    inline explicit operator bool() const noexcept { return int8_ > (max_k / 2); }
-    inline explicit operator std::int8_t() const noexcept { return int8_; }
-    inline explicit operator std::int16_t() const noexcept { return int8_; }
-    inline explicit operator std::int32_t() const noexcept { return int8_; }
-    inline explicit operator std::int64_t() const noexcept { return int8_; }
-
-    inline f8_bits_t(f16_t v)
-        : int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
-    inline f8_bits_t(float v)
-        : int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
-    inline f8_bits_t(double v)
-        : int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
-};
-
-inline f16_bits_t::f16_bits_t(f8_bits_t v) noexcept : f16_bits_t(float(v)) {}
-
-struct uuid_t {
-    std::uint8_t octets[16];
-};
-
-/**
- *  @brief  An STL-based executor or a "thread-pool" for parallel execution.
- *          Isn't efficient for small batches, as it recreates the threads on every call.
- */
-class executor_stl_t {
-    std::size_t threads_count_{};
-
-  public:
-    /**
-     *  @param threads_count The number of threads to be used for parallel execution.
-     */
-    executor_stl_t(std::size_t threads_count = 0) noexcept
-        : threads_count_(threads_count ? threads_count : std::thread::hardware_concurrency()) {}
-
-    /**
-     *  @return Maximum number of threads available to the executor.
-     */
-    std::size_t size() const noexcept { return threads_count_; }
-
-    /**
-     *  @brief Executes tasks in bulk using the specified thread-aware function.
-     *  @param tasks                 The total number of tasks to be executed.
-     *  @param thread_aware_function The thread-aware function to be called for each thread index and task index.
-     *  @throws If an exception occurs during execution of the thread-aware function.
-     */
-    template <typename thread_aware_function_at>
-    void execute_bulk(std::size_t tasks, thread_aware_function_at&& thread_aware_function) noexcept(false) {
-        std::vector<std::thread> threads_pool;
-        std::size_t tasks_per_thread = (tasks / threads_count_) + ((tasks % threads_count_) != 0);
-        for (std::size_t thread_idx = 0; thread_idx != threads_count_; ++thread_idx) {
-            threads_pool.emplace_back([=]() {
-                for (std::size_t task_idx = thread_idx * tasks_per_thread;
-                     task_idx < (std::min)(tasks, thread_idx * tasks_per_thread + tasks_per_thread); ++task_idx)
-                    thread_aware_function(thread_idx, task_idx);
-            });
-        }
-        for (std::size_t thread_idx = 0; thread_idx != threads_count_; ++thread_idx)
-            threads_pool[thread_idx].join();
-    }
-
-    /**
-     *  @brief Saturates every available thread with the given workload, until they finish.
-     *  @param thread_aware_function The thread-aware function to be called for each thread index.
-     *  @throws If an exception occurs during execution of the thread-aware function.
-     */
-    template <typename thread_aware_function_at>
-    void execute_bulk(thread_aware_function_at&& thread_aware_function) noexcept(false) {
-        std::vector<std::thread> threads_pool;
-        for (std::size_t thread_idx = 0; thread_idx != threads_count_; ++thread_idx)
-            threads_pool.emplace_back([=]() { thread_aware_function(thread_idx); });
-        for (std::size_t thread_idx = 0; thread_idx != threads_count_; ++thread_idx)
-            threads_pool[thread_idx].join();
-    }
-};
-
-#if USEARCH_USE_OPENMP
-
-/**
- *  @brief  An OpenMP-based executor or a "thread-pool" for parallel execution.
- *          Is the preferred implementation, when available, and maximum performance is needed.
- */
-class executor_openmp_t {
-  public:
-    /**
-     *  @param threads_count The number of threads to be used for parallel execution.
-     */
-    executor_openmp_t(std::size_t threads_count = 0) noexcept {
-        omp_set_num_threads(threads_count ? threads_count : std::thread::hardware_concurrency());
-    }
-
-    /**
-     *  @return Maximum number of threads available to the executor.
-     */
-    std::size_t size() const noexcept { return omp_get_num_threads(); }
-
-    /**
-     *  @brief Executes tasks in bulk using the specified thread-aware function.
-     *  @param tasks                 The total number of tasks to be executed.
-     *  @param thread_aware_function The thread-aware function to be called for each thread index and task index.
-     *  @throws If an exception occurs during execution of the thread-aware function.
-     */
-    template <typename thread_aware_function_at>
-    void execute_bulk(std::size_t tasks, thread_aware_function_at&& thread_aware_function) noexcept(false) {
-#pragma omp parallel for schedule(dynamic)
-        for (std::size_t i = 0; i != tasks; ++i)
-            thread_aware_function(omp_get_thread_num(), i);
-    }
-
-    /**
-     *  @brief Saturates every available thread with the given workload, until they finish.
-     *  @param thread_aware_function The thread-aware function to be called for each thread index.
-     *  @throws If an exception occurs during execution of the thread-aware function.
-     */
-    template <typename thread_aware_function_at>
-    void execute_bulk(thread_aware_function_at&& thread_aware_function) noexcept(false) {
-#pragma omp parallel
-        { thread_aware_function(omp_get_thread_num()); }
-    }
-};
-
-using executor_default_t = executor_openmp_t;
-
-#else
-
-using executor_default_t = executor_stl_t;
-
-#endif
-
-/**
- *  @brief Uses OS-specific APIs for aligned memory allocations.
- */
-template <typename element_at = char, std::size_t alignment_ak = 64> //
-class aligned_allocator_gt {
-  public:
-    using value_type = element_at;
-    using size_type = std::size_t;
-    using pointer = element_at*;
-    using const_pointer = element_at const*;
-    template <typename other_element_at> struct rebind {
-        using other = aligned_allocator_gt<other_element_at>;
-    };
-
-    constexpr std::size_t alignment() const { return alignment_ak; }
-
-    pointer allocate(size_type length) const {
-        std::size_t length_bytes = alignment_ak * divide_round_up<alignment_ak>(length * sizeof(value_type));
-        std::size_t alignment = alignment_ak;
-        // void* result = nullptr;
-        // int status = posix_memalign(&result, alignment, length_bytes);
-        // return status == 0 ? (pointer)result : nullptr;
-#if defined(USEARCH_DEFINED_WINDOWS)
-        return (pointer)_aligned_malloc(length_bytes, alignment);
-#else
-        return (pointer)aligned_alloc(alignment, length_bytes);
-#endif
-    }
-
-    void deallocate(pointer begin, size_type) const {
-#if defined(USEARCH_DEFINED_WINDOWS)
-        _aligned_free(begin);
-#else
-        free(begin);
-#endif
-    }
-};
-
-using aligned_allocator_t = aligned_allocator_gt<>;
-
-/**
- *  @brief  Memory-mapping allocator designed for "alloc many, free at once" usage patterns.
- *          Thread-safe, @b except constructors and destructors.
- *
- *  Using this memory allocator won't affect your overall speed much, as that is not the bottleneck.
- *  However, it can drastically improve memory usage especcially for huge indexes of small vectors.
- */
-template <std::size_t alignment_ak = 1> class memory_mapping_allocator_gt {
-
-    static constexpr std::size_t min_capacity() { return 1024 * 1024 * 4; }
-    static constexpr std::size_t capacity_multiplier() { return 2; }
-    static constexpr std::size_t head_size() {
-        /// Pointer to the the previous arena and the size of the current one.
-        return divide_round_up<alignment_ak>(sizeof(byte_t*) + sizeof(std::size_t)) * alignment_ak;
-    }
-
-    std::mutex mutex_;
-    byte_t* last_arena_ = nullptr;
-    std::size_t last_usage_ = head_size();
-    std::size_t last_capacity_ = min_capacity();
-    std::size_t wasted_space_ = 0;
-
-  public:
-    using value_type = byte_t;
-    using size_type = std::size_t;
-    using pointer = byte_t*;
-    using const_pointer = byte_t const*;
-
-    memory_mapping_allocator_gt() = default;
-    memory_mapping_allocator_gt(memory_mapping_allocator_gt&& other) noexcept
-        : last_arena_(exchange(other.last_arena_, nullptr)), last_usage_(exchange(other.last_usage_, 0)),
-          last_capacity_(exchange(other.last_capacity_, 0)), wasted_space_(exchange(other.wasted_space_, 0)) {}
-
-    memory_mapping_allocator_gt& operator=(memory_mapping_allocator_gt&& other) noexcept {
-        std::swap(last_arena_, other.last_arena_);
-        std::swap(last_usage_, other.last_usage_);
-        std::swap(last_capacity_, other.last_capacity_);
-        std::swap(wasted_space_, other.wasted_space_);
-        return *this;
-    }
-
-    ~memory_mapping_allocator_gt() noexcept { reset(); }
-
-    /**
-     *  @brief Discards all previously allocated memory buffers.
-     */
-    void reset() noexcept {
-        byte_t* last_arena = last_arena_;
-        while (last_arena) {
-            byte_t* previous_arena;
-            std::memcpy(&previous_arena, last_arena, sizeof(byte_t*));
-            std::size_t current_size;
-            std::memcpy(&current_size, last_arena + sizeof(byte_t*), sizeof(std::size_t));
-#if defined(USEARCH_DEFINED_WINDOWS)
-            ::VirtualFree(last_arena, 0, MEM_RELEASE);
-#else
-            munmap(last_arena, current_size);
-#endif
-            last_arena = previous_arena;
-        }
-
-        // Clear the references:
-        last_arena_ = nullptr;
-        last_usage_ = head_size();
-        last_capacity_ = min_capacity();
-        wasted_space_ = 0;
-    }
-
-    /**
-     *  @brief Copy constructor.
-     *  @note This is a no-op copy constructor since the allocator is not copyable.
-     */
-    memory_mapping_allocator_gt(memory_mapping_allocator_gt const&) noexcept {}
-
-    /**
-     *  @brief Copy assignment operator.
-     *  @note This is a no-op copy assignment operator since the allocator is not copyable.
-     *  @return Reference to the allocator after the assignment.
-     */
-    memory_mapping_allocator_gt& operator=(memory_mapping_allocator_gt const&) noexcept {
-        reset();
-        return *this;
-    }
-
-    /**
-     *  @brief Allocates an @b uninitialized block of memory of the specified size.
-     *  @param count_bytes The number of bytes to allocate.
-     *  @return A pointer to the allocated memory block, or `nullptr` if allocation fails.
-     */
-    inline byte_t* allocate(std::size_t count_bytes) noexcept {
-        std::size_t extended_bytes = divide_round_up<alignment_ak>(count_bytes) * alignment_ak;
-        // Check if the requested allocation size is absurd
-        if (extended_bytes > min_capacity())
-            return nullptr;
-
-        std::unique_lock<std::mutex> lock(mutex_);
-        if (!last_arena_ || (last_usage_ + extended_bytes > last_capacity_)) {
-            std::size_t new_cap = last_capacity_ * capacity_multiplier();
-#if defined(USEARCH_DEFINED_WINDOWS)
-            byte_t* new_arena = (byte_t*)(::VirtualAlloc(NULL, new_cap, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
-            if (new_arena == nullptr)
-                return nullptr;
-#else
-            byte_t* new_arena = (byte_t*)mmap(NULL, new_cap, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-            if (!new_arena)
-                return nullptr;
-#endif
-            std::memcpy(new_arena, &last_arena_, sizeof(byte_t*));
-            std::memcpy(new_arena + sizeof(byte_t*), &new_cap, sizeof(std::size_t));
-
-            wasted_space_ += total_reserved();
-            last_arena_ = new_arena;
-            last_capacity_ = new_cap;
-            last_usage_ = head_size();
-        }
-
-        wasted_space_ += extended_bytes - count_bytes;
-        return last_arena_ + exchange(last_usage_, last_usage_ + extended_bytes);
-    }
-
-    /**
-     *  @brief Returns the amount of memory used by the allocator across all arenas.
-     *  @return The amount of space in bytes.
-     */
-    std::size_t total_allocated() const noexcept {
-        if (!last_arena_)
-            return 0;
-        std::size_t total_used = 0;
-        std::size_t last_capacity = last_capacity_;
-        do {
-            total_used += last_capacity;
-            last_capacity /= capacity_multiplier();
-        } while (last_capacity >= min_capacity());
-        return total_used;
-    }
-
-    /**
-     *  @brief Returns the amount of wasted space due to alignment.
-     *  @return The amount of wasted space in bytes.
-     */
-    std::size_t total_wasted() const noexcept { return wasted_space_; }
-
-    /**
-     *  @brief Returns the amount of remaining memory already reserved but not yet used.
-     *  @return The amount of reserved memory in bytes.
-     */
-    std::size_t total_reserved() const noexcept { return last_capacity_ - last_usage_; }
-
-    /**
-     *  @warning The very first memory de-allocation discards all the arenas!
-     */
-    void deallocate(byte_t* = nullptr, std::size_t = 0) noexcept { reset(); }
-};
-
-using memory_mapping_allocator_t = memory_mapping_allocator_gt<>;
-
-/**
- *  @brief  Utility class used to cast arrays of one scalar type to another,
- *          avoiding unnecessary conversions.
- */
-template <typename from_scalar_at, typename to_scalar_at> struct cast_gt {
-    inline bool operator()(byte_t const* input, std::size_t dimensions, byte_t* output) const {
-        from_scalar_at const* typed_input = reinterpret_cast<from_scalar_at const*>(input);
-        to_scalar_at* typed_output = reinterpret_cast<to_scalar_at*>(output);
-        auto converter = [](from_scalar_at from) { return to_scalar_at(from); };
-        std::transform(typed_input, typed_input + dimensions, typed_output, converter);
-        return true;
-    }
-};
-
-template <> struct cast_gt<f32_t, f32_t> {
-    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
-};
-
-template <> struct cast_gt<f64_t, f64_t> {
-    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
-};
-
-template <> struct cast_gt<f16_bits_t, f16_bits_t> {
-    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
-};
-
-template <> struct cast_gt<f8_bits_t, f8_bits_t> {
-    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
-};
-
-template <> struct cast_gt<b1x8_t, b1x8_t> {
-    bool operator()(byte_t const*, std::size_t, byte_t*) const { return false; }
-};
-
-template <typename from_scalar_at> struct cast_gt<from_scalar_at, b1x8_t> {
-    inline bool operator()(byte_t const* input, std::size_t dimensions, byte_t* output) const {
-        from_scalar_at const* typed_input = reinterpret_cast<from_scalar_at const*>(input);
-        unsigned char* typed_output = reinterpret_cast<unsigned char*>(output);
-        for (std::size_t i = 0; i != dimensions; ++i)
-            typed_output[i / CHAR_BIT] |= bool(typed_input[i]) ? (128 >> (i & (CHAR_BIT - 1))) : 0;
-        return true;
-    }
-};
-
-template <typename to_scalar_at> struct cast_gt<b1x8_t, to_scalar_at> {
-    inline bool operator()(byte_t const* input, std::size_t dimensions, byte_t* output) const {
-        unsigned char const* typed_input = reinterpret_cast<unsigned char const*>(input);
-        to_scalar_at* typed_output = reinterpret_cast<to_scalar_at*>(output);
-        for (std::size_t i = 0; i != dimensions; ++i)
-            typed_output[i] = bool(typed_input[i / CHAR_BIT] & (128 >> (i & (CHAR_BIT - 1))));
-        return true;
-    }
-};
-
-} // namespace usearch
-} // namespace unum
diff --git a/java/README.md b/java/README.md
index a087d9d3..489d9953 100644
--- a/java/README.md
+++ b/java/README.md
@@ -18,5 +18,5 @@ Add that snippet to your `pom.xml` and hit `mvn install`.
 Index index = new Index.Config().metric("cos").dimensions(2).build();
 float vec[] = {10, 20};
 index.add(42, vec);
-int[] labels = index.search(vec, 5);
+int[] keys = index.search(vec, 5);
 ```
diff --git a/java/cloud/unum/usearch/Index.java b/java/cloud/unum/usearch/Index.java
index 5b078961..3b234720 100644
--- a/java/cloud/unum/usearch/Index.java
+++ b/java/cloud/unum/usearch/Index.java
@@ -16,12 +16,12 @@ public class Index {
 
   private long c_ptr = 0;
 
-  public Index(String metric, String accuracy, //
+  public Index(String metric, String quantization, //
       long dimensions, long capacity, long connectivity, //
       long expansion_add, long expansion_search) {
     c_ptr = c_create(
         metric,
-        accuracy,
+        quantization,
         dimensions,
         capacity,
         connectivity,
@@ -49,8 +49,8 @@ public void reserve(long capacity) {
     c_reserve(c_ptr, capacity);
   }
 
-  public void add(int label, float vector[]) {
-    c_add(c_ptr, label, vector);
+  public void add(int key, float vector[]) {
+    c_add(c_ptr, key, vector);
   }
 
   public int[] search(float vector[], long count) {
@@ -71,7 +71,7 @@ public void view(String path) {
 
   public static class Config {
     private String _metric = "ip";
-    private String _accuracy = "f32";
+    private String _quantization = "f32";
     private long _dimensions = 0;
     private long _capacity = 0;
     private long _connectivity = 0;
@@ -84,7 +84,7 @@ public Config() {
     public Index build() {
       return new Index(
           _metric,
-          _accuracy,
+          _quantization,
           _dimensions,
           _capacity,
           _connectivity,
@@ -97,8 +97,8 @@ public Config metric(String _metric) {
       return this;
     }
 
-    public Config accuracy(String _accuracy) {
-      this._accuracy = _accuracy;
+    public Config quantization(String _quantization) {
+      this._quantization = _quantization;
       return this;
     }
 
@@ -138,7 +138,7 @@ public static void main(String[] args) {
   }
 
   private static native long c_create(//
-      String metric, String accuracy, //
+      String metric, String quantization, //
       long dimensions, long capacity, long connectivity, //
       long expansion_add, long expansion_search);
 
@@ -154,7 +154,7 @@ private static native long c_create(//
 
   private static native void c_reserve(long ptr, long capacity);
 
-  private static native void c_add(long ptr, int label, float vector[]);
+  private static native void c_add(long ptr, int key, float vector[]);
 
   private static native int[] c_search(long ptr, float vector[], long count);
 
diff --git a/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp b/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp
index dfd68502..3f8d4d3b 100644
--- a/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp
+++ b/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp
@@ -4,53 +4,44 @@
 
 #include <thread>
 
-#include <usearch/index_punned_dense.hpp>
+#include <usearch/index_dense.hpp>
 
 using namespace unum::usearch;
 using namespace unum;
 
-using metric_t = index_punned_dense_metric_t;
-using distance_t = punned_distance_t;
-using index_t = punned_small_t;
-
-using add_result_t = typename index_t::add_result_t;
-using search_result_t = typename index_t::search_result_t;
-using serialization_result_t = typename index_t::serialization_result_t;
-using label_t = typename index_t::label_t;
-using id_t = typename index_t::id_t;
-using vector_view_t = unum::usearch::span_gt<float>;
+using float_span_t = unum::usearch::span_gt<float>;
 
 JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
     JNIEnv* env, jclass,                                         //
-    jstring metric, jstring accuracy,                            //
+    jstring metric, jstring quantization,                        //
     jlong dimensions, jlong capacity, jlong connectivity,        //
     jlong expansion_add, jlong expansion_search) {
 
     jlong result{};
     char const* metric_cstr{};
-    char const* accuracy_cstr{};
+    char const* quantization_cstr{};
     try {
 
-        index_config_t config;
-        config.connectivity = static_cast<std::size_t>(connectivity);
+        std::size_t connectivity = static_cast<std::size_t>(connectivity);
         std::size_t expansion_add = static_cast<std::size_t>(expansion_add);
         std::size_t expansion_search = static_cast<std::size_t>(expansion_search);
 
         metric_cstr = (*env).GetStringUTFChars(metric, 0);
         std::size_t metric_length = (*env).GetStringUTFLength(metric);
-        accuracy_cstr = (*env).GetStringUTFChars(accuracy, 0);
-        std::size_t accuracy_length = (*env).GetStringUTFLength(accuracy);
+        quantization_cstr = (*env).GetStringUTFChars(quantization, 0);
+        std::size_t quantization_length = (*env).GetStringUTFLength(quantization);
 
-        scalar_kind_t accuracy = scalar_kind_from_name(accuracy_cstr, accuracy_length);
         metric_kind_t metric_kind = metric_from_name(metric_cstr, metric_length);
-        index_t index = index_t::make( //
-            static_cast<std::size_t>(dimensions), metric_kind, config, accuracy, expansion_add, expansion_search);
+        scalar_kind_t quantization = scalar_kind_from_name(quantization_cstr, quantization_length);
+        index_dense_config_t config(connectivity, expansion_add, expansion_search);
+        metric_punned_t metric(static_cast<std::size_t>(dimensions), metric_kind, quantization);
+        index_dense_t index = index_dense_t::make(metric, config);
         if (!index.reserve(static_cast<std::size_t>(capacity))) {
             jclass jc = (*env).FindClass("java/lang/Error");
             if (jc)
                 (*env).ThrowNew(jc, "Failed to reserve desired capacity!");
         } else {
-            index_t* result_ptr = new index_t(std::move(index));
+            index_dense_t* result_ptr = new index_dense_t(std::move(index));
             std::memcpy(&result, &result_ptr, sizeof(jlong));
         }
 
@@ -61,13 +52,13 @@ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
     }
 
     (*env).ReleaseStringUTFChars(metric, metric_cstr);
-    (*env).ReleaseStringUTFChars(accuracy, accuracy_cstr);
+    (*env).ReleaseStringUTFChars(quantization, quantization_cstr);
     return result;
 }
 
 JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1save(JNIEnv* env, jclass, jlong c_ptr, jstring path) {
     char const* path_cstr = (*env).GetStringUTFChars(path, 0);
-    if (!reinterpret_cast<index_t*>(c_ptr)->save(path_cstr)) {
+    if (!reinterpret_cast<index_dense_t*>(c_ptr)->save(path_cstr)) {
         jclass jc = (*env).FindClass("java/lang/Error");
         if (jc)
             (*env).ThrowNew(jc, "Failed to dump vector index to path!");
@@ -77,7 +68,7 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1save(JNIEnv* env, jclass
 
 JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1load(JNIEnv* env, jclass, jlong c_ptr, jstring path) {
     char const* path_cstr = (*env).GetStringUTFChars(path, 0);
-    if (!reinterpret_cast<index_t*>(c_ptr)->load(path_cstr)) {
+    if (!reinterpret_cast<index_dense_t*>(c_ptr)->load(path_cstr)) {
         jclass jc = (*env).FindClass("java/lang/Error");
         if (jc)
             (*env).ThrowNew(jc, "Failed to load vector index from path!");
@@ -87,7 +78,7 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1load(JNIEnv* env, jclass
 
 JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1view(JNIEnv* env, jclass, jlong c_ptr, jstring path) {
     char const* path_cstr = (*env).GetStringUTFChars(path, 0);
-    if (!reinterpret_cast<index_t*>(c_ptr)->view(path_cstr)) {
+    if (!reinterpret_cast<index_dense_t*>(c_ptr)->view(path_cstr)) {
         jclass jc = (*env).FindClass("java/lang/Error");
         if (jc)
             (*env).ThrowNew(jc, "Failed to view vector index from path!");
@@ -96,27 +87,27 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1view(JNIEnv* env, jclass
 }
 
 JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1destroy(JNIEnv*, jclass, jlong c_ptr) {
-    delete reinterpret_cast<index_t*>(c_ptr);
+    delete reinterpret_cast<index_dense_t*>(c_ptr);
 }
 
 JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1size(JNIEnv*, jclass, jlong c_ptr) {
-    return reinterpret_cast<index_t*>(c_ptr)->size();
+    return reinterpret_cast<index_dense_t*>(c_ptr)->size();
 }
 
 JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1connectivity(JNIEnv*, jclass, jlong c_ptr) {
-    return reinterpret_cast<index_t*>(c_ptr)->connectivity();
+    return reinterpret_cast<index_dense_t*>(c_ptr)->connectivity();
 }
 
 JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1dimensions(JNIEnv*, jclass, jlong c_ptr) {
-    return reinterpret_cast<index_t*>(c_ptr)->dimensions();
+    return reinterpret_cast<index_dense_t*>(c_ptr)->dimensions();
 }
 
 JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1capacity(JNIEnv*, jclass, jlong c_ptr) {
-    return reinterpret_cast<index_t*>(c_ptr)->capacity();
+    return reinterpret_cast<index_dense_t*>(c_ptr)->capacity();
 }
 
 JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1reserve(JNIEnv* env, jclass, jlong c_ptr, jlong capacity) {
-    if (!reinterpret_cast<index_t*>(c_ptr)->reserve(static_cast<std::size_t>(capacity))) {
+    if (!reinterpret_cast<index_dense_t*>(c_ptr)->reserve(static_cast<std::size_t>(capacity))) {
         jclass jc = (*env).FindClass("java/lang/Error");
         if (jc)
             (*env).ThrowNew(jc, "Failed to grow vector index!");
@@ -124,13 +115,14 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1reserve(JNIEnv* env, jcl
 }
 
 JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1add( //
-    JNIEnv* env, jclass, jlong c_ptr, jint label, jfloatArray vector) {
+    JNIEnv* env, jclass, jlong c_ptr, jint key, jfloatArray vector) {
 
     jfloat* vector_data = (*env).GetFloatArrayElements(vector, 0);
     jsize vector_dims = (*env).GetArrayLength(vector);
-    vector_view_t vector_span = vector_view_t{vector_data, static_cast<std::size_t>(vector_dims)};
+    float_span_t vector_span = float_span_t{vector_data, static_cast<std::size_t>(vector_dims)};
 
-    if (!reinterpret_cast<index_t*>(c_ptr)->add(static_cast<label_t>(label), vector_span)) {
+    using key_t = typename index_dense_t::key_t;
+    if (!reinterpret_cast<index_dense_t*>(c_ptr)->add(static_cast<key_t>(key), vector_span)) {
         jclass jc = (*env).FindClass("java/lang/Error");
         if (jc)
             (*env).ThrowNew(jc, "Failed to insert a new point in vector index!");
@@ -152,10 +144,15 @@ JNIEXPORT jintArray JNICALL Java_cloud_unum_usearch_Index_c_1search( //
 
     jfloat* vector_data = (*env).GetFloatArrayElements(vector, 0);
     jsize vector_dims = (*env).GetArrayLength(vector);
-    vector_view_t vector_span = vector_view_t{vector_data, static_cast<std::size_t>(vector_dims)};
-    search_result_t result = reinterpret_cast<index_t*>(c_ptr)->search(vector_span, static_cast<std::size_t>(wanted));
+    float_span_t vector_span = float_span_t{vector_data, static_cast<std::size_t>(vector_dims)};
+
+    using key_t = typename index_dense_t::key_t;
+    using search_result_t = typename index_dense_t::search_result_t;
+
+    search_result_t result =
+        reinterpret_cast<index_dense_t*>(c_ptr)->search(vector_span, static_cast<std::size_t>(wanted));
     if (result) {
-        std::size_t found = result.dump_to(reinterpret_cast<label_t*>(matches_data), NULL);
+        std::size_t found = result.dump_to(reinterpret_cast<key_t*>(matches_data), NULL);
         (*env).SetIntArrayRegion(matches, 0, found, matches_data);
     } else {
         jclass jc = (*env).FindClass("java/lang/Error");
diff --git a/javascript/README.md b/javascript/README.md
index ca059b61..3d15f205 100644
--- a/javascript/README.md
+++ b/javascript/README.md
@@ -3,7 +3,7 @@
 ## Installation
 
 USearch is available both for Node.js backend runtime and WASM frontend runtime.
-For first use the conventional `npm install`:
+For the first option, use the conventional `npm install`:
 
 ```sh
 npm install usearch
@@ -18,12 +18,12 @@ wasmer install unum/usearch
 ## Quickstart
 
 ```js
-var index = new usearch.Index({ metric: 'cos', connectivity: 16, dimensions: 3 })
-index.add(42, new Float32Array([0.2, 0.6, 0.4]))
-var results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10)
+var index = new usearch.Index({ metric: 'cos', connectivity: 16n, dimensions: 3n })
+index.add(42n, new Float32Array([0.2, 0.6, 0.4]))
+var results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10n)
 
-assert.equal(index.size(), 1)
-assert.deepEqual(results.labels, new BigUint64Array([42n]))
+assert.equal(index.size(), 1n)
+assert.deepEqual(results.keys, new BigUint64Array([42n]))
 assert.deepEqual(results.distances, new Float32Array([0]))
 ```
 
diff --git a/javascript/lib.cpp b/javascript/lib.cpp
index 6abbd70d..5034dd5f 100644
--- a/javascript/lib.cpp
+++ b/javascript/lib.cpp
@@ -1,6 +1,6 @@
 /**
  *  @file javascript.cpp
- *  @author Ashot Vardanian
+ *  @author Ash Vardanian
  *  @brief JavaScript bindings for Unum USearch.
  *  @date 2023-04-26
  *
@@ -15,19 +15,11 @@
 #include <napi.h>
 #include <node_api.h>
 
-#include <usearch/index_punned_dense.hpp>
+#include <usearch/index_dense.hpp>
 
 using namespace unum::usearch;
 using namespace unum;
 
-using metric_t = index_punned_dense_metric_t;
-using distance_t = punned_distance_t;
-using index_t = punned_small_t;
-using add_result_t = typename index_t::add_result_t;
-using search_result_t = typename index_t::search_result_t;
-using label_t = typename index_t::label_t;
-using id_t = typename index_t::id_t;
-
 class Index : public Napi::ObjectWrap<Index> {
   public:
     static Napi::Object Init(Napi::Env env, Napi::Object exports);
@@ -46,7 +38,7 @@ class Index : public Napi::ObjectWrap<Index> {
     void Add(Napi::CallbackInfo const& ctx);
     Napi::Value Search(Napi::CallbackInfo const& ctx);
 
-    std::unique_ptr<index_t> native_;
+    std::unique_ptr<index_dense_t> native_;
 };
 
 Napi::Object Index::Init(Napi::Env env, Napi::Object exports) {
@@ -82,32 +74,38 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
         return;
     }
 
+    bool lossless = true;
     Napi::Object params = ctx[0].As<Napi::Object>();
-    std::size_t dimensions = params.Has("dimensions") ? params.Get("dimensions").As<Napi::Number>().Uint32Value() : 0;
+    std::size_t dimensions =
+        params.Has("dimensions") ? params.Get("dimensions").As<Napi::BigInt>().Uint64Value(&lossless) : 0;
 
-    index_config_t config;
     index_limits_t limits;
+    std::size_t connectivity = default_connectivity();
     std::size_t expansion_add = default_expansion_add();
     std::size_t expansion_search = default_expansion_search();
 
     if (params.Has("capacity"))
-        limits.members = params.Get("capacity").As<Napi::Number>().Uint32Value();
+        limits.members = params.Get("capacity").As<Napi::BigInt>().Uint64Value(&lossless);
     if (params.Has("connectivity"))
-        config.connectivity = params.Get("connectivity").As<Napi::Number>().Uint32Value();
+        connectivity = params.Get("connectivity").As<Napi::BigInt>().Uint64Value(&lossless);
     if (params.Has("expansion_add"))
-        expansion_add = params.Get("expansion_add").As<Napi::Number>().Uint32Value();
+        expansion_add = params.Get("expansion_add").As<Napi::BigInt>().Uint64Value(&lossless);
     if (params.Has("expansion_search"))
-        expansion_search = params.Get("expansion_search").As<Napi::Number>().Uint32Value();
+        expansion_search = params.Get("expansion_search").As<Napi::BigInt>().Uint64Value(&lossless);
+    if (!lossless) {
+        Napi::TypeError::New(env, "Arguments must be unsigned integers").ThrowAsJavaScriptException();
+        return;
+    }
 
-    scalar_kind_t accuracy = scalar_kind_t::f32_k;
-    if (params.Has("accuracy")) {
-        std::string accuracy_str = params.Get("accuracy").As<Napi::String>().Utf8Value();
-        expected_gt<scalar_kind_t> expected = scalar_kind_from_name(accuracy_str.c_str(), accuracy_str.size());
+    scalar_kind_t quantization = scalar_kind_t::f32_k;
+    if (params.Has("quantization")) {
+        std::string quantization_str = params.Get("quantization").As<Napi::String>().Utf8Value();
+        expected_gt<scalar_kind_t> expected = scalar_kind_from_name(quantization_str.c_str(), quantization_str.size());
         if (!expected) {
             Napi::TypeError::New(env, expected.error.what()).ThrowAsJavaScriptException();
             return;
         }
-        accuracy = *expected;
+        quantization = *expected;
     }
 
     // By default we use the Inner Product similarity
@@ -122,20 +120,23 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
         metric_kind = *expected;
     }
 
-    native_.reset(
-        new index_t(index_t::make(dimensions, metric_kind, config, accuracy, expansion_add, expansion_search)));
+    metric_punned_t metric(dimensions, metric_kind, quantization);
+    index_dense_config_t config(connectivity, expansion_add, expansion_search);
+    native_.reset(new index_dense_t(index_dense_t::make(metric, config)));
     native_->reserve(limits);
 }
 
 Napi::Value Index::GetDimensions(Napi::CallbackInfo const& ctx) {
-    return Napi::Number::New(ctx.Env(), native_->dimensions());
+    return Napi::BigInt::New(ctx.Env(), static_cast<std::uint64_t>(native_->dimensions()));
+}
+Napi::Value Index::GetSize(Napi::CallbackInfo const& ctx) {
+    return Napi::BigInt::New(ctx.Env(), static_cast<std::uint64_t>(native_->size()));
 }
-Napi::Value Index::GetSize(Napi::CallbackInfo const& ctx) { return Napi::Number::New(ctx.Env(), native_->size()); }
 Napi::Value Index::GetConnectivity(Napi::CallbackInfo const& ctx) {
-    return Napi::Number::New(ctx.Env(), native_->connectivity());
+    return Napi::BigInt::New(ctx.Env(), static_cast<std::uint64_t>(native_->connectivity()));
 }
 Napi::Value Index::GetCapacity(Napi::CallbackInfo const& ctx) {
-    return Napi::Number::New(ctx.Env(), native_->capacity());
+    return Napi::BigInt::New(ctx.Env(), static_cast<std::uint64_t>(native_->capacity()));
 }
 
 void Index::Save(Napi::CallbackInfo const& ctx) {
@@ -191,57 +192,95 @@ void Index::View(Napi::CallbackInfo const& ctx) {
 
 void Index::Add(Napi::CallbackInfo const& ctx) {
     Napi::Env env = ctx.Env();
-    if (ctx.Length() < 2 || !ctx[0].IsNumber() || !ctx[1].IsTypedArray())
-        return Napi::TypeError::New(env, "Expects an integral label and a float vector").ThrowAsJavaScriptException();
 
-    Napi::Number label_js = ctx[0].As<Napi::Number>();
-    Napi::Float32Array vector_js = ctx[1].As<Napi::Float32Array>();
+    if (ctx.Length() < 2)
+        return Napi::TypeError::New(env, "Expects at least two arguments").ThrowAsJavaScriptException();
 
-    label_t label = label_js.Uint32Value();
-    float const* vector = vector_js.Data();
-    std::size_t dimensions = static_cast<std::size_t>(vector_js.ElementLength());
-    if (dimensions != native_->dimensions())
-        return Napi::TypeError::New(env, "Wrong number of dimensions").ThrowAsJavaScriptException();
+    using key_t = typename index_dense_t::key_t;
+    std::size_t index_dimensions = native_->dimensions();
 
-    if (native_->size() + 1 >= native_->capacity())
-        native_->reserve(ceil2(native_->size() + 1));
+    auto add = [&](Napi::BigInt key_js, Napi::Float32Array vector_js) {
+        bool lossless = true;
+        key_t key = static_cast<key_t>(key_js.Uint64Value(&lossless));
+        if (!lossless)
+            return Napi::TypeError::New(env, "Keys must be unsigned integers").ThrowAsJavaScriptException();
 
-    try {
-        native_->add(label, vector);
-    } catch (std::bad_alloc const&) {
-        Napi::TypeError::New(env, "Out of memory").ThrowAsJavaScriptException();
-    } catch (...) {
-        Napi::TypeError::New(env, "Insertion failed").ThrowAsJavaScriptException();
-    }
+        float const* vector = vector_js.Data();
+        std::size_t dimensions = static_cast<std::size_t>(vector_js.ElementLength());
+
+        if (dimensions != index_dimensions)
+            return Napi::TypeError::New(env, "Wrong number of dimensions").ThrowAsJavaScriptException();
+
+        try {
+            native_->add(key, vector);
+        } catch (std::bad_alloc const&) {
+            return Napi::TypeError::New(env, "Out of memory").ThrowAsJavaScriptException();
+        } catch (...) {
+            return Napi::TypeError::New(env, "Insertion failed").ThrowAsJavaScriptException();
+        }
+    };
+
+    if (ctx[0].IsArray() && ctx[1].IsArray()) {
+        Napi::Array keys_js = ctx[0].As<Napi::Array>();
+        Napi::Array vectors_js = ctx[1].As<Napi::Array>();
+        auto length = keys_js.Length();
+
+        if (length != vectors_js.Length())
+            return Napi::TypeError::New(env, "The number of keys must match the number of vectors")
+                .ThrowAsJavaScriptException();
+
+        if (native_->size() + length >= native_->capacity())
+            native_->reserve(ceil2(native_->size() + length));
+
+        for (std::size_t i = 0; i < length; i++) {
+            Napi::Value key_js = keys_js[i];
+            Napi::Value vector_js = vectors_js[i];
+            add(key_js.As<Napi::BigInt>(), vector_js.As<Napi::Float32Array>());
+        }
+
+    } else if (ctx[0].IsBigInt() && ctx[1].IsTypedArray()) {
+        if (native_->size() + 1 >= native_->capacity())
+            native_->reserve(ceil2(native_->size() + 1));
+        add(ctx[0].As<Napi::BigInt>(), ctx[1].As<Napi::Float32Array>());
+    } else
+        return Napi::TypeError::New(env, "Invalid argument type, expects integral key(s) and float vector(s)")
+            .ThrowAsJavaScriptException();
 }
 
 Napi::Value Index::Search(Napi::CallbackInfo const& ctx) {
     Napi::Env env = ctx.Env();
-    if (ctx.Length() < 2 || !ctx[0].IsTypedArray() || !ctx[1].IsNumber()) {
-        Napi::TypeError::New(env, "Expects a float vector and the number of wanted results")
-            .ThrowAsJavaScriptException();
+    if (ctx.Length() < 2 || !ctx[0].IsTypedArray() || !ctx[1].IsBigInt()) {
+        Napi::TypeError::New(env, "Expects a  and the number of wanted results").ThrowAsJavaScriptException();
         return {};
     }
 
     Napi::Float32Array vector_js = ctx[0].As<Napi::Float32Array>();
-    Napi::Number wanted_js = ctx[1].As<Napi::Number>();
+    Napi::BigInt wanted_js = ctx[1].As<Napi::BigInt>();
 
     float const* vector = vector_js.Data();
     std::size_t dimensions = static_cast<std::size_t>(vector_js.ElementLength());
-    std::uint32_t wanted = wanted_js.Uint32Value();
     if (dimensions != native_->dimensions()) {
         Napi::TypeError::New(env, "Wrong number of dimensions").ThrowAsJavaScriptException();
         return {};
     }
 
-    Napi::TypedArrayOf<label_t> matches_js = Napi::TypedArrayOf<label_t>::New(env, wanted);
+    bool lossless = true;
+    std::uint64_t wanted = wanted_js.Uint64Value(&lossless);
+    if (!lossless) {
+        Napi::TypeError::New(env, "Wanted number of matches must be an unsigned integer").ThrowAsJavaScriptException();
+        return {};
+    }
+
+    using key_t = typename index_dense_t::key_t;
+    Napi::TypedArrayOf<key_t> matches_js = Napi::TypedArrayOf<key_t>::New(env, wanted);
+    static_assert(std::is_same<std::uint64_t, key_t>::value, "Matches.key interface expects BigUint64Array");
     Napi::Float32Array distances_js = Napi::Float32Array::New(env, wanted);
     try {
-        std::size_t count = native_->search(vector, wanted).dump_to(matches_js.Data(), distances_js.Data());
+        std::uint64_t count = native_->search(vector, wanted).dump_to(matches_js.Data(), distances_js.Data());
         Napi::Object result_js = Napi::Object::New(env);
-        result_js.Set("labels", matches_js);
+        result_js.Set("keys", matches_js);
         result_js.Set("distances", distances_js);
-        result_js.Set("count", Napi::Number::New(env, count));
+        result_js.Set("count", Napi::BigInt::New(env, count));
         return result_js;
     } catch (std::bad_alloc const&) {
         Napi::TypeError::New(env, "Out of memory").ThrowAsJavaScriptException();
diff --git a/javascript/usearch.d.ts b/javascript/usearch.d.ts
new file mode 100644
index 00000000..50cb411a
--- /dev/null
+++ b/javascript/usearch.d.ts
@@ -0,0 +1,87 @@
+
+/** Search result object. */
+export interface Matches {
+    /** The keys of the nearest neighbors found, size n*k. */
+    keys: BigUint64Array,
+    /** The distances of the nearest neighbors found, size n*k. */
+    distances: Float32Array,
+    /** The distances of the nearest neighbors found, size n*k. */
+    count: bigint
+}
+
+/** K-Approximate Nearest Neighbors search index. */
+export class Index {
+    
+    /**
+     * Constructs a new index.
+     * 
+     * @param {bigint} dimensions
+     * @param {string} metric
+     * @param {string} quantization
+     * @param {bigint} capacity
+     * @param {bigint} connectivity
+     * @param {bigint} expansion_add
+     * @param {bigint} expansion_search
+     */
+    constructor(...args);
+
+    /**
+     * Returns the dimensionality of vectors.
+     * @return {bigint} The dimensionality of vectors.
+     */
+    dimensions(): bigint;
+
+    /**
+     * Returns the bigint of vectors currently indexed.
+     * @return {bigint} The bigint of vectors currently indexed.
+     */
+    size(): bigint;
+
+    /**
+     * Returns index capacity.
+     * @return {bigints} The capacity of index.
+     */
+    capacity(): bigint;
+    
+    /**
+     * Returns connectivity.
+     * @return {bigint} The connectivity of index.
+     */
+    connectivity(): bigint;
+
+    /** 
+     * Write index to a file.
+     * @param {string} path File path to write.
+     */
+    save(path: string): void;
+
+    /** 
+     * Load index from a file.
+     * @param {string} path File path to read.
+     */
+    load(path: string): void;
+
+    /** 
+     * View index from a file, without loading into RAM.
+     * @param {string} path File path to read.
+     */
+    load(path: string): void;
+
+    /** 
+     * Add n vectors of dimension d to the index.
+     * 
+     * @param {bigint | bigint[]} keys Input identifiers for every vector.
+     * @param {Float32Array | Float32Array[]} mat Input matrix, matrix of size n * d.
+     */
+    add(keys: bigint | bigint[], mat: Float32Array | Float32Array[]): void;
+
+    /** 
+     * Query n vectors of dimension d to the index. Return at most k vectors for each. 
+     * If there are not enough results for a query, the result array is padded with -1s.
+     *
+     * @param {Float32Array} mat Input vectors to search, matrix of size n * d.
+     * @param {bigint} k The bigint of nearest neighbors to search for.
+     * @return {Matches} Output of the search result.
+     */
+    search(mat: Float32Array, k: bigint): Matches;
+}
\ No newline at end of file
diff --git a/javascript/usearch.js b/javascript/usearch.js
index 47da53ca..3d4a85ff 100644
--- a/javascript/usearch.js
+++ b/javascript/usearch.js
@@ -1,118 +1,2 @@
-const usearch_native = require('bindings')('usearch');
-
-class Index {
-    /**
-     * Creates an instance of Index.
-     * @date 6/7/2023 - 7:32:29 AM
-     *
-     * @constructor
-     * @param {...{}} args
-     */
-    constructor(...args) {
-        this.native = new usearch_native.Index(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:28 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    dimensions(...args) {
-        return this.native.dimensions(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:28 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    size(...args) {
-        return this.native.size(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:28 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    capacity(...args) {
-        return this.native.capacity(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:28 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    connectivity(...args) {
-        return this.native.connectivity(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:28 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    save(...args) {
-        return this.native.save(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:27 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    load(...args) {
-        return this.native.load(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:27 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    view(...args) {
-        return this.native.view(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:27 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    add(...args) {
-        return this.native.add(...args)
-    }
-
-    /**
-     * Description placeholder
-     * @date 6/7/2023 - 7:32:27 AM
-     *
-     * @param {...{}} args
-     * @returns {*}
-     */
-    search(...args) {
-        return this.native.search(...args)
-    }
-}
-
-
-module.exports = {
-    Index: Index
-};
\ No newline at end of file
+const usearch = require('bindings')('usearch');
+module.exports = usearch;
\ No newline at end of file
diff --git a/objc/USearchObjective.mm b/objc/USearchObjective.mm
index d497b9af..bc2160bf 100644
--- a/objc/USearchObjective.mm
+++ b/objc/USearchObjective.mm
@@ -2,21 +2,19 @@
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdocumentation"
-#import <usearch/index_punned_dense.hpp>
+#import <usearch/index_dense.hpp>
 #pragma clang diagnostic pop
 
 using namespace unum::usearch;
 using namespace unum;
 
-using metric_t = index_punned_dense_metric_t;
-using distance_t = punned_distance_t;
-using index_t = punned_small_t;
-using add_result_t = typename index_t::add_result_t;
-using search_result_t = typename index_t::search_result_t;
-using serialization_result_t = typename index_t::serialization_result_t;
-using label_t = typename index_t::label_t;
-using id_t = typename index_t::id_t;
-using shared_index_t = std::shared_ptr<index_t>;
+using distance_t = distance_punned_t;
+using add_result_t = typename index_dense_t::add_result_t;
+using labeling_result_t = typename index_dense_t::labeling_result_t;
+using search_result_t = typename index_dense_t::search_result_t;
+using shared_index_dense_t = std::shared_ptr<index_dense_t>;
+
+static_assert(std::is_same<USearchKey, index_dense_t::key_t>::value, "Type mismatch between Objective-C and C++");
 
 metric_kind_t to_native_metric(USearchMetric m) {
     switch (m) {
@@ -54,8 +52,8 @@ metric_kind_t to_native_metric(USearchMetric m) {
 
 scalar_kind_t to_native_scalar(USearchScalar m) {
     switch (m) {
-        case USearchScalarF8:
-            return scalar_kind_t::f8_k;
+        case USearchScalarI8:
+            return scalar_kind_t::i8_k;
 
         case USearchScalarF16:
             return scalar_kind_t::f16_k;
@@ -73,15 +71,15 @@ scalar_kind_t to_native_scalar(USearchScalar m) {
 
 @interface USearchIndex ()
 
-@property (readonly) shared_index_t native;
+@property (readonly) shared_index_dense_t native;
 
-- (instancetype)initWithIndex:(shared_index_t)native;
+- (instancetype)initWithIndex:(shared_index_dense_t)native;
 
 @end
 
 @implementation USearchIndex
 
-- (instancetype)initWithIndex:(shared_index_t)native {
+- (instancetype)initWithIndex:(shared_index_dense_t)native {
     self = [super init];
     _native = native;
     return self;
@@ -115,18 +113,18 @@ - (UInt32)expansionSearch {
     return static_cast<UInt32>(_native->expansion_search());
 }
 
-+ (instancetype)make:(USearchMetric)metric dimensions:(UInt32)dimensions connectivity:(UInt32)connectivity quantization:(USearchScalar)quantization {
++ (instancetype)make:(USearchMetric)metricKind dimensions:(UInt32)dimensions connectivity:(UInt32)connectivity quantization:(USearchScalar)quantization {
     std::size_t dims = static_cast<std::size_t>(dimensions);
-    index_config_t config;
 
-    config.connectivity = static_cast<std::size_t>(connectivity);
-    shared_index_t ptr = std::make_shared<index_t>(index_t::make(dims, to_native_metric(metric), config, to_native_scalar(quantization)));
+    index_config_t config(static_cast<std::size_t>(connectivity));
+    metric_punned_t metric(dims, to_native_metric(metricKind), to_native_scalar(quantization));
+    shared_index_dense_t ptr = std::make_shared<index_dense_t>(index_dense_t::make(metric, config));
     return [[USearchIndex alloc] initWithIndex:ptr];
 }
 
-- (void)addSingle:(USearchLabel)label
+- (void)addSingle:(USearchKey)key
            vector:(Float32 const *_Nonnull)vector {
-    add_result_t result = _native->add(label, vector);
+    add_result_t result = _native->add(key, vector);
 
     if (!result) {
         @throw [NSException exceptionWithName:@"Can't add to index"
@@ -137,7 +135,7 @@ - (void)addSingle:(USearchLabel)label
 
 - (UInt32)searchSingle:(Float32 const *_Nonnull)vector
                  count:(UInt32)wanted
-                labels:(USearchLabel *_Nullable)labels
+                  keys:(USearchKey *_Nullable)keys
              distances:(Float32 *_Nullable)distances {
     search_result_t result = _native->search(vector, static_cast<std::size_t>(wanted));
 
@@ -147,13 +145,13 @@ - (UInt32)searchSingle:(Float32 const *_Nonnull)vector
                                      userInfo:nil];
     }
 
-    std::size_t found = result.dump_to(labels, distances);
+    std::size_t found = result.dump_to(keys, distances);
     return static_cast<UInt32>(found);
 }
 
-- (void)addDouble:(USearchLabel)label
+- (void)addDouble:(USearchKey)key
            vector:(Float64 const *_Nonnull)vector {
-    add_result_t result = _native->add(label, (f64_t const *)vector);
+    add_result_t result = _native->add(key, (f64_t const *)vector);
 
     if (!result) {
         @throw [NSException exceptionWithName:@"Can't add to index"
@@ -164,7 +162,7 @@ - (void)addDouble:(USearchLabel)label
 
 - (UInt32)searchDouble:(Float64 const *_Nonnull)vector
                  count:(UInt32)wanted
-                labels:(USearchLabel *_Nullable)labels
+                  keys:(USearchKey *_Nullable)keys
              distances:(Float32 *_Nullable)distances {
     search_result_t result = _native->search((f64_t const *)vector, static_cast<std::size_t>(wanted));
 
@@ -174,13 +172,13 @@ - (UInt32)searchDouble:(Float64 const *_Nonnull)vector
                                      userInfo:nil];
     }
 
-    std::size_t found = result.dump_to(labels, distances);
+    std::size_t found = result.dump_to(keys, distances);
     return static_cast<UInt32>(found);
 }
 
-- (void)addHalf:(USearchLabel)label
+- (void)addHalf:(USearchKey)key
          vector:(void const *_Nonnull)vector {
-    add_result_t result = _native->add(label, (f16_t const *)vector);
+    add_result_t result = _native->add(key, (f16_t const *)vector);
 
     if (!result) {
         @throw [NSException exceptionWithName:@"Can't add to index"
@@ -191,7 +189,7 @@ - (void)addHalf:(USearchLabel)label
 
 - (UInt32)searchHalf:(void const *_Nonnull)vector
                count:(UInt32)wanted
-              labels:(USearchLabel *_Nullable)labels
+                keys:(USearchKey *_Nullable)keys
            distances:(Float32 *_Nullable)distances {
     search_result_t result = _native->search((f16_t const *)vector, static_cast<std::size_t>(wanted));
 
@@ -201,7 +199,7 @@ - (UInt32)searchHalf:(void const *_Nonnull)vector
                                      userInfo:nil];
     }
 
-    std::size_t found = result.dump_to(labels, distances);
+    std::size_t found = result.dump_to(keys, distances);
     return static_cast<UInt32>(found);
 }
 
@@ -213,6 +211,34 @@ - (void)reserve:(UInt32)count {
     _native->reserve(static_cast<std::size_t>(count));
 }
 
+- (Boolean)contains:(USearchKey)key {
+    return _native->contains(key);
+}
+
+- (UInt32)count:(USearchKey)key {
+    return _native->count(key);
+}
+
+- (void)remove:(USearchKey)key {
+    labeling_result_t result = _native->remove(key);
+
+    if (!result) {
+        @throw [NSException exceptionWithName:@"Can't remove an entry"
+                                       reason:[NSString stringWithUTF8String:result.error.what()]
+                                     userInfo:nil];
+    }
+}
+
+- (void)rename:(USearchKey)key to:(USearchKey)to {
+    labeling_result_t result = _native->rename(key, to);
+
+    if (!result) {
+        @throw [NSException exceptionWithName:@"Can't rename the entry"
+                                       reason:[NSString stringWithUTF8String:result.error.what()]
+                                     userInfo:nil];
+    }
+}
+
 - (void)save:(NSString *)path {
     char const *path_c = [path UTF8String];
 
diff --git a/objc/include/USearchObjective.h b/objc/include/USearchObjective.h
index e5264c18..62b898c1 100644
--- a/objc/include/USearchObjective.h
+++ b/objc/include/USearchObjective.h
@@ -8,7 +8,7 @@ typedef NS_ENUM(NSUInteger, USearchScalar) {
     USearchScalarF32,
     USearchScalarF16,
     USearchScalarF64,
-    USearchScalarF8,
+    USearchScalarI8,
     USearchScalarB1
 };
 
@@ -25,7 +25,7 @@ typedef NS_ENUM(NSUInteger, USearchMetric) {
     USearchMetricSorensen
 };
 
-typedef UInt64 USearchLabel;
+typedef UInt64 USearchKey;
 
 API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0))
 @interface USearchIndex : NSObject
@@ -46,8 +46,8 @@ API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0))
  * @param metric The distance function to compare the dis-similarity of vectors.
  * @param dimensions The number of dimensions planned for this index.
  * @param connectivity Number of connections per node in the proximity graph.
- * Higher connectivity improves accuracy, increases memory usage, and reduces construction speed.
- * @param quantization Accuracy of internal vector representations. Lower accuracy means higher speed.
+ * Higher connectivity improves quantization, increases memory usage, and reduces construction speed.
+ * @param quantization Quantization of internal vector representations. Lower quantization means higher speed.
  */
 + (instancetype)make:(USearchMetric)metric dimensions:(UInt32)dimensions connectivity:(UInt32)connectivity quantization:(USearchScalar)quantization NS_SWIFT_NAME(make(metric:dimensions:connectivity:quantization:));
 
@@ -60,61 +60,71 @@ API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0))
  * @brief Adds a labeled vector to the index.
  * @param vector Single-precision vector.
  */
-- (void)addSingle:(USearchLabel)label
-           vector:(Float32 const *_Nonnull)vector NS_SWIFT_NAME(addSingle(label:vector:));
+- (void)addSingle:(USearchKey)key
+           vector:(Float32 const *_Nonnull)vector NS_SWIFT_NAME(addSingle(key:vector:));
 
 /**
  * @brief Approximate nearest neighbors search.
  * @param vector Single-precision query vector.
  * @param count Upper limit on the number of matches to retrieve.
- * @param labels Optional output buffer for labels of approximate neighbors.
+ * @param keys Optional output buffer for keys of approximate neighbors.
  * @param distances Optional output buffer for (increasing) distances to approximate neighbors.
- * @return Number of matches exported to `labels` and `distances`.
+ * @return Number of matches exported to `keys` and `distances`.
  */
 - (UInt32)searchSingle:(Float32 const *_Nonnull)vector
                  count:(UInt32)count
-                labels:(USearchLabel *_Nullable)labels
-             distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchSingle(vector:count:labels:distances:));
+                  keys:(USearchKey *_Nullable)keys
+             distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchSingle(vector:count:keys:distances:));
 
 /**
  * @brief Adds a labeled vector to the index.
  * @param vector Double-precision vector.
  */
-- (void)addDouble:(USearchLabel)label
-           vector:(Float64 const *_Nonnull)vector NS_SWIFT_NAME(addDouble(label:vector:));
+- (void)addDouble:(USearchKey)key
+           vector:(Float64 const *_Nonnull)vector NS_SWIFT_NAME(addDouble(key:vector:));
 
 /**
  * @brief Approximate nearest neighbors search.
  * @param vector Double-precision query vector.
  * @param count Upper limit on the number of matches to retrieve.
- * @param labels Optional output buffer for labels of approximate neighbors.
+ * @param keys Optional output buffer for keys of approximate neighbors.
  * @param distances Optional output buffer for (increasing) distances to approximate neighbors.
- * @return Number of matches exported to `labels` and `distances`.
+ * @return Number of matches exported to `keys` and `distances`.
  */
 - (UInt32)searchDouble:(Float64 const *_Nonnull)vector
                  count:(UInt32)count
-                labels:(USearchLabel *_Nullable)labels
-             distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchDouble(vector:count:labels:distances:));
+                  keys:(USearchKey *_Nullable)keys
+             distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchDouble(vector:count:keys:distances:));
 
 /**
  * @brief Adds a labeled vector to the index.
  * @param vector Half-precision vector.
  */
-- (void)addHalf:(USearchLabel)label
-         vector:(void const *_Nonnull)vector NS_SWIFT_NAME(addHalf(label:vector:));
+- (void)addHalf:(USearchKey)key
+         vector:(void const *_Nonnull)vector NS_SWIFT_NAME(addHalf(key:vector:));
 
 /**
  * @brief Approximate nearest neighbors search.
  * @param vector Half-precision query vector.
  * @param count Upper limit on the number of matches to retrieve.
- * @param labels Optional output buffer for labels of approximate neighbors.
+ * @param keys Optional output buffer for keys of approximate neighbors.
  * @param distances Optional output buffer for (increasing) distances to approximate neighbors.
- * @return Number of matches exported to `labels` and `distances`.
+ * @return Number of matches exported to `keys` and `distances`.
  */
 - (UInt32)searchHalf:(void const *_Nonnull)vector
                count:(UInt32)count
-              labels:(USearchLabel *_Nullable)labels
-           distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchHalf(vector:count:labels:distances:));
+                keys:(USearchKey *_Nullable)keys
+           distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchHalf(vector:count:keys:distances:));
+
+
+- (Boolean)contains:(USearchKey)key NS_SWIFT_NAME(contains(key:));
+
+- (UInt32)count:(USearchKey)key NS_SWIFT_NAME(count(key:));
+
+- (void)remove:(USearchKey)key NS_SWIFT_NAME(remove(key:));
+
+- (void)rename:(USearchKey)key to:(USearchKey)key NS_SWIFT_NAME(rename(from:to:));
+
 
 /**
  * @brief Saves pre-constructed index to disk.
diff --git a/package.json b/package.json
index 5601e524..4bd7da53 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
     "name": "usearch",
     "version": "0.22.3",
     "description": "Smaller & Faster Single-File Vector Search Engine from Unum",
-    "author": "Ashot Vardanian",
+    "author": "Ash Vardanian",
     "license": "Apache 2.0",
     "main": "javascript/usearch.js",
     "repository": {
@@ -14,6 +14,7 @@
         "node": "~10 >=10.20 || >=12.17"
     },
     "dependencies": {
+        "@types/node": "^20.4.5",
         "bindings": "~1.2.1",
         "node-addon-api": "^3.0.0"
     },
@@ -24,6 +25,7 @@
         "@semantic-release/exec": "^6.0.3",
         "@semantic-release/git": "^10.0.1",
         "conventional-changelog-eslint": "^3.0.9",
-        "semantic-release": "^21.0.7"
+        "semantic-release": "^21.0.7",
+        "typescript": "^5.1.6"
     }
 }
diff --git a/python/README.md b/python/README.md
index e10c2df4..3c494678 100644
--- a/python/README.md
+++ b/python/README.md
@@ -15,7 +15,7 @@ from usearch.index import Index
 index = Index(
     ndim=3, # Define the number of dimensions in input vectors
     metric='cos', # Choose 'l2sq', 'haversine' or other metric, default = 'ip'
-    dtype='f32', # Quantize to 'f16' or 'f8' if needed, default = 'f32'
+    dtype='f32', # Quantize to 'f16' or 'i8' if needed, default = 'f32'
     connectivity=16, # How frequent should the connections in the graph be, optional
     expansion_add=128, # Control the recall of indexing, optional
     expansion_search=64, # Control the quality of search, optional
@@ -23,12 +23,12 @@ index = Index(
 
 vector = np.array([0.2, 0.6, 0.4])
 index.add(42, vector)
-matches, distances, count = index.search(vector, 10)
+matches: Matches = index.search(vector, 10)
 
 assert len(index) == 1
-assert count == 1
-assert matches[0] == 42
-assert distances[0] <= 0.001
+assert len(matches) == 1
+assert matches[0].key == 42
+assert matches[0].distance <= 0.001
 assert np.allclose(index[42], vector)
 ```
 
@@ -57,14 +57,18 @@ The difference would be in the shape of the tensors.
 
 ```py
 n = 100
-labels = np.arange(n)
+keys = np.arange(n)
 vectors = np.random.uniform(0, 0.3, (n, index.ndim)).astype(np.float32)
 
-index.add(labels, vectors, threads=..., copy=...)
-matches, distances, counts = index.search(vectors, 10, threads=...)
+index.add(keys, vectors, threads=..., copy=...)
+matches: BatchMatches = index.search(vectors, 10, threads=...)
 
-assert matches.shape[0] == vectors.shape[0]
-assert counts[0] <= 10
+first_query_matches: Matches = matches[0]
+assert matches[0].key == 0
+assert matches[0].distance <= 0.001
+
+assert len(matches) == vectors.shape[0]
+assert len(matches[0]) <= 10
 ```
 
 You can also override the default `threads` and `copy` arguments in bulk workloads.
@@ -257,17 +261,22 @@ from usearch.io import load_matrix, save_matrix
 
 vectors = load_matrix('deep1B.fbin')
 index = Index(ndim=vectors.shape[1])
-index.add(labels, vectors)
+index.add(keys, vectors)
 ```
 
 One may often want to evaluate the quality of the constructed index before running in production.
 The trivial way is to measure `recall@1` on the entries already present in the index.
 
 ```py
-from usearch.eval import recall_members
+from usearch.eval import self_recall
+
+stats: SearchStats = self_recall(index, exact=True)
+assert stats.visited_members == 0, "Exact search won't attend index nodes"
+assert stats.computed_distances == len(index), "And will compute the distance to every node"
 
-assert recall_members(index, exact=True) == 1
-print(recall_members(index, exact=False))
+stats: SearchStats = self_recall(index, exact=False)
+assert stats.visited_members > 0
+assert stats.computed_distances <= len(index)
 ```
 
 In case you have some ground-truth data for more than one entry, you compare search results against expected values:
diff --git a/python/lib.cpp b/python/lib.cpp
index 2df24ba4..1d8b92a0 100644
--- a/python/lib.cpp
+++ b/python/lib.cpp
@@ -1,6 +1,6 @@
 /**
  *  @file python.cpp
- *  @author Ashot Vardanian
+ *  @author Ash Vardanian
  *  @brief Python bindings for Unum USearch.
  *  @date 2023-04-26
  *
@@ -12,6 +12,7 @@
  *
  *  @copyright Copyright (c) 2023
  */
+#define __cpp_exceptions 1
 #include <limits> // `std::numeric_limits`
 #include <thread> // `std::thread`
 
@@ -21,7 +22,8 @@
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
 
-#include <usearch/index_punned_dense.hpp>
+#include <usearch/index_dense.hpp>
+#include <usearch/index_plugins.hpp>
 
 using namespace unum::usearch;
 using namespace unum;
@@ -39,83 +41,104 @@ enum class metric_signature_t {
 
 namespace py = pybind11;
 using py_shape_t = py::array::ShapeContainer;
-using label_t = typename punned_small_t::label_t;
-using id_t = typename punned_small_t::id_t;
-using metric_t = index_punned_dense_metric_t;
-using distance_t = punned_distance_t;
-using dense_index_t = punned_small_t;
-using dense_add_result_t = typename dense_index_t::add_result_t;
-using dense_search_result_t = typename dense_index_t::search_result_t;
-using dense_labeling_result_t = typename dense_index_t::labeling_result_t;
-
-struct dense_index_py_t : public dense_index_t {
-    using native_t = dense_index_t;
+#define key_t typename index_dense_t::key_t
+using metric_t = metric_punned_t;
+using distance_t = distance_punned_t;
+
+using dense_add_result_t = typename index_dense_t::add_result_t;
+using dense_search_result_t = typename index_dense_t::search_result_t;
+using dense_labeling_result_t = typename index_dense_t::labeling_result_t;
+
+struct dense_index_py_t : public index_dense_t {
+    using native_t = index_dense_t;
     using native_t::add;
     using native_t::capacity;
     using native_t::reserve;
     using native_t::search;
     using native_t::size;
 
-    dense_index_py_t(native_t&& base) : native_t(std::move(base)) {}
+    dense_index_py_t(native_t&& base) : index_dense_t(std::move(base)) {}
 };
 
-using set_member_t = std::uint32_t;
-using set_view_t = span_gt<set_member_t const>;
-using sparse_index_t = index_gt<jaccard_gt<set_member_t>, label_t, id_t>;
-
-struct sparse_index_py_t : public sparse_index_t {
-    using native_t = sparse_index_t;
-    using native_t::add;
-    using native_t::capacity;
-    using native_t::reserve;
-    using native_t::search;
-    using native_t::size;
+struct dense_indexes_py_t {
+    std::vector<std::shared_ptr<dense_index_py_t>> shards_;
+
+    void add(std::shared_ptr<dense_index_py_t> shard) { shards_.push_back(shard); }
+    std::size_t bytes_per_vector() const noexcept { return shards_.empty() ? 0 : shards_[0]->bytes_per_vector(); }
+    std::size_t scalar_words() const noexcept { return shards_.empty() ? 0 : shards_[0]->scalar_words(); }
+    index_limits_t limits() const noexcept { return {size(), std::numeric_limits<std::size_t>::max()}; }
+
+    void add_paths(std::vector<std::string> const& paths, bool view = true, std::size_t threads = 0) {
+        if (!threads)
+            threads = std::thread::hardware_concurrency();
+
+        shards_.reserve(shards_.size() + paths.size());
+        std::mutex shards_mutex;
+        executor_default_t{threads}.execute_bulk(paths.size(), [&](std::size_t, std::size_t task_idx) {
+            index_dense_t index = index_dense_t::make(paths[task_idx].c_str(), view);
+            if (!index)
+                return;
+            auto shared_index = std::make_shared<dense_index_py_t>(std::move(index));
+            std::unique_lock<std::mutex> lock(shards_mutex);
+            shards_.push_back(shared_index);
+            if (PyErr_CheckSignals() != 0)
+                throw py::error_already_set();
+        });
+    }
 
-    sparse_index_py_t(native_t&& base) : native_t(std::move(base)) {}
+    std::size_t size() const noexcept {
+        std::size_t result = 0;
+        for (auto const& shard : shards_)
+            result += shard->size();
+        return result;
+    }
 };
 
 template <typename scalar_at>
-metric_t typed_udf( //
-    metric_kind_t kind, metric_signature_t signature, std::uintptr_t metric_uintptr, scalar_kind_t accuracy) {
+metric_t typed_udf(                                                                  //
+    metric_kind_t kind, metric_signature_t signature, std::uintptr_t metric_uintptr, //
+    scalar_kind_t scalar_kind, std::size_t dimensions) {
     //
-    metric_t result;
-    result.kind_ = kind;
-    result.scalar_kind_ = accuracy;
+    using stl_function_t = metric_t::stl_function_t;
+    stl_function_t stl_function;
+    std::size_t scalar_words =
+        divide_round_up(dimensions * bits_per_scalar(scalar_kind), bits_per_scalar_word(scalar_kind));
     switch (signature) {
     case metric_signature_t::array_array_k:
-        result.func_ = [metric_uintptr](punned_vector_view_t a, punned_vector_view_t b) -> distance_t {
-            using metric_raw_t = punned_distance_t (*)(scalar_at const*, scalar_at const*);
+        stl_function = [metric_uintptr](byte_t const* a, byte_t const* b) -> distance_t {
+            using metric_raw_t = distance_punned_t (*)(scalar_at const*, scalar_at const*);
             metric_raw_t metric_ptr = reinterpret_cast<metric_raw_t>(metric_uintptr);
-            return metric_ptr((scalar_at const*)a.data(), (scalar_at const*)b.data());
+            return metric_ptr((scalar_at const*)a, (scalar_at const*)b);
         };
         break;
     case metric_signature_t::array_array_size_k:
-        result.func_ = [metric_uintptr](punned_vector_view_t a, punned_vector_view_t b) -> distance_t {
-            using metric_raw_t = punned_distance_t (*)(scalar_at const*, scalar_at const*, size_t);
+        stl_function = [metric_uintptr, scalar_words](byte_t const* a, byte_t const* b) -> distance_t {
+            using metric_raw_t = distance_punned_t (*)(scalar_at const*, scalar_at const*, size_t);
             metric_raw_t metric_ptr = reinterpret_cast<metric_raw_t>(metric_uintptr);
-            return metric_ptr((scalar_at const*)a.data(), (scalar_at const*)b.data(), a.size() / sizeof(scalar_at));
+            return metric_ptr((scalar_at const*)a, (scalar_at const*)b, scalar_words);
         };
         break;
     case metric_signature_t::array_size_array_size_k:
-        result.func_ = [metric_uintptr](punned_vector_view_t a, punned_vector_view_t b) -> distance_t {
-            using metric_raw_t = punned_distance_t (*)(scalar_at const*, size_t, scalar_at const*, size_t);
+        stl_function = [metric_uintptr, scalar_words](byte_t const* a, byte_t const* b) -> distance_t {
+            using metric_raw_t = distance_punned_t (*)(scalar_at const*, size_t, scalar_at const*, size_t);
             metric_raw_t metric_ptr = reinterpret_cast<metric_raw_t>(metric_uintptr);
-            return metric_ptr(                                            //
-                (scalar_at const*)a.data(), a.size() / sizeof(scalar_at), //
-                (scalar_at const*)b.data(), b.size() / sizeof(scalar_at));
+            return metric_ptr((scalar_at const*)a, scalar_words, (scalar_at const*)b, scalar_words);
         };
         break;
     }
-    return result;
+    return metric_t(stl_function, dimensions, kind, scalar_kind);
 }
 
-metric_t udf(metric_kind_t kind, metric_signature_t signature, std::uintptr_t metric_uintptr, scalar_kind_t accuracy) {
-    switch (accuracy) {
-    case scalar_kind_t::b1x8_k: return typed_udf<b1x8_t>(kind, signature, metric_uintptr, accuracy);
-    case scalar_kind_t::f8_k: return typed_udf<f8_bits_t>(kind, signature, metric_uintptr, accuracy);
-    case scalar_kind_t::f16_k: return typed_udf<f16_t>(kind, signature, metric_uintptr, accuracy);
-    case scalar_kind_t::f32_k: return typed_udf<f32_t>(kind, signature, metric_uintptr, accuracy);
-    case scalar_kind_t::f64_k: return typed_udf<f64_t>(kind, signature, metric_uintptr, accuracy);
+metric_t udf(                                                                        //
+    metric_kind_t kind, metric_signature_t signature, std::uintptr_t metric_uintptr, //
+    scalar_kind_t scalar_kind, std::size_t dimensions) {
+
+    switch (scalar_kind) {
+    case scalar_kind_t::b1x8_k: return typed_udf<b1x8_t>(kind, signature, metric_uintptr, scalar_kind, dimensions);
+    case scalar_kind_t::i8_k: return typed_udf<i8_bits_t>(kind, signature, metric_uintptr, scalar_kind, dimensions);
+    case scalar_kind_t::f16_k: return typed_udf<f16_t>(kind, signature, metric_uintptr, scalar_kind, dimensions);
+    case scalar_kind_t::f32_k: return typed_udf<f32_t>(kind, signature, metric_uintptr, scalar_kind, dimensions);
+    case scalar_kind_t::f64_k: return typed_udf<f64_t>(kind, signature, metric_uintptr, scalar_kind, dimensions);
     default: return {};
     }
 }
@@ -123,37 +146,19 @@ metric_t udf(metric_kind_t kind, metric_signature_t signature, std::uintptr_t me
 static dense_index_py_t make_index(      //
     std::size_t dimensions,              //
     scalar_kind_t scalar_kind,           //
-    metric_kind_t metric_kind,           //
     std::size_t connectivity,            //
     std::size_t expansion_add,           //
     std::size_t expansion_search,        //
+    metric_kind_t metric_kind,           //
     metric_signature_t metric_signature, //
-    std::uintptr_t metric_uintptr,       //
-    bool tune) {
-
-    index_config_t config;
-    config.connectivity = connectivity;
-
-    if (tune)
-        config = dense_index_t::optimize(config);
-
-    if (metric_uintptr)
-        return dense_index_t::make( //
-            dimensions, udf(metric_kind, metric_signature, metric_uintptr, scalar_kind), config, scalar_kind,
-            expansion_add, expansion_search);
-    else
-        return dense_index_t::make(dimensions, metric_kind, config, scalar_kind, expansion_add, expansion_search);
-}
-
-static std::unique_ptr<sparse_index_py_t> make_sparse_index( //
-    std::size_t connectivity,                                //
-    std::size_t expansion_add,                               //
-    std::size_t expansion_search                             //
-) {
-    index_config_t config;
-    config.connectivity = connectivity;
-
-    return std::unique_ptr<sparse_index_py_t>(new sparse_index_py_t(sparse_index_t(config)));
+    std::uintptr_t metric_uintptr) {
+
+    index_dense_config_t config(connectivity, expansion_add, expansion_search);
+    metric_t metric =  //
+        metric_uintptr //
+            ? udf(metric_kind, metric_signature, metric_uintptr, scalar_kind, dimensions)
+            : metric_t(dimensions, metric_kind, scalar_kind);
+    return index_dense_t::make(metric, config);
 }
 
 scalar_kind_t numpy_string_to_kind(std::string const& name) {
@@ -161,162 +166,96 @@ scalar_kind_t numpy_string_to_kind(std::string const& name) {
     if (name == "B" || name == "<B" || name == "u1" || name == "|u1")
         return scalar_kind_t::b1x8_k;
     else if (name == "b" || name == "<b" || name == "i1" || name == "|i1")
-        return scalar_kind_t::f8_k;
+        return scalar_kind_t::i8_k;
     else if (name == "e" || name == "<e" || name == "f2" || name == "<f2")
         return scalar_kind_t::f16_k;
     else if (name == "f" || name == "<f" || name == "f4" || name == "<f4")
         return scalar_kind_t::f32_k;
-    else if (name == "d" || name == "<d" || name == "f8" || name == "<f8")
+    else if (name == "d" || name == "<d" || name == "i8" || name == "<i8")
         return scalar_kind_t::f64_k;
     else
         return scalar_kind_t::unknown_k;
 }
 
-static void add_one_to_index(dense_index_py_t& index, label_t label, py::buffer vector, bool copy, std::size_t) {
-
-    py::buffer_info vector_info = vector.request();
-    if (vector_info.ndim != 1)
-        throw std::invalid_argument("Expects a vector, not a higher-rank tensor!");
-
-    Py_ssize_t vector_dimensions = vector_info.shape[0];
-    char const* vector_data = reinterpret_cast<char const*>(vector_info.ptr);
-    if (vector_dimensions != static_cast<Py_ssize_t>(index.scalar_words()))
-        throw std::invalid_argument("The number of vector dimensions doesn't match!");
-
-    if (!index.reserve(ceil2(index.size() + 1)))
-        throw std::invalid_argument("Out of memory!");
-
-    add_config_t config;
-    config.store_vector = copy;
-
-    switch (numpy_string_to_kind(vector_info.format)) {
-    case scalar_kind_t::b1x8_k: index.add(label, (b1x8_t const*)(vector_data), config).error.raise(); break;
-    case scalar_kind_t::f8_k: index.add(label, (f8_bits_t const*)(vector_data), config).error.raise(); break;
-    case scalar_kind_t::f16_k: index.add(label, (f16_t const*)(vector_data), config).error.raise(); break;
-    case scalar_kind_t::f32_k: index.add(label, (f32_t const*)(vector_data), config).error.raise(); break;
-    case scalar_kind_t::f64_k: index.add(label, (f64_t const*)(vector_data), config).error.raise(); break;
-    case scalar_kind_t::unknown_k:
-        throw std::invalid_argument("Incompatible scalars in the vector: " + vector_info.format);
-    }
-}
-
 template <typename scalar_at>
-static void add_typed_to_index(                                              //
-    dense_index_py_t& index,                                                 //
-    py::buffer_info const& labels_info, py::buffer_info const& vectors_info, //
-    bool copy, std::size_t threads) {
+static void add_typed_to_index(                                            //
+    dense_index_py_t& index,                                               //
+    py::buffer_info const& keys_info, py::buffer_info const& vectors_info, //
+    bool force_copy, std::size_t threads) {
 
     Py_ssize_t vectors_count = vectors_info.shape[0];
-    char const* vectors_data = reinterpret_cast<char const*>(vectors_info.ptr);
-    char const* labels_data = reinterpret_cast<char const*>(labels_info.ptr);
+    byte_t const* vectors_data = reinterpret_cast<byte_t const*>(vectors_info.ptr);
+    byte_t const* keys_data = reinterpret_cast<byte_t const*>(keys_info.ptr);
 
     executor_default_t{threads}.execute_bulk(vectors_count, [&](std::size_t thread_idx, std::size_t task_idx) {
-        add_config_t config;
-        config.store_vector = copy;
+        index_dense_update_config_t config;
+        config.force_vector_copy = force_copy;
         config.thread = thread_idx;
-        label_t label = *reinterpret_cast<label_t const*>(labels_data + task_idx * labels_info.strides[0]);
+        key_t key = *reinterpret_cast<key_t const*>(keys_data + task_idx * keys_info.strides[0]);
         scalar_at const* vector = reinterpret_cast<scalar_at const*>(vectors_data + task_idx * vectors_info.strides[0]);
-        index.add(label, vector, config).error.raise();
+        dense_add_result_t result = index.add(key, vector, config);
+        result.error.raise();
         if (PyErr_CheckSignals() != 0)
             throw py::error_already_set();
     });
 }
 
-static void add_many_to_index(                                      //
-    dense_index_py_t& index, py::buffer labels, py::buffer vectors, //
-    bool copy, std::size_t threads) {
+template <typename index_at>
+static void add_many_to_index(                            //
+    index_at& index, py::buffer keys, py::buffer vectors, //
+    bool force_copy, std::size_t threads) {
 
-    py::buffer_info labels_info = labels.request();
+    py::buffer_info keys_info = keys.request();
     py::buffer_info vectors_info = vectors.request();
 
-    if (labels_info.itemsize != sizeof(label_t))
-        throw std::invalid_argument("Incompatible label type!");
+    if (keys_info.itemsize != sizeof(key_t))
+        throw std::invalid_argument("Incompatible key type!");
 
-    if (labels_info.ndim != 1)
+    if (keys_info.ndim != 1)
         throw std::invalid_argument("Labels must be placed in a single-dimensional array!");
 
     if (vectors_info.ndim != 2)
         throw std::invalid_argument("Expects a matrix of vectors to add!");
 
-    Py_ssize_t labels_count = labels_info.shape[0];
+    Py_ssize_t keys_count = keys_info.shape[0];
     Py_ssize_t vectors_count = vectors_info.shape[0];
     Py_ssize_t vectors_dimensions = vectors_info.shape[1];
     if (vectors_dimensions != static_cast<Py_ssize_t>(index.scalar_words()))
         throw std::invalid_argument("The number of vector dimensions doesn't match!");
 
-    if (labels_count != vectors_count)
-        throw std::invalid_argument("Number of labels and vectors must match!");
+    if (keys_count != vectors_count)
+        throw std::invalid_argument("Number of keys and vectors must match!");
 
     if (!threads)
         threads = std::thread::hardware_concurrency();
     if (!index.reserve(index_limits_t(ceil2(index.size() + vectors_count), threads)))
         throw std::invalid_argument("Out of memory!");
 
+    // clang-format off
     switch (numpy_string_to_kind(vectors_info.format)) {
-    case scalar_kind_t::b1x8_k: add_typed_to_index<b1x8_t>(index, labels_info, vectors_info, copy, threads); break;
-    case scalar_kind_t::f8_k: add_typed_to_index<f8_bits_t>(index, labels_info, vectors_info, copy, threads); break;
-    case scalar_kind_t::f16_k: add_typed_to_index<f16_t>(index, labels_info, vectors_info, copy, threads); break;
-    case scalar_kind_t::f32_k: add_typed_to_index<f32_t>(index, labels_info, vectors_info, copy, threads); break;
-    case scalar_kind_t::f64_k: add_typed_to_index<f64_t>(index, labels_info, vectors_info, copy, threads); break;
-    case scalar_kind_t::unknown_k:
-        throw std::invalid_argument("Incompatible scalars in the vectors matrix: " + vectors_info.format);
+    case scalar_kind_t::b1x8_k: add_typed_to_index<b1x8_t>(index, keys_info, vectors_info, force_copy, threads); break;
+    case scalar_kind_t::i8_k: add_typed_to_index<i8_bits_t>(index, keys_info, vectors_info, force_copy, threads); break;
+    case scalar_kind_t::f16_k: add_typed_to_index<f16_t>(index, keys_info, vectors_info, force_copy, threads); break;
+    case scalar_kind_t::f32_k: add_typed_to_index<f32_t>(index, keys_info, vectors_info, force_copy, threads); break;
+    case scalar_kind_t::f64_k: add_typed_to_index<f64_t>(index, keys_info, vectors_info, force_copy, threads); break;
+    default: throw std::invalid_argument("Incompatible scalars in the vectors matrix: " + vectors_info.format);
     }
-}
-
-static py::tuple search_one_in_index(dense_index_py_t& index, py::buffer vector, std::size_t wanted, bool exact) {
-
-    py::buffer_info vector_info = vector.request();
-    Py_ssize_t vector_dimensions = vector_info.shape[0];
-    char const* vector_data = reinterpret_cast<char const*>(vector_info.ptr);
-    if (vector_dimensions != static_cast<Py_ssize_t>(index.scalar_words()))
-        throw std::invalid_argument("The number of vector dimensions doesn't match!");
-
-    py::array_t<label_t> labels_py(static_cast<Py_ssize_t>(wanted));
-    py::array_t<distance_t> distances_py(static_cast<Py_ssize_t>(wanted));
-    std::size_t count{};
-    auto labels_py1d = labels_py.template mutable_unchecked<1>();
-    auto distances_py1d = distances_py.template mutable_unchecked<1>();
-
-    search_config_t config;
-    config.exact = exact;
-
-    auto raise_and_dump = [&](dense_search_result_t result) {
-        result.error.raise();
-        count = result.dump_to(&labels_py1d(0), &distances_py1d(0));
-    };
-
-    switch (numpy_string_to_kind(vector_info.format)) {
-    case scalar_kind_t::b1x8_k: raise_and_dump(index.search((b1x8_t const*)(vector_data), wanted, config)); break;
-    case scalar_kind_t::f8_k: raise_and_dump(index.search((f8_bits_t const*)(vector_data), wanted, config)); break;
-    case scalar_kind_t::f16_k: raise_and_dump(index.search((f16_t const*)(vector_data), wanted, config)); break;
-    case scalar_kind_t::f32_k: raise_and_dump(index.search((f32_t const*)(vector_data), wanted, config)); break;
-    case scalar_kind_t::f64_k: raise_and_dump(index.search((f64_t const*)(vector_data), wanted, config)); break;
-    case scalar_kind_t::unknown_k:
-        throw std::invalid_argument("Incompatible scalars in the query vector: " + vector_info.format);
-    }
-
-    labels_py.resize(py_shape_t{static_cast<Py_ssize_t>(count)});
-    distances_py.resize(py_shape_t{static_cast<Py_ssize_t>(count)});
-
-    py::tuple results(3);
-    results[0] = labels_py;
-    results[1] = distances_py;
-    results[2] = static_cast<Py_ssize_t>(count);
-    return results;
+    // clang-format on
 }
 
 template <typename scalar_at>
 static void search_typed(                                   //
     dense_index_py_t& index, py::buffer_info& vectors_info, //
     std::size_t wanted, bool exact, std::size_t threads,    //
-    py::array_t<label_t>& labels_py, py::array_t<distance_t>& distances_py, py::array_t<Py_ssize_t>& counts_py) {
+    py::array_t<key_t>& keys_py, py::array_t<distance_t>& distances_py, py::array_t<Py_ssize_t>& counts_py,
+    std::atomic<std::size_t>& stats_visited_members, std::atomic<std::size_t>& stats_computed_distances) {
 
-    auto labels_py2d = labels_py.template mutable_unchecked<2>();
+    auto keys_py2d = keys_py.template mutable_unchecked<2>();
     auto distances_py2d = distances_py.template mutable_unchecked<2>();
     auto counts_py1d = counts_py.template mutable_unchecked<1>();
 
     Py_ssize_t vectors_count = vectors_info.shape[0];
-    char const* vectors_data = reinterpret_cast<char const*>(vectors_info.ptr);
+    byte_t const* vectors_data = reinterpret_cast<byte_t const*>(vectors_info.ptr);
 
     if (!threads)
         threads = std::thread::hardware_concurrency();
@@ -324,19 +263,77 @@ static void search_typed(                                   //
         throw std::invalid_argument("Out of memory!");
 
     executor_default_t{threads}.execute_bulk(vectors_count, [&](std::size_t thread_idx, std::size_t task_idx) {
-        search_config_t config;
+        index_search_config_t config;
         config.thread = thread_idx;
         config.exact = exact;
         scalar_at const* vector = (scalar_at const*)(vectors_data + task_idx * vectors_info.strides[0]);
         dense_search_result_t result = index.search(vector, wanted, config);
         result.error.raise();
         counts_py1d(task_idx) =
-            static_cast<Py_ssize_t>(result.dump_to(&labels_py2d(task_idx, 0), &distances_py2d(task_idx, 0)));
+            static_cast<Py_ssize_t>(result.dump_to(&keys_py2d(task_idx, 0), &distances_py2d(task_idx, 0)));
+
+        stats_visited_members += result.visited_members;
+        stats_computed_distances += result.computed_distances;
         if (PyErr_CheckSignals() != 0)
             throw py::error_already_set();
     });
 }
 
+template <typename scalar_at>
+static void search_typed(                                       //
+    dense_indexes_py_t& indexes, py::buffer_info& vectors_info, //
+    std::size_t wanted, bool exact, std::size_t threads,        //
+    py::array_t<key_t>& keys_py, py::array_t<distance_t>& distances_py, py::array_t<Py_ssize_t>& counts_py,
+    std::atomic<std::size_t>& stats_visited_members, std::atomic<std::size_t>& stats_computed_distances) {
+
+    auto keys_py2d = keys_py.template mutable_unchecked<2>();
+    auto distances_py2d = distances_py.template mutable_unchecked<2>();
+    auto counts_py1d = counts_py.template mutable_unchecked<1>();
+
+    Py_ssize_t vectors_count = vectors_info.shape[0];
+    byte_t const* vectors_data = reinterpret_cast<byte_t const*>(vectors_info.ptr);
+    for (std::size_t vector_idx = 0; vector_idx != static_cast<std::size_t>(vectors_count); ++vector_idx)
+        counts_py1d(vector_idx) = 0;
+
+    if (!threads)
+        threads = std::thread::hardware_concurrency();
+
+    std::vector<std::mutex> query_mutexes(static_cast<std::size_t>(vectors_count));
+    executor_default_t{threads}.execute_bulk(indexes.shards_.size(), [&](std::size_t, std::size_t task_idx) {
+        dense_index_py_t& index = *indexes.shards_[task_idx].get();
+
+        index_limits_t limits;
+        limits.members = index.size();
+        limits.threads_add = 0;
+        limits.threads_search = 1;
+        if (!index.reserve(limits))
+            throw std::bad_alloc();
+
+        index_search_config_t config;
+        config.thread = 0;
+        config.exact = exact;
+
+        for (std::size_t vector_idx = 0; vector_idx != static_cast<std::size_t>(vectors_count); ++vector_idx) {
+            scalar_at const* vector = (scalar_at const*)(vectors_data + vector_idx * vectors_info.strides[0]);
+            dense_search_result_t result = index.search(vector, wanted, config);
+            result.error.raise();
+            {
+                std::unique_lock<std::mutex> lock(query_mutexes[vector_idx]);
+                counts_py1d(vector_idx) = static_cast<Py_ssize_t>(result.merge_into( //
+                    &keys_py2d(vector_idx, 0),                                       //
+                    &distances_py2d(vector_idx, 0),                                  //
+                    static_cast<std::size_t>(counts_py1d(vector_idx)),               //
+                    wanted));
+            }
+
+            stats_visited_members += result.visited_members;
+            stats_computed_distances += result.computed_distances;
+            if (PyErr_CheckSignals() != 0)
+                throw py::error_already_set();
+        }
+    });
+}
+
 /**
  *  @param vectors Matrix of vectors to search for.
  *  @param wanted Number of matches per request.
@@ -346,18 +343,17 @@ static void search_typed(                                   //
  *      2. matrix of distances,
  *      3. array with match counts.
  */
+template <typename index_at>
 static py::tuple search_many_in_index( //
-    dense_index_py_t& index, py::buffer vectors, std::size_t wanted, bool exact, std::size_t threads) {
+    index_at& index, py::buffer vectors, std::size_t wanted, bool exact, std::size_t threads) {
 
     if (wanted == 0)
-        return py::tuple(3);
+        return py::tuple(5);
 
     if (index.limits().threads_search < threads)
         throw std::invalid_argument("Can't use that many threads!");
 
     py::buffer_info vectors_info = vectors.request();
-    if (vectors_info.ndim == 1)
-        return search_one_in_index(index, vectors, wanted, exact);
     if (vectors_info.ndim != 2)
         throw std::invalid_argument("Expects a matrix of vectors to add!");
 
@@ -366,65 +362,193 @@ static py::tuple search_many_in_index( //
     if (vectors_dimensions != static_cast<Py_ssize_t>(index.scalar_words()))
         throw std::invalid_argument("The number of vector dimensions doesn't match!");
 
-    py::array_t<label_t> ls({vectors_count, static_cast<Py_ssize_t>(wanted)});
-    py::array_t<distance_t> ds({vectors_count, static_cast<Py_ssize_t>(wanted)});
-    py::array_t<Py_ssize_t> cs(vectors_count);
+    py::array_t<key_t> keys_py({vectors_count, static_cast<Py_ssize_t>(wanted)});
+    py::array_t<distance_t> distances_py({vectors_count, static_cast<Py_ssize_t>(wanted)});
+    py::array_t<Py_ssize_t> counts_py(vectors_count);
+    std::atomic<std::size_t> stats_visited_members(0);
+    std::atomic<std::size_t> stats_computed_distances(0);
 
+    // clang-format off
     switch (numpy_string_to_kind(vectors_info.format)) {
-    case scalar_kind_t::b1x8_k: search_typed<b1x8_t>(index, vectors_info, wanted, exact, threads, ls, ds, cs); break;
-    case scalar_kind_t::f8_k: search_typed<f8_bits_t>(index, vectors_info, wanted, exact, threads, ls, ds, cs); break;
-    case scalar_kind_t::f16_k: search_typed<f16_t>(index, vectors_info, wanted, exact, threads, ls, ds, cs); break;
-    case scalar_kind_t::f32_k: search_typed<f32_t>(index, vectors_info, wanted, exact, threads, ls, ds, cs); break;
-    case scalar_kind_t::f64_k: search_typed<f64_t>(index, vectors_info, wanted, exact, threads, ls, ds, cs); break;
-    case scalar_kind_t::unknown_k:
-        throw std::invalid_argument("Incompatible scalars in the query matrix: " + vectors_info.format);
+    case scalar_kind_t::b1x8_k: search_typed<b1x8_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
+    case scalar_kind_t::i8_k: search_typed<i8_bits_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
+    case scalar_kind_t::f16_k: search_typed<f16_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
+    case scalar_kind_t::f32_k: search_typed<f32_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
+    case scalar_kind_t::f64_k: search_typed<f64_t>(index, vectors_info, wanted, exact, threads, keys_py, distances_py, counts_py, stats_visited_members, stats_computed_distances); break;
+    default: throw std::invalid_argument("Incompatible scalars in the query matrix: " + vectors_info.format);
     }
+    // clang-format on
 
-    py::tuple results(3);
-    results[0] = ls;
-    results[1] = ds;
-    results[2] = cs;
+    py::tuple results(5);
+    results[0] = keys_py;
+    results[1] = distances_py;
+    results[2] = counts_py;
+    results[3] = stats_visited_members.load();
+    results[4] = stats_computed_distances.load();
     return results;
 }
 
-static std::unordered_map<label_t, label_t> join_index(   //
+template <typename scalar_at>
+static void search_typed_brute_force(                                //
+    py::buffer_info& dataset_info, py::buffer_info& queries_info,    //
+    std::size_t wanted, std::size_t threads, metric_t const& metric, //
+    py::array_t<key_t>& keys_py, py::array_t<distance_t>& distances_py, py::array_t<Py_ssize_t>& counts_py) {
+
+    auto keys_py2d = keys_py.template mutable_unchecked<2>();
+    auto distances_py2d = distances_py.template mutable_unchecked<2>();
+    auto counts_py1d = counts_py.template mutable_unchecked<1>();
+
+    std::size_t dataset_count = static_cast<std::size_t>(dataset_info.shape[0]);
+    std::size_t queries_count = static_cast<std::size_t>(queries_info.shape[0]);
+    std::size_t dimensions = static_cast<std::size_t>(dataset_info.shape[1]);
+
+    byte_t const* dataset_data = reinterpret_cast<byte_t const*>(dataset_info.ptr);
+    byte_t const* queries_data = reinterpret_cast<byte_t const*>(queries_info.ptr);
+    for (std::size_t query_idx = 0; query_idx != queries_count; ++query_idx)
+        counts_py1d(query_idx) = 0;
+
+    if (!threads)
+        threads = std::thread::hardware_concurrency();
+
+    std::size_t tasks_count = static_cast<std::size_t>(dataset_count * queries_count);
+    visits_bitset_t query_mutexes(static_cast<std::size_t>(queries_count));
+    if (!query_mutexes)
+        throw std::bad_alloc();
+
+    executor_default_t{threads}.execute_bulk(tasks_count, [&](std::size_t, std::size_t task_idx) {
+        //
+        std::size_t dataset_idx = task_idx / queries_count;
+        std::size_t query_idx = task_idx % queries_count;
+
+        byte_t const* dataset = dataset_data + dataset_idx * dataset_info.strides[0];
+        byte_t const* query = queries_data + query_idx * queries_info.strides[0];
+        distance_t distance = metric(dataset, query);
+
+        {
+            auto lock = query_mutexes.lock(query_idx);
+            key_t* keys = &keys_py2d(query_idx, 0);
+            distance_t* distances = &distances_py2d(query_idx, 0);
+            std::size_t& matches = reinterpret_cast<std::size_t&>(counts_py1d(query_idx));
+            if (matches == wanted)
+                if (distances[wanted - 1] <= distance)
+                    return;
+
+            std::size_t offset = std::lower_bound(distances, distances + matches, distance) - distances;
+
+            std::size_t count_worse = matches - offset - (wanted == matches);
+            std::memmove(keys + offset + 1, keys + offset, count_worse * sizeof(key_t));
+            std::memmove(distances + offset + 1, distances + offset, count_worse * sizeof(distance_t));
+            keys[offset] = static_cast<key_t>(dataset_idx);
+            distances[offset] = distance;
+            matches += matches != wanted;
+        }
+
+        if (PyErr_CheckSignals() != 0)
+            throw py::error_already_set();
+    });
+}
+
+static py::tuple search_many_brute_force(    //
+    py::buffer dataset, py::buffer queries,  //
+    std::size_t wanted, std::size_t threads, //
+    metric_kind_t metric_kind,               //
+    metric_signature_t metric_signature,     //
+    std::uintptr_t metric_uintptr) {
+
+    if (wanted == 0)
+        return py::tuple(5);
+
+    py::buffer_info dataset_info = dataset.request();
+    py::buffer_info queries_info = queries.request();
+    if (dataset_info.ndim != 2 || queries_info.ndim != 2)
+        throw std::invalid_argument("Expects a matrix of dataset to add!");
+
+    Py_ssize_t dataset_count = dataset_info.shape[0];
+    Py_ssize_t dataset_dimensions = dataset_info.shape[1];
+    Py_ssize_t queries_count = queries_info.shape[0];
+    Py_ssize_t queries_dimensions = queries_info.shape[1];
+    if (dataset_dimensions != queries_dimensions)
+        throw std::invalid_argument("The number of vector dimensions doesn't match!");
+
+    scalar_kind_t dataset_kind = numpy_string_to_kind(dataset_info.format);
+    scalar_kind_t queries_kind = numpy_string_to_kind(queries_info.format);
+    if (dataset_kind != queries_kind)
+        throw std::invalid_argument("The types of vectors don't match!");
+
+    py::array_t<key_t> keys_py({dataset_count, static_cast<Py_ssize_t>(wanted)});
+    py::array_t<distance_t> distances_py({dataset_count, static_cast<Py_ssize_t>(wanted)});
+    py::array_t<Py_ssize_t> counts_py(dataset_count);
+
+    std::size_t dimensions = static_cast<std::size_t>(queries_dimensions);
+    metric_t metric =  //
+        metric_uintptr //
+            ? udf(metric_kind, metric_signature, metric_uintptr, queries_kind, dimensions)
+            : metric_t(dimensions, metric_kind, queries_kind);
+
+    // clang-format off
+    switch (dataset_kind) {
+    case scalar_kind_t::b1x8_k: search_typed_brute_force<b1x8_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
+    case scalar_kind_t::i8_k: search_typed_brute_force<i8_bits_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
+    case scalar_kind_t::f16_k: search_typed_brute_force<f16_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
+    case scalar_kind_t::f32_k: search_typed_brute_force<f32_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
+    case scalar_kind_t::f64_k: search_typed_brute_force<f64_t>(dataset_info, queries_info, wanted, threads, metric, keys_py, distances_py, counts_py); break;
+    default: throw std::invalid_argument("Incompatible vector types: " + dataset_info.format);
+    }
+    // clang-format on
+
+    py::tuple results(5);
+    results[0] = keys_py;
+    results[1] = distances_py;
+    results[2] = counts_py;
+    results[3] = 0;
+    results[4] = static_cast<std::size_t>(dataset_count * queries_count);
+    return results;
+}
+
+static std::unordered_map<key_t, key_t> join_index(       //
     dense_index_py_t const& a, dense_index_py_t const& b, //
     std::size_t max_proposals, bool exact) {
 
-    std::unordered_map<label_t, label_t> a_to_b;
+    std::unordered_map<key_t, key_t> a_to_b;
+    dummy_label_to_label_mapping_t b_to_a;
     a_to_b.reserve((std::min)(a.size(), b.size()));
 
-    using join_result_t = typename dense_index_py_t::join_result_t;
-    join_config_t config;
-
+    index_join_config_t config;
     config.max_proposals = max_proposals;
     config.exact = exact;
     config.expansion = (std::max)(a.expansion_search(), b.expansion_search());
     std::size_t threads = (std::min)(a.limits().threads(), b.limits().threads());
     executor_default_t executor{threads};
-    join_result_t result = dense_index_py_t::join( //
-        a, b, config,                              //
-        a_to_b,                                    //
-        dummy_label_to_label_mapping_t{},          //
-        executor);
+    join_result_t result = a.join(b, config, a_to_b, b_to_a, executor);
     result.error.raise();
+
     return a_to_b;
 }
 
 static dense_index_py_t copy_index(dense_index_py_t const& index) {
 
     using copy_result_t = typename dense_index_py_t::copy_result_t;
-    copy_config_t config;
-
-    copy_result_t result = index.copy();
+    index_copy_config_t config;
+    copy_result_t result = index.copy(config);
     result.error.raise();
     return std::move(result.index);
 }
 
+static void compact_index(dense_index_py_t& index, std::size_t threads) {
+
+    if (!threads)
+        threads = std::thread::hardware_concurrency();
+    if (!index.reserve(index_limits_t(index.size(), threads)))
+        throw std::invalid_argument("Out of memory!");
+
+    index.compact(executor_default_t{threads});
+}
+
 // clang-format off
 template <typename index_at> void save_index(index_at const& index, std::string const& path) { index.save(path.c_str()).error.raise(); }
 template <typename index_at> void load_index(index_at& index, std::string const& path) { index.load(path.c_str()).error.raise(); }
 template <typename index_at> void view_index(index_at& index, std::string const& path) { index.view(path.c_str()).error.raise(); }
+template <typename index_at> void reset_index(index_at& index) { index.reset(); }
 template <typename index_at> void clear_index(index_at& index) { index.clear(); }
 template <typename index_at> std::size_t max_level(index_at const &index) { return index.max_level(); }
 template <typename index_at> typename index_at::stats_t compute_stats(index_at const &index) { return index.stats(); }
@@ -432,41 +556,39 @@ template <typename index_at> typename index_at::stats_t compute_level_stats(inde
 // clang-format on
 
 template <typename internal_at, typename external_at = internal_at, typename index_at = void>
-py::object get_typed_member(index_at const& index, label_t label) {
-    std::size_t result_slots = std::is_same<internal_at, b1x8_t>() ? index.scalar_words() : index.dimensions();
-    py::array_t<external_at> result_py(static_cast<Py_ssize_t>(result_slots));
+py::object get_typed_member(index_at const& index, key_t key) {
+    py::array_t<external_at> result_py(static_cast<Py_ssize_t>(index.scalar_words()));
     auto result_py1d = result_py.template mutable_unchecked<1>();
-    if (!index.get(label, (internal_at*)&result_py1d(0)))
+    if (!index.get(key, (internal_at*)&result_py1d(0)))
         return py::none();
     return py::object(result_py);
 }
 
-template <typename index_at> py::object get_member(index_at const& index, label_t label, scalar_kind_t scalar_kind) {
+template <typename index_at> py::object get_member(index_at const& index, key_t key, scalar_kind_t scalar_kind) {
     if (scalar_kind == scalar_kind_t::f32_k)
-        return get_typed_member<f32_t>(index, label);
+        return get_typed_member<f32_t>(index, key);
     else if (scalar_kind == scalar_kind_t::f64_k)
-        return get_typed_member<f64_t>(index, label);
+        return get_typed_member<f64_t>(index, key);
     else if (scalar_kind == scalar_kind_t::f16_k)
-        return get_typed_member<f16_t, std::uint16_t>(index, label);
-    else if (scalar_kind == scalar_kind_t::f8_k)
-        return get_typed_member<f8_bits_t, std::int8_t>(index, label);
+        return get_typed_member<f16_t, std::uint16_t>(index, key);
+    else if (scalar_kind == scalar_kind_t::i8_k)
+        return get_typed_member<i8_bits_t, std::int8_t>(index, key);
     else if (scalar_kind == scalar_kind_t::b1x8_k)
-        return get_typed_member<b1x8_t, std::uint8_t>(index, label);
+        return get_typed_member<b1x8_t, std::uint8_t>(index, key);
     else
         throw std::invalid_argument("Incompatible scalars in the query matrix!");
 }
 
-template <typename index_at>
-py::array_t<label_t> get_labels(index_at const& index, std::size_t offset, std::size_t limit) {
+template <typename index_at> py::array_t<key_t> get_keys(index_at const& index, std::size_t offset, std::size_t limit) {
     limit = std::min(index.size(), limit);
-    py::array_t<label_t> result_py(static_cast<Py_ssize_t>(limit));
+    py::array_t<key_t> result_py(static_cast<Py_ssize_t>(limit));
     auto result_py1d = result_py.template mutable_unchecked<1>();
-    index.export_labels(&result_py1d(0), offset, limit);
+    index.export_keys(&result_py1d(0), offset, limit);
     return result_py;
 }
 
-template <typename index_at> py::array_t<label_t> get_all_labels(index_at const& index) {
-    return get_labels(index, 0, index.size());
+template <typename index_at> py::array_t<key_t> get_all_keys(index_at const& index) {
+    return get_keys(index, 0, index.size());
 }
 
 template <typename element_at> bool has_duplicates(element_at const* begin, element_at const* end) {
@@ -481,97 +603,6 @@ template <typename element_at> bool has_duplicates(element_at const* begin, elem
     return false;
 }
 
-void validate_set(py::array_t<set_member_t> const& set) {
-    if (set.ndim() != 1)
-        throw std::invalid_argument("Set can't be multi-dimensional!");
-    if (set.strides(0) != sizeof(set_member_t))
-        throw std::invalid_argument("Set can't be strided!");
-    auto proxy = set.unchecked<1>();
-    set_member_t const* begin = &proxy(0);
-    set_member_t const* end = begin + proxy.size();
-    if (!std::is_sorted(begin, end))
-        throw std::invalid_argument("Set must be sorted!");
-    if (has_duplicates(begin, end))
-        throw std::invalid_argument("Set must be deduplicated!");
-}
-#if 0
-
-inline std::size_t hash_ror64(std::size_t v, int r) noexcept { return (v >> r) | (v << (64 - r)); }
-
-inline std::size_t hash(std::size_t v) noexcept {
-    v ^= hash_ror64(v, 25) ^ hash_ror64(v, 50);
-    v *= 0xA24BAED4963EE407UL;
-    v ^= hash_ror64(v, 24) ^ hash_ror64(v, 49);
-    v *= 0x9FB21C651E98DF25UL;
-    return v ^ v >> 28;
-}
-
-template <typename scalar_at>
-void hash_typed_row(                                                             //
-    byte_t const* scalars, std::size_t scalar_stride, std::size_t scalars_count, //
-    b1x8_t* hashes, std::size_t bits) noexcept {
-
-    std::size_t words = divide_round_up<8>(bits);
-    for (std::size_t i = 0; i != scalars_count; ++i) {
-        scalar_at scalar;
-        std::memcpy(&scalar, scalars + i * scalar_stride, sizeof(scalar_at));
-        std::size_t scalar_hash = hash(scalar);
-        hashes[scalar_hash & (words - 1)] |= std::uint8_t(1) << (scalar_hash % 8);
-    }
-}
-
-template <typename scalar_at>
-py::array_t<bits_numpy_word_t> hash_typed_buffer(py::buffer_info const& info, std::size_t bits) {
-    byte_t const* data = reinterpret_cast<byte_t const*>(info.ptr);
-    Py_ssize_t elements_per_row = info.shape[0];
-    Py_ssize_t elements_stride = info.strides[0];
-    Py_ssize_t words_per_row = divide_round_up<std::size_t>(bits, 8);
-
-    if (info.ndim == 2) {
-        Py_ssize_t rows_count = info.shape[1];
-        Py_ssize_t rows_stride = info.strides[1];
-        auto hashes_shape = py_shape_t{rows_count, words_per_row};
-        auto hashes_py = py::array_t<bits_numpy_word_t>(hashes_shape);
-        auto hashes_proxy = hashes_py.template mutable_unchecked<2>();
-
-        for (Py_ssize_t i = 0; i != rows_count; ++i)
-            hash_typed_row(                                                                                 //
-                data + i * rows_stride, hashes_proxy.stride(1), static_cast<std::size_t>(elements_per_row), //
-                &hashes_proxy(i, 0), bits);
-
-        return hashes_py;
-    } else {
-        auto hashes_shape = py_shape_t{words_per_row};
-        auto hashes_py = py::array_t<bits_numpy_word_t>(hashes_shape);
-        auto hashes_proxy = hashes_py.template mutable_unchecked<1>();
-
-        hash_typed_row(                                                               //
-            data, hashes_info.strides[0], static_cast<std::size_t>(elements_per_row), //
-            &hashes_proxy(0), bits);
-
-        return hashes_py;
-    }
-}
-
-py::array_t<bits_numpy_word_t> hash_buffer(py::buffer vector, std::size_t bits) {
-    if (std::bitset<64>(bits).count() == 1)
-        throw std::invalid_argument("Number of bits must be a power of two!");
-    py::buffer_info info = vector.request();
-    if (info.ndim > 2)
-        throw std::invalid_argument("Only one or two-dimensional arrays are supported!");
-
-    // https://docs.python.org/3/library/struct.html#format-characters
-    if (info.format == "h" || info.format == "H")
-        return hash_typed_buffer<std::uint16_t>(info, bits);
-    else if (info.format == "i" || info.format == "I" || info.format == "l" || info.format == "L")
-        return hash_typed_buffer<std::uint32_t>(info, bits);
-    else if (info.format == "q" || info.format == "Q" || info.format == "n" || info.format == "N")
-        return hash_typed_buffer<std::uint64_t>(info, bits);
-    else
-        throw std::invalid_argument("Array elements must be 16, 32, or 64 bit hashable integers!");
-}
-#endif
-
 PYBIND11_MODULE(compiled, m) {
     m.doc() = "Smaller & Faster Single-File Vector Search Engine from Unum";
 
@@ -590,92 +621,109 @@ PYBIND11_MODULE(compiled, m) {
 
     py::enum_<metric_kind_t>(m, "MetricKind")
         .value("Unknown", metric_kind_t::unknown_k)
-        .value("IP", metric_kind_t::ip_k)
+
+        .value("IP", metric_kind_t::cos_k)
         .value("Cos", metric_kind_t::cos_k)
         .value("L2sq", metric_kind_t::l2sq_k)
+
         .value("Haversine", metric_kind_t::haversine_k)
         .value("Pearson", metric_kind_t::pearson_k)
         .value("Jaccard", metric_kind_t::jaccard_k)
         .value("Hamming", metric_kind_t::hamming_k)
         .value("Tanimoto", metric_kind_t::tanimoto_k)
-        .value("Sorensen", metric_kind_t::sorensen_k);
+        .value("Sorensen", metric_kind_t::sorensen_k)
+
+        .value("Cosine", metric_kind_t::cos_k)
+        .value("InnerProduct", metric_kind_t::cos_k);
 
     py::enum_<scalar_kind_t>(m, "ScalarKind")
+        .value("Unknown", scalar_kind_t::unknown_k)
+        .value("B1", scalar_kind_t::b1x8_k)
+        .value("U40", scalar_kind_t::u40_k)
+        .value("UUID", scalar_kind_t::uuid_k)
         .value("F64", scalar_kind_t::f64_k)
         .value("F32", scalar_kind_t::f32_k)
         .value("F16", scalar_kind_t::f16_k)
         .value("F8", scalar_kind_t::f8_k)
-        .value("B1", scalar_kind_t::b1x8_k);
-
-    auto h = py::class_<file_head_result_t>(m, "IndexMetadata");
-    h.def(py::init([](std::string const& path) {
-        file_head_result_t h = index_metadata(path.c_str());
-        h.error.raise();
-        return h;
-    }));
-    h.def_property_readonly("version", [](file_head_result_t const& h) {
-        return                                      //
-            std::to_string(h.version_major) + "." + //
-            std::to_string(h.version_minor) + "." + //
-            std::to_string(h.version_patch);
+        .value("U64", scalar_kind_t::u64_k)
+        .value("U32", scalar_kind_t::u32_k)
+        .value("U16", scalar_kind_t::u16_k)
+        .value("U8", scalar_kind_t::u8_k)
+        .value("I64", scalar_kind_t::i64_k)
+        .value("I32", scalar_kind_t::i32_k)
+        .value("I16", scalar_kind_t::i16_k)
+        .value("I8", scalar_kind_t::i8_k);
+
+    m.def("index_dense_metadata", [](std::string const& path) -> py::dict {
+        index_dense_metadata_result_t meta = index_dense_metadata(path.c_str());
+        meta.error.raise();
+        index_dense_head_t const& head = meta.head;
+
+        py::dict result;
+        result["matrix_included"] = !meta.config.exclude_vectors;
+        result["matrix_uses_64_bit_dimensions"] = meta.config.use_64_bit_dimensions;
+
+        result["version"] = std::to_string(head.version_major) + "." + //
+                            std::to_string(head.version_minor) + "." + //
+                            std::to_string(head.version_patch);
+
+        result["kind_metric"] = metric_kind_t(head.kind_metric);
+        result["kind_scalar"] = scalar_kind_t(head.kind_scalar);
+        result["kind_key"] = scalar_kind_t(head.kind_key);
+        result["kind_compressed_slot"] = scalar_kind_t(head.kind_compressed_slot);
+
+        result["count_present"] = std::uint64_t(head.count_present);
+        result["count_deleted"] = std::uint64_t(head.count_deleted);
+        result["dimensions"] = std::uint64_t(head.dimensions);
+
+        return result;
     });
-    h.def_readonly("metric", &file_head_result_t::metric);
-    h.def_readonly("connectivity", &file_head_result_t::connectivity);
-    h.def_readonly("max_level", &file_head_result_t::max_level);
-    h.def_readonly("vector_alignment", &file_head_result_t::vector_alignment);
-    h.def_readonly("bytes_per_label", &file_head_result_t::bytes_per_label);
-    h.def_readonly("bytes_per_id", &file_head_result_t::bytes_per_id);
-    h.def_readonly("scalar_kind", &file_head_result_t::scalar_kind);
-    h.def_readonly("size", &file_head_result_t::size);
-    h.def_readonly("entry_idx", &file_head_result_t::entry_idx);
-    h.def_readonly("bytes_for_graphs", &file_head_result_t::bytes_for_graphs);
-    h.def_readonly("bytes_for_vectors", &file_head_result_t::bytes_for_vectors);
-    h.def_readonly("bytes_checksum", &file_head_result_t::bytes_checksum);
-
-    auto i = py::class_<dense_index_py_t>(m, "Index");
+
+    m.def("exact_search", &search_many_brute_force,                        //
+          py::arg("dataset"),                                              //
+          py::arg("queries"),                                              //
+          py::arg("count") = 10,                                           //
+          py::kw_only(),                                                   //
+          py::arg("threads") = 0,                                          //
+          py::arg("metric_kind") = metric_kind_t::cos_k,                   //
+          py::arg("metric_signature") = metric_signature_t::array_array_k, //
+          py::arg("metric_pointer") = 0                                    //
+    );
+
+    auto i = py::class_<dense_index_py_t, std::shared_ptr<dense_index_py_t>>(m, "Index");
 
     i.def(py::init(&make_index),                                           //
           py::kw_only(),                                                   //
           py::arg("ndim") = 0,                                             //
           py::arg("dtype") = scalar_kind_t::f32_k,                         //
-          py::arg("metric") = metric_kind_t::ip_k,                         //
           py::arg("connectivity") = default_connectivity(),                //
           py::arg("expansion_add") = default_expansion_add(),              //
           py::arg("expansion_search") = default_expansion_search(),        //
+          py::arg("metric_kind") = metric_kind_t::cos_k,                   //
           py::arg("metric_signature") = metric_signature_t::array_array_k, //
-          py::arg("metric_pointer") = 0,                                   //
-          py::arg("tune") = false                                          //
-    );
-
-    i.def(                         //
-        "add", &add_many_to_index, //
-        py::arg("labels"),         //
-        py::arg("vectors"),        //
-        py::kw_only(),             //
-        py::arg("copy") = true,    //
-        py::arg("threads") = 0     //
+          py::arg("metric_pointer") = 0                                    //
     );
 
-    i.def(                        //
-        "add", &add_one_to_index, //
-        py::arg("label"),         //
-        py::arg("vector"),        //
-        py::kw_only(),            //
-        py::arg("copy") = true,   //
-        py::arg("threads") = 0    //
+    i.def(                                           //
+        "add", &add_many_to_index<dense_index_py_t>, //
+        py::arg("keys"),                             //
+        py::arg("vectors"),                          //
+        py::kw_only(),                               //
+        py::arg("copy") = true,                      //
+        py::arg("threads") = 0                       //
     );
 
-    i.def(                               //
-        "search", &search_many_in_index, //
-        py::arg("query"),                //
-        py::arg("count") = 10,           //
-        py::arg("exact") = false,        //
-        py::arg("threads") = 0           //
+    i.def(                                                 //
+        "search", &search_many_in_index<dense_index_py_t>, //
+        py::arg("query"),                                  //
+        py::arg("count") = 10,                             //
+        py::arg("exact") = false,                          //
+        py::arg("threads") = 0                             //
     );
 
     i.def(
         "rename",
-        [](dense_index_py_t& index, label_t from, label_t to) -> bool {
+        [](dense_index_py_t& index, key_t from, key_t to) -> bool {
             dense_labeling_result_t result = index.rename(from, to);
             result.error.raise();
             return result.completed;
@@ -684,8 +732,8 @@ PYBIND11_MODULE(compiled, m) {
 
     i.def(
         "remove",
-        [](dense_index_py_t& index, label_t label, bool compact, std::size_t threads) -> bool {
-            dense_labeling_result_t result = index.remove(label);
+        [](dense_index_py_t& index, key_t key, bool compact, std::size_t threads) -> bool {
+            dense_labeling_result_t result = index.remove(key);
             result.error.raise();
             if (!compact)
                 return result.completed;
@@ -695,16 +743,15 @@ PYBIND11_MODULE(compiled, m) {
             if (!index.reserve(index_limits_t(index.size(), threads)))
                 throw std::invalid_argument("Out of memory!");
 
-            index.compact(executor_default_t{threads});
+            index.isolate(executor_default_t{threads});
             return result.completed;
         },
-        py::arg("label"), py::arg("compact"), py::arg("threads"));
+        py::arg("key"), py::arg("compact"), py::arg("threads"));
 
     i.def(
         "remove",
-        [](dense_index_py_t& index, std::vector<label_t> const& labels, bool compact,
-           std::size_t threads) -> std::size_t {
-            dense_labeling_result_t result = index.remove(labels.begin(), labels.end());
+        [](dense_index_py_t& index, std::vector<key_t> const& keys, bool compact, std::size_t threads) -> std::size_t {
+            dense_labeling_result_t result = index.remove(keys.begin(), keys.end());
             result.error.raise();
             if (!compact)
                 return result.completed;
@@ -714,18 +761,19 @@ PYBIND11_MODULE(compiled, m) {
             if (!index.reserve(index_limits_t(index.size(), threads)))
                 throw std::invalid_argument("Out of memory!");
 
-            index.compact(executor_default_t{threads});
+            index.isolate(executor_default_t{threads});
             return result.completed;
         },
-        py::arg("label"), py::arg("compact"), py::arg("threads"));
+        py::arg("key"), py::arg("compact"), py::arg("threads"));
 
     i.def("__len__", &dense_index_py_t::size);
     i.def_property_readonly("size", &dense_index_py_t::size);
-    i.def_property_readonly("ndim", &dense_index_py_t::dimensions);
     i.def_property_readonly("connectivity", &dense_index_py_t::connectivity);
     i.def_property_readonly("capacity", &dense_index_py_t::capacity);
+    i.def_property_readonly("ndim",
+                            [](dense_index_py_t const& index) -> std::size_t { return index.metric().dimensions(); });
     i.def_property_readonly( //
-        "dtype", [](dense_index_py_t const& index) -> scalar_kind_t { return index.metric().scalar_kind_; });
+        "dtype", [](dense_index_py_t const& index) -> scalar_kind_t { return index.scalar_kind(); });
     i.def_property_readonly( //
         "memory_usage", [](dense_index_py_t const& index) -> std::size_t { return index.memory_usage(); },
         py::call_guard<py::gil_scoped_release>());
@@ -733,17 +781,36 @@ PYBIND11_MODULE(compiled, m) {
     i.def_property("expansion_add", &dense_index_py_t::expansion_add, &dense_index_py_t::change_expansion_add);
     i.def_property("expansion_search", &dense_index_py_t::expansion_search, &dense_index_py_t::change_expansion_search);
 
-    i.def_property_readonly("labels", &get_all_labels<dense_index_py_t>);
-    i.def("get_labels", &get_labels<dense_index_py_t>, py::arg("offset") = 0,
+    i.def(
+        "change_metric",
+        [](dense_index_py_t& index, metric_kind_t metric_kind, metric_signature_t metric_signature,
+           std::uintptr_t metric_uintptr) {
+            scalar_kind_t scalar_kind = index.scalar_kind();
+            std::size_t dimensions = index.dimensions();
+            metric_t metric =  //
+                metric_uintptr //
+                    ? udf(metric_kind, metric_signature, metric_uintptr, scalar_kind, dimensions)
+                    : metric_t(dimensions, metric_kind, scalar_kind);
+            index.change_metric(std::move(metric));
+        },
+        py::arg("metric_kind") = metric_kind_t::cos_k,                   //
+        py::arg("metric_signature") = metric_signature_t::array_array_k, //
+        py::arg("metric_pointer") = 0                                    //
+    );
+
+    i.def_property_readonly("keys", &get_all_keys<dense_index_py_t>);
+    i.def("get_keys", &get_keys<dense_index_py_t>, py::arg("offset") = 0,
           py::arg("limit") = std::numeric_limits<std::size_t>::max());
     i.def("__contains__", &dense_index_py_t::contains);
-    i.def("__getitem__", &get_member<dense_index_py_t>, py::arg("label"), py::arg("dtype") = scalar_kind_t::f32_k);
+    i.def("__getitem__", &get_member<dense_index_py_t>, py::arg("key"), py::arg("dtype") = scalar_kind_t::f32_k);
 
     i.def("save", &save_index<dense_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
     i.def("load", &load_index<dense_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
     i.def("view", &view_index<dense_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
+    i.def("reset", &reset_index<dense_index_py_t>, py::call_guard<py::gil_scoped_release>());
     i.def("clear", &clear_index<dense_index_py_t>, py::call_guard<py::gil_scoped_release>());
     i.def("copy", &copy_index, py::call_guard<py::gil_scoped_release>());
+    i.def("compact", &compact_index, py::call_guard<py::gil_scoped_release>());
     i.def("join", &join_index, py::arg("other"), py::arg("max_proposals") = 0, py::arg("exact") = false,
           py::call_guard<py::gil_scoped_release>());
 
@@ -758,60 +825,17 @@ PYBIND11_MODULE(compiled, m) {
     i.def_property_readonly("levels_stats", &compute_stats<dense_index_py_t>);
     i.def("level_stats", &compute_level_stats<dense_index_py_t>, py::arg("level"));
 
-    auto si = py::class_<sparse_index_py_t>(m, "SparseIndex");
-
-    si.def(                                                      //
-        py::init(&make_sparse_index),                            //
-        py::kw_only(),                                           //
-        py::arg("connectivity") = default_connectivity(),        //
-        py::arg("expansion_add") = default_expansion_add(),      //
-        py::arg("expansion_search") = default_expansion_search() //
-    );
-
-    si.def( //
-        "add",
-        [](sparse_index_py_t& index, label_t label, py::array_t<set_member_t> set, bool copy) {
-            validate_set(set);
-            if (index.size() + 1 >= index.capacity())
-                index.reserve(ceil2(index.size() + 1));
-            auto proxy = set.unchecked<1>();
-            auto view = set_view_t{&proxy(0), static_cast<std::size_t>(proxy.shape(0))};
-
-            add_config_t config;
-            config.store_vector = copy;
-            index.add(label, view, config).error.raise();
-        },                     //
-        py::arg("label"),      //
-        py::arg("set"),        //
-        py::kw_only(),         //
-        py::arg("copy") = true //
+    auto is = py::class_<dense_indexes_py_t>(m, "Indexes");
+    is.def(py::init());
+    is.def("__len__", &dense_indexes_py_t::size);
+    is.def("add", &dense_indexes_py_t::add);
+    is.def("add_paths", &dense_indexes_py_t::add_paths, py::arg("paths"), py::arg("view") = true,
+           py::arg("threads") = 0);
+    is.def(                                                  //
+        "search", &search_many_in_index<dense_indexes_py_t>, //
+        py::arg("query"),                                    //
+        py::arg("count") = 10,                               //
+        py::arg("exact") = false,                            //
+        py::arg("threads") = 0                               //
     );
-
-    si.def( //
-        "search",
-        [](sparse_index_py_t& index, py::array_t<set_member_t> set, std::size_t count) -> py::array_t<label_t> {
-            validate_set(set);
-            auto proxy = set.unchecked<1>();
-            auto view = set_view_t{&proxy(0), static_cast<std::size_t>(proxy.shape(0))};
-            auto labels_py = py::array_t<label_t>(py_shape_t{static_cast<Py_ssize_t>(count)});
-            auto labels_proxy = labels_py.template mutable_unchecked<1>();
-            auto result = index.search(view, count);
-            result.error.raise();
-            auto found = result.dump_to(&labels_proxy(0));
-            labels_py.resize(py_shape_t{static_cast<Py_ssize_t>(found)});
-            return labels_py;
-        },
-        py::arg("set"),       //
-        py::arg("count") = 10 //
-    );
-
-    si.def("__len__", &sparse_index_py_t::size);
-    si.def_property_readonly("size", &sparse_index_py_t::size);
-    si.def_property_readonly("connectivity", &sparse_index_py_t::connectivity);
-    si.def_property_readonly("capacity", &sparse_index_py_t::capacity);
-
-    si.def("save", &save_index<sparse_index_py_t>, py::arg("path"));
-    si.def("load", &load_index<sparse_index_py_t>, py::arg("path"));
-    si.def("view", &view_index<sparse_index_py_t>, py::arg("path"));
-    si.def("clear", &sparse_index_py_t::clear);
 }
diff --git a/python/scripts/bench.ipynb b/python/scripts/bench.ipynb
index 545da676..d3ec0f2e 100644
--- a/python/scripts/bench.ipynb
+++ b/python/scripts/bench.ipynb
@@ -6,7 +6,7 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "!pip install faiss-cpu numba pandas plotly nbformat jinja2 kaleido tqdm sklearn scikit-learn scipy matplotlib"
+    "!pip install faiss-cpu numba pandas plotly nbformat jinja2 kaleido tqdm scikit-learn scipy matplotlib"
    ]
   },
   {
@@ -61,6 +61,7 @@
    "metadata": {},
    "outputs": [],
    "source": [
+    "from usearch.eval import Dataset\n",
     "data = Dataset.build(\n",
     "    vectors='../../datasets/wiki_1M/base.1M.fbin',\n",
     "    queries='../../datasets/wiki_1M/query.public.100K.fbin',\n",
@@ -161,7 +162,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.10.10"
+   "version": "3.10.11"
   },
   "orig_nbformat": 4
  },
diff --git a/python/scripts/bench.py b/python/scripts/bench.py
index 16571e59..cac7a8e7 100644
--- a/python/scripts/bench.py
+++ b/python/scripts/bench.py
@@ -5,7 +5,7 @@
 import numpy as np
 import pandas as pd
 
-from usearch.index import Index, Label, MetricKind, ScalarKind
+from usearch.index import Index, Key, MetricKind, ScalarKind
 from usearch.numba import jit as njit
 from usearch.eval import Evaluation, AddTask
 from usearch.index import (
@@ -26,7 +26,7 @@ def bench_speed(
     # Build various indexes:
     indexes = []
     jit_options = [False, True] if jit else [False]
-    dtype_options = [ScalarKind.F32, ScalarKind.F16, ScalarKind.F8]
+    dtype_options = [ScalarKind.F32, ScalarKind.F16, ScalarKind.I8]
     for jit, dtype in itertools.product(jit_options, dtype_options):
         metric = MetricKind.IP
         if jit:
@@ -38,7 +38,7 @@ def bench_speed(
             expansion_add=expansion_add,
             expansion_search=expansion_search,
             connectivity=connectivity,
-            path="USearch" + ["", "+JIT"][jit] + ":" + dtype,
+            path="USearch" + ["", "+JIT"][jit] + ":" + str(dtype),
         )
 
         # Skip the cases, where JIT-ing is impossible
@@ -115,7 +115,7 @@ def bench_params(
     results = []
     for connectivity, ndim in itertools.product(connectivities, dimensions):
         task = AddTask(
-            labels=np.arange(count, dtype=Label),
+            keys=np.arange(count, dtype=Key),
             vectors=np.random.rand(count, ndim).astype(np.float32),
         )
         index = Index(
diff --git a/python/scripts/index_faiss.py b/python/scripts/index_faiss.py
index 8246e381..6a57d7fe 100644
--- a/python/scripts/index_faiss.py
+++ b/python/scripts/index_faiss.py
@@ -40,14 +40,14 @@ def __init__(
 
         self.path = path
 
-    def add(self, labels, vectors):
-        # Adding labels isn't supported for most index types
-        # self._faiss.add_with_ids(vectors, labels)
+    def add(self, keys, vectors):
+        # Adding keys isn't supported for most index types
+        # self._faiss.add_with_ids(vectors, keys)
         self._faiss.add(vectors)
 
     def search(self, queries, k: int) -> Matches:
-        distances, labels = self._faiss.search(queries, k)
-        return Matches(labels, distances, np.array([k] * queries.shape[0]))
+        distances, keys = self._faiss.search(queries, k)
+        return Matches(keys, distances, np.array([k] * queries.shape[0]))
 
     def __len__(self) -> int:
         return self._faiss.ntotal
diff --git a/python/scripts/join.py b/python/scripts/join.py
index 31f7b965..43ddcac9 100644
--- a/python/scripts/join.py
+++ b/python/scripts/join.py
@@ -110,28 +110,28 @@
         exact=exact,
     )
 
-    secs, a_self_recall = dt(lambda: a.search(a.vectors, **args).recall(a.labels))
+    secs, a_self_recall = dt(lambda: a.search(a.vectors, **args).recall(a.keys))
     print(
         "Self-recall @{} of {} index: {:.2f}%, took {:.2f}s".format(
             k, a_name, a_self_recall * 100, secs
         )
     )
 
-    secs, b_self_recall = dt(lambda: b.search(b.vectors, **args).recall(b.labels))
+    secs, b_self_recall = dt(lambda: b.search(b.vectors, **args).recall(b.keys))
     print(
         "Self-recall @{} of {} index: {:.2f}%, took {:.2f}s".format(
             k, b_name, b_self_recall * 100, secs
         )
     )
 
-    secs, ab_recall = dt(lambda: b.search(a.vectors, **args).recall(b.labels))
+    secs, ab_recall = dt(lambda: b.search(a.vectors, **args).recall(b.keys))
     print(
         "Cross-recall @{} of {} in {}: {:.2f}%, took {:.2f}s".format(
             k, a_name, b_name, ab_recall * 100, secs
         )
     )
 
-    secs, ba_recall = dt(lambda: a.search(b.vectors, **args).recall(a.labels))
+    secs, ba_recall = dt(lambda: a.search(b.vectors, **args).recall(a.keys))
     print(
         "Cross-recall @{} of {} in {}: {:.2f}%, took {:.2f}s".format(
             k, b_name, a_name, ba_recall * 100, secs
diff --git a/python/usearch/client.py b/python/usearch/client.py
index 13442509..684e12a4 100644
--- a/python/usearch/client.py
+++ b/python/usearch/client.py
@@ -21,36 +21,33 @@ def _vector_to_ascii(vector: np.ndarray) -> Optional[str]:
 
 
 class IndexClient:
-
     def __init__(
-            self,
-            uri: str = '127.0.0.1',
-            port: int = 8545,
-            use_http: bool = True) -> None:
+        self, uri: str = "127.0.0.1", port: int = 8545, use_http: bool = True
+    ) -> None:
         self.client = Client(uri=uri, port=port, use_http=use_http)
 
-    def add_one(self, label: int, vector: np.ndarray):
-        assert isinstance(label, int)
+    def add_one(self, key: int, vector: np.ndarray):
+        assert isinstance(key, int)
         assert isinstance(vector, np.ndarray)
         vector = vector.flatten()
         ascii = _vector_to_ascii(vector)
         if ascii:
-            self.client.add_ascii(label=label, string=ascii)
+            self.client.add_ascii(key=key, string=ascii)
         else:
-            self.client.add_one(label=label, vectors=vector)
+            self.client.add_one(key=key, vectors=vector)
 
-    def add_many(self, labels: np.ndarray, vectors: np.ndarray):
-        assert isinstance(labels, int)
+    def add_many(self, keys: np.ndarray, vectors: np.ndarray):
+        assert isinstance(keys, int)
         assert isinstance(vectors, np.ndarray)
-        assert labels.ndim == 1 and vectors.ndim == 2
-        assert labels.shape[0] == vectors.shape[0]
-        self.client.add_many(labels=labels, vectors=vectors)
+        assert keys.ndim == 1 and vectors.ndim == 2
+        assert keys.shape[0] == vectors.shape[0]
+        self.client.add_many(keys=keys, vectors=vectors)
 
-    def add(self, labels: Union[np.ndarray, int], vectors: np.ndarray):
-        if isinstance(labels, int) or len(labels) == 1:
-            return self.add_one(labels, vectors)
+    def add(self, keys: Union[np.ndarray, int], vectors: np.ndarray):
+        if isinstance(keys, int) or len(keys) == 1:
+            return self.add_one(keys, vectors)
         else:
-            return self.add_many(labels, vectors)
+            return self.add_many(keys, vectors)
 
     def search_one(self, vector: np.ndarray, count: int) -> Matches:
         matches: List[dict] = []
@@ -64,31 +61,32 @@ def search_one(self, vector: np.ndarray, count: int) -> Matches:
         print(matches.data)
         matches = matches.json
 
-        labels = np.array((1, count), dtype=np.uint32)
+        keys = np.array((1, count), dtype=np.uint32)
         distances = np.array((1, count), dtype=np.float32)
         counts = np.array((1), dtype=np.uint32)
         for col, result in enumerate(matches):
-            labels[0, col] = result['label']
-            distances[0, col] = result['distance']
+            keys[0, col] = result["key"]
+            distances[0, col] = result["distance"]
         counts[0] = len(matches)
 
-        return labels, distances, counts
+        return keys, distances, counts
 
     def search_many(self, vectors: np.ndarray, count: int) -> Matches:
         batch_size: int = vectors.shape[0]
         list_of_matches: List[List[dict]] = self.client.search_many(
-            vectors=vectors, count=count)
+            vectors=vectors, count=count
+        )
 
-        labels = np.array((batch_size, count), dtype=np.uint32)
+        keys = np.array((batch_size, count), dtype=np.uint32)
         distances = np.array((batch_size, count), dtype=np.float32)
         counts = np.array((batch_size), dtype=np.uint32)
         for row, matches in enumerate(list_of_matches):
             for col, result in enumerate(matches):
-                labels[row, col] = result['label']
-                distances[row, col] = result['distance']
+                keys[row, col] = result["key"]
+                distances[row, col] = result["distance"]
             counts[row] = len(results)
 
-        return labels, distances, counts
+        return keys, distances, counts
 
     def search(self, vectors: np.ndarray, count: int) -> Matches:
         if vectors.ndim == 1 or (vectors.ndim == 2 and vectors.shape[0] == 1):
@@ -119,7 +117,7 @@ def save(self, path: str):
         raise NotImplementedError()
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     index = IndexClient()
     index.add(42, np.array([0.4] * 256, dtype=np.float32))
     results = index.search(np.array([0.4] * 256, dtype=np.float32), 10)
diff --git a/python/usearch/eval.py b/python/usearch/eval.py
index cedcbf7a..c4c884bd 100644
--- a/python/usearch/eval.py
+++ b/python/usearch/eval.py
@@ -8,7 +8,14 @@
 import numpy as np
 
 from usearch.io import load_matrix
-from usearch.index import Index, Matches, MetricKind, MetricKindBitwise, Label
+from usearch.index import (
+    Index,
+    Matches,
+    BatchMatches,
+    MetricKind,
+    MetricKindBitwise,
+    Key,
+)
 
 
 def random_vectors(
@@ -48,28 +55,71 @@ def random_vectors(
         return x
 
 
-def recall_members(index: Index, sample: float = 1, **kwargs) -> float:
+@dataclass
+class SearchStats:
+    """
+    Contains statistics for one or more search runs, including the number of
+    internal nodes that were fetched (`visited_members`) and the number
+    of times the distance metric was invoked (`computed_distances`).
+
+    Other derivative metrics include the `mean_recall` and `mean_efficiency`.
+    Recall is the share of queried vectors, that were successfully found.
+    Efficiency describes the number of distances that had to be computed for
+    each query, normalized to size of the `index`. Highest efficiency is 0.(9),
+    lowest is zero. Highest is achieved, when the distance metric was computed
+    just once per query. Lowest happens during exact search, when every distance
+    to every present vector had to be computed.
+    """
+
+    index_size: int
+    count_queries: int
+    count_matches: int
+
+    visited_members: int
+    computed_distances: int
+
+    @property
+    def mean_efficiency(self) -> float:
+        return 1 - float(self.computed_distances) / (
+            self.count_queries * self.index_size
+        )
+
+    @property
+    def mean_recall(self) -> float:
+        return self.count_matches / self.count_queries
+
+
+def self_recall(index: Index, sample: float = 1, **kwargs) -> SearchStats:
     """Simplest benchmark for a quality of search, which queries every
     existing member of the index, to make sure approximate search finds
     the point itself.
 
     :param index: Non-empty pre-constructed index
     :type index: Index
-    :return: Value from 0 to 1, for the share of found self-references
-    :rtype: float
+    :param sample: Share of vectors to search, defaults to 1
+    :type sample: float
+    :return: Evaluation report with key metrics
+    :rtype: SearchStats
     """
     if len(index) == 0:
         return 0
     if "k" not in kwargs:
         kwargs["k"] = 1
 
-    labels = index.labels
+    keys = index.keys
     if sample != 1:
-        labels = np.random.choice(labels, int(ceil(len(labels) * sample)))
+        keys = np.random.choice(keys, int(ceil(len(keys) * sample)))
 
-    queries = index.get_vectors(labels, index.dtype)
-    matches: Matches = index.search(queries, **kwargs)
-    return matches.recall_first(labels)
+    queries = index.get_vectors(keys, index.dtype)
+    matches: BatchMatches = index.search(queries, **kwargs)
+    count_matches: float = matches.count_matches(keys)
+    return SearchStats(
+        index_size=len(index),
+        count_queries=len(keys),
+        count_matches=count_matches,
+        visited_members=matches.visited_members,
+        computed_distances=matches.computed_distances,
+    )
 
 
 def measure_seconds(f: Callable) -> Tuple[float, Any]:
@@ -131,9 +181,9 @@ def relevance(
 ) -> np.ndarray:
     """Calculate relevance scores. Binary relevance scores
 
-    :param expected: ground-truth labels
+    :param expected: ground-truth keys
     :type expected: np.ndarray
-    :param predicted: predicted labels
+    :param predicted: predicted keys
     :type predicted: np.ndarray
     """
     expected = expected[:k]
@@ -143,7 +193,7 @@ def relevance(
 
 @dataclass
 class Dataset:
-    labels: np.ndarray
+    keys: np.ndarray
     vectors: np.ndarray
     queries: np.ndarray
     neighbors: np.ndarray
@@ -189,7 +239,7 @@ def build(
                 else d.vectors.shape[0]
             )
             d.vectors = d.vectors[:count, :]
-            d.labels = np.arange(count, dtype=Label)
+            d.keys = np.arange(count, dtype=Key)
 
             if queries is not None:
                 d.queries = load_matrix(queries)
@@ -202,7 +252,7 @@ def build(
                     d.neighbors = d.neighbors[:, :k]
             else:
                 assert k is None, "Cant ovveride `k`, will retrieve one neighbor"
-                d.neighbors = np.reshape(d.labels, (count, 1))
+                d.neighbors = np.reshape(d.keys, (count, 1))
 
         else:
             assert ndim is not None
@@ -211,8 +261,8 @@ def build(
 
             d.vectors = random_vectors(count=count, ndim=ndim)
             d.queries = d.vectors
-            d.labels = np.arange(count, dtype=Label)
-            d.neighbors = np.reshape(d.labels, (count, 1))
+            d.keys = np.arange(count, dtype=Key)
+            d.neighbors = np.reshape(d.keys, (count, 1))
 
         return d
 
@@ -276,13 +326,13 @@ def __add__(self, other: TaskResult):
 
 @dataclass
 class AddTask:
-    labels: np.ndarray
+    keys: np.ndarray
     vectors: np.ndarray
 
     def __call__(self, index: Index) -> TaskResult:
         batch_size: int = self.vectors.shape[0]
         old_size: int = len(index)
-        dt, _ = measure_seconds(lambda: index.add(self.labels, self.vectors))
+        dt, _ = measure_seconds(lambda: index.add(self.keys, self.vectors))
 
         assert len(index) == old_size + batch_size
         return TaskResult(
@@ -299,11 +349,11 @@ def count(self):
         return self.vectors.shape[0]
 
     def inplace_shuffle(self):
-        """Rorders the `vectors` and `labels`. Often used for robustness benchmarks."""
+        """Rorders the `vectors` and `keys`. Often used for robustness benchmarks."""
 
         new_order = np.arange(self.count)
         np.random.shuffle(new_order)
-        self.labels = self.labels[new_order]
+        self.keys = self.keys[new_order]
         self.vectors = self.vectors[new_order, :]
 
     def slices(self, batch_size: int) -> List[AddTask]:
@@ -311,7 +361,7 @@ def slices(self, batch_size: int) -> List[AddTask]:
 
         return [
             AddTask(
-                labels=self.labels[start_row : start_row + batch_size],
+                keys=self.keys[start_row : start_row + batch_size],
                 vectors=self.vectors[start_row : start_row + batch_size, :],
             )
             for start_row in range(0, self.count, batch_size)
@@ -334,7 +384,7 @@ def clusters(self, number_of_clusters: int) -> List[AddTask]:
 
         return [
             AddTask(
-                labels=self.labels[rows],
+                keys=self.keys[rows],
                 vectors=self.vectors[rows, :],
             )
             for rows in partitioning.values()
@@ -379,7 +429,7 @@ def for_dataset(
         dataset: Dataset, batch_size: int = 0, clusters: int = 1
     ) -> Evaluation:
         tasks = []
-        add = AddTask(vectors=dataset.vectors, labels=dataset.labels)
+        add = AddTask(vectors=dataset.vectors, keys=dataset.keys)
         search = SearchTask(queries=dataset.queries, neighbors=dataset.neighbors)
 
         if batch_size:
diff --git a/python/usearch/index.py b/python/usearch/index.py
index be72a6b7..c76611d7 100644
--- a/python/usearch/index.py
+++ b/python/usearch/index.py
@@ -7,13 +7,17 @@
 import os
 import math
 from typing import Optional, Union, NamedTuple, List, Iterable
+from dataclasses import dataclass
 
 import numpy as np
 from tqdm import tqdm
 
-from usearch.compiled import Index as _CompiledIndex, IndexMetadata, IndexStats
-from usearch.compiled import SparseIndex as _CompiledSetsIndex
+from usearch.compiled import Index as _CompiledIndex
+from usearch.compiled import Indexes as _CompiledIndexes
+from usearch.compiled import IndexStats as _CompiledIndexStats
 
+from usearch.compiled import index_dense_metadata as _index_dense_metadata
+from usearch.compiled import exact_search as _exact_search
 from usearch.compiled import MetricKind, ScalarKind, MetricSignature
 from usearch.compiled import (
     DEFAULT_CONNECTIVITY,
@@ -30,12 +34,10 @@
     MetricKind.Sorensen,
 )
 
-SparseIndex = _CompiledSetsIndex
+Key = np.uint64
 
-Label = np.uint64
 
-
-def _normalize_dtype(dtype, metric: MetricKind = MetricKind.IP) -> ScalarKind:
+def _normalize_dtype(dtype, metric: MetricKind = MetricKind.Cos) -> ScalarKind:
     if dtype is None or dtype == "":
         return ScalarKind.B1 if metric in MetricKindBitwise else ScalarKind.F32
 
@@ -49,14 +51,16 @@ def _normalize_dtype(dtype, metric: MetricKind = MetricKind.IP) -> ScalarKind:
         "f64": ScalarKind.F64,
         "f32": ScalarKind.F32,
         "f16": ScalarKind.F16,
-        "f8": ScalarKind.F8,
+        "i8": ScalarKind.I8,
         "b1": ScalarKind.B1,
         "b1x8": ScalarKind.B1,
-        np.float64: ScalarKind.F64,
-        np.float32: ScalarKind.F32,
-        np.float16: ScalarKind.F16,
-        np.int8: ScalarKind.F8,
+        "float64": ScalarKind.F64,
+        "float32": ScalarKind.F32,
+        "float16": ScalarKind.F16,
+        "int8": ScalarKind.I8,
     }
+    if isinstance(dtype, np.dtype):
+        dtype = dtype.name
     return _normalize[dtype]
 
 
@@ -65,7 +69,7 @@ def _to_numpy_compatible_dtype(dtype: ScalarKind) -> ScalarKind:
         ScalarKind.F64: ScalarKind.F64,
         ScalarKind.F32: ScalarKind.F32,
         ScalarKind.F16: ScalarKind.F16,
-        ScalarKind.F8: ScalarKind.F16,
+        ScalarKind.I8: ScalarKind.F16,
         ScalarKind.B1: ScalarKind.B1,
     }
     return _normalize[dtype]
@@ -76,7 +80,7 @@ def _to_numpy_dtype(dtype: ScalarKind):
         ScalarKind.F64: np.float64,
         ScalarKind.F32: np.float32,
         ScalarKind.F16: np.float16,
-        ScalarKind.F8: np.float16,
+        ScalarKind.I8: np.float16,
         ScalarKind.B1: np.uint8,
     }
     return _normalize[dtype]
@@ -84,15 +88,19 @@ def _to_numpy_dtype(dtype: ScalarKind):
 
 def _normalize_metric(metric):
     if metric is None:
-        return MetricKind.IP
+        return MetricKind.Cos
 
     if isinstance(metric, str):
         _normalize = {
             "cos": MetricKind.Cos,
+            "cosine": MetricKind.Cos,
             "ip": MetricKind.IP,
+            "dot": MetricKind.IP,
+            "inner_product": MetricKind.IP,
+            "l2sq": MetricKind.L2sq,
             "l2_sq": MetricKind.L2sq,
             "haversine": MetricKind.Haversine,
-            "perason": MetricKind.Pearson,
+            "pearson": MetricKind.Pearson,
             "hamming": MetricKind.Hamming,
             "tanimoto": MetricKind.Tanimoto,
             "sorensen": MetricKind.Sorensen,
@@ -102,59 +110,234 @@ def _normalize_metric(metric):
     return metric
 
 
-class Matches(NamedTuple):
-    labels: np.ndarray
+def _search_in_compiled(
+    *,
+    compiled: Union[_CompiledIndex, _CompiledIndexes],
+    vectors: np.ndarray,
+    k: int,
+    threads: int,
+    exact: bool,
+    log: Union[str, bool],
+    batch_size: int,
+) -> Union[Matches, BatchMatches]:
+    #
+    assert isinstance(vectors, np.ndarray), "Expects a NumPy array"
+    assert vectors.ndim == 1 or vectors.ndim == 2, "Expects a matrix or vector"
+    if vectors.ndim == 1:
+        vectors = vectors.reshape(1, len(vectors))
+    count_vectors = vectors.shape[0]
+
+    def distil_batch(
+        batch_matches: BatchMatches,
+    ) -> Union[BatchMatches, Matches]:
+        return batch_matches[0] if count_vectors == 1 else batch_matches
+
+    if log and batch_size == 0:
+        batch_size = int(math.ceil(count_vectors / 100))
+
+    if batch_size:
+        tasks = [
+            vectors[start_row : start_row + batch_size, :]
+            for start_row in range(0, count_vectors, batch_size)
+        ]
+        tasks_matches = []
+        name = log if isinstance(log, str) else "Search"
+        pbar = tqdm(
+            tasks,
+            desc=name,
+            total=count_vectors,
+            unit="vector",
+            disable=log is False,
+        )
+        for vectors in tasks:
+            tuple_ = compiled.search(
+                vectors,
+                k,
+                exact=exact,
+                threads=threads,
+            )
+            tasks_matches.append(BatchMatches(*tuple_))
+            pbar.update(vectors.shape[0])
+
+        pbar.close()
+        return distil_batch(
+            BatchMatches(
+                keys=np.vstack([m.keys for m in tasks_matches]),
+                distances=np.vstack([m.distances for m in tasks_matches]),
+                counts=np.concatenate([m.counts for m in tasks_matches], axis=None),
+            )
+        )
+
+    else:
+        tuple_ = compiled.search(
+            vectors,
+            k,
+            exact=exact,
+            threads=threads,
+        )
+        return distil_batch(BatchMatches(*tuple_))
+
+
+def _add_to_compiled(
+    *,
+    compiled,
+    keys,
+    vectors,
+    copy: bool,
+    threads: int,
+    log: Union[str, bool],
+    batch_size: int,
+) -> Union[int, np.ndarray]:
+    assert isinstance(vectors, np.ndarray), "Expects a NumPy array"
+    assert vectors.ndim == 1 or vectors.ndim == 2, "Expects a matrix or vector"
+    if vectors.ndim == 1:
+        vectors = vectors.reshape(1, len(vectors))
+
+    # Validate or generate the keys
+    count_vectors = vectors.shape[0]
+    generate_labels = keys is None
+    if generate_labels:
+        start_id = len(compiled)
+        keys = np.arange(start_id, start_id + count_vectors, dtype=Key)
+    else:
+        if not isinstance(keys, Iterable):
+            assert count_vectors == 1, "Each vector must have a key"
+            keys = [keys]
+        keys = np.array(keys).astype(Key)
+
+    assert len(keys) == count_vectors
+
+    # If logging is requested, and batch size is undefined, set it to grow 1% at a time:
+    if log and batch_size == 0:
+        batch_size = int(math.ceil(count_vectors / 100))
+
+    # Split into batches and log progress, if needed
+    if batch_size:
+        keys = [
+            keys[start_row : start_row + batch_size]
+            for start_row in range(0, count_vectors, batch_size)
+        ]
+        vectors = [
+            vectors[start_row : start_row + batch_size, :]
+            for start_row in range(0, count_vectors, batch_size)
+        ]
+        tasks = zip(keys, vectors)
+        name = log if isinstance(log, str) else "Add"
+        pbar = tqdm(
+            tasks,
+            desc=name,
+            total=count_vectors,
+            unit="vector",
+            disable=log is False,
+        )
+        for keys, vectors in tasks:
+            compiled.add(keys, vectors, copy=copy, threads=threads)
+            pbar.update(len(keys))
+
+        pbar.close()
+
+    else:
+        compiled.add(keys, vectors, copy=copy, threads=threads)
+
+    return keys
+
+
+@dataclass
+class Match:
+    """This class contains information about retrieved vector."""
+
+    key: int
+    distance: float
+
+
+@dataclass
+class Matches:
+    """This class contains information about multiple retrieved vectors for single query,
+    i.e it is a set of `Match` instances."""
+
+    keys: np.ndarray
     distances: np.ndarray
-    counts: Union[np.ndarray, int]
 
-    @property
-    def is_multiple(self) -> bool:
-        return isinstance(self.counts, np.ndarray)
+    visited_members: int
+    computed_distances: int
 
-    @property
-    def batch_size(self) -> int:
-        return len(self.counts) if isinstance(self.counts, np.ndarray) else 1
+    def __len__(self) -> int:
+        return len(self.keys)
 
-    @property
-    def total_matches(self) -> int:
-        return np.sum(self.counts)
+    def __getitem__(self, index: int) -> Match:
+        if isinstance(index, int) and index < len(self):
+            return Match(
+                key=self.keys[index],
+                distance=self.distances[index],
+            )
+        else:
+            raise IndexError(f"`index` must be an integer under {len(self)}")
+
+    def to_list(self) -> List[tuple]:
+        """
+        Convert matches to the list of tuples which contain matches' indices and distances to them.
+        """
+
+        return [(int(l), float(d)) for l, d in zip(self.keys, self.distances)]
+
+    def __repr__(self) -> str:
+        return f"usearch.Matches({len(self)})"
 
-    def to_list(self, row: Optional[int] = None) -> Union[List[dict], List[List[dict]]]:
-        if not self.is_multiple:
-            assert row is None, "Exporting a single sequence is only for batch requests"
-            labels = self.labels
-            distances = self.distances
 
-        elif row is None:
-            return [self.to_list(i) for i in range(self.batch_size)]
+@dataclass
+class BatchMatches:
+    """This class contains information about multiple retrieved vectors for multiple queries,
+    i.e it is a set of `Matches` instances."""
 
+    keys: np.ndarray
+    distances: np.ndarray
+    counts: np.ndarray
+
+    visited_members: int
+    computed_distances: int
+
+    def __len__(self) -> int:
+        return len(self.counts)
+
+    def __getitem__(self, index: int) -> Matches:
+        if isinstance(index, int) and index < len(self):
+            return Matches(
+                keys=self.keys[index, : self.counts[index]],
+                distances=self.distances[index, : self.counts[index]],
+                visited_members=self.visited_members // len(self),
+                computed_distances=self.computed_distances // len(self),
+            )
         else:
-            count = self.counts[row]
-            labels = self.labels[row, :count]
-            distances = self.distances[row, :count]
+            raise IndexError(f"`index` must be an integer under {len(self)}")
 
-        return [
-            {"label": int(label), "distance": float(distance)}
-            for label, distance in zip(labels, distances)
-        ]
+    def to_list(self) -> List[List[tuple]]:
+        """Convert the result for each query to the list of tuples with information about its matches."""
+        list_of_matches = [self.__getitem__(row) for row in range(self.__len__())]
+        return [match.to_list() for matches in list_of_matches for match in matches]
 
-    def recall_first(self, expected: np.ndarray) -> float:
-        best_matches = self.labels if not self.is_multiple else self.labels[:, 0]
-        return np.sum(best_matches == expected) / len(expected)
+    def mean_recall(self, expected: np.ndarray, k: Optional[int] = None) -> float:
+        """Measures recall [0, 1] as of `Matches` that contain the corresponding
+        `expected` entry anywhere among results."""
+        return self.count_matches(expected, k=k) / len(expected)
 
-    def recall(self, expected: np.ndarray) -> float:
-        assert len(expected) == self.batch_size
+    def count_matches(self, expected: np.ndarray, k: Optional[int] = None) -> int:
+        """Measures recall [0, len(expected)] as of `Matches` that contain the corresponding
+        `expected` entry anywhere among results.
+        """
+        assert len(expected) == len(self)
         recall = 0
-        for i in range(self.batch_size):
-            recall += expected[i] in self.labels[i]
-        return recall / len(expected)
+        if k is None:
+            k = self.keys.shape[1]
+
+        if k == 1:
+            recall = np.sum(self.keys[:, 0] == expected)
+        else:
+            for i in range(len(self)):
+                recall += expected[i] in self.keys[i, :k]
+        return recall
 
     def __repr__(self) -> str:
-        return (
-            f"usearch.Matches({self.total_matches})"
-            if self.is_multiple
-            else f"usearch.Matches({self.total_matches} across {self.batch_size} queries)"
-        )
+        return f"usearch.BatchMatches({np.sum(self.counts)} across {len(self)} queries)"
 
 
 class CompiledMetric(NamedTuple):
@@ -166,7 +349,7 @@ class CompiledMetric(NamedTuple):
 class Index:
     """Fast JIT-compiled vector-search index for dense equi-dimensional embeddings.
 
-    Vector labels must be integers.
+    Vector keys must be integers.
     Vectors must have the same number of dimensions within the index.
     Supports Inner Product, Cosine Distance, Ln measures
     like the Euclidean metric, as well as automatic downcasting
@@ -175,13 +358,13 @@ class Index:
 
     def __init__(
         self,
+        *,
         ndim: int = 0,
-        metric: Union[str, MetricKind, CompiledMetric] = MetricKind.IP,
+        metric: Union[str, MetricKind, CompiledMetric] = MetricKind.Cos,
         dtype: Optional[Union[str, ScalarKind]] = None,
-        connectivity: int = DEFAULT_CONNECTIVITY,
-        expansion_add: int = DEFAULT_EXPANSION_ADD,
-        expansion_search: int = DEFAULT_EXPANSION_SEARCH,
-        tune: bool = False,
+        connectivity: Optional[int] = None,
+        expansion_add: Optional[int] = None,
+        expansion_search: Optional[int] = None,
         path: Optional[os.PathLike] = None,
         view: bool = False,
     ) -> None:
@@ -189,21 +372,20 @@ def __init__(
 
         :param ndim: Number of vector dimensions
         :type ndim: int
-            Required for some metrics, optional for others.
+            Required for some metrics, pre-set for others.
             Haversine, for example, only applies to 2-dimensional latitude/longitude
             coordinates. Angular (Cos) and Euclidean (L2sq), obviously, apply to
             vectors with arbitrary number of dimensions.
 
-        :param metric: Distance function, defaults to MetricKind.IP
+        :param metric: Distance function, defaults to MetricKind.Cos
         :type metric: Union[MetricKind, Callable, str], optional
             Kind of the distance function, or the Numba `cfunc` JIT-compiled object.
             Possible `MetricKind` values: IP, Cos, L2sq, Haversine, Pearson,
             Hamming, Tanimoto, Sorensen.
-            Not every kind is JIT-able. For Jaccard distance, use `SparseIndex`.
 
         :param dtype: Scalar type for internal vector storage, defaults to None
         :type dtype: Optional[Union[str, ScalarKind]], optional
-            For continuous metrics can be: f16, f32, f64, or f8.
+            For continuous metrics can be: f16, f32, f64, or i8.
             For bitwise metrics it's implementation-defined, and can't change.
             Example: you can use the `f16` index with `f32` vectors in Euclidean space,
             which will be automatically downcasted.
@@ -226,15 +408,23 @@ def __init__(
             nearest neighbors. The original paper calls it "ef".
             Can be changed afterwards, as the `.expansion_search`.
 
-        :param tune: Automatically adjusts hyper-parameters, defaults to False
-        :type tune: bool, optional
-
         :param path: Where to store the index, defaults to None
         :type path: Optional[os.PathLike], optional
         :param view: Are we simply viewing an immutable index, defaults to False
         :type view: bool, optional
         """
 
+        if connectivity is None:
+            connectivity = DEFAULT_CONNECTIVITY
+        if expansion_add is None:
+            expansion_add = DEFAULT_EXPANSION_ADD
+        if expansion_search is None:
+            expansion_search = DEFAULT_EXPANSION_SEARCH
+
+        assert isinstance(connectivity, int), "Expects integer `connectivity`"
+        assert isinstance(expansion_add, int), "Expects integer `expansion_add`"
+        assert isinstance(expansion_search, int), "Expects integer `expansion_search`"
+
         metric = _normalize_metric(metric)
         if isinstance(metric, MetricKind):
             self._metric_kind = metric
@@ -256,13 +446,12 @@ def __init__(
         self._compiled = _CompiledIndex(
             ndim=ndim,
             dtype=dtype,
-            metric=self._metric_kind,
-            metric_pointer=self._metric_pointer,
-            metric_signature=self._metric_signature,
             connectivity=connectivity,
             expansion_add=expansion_add,
             expansion_search=expansion_search,
-            tune=tune,
+            metric_kind=self._metric_kind,
+            metric_pointer=self._metric_pointer,
+            metric_signature=self._metric_signature,
         )
 
         self.path = path
@@ -273,31 +462,30 @@ def __init__(
                 self._compiled.load(path)
 
     @staticmethod
-    def metadata(path: os.PathLike) -> IndexMetadata:
-        return IndexMetadata(path)
+    def metadata(path: os.PathLike) -> Optional[dict]:
+        if not os.path.exists(path):
+            return None
+        try:
+            return _index_dense_metadata(path)
+        except Exception:
+            return None
 
     @staticmethod
-    def restore(path: os.PathLike, view: bool = False) -> Index:
+    def restore(path: os.PathLike, view: bool = False) -> Optional[Index]:
         meta = Index.metadata(path)
-        bits_per_scalar = {
-            ScalarKind.F8: 8,
-            ScalarKind.F16: 16,
-            ScalarKind.F32: 32,
-            ScalarKind.F64: 64,
-            ScalarKind.B1: 1,
-        }[meta.scalar_kind]
-        ndim = meta.bytes_for_vectors * 8 // meta.size // bits_per_scalar
+        if not meta:
+            return None
         return Index(
-            ndim=ndim,
-            connectivity=meta.connectivity,
-            metric=meta.metric,
+            ndim=meta["dimensions"],
+            dtype=meta["kind_scalar"],
+            metric=meta["kind_metric"],
             path=path,
             view=view,
         )
 
     def add(
         self,
-        labels,
+        keys,
         vectors,
         *,
         copy: bool = True,
@@ -307,22 +495,22 @@ def add(
     ) -> Union[int, np.ndarray]:
         """Inserts one or move vectors into the index.
 
-        For maximal performance the `labels` and `vectors`
+        For maximal performance the `keys` and `vectors`
         should conform to the Python's "buffer protocol" spec.
 
         To index a single entry:
-            labels: int, vectors: np.ndarray.
+            keys: int, vectors: np.ndarray.
         To index many entries:
-            labels: np.ndarray, vectors: np.ndarray.
+            keys: np.ndarray, vectors: np.ndarray.
 
         When working with extremely large indexes, you may want to
         pass `copy=False`, if you can guarantee the lifetime of the
         primary vectors store during the process of construction.
 
-        :param labels: Unique identifier(s) for passed vectors, optional
-        :type labels: Buffer
+        :param keys: Unique identifier(s) for passed vectors, optional
+        :type keys: np.ndarray
         :param vectors: Vector or a row-major matrix
-        :type vectors: Buffer
+        :type vectors: np.ndarray
         :param copy: Should the index store a copy of vectors, defaults to True
         :type copy: bool, optional
         :param threads: Optimal number of cores to use, defaults to 0
@@ -331,66 +519,18 @@ def add(
         :type log: Union[str, bool], optional
         :param batch_size: Number of vectors to process at once, defaults to 0
         :type batch_size: int, optional
-        :return: Inserted label or labels
+        :return: Inserted key or keys
         :type: Union[int, np.ndarray]
         """
-        assert isinstance(vectors, np.ndarray), "Expects a NumPy array"
-        assert vectors.ndim == 1 or vectors.ndim == 2, "Expects a matrix or vector"
-        count_vectors = vectors.shape[0] if vectors.ndim == 2 else 1
-        is_multiple = count_vectors > 1
-        if not is_multiple:
-            vectors = vectors.flatten()
-
-        # Validate of generate teh labels
-        generate_labels = labels is None
-        if generate_labels:
-            start_id = len(self._compiled)
-            if is_multiple:
-                labels = np.arange(start_id, start_id + count_vectors, dtype=Label)
-            else:
-                labels = start_id
-        else:
-            if isinstance(labels, np.ndarray):
-                if not is_multiple:
-                    labels = int(labels[0])
-                else:
-                    labels = labels.astype(Label)
-        count_labels = len(labels) if isinstance(labels, Iterable) else 1
-        assert count_labels == count_vectors
-
-        # If logging is requested, and batch size is undefined, set it to grow 1% at a time:
-        if log and batch_size == 0:
-            batch_size = int(math.ceil(count_vectors / 100))
-
-        # Split into batches and log progress, if needed
-        if batch_size:
-            labels = [
-                labels[start_row : start_row + batch_size]
-                for start_row in range(0, count_vectors, batch_size)
-            ]
-            vectors = [
-                vectors[start_row : start_row + batch_size, :]
-                for start_row in range(0, count_vectors, batch_size)
-            ]
-            tasks = zip(labels, vectors)
-            name = log if isinstance(log, str) else "Add"
-            pbar = tqdm(
-                tasks,
-                desc=name,
-                total=count_vectors,
-                unit="Vector",
-                disable=log is False,
-            )
-            for labels, vectors in tasks:
-                self._compiled.add(labels, vectors, copy=copy, threads=threads)
-                pbar.update(len(labels))
-
-            pbar.close()
-
-        else:
-            self._compiled.add(labels, vectors, copy=copy, threads=threads)
-
-        return labels
+        return _add_to_compiled(
+            compiled=self._compiled,
+            keys=keys,
+            vectors=vectors,
+            copy=copy,
+            threads=threads,
+            log=log,
+            batch_size=batch_size,
+        )
 
     def search(
         self,
@@ -401,12 +541,12 @@ def search(
         exact: bool = False,
         log: Union[str, bool] = False,
         batch_size: int = 0,
-    ) -> Matches:
+    ) -> Union[Matches, BatchMatches]:
         """
         Performs approximate nearest neighbors search for one or more queries.
 
         :param vectors: Query vector or vectors.
-        :type vectors: Buffer
+        :type vectors: np.ndarray
         :param k: Upper limit on the number of matches to find, defaults to 10
         :type k: int, optional
         :param threads: Optimal number of cores to use, defaults to 0
@@ -417,60 +557,23 @@ def search(
         :type log: Union[str, bool], optional
         :param batch_size: Number of vectors to process at once, defaults to 0
         :type batch_size: int, optional
-        :return: Approximate matches for one or more queries
-        :rtype: Matches
+        :return: Matches for one or more queries
+        :rtype: Union[Matches, BatchMatches]
         """
 
-        assert isinstance(vectors, np.ndarray), "Expects a NumPy array"
-        assert vectors.ndim == 1 or vectors.ndim == 2, "Expects a matrix or vector"
-        count_vectors = vectors.shape[0] if vectors.ndim == 2 else 1
-
-        if log and batch_size == 0:
-            batch_size = int(math.ceil(count_vectors / 100))
-
-        if batch_size:
-            tasks = [
-                vectors[start_row : start_row + batch_size, :]
-                for start_row in range(0, count_vectors, batch_size)
-            ]
-            tasks_matches = []
-            name = log if isinstance(log, str) else "Search"
-            pbar = tqdm(
-                tasks,
-                desc=name,
-                total=count_vectors,
-                unit="Vector",
-                disable=log is False,
-            )
-            for vectors in tasks:
-                tuple_ = self._compiled.search(
-                    vectors,
-                    k,
-                    exact=exact,
-                    threads=threads,
-                )
-                tasks_matches.append(Matches(*tuple_))
-                pbar.update(vectors.shape[0])
-
-            pbar.close()
-            return Matches(
-                labels=np.vstack([m.labels for m in tasks_matches]),
-                distances=np.vstack([m.distances for m in tasks_matches]),
-                counts=np.concatenate([m.counts for m in tasks_matches], axis=None),
-            )
-
-        else:
-            tuple_ = self._compiled.search(
-                vectors,
-                k,
-                exact=exact,
-                threads=threads,
-            )
-            return Matches(*tuple_)
+        return _search_in_compiled(
+            compiled=self._compiled,
+            vectors=vectors,
+            k=k,
+            exact=exact,
+            threads=threads,
+            log=log,
+            batch_size=batch_size,
+        )
 
     def remove(
         self,
-        labels: Union[int, Iterable[int]],
+        keys: Union[int, Iterable[int]],
         *,
         compact: bool = False,
         threads: int = 0,
@@ -481,8 +584,8 @@ def remove(
         mark some entries deleted, instead of rebuilding a filtered index.
         In other cases, rebuilding - is the recommended approach.
 
-        :param labels: Unique identifier for passed vectors, optional
-        :type labels: Buffer
+        :param keys: Unique identifier for passed vectors, optional
+        :type keys: np.ndarray
         :param compact: Removes links to removed nodes (expensive), defaults to False
         :type compact: bool, optional
         :param threads: Optimal number of cores to use, defaults to 0
@@ -490,7 +593,7 @@ def remove(
         :return: Number of removed entries
         :type: Union[bool, int]
         """
-        return self._compiled.remove(labels, compact=compact, threads=threads)
+        return self._compiled.remove(keys, compact=compact, threads=threads)
 
     def rename(self, label_from: int, label_to: int) -> bool:
         """Relabel existing entry"""
@@ -516,16 +619,16 @@ def specs(self) -> dict:
     def __len__(self) -> int:
         return self._compiled.__len__()
 
-    def __delitem__(self, label: int) -> bool:
-        raise self.remove(label)
+    def __delitem__(self, key: int) -> bool:
+        raise self.remove(key)
 
-    def __contains__(self, label: int) -> bool:
-        return self._compiled.__contains__(label)
+    def __contains__(self, key: int) -> bool:
+        return self._compiled.__contains__(key)
 
-    def __getitem__(self, label: int) -> np.ndarray:
+    def __getitem__(self, key: int) -> np.ndarray:
         dtype = self.dtype
         get_dtype = _to_numpy_compatible_dtype(dtype)
-        vector = self._compiled.__getitem__(label, get_dtype)
+        vector = self._compiled.__getitem__(key, get_dtype)
         view_dtype = _to_numpy_dtype(dtype)
         return None if vector is None else vector.view(view_dtype)
 
@@ -545,6 +648,28 @@ def ndim(self) -> int:
     def metric(self) -> Union[MetricKind, CompiledMetric]:
         return self._metric_jit if self._metric_jit else self._metric_kind
 
+    @metric.setter
+    def metric(self, metric: Union[str, MetricKind, CompiledMetric]):
+        metric = _normalize_metric(metric)
+        if isinstance(metric, MetricKind):
+            metric_kind = metric
+            metric_pointer = 0
+            metric_signature = MetricSignature.ArrayArraySize
+        elif isinstance(metric, CompiledMetric):
+            metric_kind = metric.kind
+            metric_pointer = metric.pointer
+            metric_signature = metric.signature
+        else:
+            raise ValueError(
+                "The `metric` must be a `CompiledMetric` or a `MetricKind`"
+            )
+
+        return self._compiled.change_metric(
+            metric_kind=metric_kind,
+            metric_pointer=metric_pointer,
+            metric_signature=metric_signature,
+        )
+
     @property
     def dtype(self) -> ScalarKind:
         return self._compiled.dtype
@@ -581,25 +706,27 @@ def save(self, path: Optional[os.PathLike] = None):
         path = path if path else self.path
         if path is None:
             raise Exception("Define `path` argument")
-        self._compiled.save(path)
+        self._compiled.save(os.fspath(path))
 
     def load(self, path: Optional[os.PathLike] = None):
         path = path if path else self.path
         if path is None:
             raise Exception("Define `path` argument")
-        self._compiled.load(path)
+        self._compiled.load(os.fspath(path))
 
     def view(self, path: Optional[os.PathLike] = None):
         path = path if path else self.path
         if path is None:
             raise Exception("Define `path` argument")
-        self._compiled.view(path)
+        self._compiled.view(os.fspath(path))
 
     def clear(self):
+        """Erases all the vectors from the index, preserving the space for future insertions."""
         self._compiled.clear()
 
-    def close(self):
-        self._compiled.close()
+    def reset(self):
+        """Erases all members from index, closing files, and returning RAM to OS."""
+        self._compiled.reset()
 
     def copy(self) -> Index:
         result = Index(
@@ -626,7 +753,7 @@ def join(self, other: Index, max_proposals: int = 0, exact: bool = False) -> dic
         :type max_proposals: int, optional
         :param exact: Controls if underlying `search` should be exact, defaults to False
         :type exact: bool, optional
-        :return: Mapping from labels of `self` to labels of `other`
+        :return: Mapping from keys of `self` to keys of `other`
         :rtype: dict
         """
         return self._compiled.join(
@@ -635,49 +762,71 @@ def join(self, other: Index, max_proposals: int = 0, exact: bool = False) -> dic
             exact=exact,
         )
 
-    def get_labels(self, offset: int = 0, limit: int = 0) -> np.ndarray:
+    def get_keys(self, offset: int = 0, limit: int = 0) -> np.ndarray:
         if limit == 0:
             limit = 2**63 - 1
-        return self._compiled.get_labels(offset, limit)
+        return self._compiled.get_keys(offset, limit)
 
     @property
-    def labels(self) -> np.ndarray:
-        """Retrieves the labels of all vectors present in `self`
+    def keys(self) -> np.ndarray:
+        """Retrieves the keys of all vectors present in `self`
 
-        :return: Array of labels
+        :return: Array of keys
         :rtype: np.ndarray
         """
-        return self._compiled.labels
+        return self._compiled.keys
 
     def get_vectors(
         self,
-        labels: np.ndarray,
+        keys: np.ndarray,
         dtype: ScalarKind = ScalarKind.F32,
     ) -> np.ndarray:
-        """Retrieves vectors associated with given `labels`
+        """Retrieves vectors associated with given `keys`
 
         :return: Matrix of vectors (row-major)
         :rtype: np.ndarray
         """
         dtype = _normalize_dtype(dtype, self._metric_kind)
         get_dtype = _to_numpy_compatible_dtype(dtype)
-        vectors = np.vstack([self._compiled.__getitem__(l, get_dtype) for l in labels])
+        vectors = np.vstack([self._compiled.__getitem__(l, get_dtype) for l in keys])
         view_dtype = _to_numpy_dtype(dtype)
         return vectors.view(view_dtype)
 
     @property
     def vectors(self) -> np.ndarray:
-        return self.get_vectors(self.labels, self.dtype)
+        return self.get_vectors(self.keys, self.dtype)
 
     @property
     def max_level(self) -> int:
         return self._compiled.max_level
 
     @property
-    def levels_stats(self) -> IndexStats:
+    def levels_stats(self) -> _CompiledIndexStats:
+        """Get the accumulated statistics for the entire multi-level graph.
+
+        :return: Statistics for the entire multi-level graph.
+        :rtype: _CompiledIndexStats
+
+        Statistics:
+            - ``nodes`` (int): The number of nodes in that level.
+            - ``edges`` (int): The number of edges in that level.
+            - ``max_edges`` (int): The maximum possible number of edges in that level.
+            - ``allocated_bytes`` (int): The amount of allocated memory for that level.
+        """
         return self._compiled.levels_stats
 
-    def level_stats(self, level: int) -> IndexStats:
+    def level_stats(self, level: int) -> _CompiledIndexStats:
+        """Get statistics for one level of the index - one graph.
+
+        :return: Statistics for one level of the index - one graph.
+        :rtype: _CompiledIndexStats
+
+        Statistics:
+            - ``nodes`` (int): The number of nodes in that level.
+            - ``edges`` (int): The number of edges in that level.
+            - ``max_edges`` (int): The maximum possible number of edges in that level.
+            - ``allocated_bytes`` (int): The amount of allocated memory for that level.
+        """
         return self._compiled.level_stats(level)
 
     def __repr__(self) -> str:
@@ -711,3 +860,146 @@ def _repr_pretty_(self) -> str:
                 *level_stats,
             ]
         )
+
+
+class Indexes:
+    def __init__(
+        self,
+        indexes: Iterable[Index] = [],
+        paths: Iterable[os.PathLike] = [],
+        view: bool = False,
+        threads: int = 0,
+    ) -> None:
+        self._compiled = _CompiledIndexes()
+        for index in indexes:
+            self._compiled.add(index._compiled)
+        self._compiled.add_paths(paths, view=view, threads=threads)
+
+    def add(self, index: Index):
+        self._compiled.add(index._compiled)
+
+    def __len__(self) -> int:
+        return self._compiled.__len__()
+
+    def search(
+        self,
+        vectors,
+        k: int = 10,
+        *,
+        threads: int = 0,
+        exact: bool = False,
+    ):
+        return _search_in_compiled(
+            compiled=self._compiled,
+            vectors=vectors,
+            k=k,
+            exact=exact,
+            threads=threads,
+            log=False,
+            batch_size=None,
+        )
+
+
+def search(
+    dataset: np.ndarray,
+    query: np.ndarray,
+    k: int = 10,
+    metric: Union[str, MetricKind, CompiledMetric] = MetricKind.Cos,
+    *,
+    exact: bool = False,
+    threads: int = 0,
+    log: Union[str, bool] = False,
+    batch_size: int = 0,
+) -> Union[Matches, BatchMatches]:
+    """Shortcut for search, that can avoid index construction. Particularly useful for
+    tiny datasets, where brute-force exact search works fast enough.
+
+    :param dataset: Row-major matrix.
+    :type dataset: np.ndarray
+    :param query: Query vector or vectors (also row-major), to find in `dataset`.
+    :type query: np.ndarray
+
+    :param k: Upper limit on the number of matches to find, defaults to 10
+    :type k: int, optional
+
+    :param metric: Distance function, defaults to MetricKind.Cos
+    :type metric: Union[MetricKind, Callable, str], optional
+        Kind of the distance function, or the Numba `cfunc` JIT-compiled object.
+        Possible `MetricKind` values: IP, Cos, L2sq, Haversine, Pearson,
+        Hamming, Tanimoto, Sorensen.
+
+    :param threads: Optimal number of cores to use, defaults to 0
+    :type threads: int, optional
+    :param exact: Perform exhaustive linear-time exact search, defaults to False
+    :type exact: bool, optional
+    :param log: Whether to print the progress bar, default to False
+    :type log: Union[str, bool], optional
+    :param batch_size: Number of vectors to process at once, defaults to 0
+    :type batch_size: int, optional
+
+    :return: Matches for one or more queries
+    :rtype: Union[Matches, BatchMatches]
+    """
+    assert dataset.ndim == 2, "Dataset must be a matrix, with a vector in each row"
+
+    if not exact:
+        index = Index(
+            dataset.shape[1],
+            metric=metric,
+            dtype=dataset.dtype,
+        )
+        index.add(
+            None,
+            dataset,
+            threads=threads,
+            log=log,
+            batch_size=batch_size,
+        )
+        return index.search(
+            query,
+            k,
+            threads=threads,
+            log=log,
+            batch_size=batch_size,
+        )
+
+    metric = _normalize_metric(metric)
+    if isinstance(metric, MetricKind):
+        metric_kind = metric
+        metric_pointer = 0
+        metric_signature = MetricSignature.ArrayArraySize
+    elif isinstance(metric, CompiledMetric):
+        metric_kind = metric.kind
+        metric_pointer = metric.pointer
+        metric_signature = metric.signature
+    else:
+        raise ValueError("The `metric` must be a `CompiledMetric` or a `MetricKind`")
+
+    class WrappedDataset:
+        def __init__(self) -> None:
+            pass
+
+        def search(self, query, k, **kwargs):
+            kwargs.pop("exact")
+            kwargs.update(
+                dict(
+                    metric_kind=metric_kind,
+                    metric_pointer=metric_pointer,
+                    metric_signature=metric_signature,
+                )
+            )
+            assert dataset.shape[1] == query.shape[1], "Number of dimensions differs"
+            if dataset.dtype != query.dtype:
+                query = query.astype(dataset.dtype)
+
+            return _exact_search(dataset, query, k, **kwargs)
+
+    return _search_in_compiled(
+        compiled=WrappedDataset(),
+        vectors=query,
+        k=k,
+        threads=threads,
+        exact=True,
+        log=log,
+        batch_size=batch_size,
+    )
diff --git a/python/usearch/io.py b/python/usearch/io.py
index a0bd14a9..6cfd0cb5 100644
--- a/python/usearch/io.py
+++ b/python/usearch/io.py
@@ -1,11 +1,48 @@
+import os
 import struct
+import typing
 
 import numpy as np
 
 
+def numpy_scalar_size(dtype) -> int:
+    return {
+        np.float64: 8,
+        np.int64: 8,
+        np.uint64: 8,
+        np.float32: 4,
+        np.int32: 4,
+        np.uint32: 4,
+        np.float16: 2,
+        np.int16: 2,
+        np.uint16: 2,
+        np.int8: 1,
+        np.uint8: 1,
+    }[dtype]
+
+
+def guess_numpy_dtype_from_filename(filename) -> typing.Optional[type]:
+    if filename.endswith(".fbin"):
+        return np.float32
+    elif filename.endswith(".dbin"):
+        return np.float64
+    elif filename.endswith(".hbin"):
+        return np.float16
+    elif filename.endswith(".ibin"):
+        return np.int32
+    elif filename.endswith(".bbin"):
+        return np.uint8
+    else:
+        return None
+
+
 def load_matrix(
-    filename: str, start_row: int = 0, count_rows: int = None, view: bool = False
-) -> np.ndarray:
+    filename: str,
+    start_row: int = 0,
+    count_rows: int = None,
+    view: bool = False,
+    dtype: typing.Optional[type] = None,
+) -> typing.Optional[np.ndarray]:
     """Read *.ibin, *.bbib, *.hbin, *.fbin, *.dbin files with matrices.
 
     :param filename: path to the matrix file
@@ -16,25 +53,14 @@ def load_matrix(
     :return: parsed matrix
     :rtype: numpy.ndarray
     """
-    dtype = np.float32
-    scalar_size = 4
-    if filename.endswith(".fbin"):
-        dtype = np.float32
-        scalar_size = 4
-    elif filename.endswith(".dbin"):
-        dtype = np.float64
-        scalar_size = 8
-    elif filename.endswith(".hbin"):
-        dtype = np.float16
-        scalar_size = 2
-    elif filename.endswith(".ibin"):
-        dtype = np.int32
-        scalar_size = 4
-    elif filename.endswith(".bbin"):
-        dtype = np.uint8
-        scalar_size = 1
-    else:
-        raise Exception("Unknown file type")
+    if dtype is None:
+        dtype = guess_numpy_dtype_from_filename(filename)
+        if dtype is None:
+            raise Exception("Unknown file type")
+    scalar_size = numpy_scalar_size(dtype)
+
+    if not os.path.exists(filename):
+        return None
 
     with open(filename, "rb") as f:
         rows, cols = np.fromfile(f, count=2, dtype=np.int32)
@@ -43,11 +69,18 @@ def load_matrix(
 
         if view:
             return np.memmap(
-                f, dtype=dtype, mode="r", offset=8 + row_offset, shape=(rows, cols)
+                f,
+                dtype=dtype,
+                mode="r",
+                offset=8 + row_offset,
+                shape=(rows, cols),
             )
         else:
             return np.fromfile(
-                f, count=rows * cols, dtype=dtype, offset=row_offset
+                f,
+                count=rows * cols,
+                dtype=dtype,
+                offset=row_offset,
             ).reshape(rows, cols)
 
 
@@ -59,7 +92,6 @@ def save_matrix(vectors: np.ndarray, filename: str):
     :param filename: path to the matrix file
     :type filename: str
     """
-    dtype = np.float32
     if filename.endswith(".fbin"):
         dtype = np.float32
     elif filename.endswith(".dbin"):
@@ -71,7 +103,7 @@ def save_matrix(vectors: np.ndarray, filename: str):
     elif filename.endswith(".bbin"):
         dtype = np.uint8
     else:
-        raise Exception("Unknown file type")
+        dtype = vectors.dtype
 
     assert len(vectors.shape) == 2, "Input array must have 2 dimensions"
     with open(filename, "wb") as f:
diff --git a/python/usearch/numba.py b/python/usearch/numba.py
index 91b5e753..5885501d 100644
--- a/python/usearch/numba.py
+++ b/python/usearch/numba.py
@@ -44,7 +44,7 @@ def jit(
     )
 
     numba_supported_types = (
-        ScalarKind.F8,
+        ScalarKind.I8,
         # Half-precision is still unsupported
         # https://github.com/numba/numba/issues/4402
         # ScalarKind.F16: np.float16,
@@ -55,7 +55,7 @@ def jit(
         return metric
 
     scalar_kind_to_accumulator_type = {
-        ScalarKind.F8: types.int32,
+        ScalarKind.I8: types.int32,
         ScalarKind.F16: types.float16,
         ScalarKind.F32: types.float32,
         ScalarKind.F64: types.float64,
@@ -98,7 +98,7 @@ def numba_l2sq(a, b):
         return types.float32(ab_delta_sq)
 
     scalar_kind_to_signature = {
-        ScalarKind.F8: signature_i8args,
+        ScalarKind.I8: signature_i8args,
         ScalarKind.F16: signature_f16args,
         ScalarKind.F32: signature_f32args,
         ScalarKind.F64: signature_f64args,
@@ -110,7 +110,7 @@ def numba_l2sq(a, b):
         MetricKind.L2sq: numba_l2sq,
     }
 
-    if dtype == ScalarKind.F8 and metric == MetricKind.IP:
+    if dtype == ScalarKind.I8 and metric == MetricKind.IP:
         metric = MetricKind.Cos
 
     pointer = cfunc(scalar_kind_to_signature[dtype])(metric_kind_to_function[metric])
diff --git a/python/usearch/server.py b/python/usearch/server.py
index 00b089c8..5f53b90e 100644
--- a/python/usearch/server.py
+++ b/python/usearch/server.py
@@ -7,13 +7,13 @@
 from typing import List
 
 from ucall.rich_posix import Server
-from usearch.index import Index, Matches, Label
+from usearch.index import Index, Matches, Key
 
 
 def _ascii_to_vector(string: str) -> np.ndarray:
     """
     WARNING: A dirty performance hack!
-    Assuming the `f8` vectors in our implementations are just integers,
+    Assuming the `i8` vectors in our implementations are just integers,
     and generally contain scalars in the [0, 100] range, we can transmit
     them as JSON-embedded strings. The only symbols we must avoid are
     the double-quote '"' (code 22) and backslash '\' (code 60).
@@ -59,15 +59,15 @@ def connectivity() -> int:
         return index.connectivity()
 
     @server
-    def add_one(label: int, vector: np.ndarray):
-        print("adding", label, vector)
-        labels = np.array([label], dtype=Label)
+    def add_one(key: int, vector: np.ndarray):
+        print("adding", key, vector)
+        keys = np.array([key], dtype=Key)
         vectors = vector.flatten().reshape(vector.shape[0], 1)
-        index.add(labels, vectors)
+        index.add(keys, vectors)
 
     @server
-    def add_many(labels: np.ndarray, vectors: np.ndarray):
-        index.add(labels, vectors, threads=threads)
+    def add_many(keys: np.ndarray, vectors: np.ndarray):
+        index.add(keys, vectors, threads=threads)
 
     @server
     def search_one(vector: np.ndarray, count: int) -> List[dict]:
@@ -82,8 +82,8 @@ def search_many(vectors: np.ndarray, count: int) -> List[List[dict]]:
         return results.to_list()
 
     @server
-    def add_ascii(label: int, string: str):
-        return add_one(label, _ascii_to_vector(string))
+    def add_ascii(key: int, string: str):
+        return add_one(key, _ascii_to_vector(string))
 
     @server
     def search_ascii(string: str, count: int):
diff --git a/rust/lib.cpp b/rust/lib.cpp
index 168d47b1..1afd67e8 100644
--- a/rust/lib.cpp
+++ b/rust/lib.cpp
@@ -7,46 +7,45 @@ using namespace unum;
 using index_t = typename Index::index_t;
 using add_result_t = typename index_t::add_result_t;
 using search_result_t = typename index_t::search_result_t;
-using serialization_result_t = typename index_t::serialization_result_t;
 
 Index::Index(std::unique_ptr<index_t> index) : index_(std::move(index)) {}
 
-void Index::add_in_thread(label_t label, rust::Slice<float const> vector, size_t thread) const {
-    add_config_t config;
+void Index::add_in_thread(key_t key, rust::Slice<float const> vector, size_t thread) const {
+    index_update_config_t config;
     config.thread = thread;
-    index_->add(label, vector.data(), config).error.raise();
+    config.expansion = index_->expansion_add();
+    index_->add(key, vector.data(), config).error.raise();
 }
 
 Matches Index::search_in_thread(rust::Slice<float const> vector, size_t count, size_t thread) const {
     Matches matches;
-    matches.labels.reserve(count);
+    matches.keys.reserve(count);
     matches.distances.reserve(count);
     for (size_t i = 0; i != count; ++i)
-        matches.labels.push_back(0), matches.distances.push_back(0);
-    search_config_t config;
+        matches.keys.push_back(0), matches.distances.push_back(0);
+    index_search_config_t config;
     config.thread = thread;
+    config.expansion = index_->expansion_search();
     search_result_t result = index_->search(vector.data(), count, config);
     result.error.raise();
-    matches.count = result.dump_to(matches.labels.data(), matches.distances.data());
-    matches.labels.truncate(matches.count);
+    matches.count = result.dump_to(matches.keys.data(), matches.distances.data());
+    matches.keys.truncate(matches.count);
     matches.distances.truncate(matches.count);
     return matches;
 }
 
-void Index::add(label_t label, rust::Slice<float const> vector) const {
-    index_->add(label, vector.data()).error.raise();
-}
+void Index::add(key_t key, rust::Slice<float const> vector) const { index_->add(key, vector.data()).error.raise(); }
 
 Matches Index::search(rust::Slice<float const> vector, size_t count) const {
     Matches matches;
-    matches.labels.reserve(count);
+    matches.keys.reserve(count);
     matches.distances.reserve(count);
     for (size_t i = 0; i != count; ++i)
-        matches.labels.push_back(0), matches.distances.push_back(0);
+        matches.keys.push_back(0), matches.distances.push_back(0);
     search_result_t result = index_->search(vector.data(), count);
     result.error.raise();
-    matches.count = result.dump_to(matches.labels.data(), matches.distances.data());
-    matches.labels.truncate(matches.count);
+    matches.count = result.dump_to(matches.keys.data(), matches.distances.data());
+    matches.keys.truncate(matches.count);
     matches.distances.truncate(matches.count);
     return matches;
 }
@@ -62,7 +61,7 @@ void Index::save(rust::Str path) const { index_->save(std::string(path).c_str())
 void Index::load(rust::Str path) const { index_->load(std::string(path).c_str()); }
 void Index::view(rust::Str path) const { index_->view(std::string(path).c_str()); }
 
-scalar_kind_t accuracy(rust::Str quant) { return scalar_kind_from_name(quant.data(), quant.size()); }
+scalar_kind_t quantization(rust::Str quant) { return scalar_kind_from_name(quant.data(), quant.size()); }
 
 std::unique_ptr<Index> wrap(index_t&& index) {
     std::unique_ptr<index_t> punned_ptr;
@@ -72,12 +71,6 @@ std::unique_ptr<Index> wrap(index_t&& index) {
     return result;
 }
 
-index_config_t config(size_t connectivity) {
-    index_config_t result;
-    result.connectivity = connectivity ? connectivity : default_connectivity();
-    return result;
-}
-
 metric_kind_t rust_to_cpp_metric(MetricKind value) {
     switch (value) {
     case MetricKind::IP: return metric_kind_t::ip_k;
@@ -94,7 +87,7 @@ metric_kind_t rust_to_cpp_metric(MetricKind value) {
 
 scalar_kind_t rust_to_cpp_scalar(ScalarKind value) {
     switch (value) {
-    case ScalarKind::F8: return scalar_kind_t::f8_k;
+    case ScalarKind::I8: return scalar_kind_t::i8_k;
     case ScalarKind::F16: return scalar_kind_t::f16_k;
     case ScalarKind::F32: return scalar_kind_t::f32_k;
     case ScalarKind::F64: return scalar_kind_t::f64_k;
@@ -104,7 +97,9 @@ scalar_kind_t rust_to_cpp_scalar(ScalarKind value) {
 }
 
 std::unique_ptr<Index> new_index(IndexOptions const& options) {
-    return wrap(index_t::make(options.dimensions, rust_to_cpp_metric(options.metric), config(options.connectivity),
-                              rust_to_cpp_scalar(options.quantization), options.expansion_add,
-                              options.expansion_search));
+    metric_kind_t metric_kind = rust_to_cpp_metric(options.metric);
+    scalar_kind_t scalar_kind = rust_to_cpp_scalar(options.quantization);
+    metric_punned_t metric(options.dimensions, metric_kind, scalar_kind);
+    index_dense_config_t config(options.connectivity, options.expansion_add, options.expansion_search);
+    return wrap(index_t::make(metric, config));
 }
diff --git a/rust/lib.hpp b/rust/lib.hpp
index 543107d8..42192b7c 100644
--- a/rust/lib.hpp
+++ b/rust/lib.hpp
@@ -3,27 +3,26 @@
 
 #include <memory> // `std::shared_ptr`
 
-#include <usearch/index_punned_dense.hpp>
+#include <usearch/index_dense.hpp>
 
 struct Matches;
 struct IndexOptions;
 
 class Index {
   public:
-    using metric_t = unum::usearch::index_punned_dense_metric_t;
-    using distance_t = unum::usearch::punned_distance_t;
-    using index_t = unum::usearch::punned_small_t;
-    using add_result_t = typename index_t::add_result_t;
-    using search_result_t = typename index_t::search_result_t;
-    using label_t = typename index_t::label_t;
-    using id_t = typename index_t::id_t;
+    using metric_t = unum::usearch::metric_punned_t;
+    using distance_t = unum::usearch::distance_punned_t;
+    using index_dense_t = unum::usearch::index_dense_t;
+    using add_result_t = typename index_dense_t::add_result_t;
+    using search_result_t = typename index_dense_t::search_result_t;
+    using key_t = typename index_dense_t::key_t;
 
-    Index(std::unique_ptr<index_t> index);
+    Index(std::unique_ptr<index_dense_t> index);
 
     void reserve(size_t) const;
 
-    void add(label_t label, rust::Slice<float const> vector) const;
-    void add_in_thread(label_t label, rust::Slice<float const> vector, size_t thread) const;
+    void add(key_t key, rust::Slice<float const> vector) const;
+    void add_in_thread(key_t key, rust::Slice<float const> vector, size_t thread) const;
 
     Matches search(rust::Slice<float const> vector, size_t count) const;
     Matches search_in_thread(rust::Slice<float const> vector, size_t count, size_t thread) const;
@@ -38,7 +37,7 @@ class Index {
     void view(rust::Str path) const;
 
   private:
-    std::unique_ptr<index_t> index_;
+    std::unique_ptr<index_dense_t> index_;
 };
 
 std::unique_ptr<Index> new_index(IndexOptions const& options);
diff --git a/rust/lib.rs b/rust/lib.rs
index 17da20b1..46aeabb7 100644
--- a/rust/lib.rs
+++ b/rust/lib.rs
@@ -4,7 +4,7 @@ pub mod ffi {
     // Shared structs with fields visible to both languages.
     struct Matches {
         count: usize,
-        labels: Vec<u64>,
+        keys: Vec<u64>,
         distances: Vec<f32>,
     }
 
@@ -23,7 +23,7 @@ pub mod ffi {
         F64,
         F32,
         F16,
-        F8,
+        I8,
         B1,
     }
 
@@ -51,7 +51,7 @@ pub mod ffi {
         pub fn size(self: &Index) -> usize;
         pub fn capacity(self: &Index) -> usize;
 
-        pub fn add(self: &Index, label: u64, vector: &[f32]) -> Result<()>;
+        pub fn add(self: &Index, key: u64, vector: &[f32]) -> Result<()>;
         pub fn search(self: &Index, query: &[f32], count: usize) -> Result<Matches>;
 
         pub fn save(self: &Index, path: &str) -> Result<()>;
diff --git a/setup.py b/setup.py
index e6748cb7..7215d0e4 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,8 @@
 
 if sys.platform == "linux":
     compile_args.append("-std=c++11")
-    compile_args.append("-O3")
+    compile_args.append("-O3")  # Maximize performance
+    compile_args.append("-g")  # Simplify debugging
     compile_args.append("-Wno-unknown-pragmas")
 
     macros_args.append(("USEARCH_USE_OPENMP", "1"))
@@ -26,7 +27,8 @@
     # https://github.com/unum-cloud/usearch/actions/runs/4975434891/jobs/8902603392
     compile_args.append("-mmacosx-version-min=10.15")
     compile_args.append("-std=c++11")
-    compile_args.append("-O3")
+    compile_args.append("-O3")  # Maximize performance
+    compile_args.append("-g")  # Simplify debugging
     compile_args.append("-Wno-unknown-pragmas")
 
     # Linking OpenMP requires additional preparion in CIBuildWheel
@@ -63,6 +65,7 @@
     packages=["usearch"],
     package_dir={"usearch": "python/usearch"},
     description="Smaller & Faster Single-File Vector Search Engine from Unum",
+    author="Ash Vardanian",
     long_description=long_description,
     long_description_content_type="text/markdown",
     license="Apache-2.0",
diff --git a/simsimd b/simsimd
index 74760c7d..de2cb75b 160000
--- a/simsimd
+++ b/simsimd
@@ -1,1 +1,1 @@
-Subproject commit 74760c7d9a018bb6c959db75e7898186d79a9faa
+Subproject commit de2cb75b9e9e3389d5e1e51fd9f8ed151f3c17cf
diff --git a/swift/Index+Sugar.swift b/swift/Index+Sugar.swift
index 71a99180..0b23c774 100644
--- a/swift/Index+Sugar.swift
+++ b/swift/Index+Sugar.swift
@@ -2,98 +2,150 @@
 //  Index+Sugar.swift
 //
 //
-//  Created by Ashot Vardanian on 5/11/23.
+//  Created by Ash Vardanian on 5/11/23.
 //
 
 @available(iOS 13, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
 extension USearchIndex {
-    public typealias Label = USearchLabel
+    public typealias Key = USearchKey
     public typealias Metric = USearchMetric
     public typealias Scalar = USearchScalar
-    
+
     /// Adds a labeled vector to the index.
-    /// - Parameter label: Unique identifer for that object.
+    /// - Parameter key: Unique identifer for that object.
     /// - Parameter vector: Single-precision vector.
     /// - Throws: If runs out of memory.
-    public func add(label: USearchLabel, vector: ArraySlice<Float32>) {
+    public func add(key: USearchKey, vector: ArraySlice<Float32>) {
         vector.withContiguousStorageIfAvailable {
-            addSingle(label: label, vector: $0.baseAddress!)
+            addSingle(key: key, vector: $0.baseAddress!)
         }
     }
 
-    
+    /// Adds a labeled vector to the index.
+    /// - Parameter key: Unique identifer for that object.
+    /// - Parameter vector: Single-precision vector.
+    /// - Throws: If runs out of memory.
+    public func add(key: USearchKey, vector: Array<Float32>) {
+        add(key: key, vector: vector[...])
+    }
+
     /// Approximate nearest neighbors search.
     /// - Parameter vector: Single-precision query vector.
     /// - Parameter count: Upper limit on the number of matches to retrieve.
     /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
     /// - Throws: If runs out of memory.
-    public func search(vector: ArraySlice<Float32>, count: Int) -> ([Label], [Float]) {
-        var matches: [Label] = Array(repeating: 0, count: count)
+    public func search(vector: ArraySlice<Float32>, count: Int) -> ([Key], [Float]) {
+        var matches: [Key] = Array(repeating: 0, count: count)
         var distances: [Float] = Array(repeating: 0, count: count)
         let results = vector.withContiguousStorageIfAvailable {
-            searchSingle(vector: $0.baseAddress!, count: CUnsignedInt(count), labels: &matches, distances: &distances)
+            searchSingle(vector: $0.baseAddress!, count: CUnsignedInt(count), keys: &matches, distances: &distances)
         }
         matches.removeLast(count - Int(results!))
         distances.removeLast(count - Int(results!))
         return (matches, distances)
     }
 
+    /// Approximate nearest neighbors search.
+    /// - Parameter vector: Single-precision query vector.
+    /// - Parameter count: Upper limit on the number of matches to retrieve.
+    /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
+    /// - Throws: If runs out of memory.
+    public func search(vector: Array<Float32>, count: Int) -> ([Key], [Float]) {
+        return search(vector: vector[...], count: count)
+    }
+
     /// Adds a labeled vector to the index.
-    /// - Parameter label: Unique identifer for that object.
+    /// - Parameter key: Unique identifer for that object.
     /// - Parameter vector: Double-precision vector.
     /// - Throws: If runs out of memory.
-    public func add(label: Label, vector: ArraySlice<Float64>) {
+    public func add(key: Key, vector: ArraySlice<Float64>) {
         vector.withContiguousStorageIfAvailable {
-            addDouble(label: label, vector: $0.baseAddress!)
+            addDouble(key: key, vector: $0.baseAddress!)
         }
     }
-    
+
+    /// Adds a labeled vector to the index.
+    /// - Parameter key: Unique identifer for that object.
+    /// - Parameter vector: Double-precision vector.
+    /// - Throws: If runs out of memory.
+    public func add(key: Key, vector: Array<Float64>) {
+        add(key: key, vector: vector[...])
+    }
+
     /// Approximate nearest neighbors search.
     /// - Parameter vector: Double-precision query vector.
     /// - Parameter count: Upper limit on the number of matches to retrieve.
     /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
     /// - Throws: If runs out of memory.
-    public func search(vector: ArraySlice<Float64>, count: Int) -> ([Label], [Float]) {
-        var matches: [Label] = Array(repeating: 0, count: count)
+    public func search(vector: ArraySlice<Float64>, count: Int) -> ([Key], [Float]) {
+        var matches: [Key] = Array(repeating: 0, count: count)
         var distances: [Float] = Array(repeating: 0, count: count)
         let results = vector.withContiguousStorageIfAvailable {
-            searchDouble(vector: $0.baseAddress!, count: CUnsignedInt(count), labels: &matches, distances: &distances)
+            searchDouble(vector: $0.baseAddress!, count: CUnsignedInt(count), keys: &matches, distances: &distances)
         }
         matches.removeLast(count - Int(results!))
         distances.removeLast(count - Int(results!))
         return (matches, distances)
     }
 
+    /// Approximate nearest neighbors search.
+    /// - Parameter vector: Double-precision query vector.
+    /// - Parameter count: Upper limit on the number of matches to retrieve.
+    /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
+    /// - Throws: If runs out of memory.
+    public func search(vector: Array<Float64>, count: Int) -> ([Key], [Float]) {
+        search(vector: vector[...], count: count)
+    }
+
     #if arch(arm64)
 
         /// Adds a labeled vector to the index.
-        /// - Parameter label: Unique identifer for that object.
+        /// - Parameter key: Unique identifer for that object.
         /// - Parameter vector: Half-precision vector.
         /// - Throws: If runs out of memory.
         @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
-        public func add(label: Label, vector: ArraySlice<Float16>) {
+        public func add(key: Key, vector: ArraySlice<Float16>) {
             vector.withContiguousStorageIfAvailable { buffer in
-                addHalf(label: label, vector: buffer.baseAddress!)
+                addHalf(key: key, vector: buffer.baseAddress!)
             }
         }
 
+        /// Adds a labeled vector to the index.
+        /// - Parameter key: Unique identifer for that object.
+        /// - Parameter vector: Half-precision vector.
+        /// - Throws: If runs out of memory.
+        @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
+        public func add(key: Key, vector: Array<Float16>) {
+            add(key: key, vector: vector[...])
+        }
+
         /// Approximate nearest neighbors search.
         /// - Parameter vector: Half-precision query vector.
         /// - Parameter count: Upper limit on the number of matches to retrieve.
         /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
         /// - Throws: If runs out of memory.
         @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
-        public func search(vector: ArraySlice<Float16>, count: Int) -> ([Label], [Float]) {
-            var matches: [Label] = Array(repeating: 0, count: count)
+        public func search(vector: ArraySlice<Float16>, count: Int) -> ([Key], [Float]) {
+            var matches: [Key] = Array(repeating: 0, count: count)
             var distances: [Float] = Array(repeating: 0, count: count)
             let results = vector.withContiguousStorageIfAvailable {
-                searchHalf(vector: $0.baseAddress!, count: CUnsignedInt(count), labels: &matches, distances: &distances)
+                searchHalf(vector: $0.baseAddress!, count: CUnsignedInt(count), keys: &matches, distances: &distances)
             }
             matches.removeLast(count - Int(results!))
             distances.removeLast(count - Int(results!))
             return (matches, distances)
         }
 
+        /// Approximate nearest neighbors search.
+        /// - Parameter vector: Half-precision query vector.
+        /// - Parameter count: Upper limit on the number of matches to retrieve.
+        /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
+        /// - Throws: If runs out of memory.
+        @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
+        public func search(vector: Array<Float16>, count: Int) -> ([Key], [Float]) {
+            search(vector: vector[...], count: count)
+        }
+
     #endif
 
     /// Number of vectors in the index.
diff --git a/swift/README.md b/swift/README.md
index 04b85a02..852f8f73 100644
--- a/swift/README.md
+++ b/swift/README.md
@@ -12,9 +12,33 @@ https://github.com/unum-cloud/usearch
 let index = Index.l2sq(dimensions: 3, connectivity: 8)
 let vectorA: [Float32] = [0.3, 0.5, 1.2]
 let vectorB: [Float32] = [0.4, 0.2, 1.2]
-index.add(label: 42, vector: vectorA[...])
-index.add(label: 43, vector: vectorB[...])
+index.add(key: 42, vector: vectorA[...])
+index.add(key: 43, vector: vectorB[...])
 
 let results = index.search(vector: vectorA[...], count: 10)
 assert(results.0[0] == 42)
 ```
+
+If using in a SwiftUI application, make sure to annulate the void responses:
+
+```swift
+import SwiftUI
+import USearch
+
+@main
+struct USearchMobileApp: App {
+    var body: some Scene {
+        WindowGroup {
+            let index = USearchIndex.make(metric: .IP, dimensions: 2, connectivity: 16, quantization: .F32)
+            let _ = index.reserve(10)
+            let coordiantes: Array<Float32> = [40.177200, 44.503490]
+            let _ = index.add(key: 10, vector: coordiantes[...])            
+            VStack {
+                Text("USearch index contains \(index.length) vectors")
+                Spacer()
+            }
+
+        }
+    }
+}
+```
diff --git a/swift/Test.swift b/swift/Test.swift
index 5d9fb7f0..cae6db39 100644
--- a/swift/Test.swift
+++ b/swift/Test.swift
@@ -1,25 +1,37 @@
 //
 //  File.swift
-//  
 //
-//  Created by Ashot Vardanian on 5/11/23.
+//
+//  Created by Ash Vardanian on 5/11/23.
 //
 
 import Foundation
-import XCTest
 import USearch
+import XCTest
 
 @available(iOS 13, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
 class Test: XCTestCase {
     func testUnit() throws {
-        let index = USearchIndex.make(metric:USearchMetric.l2sq, dimensions: 4, connectivity: 8, quantization:USearchScalar.F32)
+        let index = USearchIndex.make(metric: USearchMetric.l2sq, dimensions: 4, connectivity: 8, quantization: USearchScalar.F32)
         let vectorA: [Float32] = [0.3, 0.5, 1.2, 1.4]
         let vectorB: [Float32] = [0.4, 0.2, 1.2, 1.1]
         index.reserve(2)
-        index.add(label: 42, vector: vectorA[...])
-        index.add(label: 43, vector: vectorB[...])
         
-        let results = index.search(vector: vectorA[...], count: 10)
+        // Adding a slice
+        index.add(key: 42, vector: vectorA[...])
+        
+        // Adding a vector
+        index.add(key: 43, vector: vectorB)
+        
+        let results = index.search(vector: vectorA, count: 10)
         assert(results.0[0] == 42)
+        
+        assert(index.contains(key: 42))
+        assert(index.count(key: 42) == 1)
+        assert(index.count(key: 49) == 0)
+        index.rename(from: 42, to: 49)
+        assert(index.count(key: 49) == 1)
+        index.remove(key: 49)
+        assert(index.count(key: 49) == 0)
     }
 }
diff --git a/swift/USearch.swift b/swift/USearch.swift
index b27b0b8a..af8b8f59 100644
--- a/swift/USearch.swift
+++ b/swift/USearch.swift
@@ -1,8 +1,8 @@
 //
 //  File.swift
-//  
 //
-//  Created by Ashot Vardanian on 5/11/23.
+//
+//  Created by Ash Vardanian on 5/11/23.
 //
 
 @_exported import USearchObjective
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 00000000..dc7df0d4
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,8 @@
+{
+    "typedocOptions": {
+        "entryPoints": [
+            "javascript/usearch.d.ts"
+        ],
+        "out": "docs"
+    }
+}
\ No newline at end of file
diff --git a/wasm/CMakeLists.txt b/wasm/CMakeLists.txt
index 3d7a0651..ed6f6c2c 100644
--- a/wasm/CMakeLists.txt
+++ b/wasm/CMakeLists.txt
@@ -13,3 +13,4 @@ set(USEARCH_PUNNED_INCLUDE_DIRS
 add_executable(index lib.cpp)
 target_include_directories(index PRIVATE ${USEARCH_PUNNED_INCLUDE_DIRS})
 set_target_properties(index PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/wasm)
+set_target_properties(index PROPERTIES CXX_STANDARD 11)
diff --git a/wolfram/CMakeLists.txt b/wolfram/CMakeLists.txt
index db2bddd2..261e0361 100644
--- a/wolfram/CMakeLists.txt
+++ b/wolfram/CMakeLists.txt
@@ -15,3 +15,4 @@ target_link_libraries(usearchWFM WSTP::STATIC_LIBRARY)
 
 # Set the output name of the library to be compatible with Wolfram Language
 set_target_properties(usearchWFM PROPERTIES PREFIX "" OUTPUT_NAME "usearchWFM")
+set_target_properties(usearchWFM PROPERTIES CXX_STANDARD 11)
diff --git a/wolfram/lib.cpp b/wolfram/lib.cpp
index 8bf8b27d..d7d0d259 100644
--- a/wolfram/lib.cpp
+++ b/wolfram/lib.cpp
@@ -1,27 +1,25 @@
 #include "WolframLibrary.h"
-#include <usearch/index_punned_dense.hpp>
+#include <usearch/index_dense.hpp>
 
 using namespace unum::usearch;
 
-using metric_t = index_punned_dense_metric_t;
-using distance_t = punned_distance_t;
-using index_t = punned_small_t;
+using distance_t = distance_punned_t;
+using index_t = index_dense_t;
 using vector_view_t = span_gt<float>;
 
 using add_result_t = typename index_t::add_result_t;
 using search_result_t = typename index_t::search_result_t;
-using label_t = typename index_t::label_t;
-using id_t = typename index_t::id_t;
+using key_t = typename index_t::key_t;
 
 EXTERN_C DLLEXPORT int WolframLibrary_initialize(WolframLibraryData libData) { return LIBRARY_NO_ERROR; }
 EXTERN_C DLLEXPORT void WolframLibrary_uninitialize(WolframLibraryData libData) { return; }
 
 EXTERN_C DLLEXPORT int IndexCreate(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res) {
     index_config_t config;
-    char* accuracy_cstr = nullptr;
+    char* quantization_cstr = nullptr;
     char* metric_cstr = nullptr;
     try {
-        accuracy_cstr = MArgument_getUTF8String(Args[1]);
+        quantization_cstr = MArgument_getUTF8String(Args[1]);
         metric_cstr = MArgument_getUTF8String(Args[0]);
         std::size_t dimensions = static_cast<std::size_t>(MArgument_getInteger(Args[2]));
         std::size_t capacity = static_cast<std::size_t>(MArgument_getInteger(Args[3]));
@@ -29,9 +27,9 @@ EXTERN_C DLLEXPORT int IndexCreate(WolframLibraryData libData, mint Argc, MArgum
         config.expansion_add = static_cast<std::size_t>(MArgument_getInteger(Args[5]));
         config.expansion_search = static_cast<std::size_t>(MArgument_getInteger(Args[6]));
 
-        scalar_kind_t accuracy = scalar_kind_from_name(accuracy_cstr, std::strlen(accuracy_cstr));
+        scalar_kind_t quantization = scalar_kind_from_name(quantization_cstr, std::strlen(quantization_cstr));
         metric_kind_t metric_kind = metric_from_name(metric_cstr, std::strlen(metric_cstr));
-        index_t index = make_punned<index_t>(metric_kind, dimensions, accuracy, config);
+        index_t index = make_punned<index_t>(metric_kind, dimensions, quantization, config);
         index.reserve(capacity);
 
         index_t* result_ptr = new index_t(std::move(index));
@@ -41,7 +39,7 @@ EXTERN_C DLLEXPORT int IndexCreate(WolframLibraryData libData, mint Argc, MArgum
         return LIBRARY_FUNCTION_ERROR;
     }
 
-    libData->UTF8String_disown(accuracy_cstr);
+    libData->UTF8String_disown(quantization_cstr);
     libData->UTF8String_disown(metric_cstr);
     return LIBRARY_NO_ERROR;
 }
@@ -119,12 +117,12 @@ EXTERN_C DLLEXPORT int IndexAdd(WolframLibraryData libData, mint Argc, MArgument
     index_t* c_ptr = (index_t*)MArgument_getUTF8String(Args[0]);
     float* vector_data = nullptr;
     try {
-        int label = MArgument_getInteger(Args[1]);
+        int key = MArgument_getInteger(Args[1]);
         MTensor tens = MArgument_getMTensor(Args[2]);
         std::size_t len = libData->MTensor_getFlattenedLength(tens);
         vector_data = (float*)libData->MTensor_getRealData(tens);
         vector_view_t vector_span = vector_view_t{vector_data, len};
-        c_ptr->add(label, vector_span);
+        c_ptr->add(key, vector_span);
     } catch (...) {
         return LIBRARY_FUNCTION_ERROR;
     }


Test patch:
diff --git a/c/test.c b/c/test.c
index 973e89ae..946f3c81 100644
--- a/c/test.c
+++ b/c/test.c
@@ -107,8 +107,8 @@ void test_add_vector(size_t vectors_count, size_t vector_dimension, float const*
 
     // Add vectors
     for (size_t i = 0; i < vectors_count; ++i) {
-        usearch_label_t label = i;
-        usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
+        usearch_key_t key = i;
+        usearch_add(idx, key, data + i * vector_dimension, usearch_scalar_f32_k, &error);
         ASSERT(!error, error);
     }
 
@@ -117,10 +117,10 @@ void test_add_vector(size_t vectors_count, size_t vector_dimension, float const*
 
     // Check vectors in the index
     for (size_t i = 0; i < vectors_count; ++i) {
-        usearch_label_t label = i;
-        ASSERT(usearch_contains(idx, label, &error), error);
+        usearch_key_t key = i;
+        ASSERT(usearch_contains(idx, key, &error), error);
     }
-    ASSERT(!usearch_contains(idx, -1, &error), error); // Non existing label
+    ASSERT(!usearch_contains(idx, -1, &error), error); // Non existing key
 
     usearch_free(idx, &error);
     printf("Test: Add Vector - PASSED\n");
@@ -137,21 +137,21 @@ void test_find_vector(size_t vectors_count, size_t vector_dimension, float const
 
     // Create result buffers
     int results_count = 10;
-    usearch_label_t* labels = (usearch_label_t*)malloc(results_count * sizeof(usearch_label_t));
+    usearch_key_t* keys = (usearch_key_t*)malloc(results_count * sizeof(usearch_key_t));
     float* distances = (float*)malloc(results_count * sizeof(float));
-    ASSERT(labels && distances, "Failed to allocate memory");
+    ASSERT(keys && distances, "Failed to allocate memory");
 
     // Add vectors
     for (size_t i = 0; i < vectors_count; ++i) {
-        usearch_label_t label = i;
-        usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
+        usearch_key_t key = i;
+        usearch_add(idx, key, data + i * vector_dimension, usearch_scalar_f32_k, &error);
         ASSERT(!error, error);
     }
 
     // Find the vectors
     for (size_t i = 0; i < vectors_count; i++) {
         const void *query_vector = data + i * vector_dimension;
-        size_t found_count = usearch_search(idx, query_vector, usearch_scalar_f32_k, results_count, labels, distances, &error);
+        size_t found_count = usearch_search(idx, query_vector, usearch_scalar_f32_k, results_count, keys, distances, &error);
         ASSERT(!error, error);
         ASSERT(found_count = results_count, "Vector is missing");
     }
@@ -171,15 +171,15 @@ void test_remove_vector(size_t vectors_count, size_t vector_dimension, float con
 
     // Add vectors
     for (size_t i = 0; i < vectors_count; ++i) {
-        usearch_label_t label = i;
-        usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
+        usearch_key_t key = i;
+        usearch_add(idx, key, data + i * vector_dimension, usearch_scalar_f32_k, &error);
         ASSERT(!error, error);
     }
 
     // Remove the vectors
     for (size_t i = 0; i < vectors_count; i++) {
-        usearch_label_t label = i;
-        usearch_remove(idx, label, &error);
+        usearch_key_t key = i;
+        usearch_remove(idx, key, &error);
         ASSERT(error, "Currently, Remove is not supported");
     }
 
@@ -198,8 +198,8 @@ void test_save_load(size_t vectors_count, size_t vector_dimension, float const*
 
     // Add vectors
     for (size_t i = 0; i < vectors_count; ++i) {
-        usearch_label_t label = i;
-        usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
+        usearch_key_t key = i;
+        usearch_add(idx, key, data + i * vector_dimension, usearch_scalar_f32_k, &error);
         ASSERT(!error, error);
     }
 
@@ -224,8 +224,8 @@ void test_save_load(size_t vectors_count, size_t vector_dimension, float const*
 
     // Check vectors in the index
     for (size_t i = 0; i < vectors_count; ++i) {
-        usearch_label_t label = i;
-        ASSERT(usearch_contains(idx, label, &error), error);
+        usearch_key_t key = i;
+        ASSERT(usearch_contains(idx, key, &error), error);
     }
 
     usearch_free(idx, &error);
@@ -243,8 +243,8 @@ void test_view(size_t vectors_count, size_t vector_dimension, float const* data)
 
     // Add vectors
     for (size_t i = 0; i < vectors_count; ++i) {
-        usearch_label_t label = i;
-        usearch_add(idx, label, data + i * vector_dimension, usearch_scalar_f32_k, &error);
+        usearch_key_t key = i;
+        usearch_add(idx, key, data + i * vector_dimension, usearch_scalar_f32_k, &error);
         ASSERT(!error, error);
     }
 
diff --git a/cpp/test.cpp b/cpp/test.cpp
index 1045e1f8..82075c02 100644
--- a/cpp/test.cpp
+++ b/cpp/test.cpp
@@ -3,8 +3,11 @@
  */
 #include <algorithm>
 #include <stdexcept>
+#include <unordered_map>
 
-#include <usearch/index_punned_dense.hpp>
+#include <usearch/index.hpp>
+#include <usearch/index_dense.hpp>
+#include <usearch/index_plugins.hpp>
 
 using namespace unum::usearch;
 using namespace unum;
@@ -14,94 +17,197 @@ void expect(bool must_be_true) {
         throw std::runtime_error("Failed!");
 }
 
-template <typename scalar_at, typename index_at> void test3d(index_at&& index) {
+template <bool punned_ak, typename index_at, typename scalar_at, typename... extra_args_at>
+void test_cosine(index_at& index, std::vector<std::vector<scalar_at>> const& vectors, extra_args_at&&... args) {
 
     using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using index_t = typename std::remove_reference<index_at>::type;
+    using index_t = index_at;
+    using key_t = typename index_t::key_t;
     using distance_t = typename index_t::distance_t;
-    using label_t = typename index_t::label_t;
 
-    scalar_t vec[3] = {10, 20, 15};
-    scalar_t vec_a[3] = {15, 16, 17};
-    scalar_t vec_b[3] = {16, 17, 18};
+    // Generate some keys starting from end,
+    // for three vectors from the dataset
+    key_t const key_max = default_free_value<key_t>() - 1;
+    key_t const key_first = key_max - 0;
+    key_t const key_second = key_max - 1;
+    key_t const key_third = key_max - 2;
+    scalar_t const* vector_first = vectors[0].data();
+    scalar_t const* vector_second = vectors[1].data();
+    scalar_t const* vector_third = vectors[2].data();
+    std::size_t dimensions = vectors[0].size();
 
     index.reserve(10);
-    index.add(42, view_t{&vec[0], 3ul});
+    index.add(key_first, vector_first, args...);
 
     // Default approximate search
-    label_t matched_labels[10] = {0};
+    key_t matched_labels[10] = {0};
     distance_t matched_distances[10] = {0};
-    std::size_t matched_count = index.search(view_t{&vec[0], 3ul}, 5).dump_to(matched_labels, matched_distances);
+    std::size_t matched_count = index.search(vector_first, 5, args...).dump_to(matched_labels, matched_distances);
 
     expect(matched_count == 1);
-    expect(matched_labels[0] == 42);
+    expect(matched_labels[0] == key_first);
     expect(std::abs(matched_distances[0]) < 0.01);
 
     // Add more entries
-    search_config_t search_config;
+    index_search_config_t search_config;
     search_config.exact = true;
-    index.add(43, view_t{&vec_a[0], 3ul});
-    index.add(44, view_t{&vec_b[0], 3ul});
+    index.add(key_second, vector_second, args...);
+    index.add(key_third, vector_third, args...);
     expect(index.size() == 3);
 
     // Perform exact search
-    matched_count = index.search(view_t{&vec[0], 3ul}, 5, search_config).dump_to(matched_labels, matched_distances);
+    matched_count = index.search(vector_first, 5, args..., search_config).dump_to(matched_labels, matched_distances);
 
     // Validate scans
     std::size_t count = 0;
     for (auto member : index) {
-        label_t id = member.label;
-        expect(id >= 42 && id <= 44);
+        key_t id = member.key;
+        expect(id <= key_first && id >= key_third);
         count++;
     }
     expect((count == 3));
     expect((index.stats(0).nodes == 3));
 
+    // Try removals and replacements
+    if constexpr (punned_ak) {
+        using labeling_result_t = typename index_t::labeling_result_t;
+        labeling_result_t result = index.remove(key_third);
+        expect(bool(result));
+        expect(index.size() == 2);
+        index.add(key_third, vector_third, args...);
+        expect(index.size() == 3);
+    }
+
     // Search again over reconstructed index
     index.save("tmp.usearch");
     index.load("tmp.usearch");
-    matched_count = index.search(view_t{&vec[0], 3ul}, 5).dump_to(matched_labels, matched_distances);
+    matched_count = index.search(vector_first, 5, args...).dump_to(matched_labels, matched_distances);
     expect(matched_count == 3);
-    expect(matched_labels[0] == 42);
+    expect(matched_labels[0] == key_first);
     expect(std::abs(matched_distances[0]) < 0.01);
 
+    if constexpr (punned_ak) {
+        std::vector<scalar_t> vec_recovered_from_load(dimensions);
+        index.get(key_second, vec_recovered_from_load.data());
+        expect(std::equal(vector_second, vector_second + dimensions, vec_recovered_from_load.data()));
+    }
+
+    // Try batch requests
+    executor_default_t executor;
+    index.reserve({vectors.size(), executor.size()});
+    executor.execute_bulk(vectors.size() - 3, [&](std::size_t thread, std::size_t task) {
+        index_update_config_t config;
+        config.thread = thread;
+        index.add(key_max - task - 3, vectors[task + 3].data(), args..., config);
+    });
+
     // Search again over mapped index
-    file_head_result_t head = index_metadata("tmp.usearch");
-    expect(head.size == 3);
+    // file_head_result_t head = index_dense_metadata("tmp.usearch");
+    // expect(head.size == 3);
     index.view("tmp.usearch");
-    matched_count = index.search(view_t{&vec[0], 3ul}, 5).dump_to(matched_labels, matched_distances);
+    matched_count = index.search(vector_first, 5, args...).dump_to(matched_labels, matched_distances);
     expect(matched_count == 3);
-    expect(matched_labels[0] == 42);
+    expect(matched_labels[0] == key_first);
     expect(std::abs(matched_distances[0]) < 0.01);
 
+    if constexpr (punned_ak) {
+        std::vector<scalar_t> vec_recovered_from_view(dimensions);
+        index.get(key_second, vec_recovered_from_view.data());
+        expect(std::equal(vector_second, vector_second + dimensions, vec_recovered_from_view.data()));
+
+        auto compaction_result = index.compact();
+        expect(bool(compaction_result));
+    }
+
     expect(index.memory_usage() > 0);
     expect(index.stats().max_edges > 0);
+
+    // Check metadata
+    if constexpr (punned_ak) {
+        index_dense_metadata_result_t meta = index_dense_metadata("tmp.usearch");
+        expect(bool(meta));
+    }
 }
 
-template <typename scalar_at, typename index_at> void test3d_punned(index_at&& index) {
+template <typename scalar_at, typename key_at, typename slot_at> //
+void test_cosine(std::size_t collection_size, std::size_t dimensions) {
 
     using scalar_t = scalar_at;
-    using view_t = span_gt<scalar_t const>;
-    using span_t = span_gt<scalar_at>;
+    using key_t = key_at;
+    using slot_t = slot_at;
 
-    scalar_t vec42[3] = {10, 20, 15};
-    scalar_t vec43[3] = {19, 22, 11};
+    using index_typed_t = index_gt<float, key_t, slot_t>;
+    using member_cref_t = typename index_typed_t::member_cref_t;
+    using member_citerator_t = typename index_typed_t::member_citerator_t;
 
-    index.reserve(10);
-    index.add(42, view_t{&vec42[0], 3ul});
-
-    // Reconstruct
-    scalar_t vec42_reconstructed[3] = {0, 0, 0};
-    index.get(42, span_t{&vec42_reconstructed[0], 3ul});
-    expect(vec42_reconstructed[0] == vec42[0]);
-    expect(vec42_reconstructed[1] == vec42[1]);
-    expect(vec42_reconstructed[2] == vec42[2]);
-
-    index.add(43, view_t{&vec43[0], 3ul});
-    expect(index.size() == 2);
-    index.remove(43);
-    expect(index.size() == 1);
+    std::vector<std::vector<scalar_at>> matrix(collection_size);
+    for (std::vector<scalar_at>& vector : matrix) {
+        vector.resize(dimensions);
+        std::generate(vector.begin(), vector.end(), [=] { return float(std::rand()) / float(INT_MAX); });
+    }
+
+    struct metric_t {
+        std::vector<std::vector<scalar_at>> const* matrix_ptr;
+        std::size_t dimensions;
+
+        scalar_t const* row(std::size_t i) const noexcept { return (*matrix_ptr)[i].data(); }
+
+        float operator()(member_cref_t const& a, member_cref_t const& b) const {
+            return metric_cos_gt<scalar_t>{}(row(get_slot(b)), row(get_slot(a)), dimensions);
+        }
+        float operator()(scalar_t const* some_vector, member_cref_t const& member) const {
+            return metric_cos_gt<scalar_t>{}(some_vector, row(get_slot(member)), dimensions);
+        }
+        float operator()(member_citerator_t const& a, member_citerator_t const& b) const {
+            return metric_cos_gt<scalar_t>{}(row(get_slot(b)), row(get_slot(a)), dimensions);
+        }
+        float operator()(scalar_t const* some_vector, member_citerator_t const& member) const {
+            return metric_cos_gt<scalar_t>{}(some_vector, row(get_slot(member)), dimensions);
+        }
+    };
+
+    // Template:
+    for (std::size_t connectivity : {3, 13, 50}) {
+        std::printf("- templates with connectivity %zu \n", connectivity);
+        metric_t metric{&matrix, dimensions};
+        index_config_t config(connectivity);
+        index_typed_t index_typed(config);
+        test_cosine<false>(index_typed, matrix, metric);
+    }
+
+    // Type-punned:
+    for (std::size_t connectivity : {3, 13, 50}) {
+        std::printf("- punned with connectivity %zu \n", connectivity);
+        using index_t = index_dense_gt<key_t, slot_t>;
+        metric_punned_t metric(dimensions, metric_kind_t::cos_k, scalar_kind<scalar_at>());
+        index_config_t config(connectivity);
+        index_t index = index_t::make(metric, config);
+        test_cosine<true>(index, matrix);
+    }
+}
+
+template <typename key_at, typename slot_at> void test_tanimoto(std::size_t dimensions, std::size_t connectivity) {
+
+    using key_t = key_at;
+    using slot_t = slot_at;
+
+    using index_punned_t = index_dense_gt<key_t, slot_t>;
+    std::size_t words = divide_round_up<CHAR_BIT>(dimensions);
+    metric_punned_t metric(words, metric_kind_t::tanimoto_k, scalar_kind_t::b1x8_k);
+    index_config_t config(connectivity);
+    index_punned_t index = index_punned_t::make(metric, config);
+
+    executor_default_t executor;
+    std::size_t batch_size = 1000;
+    std::vector<b1x8_t> scalars(batch_size * index.scalar_words());
+    std::generate(scalars.begin(), scalars.end(), [] { return static_cast<b1x8_t>(std::rand()); });
+
+    index.reserve({batch_size + index.size(), executor.size()});
+    executor.execute_bulk(batch_size, [&](std::size_t thread, std::size_t task) {
+        index_update_config_t config;
+        config.thread = thread;
+        index.add(task + 25000, scalars.data() + index.scalar_words() * task, config);
+    });
 }
 
 template <typename index_at> void test_sets(index_at&& index) {
@@ -122,18 +228,18 @@ template <typename index_at> void test_sets(index_at&& index) {
     expect(index.size() == 3);
 }
 
-template <typename index_at> void test_sets_moved() {
+template <typename index_at> void test_sets_moved(index_config_t const& config) {
     {
-        index_at index;
+        index_at index{config};
         test_sets(index);
     }
     {
-        index_at index;
+        index_at index{config};
         index.reserve(1);
         test_sets(index_at(std::move(index)));
     }
     {
-        index_at index;
+        index_at index{config};
         index.reserve(1);
         index_at index_moved = std::move(index);
         test_sets(index_moved);
@@ -142,39 +248,17 @@ template <typename index_at> void test_sets_moved() {
 
 int main(int, char**) {
 
-    static_assert(!std::is_same<index_gt<ip_gt<>>::value_type, std::true_type>());
-    static_assert(!std::is_same<index_gt<cos_gt<>>::value_type, std::true_type>());
-    static_assert(!std::is_same<index_gt<l2sq_gt<>>::value_type, std::true_type>());
-
-    static_assert(has_reset<memory_mapping_allocator_t>());
-    // static_assert(!std::is_same<index_gt<hamming_gt<>>::value_type, std::true_type>());
-    // static_assert(!std::is_same<index_gt<tanimoto_gt<>>::value_type, std::true_type>());
-    // static_assert(!std::is_same<index_gt<sorensen_gt<>>::value_type, std::true_type>());
-    // static_assert(!std::is_same<index_gt<jaccard_gt<>>::value_type, std::true_type>());
-    // static_assert(!std::is_same<index_gt<pearson_correlation_gt<>>::value_type, std::true_type>());
-    // static_assert(!std::is_same<index_gt<haversine_gt<>>::value_type, std::true_type>());
-
-    using big_point_id_t = std::int64_t;
-    test3d<float>(index_gt<cos_gt<float>, big_point_id_t, std::uint32_t>{});
-    test3d<float>(index_gt<l2sq_gt<float>, big_point_id_t, std::uint32_t>{});
-
-    test3d<double>(index_gt<cos_gt<double>, big_point_id_t, std::uint32_t>{});
-    test3d<double>(index_gt<l2sq_gt<double>, big_point_id_t, std::uint32_t>{});
-
-    test3d<float>(punned_small_t::make(3, metric_kind_t::cos_k));
-    test3d<float>(punned_small_t::make(3, metric_kind_t::l2sq_k));
-
-    test3d<double>(punned_small_t::make(3, metric_kind_t::cos_k));
-    test3d<double>(punned_small_t::make(3, metric_kind_t::l2sq_k));
-
-    test3d_punned<float>(punned_small_t::make(3, metric_kind_t::cos_k));
-    test3d_punned<float>(punned_small_t::make(3, metric_kind_t::l2sq_k));
-
-    test_sets(index_gt<jaccard_gt<std::int32_t, float>, big_point_id_t, std::uint32_t>{});
-    test_sets(index_gt<jaccard_gt<std::int64_t, float>, big_point_id_t, std::uint32_t>{});
-
-    test_sets_moved<index_gt<jaccard_gt<std::int32_t, float>, big_point_id_t, std::uint32_t>>();
-    test_sets_moved<index_gt<jaccard_gt<std::int64_t, float>, big_point_id_t, std::uint32_t>>();
+    for (std::size_t collection_size : {10, 500})
+        for (std::size_t dimensions : {97, 256}) {
+            std::printf("Indexing %zu vectors with cos: <float, std::int64_t, std::uint32_t> \n", collection_size);
+            test_cosine<float, std::int64_t, std::uint32_t>(collection_size, dimensions);
+            std::printf("Indexing %zu vectors with cos: <float, std::int64_t, uint40_t> \n", collection_size);
+            test_cosine<float, std::int64_t, uint40_t>(collection_size, dimensions);
+        }
+
+    for (std::size_t connectivity : {3, 13, 50})
+        for (std::size_t dimensions : {97, 256})
+            test_tanimoto<std::int64_t, std::uint32_t>(dimensions, connectivity);
 
     return 0;
 }
\ No newline at end of file
diff --git a/golang/lib_test.go b/golang/lib_test.go
new file mode 100644
index 00000000..ab2ad332
--- /dev/null
+++ b/golang/lib_test.go
@@ -0,0 +1,105 @@
+package usearch
+
+import (
+	"runtime"
+	"testing"
+)
+
+func TestUSearch(t *testing.T) {
+	runtime.LockOSThread()
+
+	t.Run("Test Index Initialization", func(t *testing.T) {
+		dim := uint(128)
+		conf := DefaultConfig(dim)
+		ind, err := NewIndex(conf)
+		if err != nil {
+			t.Fatalf("Failed to construct the index: %s", err)
+		}
+		defer ind.Destroy()
+
+		found_dims, err := ind.Dimensions()
+		if err != nil {
+			t.Fatalf("Failed to retrieve dimensions: %s", err)
+		}
+		if found_dims != dim {
+			t.Fatalf("Expected %d dimensions, got %d", dim, found_dims)
+		}
+
+		found_len, err := ind.Len()
+		if err != nil {
+			t.Fatalf("Failed to retrieve size: %s", err)
+		}
+		if found_len != 0 {
+			t.Fatalf("Expected size to be 0, got %d", found_len)
+		}
+
+		err = ind.Reserve(100)
+		if err != nil {
+			t.Fatalf("Failed to reserve capacity: %s", err)
+		}
+	})
+
+	t.Run("Test Insertion", func(t *testing.T) {
+		dim := uint(128)
+		conf := DefaultConfig(dim)
+		ind, err := NewIndex(conf)
+		if err != nil {
+			t.Fatalf("Failed to construct the index: %s", err)
+		}
+		defer ind.Destroy()
+
+		err = ind.Reserve(100)
+		if err != nil {
+			t.Fatalf("Failed to reserve capacity: %s", err)
+		}
+
+		vec := make([]float32, dim)
+		vec[0] = 40.0
+		vec[1] = 2.0
+
+		err = ind.Add(42, vec)
+		if err != nil {
+			t.Fatalf("Failed to insert: %s", err)
+		}
+
+		found_len, err := ind.Len()
+		if err != nil {
+			t.Fatalf("Failed to retrieve size after insertion: %s", err)
+		}
+		if found_len != 1 {
+			t.Fatalf("Expected size to be 1, got %d", found_len)
+		}
+	})
+
+	t.Run("Test Search", func(t *testing.T) {
+		dim := uint(128)
+		conf := DefaultConfig(dim)
+		ind, err := NewIndex(conf)
+		if err != nil {
+			t.Fatalf("Failed to construct the index: %s", err)
+		}
+		defer ind.Destroy()
+
+		err = ind.Reserve(100)
+		if err != nil {
+			t.Fatalf("Failed to reserve capacity: %s", err)
+		}
+
+		vec := make([]float32, dim)
+		vec[0] = 40.0
+		vec[1] = 2.0
+
+		err = ind.Add(42, vec)
+		if err != nil {
+			t.Fatalf("Failed to insert: %s", err)
+		}
+
+		keys, distances, err := ind.Search(vec, 10)
+		if err != nil {
+			t.Fatalf("Failed to search: %s", err)
+		}
+		if keys[0] != 42 || distances[0] != 0.0 {
+			t.Fatalf("Expected result 42 with distance 0, got key %d with distance %f", keys[0], distances[0])
+		}
+	})
+}
diff --git a/golang/usearch_par_test.go b/golang/usearch_par_test.go
deleted file mode 100644
index 82da6592..00000000
--- a/golang/usearch_par_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package usearch
-
-import (
-	"sync"
-	"testing"
-)
-
-func TestParallelism(t *testing.T) {
-	totalInserts := 3000
-	ind := NewIndex(DefaultConfig(128))
-	defer ind.Destroy()
-
-	var v0 = make([]float32, 128)
-	v0[0] = 4.4
-	var wg sync.WaitGroup
-	ind.Reserve(totalInserts)
-
-	// second thread
-	wg.Add(1)
-	go func() {
-		defer wg.Done()
-		var v1 = make([]float32, 128)
-		for l := 0; l < totalInserts/2; l++ {
-			ind.Add(10000+l, v1)
-		}
-	}()
-
-	for l := 0; l < totalInserts/2; l++ {
-		ind.Add(l, v0)
-	}
-	wg.Wait()
-	if ind.Len() != totalInserts {
-		t.Errorf("wrong length: expected %d, got %d", totalInserts, ind.Len())
-	}
-
-	res := ind.Search(v0[:], 10)
-	if len(res) != 10 {
-		t.Errorf("wrong search result length: expected %d, got %d", 10, len(res))
-	}
-}
diff --git a/golang/usearch_test.go b/golang/usearch_test.go
deleted file mode 100644
index 0cbe0e3e..00000000
--- a/golang/usearch_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-package usearch
-
-import (
-	"runtime"
-	"testing"
-)
-
-func Assure(err error) {
-	if err != nil {
-		panic(err)
-	}
-}
-func TestUsearch(t *testing.T) {
-	runtime.LockOSThread()
-	dim := 128
-	conf := DefaultConfig(dim)
-	ind := NewIndex(conf)
-	defer ind.Destroy()
-	if ind.VecDimension() != dim {
-		t.Fatalf("expected dimension %d, got %d", dim, ind.VecDimension())
-	}
-
-	if ind.Connectivity() != conf.Connectivity {
-		t.Fatalf("expected connectivity %d, got %d", conf.Connectivity, ind.Connectivity())
-	}
-
-	if ind.Capacity() != conf.InitCapacity {
-		t.Fatalf("expected initial capacity %d, got %d", conf.InitCapacity, ind.Capacity())
-	}
-
-	if ind.Len() != 0 {
-		t.Fatalf("expected empty initial index, got %d", ind.Len())
-	}
-
-	vec := make([]float32, dim)
-	vec[0] = 40.0
-	vec[1] = 2.0
-	Assure(ind.Add(42, vec))
-	if ind.Len() != 1 {
-		t.Fatalf("expected index size 1, got %d", ind.Len())
-	}
-
-	res := ind.Search(vec, 10)
-	if len(res) != 1 {
-		t.Fatalf("expected 1 result, got %d", len(res))
-	}
-
-	if res[0] != 42 {
-		t.Fatalf("expected result 42, got %d", res[0])
-	}
-
-	vec_far := make([]float32, dim)
-	Assure(ind.Add(43, vec_far))
-	vec_close := make([]float32, dim)
-	vec_close[0] = 40.0
-	vec_close[1] = 4.0
-	res = ind.Search(vec_close, 1)
-	if len(res) != 1 {
-		t.Fatalf("expected 1 result, got %d", len(res))
-	}
-	if res[0] != 42 {
-		t.Fatalf("expected closest vector label to be 42, got %d", res[0])
-	}
-
-	res = ind.Search(vec_close, 2)
-	if len(res) != 2 {
-		t.Fatalf("expected 2 results, got %d", len(res))
-	}
-	if !(res[0] == 42 && res[1] == 43) {
-		t.Fatalf("expected closest vector labels to be 42, 43, got %d, %d", res[0], res[1])
-	}
-
-	Assure(ind.Reserve(102))
-	for i := 0; i < 100; i++ {
-		vec[i] += 10
-		Assure(ind.Add(i, vec))
-	}
-	res = ind.Search(vec, 100)
-	if len(res) != 100 {
-		t.Fatalf("expected 100 results, got %d", len(res))
-	}
-}
diff --git a/java/test/IndexTest.java b/java/test/IndexTest.java
index 1c6e5e6a..2bda8892 100644
--- a/java/test/IndexTest.java
+++ b/java/test/IndexTest.java
@@ -23,7 +23,7 @@ public void test() {
         // Index index = new Index.Config().metric("cos").dimensions(2).build();
         // float vec[] = {10, 20};
         // index.add(42, vec);
-        // int[] labels = index.search(vec, 5);
+        // int[] keys = index.search(vec, 5);
 
         System.out.println("Java Tests Passed!");
     }
diff --git a/javascript/test.js b/javascript/test.js
index 90d5ddd6..a6332ca8 100644
--- a/javascript/test.js
+++ b/javascript/test.js
@@ -1,17 +1,31 @@
 var assert = require('assert');
 var usearch = require('bindings')('usearch');
 
-var index = new usearch.Index({ metric: 'l2sq', connectivity: 16, dimensions: 2 })
-assert.equal(index.connectivity(), 16)
-assert.equal(index.dimensions(), 2)
-assert.equal(index.size(), 0)
+// Single-entry operations
 
-index.add(15, new Float32Array([10, 20]))
-index.add(16, new Float32Array([10, 25]))
-assert.equal(index.size(), 2)
+var index = new usearch.Index({ metric: 'l2sq', connectivity: 16n, dimensions: 2n });
+assert.equal(index.connectivity(), 16n, 'connectivity should be 16');
+assert.equal(index.dimensions(), 2n, 'dimensions should be 2');
+assert.equal(index.size(), 0n, 'initial size should be 0');
 
-var results = index.search(new Float32Array([13, 14]), 2)
-assert.deepEqual(results.labels, new BigUint64Array([15n, 16n]))
-assert.deepEqual(results.distances, new Float32Array([45, 130]))
+index.add(15n, new Float32Array([10, 20]));
+index.add(16n, new Float32Array([10, 25]));
+assert.equal(index.size(), 2n, 'size after adding elements should be 2');
 
-console.log('JavaScript tests passed!')
\ No newline at end of file
+var results = index.search(new Float32Array([13, 14]), 2n);
+assert.deepEqual(results.keys, new BigUint64Array([15n, 16n]), 'keys should be 15 and 16');
+assert.deepEqual(results.distances, new Float32Array([45, 130]), 'distances should be 45 and 130');
+
+// Batch operations
+
+var indexBatch = new usearch.Index({ metric: 'l2sq', connectivity: 16n, dimensions: 2n });
+const keys = [15n, 16n];
+const vectors = [new Float32Array([10, 20]), new Float32Array([10, 25])];
+indexBatch.add(keys, vectors);
+assert.equal(indexBatch.size(), 2, 'size after adding batch should be 2');
+
+results = indexBatch.search(new Float32Array([13, 14]), 2n);
+assert.deepEqual(results.keys, new BigUint64Array([15n, 16n]), 'keys should be 15 and 16');
+assert.deepEqual(results.distances, new Float32Array([45, 130]), 'distances should be 45 and 130');
+
+console.log('JavaScript tests passed!');
diff --git a/python/scripts/test.py b/python/scripts/test.py
index 1620dc72..9ec0ea9c 100644
--- a/python/scripts/test.py
+++ b/python/scripts/test.py
@@ -5,13 +5,16 @@
 
 from usearch.io import load_matrix, save_matrix
 from usearch.eval import random_vectors
+from usearch.index import search
 
 from usearch.index import (
     Index,
-    SparseIndex,
+    Indexes,
     MetricKind,
     ScalarKind,
+    Match,
     Matches,
+    BatchMatches,
 )
 from usearch.index import (
     DEFAULT_CONNECTIVITY,
@@ -19,6 +22,11 @@
     DEFAULT_EXPANSION_SEARCH,
 )
 
+# When running the tests concurrently in different VMs, one can get access violation errors.
+# To avoid that, we embed the OS name into the temporary files name.
+# https://github.com/unum-cloud/usearch/actions/runs/5705359698/job/15459945738
+temporary_filename = f"tmp-{os.name}"
+temporary_usearch_filename = temporary_filename + ".usearch"
 
 dimensions = [3, 97, 256]
 batch_sizes = [1, 77]
@@ -26,7 +34,7 @@
     ScalarKind.F32,
     ScalarKind.F64,
     ScalarKind.F16,
-    ScalarKind.F8,
+    ScalarKind.I8,
 ]
 numpy_types = [np.float32, np.float64, np.float16]
 
@@ -52,10 +60,10 @@ def test_serializing_fbin_matrix(rows: int, cols: int):
     :param int cols: The number of columns in the matrix.
     """
     original = np.random.rand(rows, cols).astype(np.float32)
-    save_matrix(original, "tmp.fbin")
-    reconstructed = load_matrix("tmp.fbin")
+    save_matrix(original, temporary_filename + ".fbin")
+    reconstructed = load_matrix(temporary_filename + ".fbin")
     assert np.allclose(original, reconstructed)
-    os.remove("tmp.fbin")
+    os.remove(temporary_filename + ".fbin")
 
 
 @pytest.mark.parametrize("rows", batch_sizes)
@@ -68,10 +76,31 @@ def test_serializing_ibin_matrix(rows: int, cols: int):
     :param int cols: The number of columns in the matrix.
     """
     original = np.random.randint(0, rows + 1, size=(rows, cols)).astype(np.int32)
-    save_matrix(original, "tmp.ibin")
-    reconstructed = load_matrix("tmp.ibin")
+    save_matrix(original, temporary_filename + ".ibin")
+    reconstructed = load_matrix(temporary_filename + ".ibin")
     assert np.allclose(original, reconstructed)
-    os.remove("tmp.ibin")
+    os.remove(temporary_filename + ".ibin")
+
+
+@pytest.mark.parametrize("rows", batch_sizes)
+@pytest.mark.parametrize("cols", dimensions)
+def test_exact_search(rows: int, cols: int):
+    """
+    Test exact search.
+
+    :param int rows: The number of rows in the matrix.
+    :param int cols: The number of columns in the matrix.
+    """
+    original = np.random.rand(rows, cols)
+    matches: BatchMatches = search(original, original, 10, exact=True)
+    top_matches = (
+        [int(m.keys[0]) for m in matches] if rows > 1 else int(matches.keys[0])
+    )
+    assert np.all(top_matches == np.arange(rows))
+
+    matches: Matches = search(original, original[0], 10, exact=True)
+    top_match = int(matches.keys[0])
+    assert top_match == 0
 
 
 @pytest.mark.parametrize("ndim", dimensions)
@@ -100,23 +129,26 @@ def test_index(
     vector = random_vectors(count=1, ndim=ndim, dtype=numpy_type).flatten()
     index.add(42, vector)
 
-    assert 42 in index
-    assert 42 in index.labels
-    assert 43 not in index
-    assert index[42] is not None
-    assert index[43] is None
+    assert len(index) == 1, "Size after addition"
+    assert 42 in index, "Presence in the index"
+    assert 42 in index.keys, "Presence among keys"
+    assert 43 not in index, "Presence in the index, false positive"
+    assert index[42] is not None, "Vector recovery"
+    assert index[43] is None, "Vector recovery, false positive"
     assert len(index[42]) == ndim
     if numpy_type != np.byte:
         assert np.allclose(index[42], vector, atol=0.1)
 
-    matches, distances, count = index.search(vector, 10)
-    assert len(index) == 1
-    assert len(matches) == count
-    assert len(distances) == count
-    assert count == 1
-    assert matches[0] == 42
-    assert distances[0] == pytest.approx(0, abs=1e-3)
+    matches: Matches = index.search(vector, 10)
+    assert len(matches.keys) == 1, "Number of matches"
+    assert len(matches.keys) == len(matches.distances), "Symmetric match sub-arrays"
+    assert len({match.key for match in matches}) == 1, "Iteration over matches"
+    assert matches[0].key == 42
+    assert matches[0].distance == pytest.approx(0, abs=1e-3)
+    assert matches.computed_distances != 0
+    assert matches.visited_members != 0
 
+    # Validating the index structure and metadata:
     assert index.max_level >= 0
     assert index.levels_stats.nodes >= 1
     assert index.level_stats(0).nodes == 1
@@ -129,30 +161,61 @@ def test_index(
     index.remove(43)
     assert len(index) == 1
 
-    index.save("tmp.usearch")
+    # Try inserting back
+    index.add(43, other_vector)
+    assert len(index) == 2
+    index.remove(43)
+    assert len(index) == 1
+
+    index.save(temporary_usearch_filename)
 
     # Re-populate cleared index
     index.clear()
     assert len(index) == 0
     index.add(42, vector)
     assert len(index) == 1
-    matches, distances, count = index.search(vector, 10)
-    assert count == 1
+    matches: Matches = index.search(vector, 10)
+    assert len(matches) == 1
+
+    index_copy = index.copy()
+    assert len(index_copy) == 1
+    assert len(index_copy[42]) == ndim
+    matches_copy: Matches = index_copy.search(vector, 10)
+    assert np.all(matches_copy.keys == matches.keys)
 
-    index.load("tmp.usearch")
+    index.load(temporary_usearch_filename)
     assert len(index) == 1
     assert len(index[42]) == ndim
 
-    index = Index.restore("tmp.usearch")
+    matches_loaded: Matches = index.search(vector, 10)
+    assert np.all(matches_loaded.keys == matches.keys)
+
+    index = Index.restore(temporary_usearch_filename, view=True)
     assert len(index) == 1
     assert len(index[42]) == ndim
 
-    index_copy = index.copy()
-    assert len(index_copy) == 1
-    assert len(index_copy[42]) == ndim
+    matches_viewed: Matches = index.search(vector, 10)
+    assert np.all(matches_viewed.keys == matches.keys)
 
     # Cleanup
-    os.remove("tmp.usearch")
+    index.reset()
+    os.remove(temporary_usearch_filename)
+
+    # Try opening a missing file
+    meta = Index.metadata(temporary_usearch_filename)
+    assert meta is None
+    index = Index.restore(temporary_usearch_filename)
+    assert index is None
+
+    # Try opening a corrupt file
+    with open(temporary_usearch_filename, "w") as file:
+        file.write("Some random string")
+    meta = Index.metadata(temporary_usearch_filename)
+    assert meta is None
+    index = Index.restore(temporary_usearch_filename)
+
+    assert index is None
+    os.remove(temporary_usearch_filename)
 
 
 @pytest.mark.parametrize("ndim", dimensions)
@@ -169,36 +232,50 @@ def test_index_batch(
 ):
     index = Index(ndim=ndim, metric=metric, dtype=index_type)
 
-    labels = np.arange(batch_size)
+    keys = np.arange(batch_size)
     vectors = random_vectors(count=batch_size, ndim=ndim, dtype=numpy_type)
 
-    index.add(labels, vectors, threads=2)
+    index.add(keys, vectors, threads=2)
     assert len(index) == batch_size
-    assert np.allclose(index.get_vectors(labels).astype(numpy_type), vectors, atol=0.1)
+    assert np.allclose(index.get_vectors(keys).astype(numpy_type), vectors, atol=0.1)
 
-    matches: Matches = index.search(vectors, 10, threads=2)
-    assert matches.labels.shape[0] == matches.distances.shape[0]
-    assert matches.counts.shape[0] == batch_size
-    assert np.all(np.sort(index.labels) == np.sort(labels))
+    matches: BatchMatches = index.search(vectors, 10, threads=2)
+    assert matches.keys.shape[0] == matches.distances.shape[0]
+    assert len(matches) == batch_size
+    assert np.all(np.sort(index.keys) == np.sort(keys))
 
-    assert index.max_level >= 0  # TODO: This should be 1
+    if batch_size > 1:
+        assert index.max_level >= 1
+    else:
+        assert index.max_level >= 0
     assert index.levels_stats.nodes >= batch_size
     assert index.level_stats(0).nodes == batch_size
 
-    index.save("tmp.usearch")
+    index.save(temporary_usearch_filename)
     index.clear()
     assert len(index) == 0
 
-    index.load("tmp.usearch")
+    index.load(temporary_usearch_filename)
     assert len(index) == batch_size
     assert len(index[0]) == ndim
 
-    index = Index.restore("tmp.usearch")
+    if batch_size > 1:
+        matches_loaded: BatchMatches = index.search(vectors, 10, threads=2)
+        for idx in range(len(matches_loaded)):
+            assert np.all(matches_loaded[idx].keys == matches[idx].keys)
+
+    index = Index.restore(temporary_usearch_filename, view=True)
     assert len(index) == batch_size
     assert len(index[0]) == ndim
 
+    if batch_size > 1:
+        matches_viewed: BatchMatches = index.search(vectors, 10, threads=2)
+        for idx in range(len(matches_viewed)):
+            assert np.all(matches_viewed[idx].keys == matches[idx].keys)
+
     # Cleanup
-    os.remove("tmp.usearch")
+    index.reset()
+    os.remove(temporary_usearch_filename)
 
 
 @pytest.mark.parametrize("metric", [MetricKind.L2sq])
@@ -213,33 +290,54 @@ def test_exact_recall(
 ):
     ndim: int = batch_size
     index = Index(ndim=ndim, metric=metric, dtype=index_type)
+    assert index.ndim == ndim
 
     vectors = np.zeros((batch_size, ndim), dtype=numpy_type)
     for i in range(batch_size):
         vectors[i, i] = 1
-    labels = np.arange(batch_size)
-    index.add(labels, vectors)
+    keys = np.arange(batch_size)
+    index.add(keys, vectors)
     assert len(index) == batch_size
 
     # Search one at a time
     for i in range(batch_size):
         matches: Matches = index.search(vectors[i], 10, exact=True)
-        found_labels = matches.labels
+        found_labels = matches.keys
         assert found_labels[0] == i
+        assert matches.computed_distances == len(index)
+        assert matches.visited_members == 0, "Exact search won't traverse the graph"
 
     # Search the whole batch
-    matches: Matches = index.search(vectors, 10, exact=True)
-    found_labels = matches.labels
-    for i in range(batch_size):
-        assert found_labels[i, 0] == i
+    if batch_size > 1:
+        matches: BatchMatches = index.search(vectors, 10, exact=True)
+        assert matches.computed_distances == len(index) * len(vectors)
+        assert matches.visited_members == 0, "Exact search won't traverse the graph"
 
-    # Match entries aginst themselves
+        found_labels = matches.keys
+        for i in range(batch_size):
+            assert found_labels[i, 0] == i
+
+    # Match entries against themselves
     index_copy: Index = index.copy()
     mapping: dict = index.join(index_copy, exact=True)
     for man, woman in mapping.items():
         assert man == woman, "Stable marriage failed"
 
 
+def test_indexes():
+    ndim = 10
+    index_a = Index(ndim=ndim)
+    index_b = Index(ndim=ndim)
+
+    vectors = random_vectors(count=3, ndim=ndim)
+    index_a.add(42, vectors[0])
+    index_b.add(43, vectors[1])
+
+    indexes = Indexes([index_a, index_b])
+    matches = indexes.search(vectors[2], 10)
+    assert len(matches) == 2
+
+
 @pytest.mark.parametrize("bits", dimensions)
 @pytest.mark.parametrize("metric", hash_metrics)
 @pytest.mark.parametrize("connectivity", connectivity_options)
@@ -252,22 +350,15 @@ def test_bitwise_index(
 ):
     index = Index(ndim=bits, metric=metric, connectivity=connectivity)
 
-    labels = np.arange(batch_size)
+    keys = np.arange(batch_size)
     byte_vectors = np.random.randint(2, size=(batch_size, bits))
     bit_vectors = np.packbits(byte_vectors, axis=1)
 
-    index.add(labels, bit_vectors)
-    assert np.allclose(index.get_vectors(labels), byte_vectors, atol=0.1)
-    assert np.all(index.get_vectors(labels, ScalarKind.B1) == bit_vectors)
+    index.add(keys, bit_vectors)
+    assert np.all(index.get_vectors(keys, ScalarKind.B1) == bit_vectors)
 
     index.search(bit_vectors, 10)
 
 
-@pytest.mark.parametrize("connectivity", connectivity_options)
-@pytest.mark.skipif(os.name == "nt", reason="Spurious behaviour on windows")
-def test_sets_index(connectivity: int):
-    index = SparseIndex(connectivity=connectivity)
-    index.add(10, np.array([10, 12, 15], dtype=np.uint32))
-    index.add(11, np.array([11, 12, 15, 16], dtype=np.uint32))
-    results = index.search(np.array([12, 15], dtype=np.uint32), 10)
-    assert list(results) == [10, 11]
+if __name__ == "__main__":
+    pytest.main(args=["python/scripts/test.py", "-s", "-x", "-v"])
diff --git a/python/scripts/test_jit.py b/python/scripts/test_jit.py
index 0e0eec51..dd7aab79 100644
--- a/python/scripts/test_jit.py
+++ b/python/scripts/test_jit.py
@@ -85,13 +85,12 @@ def python_inner_product_four_args(a, a_ndim, b, b_ndim):
         )
         index = Index(ndim=ndim, metric=metric)
 
-        labels = np.arange(batch_size)
+        keys = np.arange(batch_size)
         vectors = random_vectors(count=batch_size, ndim=ndim)
 
-        index.add(labels, vectors)
-        matches, distances, count = index.search(vectors, 10)
-        assert matches.shape[0] == distances.shape[0]
-        assert count.shape[0] == batch_size
+        index.add(keys, vectors)
+        matches = index.search(vectors, 10)
+        assert len(matches) == batch_size
 
 
 @pytest.mark.parametrize("ndim", dimensions[-1:])
@@ -149,13 +148,12 @@ def test_index_cppyy(ndim: int, batch_size: int):
         )
         index = Index(ndim=ndim, metric=metric)
 
-        labels = np.arange(batch_size)
+        keys = np.arange(batch_size)
         vectors = random_vectors(count=batch_size, ndim=ndim)
 
-        index.add(labels, vectors)
-        matches, distances, count = index.search(vectors, 10)
-        assert matches.shape[0] == distances.shape[0]
-        assert count.shape[0] == batch_size
+        index.add(keys, vectors)
+        matches = index.search(vectors, 10)
+        assert len(matches) == batch_size
 
 
 @pytest.mark.parametrize("ndim", [8])
@@ -235,10 +233,10 @@ def test_index_peachpy(ndim: int, batch_size: int):
     )
     index = Index(ndim=ndim, metric=metric)
 
-    labels = np.arange(batch_size)
+    keys = np.arange(batch_size)
     vectors = random_vectors(count=batch_size, ndim=ndim)
 
-    index.add(labels, vectors)
+    index.add(keys, vectors)
     matches, distances, count = index.search(vectors, 10)
     assert matches.shape[0] == distances.shape[0]
     assert count.shape[0] == batch_size
diff --git a/python/scripts/test_sparse.py b/python/scripts/test_sparse.py
new file mode 100644
index 00000000..bb77a395
--- /dev/null
+++ b/python/scripts/test_sparse.py
@@ -0,0 +1,32 @@
+import os
+
+import pytest
+import numpy as np
+
+from usearch.index import (
+    SparseIndex,
+)
+from usearch.index import (
+    DEFAULT_CONNECTIVITY,
+    DEFAULT_EXPANSION_ADD,
+    DEFAULT_EXPANSION_SEARCH,
+)
+
+
+dimensions = [3, 97, 256]
+batch_sizes = [1, 77]
+connectivity_options = [3, 13, 50, DEFAULT_CONNECTIVITY]
+
+
+@pytest.mark.parametrize("connectivity", connectivity_options)
+@pytest.mark.skipif(os.name == "nt", reason="Spurious behaviour on windows")
+def test_sets_index(connectivity: int):
+    index = SparseIndex(connectivity=connectivity)
+    index.add(10, np.array([10, 12, 15], dtype=np.uint32))
+    index.add(11, np.array([11, 12, 15, 16], dtype=np.uint32))
+    results = index.search(np.array([12, 15], dtype=np.uint32), 10)
+    assert list(results) == [10, 11]
+
+
+if __name__ == "__main__":
+    pytest.main(args=["python/scripts/test.py", "-s", "-x", "-v"])