usearch 2.25.1 → 2.26.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/README.md +2 -2
- package/c/lib.cpp +28 -13
- package/cpp/test.cpp +169 -0
- package/include/usearch/index.hpp +364 -58
- package/include/usearch/index_dense.hpp +155 -50
- package/include/usearch/index_plugins.hpp +156 -79
- package/javascript/lib.cpp +4 -2
- package/numkong/CITATION.cff +1 -1
- package/numkong/Cargo.toml +1 -1
- package/numkong/bench/bench_cross_amx.cpp +12 -0
- package/numkong/bench/bench_mesh.cpp +12 -0
- package/numkong/bench/bench_spatial.cpp +0 -3
- package/numkong/binding.gyp +18 -0
- package/numkong/build.rs +1 -0
- package/numkong/c/dispatch_e5m2.c +23 -3
- package/numkong/include/numkong/capabilities.h +1 -1
- package/numkong/include/numkong/cast/README.md +3 -0
- package/numkong/include/numkong/cast/haswell.h +28 -64
- package/numkong/include/numkong/cast/serial.h +17 -0
- package/numkong/include/numkong/cast/skylake.h +67 -52
- package/numkong/include/numkong/cast.h +1 -0
- package/numkong/include/numkong/dot/README.md +1 -0
- package/numkong/include/numkong/dot/haswell.h +92 -13
- package/numkong/include/numkong/dot/serial.h +15 -0
- package/numkong/include/numkong/dot/skylake.h +61 -14
- package/numkong/include/numkong/dots/README.md +2 -0
- package/numkong/include/numkong/dots/graniteamx.h +434 -0
- package/numkong/include/numkong/dots/haswell.h +28 -28
- package/numkong/include/numkong/dots/sapphireamx.h +1 -1
- package/numkong/include/numkong/dots/serial.h +23 -8
- package/numkong/include/numkong/dots/skylake.h +28 -23
- package/numkong/include/numkong/dots.h +12 -0
- package/numkong/include/numkong/each/serial.h +18 -1
- package/numkong/include/numkong/geospatial/serial.h +14 -3
- package/numkong/include/numkong/maxsim/serial.h +15 -0
- package/numkong/include/numkong/mesh/README.md +50 -44
- package/numkong/include/numkong/mesh/genoa.h +462 -0
- package/numkong/include/numkong/mesh/haswell.h +806 -933
- package/numkong/include/numkong/mesh/neon.h +871 -943
- package/numkong/include/numkong/mesh/neonbfdot.h +382 -522
- package/numkong/include/numkong/mesh/neonfhm.h +676 -0
- package/numkong/include/numkong/mesh/rvv.h +404 -319
- package/numkong/include/numkong/mesh/serial.h +204 -162
- package/numkong/include/numkong/mesh/skylake.h +1029 -1585
- package/numkong/include/numkong/mesh/v128relaxed.h +403 -377
- package/numkong/include/numkong/mesh.h +38 -0
- package/numkong/include/numkong/reduce/serial.h +15 -1
- package/numkong/include/numkong/sparse/serial.h +17 -2
- package/numkong/include/numkong/spatial/genoa.h +0 -68
- package/numkong/include/numkong/spatial/haswell.h +98 -56
- package/numkong/include/numkong/spatial/serial.h +15 -0
- package/numkong/include/numkong/spatial/skylake.h +114 -54
- package/numkong/include/numkong/spatial.h +0 -12
- package/numkong/include/numkong/spatials/graniteamx.h +128 -0
- package/numkong/include/numkong/spatials/serial.h +18 -1
- package/numkong/include/numkong/spatials/skylake.h +2 -2
- package/numkong/include/numkong/spatials.h +17 -0
- package/numkong/include/numkong/tensor.hpp +107 -23
- package/numkong/javascript/@numkong-darwin-arm64/package.json +1 -1
- package/numkong/javascript/@numkong-darwin-x64/package.json +1 -1
- package/numkong/javascript/@numkong-linux-arm64/package.json +1 -1
- package/numkong/javascript/@numkong-linux-x64/package.json +1 -1
- package/numkong/javascript/@numkong-win32-arm64/package.json +1 -1
- package/numkong/javascript/@numkong-win32-x64/package.json +1 -1
- package/numkong/javascript/numkong.c +3 -2
- package/numkong/package.json +7 -7
- package/numkong/test/test.cu +841 -0
- package/numkong/test/test_cross_amx.cpp +13 -0
- package/numkong/test/test_dlpack.py +492 -0
- package/numkong/test/test_mesh.cpp +12 -0
- package/numkong/test/test_spatial.cpp +0 -3
- package/numkong/test/test_tensor.cpp +87 -27
- package/package.json +2 -2
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/prebuilds/win32-x64/usearch.node +0 -0
|
@@ -96,62 +96,100 @@ void test_tensor_operator_indexing() {
|
|
|
96
96
|
|
|
97
97
|
assert(t[0] == 1.0f && "flat tensor lookup failed");
|
|
98
98
|
assert(t[-1] == 6.0f && "negative flat tensor lookup failed");
|
|
99
|
-
assert((t
|
|
100
|
-
assert((t
|
|
99
|
+
assert((t(0, 0) == 1.0f) && "exact tensor lookup failed");
|
|
100
|
+
assert((t(1, -1) == 6.0f) && "negative exact tensor lookup failed");
|
|
101
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
102
|
+
assert((t[0, 0] == 1.0f) && "exact tensor lookup via operator[] failed");
|
|
103
|
+
assert((t[1, -1] == 6.0f) && "negative exact tensor lookup via operator[] failed");
|
|
104
|
+
#endif
|
|
101
105
|
|
|
102
106
|
auto whole = t[nk::slice];
|
|
103
107
|
assert(whole.rank() == 2 && "slice identity rank mismatch");
|
|
104
108
|
assert(whole.extent(0) == 2 && whole.extent(1) == 3 && "slice identity extents mismatch");
|
|
105
109
|
|
|
106
|
-
auto row1 = t
|
|
110
|
+
auto row1 = t(1, nk::slice);
|
|
107
111
|
assert(row1.rank() == 1 && "row slice rank mismatch");
|
|
108
112
|
assert(row1.extent(0) == 3 && "row slice extent mismatch");
|
|
109
113
|
assert(row1[0] == 4.0f && row1[-1] == 6.0f && "row slice values mismatch");
|
|
110
114
|
row1[1] = 42.0f;
|
|
111
|
-
assert((t
|
|
115
|
+
assert((t(1, 1) == 42.0f) && "row slice write-through failed");
|
|
116
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
117
|
+
assert((t[1, 1] == 42.0f) && "operator[] row slice write-through failed");
|
|
118
|
+
auto row1_subscript = t[1, nk::slice];
|
|
119
|
+
assert(row1_subscript.extent(0) == row1.extent(0) && "operator[] row slice mismatch");
|
|
120
|
+
#endif
|
|
112
121
|
|
|
113
|
-
auto cell = t
|
|
122
|
+
auto cell = t(1, 1, nk::slice);
|
|
114
123
|
assert(cell.rank() == 0 && "scalar slice rank mismatch");
|
|
115
124
|
assert(cell.scalar() == 42.0f && "scalar slice value mismatch");
|
|
116
125
|
cell.scalar_ref() = 24.0f;
|
|
117
|
-
assert((t
|
|
126
|
+
assert((t(1, 1) == 24.0f) && "scalar slice write-through failed");
|
|
127
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
128
|
+
assert((t[1, 1] == 24.0f) && "operator[] scalar slice write-through failed");
|
|
129
|
+
auto cell_subscript = t[1, 1, nk::slice];
|
|
130
|
+
assert(cell_subscript.rank() == 0 && "operator[] scalar slice rank mismatch");
|
|
131
|
+
#endif
|
|
118
132
|
|
|
119
133
|
auto const &ct = t;
|
|
120
|
-
auto const last_row = ct
|
|
134
|
+
auto const last_row = ct(-1, nk::slice);
|
|
121
135
|
assert(last_row.rank() == 1 && "const row slice rank mismatch");
|
|
122
136
|
assert(last_row[0] == 4.0f && "const row slice mismatch");
|
|
137
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
138
|
+
auto const last_row_subscript = ct[-1, nk::slice];
|
|
139
|
+
assert(last_row_subscript.rank() == 1 && "operator[] const row slice mismatch");
|
|
140
|
+
#endif
|
|
123
141
|
|
|
124
142
|
auto cube = nk::tensor<float>::try_zeros({2, 3, 4});
|
|
125
143
|
assert(!cube.empty() && "cube allocation failed");
|
|
126
144
|
for (int i = 0; i < 24; ++i) cube[i] = static_cast<float>(i);
|
|
127
145
|
|
|
128
|
-
auto plane = cube
|
|
146
|
+
auto plane = cube(1, nk::slice);
|
|
129
147
|
assert(plane.rank() == 2 && plane.extent(0) == 3 && plane.extent(1) == 4 && "plane slice mismatch");
|
|
130
|
-
auto line = cube
|
|
148
|
+
auto line = cube(1, 2, nk::slice);
|
|
131
149
|
assert(line.rank() == 1 && line.extent(0) == 4 && "line slice mismatch");
|
|
132
|
-
assert((line[3] == cube
|
|
133
|
-
auto point = cube
|
|
134
|
-
assert((point.rank() == 0 && point.scalar() == cube
|
|
150
|
+
assert((line[3] == cube(1, 2, 3)) && "line slice element mismatch");
|
|
151
|
+
auto point = cube(1, 2, 3, nk::slice);
|
|
152
|
+
assert((point.rank() == 0 && point.scalar() == cube(1, 2, 3)) && "point slice mismatch");
|
|
153
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
154
|
+
auto plane_subscript = cube[1, nk::slice];
|
|
155
|
+
auto line_subscript = cube[1, 2, nk::slice];
|
|
156
|
+
auto point_subscript = cube[1, 2, 3, nk::slice];
|
|
157
|
+
assert((line_subscript[3] == cube[1, 2, 3]) && "operator[] line slice element mismatch");
|
|
158
|
+
assert((point_subscript.scalar() == cube[1, 2, 3]) && "operator[] point slice mismatch");
|
|
159
|
+
assert(plane_subscript.rank() == 2 && "operator[] plane slice rank mismatch");
|
|
160
|
+
#endif
|
|
135
161
|
|
|
136
162
|
// all_t slicing: extract a column
|
|
137
|
-
auto second_column = t
|
|
163
|
+
auto second_column = t(nk::all, 1, nk::slice);
|
|
138
164
|
assert(second_column.rank() == 1 && "all_t column rank mismatch");
|
|
139
165
|
assert(second_column.numel() == 2 && "all_t column numel mismatch");
|
|
140
166
|
|
|
141
167
|
// range slicing: extract a sub-range of rows
|
|
142
|
-
auto first_two_planes = cube
|
|
168
|
+
auto first_two_planes = cube(nk::range(0, 2), nk::slice);
|
|
143
169
|
assert(first_two_planes.rank() == 3 && "range slice rank mismatch");
|
|
144
170
|
assert(first_two_planes.extent(0) == 2 && "range slice extent mismatch");
|
|
145
171
|
|
|
146
172
|
// combined: range + all_t + slice on a 3D tensor
|
|
147
|
-
auto sub = cube
|
|
173
|
+
auto sub = cube(nk::range(0, 2), nk::all, nk::slice);
|
|
148
174
|
assert(sub.rank() == 3 && sub.extent(0) == 2 && sub.extent(1) == 3 && "range+all slice mismatch");
|
|
175
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
176
|
+
auto second_column_subscript = t[nk::all, 1, nk::slice];
|
|
177
|
+
auto first_two_planes_subscript = cube[nk::range(0, 2), nk::slice];
|
|
178
|
+
auto sub_subscript = cube[nk::range(0, 2), nk::all, nk::slice];
|
|
179
|
+
assert(second_column_subscript.numel() == 2 && "operator[] all_t column mismatch");
|
|
180
|
+
assert(first_two_planes_subscript.extent(0) == 2 && "operator[] range slice mismatch");
|
|
181
|
+
assert(sub_subscript.extent(1) == 3 && "operator[] range+all slice mismatch");
|
|
182
|
+
#endif
|
|
149
183
|
|
|
150
184
|
// row() access
|
|
151
185
|
auto row0 = t.row(0);
|
|
152
186
|
assert(row0.rank() == 1 && row0.extent(0) == 3 && "row() rank/extent mismatch");
|
|
153
|
-
auto row0_via_slice = t
|
|
154
|
-
assert(row0[0] == row0_via_slice[0] && "row() should match t
|
|
187
|
+
auto row0_via_slice = t(0, nk::slice);
|
|
188
|
+
assert(row0[0] == row0_via_slice[0] && "row() should match t(0, slice)");
|
|
189
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
190
|
+
auto row0_via_subscript = t[0, nk::slice];
|
|
191
|
+
assert(row0[0] == row0_via_subscript[0] && "row() should match t[0, slice]");
|
|
192
|
+
#endif
|
|
155
193
|
}
|
|
156
194
|
|
|
157
195
|
void test_packed_tensor_operator_indexing() {
|
|
@@ -162,14 +200,23 @@ void test_packed_tensor_operator_indexing() {
|
|
|
162
200
|
|
|
163
201
|
assert(int(t4[0]) == 1 && "packed flat lookup failed");
|
|
164
202
|
assert(int(t4[-1]) == 8 && "packed negative flat lookup failed");
|
|
165
|
-
assert((int(t4
|
|
166
|
-
assert((int(t4
|
|
203
|
+
assert((int(t4(0, 3)) == 4) && "packed exact lookup failed");
|
|
204
|
+
assert((int(t4(1, -1)) == 8) && "packed negative exact lookup failed");
|
|
205
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
206
|
+
assert((int(t4[0, 3]) == 4) && "packed operator[] exact lookup failed");
|
|
207
|
+
assert((int(t4[1, -1]) == 8) && "packed operator[] negative exact lookup failed");
|
|
208
|
+
#endif
|
|
167
209
|
|
|
168
|
-
auto second_row = t4
|
|
210
|
+
auto second_row = t4(1, nk::slice);
|
|
169
211
|
assert(second_row.rank() == 1 && second_row.extent(0) == 4 && "packed row slice rank mismatch");
|
|
170
212
|
assert(int(second_row[0]) == 5 && int(second_row[-1]) == 8 && "packed row slice values mismatch");
|
|
171
213
|
second_row[1] = 14;
|
|
172
|
-
assert((int(t4
|
|
214
|
+
assert((int(t4(1, 1)) == 14) && "packed row slice write-through failed");
|
|
215
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
216
|
+
auto second_row_subscript = t4[1, nk::slice];
|
|
217
|
+
assert(second_row_subscript.extent(0) == 4 && "packed operator[] row slice rank mismatch");
|
|
218
|
+
assert((int(t4[1, 1]) == 14) && "packed operator[] row slice write-through failed");
|
|
219
|
+
#endif
|
|
173
220
|
|
|
174
221
|
auto t1 = nk::tensor<nk::u1x8_t>::try_zeros({2, 8});
|
|
175
222
|
assert(!t1.empty() && "packed u1 tensor allocation failed");
|
|
@@ -179,14 +226,23 @@ void test_packed_tensor_operator_indexing() {
|
|
|
179
226
|
t1[-1] = true;
|
|
180
227
|
|
|
181
228
|
assert(bool(t1[0]) && "packed bit flat lookup failed");
|
|
182
|
-
assert((bool(t1
|
|
183
|
-
assert((bool(t1
|
|
229
|
+
assert((bool(t1(0, 7))) && "packed bit exact lookup failed");
|
|
230
|
+
assert((bool(t1(1, 3))) && "packed bit second-row lookup failed");
|
|
184
231
|
assert(bool(t1[-1]) && "packed bit negative flat lookup failed");
|
|
232
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
233
|
+
assert((bool(t1[0, 7])) && "packed bit operator[] exact lookup failed");
|
|
234
|
+
assert((bool(t1[1, 3])) && "packed bit operator[] second-row lookup failed");
|
|
235
|
+
#endif
|
|
185
236
|
|
|
186
|
-
auto bits = t1
|
|
237
|
+
auto bits = t1(1, nk::slice);
|
|
187
238
|
assert(bits.rank() == 1 && bits.extent(0) == 8 && "packed bit slice rank mismatch");
|
|
188
239
|
bits[4] = true;
|
|
189
|
-
assert((bool(t1
|
|
240
|
+
assert((bool(t1(1, 4))) && "packed bit slice write-through failed");
|
|
241
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
242
|
+
auto bits_subscript = t1[1, nk::slice];
|
|
243
|
+
assert(bits_subscript.extent(0) == 8 && "packed bit operator[] slice rank mismatch");
|
|
244
|
+
assert((bool(t1[1, 4])) && "packed bit operator[] slice write-through failed");
|
|
245
|
+
#endif
|
|
190
246
|
}
|
|
191
247
|
|
|
192
248
|
void test_move_semantics() {
|
|
@@ -470,8 +526,12 @@ void test_packed_tensor_fail_closed_views() {
|
|
|
470
526
|
auto packed = nk::tensor<nk::i4x2_t>::try_zeros({2, 4});
|
|
471
527
|
assert(!packed.empty() && "packed tensor allocation failed");
|
|
472
528
|
assert(packed.view().transpose().empty() && "packed transpose should fail closed");
|
|
473
|
-
assert((!packed
|
|
474
|
-
assert((packed
|
|
529
|
+
assert((!packed(1, nk::slice).empty()) && "packed row slice should remain supported");
|
|
530
|
+
assert((packed(1, 2, nk::slice).empty()) && "packed scalar trailing slice should fail closed");
|
|
531
|
+
#if NK_HAS_MULTIDIMENSIONAL_SUBSCRIPT_
|
|
532
|
+
assert((!packed[1, nk::slice].empty()) && "packed operator[] row slice should remain supported");
|
|
533
|
+
assert((packed[1, 2, nk::slice].empty()) && "packed operator[] scalar trailing slice should fail closed");
|
|
534
|
+
#endif
|
|
475
535
|
}
|
|
476
536
|
|
|
477
537
|
void test_vector_types() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usearch",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.26.0",
|
|
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",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"email": "info@unum.cloud"
|
|
15
15
|
},
|
|
16
16
|
"engines": {
|
|
17
|
-
"node": ">=
|
|
17
|
+
"node": ">=22"
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"binding.gyp",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|