let weighted_distance = Box::new(move |a: *const f32, b: *const f32| unsafe {
let a_slice = std::slice::from_raw_parts(a, image_dimensions + text_dimensions);
let b_slice = std::slice::from_raw_parts(b, image_dimensions + text_dimensions);
let image_similarity = f32::cosine(a_slice[0..image_dimensions], b_slice[0..image_dimensions]);
let text_similarity = f32::cosine(a_slice[image_dimensions..], b_slice[image_dimensions..]);
let similarity = image_weights * image_similarity + text_weights * text_similarity / (image_weights + text_weights);
1.0 - similarity
});
index.change_metric(weighted_distance);
Broader Type System for Rust
USearch supports the Rust-native `f32` and `f64` scalar types, as well as the `i8` for quantized 8-bit scalars. Going beyond that, USearch supports non-native `f16` and `b1x8` for half-precision floating point and binary vectors, respectively.
Half Precision Floating Point
Rust has no native support for half-precision floating-point numbers, but USearch provides a `f16` type. It has no advanced functionality - it is a transparent wrapper around `i16` and can be used with `half` or any other half-precision library. Assuming USearch uses the IEEE 754 no conversion is needed, you can `unsafe`-cast the outputs of other IEEE-compliant libraries to `usearch::f16`.
rust
use usearch::f16 as USearchF16;
use half::f16 as HalfF16;
let vector_a: Vec<HalfF16> = ...
let vector_b: Vec<HalfF16> = ...
let buffer_a: &[USearchF16] = unsafe { std::slice::from_raw_parts(a_half.as_ptr() as *const SimF16, a_half.len()) };
let buffer_b: &[USearchF16] = unsafe { std::slice::from_raw_parts(b_half.as_ptr() as *const SimF16, b_half.len()) };
index.add(42, buffer_a);
index.add(43, buffer_b);
Binary Vectors
USearch also implement binary distance functions and natively supports bit-vectors. If you initialize the index with `quantization: ScalarKind::B1`, you can add floating-point vectors and they will be quantized mapping positive values to `1` and negative and zero values to `0`. Alternatively, you can use the `b1x8` type to represent packed binary vectors directly.
rs
let index = Index::new(&IndexOptions {
dimensions: 8,
metric: MetricKind::Hamming,
quantization: ScalarKind::B1,
..Default::default()
})
.unwrap();
// Binary vectors represented as `b1x8` slices
let vector42: Vec<b1x8> = vec![b1x8(0b00001111)];
let vector43: Vec<b1x8> = vec![b1x8(0b11110000)];
let query: Vec<b1x8> = vec![b1x8(0b01111000)];
// Adding binary vectors to the index
index.reserve(10).unwrap();
index.add(42, &vector42).unwrap();
index.add(43, &vector43).unwrap();
let results = index.search(&query, 5).unwrap();
// Validate the search results based on Hamming distance
assert_eq!(results.keys.len(), 2);
assert_eq!(results.keys[0], 43);
assert_eq!(results.distances[0], 2.0); // 2 bits differ between query and vector43
assert_eq!(results.keys[1], 42);
assert_eq!(results.distances[1], 6.0); // 6 bits differ between query and vector42
Metadata
Both C and Rust now provide:
- `memory_usage` API, that reports the number of bytes consumed.
- `hardware_acceleration` API that reports the codename for used SIMD extensions.
Changelog [2.11.0](https://github.com/unum-cloud/usearch/compare/v2.10.5...v2.11.0) (2024-04-08)
* `b1x8` for Rust ([540fc75](https://github.com/unum-cloud/usearch/commit/540fc75d682c209172170b75cafc879bcfcbdc58))
* `filtered_search` API in C & C++ ([5bb38aa](https://github.com/unum-cloud/usearch/commit/5bb38aacfba28ac270dc6d7e032ed89da772ff4e))
* `filtered_search` in Rust ([e1b24e1](https://github.com/unum-cloud/usearch/commit/e1b24e1950f25119471f037c90a5685e544897e0))
* Hyper-param configs in C ([c7ed1d4](https://github.com/unum-cloud/usearch/commit/c7ed1d4f6e1cabbe80b6f016863ae9bd9c311260))
* Metadata extraction in C ([2c698cd](https://github.com/unum-cloud/usearch/commit/2c698cd187c5dda1a313966bd71a77231bf1e3bf))
* Guides for Rust and C ([fe05ad8](https://github.com/unum-cloud/usearch/commit/fe05ad8516ebf6c0388c2cd14f5583e28f41a0ba))
* `-Wdeprecated-this-capture` (387) ([a233e20](https://github.com/unum-cloud/usearch/commit/a233e2084af903cb300c93c4d52f6dc2cdf9553b)), closes [#387](https://github.com/unum-cloud/usearch/issues/387)
* Explicit capture ([208e383](https://github.com/unum-cloud/usearch/commit/208e383c12b06fae783c7a15290c4f6100fb3718))
* Filter the entry point in the 0 layer ([4ff568b](https://github.com/unum-cloud/usearch/commit/4ff568b2322e1fc0ae20151a63d616f5f966007d))
* JS imports & Doxygen (384) ([7356158](https://github.com/unum-cloud/usearch/commit/7356158d62e2a290cc1edba55912895f0658adf9)), closes [#384](https://github.com/unum-cloud/usearch/issues/384)
* More adequate default Rust params ([c4f9e65](https://github.com/unum-cloud/usearch/commit/c4f9e6559b4037add0bd8de589de67f24003a303))
* `metric_punned_t` static methods ([220ef57](https://github.com/unum-cloud/usearch/commit/220ef572e6c42f6fa0e5cc6f144a8c2669949673))
* Configure Rust compilation options ([32c9f3b](https://github.com/unum-cloud/usearch/commit/32c9f3b12c516884685eaa451b4fc23a93e4e325)), closes [#378](https://github.com/unum-cloud/usearch/issues/378)
* Include sources in Crates ([0d414e4](https://github.com/unum-cloud/usearch/commit/0d414e46e6be0a816e30ec2cc9c4bd435d014da7))