usearch 2.6.0 → 2.7.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.
- package/. npmignore +14 -0
- package/.cmake-format.py +19 -0
- package/.github/workflows/Dockerfile.libs +2 -2
- package/.github/workflows/prerelease.yml +85 -64
- package/.github/workflows/release.yml +24 -15
- package/.gitignore +1 -1
- package/.vscode/launch.json +47 -14
- package/.vscode/settings.json +7 -0
- package/.vscode/tasks.json +44 -8
- package/CITATION.cff +1 -1
- package/CMakeLists.txt +218 -67
- package/Cargo.toml +1 -1
- package/README.md +1 -1
- package/binding.gyp +3 -2
- package/build.gradle +19 -10
- package/c/CMakeLists.txt +21 -48
- package/c/README.md +5 -5
- package/c/lib.cpp +52 -7
- package/c/test.c +137 -94
- package/c/usearch.h +42 -0
- package/cmake/clipp.cmake +0 -1
- package/cmake/jemalloc.cmake +21 -37
- package/conanfile.py +1 -1
- package/cpp/CMakeLists.txt +14 -123
- package/cpp/README.md +26 -22
- package/cpp/bench.cpp +0 -12
- package/cpp/test.cpp +29 -1
- package/csharp/nuget/nuget-package.props +1 -1
- package/docs/compilation.md +23 -16
- package/docs/conf.py +1 -1
- package/golang/README.md +52 -51
- package/golang/lib.go +1 -1
- package/golang/lib_test.go +4 -1
- package/include/usearch/index.hpp +2 -2
- package/include/usearch/index_plugins.hpp +345 -160
- package/javascript/lib.cpp +204 -250
- package/javascript/usearch.js +440 -2
- package/javascript/usearch.test.js +37 -0
- package/package.json +10 -5
- package/python/lib.cpp +95 -224
- package/python/scripts/bench_exact.py +2 -2
- package/python/scripts/test_jit.py +2 -13
- package/python/scripts/test_sparse.py +1 -1
- package/python/scripts/test_tooling.py +15 -5
- package/rust/lib.cpp +7 -4
- package/rust/lib.hpp +2 -0
- package/rust/lib.rs +128 -8
- package/setup.py +14 -4
- package/wasm/CMakeLists.txt +4 -12
- package/wasm/lib.cpp +1 -1
- package/wasmer.toml +1 -1
- package/javascript/docs.js +0 -111
- package/javascript/test.js +0 -32
- package/javascript/usearch.d.ts +0 -110
- 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,7 +43,7 @@ pub mod ffi {
|
|
|
40
43
|
unsafe extern "C++" {
|
|
41
44
|
include!("lib.hpp");
|
|
42
45
|
|
|
43
|
-
/// Low-level C++ interface
|
|
46
|
+
/// Low-level C++ interface that is further wrapped into the high-level `Index`
|
|
44
47
|
type NativeIndex;
|
|
45
48
|
|
|
46
49
|
pub fn new_native_index(options: &IndexOptions) -> Result<UniquePtr<NativeIndex>>;
|
|
@@ -74,6 +77,9 @@ pub mod ffi {
|
|
|
74
77
|
pub fn save(self: &NativeIndex, path: &str) -> Result<()>;
|
|
75
78
|
pub fn load(self: &NativeIndex, path: &str) -> Result<()>;
|
|
76
79
|
pub fn view(self: &NativeIndex, path: &str) -> Result<()>;
|
|
80
|
+
pub fn reset(self: &NativeIndex) -> Result<()>;
|
|
81
|
+
pub fn memory_usage(self: &NativeIndex) -> usize;
|
|
82
|
+
|
|
77
83
|
pub fn save_to_buffer(self: &NativeIndex, buffer: &mut [u8]) -> Result<()>;
|
|
78
84
|
pub fn load_from_buffer(self: &NativeIndex, buffer: &[u8]) -> Result<()>;
|
|
79
85
|
pub fn view_from_buffer(self: &NativeIndex, buffer: &[u8]) -> Result<()>;
|
|
@@ -100,6 +106,20 @@ impl Default for ffi::IndexOptions {
|
|
|
100
106
|
}
|
|
101
107
|
}
|
|
102
108
|
|
|
109
|
+
impl Clone for ffi::IndexOptions {
|
|
110
|
+
fn clone(&self) -> Self {
|
|
111
|
+
ffi::IndexOptions {
|
|
112
|
+
dimensions: (self.dimensions),
|
|
113
|
+
metric: (self.metric),
|
|
114
|
+
quantization: (self.quantization),
|
|
115
|
+
connectivity: (self.connectivity),
|
|
116
|
+
expansion_add: (self.expansion_add),
|
|
117
|
+
expansion_search: (self.expansion_search),
|
|
118
|
+
multi: (self.multi),
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
103
123
|
pub trait VectorType {
|
|
104
124
|
fn add(index: &Index, key: u64, vector: &[Self]) -> Result<(), cxx::Exception>
|
|
105
125
|
where
|
|
@@ -185,6 +205,11 @@ impl Index {
|
|
|
185
205
|
}
|
|
186
206
|
|
|
187
207
|
/// Extracts one or more vectors matching specified key.
|
|
208
|
+
/// The `vector` slice must be a multiple number of dimensions in the index.
|
|
209
|
+
/// After the execution return the number `X` of vectors found.
|
|
210
|
+
/// The first `X * dimensions` elements of the vector slice will be filled.
|
|
211
|
+
///
|
|
212
|
+
/// If you are a novice user, consider `export`.
|
|
188
213
|
///
|
|
189
214
|
/// # Arguments
|
|
190
215
|
///
|
|
@@ -198,11 +223,34 @@ impl Index {
|
|
|
198
223
|
T::get(self, key, vector)
|
|
199
224
|
}
|
|
200
225
|
|
|
226
|
+
/// Extracts one or more vectors matching specified key into supplied resizable vector.
|
|
227
|
+
/// The `vector` is resized to a multiple number of dimensions in the index.
|
|
228
|
+
///
|
|
229
|
+
/// # Arguments
|
|
230
|
+
///
|
|
231
|
+
/// * `key` - The key associated with the vector.
|
|
232
|
+
/// * `vector` - A mutable vector containing the vector data.
|
|
233
|
+
pub fn export<T: VectorType + Default + Clone>(
|
|
234
|
+
self: &Index,
|
|
235
|
+
key: u64,
|
|
236
|
+
vector: &mut Vec<T>,
|
|
237
|
+
) -> Result<usize, cxx::Exception> {
|
|
238
|
+
let dim = self.dimensions();
|
|
239
|
+
let max_matches = self.count(key);
|
|
240
|
+
vector.resize(dim * max_matches, T::default());
|
|
241
|
+
let matches = T::get(self, key, &mut vector[..]);
|
|
242
|
+
if matches.is_err() {
|
|
243
|
+
return matches;
|
|
244
|
+
}
|
|
245
|
+
vector.resize(dim * matches.as_ref().unwrap(), T::default());
|
|
246
|
+
return matches;
|
|
247
|
+
}
|
|
248
|
+
|
|
201
249
|
/// Reserves memory for a specified number of incoming vectors.
|
|
202
250
|
///
|
|
203
251
|
/// # Arguments
|
|
204
252
|
///
|
|
205
|
-
/// * `capacity` - The desired total capacity including the current size.
|
|
253
|
+
/// * `capacity` - The desired total capacity, including the current size.
|
|
206
254
|
pub fn reserve(self: &Index, capacity: usize) -> Result<(), cxx::Exception> {
|
|
207
255
|
self.inner.reserve(capacity)
|
|
208
256
|
}
|
|
@@ -245,7 +293,7 @@ impl Index {
|
|
|
245
293
|
self.inner.remove(key)
|
|
246
294
|
}
|
|
247
295
|
|
|
248
|
-
/// Renames the vector under a
|
|
296
|
+
/// Renames the vector under a specific key.
|
|
249
297
|
///
|
|
250
298
|
/// # Arguments
|
|
251
299
|
///
|
|
@@ -254,7 +302,7 @@ impl Index {
|
|
|
254
302
|
///
|
|
255
303
|
/// # Returns
|
|
256
304
|
///
|
|
257
|
-
/// `true` if the vector is
|
|
305
|
+
/// `true` if the vector is renamed, `false` otherwise.
|
|
258
306
|
pub fn rename(self: &Index, from: u64, to: u64) -> Result<usize, cxx::Exception> {
|
|
259
307
|
self.inner.rename(from, to)
|
|
260
308
|
}
|
|
@@ -272,7 +320,7 @@ impl Index {
|
|
|
272
320
|
self.inner.contains(key)
|
|
273
321
|
}
|
|
274
322
|
|
|
275
|
-
/// Count the count of
|
|
323
|
+
/// Count the count of vectors with the same specified key.
|
|
276
324
|
///
|
|
277
325
|
/// # Arguments
|
|
278
326
|
///
|
|
@@ -312,6 +360,17 @@ impl Index {
|
|
|
312
360
|
self.inner.view(path)
|
|
313
361
|
}
|
|
314
362
|
|
|
363
|
+
/// Erases all members from the index, closes files, and returns RAM to OS.
|
|
364
|
+
pub fn reset(self: &Index) -> Result<(), cxx::Exception> {
|
|
365
|
+
self.inner.reset()
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/// A relatively accurate lower bound on the amount of memory consumed by the system.
|
|
369
|
+
/// In practice, its error will be below 10%.
|
|
370
|
+
pub fn memory_usage(self: &Index) -> usize {
|
|
371
|
+
self.inner.memory_usage()
|
|
372
|
+
}
|
|
373
|
+
|
|
315
374
|
/// Saves the index to a specified file.
|
|
316
375
|
///
|
|
317
376
|
/// # Arguments
|
|
@@ -352,6 +411,36 @@ mod tests {
|
|
|
352
411
|
use crate::new_index;
|
|
353
412
|
use crate::Index;
|
|
354
413
|
|
|
414
|
+
#[test]
|
|
415
|
+
fn test_add_get_vector() {
|
|
416
|
+
let mut options = IndexOptions::default();
|
|
417
|
+
options.dimensions = 5;
|
|
418
|
+
let index = Index::new(&options).unwrap();
|
|
419
|
+
assert!(index.reserve(10).is_ok());
|
|
420
|
+
|
|
421
|
+
let first: [f32; 5] = [0.2, 0.1, 0.2, 0.1, 0.3];
|
|
422
|
+
let second: [f32; 5] = [0.3, 0.2, 0.4, 0.0, 0.1];
|
|
423
|
+
assert!(index.add(1, &first).is_ok());
|
|
424
|
+
assert!(index.add(2, &second).is_ok());
|
|
425
|
+
assert_eq!(index.size(), 2);
|
|
426
|
+
|
|
427
|
+
// Test using Vec<T>
|
|
428
|
+
let mut found_vec: Vec<f32> = Vec::new();
|
|
429
|
+
assert_eq!(index.export(1, &mut found_vec).unwrap(), 1);
|
|
430
|
+
assert_eq!(found_vec.len(), 5);
|
|
431
|
+
assert_eq!(found_vec, first.to_vec());
|
|
432
|
+
|
|
433
|
+
// Test using slice
|
|
434
|
+
let mut found_slice = [0.0 as f32; 5];
|
|
435
|
+
assert_eq!(index.get(1, &mut found_slice).unwrap(), 1);
|
|
436
|
+
assert_eq!(found_slice, first);
|
|
437
|
+
|
|
438
|
+
// Create a slice with incorrect size
|
|
439
|
+
let mut found = [0.0 as f32; 6]; // This isn't a multiple of the index's dimensions.
|
|
440
|
+
let result = index.get(1, &mut found);
|
|
441
|
+
assert!(result.is_err());
|
|
442
|
+
}
|
|
443
|
+
|
|
355
444
|
#[test]
|
|
356
445
|
fn integration() {
|
|
357
446
|
let mut options = IndexOptions::default();
|
|
@@ -366,14 +455,29 @@ mod tests {
|
|
|
366
455
|
assert_eq!(index.size(), 0);
|
|
367
456
|
|
|
368
457
|
let first: [f32; 5] = [0.2, 0.1, 0.2, 0.1, 0.3];
|
|
369
|
-
let second: [f32; 5] = [0.
|
|
370
|
-
|
|
458
|
+
let second: [f32; 5] = [0.3, 0.2, 0.4, 0.0, 0.1];
|
|
459
|
+
|
|
460
|
+
println!(
|
|
461
|
+
"before add, memory_usage: {} \
|
|
462
|
+
cap: {} \
|
|
463
|
+
",
|
|
464
|
+
index.memory_usage(),
|
|
465
|
+
index.capacity(),
|
|
466
|
+
);
|
|
371
467
|
assert!(index.add(42, &first).is_ok());
|
|
372
468
|
assert!(index.add(43, &second).is_ok());
|
|
373
469
|
assert_eq!(index.size(), 2);
|
|
470
|
+
println!(
|
|
471
|
+
"after add, memory_usage: {} \
|
|
472
|
+
cap: {} \
|
|
473
|
+
",
|
|
474
|
+
index.memory_usage(),
|
|
475
|
+
index.capacity(),
|
|
476
|
+
);
|
|
374
477
|
|
|
375
478
|
// Read back the tags
|
|
376
479
|
let results = index.search(&first, 10).unwrap();
|
|
480
|
+
println!("{:?}", results);
|
|
377
481
|
assert_eq!(results.keys.len(), 2);
|
|
378
482
|
|
|
379
483
|
// Validate serialization
|
|
@@ -399,5 +503,21 @@ mod tests {
|
|
|
399
503
|
.load_from_buffer(&serialization_buffer)
|
|
400
504
|
.is_ok());
|
|
401
505
|
assert_eq!(index.size(), deserialized_index.size());
|
|
506
|
+
|
|
507
|
+
// reset
|
|
508
|
+
assert_ne!(index.memory_usage(), 0);
|
|
509
|
+
assert!(index.reset().is_ok());
|
|
510
|
+
assert_eq!(index.size(), 0);
|
|
511
|
+
assert_eq!(index.memory_usage(), 0);
|
|
512
|
+
|
|
513
|
+
// clone
|
|
514
|
+
options.metric = MetricKind::Haversine;
|
|
515
|
+
let mut opts = options.clone();
|
|
516
|
+
assert_eq!(opts.metric, options.metric);
|
|
517
|
+
assert_eq!(opts.quantization, options.quantization);
|
|
518
|
+
assert_eq!(opts, options);
|
|
519
|
+
opts.metric = MetricKind::Cos;
|
|
520
|
+
assert_ne!(opts.metric, options.metric);
|
|
521
|
+
assert!(new_index(&opts).is_ok());
|
|
402
522
|
}
|
|
403
523
|
}
|
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
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
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(
|
package/wasm/CMakeLists.txt
CHANGED
|
@@ -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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
package/wasmer.toml
CHANGED
package/javascript/docs.js
DELETED
|
@@ -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
|
-
}
|
package/javascript/test.js
DELETED
|
@@ -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!');
|
package/javascript/usearch.d.ts
DELETED
|
@@ -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
|
-
}
|