usearch 0.19.2 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,7 @@ index.add(16, new Float32Array([10, 25]))
11
11
  assert.equal(index.size(), 2)
12
12
 
13
13
  var results = index.search(new Float32Array([13, 14]), 2)
14
- assert.deepEqual(results.labels, new Uint32Array([15, 16]))
14
+ assert.deepEqual(results.labels, new BigUint64Array([15n, 16n]))
15
15
  assert.deepEqual(results.distances, new Float32Array([45, 130]))
16
16
 
17
17
  console.log('JavaScript tests passed!')
@@ -8,12 +8,15 @@
8
8
  using namespace unum::usearch;
9
9
  using namespace unum;
10
10
 
11
+ using metric_t = index_punned_dense_metric_t;
11
12
  using distance_t = punned_distance_t;
12
- using punned_t = index_punned_dense_gt<UInt32>;
13
- using add_result_t = punned_t::add_result_t;
14
- using search_result_t = punned_t::search_result_t;
15
- using serialization_result_t = punned_t::serialization_result_t;
16
- using shared_index_t = std::shared_ptr<punned_t>;
13
+ using index_t = punned_small_t;
14
+ using add_result_t = typename index_t::add_result_t;
15
+ using search_result_t = typename index_t::search_result_t;
16
+ using serialization_result_t = typename index_t::serialization_result_t;
17
+ using label_t = typename index_t::label_t;
18
+ using id_t = typename index_t::id_t;
19
+ using shared_index_t = std::shared_ptr<index_t>;
17
20
 
18
21
  metric_kind_t to_native_metric(USearchMetric m) {
19
22
  switch (m) {
@@ -117,11 +120,11 @@ scalar_kind_t to_native_scalar(USearchScalar m) {
117
120
  index_config_t config;
118
121
 
119
122
  config.connectivity = static_cast<std::size_t>(connectivity);
120
- shared_index_t ptr = std::make_shared<punned_t>(punned_t::make(dims, to_native_metric(metric), config, to_native_scalar(quantization)));
123
+ shared_index_t ptr = std::make_shared<index_t>(index_t::make(dims, to_native_metric(metric), config, to_native_scalar(quantization)));
121
124
  return [[USearchIndex alloc] initWithIndex:ptr];
122
125
  }
123
126
 
124
- - (void)addSingle:(UInt32)label
127
+ - (void)addSingle:(USearchLabel)label
125
128
  vector:(Float32 const *_Nonnull)vector {
126
129
  add_result_t result = _native->add(label, vector);
127
130
 
@@ -134,7 +137,7 @@ scalar_kind_t to_native_scalar(USearchScalar m) {
134
137
 
135
138
  - (UInt32)searchSingle:(Float32 const *_Nonnull)vector
136
139
  count:(UInt32)wanted
137
- labels:(UInt32 *_Nullable)labels
140
+ labels:(USearchLabel *_Nullable)labels
138
141
  distances:(Float32 *_Nullable)distances {
139
142
  search_result_t result = _native->search(vector, static_cast<std::size_t>(wanted));
140
143
 
@@ -148,7 +151,7 @@ scalar_kind_t to_native_scalar(USearchScalar m) {
148
151
  return static_cast<UInt32>(found);
149
152
  }
150
153
 
151
- - (void)addDouble:(UInt32)label
154
+ - (void)addDouble:(USearchLabel)label
152
155
  vector:(Float64 const *_Nonnull)vector {
153
156
  add_result_t result = _native->add(label, (f64_t const *)vector);
154
157
 
@@ -161,7 +164,7 @@ scalar_kind_t to_native_scalar(USearchScalar m) {
161
164
 
162
165
  - (UInt32)searchDouble:(Float64 const *_Nonnull)vector
163
166
  count:(UInt32)wanted
164
- labels:(UInt32 *_Nullable)labels
167
+ labels:(USearchLabel *_Nullable)labels
165
168
  distances:(Float32 *_Nullable)distances {
166
169
  search_result_t result = _native->search((f64_t const *)vector, static_cast<std::size_t>(wanted));
167
170
 
@@ -175,7 +178,7 @@ scalar_kind_t to_native_scalar(USearchScalar m) {
175
178
  return static_cast<UInt32>(found);
176
179
  }
177
180
 
178
- - (void)addHalf:(UInt32)label
181
+ - (void)addHalf:(USearchLabel)label
179
182
  vector:(void const *_Nonnull)vector {
180
183
  add_result_t result = _native->add(label, (f16_t const *)vector);
181
184
 
@@ -188,7 +191,7 @@ scalar_kind_t to_native_scalar(USearchScalar m) {
188
191
 
189
192
  - (UInt32)searchHalf:(void const *_Nonnull)vector
190
193
  count:(UInt32)wanted
191
- labels:(UInt32 *_Nullable)labels
194
+ labels:(USearchLabel *_Nullable)labels
192
195
  distances:(Float32 *_Nullable)distances {
193
196
  search_result_t result = _native->search((f16_t const *)vector, static_cast<std::size_t>(wanted));
194
197
 
@@ -25,7 +25,7 @@ typedef NS_ENUM(NSUInteger, USearchMetric) {
25
25
  USearchMetricSorensen
26
26
  };
27
27
 
28
- typedef UInt32 USearchLabel;
28
+ typedef UInt64 USearchLabel;
29
29
 
30
30
  API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0))
31
31
  @interface USearchIndex : NSObject
@@ -80,7 +80,7 @@ API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0))
80
80
  * @brief Adds a labeled vector to the index.
81
81
  * @param vector Double-precision vector.
82
82
  */
83
- - (void)addDouble:(UInt32)label
83
+ - (void)addDouble:(USearchLabel)label
84
84
  vector:(Float64 const *_Nonnull)vector NS_SWIFT_NAME(addDouble(label:vector:));
85
85
 
86
86
  /**
@@ -100,7 +100,7 @@ API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0))
100
100
  * @brief Adds a labeled vector to the index.
101
101
  * @param vector Half-precision vector.
102
102
  */
103
- - (void)addHalf:(UInt32)label
103
+ - (void)addHalf:(USearchLabel)label
104
104
  vector:(void const *_Nonnull)vector NS_SWIFT_NAME(addHalf(label:vector:));
105
105
 
106
106
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "0.19.2",
3
+ "version": "0.20.0",
4
4
  "description": "Smaller & Faster Single-File Vector Search Engine from Unum",
5
5
  "author": "Ashot Vardanian",
6
6
  "license": "Apache 2.0",
@@ -24,6 +24,6 @@
24
24
  "@semantic-release/exec": "^6.0.3",
25
25
  "@semantic-release/git": "^10.0.1",
26
26
  "conventional-changelog-eslint": "^3.0.9",
27
- "semantic-release": "^21.0.6"
27
+ "semantic-release": "^21.0.7"
28
28
  }
29
29
  }
package/python/lib.cpp CHANGED
@@ -12,11 +12,10 @@
12
12
  *
13
13
  * @copyright Copyright (c) 2023
14
14
  */
15
- #define PY_SSIZE_T_CLEAN
16
- #define NOMINMAX // Some of our dependencies call `std::max(x, y)`, which crashes Windows builds
17
15
  #include <limits> // `std::numeric_limits`
18
16
  #include <thread> // `std::thread`
19
17
 
18
+ #define PY_SSIZE_T_CLEAN
20
19
  #include <pybind11/numpy.h>
21
20
  #include <pybind11/pybind11.h>
22
21
 
@@ -38,26 +37,23 @@ enum class metric_signature_t {
38
37
 
39
38
  namespace py = pybind11;
40
39
  using py_shape_t = py::array::ShapeContainer;
41
-
42
- using label_t = std::uint32_t;
43
- using distance_t = punned_distance_t;
40
+ using label_t = typename punned_small_t::label_t;
41
+ using id_t = typename punned_small_t::id_t;
44
42
  using metric_t = index_punned_dense_metric_t;
45
- using id_t = std::uint32_t;
46
- using big_id_t = std::uint64_t;
47
-
48
- using punned_index_t = index_punned_dense_gt<label_t, id_t>;
49
- using punned_add_result_t = typename punned_index_t::add_result_t;
50
- using punned_search_result_t = typename punned_index_t::search_result_t;
43
+ using distance_t = punned_distance_t;
44
+ using dense_index_t = punned_small_t;
45
+ using dense_add_result_t = typename dense_index_t::add_result_t;
46
+ using dense_search_result_t = typename dense_index_t::search_result_t;
51
47
 
52
- struct punned_index_py_t : public punned_index_t {
53
- using native_t = punned_index_t;
48
+ struct dense_index_py_t : public dense_index_t {
49
+ using native_t = dense_index_t;
54
50
  using native_t::add;
55
51
  using native_t::capacity;
56
52
  using native_t::reserve;
57
53
  using native_t::search;
58
54
  using native_t::size;
59
55
 
60
- punned_index_py_t(native_t&& base) : native_t(std::move(base)) {}
56
+ dense_index_py_t(native_t&& base) : native_t(std::move(base)) {}
61
57
  };
62
58
 
63
59
  using set_member_t = std::uint32_t;
@@ -121,7 +117,7 @@ metric_t udf(metric_kind_t kind, metric_signature_t signature, std::uintptr_t me
121
117
  }
122
118
  }
123
119
 
124
- static punned_index_py_t make_index( //
120
+ static dense_index_py_t make_index( //
125
121
  std::size_t dimensions, //
126
122
  scalar_kind_t scalar_kind, //
127
123
  metric_kind_t metric_kind, //
@@ -136,14 +132,14 @@ static punned_index_py_t make_index( //
136
132
  config.connectivity = connectivity;
137
133
 
138
134
  if (tune)
139
- config = punned_index_t::optimize(config);
135
+ config = dense_index_t::optimize(config);
140
136
 
141
137
  if (metric_uintptr)
142
- return punned_index_t::make( //
138
+ return dense_index_t::make( //
143
139
  dimensions, udf(metric_kind, metric_signature, metric_uintptr, scalar_kind), config, scalar_kind,
144
140
  expansion_add, expansion_search);
145
141
  else
146
- return punned_index_t::make(dimensions, metric_kind, config, scalar_kind, expansion_add, expansion_search);
142
+ return dense_index_t::make(dimensions, metric_kind, config, scalar_kind, expansion_add, expansion_search);
147
143
  }
148
144
 
149
145
  static std::unique_ptr<sparse_index_py_t> make_sparse_index( //
@@ -173,7 +169,7 @@ scalar_kind_t numpy_string_to_kind(std::string const& name) {
173
169
  return scalar_kind_t::unknown_k;
174
170
  }
175
171
 
176
- static void add_one_to_index(punned_index_py_t& index, label_t label, py::buffer vector, bool copy, std::size_t) {
172
+ static void add_one_to_index(dense_index_py_t& index, label_t label, py::buffer vector, bool copy, std::size_t) {
177
173
 
178
174
  py::buffer_info vector_info = vector.request();
179
175
  if (vector_info.ndim != 1)
@@ -203,7 +199,7 @@ static void add_one_to_index(punned_index_py_t& index, label_t label, py::buffer
203
199
 
204
200
  template <typename scalar_at>
205
201
  static void add_typed_to_index( //
206
- punned_index_py_t& index, //
202
+ dense_index_py_t& index, //
207
203
  py::buffer_info const& labels_info, py::buffer_info const& vectors_info, //
208
204
  bool copy, std::size_t threads) {
209
205
 
@@ -223,8 +219,8 @@ static void add_typed_to_index( //
223
219
  });
224
220
  }
225
221
 
226
- static void add_many_to_index( //
227
- punned_index_py_t& index, py::buffer labels, py::buffer vectors, //
222
+ static void add_many_to_index( //
223
+ dense_index_py_t& index, py::buffer labels, py::buffer vectors, //
228
224
  bool copy, std::size_t threads) {
229
225
 
230
226
  if (index.limits().threads_add < threads)
@@ -265,7 +261,7 @@ static void add_many_to_index( //
265
261
  }
266
262
  }
267
263
 
268
- static py::tuple search_one_in_index(punned_index_py_t& index, py::buffer vector, std::size_t wanted, bool exact) {
264
+ static py::tuple search_one_in_index(dense_index_py_t& index, py::buffer vector, std::size_t wanted, bool exact) {
269
265
 
270
266
  py::buffer_info vector_info = vector.request();
271
267
  Py_ssize_t vector_dimensions = vector_info.shape[0];
@@ -282,7 +278,7 @@ static py::tuple search_one_in_index(punned_index_py_t& index, py::buffer vector
282
278
  search_config_t config;
283
279
  config.exact = exact;
284
280
 
285
- auto raise_and_dump = [&](punned_search_result_t result) {
281
+ auto raise_and_dump = [&](dense_search_result_t result) {
286
282
  result.error.raise();
287
283
  count = result.dump_to(&labels_py1d(0), &distances_py1d(0));
288
284
  };
@@ -308,9 +304,9 @@ static py::tuple search_one_in_index(punned_index_py_t& index, py::buffer vector
308
304
  }
309
305
 
310
306
  template <typename scalar_at>
311
- static void search_typed( //
312
- punned_index_py_t& index, py::buffer_info& vectors_info, //
313
- std::size_t wanted, bool exact, std::size_t threads, //
307
+ static void search_typed( //
308
+ dense_index_py_t& index, py::buffer_info& vectors_info, //
309
+ std::size_t wanted, bool exact, std::size_t threads, //
314
310
  py::array_t<label_t>& labels_py, py::array_t<distance_t>& distances_py, py::array_t<Py_ssize_t>& counts_py) {
315
311
 
316
312
  auto labels_py2d = labels_py.template mutable_unchecked<2>();
@@ -325,7 +321,7 @@ static void search_typed( //
325
321
  config.thread = thread_idx;
326
322
  config.exact = exact;
327
323
  scalar_at const* vector = (scalar_at const*)(vectors_data + task_idx * vectors_info.strides[0]);
328
- punned_search_result_t result = index.search(vector, wanted, config);
324
+ dense_search_result_t result = index.search(vector, wanted, config);
329
325
  result.error.raise();
330
326
  counts_py1d(task_idx) =
331
327
  static_cast<Py_ssize_t>(result.dump_to(&labels_py2d(task_idx, 0), &distances_py2d(task_idx, 0)));
@@ -344,7 +340,7 @@ static void search_typed( //
344
340
  * 3. array with match counts.
345
341
  */
346
342
  static py::tuple search_many_in_index( //
347
- punned_index_py_t& index, py::buffer vectors, std::size_t wanted, bool exact, std::size_t threads) {
343
+ dense_index_py_t& index, py::buffer vectors, std::size_t wanted, bool exact, std::size_t threads) {
348
344
 
349
345
  if (wanted == 0)
350
346
  return py::tuple(3);
@@ -591,7 +587,7 @@ PYBIND11_MODULE(compiled, m) {
591
587
  h.def_readonly("bytes_for_vectors", &file_head_result_t::bytes_for_vectors);
592
588
  h.def_readonly("bytes_checksum", &file_head_result_t::bytes_checksum);
593
589
 
594
- auto i = py::class_<punned_index_py_t>(m, "Index");
590
+ auto i = py::class_<dense_index_py_t>(m, "Index");
595
591
 
596
592
  i.def(py::init(&make_index), //
597
593
  py::kw_only(), //
@@ -632,30 +628,29 @@ PYBIND11_MODULE(compiled, m) {
632
628
  py::arg("threads") = 0 //
633
629
  );
634
630
 
635
- i.def("__len__", &punned_index_py_t::size);
636
- i.def_property_readonly("size", &punned_index_py_t::size);
637
- i.def_property_readonly("ndim", &punned_index_py_t::dimensions);
638
- i.def_property_readonly("connectivity", &punned_index_py_t::connectivity);
639
- i.def_property_readonly("capacity", &punned_index_py_t::capacity);
631
+ i.def("__len__", &dense_index_py_t::size);
632
+ i.def_property_readonly("size", &dense_index_py_t::size);
633
+ i.def_property_readonly("ndim", &dense_index_py_t::dimensions);
634
+ i.def_property_readonly("connectivity", &dense_index_py_t::connectivity);
635
+ i.def_property_readonly("capacity", &dense_index_py_t::capacity);
640
636
  i.def_property_readonly( //
641
- "dtype", [](punned_index_py_t const& index) -> scalar_kind_t { return index.metric().scalar_kind_; });
637
+ "dtype", [](dense_index_py_t const& index) -> scalar_kind_t { return index.metric().scalar_kind_; });
642
638
  i.def_property_readonly( //
643
- "memory_usage", [](punned_index_py_t const& index) -> std::size_t { return index.memory_usage(); },
639
+ "memory_usage", [](dense_index_py_t const& index) -> std::size_t { return index.memory_usage(); },
644
640
  py::call_guard<py::gil_scoped_release>());
645
641
 
646
- i.def_property("expansion_add", &punned_index_py_t::expansion_add, &punned_index_py_t::change_expansion_add);
647
- i.def_property("expansion_search", &punned_index_py_t::expansion_search,
648
- &punned_index_py_t::change_expansion_search);
642
+ i.def_property("expansion_add", &dense_index_py_t::expansion_add, &dense_index_py_t::change_expansion_add);
643
+ i.def_property("expansion_search", &dense_index_py_t::expansion_search, &dense_index_py_t::change_expansion_search);
649
644
 
650
- i.def_property_readonly("labels", &get_all_labels<punned_index_py_t>);
651
- i.def("get_labels", &get_labels<punned_index_py_t>, py::arg("limit") = std::numeric_limits<std::size_t>::max());
652
- i.def("__contains__", &punned_index_py_t::contains);
653
- i.def("__getitem__", &get_member<punned_index_py_t>, py::arg("label"), py::arg("dtype") = scalar_kind_t::f32_k);
645
+ i.def_property_readonly("labels", &get_all_labels<dense_index_py_t>);
646
+ i.def("get_labels", &get_labels<dense_index_py_t>, py::arg("limit") = std::numeric_limits<std::size_t>::max());
647
+ i.def("__contains__", &dense_index_py_t::contains);
648
+ i.def("__getitem__", &get_member<dense_index_py_t>, py::arg("label"), py::arg("dtype") = scalar_kind_t::f32_k);
654
649
 
655
- i.def("save", &save_index<punned_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
656
- i.def("load", &load_index<punned_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
657
- i.def("view", &view_index<punned_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
658
- i.def("clear", &punned_index_py_t::clear, py::call_guard<py::gil_scoped_release>());
650
+ i.def("save", &save_index<dense_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
651
+ i.def("load", &load_index<dense_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
652
+ i.def("view", &view_index<dense_index_py_t>, py::arg("path"), py::call_guard<py::gil_scoped_release>());
653
+ i.def("clear", &dense_index_py_t::clear, py::call_guard<py::gil_scoped_release>());
659
654
 
660
655
  auto si = py::class_<sparse_index_py_t>(m, "SparseIndex");
661
656
 
@@ -31,7 +31,7 @@ MetricKindBitwise = (
31
31
 
32
32
  SparseIndex = _CompiledSetsIndex
33
33
 
34
- Label = np.uint32
34
+ Label = np.uint64
35
35
 
36
36
 
37
37
  def _normalize_dtype(dtype, metric: MetricKind = MetricKind.IP) -> ScalarKind:
package/rust/lib.cpp CHANGED
@@ -4,14 +4,14 @@
4
4
  using namespace unum::usearch;
5
5
  using namespace unum;
6
6
 
7
- using punned_t = typename Index::punned_t;
8
- using add_result_t = typename punned_t::add_result_t;
9
- using search_result_t = typename punned_t::search_result_t;
10
- using serialization_result_t = typename punned_t::serialization_result_t;
7
+ using index_t = typename Index::index_t;
8
+ using add_result_t = typename index_t::add_result_t;
9
+ using search_result_t = typename index_t::search_result_t;
10
+ using serialization_result_t = typename index_t::serialization_result_t;
11
11
 
12
- Index::Index(std::unique_ptr<punned_t> index) : index_(std::move(index)) {}
12
+ Index::Index(std::unique_ptr<index_t> index) : index_(std::move(index)) {}
13
13
 
14
- void Index::add_in_thread(uint32_t label, rust::Slice<float const> vector, size_t thread) const {
14
+ void Index::add_in_thread(label_t label, rust::Slice<float const> vector, size_t thread) const {
15
15
  add_config_t config;
16
16
  config.thread = thread;
17
17
  index_->add(label, vector.data(), config).error.raise();
@@ -33,7 +33,7 @@ Matches Index::search_in_thread(rust::Slice<float const> vector, size_t count, s
33
33
  return matches;
34
34
  }
35
35
 
36
- void Index::add(uint32_t label, rust::Slice<float const> vector) const {
36
+ void Index::add(label_t label, rust::Slice<float const> vector) const {
37
37
  index_->add(label, vector.data()).error.raise();
38
38
  }
39
39
 
@@ -64,9 +64,9 @@ void Index::view(rust::Str path) const { index_->view(std::string(path).c_str())
64
64
 
65
65
  scalar_kind_t accuracy(rust::Str quant) { return scalar_kind_from_name(quant.data(), quant.size()); }
66
66
 
67
- std::unique_ptr<Index> wrap(punned_t&& index) {
68
- std::unique_ptr<punned_t> punned_ptr;
69
- punned_ptr.reset(new punned_t(std::move(index)));
67
+ std::unique_ptr<Index> wrap(index_t&& index) {
68
+ std::unique_ptr<index_t> punned_ptr;
69
+ punned_ptr.reset(new index_t(std::move(index)));
70
70
  std::unique_ptr<Index> result;
71
71
  result.reset(new Index(std::move(punned_ptr)));
72
72
  return result;
@@ -104,7 +104,7 @@ scalar_kind_t rust_to_cpp_scalar(ScalarKind value) {
104
104
  }
105
105
 
106
106
  std::unique_ptr<Index> new_index(IndexOptions const& options) {
107
- return wrap(punned_t::make(options.dimensions, rust_to_cpp_metric(options.metric), config(options.connectivity),
108
- rust_to_cpp_scalar(options.quantization), options.expansion_add,
109
- options.expansion_search));
107
+ return wrap(index_t::make(options.dimensions, rust_to_cpp_metric(options.metric), config(options.connectivity),
108
+ rust_to_cpp_scalar(options.quantization), options.expansion_add,
109
+ options.expansion_search));
110
110
  }
package/rust/lib.hpp CHANGED
@@ -10,16 +10,20 @@ struct IndexOptions;
10
10
 
11
11
  class Index {
12
12
  public:
13
- using label_t = std::uint32_t;
13
+ using metric_t = unum::usearch::index_punned_dense_metric_t;
14
14
  using distance_t = unum::usearch::punned_distance_t;
15
- using punned_t = unum::usearch::index_punned_dense_gt<label_t>;
15
+ using index_t = unum::usearch::punned_small_t;
16
+ using add_result_t = typename index_t::add_result_t;
17
+ using search_result_t = typename index_t::search_result_t;
18
+ using label_t = typename index_t::label_t;
19
+ using id_t = typename index_t::id_t;
16
20
 
17
- Index(std::unique_ptr<punned_t> index);
21
+ Index(std::unique_ptr<index_t> index);
18
22
 
19
23
  void reserve(size_t) const;
20
24
 
21
- void add(uint32_t label, rust::Slice<float const> vector) const;
22
- void add_in_thread(uint32_t label, rust::Slice<float const> vector, size_t thread) const;
25
+ void add(label_t label, rust::Slice<float const> vector) const;
26
+ void add_in_thread(label_t label, rust::Slice<float const> vector, size_t thread) const;
23
27
 
24
28
  Matches search(rust::Slice<float const> vector, size_t count) const;
25
29
  Matches search_in_thread(rust::Slice<float const> vector, size_t count, size_t thread) const;
@@ -34,7 +38,7 @@ class Index {
34
38
  void view(rust::Str path) const;
35
39
 
36
40
  private:
37
- std::unique_ptr<punned_t> index_;
41
+ std::unique_ptr<index_t> index_;
38
42
  };
39
43
 
40
44
  std::unique_ptr<Index> new_index(IndexOptions const& options);
package/rust/lib.rs CHANGED
@@ -4,7 +4,7 @@ pub mod ffi {
4
4
  // Shared structs with fields visible to both languages.
5
5
  struct Matches {
6
6
  count: usize,
7
- labels: Vec<u32>,
7
+ labels: Vec<u64>,
8
8
  distances: Vec<f32>,
9
9
  }
10
10
 
@@ -51,7 +51,7 @@ pub mod ffi {
51
51
  pub fn size(self: &Index) -> usize;
52
52
  pub fn capacity(self: &Index) -> usize;
53
53
 
54
- pub fn add(self: &Index, label: u32, vector: &[f32]) -> Result<()>;
54
+ pub fn add(self: &Index, label: u64, vector: &[f32]) -> Result<()>;
55
55
  pub fn search(self: &Index, query: &[f32], count: usize) -> Result<Matches>;
56
56
 
57
57
  pub fn save(self: &Index, path: &str) -> Result<()>;
@@ -7,11 +7,15 @@
7
7
 
8
8
  @available(iOS 13, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
9
9
  extension USearchIndex {
10
+ public typealias Label = USearchLabel
11
+ public typealias Metric = USearchMetric
12
+ public typealias Scalar = USearchScalar
13
+
10
14
  /// Adds a labeled vector to the index.
11
15
  /// - Parameter label: Unique identifer for that object.
12
16
  /// - Parameter vector: Single-precision vector.
13
17
  /// - Throws: If runs out of memory.
14
- public func add(label: UInt32, vector: ArraySlice<Float32>) {
18
+ public func add(label: USearchLabel, vector: ArraySlice<Float32>) {
15
19
  vector.withContiguousStorageIfAvailable {
16
20
  addSingle(label: label, vector: $0.baseAddress!)
17
21
  }
@@ -23,8 +27,8 @@ extension USearchIndex {
23
27
  /// - Parameter count: Upper limit on the number of matches to retrieve.
24
28
  /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
25
29
  /// - Throws: If runs out of memory.
26
- public func search(vector: ArraySlice<Float32>, count: Int) -> ([UInt32], [Float]) {
27
- var matches: [UInt32] = Array(repeating: 0, count: count)
30
+ public func search(vector: ArraySlice<Float32>, count: Int) -> ([Label], [Float]) {
31
+ var matches: [Label] = Array(repeating: 0, count: count)
28
32
  var distances: [Float] = Array(repeating: 0, count: count)
29
33
  let results = vector.withContiguousStorageIfAvailable {
30
34
  searchSingle(vector: $0.baseAddress!, count: CUnsignedInt(count), labels: &matches, distances: &distances)
@@ -38,7 +42,7 @@ extension USearchIndex {
38
42
  /// - Parameter label: Unique identifer for that object.
39
43
  /// - Parameter vector: Double-precision vector.
40
44
  /// - Throws: If runs out of memory.
41
- public func add(label: UInt32, vector: ArraySlice<Float64>) {
45
+ public func add(label: Label, vector: ArraySlice<Float64>) {
42
46
  vector.withContiguousStorageIfAvailable {
43
47
  addDouble(label: label, vector: $0.baseAddress!)
44
48
  }
@@ -49,8 +53,8 @@ extension USearchIndex {
49
53
  /// - Parameter count: Upper limit on the number of matches to retrieve.
50
54
  /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
51
55
  /// - Throws: If runs out of memory.
52
- public func search(vector: ArraySlice<Float64>, count: Int) -> ([UInt32], [Float]) {
53
- var matches: [UInt32] = Array(repeating: 0, count: count)
56
+ public func search(vector: ArraySlice<Float64>, count: Int) -> ([Label], [Float]) {
57
+ var matches: [Label] = Array(repeating: 0, count: count)
54
58
  var distances: [Float] = Array(repeating: 0, count: count)
55
59
  let results = vector.withContiguousStorageIfAvailable {
56
60
  searchDouble(vector: $0.baseAddress!, count: CUnsignedInt(count), labels: &matches, distances: &distances)
@@ -67,7 +71,7 @@ extension USearchIndex {
67
71
  /// - Parameter vector: Half-precision vector.
68
72
  /// - Throws: If runs out of memory.
69
73
  @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
70
- public func add(label: UInt32, vector: ArraySlice<Float16>) {
74
+ public func add(label: Label, vector: ArraySlice<Float16>) {
71
75
  vector.withContiguousStorageIfAvailable { buffer in
72
76
  addHalf(label: label, vector: buffer.baseAddress!)
73
77
  }
@@ -79,8 +83,8 @@ extension USearchIndex {
79
83
  /// - Returns: Labels and distances to closest approximate matches in decreasing similarity order.
80
84
  /// - Throws: If runs out of memory.
81
85
  @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
82
- public func search(vector: ArraySlice<Float16>, count: Int) -> ([UInt32], [Float]) {
83
- var matches: [UInt32] = Array(repeating: 0, count: count)
86
+ public func search(vector: ArraySlice<Float16>, count: Int) -> ([Label], [Float]) {
87
+ var matches: [Label] = Array(repeating: 0, count: count)
84
88
  var distances: [Float] = Array(repeating: 0, count: count)
85
89
  let results = vector.withContiguousStorageIfAvailable {
86
90
  searchHalf(vector: $0.baseAddress!, count: CUnsignedInt(count), labels: &matches, distances: &distances)