usearch 2.9.1 → 2.10.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.
Files changed (169) hide show
  1. package/README.md +50 -52
  2. package/javascript/{types → dist/cjs}/usearch.d.ts +90 -115
  3. package/javascript/dist/cjs/usearch.js +531 -0
  4. package/javascript/dist/esm/usearch.d.ts +212 -0
  5. package/javascript/{usearch.js → dist/esm/usearch.js} +202 -153
  6. package/package.json +25 -23
  7. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  8. package/prebuilds/linux-arm64/usearch.node +0 -0
  9. package/prebuilds/linux-x64/usearch.node +0 -0
  10. package/prebuilds/win32-ia32/usearch.node +0 -0
  11. package/prebuilds/win32-x64/usearch.node +0 -0
  12. package/.clang-format +0 -10
  13. package/.clang-tidy +0 -60
  14. package/.cmake-format.py +0 -19
  15. package/.dockerignore +0 -93
  16. package/.gitattributes +0 -9
  17. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
  18. package/.github/ISSUE_TEMPLATE/config.yml +0 -5
  19. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -64
  20. package/.github/workflows/Dockerfile.libs +0 -36
  21. package/.github/workflows/prerelease.yml +0 -331
  22. package/.github/workflows/release.yml +0 -722
  23. package/.github/workflows/update_version.sh +0 -15
  24. package/.gitmodules +0 -9
  25. package/.releaserc +0 -90
  26. package/CITATION.cff +0 -11
  27. package/CMakeLists.txt +0 -324
  28. package/CODE_OF_CONDUCT.md +0 -128
  29. package/CONTRIBUTING.md +0 -353
  30. package/Cargo.toml +0 -19
  31. package/Dockerfile +0 -16
  32. package/VERSION +0 -1
  33. package/assets/unum.png +0 -0
  34. package/assets/usearch-approaches-transparent.png +0 -0
  35. package/assets/usearch-approaches-white.png +0 -0
  36. package/assets/usearch-neighbor-types.png +0 -0
  37. package/binding.gyp +0 -87
  38. package/build.gradle +0 -204
  39. package/build.rs +0 -18
  40. package/c/CMakeLists.txt +0 -25
  41. package/c/README.md +0 -34
  42. package/c/lib.cpp +0 -358
  43. package/c/test.c +0 -374
  44. package/c/usearch.h +0 -311
  45. package/cmake/clipp.cmake +0 -7
  46. package/cmake/config.cmake.in +0 -15
  47. package/cmake/emscripten.cmake +0 -8
  48. package/cmake/jemalloc.cmake +0 -62
  49. package/cmake/pkg-config.pc.in +0 -4
  50. package/cmake/usearchConfigVersion.cmake.in +0 -20
  51. package/conanfile.py +0 -26
  52. package/cpp/CMakeLists.txt +0 -14
  53. package/cpp/README.md +0 -161
  54. package/cpp/bench.cpp +0 -618
  55. package/cpp/test.cpp +0 -323
  56. package/fp16/CMakeLists.txt +0 -176
  57. package/fp16/LICENSE +0 -11
  58. package/fp16/README.md +0 -20
  59. package/fp16/bench/alt-element.cc +0 -89
  60. package/fp16/bench/from-alt-array.cc +0 -175
  61. package/fp16/bench/from-ieee-array.cc +0 -399
  62. package/fp16/bench/ieee-element.cc +0 -272
  63. package/fp16/bench/to-alt-array.cc +0 -91
  64. package/fp16/bench/to-ieee-array.cc +0 -303
  65. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  66. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  67. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  68. package/fp16/configure.py +0 -65
  69. package/fp16/confu.yaml +0 -8
  70. package/fp16/include/fp16/__init__.py +0 -0
  71. package/fp16/include/fp16/avx.py +0 -50
  72. package/fp16/include/fp16/avx2.py +0 -53
  73. package/fp16/include/fp16/bitcasts.h +0 -92
  74. package/fp16/include/fp16/fp16.h +0 -451
  75. package/fp16/include/fp16/psimd.h +0 -131
  76. package/fp16/include/fp16.h +0 -11
  77. package/fp16/jni/Android.mk +0 -6
  78. package/fp16/jni/Application.mk +0 -4
  79. package/fp16/test/alt-from-fp32-value.cc +0 -498
  80. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  81. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  82. package/fp16/test/alt-to-fp32-value.cc +0 -348
  83. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  84. package/fp16/test/bitcasts.cc +0 -56
  85. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  86. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  87. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  88. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  89. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  90. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  91. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  92. package/fp16/test/peachpy/stubs.py +0 -38
  93. package/fp16/test/tables.cc +0 -530
  94. package/fp16/test/tables.h +0 -13
  95. package/fp16/third-party/THHalf.h +0 -92
  96. package/fp16/third-party/eigen-half.h +0 -170
  97. package/fp16/third-party/float16-compressor.h +0 -80
  98. package/fp16/third-party/half.hpp +0 -2916
  99. package/fp16/third-party/npy-halffloat.h +0 -328
  100. package/include/usearch/index.hpp +0 -3836
  101. package/include/usearch/index_dense.hpp +0 -2004
  102. package/include/usearch/index_plugins.hpp +0 -2203
  103. package/javascript/lib.cpp +0 -341
  104. package/javascript/types/usearch.d.ts.map +0 -1
  105. package/javascript/usearch.test.js +0 -74
  106. package/package-ci.json +0 -10
  107. package/pyproject.toml +0 -51
  108. package/setup.py +0 -201
  109. package/simsimd/.releaserc +0 -86
  110. package/simsimd/Cargo.lock +0 -708
  111. package/simsimd/Cargo.toml +0 -36
  112. package/simsimd/LICENSE +0 -201
  113. package/simsimd/README.md +0 -275
  114. package/simsimd/binding.gyp +0 -36
  115. package/simsimd/build.rs +0 -20
  116. package/simsimd/include/simsimd/binary.h +0 -201
  117. package/simsimd/include/simsimd/probability.h +0 -548
  118. package/simsimd/include/simsimd/simsimd.h +0 -456
  119. package/simsimd/include/simsimd/spatial.h +0 -1175
  120. package/simsimd/include/simsimd/types.h +0 -207
  121. package/simsimd/javascript/bench.js +0 -127
  122. package/simsimd/javascript/fallback.ts +0 -193
  123. package/simsimd/javascript/lib.c +0 -102
  124. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  125. package/simsimd/javascript/simsimd.ts +0 -124
  126. package/simsimd/javascript/test.mjs +0 -153
  127. package/simsimd/javascript/tsconfig-base.json +0 -25
  128. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  129. package/simsimd/javascript/tsconfig-esm.json +0 -8
  130. package/simsimd/package-lock.json +0 -1688
  131. package/simsimd/package.json +0 -61
  132. package/simsimd/rust/benches/cosine.rs +0 -27
  133. package/simsimd/rust/benches/native.rs +0 -27
  134. package/simsimd/rust/benches/sqeuclidean.rs +0 -27
  135. package/simsimd/rust/lib.c +0 -68
  136. package/simsimd/rust/lib.rs +0 -232
  137. package/sqlite/README.md +0 -178
  138. package/sqlite/lib.cpp +0 -325
  139. package/stringzilla/CONTRIBUTING.md +0 -429
  140. package/stringzilla/Cargo.lock +0 -25
  141. package/stringzilla/Cargo.toml +0 -26
  142. package/stringzilla/LICENSE +0 -201
  143. package/stringzilla/README.md +0 -1281
  144. package/stringzilla/VERSION +0 -1
  145. package/stringzilla/assets/cover-strinzilla.jpeg +0 -0
  146. package/stringzilla/assets/meme-stringzilla-v2.jpeg +0 -0
  147. package/stringzilla/assets/meme-stringzilla-v3.jpeg +0 -0
  148. package/stringzilla/binding.gyp +0 -16
  149. package/stringzilla/build.rs +0 -14
  150. package/stringzilla/c/lib.c +0 -304
  151. package/stringzilla/cli/README.md +0 -48
  152. package/stringzilla/cli/split.py +0 -72
  153. package/stringzilla/cli/wc.py +0 -37
  154. package/stringzilla/include/stringzilla/experimental.h +0 -724
  155. package/stringzilla/include/stringzilla/module.modulemap +0 -9
  156. package/stringzilla/include/stringzilla/stringzilla.h +0 -5240
  157. package/stringzilla/include/stringzilla/stringzilla.hpp +0 -3830
  158. package/stringzilla/javascript/lib.c +0 -125
  159. package/stringzilla/javascript/stringzilla.js +0 -22
  160. package/stringzilla/package-ci.json +0 -10
  161. package/stringzilla/package.json +0 -32
  162. package/stringzilla/rust/lib.rs +0 -362
  163. package/stringzilla/swift/StringProtocol+StringZilla.swift +0 -280
  164. package/stringzilla/swift/Test.swift +0 -60
  165. package/tsconfig.json +0 -21
  166. package/wasmer.toml +0 -12
  167. package/winlibinstaller.bat +0 -42
  168. /package/{simsimd/javascript/dist-package-cjs.json → javascript/dist/cjs/package.json} +0 -0
  169. /package/{simsimd/javascript/dist-package-esm.json → javascript/dist/esm/package.json} +0 -0
@@ -0,0 +1,531 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
26
+ if (kind === "m") throw new TypeError("Private method is not writable");
27
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
28
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
29
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
30
+ };
31
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
32
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
33
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
34
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
35
+ };
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ var _Index_compiledIndex;
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.Index = exports.BatchMatches = exports.Matches = exports.ScalarKind = exports.MetricKind = void 0;
42
+ const node_gyp_build_1 = __importDefault(require("node-gyp-build"));
43
+ const path = __importStar(require("node:path"));
44
+ const node_fs_1 = require("node:fs");
45
+ const bindings_1 = require("bindings");
46
+ const compiled = (0, node_gyp_build_1.default)(getBuildDir(getDirName()));
47
+ /**
48
+ * Enumeration representing the various metric kinds used to measure the distance between vectors in the index.
49
+ * @enum {string}
50
+ * @readonly
51
+ */
52
+ var MetricKind;
53
+ (function (MetricKind) {
54
+ MetricKind["Unknown"] = "unknown";
55
+ MetricKind["Cos"] = "cos";
56
+ MetricKind["IP"] = "ip";
57
+ MetricKind["L2sq"] = "l2sq";
58
+ MetricKind["Haversine"] = "haversine";
59
+ MetricKind["Divergence"] = "divergence";
60
+ MetricKind["Pearson"] = "pearson";
61
+ MetricKind["Jaccard"] = "jaccard";
62
+ MetricKind["Hamming"] = "hamming";
63
+ MetricKind["Tanimoto"] = "tanimoto";
64
+ MetricKind["Sorensen"] = "sorensen";
65
+ })(MetricKind || (exports.MetricKind = MetricKind = {}));
66
+ /**
67
+ * Enumeration representing the various scalar kinds used to define the type of scalar values in vectors.
68
+ * @enum {string}
69
+ * @readonly
70
+ */
71
+ var ScalarKind;
72
+ (function (ScalarKind) {
73
+ ScalarKind["Unknown"] = "unknown";
74
+ ScalarKind["F32"] = "f32";
75
+ ScalarKind["F64"] = "f64";
76
+ ScalarKind["F16"] = "f16";
77
+ ScalarKind["I8"] = "i8";
78
+ ScalarKind["B1"] = "b1";
79
+ })(ScalarKind || (exports.ScalarKind = ScalarKind = {}));
80
+ /**
81
+ * Represents a set of search results.
82
+ */
83
+ class Matches {
84
+ /**
85
+ * Constructs a Matches object.
86
+ *
87
+ * @param {BigUint64Array} keys - The keys of the nearest neighbors found.
88
+ * @param {Float32Array} distances - The distances of the nearest neighbors found.
89
+ */
90
+ constructor(keys, distances) {
91
+ this.keys = keys;
92
+ this.distances = distances;
93
+ }
94
+ }
95
+ exports.Matches = Matches;
96
+ /**
97
+ * Represents a set of batched search results.
98
+ */
99
+ class BatchMatches {
100
+ /**
101
+ * Constructs a BatchMatches object.
102
+ *
103
+ * @param {BigUint64Array} keys - The keys of the nearest neighbors found in the batch.
104
+ * @param {Float32Array} distances - The distances of the nearest neighbors found in the batch.
105
+ * @param {BigUint64Array} counts - The number of neighbors found for each query in the batch.
106
+ * @param {number} k - The limit for search results per query in the batch.
107
+ */
108
+ constructor(keys, distances, counts, k) {
109
+ this.keys = keys;
110
+ this.distances = distances;
111
+ this.counts = counts;
112
+ this.k = k;
113
+ }
114
+ /**
115
+ * Retrieves a Matches object at the specified index in the batch.
116
+ *
117
+ * @param {number} i - The index at which to retrieve the Matches object.
118
+ * @returns {Matches} - A Matches object representing the search results at the specified index in the batch.
119
+ */
120
+ get(i) {
121
+ const index = Number(i) * Number(this.k);
122
+ const count = Number(this.counts[i]);
123
+ const keysSlice = this.keys.slice(index, index + count);
124
+ const distancesSlice = this.distances.slice(index, index + count);
125
+ return new Matches(keysSlice, distancesSlice);
126
+ }
127
+ }
128
+ exports.BatchMatches = BatchMatches;
129
+ function isOneKey(keys) {
130
+ return ((!Number.isNaN(keys) && typeof keys === "number") ||
131
+ typeof keys === "bigint");
132
+ }
133
+ function normalizeKeys(keys) {
134
+ if (keys instanceof BigUint64Array) {
135
+ return keys;
136
+ }
137
+ let normalizedKeys;
138
+ if ((typeof keys === "number" && !Number.isNaN(keys)) ||
139
+ typeof keys === "bigint") {
140
+ normalizedKeys = BigUint64Array.of(BigInt(keys));
141
+ }
142
+ else if (Array.isArray(keys)) {
143
+ const bigintkeys = keys.map((key) => {
144
+ if (typeof key === "bigint") {
145
+ return key;
146
+ }
147
+ else if (typeof key === "number" &&
148
+ !Number.isNaN(key) &&
149
+ Number.isInteger(key) &&
150
+ key >= 0) {
151
+ return BigInt(key);
152
+ }
153
+ throw new Error("All keys must be positive integers or bigints.");
154
+ });
155
+ normalizedKeys = BigUint64Array.from(bigintkeys);
156
+ }
157
+ else {
158
+ throw new Error("Keys must be a number, bigint, an array of numbers or bigints, or a BigUint64Array.");
159
+ }
160
+ return normalizedKeys;
161
+ }
162
+ function isVector(vectors) {
163
+ return (vectors instanceof Float32Array ||
164
+ vectors instanceof Float64Array ||
165
+ vectors instanceof Int8Array);
166
+ }
167
+ function normalizeVectors(vectors, dimensions, targetType = Float32Array) {
168
+ let flattenedVectors;
169
+ if (isVector(vectors)) {
170
+ flattenedVectors =
171
+ vectors.constructor === targetType
172
+ ? vectors
173
+ : new targetType(vectors);
174
+ }
175
+ else if (Array.isArray(vectors)) {
176
+ let totalLength = 0;
177
+ for (const vec of vectors)
178
+ totalLength += vec.length;
179
+ flattenedVectors = new targetType(totalLength);
180
+ let offset = 0;
181
+ for (const vec of vectors) {
182
+ flattenedVectors.set(vec, offset);
183
+ offset += vec.length;
184
+ }
185
+ }
186
+ else {
187
+ throw new Error("Vectors must be a TypedArray or an array of arrays.");
188
+ }
189
+ if (flattenedVectors.length % dimensions !== 0)
190
+ throw new Error("The size of the flattened vectors must be a multiple of the dimension of the vectors.");
191
+ return flattenedVectors;
192
+ }
193
+ class Index {
194
+ /**
195
+ * Constructs a new index.
196
+ *
197
+ * @param {(number | {dimensions: number, metric: MetricKind = MetricKind.Cos, quantization: ScalarKind = ScalarKind.F32, connectivity: number = 0, expansion_add: number = 0, expansion_search: number = 0, multi: boolean = false})} dimensionsOrConfigs
198
+ * @param {MetricKind} [metric=MetricKind.Cos] - Optional, default is 'cos'.
199
+ * @param {ScalarKind} [quantization=ScalarKind.F32] - Optional, default is 'f32'.
200
+ * @param {number} [connectivity=0] - Optional, default is 0.
201
+ * @param {number} [expansion_add=0] - Optional, default is 0.
202
+ * @param {number} [expansion_search=0] - Optional, default is 0.
203
+ * @param {boolean} [multi=false] - Optional, default is false.
204
+ * @throws Will throw an error if any of the parameters are of incorrect type or invalid value.
205
+ */
206
+ constructor(dimensionsOrConfigs, metric = MetricKind.Cos, quantization = ScalarKind.F32, connectivity = 0, expansion_add = 0, expansion_search = 0, multi = false) {
207
+ _Index_compiledIndex.set(this, void 0);
208
+ let dimensions;
209
+ if ((typeof dimensionsOrConfigs === "number" &&
210
+ !Number.isNaN(dimensionsOrConfigs)) ||
211
+ typeof dimensionsOrConfigs === "bigint") {
212
+ // Parameters are provided as individual arguments
213
+ dimensions = dimensionsOrConfigs;
214
+ }
215
+ else if (typeof dimensionsOrConfigs === "object" &&
216
+ dimensionsOrConfigs !== null) {
217
+ // Parameters are provided as an object
218
+ ({
219
+ dimensions,
220
+ metric = MetricKind.Cos,
221
+ quantization = ScalarKind.F32,
222
+ connectivity = 0,
223
+ expansion_add = 0,
224
+ expansion_search = 0,
225
+ multi = false,
226
+ } = dimensionsOrConfigs);
227
+ }
228
+ else {
229
+ throw new Error("Invalid arguments. Expected either individual arguments or a single object argument.");
230
+ }
231
+ if ((typeof dimensions !== 'bigint' && (!Number.isInteger(dimensions) || dimensions <= 0)) ||
232
+ (typeof connectivity !== 'bigint' && (!Number.isInteger(connectivity) || connectivity < 0)) ||
233
+ (typeof expansion_add !== 'bigint' && (!Number.isInteger(expansion_add) || expansion_add < 0)) ||
234
+ (typeof expansion_search !== 'bigint' && (!Number.isInteger(expansion_search) || expansion_search < 0))) {
235
+ throw new Error("`dimensions`, `connectivity`, `expansion_add`, and `expansion_search` must be non-negative integers, with `dimensions` being positive.");
236
+ }
237
+ if (typeof multi !== "boolean") {
238
+ throw new Error("`multi` must be a boolean value.");
239
+ }
240
+ if (!Object.values(MetricKind).includes(metric)) {
241
+ throw new Error(`Invalid metric: ${metric}. It must be one of: ${Object.values(MetricKind).join(", ")}`);
242
+ }
243
+ if (!Object.values(ScalarKind).includes(quantization)) {
244
+ throw new Error(`Invalid quantization: ${quantization}. It must be one of: ${Object.values(ScalarKind).join(", ")}`);
245
+ }
246
+ // @ts-expect-error
247
+ __classPrivateFieldSet(this, _Index_compiledIndex, new compiled.CompiledIndex(dimensions, metric, quantization, connectivity, expansion_add, expansion_search, multi), "f");
248
+ }
249
+ /**
250
+ * Add vectors to the index.
251
+ *
252
+ * This method accepts vectors and their corresponding keys for indexing.
253
+ * Each key should correspond to a vector. If a single key is provided,
254
+ * it is broadcasted to match the number of provided vectors.
255
+ *
256
+ * Vectors should be provided as a flat typed array representing a matrix
257
+ * where each row is a vector to be indexed. The matrix should have a size
258
+ * of n * d, where n is the number of vectors, and d is the dimensionality
259
+ * of the vectors.
260
+ *
261
+ * Keys should be provided as a BigInt or an array-like object of BigInts
262
+ * representing the unique identifier for each vector.
263
+ *
264
+ * @param {bigint|bigint[]|BigUint64Array} keys - Input identifiers for every vector.
265
+ * If a single key is provided, it is associated with all provided vectors.
266
+ * @param {Float32Array|Float64Array|Int8Array} vectors - Input matrix representing vectors,
267
+ * matrix of size n * d, where n is the number of vectors, and d is their dimensionality.
268
+ * @throws Will throw an error if the length of keys doesn't match the number of vectors
269
+ * or if it's not a single key.
270
+ */
271
+ add(keys, vectors) {
272
+ let normalizedKeys = normalizeKeys(keys);
273
+ let normalizedVectors = normalizeVectors(vectors, __classPrivateFieldGet(this, _Index_compiledIndex, "f").dimensions());
274
+ let countVectors = normalizedVectors.length / __classPrivateFieldGet(this, _Index_compiledIndex, "f").dimensions();
275
+ // If a single key is provided but there are multiple vectors,
276
+ // broadcast the single key value to match the number of vectors
277
+ if (normalizedKeys.length === 1 && countVectors > 1) {
278
+ normalizedKeys = BigUint64Array.from({ length: countVectors }, () => normalizedKeys[0]);
279
+ }
280
+ else if (normalizedKeys.length !== countVectors) {
281
+ throw new Error(`The length of keys (${normalizedKeys.length}) must match the number of vectors (${countVectors}) or be a single key.`);
282
+ }
283
+ // Call the compiled method
284
+ __classPrivateFieldGet(this, _Index_compiledIndex, "f").add(normalizedKeys, normalizedVectors);
285
+ }
286
+ /**
287
+ * Perform a k-nearest neighbor search on the index.
288
+ *
289
+ * This method accepts a matrix of query vectors and returns the closest vectors
290
+ * from the index for each query. The method returns an object containing the keys,
291
+ * distances, and counts of the matches found.
292
+ *
293
+ * Vectors should be provided as a flat typed array representing a matrix where
294
+ * each row is a vector. The matrix should be of size n * d, where n is the
295
+ * number of query vectors, and d is their dimensionality.
296
+ *
297
+ * The parameter `k` specifies the number of nearest neighbors to return for each
298
+ * query vector. If there are not enough results for a query, the result array is
299
+ * padded with -1s.
300
+ *
301
+ * @param {Float32Array|Float64Array|Int8Array|Array<Array<number>>} vectors - Input matrix representing query vectors, can be a TypedArray or an array of TypedArray.
302
+ * @param {number} k - The number of nearest neighbors to search for each query vector.
303
+ * @return {Matches|BatchMatches} - Search results for one or more queries, containing keys, distances, and counts of the matches found.
304
+ * @throws Will throw an error if `k` is not a positive integer or if the size of the vectors is not a multiple of dimensions.
305
+ * @throws Will throw an error if `vectors` is not a valid input type (TypedArray or an array of TypedArray) or if its flattened size is not a multiple of dimensions.
306
+ */
307
+ search(vectors, k) {
308
+ if ((!Number.isNaN(k) && typeof k !== "number") || k <= 0) {
309
+ throw new Error("`k` must be a positive integer representing the number of nearest neighbors to search for.");
310
+ }
311
+ const normalizedVectors = normalizeVectors(vectors, __classPrivateFieldGet(this, _Index_compiledIndex, "f").dimensions());
312
+ // Call the compiled method and create Matches or BatchMatches object with the result
313
+ const result = __classPrivateFieldGet(this, _Index_compiledIndex, "f").search(normalizedVectors, k);
314
+ const countInQueries = normalizedVectors.length / Number(__classPrivateFieldGet(this, _Index_compiledIndex, "f").dimensions());
315
+ const batchMatches = new BatchMatches(...result, k);
316
+ if (countInQueries === 1) {
317
+ return batchMatches.get(0);
318
+ }
319
+ else {
320
+ return batchMatches;
321
+ }
322
+ }
323
+ /**
324
+ * Verifies the presence of one or more keys in the index.
325
+ *
326
+ * This method accepts one or multiple keys as input and returns a boolean or
327
+ * an array of booleans indicating whether each key is present in the index.
328
+ *
329
+ * @param {bigint|bigint[]|BigUint64Array} keys - The identifier(s) of the vector(s) to be checked for presence in the index.
330
+ * @return {boolean|boolean[]} - Returns true if a single key is contained in the index, false otherwise. Returns an array of booleans corresponding to the presence of each key in the index when multiple keys are provided.
331
+ * @throws Will throw an error if keys are not integers.
332
+ */
333
+ contains(keys) {
334
+ let normalizedKeys = normalizeKeys(keys);
335
+ let normalizedResults = __classPrivateFieldGet(this, _Index_compiledIndex, "f").contains(normalizedKeys);
336
+ if (isOneKey(keys))
337
+ return normalizedResults[0];
338
+ else
339
+ return normalizedResults;
340
+ }
341
+ /**
342
+ * Counts the number of times keys shows up in the index.
343
+ *
344
+ * @param {bigint|bigint[]|BigUint64Array} keys - The identifier(s) of the vector(s) to be enumerated.
345
+ * @return {number|number[]} - Returns the number of vectors found when a single key is provided. Returns an array of big integers corresponding to the number of vectors found for each key when multiple keys are provided.
346
+ * @throws Will throw an error if keys are not integers.
347
+ */
348
+ count(keys) {
349
+ let normalizedKeys = normalizeKeys(keys);
350
+ let normalizedResults = __classPrivateFieldGet(this, _Index_compiledIndex, "f").count(normalizedKeys);
351
+ if (isOneKey(keys))
352
+ return normalizedResults[0];
353
+ else
354
+ return normalizedResults;
355
+ }
356
+ /**
357
+ * Removes one or multiple vectors from the index.
358
+ *
359
+ * This method accepts one or multiple keys as input and removes the corresponding vectors from the index.
360
+ * It returns the number of vectors actually removed for each key provided.
361
+ *
362
+ * @param {bigint|bigint[]|BigUint64Array} keys - The identifier(s) of the vector(s) to be removed.
363
+ * @return {number|number[]} - Returns the number of vectors deleted when a single key is provided. Returns an array of big integers corresponding to the number of vectors deleted for each key when multiple keys are provided.
364
+ * @throws Will throw an error if keys are not integers.
365
+ */
366
+ remove(keys) {
367
+ let normalizedKeys = normalizeKeys(keys);
368
+ let normalizedResults = __classPrivateFieldGet(this, _Index_compiledIndex, "f").remove(normalizedKeys);
369
+ if (isOneKey(keys))
370
+ return normalizedResults[0];
371
+ else
372
+ return normalizedResults;
373
+ }
374
+ /**
375
+ * Returns the dimensionality of vectors.
376
+ * @return {number} The dimensionality of vectors.
377
+ */
378
+ dimensions() {
379
+ return __classPrivateFieldGet(this, _Index_compiledIndex, "f").dimensions();
380
+ }
381
+ /**
382
+ * Returns connectivity.
383
+ * @return {number} The connectivity of index.
384
+ */
385
+ connectivity() {
386
+ return __classPrivateFieldGet(this, _Index_compiledIndex, "f").connectivity();
387
+ }
388
+ /**
389
+ * Returns the number of vectors currently indexed.
390
+ * @return {number} The number of vectors currently indexed.
391
+ */
392
+ size() {
393
+ return __classPrivateFieldGet(this, _Index_compiledIndex, "f").size();
394
+ }
395
+ /**
396
+ * Returns index capacity.
397
+ * @return {number} The capacity of index.
398
+ */
399
+ capacity() {
400
+ return __classPrivateFieldGet(this, _Index_compiledIndex, "f").capacity();
401
+ }
402
+ /**
403
+ * Write index to a file.
404
+ * @param {string} path File path to write.
405
+ * @throws Will throw an error if `path` is not a string.
406
+ */
407
+ save(path) {
408
+ if (typeof path !== "string")
409
+ throw new Error("`path` must be a string representing the file path to write.");
410
+ __classPrivateFieldGet(this, _Index_compiledIndex, "f").save(path);
411
+ }
412
+ /**
413
+ * Load index from a file.
414
+ * @param {string} path File path to read.
415
+ * @throws Will throw an error if `path` is not a string.
416
+ */
417
+ load(path) {
418
+ if (typeof path !== "string")
419
+ throw new Error("`path` must be a string representing the file path to read.");
420
+ __classPrivateFieldGet(this, _Index_compiledIndex, "f").load(path);
421
+ }
422
+ /**
423
+ * View index from a file, without loading into RAM.
424
+ * @param {string} path File path to read.
425
+ * @throws Will throw an error if `path` is not a string.
426
+ */
427
+ view(path) {
428
+ if (typeof path !== "string")
429
+ throw new Error("`path` must be a string representing the file path to read.");
430
+ __classPrivateFieldGet(this, _Index_compiledIndex, "f").view(path);
431
+ }
432
+ }
433
+ exports.Index = Index;
434
+ _Index_compiledIndex = new WeakMap();
435
+ /**
436
+ * Performs an exact search on the given dataset to find the best matching vectors for each query.
437
+ *
438
+ * @param {Float32Array|Float64Array|Int8Array|Array<Array<number>>} dataset - The dataset containing vectors to be searched. It can be a TypedArray or an array of arrays.
439
+ * @param {Float32Array|Float64Array|Int8Array|Array<Array<number>>} queries - The queries containing vectors to search for in the dataset. It can be a TypedArray or an array of arrays.
440
+ * @param {number} dimensions - The dimensionality of the vectors in both the dataset and the queries. It defines the number of elements in each vector.
441
+ * @param {number} count - The number of nearest neighbors to return for each query. If the dataset contains fewer vectors than the specified count, the result will contain only the available vectors.
442
+ * @param {MetricKind} metric - The distance metric to be used for the search.
443
+ * @return {Matches|BatchMatches} - Returns a `Matches` or `BatchMatches` object containing the results of the search.
444
+ * @throws Will throw an error if `dimensions` and `count` are not positive integers.
445
+ * @throws Will throw an error if `metric` is not a valid MetricKind.
446
+ * @throws Will throw an error if `dataset` and `queries` are not valid input types (TypedArray or an array of arrays).
447
+ * @throws Will throw an error if the sizes of the flattened `dataset` and `queries` are not multiples of `dimensions`.
448
+ * @throws Will throw an error if `count` is greater than the number of vectors in the `dataset`.
449
+ *
450
+ * @example
451
+ * const dataset = [[1.0, 2.0], [3.0, 4.0]]; // Two vectors: [1.0, 2.0] and [3.0, 4.0]
452
+ * const queries = [[1.5, 2.5]]; // One vector: [1.5, 2.5]
453
+ * const dimensions = 2; // The number of elements in each vector.
454
+ * const count = 1; // The number of nearest neighbors to return for each query.
455
+ * const metric = MetricKind.IP; // Using the Inner Product distance metric.
456
+ *
457
+ * const result = exactSearch(dataset, queries, dimensions, count, metric);
458
+ * // result might be:
459
+ * // {
460
+ * // keys: BigUint64Array [ 1n ],
461
+ * // distances: Float32Array [ some_value ],
462
+ * // }
463
+ */
464
+ function exactSearch(dataset, queries, dimensions, count, metric) {
465
+ // Validate and normalize the dimensions and count
466
+ dimensions = Number(dimensions);
467
+ count = Number(count);
468
+ if (count <= 0 || dimensions <= 0) {
469
+ throw new Error("Dimensions and count must be positive integers.");
470
+ }
471
+ // Validate metric
472
+ if (!Object.values(MetricKind).includes(metric)) {
473
+ throw new Error(`Invalid metric: ${metric}. It must be one of: ${Object.values(MetricKind).join(", ")}`);
474
+ }
475
+ // Flatten and normalize dataset and queries if they are arrays of arrays
476
+ let targetType;
477
+ if (dataset instanceof Float64Array)
478
+ targetType = Float64Array;
479
+ else if (dataset instanceof Int8Array)
480
+ targetType = Int8Array;
481
+ else
482
+ targetType = Float32Array; // default to Float32Array if dataset is not Float64Array or Int8Array
483
+ dataset = normalizeVectors(dataset, dimensions, targetType);
484
+ queries = normalizeVectors(queries, dimensions, targetType);
485
+ const countInDataset = dataset.length / dimensions;
486
+ const countInQueries = queries.length / dimensions;
487
+ if (count > countInDataset) {
488
+ throw new Error("Count must be equal or smaller than the number of vectors in the dataset.");
489
+ }
490
+ // Call the compiled function with the normalized input
491
+ const result = compiled.exactSearch(dataset, queries, dimensions, count, metric);
492
+ // Create and return a Matches or BatchMatches object with the result
493
+ if (countInQueries == 1) {
494
+ return new Matches(result[0], result[1]);
495
+ }
496
+ else {
497
+ return new BatchMatches(...result, count);
498
+ }
499
+ }
500
+ module.exports = {
501
+ Index,
502
+ MetricKind,
503
+ ScalarKind,
504
+ Matches,
505
+ BatchMatches,
506
+ exactSearch,
507
+ };
508
+ // utility functions to help find native builds
509
+ function getBuildDir(dir) {
510
+ if ((0, node_fs_1.existsSync)(path.join(dir, "build")))
511
+ return dir;
512
+ if ((0, node_fs_1.existsSync)(path.join(dir, "prebuilds")))
513
+ return dir;
514
+ if (path.basename(dir) === ".next") {
515
+ // special case for next.js on custom node (not vercel)
516
+ const sideways = path.join(dir, "..", "node_modules", "usearch");
517
+ if ((0, node_fs_1.existsSync)(sideways))
518
+ return getBuildDir(sideways);
519
+ }
520
+ if (dir === "/")
521
+ throw new Error("Could not find native build for usearch");
522
+ return getBuildDir(path.join(dir, ".."));
523
+ }
524
+ function getDirName() {
525
+ try {
526
+ if (__dirname)
527
+ return __dirname;
528
+ }
529
+ catch (e) { }
530
+ return (0, bindings_1.getRoot)((0, bindings_1.getFileName)());
531
+ }