usearch 2.6.1 → 2.7.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.
Files changed (54) hide show
  1. package/. npmignore +14 -0
  2. package/.cmake-format.py +19 -0
  3. package/.github/workflows/Dockerfile.libs +3 -3
  4. package/.github/workflows/prerelease.yml +85 -64
  5. package/.github/workflows/release.yml +18 -16
  6. package/.gitignore +1 -1
  7. package/.vscode/launch.json +47 -14
  8. package/.vscode/settings.json +7 -0
  9. package/.vscode/tasks.json +44 -8
  10. package/CITATION.cff +1 -1
  11. package/CMakeLists.txt +218 -67
  12. package/Cargo.toml +1 -1
  13. package/README.md +1 -1
  14. package/binding.gyp +3 -2
  15. package/build.gradle +19 -10
  16. package/c/CMakeLists.txt +21 -48
  17. package/c/README.md +5 -5
  18. package/c/lib.cpp +52 -7
  19. package/c/test.c +137 -94
  20. package/c/usearch.h +42 -0
  21. package/cmake/clipp.cmake +0 -1
  22. package/cmake/jemalloc.cmake +21 -37
  23. package/conanfile.py +1 -1
  24. package/cpp/CMakeLists.txt +14 -123
  25. package/cpp/bench.cpp +0 -12
  26. package/cpp/test.cpp +29 -1
  27. package/csharp/nuget/nuget-package.props +1 -1
  28. package/docs/compilation.md +23 -16
  29. package/docs/conf.py +1 -1
  30. package/golang/README.md +52 -51
  31. package/golang/lib.go +1 -1
  32. package/golang/lib_test.go +4 -1
  33. package/include/usearch/index.hpp +2 -2
  34. package/include/usearch/index_plugins.hpp +345 -160
  35. package/javascript/lib.cpp +204 -250
  36. package/javascript/usearch.js +440 -2
  37. package/javascript/usearch.test.js +37 -0
  38. package/package.json +10 -5
  39. package/python/lib.cpp +96 -225
  40. package/python/scripts/bench_exact.py +2 -2
  41. package/python/scripts/test_jit.py +2 -13
  42. package/python/scripts/test_sparse.py +1 -1
  43. package/python/scripts/test_tooling.py +26 -5
  44. package/rust/lib.cpp +12 -4
  45. package/rust/lib.hpp +7 -0
  46. package/rust/lib.rs +170 -10
  47. package/setup.py +14 -4
  48. package/wasm/CMakeLists.txt +4 -12
  49. package/wasm/lib.cpp +1 -1
  50. package/wasmer.toml +1 -1
  51. package/javascript/docs.js +0 -111
  52. package/javascript/test.js +0 -32
  53. package/javascript/usearch.d.ts +0 -110
  54. package/tsconfig.json +0 -8
package/rust/lib.rs CHANGED
@@ -1,12 +1,13 @@
1
1
  #[cxx::bridge]
2
2
  pub mod ffi {
3
-
4
3
  // Shared structs with fields visible to both languages.
4
+ #[derive(Debug)]
5
5
  struct Matches {
6
6
  keys: Vec<u64>,
7
7
  distances: Vec<f32>,
8
8
  }
9
9
 
10
+ #[derive(Debug)]
10
11
  enum MetricKind {
11
12
  IP,
12
13
  L2sq,
@@ -18,6 +19,7 @@ pub mod ffi {
18
19
  Sorensen,
19
20
  }
20
21
 
22
+ #[derive(Debug)]
21
23
  enum ScalarKind {
22
24
  F64,
23
25
  F32,
@@ -26,6 +28,7 @@ pub mod ffi {
26
28
  B1,
27
29
  }
28
30
 
31
+ #[derive(Debug, PartialEq)]
29
32
  struct IndexOptions {
30
33
  dimensions: usize,
31
34
  metric: MetricKind,
@@ -40,9 +43,14 @@ pub mod ffi {
40
43
  unsafe extern "C++" {
41
44
  include!("lib.hpp");
42
45
 
43
- /// Low-level C++ interface, that is further wrapped into the high-level `Index`
46
+ /// Low-level C++ interface that is further wrapped into the high-level `Index`
44
47
  type NativeIndex;
45
48
 
49
+ pub fn expansion_add(self: &NativeIndex) -> usize;
50
+ pub fn expansion_search(self: &NativeIndex) -> usize;
51
+ pub fn change_expansion_add(self: &NativeIndex, n: usize) -> Result<()>;
52
+ pub fn change_expansion_search(self: &NativeIndex, n: usize) -> Result<()>;
53
+
46
54
  pub fn new_native_index(options: &IndexOptions) -> Result<UniquePtr<NativeIndex>>;
47
55
  pub fn reserve(self: &NativeIndex, capacity: usize) -> Result<()>;
48
56
  pub fn dimensions(self: &NativeIndex) -> usize;
@@ -74,6 +82,9 @@ pub mod ffi {
74
82
  pub fn save(self: &NativeIndex, path: &str) -> Result<()>;
75
83
  pub fn load(self: &NativeIndex, path: &str) -> Result<()>;
76
84
  pub fn view(self: &NativeIndex, path: &str) -> Result<()>;
85
+ pub fn reset(self: &NativeIndex) -> Result<()>;
86
+ pub fn memory_usage(self: &NativeIndex) -> usize;
87
+
77
88
  pub fn save_to_buffer(self: &NativeIndex, buffer: &mut [u8]) -> Result<()>;
78
89
  pub fn load_from_buffer(self: &NativeIndex, buffer: &[u8]) -> Result<()>;
79
90
  pub fn view_from_buffer(self: &NativeIndex, buffer: &[u8]) -> Result<()>;
@@ -100,6 +111,20 @@ impl Default for ffi::IndexOptions {
100
111
  }
101
112
  }
102
113
 
114
+ impl Clone for ffi::IndexOptions {
115
+ fn clone(&self) -> Self {
116
+ ffi::IndexOptions {
117
+ dimensions: (self.dimensions),
118
+ metric: (self.metric),
119
+ quantization: (self.quantization),
120
+ connectivity: (self.connectivity),
121
+ expansion_add: (self.expansion_add),
122
+ expansion_search: (self.expansion_search),
123
+ multi: (self.multi),
124
+ }
125
+ }
126
+ }
127
+
103
128
  pub trait VectorType {
104
129
  fn add(index: &Index, key: u64, vector: &[Self]) -> Result<(), cxx::Exception>
105
130
  where
@@ -156,6 +181,26 @@ impl Index {
156
181
  }
157
182
  }
158
183
 
184
+ /// Retrieves the expansion value used during index creation.
185
+ pub fn expansion_add(self: &Index) -> usize {
186
+ self.inner.expansion_add()
187
+ }
188
+
189
+ /// Retrieves the expansion value used during search.
190
+ pub fn expansion_search(self: &Index) -> usize {
191
+ self.inner.expansion_search()
192
+ }
193
+
194
+ /// Updates the expansion value used during index creation. Rarely used.
195
+ pub fn change_expansion_add(self: &Index, n: usize) -> Result<(), cxx::Exception> {
196
+ self.inner.change_expansion_add(n)
197
+ }
198
+
199
+ /// Updates the expansion value used during search operations.
200
+ pub fn change_expansion_search(self: &Index, n: usize) -> Result<(), cxx::Exception> {
201
+ self.inner.change_expansion_search(n)
202
+ }
203
+
159
204
  /// Performs k-Approximate Nearest Neighbors (kANN) Search for closest vectors to the provided query.
160
205
  ///
161
206
  /// # Arguments
@@ -184,7 +229,12 @@ impl Index {
184
229
  T::add(self, key, vector)
185
230
  }
186
231
 
187
- /// Extracts one or more vectors matching specified key.
232
+ /// Extracts one or more vectors matching the specified key.
233
+ /// The `vector` slice must be a multiple of the number of dimensions in the index.
234
+ /// After the execution, return the number `X` of vectors found.
235
+ /// The vector slice's first `X * dimensions` elements will be filled.
236
+ ///
237
+ /// If you are a novice user, consider `export`.
188
238
  ///
189
239
  /// # Arguments
190
240
  ///
@@ -198,11 +248,34 @@ impl Index {
198
248
  T::get(self, key, vector)
199
249
  }
200
250
 
251
+ /// Extracts one or more vectors matching specified key into supplied resizable vector.
252
+ /// The `vector` is resized to a multiple of the number of dimensions in the index.
253
+ ///
254
+ /// # Arguments
255
+ ///
256
+ /// * `key` - The key associated with the vector.
257
+ /// * `vector` - A mutable vector containing the vector data.
258
+ pub fn export<T: VectorType + Default + Clone>(
259
+ self: &Index,
260
+ key: u64,
261
+ vector: &mut Vec<T>,
262
+ ) -> Result<usize, cxx::Exception> {
263
+ let dim = self.dimensions();
264
+ let max_matches = self.count(key);
265
+ vector.resize(dim * max_matches, T::default());
266
+ let matches = T::get(self, key, &mut vector[..]);
267
+ if matches.is_err() {
268
+ return matches;
269
+ }
270
+ vector.resize(dim * matches.as_ref().unwrap(), T::default());
271
+ return matches;
272
+ }
273
+
201
274
  /// Reserves memory for a specified number of incoming vectors.
202
275
  ///
203
276
  /// # Arguments
204
277
  ///
205
- /// * `capacity` - The desired total capacity including the current size.
278
+ /// * `capacity` - The desired total capacity, including the current size.
206
279
  pub fn reserve(self: &Index, capacity: usize) -> Result<(), cxx::Exception> {
207
280
  self.inner.reserve(capacity)
208
281
  }
@@ -245,7 +318,7 @@ impl Index {
245
318
  self.inner.remove(key)
246
319
  }
247
320
 
248
- /// Renames the vector under a certain key.
321
+ /// Renames the vector under a specific key.
249
322
  ///
250
323
  /// # Arguments
251
324
  ///
@@ -254,7 +327,7 @@ impl Index {
254
327
  ///
255
328
  /// # Returns
256
329
  ///
257
- /// `true` if the vector is successfully renamed, `false` otherwise.
330
+ /// `true` if the vector is renamed, `false` otherwise.
258
331
  pub fn rename(self: &Index, from: u64, to: u64) -> Result<usize, cxx::Exception> {
259
332
  self.inner.rename(from, to)
260
333
  }
@@ -272,7 +345,7 @@ impl Index {
272
345
  self.inner.contains(key)
273
346
  }
274
347
 
275
- /// Count the count of vector with the same specified key.
348
+ /// Count the count of vectors with the same specified key.
276
349
  ///
277
350
  /// # Arguments
278
351
  ///
@@ -312,6 +385,17 @@ impl Index {
312
385
  self.inner.view(path)
313
386
  }
314
387
 
388
+ /// Erases all members from the index, closes files, and returns RAM to OS.
389
+ pub fn reset(self: &Index) -> Result<(), cxx::Exception> {
390
+ self.inner.reset()
391
+ }
392
+
393
+ /// A relatively accurate lower bound on the amount of memory consumed by the system.
394
+ /// In practice, its error will be below 10%.
395
+ pub fn memory_usage(self: &Index) -> usize {
396
+ self.inner.memory_usage()
397
+ }
398
+
315
399
  /// Saves the index to a specified file.
316
400
  ///
317
401
  /// # Arguments
@@ -352,6 +436,36 @@ mod tests {
352
436
  use crate::new_index;
353
437
  use crate::Index;
354
438
 
439
+ #[test]
440
+ fn test_add_get_vector() {
441
+ let mut options = IndexOptions::default();
442
+ options.dimensions = 5;
443
+ let index = Index::new(&options).unwrap();
444
+ assert!(index.reserve(10).is_ok());
445
+
446
+ let first: [f32; 5] = [0.2, 0.1, 0.2, 0.1, 0.3];
447
+ let second: [f32; 5] = [0.3, 0.2, 0.4, 0.0, 0.1];
448
+ assert!(index.add(1, &first).is_ok());
449
+ assert!(index.add(2, &second).is_ok());
450
+ assert_eq!(index.size(), 2);
451
+
452
+ // Test using Vec<T>
453
+ let mut found_vec: Vec<f32> = Vec::new();
454
+ assert_eq!(index.export(1, &mut found_vec).unwrap(), 1);
455
+ assert_eq!(found_vec.len(), 5);
456
+ assert_eq!(found_vec, first.to_vec());
457
+
458
+ // Test using slice
459
+ let mut found_slice = [0.0 as f32; 5];
460
+ assert_eq!(index.get(1, &mut found_slice).unwrap(), 1);
461
+ assert_eq!(found_slice, first);
462
+
463
+ // Create a slice with incorrect size
464
+ let mut found = [0.0 as f32; 6]; // This isn't a multiple of the index's dimensions.
465
+ let result = index.get(1, &mut found);
466
+ assert!(result.is_err());
467
+ }
468
+
355
469
  #[test]
356
470
  fn integration() {
357
471
  let mut options = IndexOptions::default();
@@ -359,6 +473,9 @@ mod tests {
359
473
 
360
474
  let index = Index::new(&options).unwrap();
361
475
 
476
+ assert!(index.expansion_add() > 0);
477
+ assert!(index.expansion_search() > 0);
478
+
362
479
  assert!(index.reserve(10).is_ok());
363
480
  assert!(index.capacity() >= 10);
364
481
  assert!(index.connectivity() != 0);
@@ -366,14 +483,41 @@ mod tests {
366
483
  assert_eq!(index.size(), 0);
367
484
 
368
485
  let first: [f32; 5] = [0.2, 0.1, 0.2, 0.1, 0.3];
369
- let second: [f32; 5] = [0.2, 0.1, 0.2, 0.1, 0.3];
370
-
486
+ let second: [f32; 5] = [0.3, 0.2, 0.4, 0.0, 0.1];
487
+
488
+ println!(
489
+ "before add, memory_usage: {} \
490
+ cap: {} \
491
+ ",
492
+ index.memory_usage(),
493
+ index.capacity(),
494
+ );
495
+ assert!(index.change_expansion_add(10).is_ok());
496
+ assert_eq!(index.expansion_add(), 10);
371
497
  assert!(index.add(42, &first).is_ok());
498
+ assert!(index.change_expansion_add(12).is_ok());
499
+ assert_eq!(index.expansion_add(), 12);
372
500
  assert!(index.add(43, &second).is_ok());
373
501
  assert_eq!(index.size(), 2);
374
-
502
+ println!(
503
+ "after add, memory_usage: {} \
504
+ cap: {} \
505
+ ",
506
+ index.memory_usage(),
507
+ index.capacity(),
508
+ );
509
+
510
+ assert!(index.change_expansion_search(10).is_ok());
511
+ assert_eq!(index.expansion_search(), 10);
375
512
  // Read back the tags
376
513
  let results = index.search(&first, 10).unwrap();
514
+ println!("{:?}", results);
515
+ assert_eq!(results.keys.len(), 2);
516
+
517
+ assert!(index.change_expansion_search(12).is_ok());
518
+ assert_eq!(index.expansion_search(), 12);
519
+ let results = index.search(&first, 10).unwrap();
520
+ println!("{:?}", results);
377
521
  assert_eq!(results.keys.len(), 2);
378
522
 
379
523
  // Validate serialization
@@ -399,5 +543,21 @@ mod tests {
399
543
  .load_from_buffer(&serialization_buffer)
400
544
  .is_ok());
401
545
  assert_eq!(index.size(), deserialized_index.size());
546
+
547
+ // reset
548
+ assert_ne!(index.memory_usage(), 0);
549
+ assert!(index.reset().is_ok());
550
+ assert_eq!(index.size(), 0);
551
+ assert_eq!(index.memory_usage(), 0);
552
+
553
+ // clone
554
+ options.metric = MetricKind::Haversine;
555
+ let mut opts = options.clone();
556
+ assert_eq!(opts.metric, options.metric);
557
+ assert_eq!(opts.quantization, options.quantization);
558
+ assert_eq!(opts, options);
559
+ opts.metric = MetricKind::Cos;
560
+ assert_ne!(opts.metric, options.metric);
561
+ assert!(new_index(&opts).is_ok());
402
562
  }
403
563
  }
package/setup.py CHANGED
@@ -12,6 +12,7 @@ macros_args = []
12
12
  if sys.platform == "linux":
13
13
  compile_args.append("-std=c++17")
14
14
  compile_args.append("-O3") # Maximize performance
15
+ compile_args.append("-ffast-math") # Maximize floating-point performance
15
16
  compile_args.append("-Wno-unknown-pragmas")
16
17
  compile_args.append("-fdiagnostics-color=always")
17
18
 
@@ -30,20 +31,29 @@ if sys.platform == "darwin":
30
31
  compile_args.append("-mmacosx-version-min=10.15")
31
32
  compile_args.append("-std=c++17")
32
33
  compile_args.append("-O3") # Maximize performance
34
+ compile_args.append("-ffast-math") # Maximize floating-point performance
33
35
  compile_args.append("-fcolor-diagnostics")
34
36
  compile_args.append("-Wno-unknown-pragmas")
35
37
 
36
38
  # Simplify debugging, but the normal `-g` may make builds much longer!
37
39
  compile_args.append("-g1")
38
40
 
39
- # Linking OpenMP requires additional preparation in CIBuildWheel
40
- # macros_args.append(("USEARCH_USE_OPENMP", "1"))
41
- # compile_args.append("-Xpreprocessor -fopenmp")
42
- # link_args.append("-Xpreprocessor -lomp")
41
+ # Linking OpenMP requires additional preparation in CIBuildWheel.
42
+ # We must install `brew install llvm` ahead of time.
43
+ # import subprocess as cli
44
+ # llvm_base = cli.check_output(["brew", "--prefix", "llvm"]).strip().decode("utf-8")
45
+ # if len(llvm_base):
46
+ # compile_args.append(f"-I{llvm_base}/include")
47
+ # compile_args.append("-Xpreprocessor -fopenmp")
48
+ # link_args.append(f"-L{llvm_base}/lib")
49
+ # link_args.append("-lomp")
50
+ # macros_args.append(("USEARCH_USE_OPENMP", "1"))
43
51
 
44
52
  if sys.platform == "win32":
45
53
  compile_args.append("/std:c++17")
46
54
  compile_args.append("/O2")
55
+ compile_args.append("/fp:fast") # Enable fast math for MSVC
56
+ compile_args.append("/W1") # Reduce warnings verbosity
47
57
 
48
58
  ext_modules = [
49
59
  Pybind11Extension(
@@ -1,15 +1,7 @@
1
1
  include(emscripten)
2
2
 
3
- set(CMAKE_C_COMPILER emcc)
4
- set(CMAKE_CXX_COMPILER em++)
3
+ # Setting the compiler globally is never a good idea! set(CMAKE_C_COMPILER emcc) set(CMAKE_CXX_COMPILER em++)
5
4
 
6
- set(USEARCH_PUNNED_INCLUDE_DIRS
7
- "${CMAKE_CURRENT_SOURCE_DIR}/../c"
8
- "${CMAKE_CURRENT_SOURCE_DIR}/../include"
9
- "${CMAKE_CURRENT_SOURCE_DIR}/../fp16/include"
10
- )
11
-
12
- add_executable(index lib.cpp)
13
- target_include_directories(index PRIVATE ${USEARCH_PUNNED_INCLUDE_DIRS})
14
- set_target_properties(index PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/wasm)
15
- set_target_properties(index PROPERTIES CXX_STANDARD 11)
5
+ add_executable(usearch_wasm lib.cpp)
6
+ setup_target(usearch_wasm)
7
+ set_target_properties(usearch_wasm PROPERTIES CXX_STANDARD 11)
package/wasm/lib.cpp CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  #include <emscripten/emscripten.h>
4
4
 
5
- #include <lib.cpp>
5
+ #include <../c/lib.cpp>
package/wasmer.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name="unum/usearch"
3
- version="2.6.1"
3
+ version="2.7.1"
4
4
  description="Smaller & Faster Single-File Vector Search Engine from Unum"
5
5
  license="Apache-2.0"
6
6
  readme="README.md"
@@ -1,111 +0,0 @@
1
- /** Search result object. */
2
- class Matches {
3
- /**
4
- * @param {BigUint64Array} keys - The keys of the nearest neighbors found.
5
- * @param {Float32Array} distances - The distances of the nearest neighbors found.
6
- * @param {bigint} count - The count of nearest neighbors found.
7
- */
8
- constructor(keys, distances, count) {
9
- this.keys = keys;
10
- this.distances = distances;
11
- this.count = count;
12
- }
13
- }
14
-
15
- /** K-Approximate Nearest Neighbors search index. */
16
- class Index {
17
- /**
18
- * Constructs a new index.
19
- *
20
- * @param {bigint} dimensions
21
- * @param {string} metric
22
- * @param {string} quantization
23
- * @param {bigint} capacity
24
- * @param {bigint} connectivity
25
- * @param {bigint} expansion_add
26
- * @param {bigint} expansion_search
27
- */
28
- constructor(
29
- dimensions,
30
- metric,
31
- quantization,
32
- capacity,
33
- connectivity,
34
- expansion_add,
35
- expansion_search
36
- ) {}
37
-
38
- /**
39
- * Returns the dimensionality of vectors.
40
- * @return {bigint} The dimensionality of vectors.
41
- */
42
- dimensions() {}
43
-
44
- /**
45
- * Returns the bigint of vectors currently indexed.
46
- * @return {bigint} The bigint of vectors currently indexed.
47
- */
48
- size() {}
49
-
50
- /**
51
- * Returns index capacity.
52
- * @return {bigint} The capacity of index.
53
- */
54
- capacity() {}
55
-
56
- /**
57
- * Returns connectivity.
58
- * @return {bigint} The connectivity of index.
59
- */
60
- connectivity() {}
61
-
62
- /**
63
- * Write index to a file.
64
- * @param {string} path File path to write.
65
- */
66
- save(path) {}
67
-
68
- /**
69
- * Load index from a file.
70
- * @param {string} path File path to read.
71
- */
72
- load(path) {}
73
-
74
- /**
75
- * View index from a file, without loading into RAM.
76
- * @param {string} path File path to read.
77
- */
78
- view(path) {}
79
-
80
- /**
81
- * Add n vectors of dimension d to the index.
82
- *
83
- * @param {bigint | bigint[]} keys Input identifiers for every vector.
84
- * @param {Float32Array | Float32Array[]} mat Input matrix, matrix of size n * d.
85
- */
86
- add(keys, mat) {}
87
-
88
- /**
89
- * Query n vectors of dimension d to the index. Return at most k vectors for each.
90
- * If there are not enough results for a query, the result array is padded with -1s.
91
- *
92
- * @param {Float32Array} mat Input vectors to search, matrix of size n * d.
93
- * @param {bigint} k The bigint of nearest neighbors to search for.
94
- * @return {Matches} Output of the search result.
95
- */
96
- search(mat, k) {}
97
-
98
- /**
99
- * Check if an entry is contained in the index.
100
- *
101
- * @param {bigint} key Identifier to look up.
102
- */
103
- contains(key) {}
104
-
105
- /**
106
- * Remove a vector from the index.
107
- *
108
- * @param {bigint} key Input identifier for every vector to be removed.
109
- */
110
- remove(key) {}
111
- }
@@ -1,32 +0,0 @@
1
- var assert = require('assert');
2
- var usearch = require('bindings')('usearch');
3
-
4
- // Single-entry operations
5
-
6
- var index = new usearch.Index({ metric: 'l2sq', connectivity: 16n, dimensions: 2n });
7
- assert.equal(index.connectivity(), 16n, 'connectivity should be 16');
8
- assert.equal(index.dimensions(), 2n, 'dimensions should be 2');
9
- assert.equal(index.size(), 0n, 'initial size should be 0');
10
-
11
- index.add(15n, new Float32Array([10, 20]));
12
- index.add(16n, new Float32Array([10, 25]));
13
- assert.equal(index.size(), 2n, 'size after adding elements should be 2');
14
- assert.equal(index.contains(15n), true, 'entry must be present after insertion');
15
-
16
- var results = index.search(new Float32Array([13, 14]), 2n);
17
- assert.deepEqual(results.keys, new BigUint64Array([15n, 16n]), 'keys should be 15 and 16');
18
- assert.deepEqual(results.distances, new Float32Array([45, 130]), 'distances should be 45 and 130');
19
-
20
- // Batch operations
21
-
22
- var indexBatch = new usearch.Index({ metric: 'l2sq', connectivity: 16n, dimensions: 2n });
23
- const keys = [15n, 16n];
24
- const vectors = [new Float32Array([10, 20]), new Float32Array([10, 25])];
25
- indexBatch.add(keys, vectors);
26
- assert.equal(indexBatch.size(), 2, 'size after adding batch should be 2');
27
-
28
- results = indexBatch.search(new Float32Array([13, 14]), 2n);
29
- assert.deepEqual(results.keys, new BigUint64Array([15n, 16n]), 'keys should be 15 and 16');
30
- assert.deepEqual(results.distances, new Float32Array([45, 130]), 'distances should be 45 and 130');
31
-
32
- console.log('JavaScript tests passed!');
@@ -1,110 +0,0 @@
1
-
2
- /** Search result object. */
3
- export interface Matches {
4
- /** The keys of the nearest neighbors found, size n*k. */
5
- keys: BigUint64Array,
6
- /** The distances of the nearest neighbors found, size n*k. */
7
- distances: Float32Array,
8
- /** The distances of the nearest neighbors found, size n*k. */
9
- count: bigint
10
- }
11
-
12
- /** K-Approximate Nearest Neighbors search index. */
13
- export class Index {
14
-
15
- /**
16
- * Constructs a new index.
17
- *
18
- * @param {bigint} dimensions
19
- * @param {string} metric
20
- * @param {string} quantization
21
- * @param {bigint} capacity
22
- * @param {bigint} connectivity
23
- * @param {bigint} expansion_add
24
- * @param {bigint} expansion_search
25
- */
26
- constructor(
27
- dimensions: bigint,
28
- metric: string,
29
- quantization: string,
30
- capacity: bigint,
31
- connectivity: bigint,
32
- expansion_add: bigint,
33
- expansion_search: bigint
34
- );
35
-
36
- /**
37
- * Returns the dimensionality of vectors.
38
- * @return {bigint} The dimensionality of vectors.
39
- */
40
- dimensions(): bigint;
41
-
42
- /**
43
- * Returns the bigint of vectors currently indexed.
44
- * @return {bigint} The bigint of vectors currently indexed.
45
- */
46
- size(): bigint;
47
-
48
- /**
49
- * Returns index capacity.
50
- * @return {bigints} The capacity of index.
51
- */
52
- capacity(): bigint;
53
-
54
- /**
55
- * Returns connectivity.
56
- * @return {bigint} The connectivity of index.
57
- */
58
- connectivity(): bigint;
59
-
60
- /**
61
- * Write index to a file.
62
- * @param {string} path File path to write.
63
- */
64
- save(path: string): void;
65
-
66
- /**
67
- * Load index from a file.
68
- * @param {string} path File path to read.
69
- */
70
- load(path: string): void;
71
-
72
- /**
73
- * View index from a file, without loading into RAM.
74
- * @param {string} path File path to read.
75
- */
76
- load(path: string): void;
77
-
78
- /**
79
- * Add n vectors of dimension d to the index.
80
- *
81
- * @param {bigint | bigint[]} keys Input identifiers for every vector.
82
- * @param {Float32Array | Float32Array[]} mat Input matrix, matrix of size n * d.
83
- */
84
- add(keys: bigint | bigint[], mat: Float32Array | Float32Array[]): void;
85
-
86
- /**
87
- * Query n vectors of dimension d to the index. Return at most k vectors for each.
88
- * If there are not enough results for a query, the result array is padded with -1s.
89
- *
90
- * @param {Float32Array} mat Input vectors to search, matrix of size n * d.
91
- * @param {bigint} k The bigint of nearest neighbors to search for.
92
- * @return {Matches} Output of the search result.
93
- */
94
- search(mat: Float32Array, k: bigint): Matches;
95
-
96
- /**
97
- * Check if an entry is contained in the index.
98
- *
99
- * @param {bigint} key Identifier to look up.
100
- */
101
- contains(key: bigint): boolean;
102
-
103
- /**
104
- * Remove a vector from the index.
105
- *
106
- * @param {bigint} key Input identifier for every vector to be removed.
107
- */
108
- remove(key: bigint): boolean;
109
-
110
- }
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "typedocOptions": {
3
- "entryPoints": [
4
- "javascript/usearch.d.ts"
5
- ],
6
- "out": "docs"
7
- }
8
- }