usearch 2.15.0 → 2.15.1

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.
package/README.md CHANGED
@@ -544,7 +544,7 @@ doi = {10.5281/zenodo.7949416},
544
544
  author = {Vardanian, Ash},
545
545
  title = {{USearch by Unum Cloud}},
546
546
  url = {https://github.com/unum-cloud/usearch},
547
- version = {2.15.0},
547
+ version = {2.15.1},
548
548
  year = {2023},
549
549
  month = oct,
550
550
  }
@@ -9,7 +9,7 @@
9
9
 
10
10
  #define USEARCH_VERSION_MAJOR 2
11
11
  #define USEARCH_VERSION_MINOR 15
12
- #define USEARCH_VERSION_PATCH 0
12
+ #define USEARCH_VERSION_PATCH 1
13
13
 
14
14
  // Inferring C++ version
15
15
  // https://stackoverflow.com/a/61552074
@@ -139,6 +139,9 @@ enum class scalar_kind_t : std::uint8_t {
139
139
  i8_k = 23,
140
140
  };
141
141
 
142
+ /**
143
+ * @brief Maps a scalar type to its corresponding scalar_kind_t enumeration value.
144
+ */
142
145
  template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
143
146
  if (std::is_same<scalar_at, b1x8_t>())
144
147
  return scalar_kind_t::b1x8_k;
@@ -175,22 +178,43 @@ template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
175
178
  return scalar_kind_t::unknown_k;
176
179
  }
177
180
 
181
+ /**
182
+ * @brief Converts an angle from degrees to radians.
183
+ */
178
184
  template <typename at> at angle_to_radians(at angle) noexcept { return angle * at(3.14159265358979323846) / at(180); }
179
185
 
186
+ /**
187
+ * @brief Readability helper to compute the square of a given value.
188
+ */
180
189
  template <typename at> at square(at value) noexcept { return value * value; }
181
190
 
191
+ /**
192
+ * @brief Clamps a value between a lower and upper bound using a custom comparator. Similar to `std::clamp`.
193
+ * https://en.cppreference.com/w/cpp/algorithm/clamp
194
+ */
182
195
  template <typename at, typename compare_at> inline at clamp(at v, at lo, at hi, compare_at comp) noexcept {
183
196
  return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
184
197
  }
198
+
199
+ /**
200
+ * @brief Clamps a value between a lower and upper bound. Similar to `std::clamp`.
201
+ * https://en.cppreference.com/w/cpp/algorithm/clamp
202
+ */
185
203
  template <typename at> inline at clamp(at v, at lo, at hi) noexcept {
186
204
  return usearch::clamp(v, lo, hi, std::less<at>{});
187
205
  }
188
206
 
189
- inline bool str_equals(char const* begin, std::size_t len, char const* other_begin) noexcept {
190
- std::size_t other_len = std::strlen(other_begin);
191
- return len == other_len && std::strncmp(begin, other_begin, len) == 0;
207
+ /**
208
+ * @brief Compares two strings for equality, given a length for the first string.
209
+ */
210
+ inline bool str_equals(char const* first_begin, std::size_t first_len, char const* second_begin) noexcept {
211
+ std::size_t second_len = std::strlen(second_begin);
212
+ return first_len == second_len && std::strncmp(first_begin, second_begin, first_len) == 0;
192
213
  }
193
214
 
215
+ /**
216
+ * @brief Returns the number of bits required to represent a scalar type.
217
+ */
194
218
  inline std::size_t bits_per_scalar(scalar_kind_t scalar_kind) noexcept {
195
219
  switch (scalar_kind) {
196
220
  case scalar_kind_t::uuid_k: return 128;
@@ -213,6 +237,10 @@ inline std::size_t bits_per_scalar(scalar_kind_t scalar_kind) noexcept {
213
237
  }
214
238
  }
215
239
 
240
+ /**
241
+ * @brief Returns the number of bits in a scalar word for a given scalar type.
242
+ * Equivalent to `bits_per_scalar` for types that are not bit-packed.
243
+ */
216
244
  inline std::size_t bits_per_scalar_word(scalar_kind_t scalar_kind) noexcept {
217
245
  switch (scalar_kind) {
218
246
  case scalar_kind_t::uuid_k: return 128;
@@ -235,6 +263,9 @@ inline std::size_t bits_per_scalar_word(scalar_kind_t scalar_kind) noexcept {
235
263
  }
236
264
  }
237
265
 
266
+ /**
267
+ * @brief Returns the string name of a given scalar type.
268
+ */
238
269
  inline char const* scalar_kind_name(scalar_kind_t scalar_kind) noexcept {
239
270
  switch (scalar_kind) {
240
271
  case scalar_kind_t::uuid_k: return "uuid";
@@ -257,6 +288,9 @@ inline char const* scalar_kind_name(scalar_kind_t scalar_kind) noexcept {
257
288
  }
258
289
  }
259
290
 
291
+ /**
292
+ * @brief Returns the string name of a given distance metric.
293
+ */
260
294
  inline char const* metric_kind_name(metric_kind_t metric) noexcept {
261
295
  switch (metric) {
262
296
  case metric_kind_t::unknown_k: return "unknown";
@@ -273,6 +307,10 @@ inline char const* metric_kind_name(metric_kind_t metric) noexcept {
273
307
  default: return "";
274
308
  }
275
309
  }
310
+
311
+ /**
312
+ * @brief Parses a string to identify the corresponding `scalar_kind_t` enumeration value.
313
+ */
276
314
  inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name, std::size_t len) {
277
315
  expected_gt<scalar_kind_t> parsed;
278
316
  if (str_equals(name, len, "f32"))
@@ -292,10 +330,16 @@ inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name, std::s
292
330
  return parsed;
293
331
  }
294
332
 
333
+ /**
334
+ * @brief Parses a string to identify the corresponding `scalar_kind_t` enumeration value.
335
+ */
295
336
  inline expected_gt<scalar_kind_t> scalar_kind_from_name(char const* name) {
296
337
  return scalar_kind_from_name(name, std::strlen(name));
297
338
  }
298
339
 
340
+ /**
341
+ * @brief Parses a string to identify the corresponding `metric_kind_t` enumeration value.
342
+ */
299
343
  inline expected_gt<metric_kind_t> metric_from_name(char const* name, std::size_t len) {
300
344
  expected_gt<metric_kind_t> parsed;
301
345
  if (str_equals(name, len, "l2sq") || str_equals(name, len, "euclidean_sq")) {
@@ -321,6 +365,10 @@ inline expected_gt<metric_kind_t> metric_from_name(char const* name, std::size_t
321
365
  "tanimoto, sorensen");
322
366
  return parsed;
323
367
  }
368
+
369
+ /**
370
+ * @brief Parses a string to identify the corresponding `metric_kind_t` enumeration value.
371
+ */
324
372
  inline expected_gt<metric_kind_t> metric_from_name(char const* name) {
325
373
  return metric_from_name(name, std::strlen(name));
326
374
  }
@@ -417,7 +465,7 @@ class f16_bits_t {
417
465
  inline f16_bits_t(float v) noexcept : uint16_(f32_to_f16(v)) {}
418
466
  inline f16_bits_t(double v) noexcept : uint16_(f32_to_f16(static_cast<float>(v))) {}
419
467
 
420
- inline bool operator<(const f16_bits_t& other) const noexcept { return float(*this) < float(other); }
468
+ inline bool operator<(f16_bits_t const& other) const noexcept { return float(*this) < float(other); }
421
469
 
422
470
  inline f16_bits_t operator+(f16_bits_t other) const noexcept { return {float(*this) + float(other)}; }
423
471
  inline f16_bits_t operator-(f16_bits_t other) const noexcept { return {float(*this) - float(other)}; }
@@ -1419,7 +1467,10 @@ template <typename scalar_at = float, typename result_at = float> struct metric_
1419
1467
  }
1420
1468
  };
1421
1469
 
1422
- struct cos_i8_t {
1470
+ /**
1471
+ * @brief Cosine (Angular) distance for signed 8-bit integers using 16-bit intermediates.
1472
+ */
1473
+ struct metric_cos_i8_t {
1423
1474
  using scalar_t = i8_t;
1424
1475
  using result_t = f32_t;
1425
1476
 
@@ -1445,7 +1496,11 @@ struct cos_i8_t {
1445
1496
  }
1446
1497
  };
1447
1498
 
1448
- struct l2sq_i8_t {
1499
+ /**
1500
+ * @brief Squared Euclidean (L2) distance for signed 8-bit integers using 16-bit intermediates.
1501
+ * Square root is avoided at the end, as it won't affect the ordering.
1502
+ */
1503
+ struct metric_l2sq_i8_t {
1449
1504
  using scalar_t = i8_t;
1450
1505
  using result_t = f32_t;
1451
1506
 
@@ -1775,7 +1830,7 @@ class metric_punned_t {
1775
1830
  case metric_kind_t::cos_k: {
1776
1831
  switch (scalar_kind_) {
1777
1832
  case scalar_kind_t::bf16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<bf16_t, f32_t>>; break;
1778
- case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<i8_t, f32_t>>; break;
1833
+ case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_i8_t>; break;
1779
1834
  case scalar_kind_t::f16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f16_t, f32_t>>; break;
1780
1835
  case scalar_kind_t::f32_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f32_t>>; break;
1781
1836
  case scalar_kind_t::f64_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_cos_gt<f64_t>>; break;
@@ -1786,7 +1841,7 @@ class metric_punned_t {
1786
1841
  case metric_kind_t::l2sq_k: {
1787
1842
  switch (scalar_kind_) {
1788
1843
  case scalar_kind_t::bf16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<bf16_t, f32_t>>; break;
1789
- case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<i8_t, f32_t>>; break;
1844
+ case scalar_kind_t::i8_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_i8_t>; break;
1790
1845
  case scalar_kind_t::f16_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f16_t, f32_t>>; break;
1791
1846
  case scalar_kind_t::f32_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f32_t>>; break;
1792
1847
  case scalar_kind_t::f64_k: metric_ptr_ = (uptr_t)&equidimensional_<metric_l2sq_gt<f64_t>>; break;
@@ -21,8 +21,9 @@ wasmer install unum/usearch
21
21
  Create an index, add vectors, and perform searches with ease:
22
22
 
23
23
  ```js
24
+ const assert = require('node:assert');
24
25
  const usearch = require('usearch');
25
- const index = new usearch.Index({ metric: 'cos', connectivity: 16, dimensions: 3 });
26
+ const index = new usearch.Index({ metric: 'l2sq', connectivity: 16, dimensions: 3 });
26
27
  index.add(42n, new Float32Array([0.2, 0.6, 0.4]));
27
28
  const results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
28
29
 
@@ -47,13 +47,13 @@ test('Batch operations', () => {
47
47
  });
48
48
 
49
49
  test("Expected results", () => {
50
- var index = new usearch.Index({
50
+ const index = new usearch.Index({
51
51
  metric: "l2sq",
52
52
  connectivity: 16,
53
53
  dimensions: 3,
54
54
  });
55
55
  index.add(42n, new Float32Array([0.2, 0.6, 0.4]));
56
- var results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
56
+ const results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
57
57
 
58
58
  assert.equal(index.size(), 1);
59
59
  assert.deepEqual(results.keys, new BigUint64Array([42n]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "2.15.0",
3
+ "version": "2.15.1",
4
4
  "description": "Smaller & Faster Single-File Vector Search Engine from Unum",
5
5
  "author": "Ash Vardanian (https://ashvardanian.com/)",
6
6
  "license": "Apache 2.0",
Binary file
Binary file