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
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ Linux • macOS • Windows • iOS • Android • WebAssembly •
|
|
|
42
42
|
<a href="https://crates.io/crates/usearch"> <img alt="Crate" src="https://img.shields.io/crates/d/usearch?label=Rust%20Crate%20installs"> </a>
|
|
43
43
|
<a href="https://www.nuget.org/packages/Cloud.Unum.USearch"> <img alt="NuGet" src="https://img.shields.io/nuget/dt/Cloud.Unum.USearch?label=CSharp%20NuGet%20installs"> </a>
|
|
44
44
|
<!-- Maven Central publishing is deprecated for now; fat-JAR download is the supported path. -->
|
|
45
|
-
<img alt="GitHub code size in bytes" src="https://img.shields.io/github/languages/code-size/unum-cloud/
|
|
45
|
+
<img alt="GitHub code size in bytes" src="https://img.shields.io/github/languages/code-size/unum-cloud/USearch?label=Repo%20size">
|
|
46
46
|
</div>
|
|
47
47
|
|
|
48
48
|
---
|
|
@@ -549,7 +549,7 @@ doi = {10.5281/zenodo.7949416},
|
|
|
549
549
|
author = {Vardanian, Ash},
|
|
550
550
|
title = {{USearch by Unum Cloud}},
|
|
551
551
|
url = {https://github.com/unum-cloud/USearch},
|
|
552
|
-
version = {2.
|
|
552
|
+
version = {2.26.0},
|
|
553
553
|
year = {2026},
|
|
554
554
|
}
|
|
555
555
|
```
|
package/c/lib.cpp
CHANGED
|
@@ -186,16 +186,14 @@ USEARCH_EXPORT usearch_index_t usearch_init(usearch_init_options_t* options, use
|
|
|
186
186
|
|
|
187
187
|
using state_result_t = typename index_dense_t::state_result_t;
|
|
188
188
|
state_result_t state = index_dense_t::make(metric, config);
|
|
189
|
-
if (!state)
|
|
189
|
+
if (!state) {
|
|
190
190
|
*error = state.error.release();
|
|
191
|
-
|
|
191
|
+
return NULL;
|
|
192
|
+
}
|
|
193
|
+
index_dense_t* result_ptr = new (std::nothrow) index_dense_t(std::move(state.index));
|
|
192
194
|
if (!result_ptr)
|
|
193
195
|
*error = "Out of memory!";
|
|
194
196
|
|
|
195
|
-
// Let's immediately make it usable by reserving enough threads for this machine:
|
|
196
|
-
if (!result_ptr->try_reserve(index_limits_t()))
|
|
197
|
-
*error = "Out of memory when preparing contexts!";
|
|
198
|
-
|
|
199
197
|
return result_ptr;
|
|
200
198
|
}
|
|
201
199
|
|
|
@@ -236,8 +234,10 @@ USEARCH_EXPORT void usearch_metadata(char const* path, usearch_init_options_t* o
|
|
|
236
234
|
|
|
237
235
|
USEARCH_ASSERT(path && options && error && "Missing arguments");
|
|
238
236
|
index_dense_metadata_result_t result = index_dense_metadata_from_path(path);
|
|
239
|
-
if (!result)
|
|
237
|
+
if (!result) {
|
|
240
238
|
*error = result.error.release();
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
241
|
|
|
242
242
|
options->metric_kind = metric_kind_to_c(result.head.kind_metric);
|
|
243
243
|
options->quantization = scalar_kind_to_c(result.head.kind_scalar);
|
|
@@ -285,8 +285,10 @@ USEARCH_EXPORT void usearch_metadata_buffer(void const* buffer, size_t length, u
|
|
|
285
285
|
USEARCH_ASSERT(buffer && length && options && error && "Missing arguments");
|
|
286
286
|
index_dense_metadata_result_t result =
|
|
287
287
|
index_dense_metadata_from_buffer(memory_mapped_file_t((byte_t*)(buffer), length));
|
|
288
|
-
if (!result)
|
|
288
|
+
if (!result) {
|
|
289
289
|
*error = result.error.release();
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
290
292
|
|
|
291
293
|
options->metric_kind = metric_kind_to_c(result.head.kind_metric);
|
|
292
294
|
options->quantization = scalar_kind_to_c(result.head.kind_scalar);
|
|
@@ -354,7 +356,8 @@ USEARCH_EXPORT void usearch_change_threads_add(usearch_index_t index, size_t thr
|
|
|
354
356
|
auto& index_dense = *reinterpret_cast<index_dense_t*>(index);
|
|
355
357
|
index_limits_t limits = index_dense.limits();
|
|
356
358
|
limits.threads_add = threads;
|
|
357
|
-
index_dense.try_reserve(limits)
|
|
359
|
+
if (!index_dense.try_reserve(limits))
|
|
360
|
+
*error = "Out of memory!";
|
|
358
361
|
}
|
|
359
362
|
|
|
360
363
|
USEARCH_EXPORT void usearch_change_threads_search(usearch_index_t index, size_t threads, usearch_error_t* error) {
|
|
@@ -362,15 +365,22 @@ USEARCH_EXPORT void usearch_change_threads_search(usearch_index_t index, size_t
|
|
|
362
365
|
auto& index_dense = *reinterpret_cast<index_dense_t*>(index);
|
|
363
366
|
index_limits_t limits = index_dense.limits();
|
|
364
367
|
limits.threads_search = threads;
|
|
365
|
-
index_dense.try_reserve(limits)
|
|
368
|
+
if (!index_dense.try_reserve(limits))
|
|
369
|
+
*error = "Out of memory!";
|
|
366
370
|
}
|
|
367
371
|
|
|
368
372
|
USEARCH_EXPORT void usearch_change_metric_kind(usearch_index_t index, usearch_metric_kind_t kind,
|
|
369
373
|
usearch_error_t* error) {
|
|
370
374
|
USEARCH_ASSERT(index && error && "Missing arguments");
|
|
371
375
|
auto& index_dense = *reinterpret_cast<index_dense_t*>(index);
|
|
372
|
-
|
|
373
|
-
metric_punned_t::builtin(index_dense.dimensions(), metric_kind_to_cpp(kind), index_dense.scalar_kind())
|
|
376
|
+
auto metric_punned =
|
|
377
|
+
metric_punned_t::builtin(index_dense.dimensions(), metric_kind_to_cpp(kind), index_dense.scalar_kind());
|
|
378
|
+
if (metric_punned.missing()) {
|
|
379
|
+
*error = "Unsupported metric for this index's dimensions and scalar kind!";
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (!index_dense.try_change_metric(std::move(metric_punned)))
|
|
383
|
+
*error = "Failed to grow cast buffer for the new metric!";
|
|
374
384
|
}
|
|
375
385
|
|
|
376
386
|
USEARCH_EXPORT void usearch_change_metric(usearch_index_t index, usearch_metric_t metric, void* state,
|
|
@@ -384,7 +394,12 @@ USEARCH_EXPORT void usearch_change_metric(usearch_index_t index, usearch_metric_
|
|
|
384
394
|
: metric_punned_t::stateless(index_dense.dimensions(), reinterpret_cast<std::uintptr_t>(metric),
|
|
385
395
|
metric_punned_signature_t::array_array_k, metric_kind_to_cpp(kind),
|
|
386
396
|
index_dense.scalar_kind());
|
|
387
|
-
|
|
397
|
+
if (metric_punned.missing()) {
|
|
398
|
+
*error = "Unsupported metric for this index's dimensions and scalar kind!";
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (!index_dense.try_change_metric(std::move(metric_punned)))
|
|
402
|
+
*error = "Failed to grow cast buffer for the new metric!";
|
|
388
403
|
}
|
|
389
404
|
|
|
390
405
|
USEARCH_EXPORT void usearch_reserve(usearch_index_t index, size_t capacity, usearch_error_t* error) {
|
package/cpp/test.cpp
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
#include <csignal> // `std::signal`, `SIGSEGV`, ...
|
|
18
18
|
#include <cstdio> // `std::fprintf`
|
|
19
19
|
#include <cstdlib> // `std::_Exit`
|
|
20
|
+
#include <limits> // `std::numeric_limits`
|
|
20
21
|
|
|
21
22
|
#include <algorithm> // `std::shuffle`
|
|
22
23
|
#include <random> // `std::default_random_engine`
|
|
@@ -216,6 +217,47 @@ void test_uint40() {
|
|
|
216
217
|
expect_eq(u40_default, uint40_t(0u));
|
|
217
218
|
}
|
|
218
219
|
|
|
220
|
+
void test_checked_size_arithmetic() {
|
|
221
|
+
|
|
222
|
+
std::printf("Testing checked size arithmetic\n");
|
|
223
|
+
std::size_t max = (std::numeric_limits<std::size_t>::max)();
|
|
224
|
+
|
|
225
|
+
checked_size_result_t cast = checked_size_from_u64(42);
|
|
226
|
+
expect(cast);
|
|
227
|
+
expect_eq(cast.value, static_cast<std::size_t>(42));
|
|
228
|
+
if (sizeof(std::size_t) < sizeof(std::uint64_t))
|
|
229
|
+
expect(!checked_size_from_u64((std::numeric_limits<std::uint64_t>::max)()));
|
|
230
|
+
|
|
231
|
+
checked_size_result_t sum = checked_add(max - 1, 1);
|
|
232
|
+
expect(sum);
|
|
233
|
+
expect_eq(sum.value, max);
|
|
234
|
+
expect(!checked_add(max, 1));
|
|
235
|
+
|
|
236
|
+
checked_size_result_t product = checked_mul(max / 2, 2);
|
|
237
|
+
expect(product);
|
|
238
|
+
expect_eq(product.value, max - 1);
|
|
239
|
+
expect(!checked_mul(max / 2 + 1, 2));
|
|
240
|
+
|
|
241
|
+
checked_size_result_t fused = checked_mul_add(10, 20, 30);
|
|
242
|
+
expect(fused);
|
|
243
|
+
expect_eq(fused.value, static_cast<std::size_t>(230));
|
|
244
|
+
expect(!checked_mul_add(max / 2 + 1, 2, 0));
|
|
245
|
+
expect(!checked_mul_add(max / 2, 2, 2));
|
|
246
|
+
|
|
247
|
+
checked_size_result_t rounded = checked_round_up(17, 8);
|
|
248
|
+
expect(rounded);
|
|
249
|
+
expect_eq(rounded.value, static_cast<std::size_t>(24));
|
|
250
|
+
expect(!checked_round_up(max, 8));
|
|
251
|
+
|
|
252
|
+
checked_size_result_t power = checked_ceil2(17);
|
|
253
|
+
expect(power);
|
|
254
|
+
expect_eq(power.value, static_cast<std::size_t>(32));
|
|
255
|
+
checked_size_result_t zero_power = checked_ceil2(0);
|
|
256
|
+
expect(zero_power);
|
|
257
|
+
expect_eq(zero_power.value, static_cast<std::size_t>(0));
|
|
258
|
+
expect(!checked_ceil2(max));
|
|
259
|
+
}
|
|
260
|
+
|
|
219
261
|
/**
|
|
220
262
|
* @brief Tests the functionality of the custom float16_t type ensuring consistent.
|
|
221
263
|
*/
|
|
@@ -1073,6 +1115,72 @@ template <typename key_at, typename slot_at> void test_strings() {
|
|
|
1073
1115
|
/**
|
|
1074
1116
|
* @brief Tests replacing and updating entries in index_dense_gt to ensure consistency after modifications.
|
|
1075
1117
|
*/
|
|
1118
|
+
/**
|
|
1119
|
+
* @brief Churns a tightly-reserved index, so `slot_lookup_` accumulates tombstones.
|
|
1120
|
+
*
|
|
1121
|
+
* Removals leave tombstones that probes must walk past. If they are never reclaimed the
|
|
1122
|
+
* table runs out of empty slots, probes can no longer terminate, and live keys go missing:
|
|
1123
|
+
* `remove` reports nothing removed while `contains` still finds the key. Copying such a
|
|
1124
|
+
* table must rebuild the probe chains, not reproduce the slot layout.
|
|
1125
|
+
*/
|
|
1126
|
+
template <typename key_at, typename slot_at> void test_slot_lookup_churn() {
|
|
1127
|
+
constexpr std::size_t live_count = 128;
|
|
1128
|
+
constexpr std::size_t churn_count = live_count * 8;
|
|
1129
|
+
constexpr std::size_t dimensions = 4;
|
|
1130
|
+
|
|
1131
|
+
using index_punned_t = index_dense_gt<key_at, slot_at>;
|
|
1132
|
+
metric_punned_t metric(dimensions, metric_kind_t::cos_k);
|
|
1133
|
+
|
|
1134
|
+
std::random_device seed_source;
|
|
1135
|
+
std::mt19937 generator(seed_source());
|
|
1136
|
+
std::uniform_real_distribution<float> distribution(0.0, 1.0);
|
|
1137
|
+
using vector_of_vectors_t = std::vector<std::vector<float>>;
|
|
1138
|
+
|
|
1139
|
+
vector_of_vectors_t vector_of_vectors(live_count + churn_count);
|
|
1140
|
+
for (auto& vector : vector_of_vectors) {
|
|
1141
|
+
vector.resize(dimensions);
|
|
1142
|
+
std::generate(vector.begin(), vector.end(), [&] { return distribution(generator); });
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
index_punned_t index = index_punned_t::make(metric);
|
|
1146
|
+
|
|
1147
|
+
// Reserve tightly, so the churn below exhausts the empty slots
|
|
1148
|
+
index.reserve(live_count * 3);
|
|
1149
|
+
|
|
1150
|
+
std::vector<key_at> live_keys;
|
|
1151
|
+
std::size_t added = 0;
|
|
1152
|
+
for (; added < live_count; ++added) {
|
|
1153
|
+
index.add(static_cast<key_at>(added), vector_of_vectors[added].data());
|
|
1154
|
+
live_keys.push_back(static_cast<key_at>(added));
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// Every iteration frees one slot and immediately reuses it
|
|
1158
|
+
for (std::size_t idx = 0; idx < churn_count; ++idx, ++added) {
|
|
1159
|
+
key_at victim = live_keys[idx % live_count];
|
|
1160
|
+
expect(index.contains(victim));
|
|
1161
|
+
expect_eq(index.remove(victim).completed, 1);
|
|
1162
|
+
expect(!index.contains(victim));
|
|
1163
|
+
index.add(static_cast<key_at>(added), vector_of_vectors[added].data());
|
|
1164
|
+
live_keys[idx % live_count] = static_cast<key_at>(added);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// Every live key stays reachable and the size never drifts
|
|
1168
|
+
expect_eq(index.size(), live_count);
|
|
1169
|
+
for (key_at key : live_keys)
|
|
1170
|
+
expect(index.contains(key));
|
|
1171
|
+
|
|
1172
|
+
// Copying a table that still holds tombstones must not strand live keys
|
|
1173
|
+
expect_eq(index.remove(live_keys.back()).completed, 1);
|
|
1174
|
+
live_keys.pop_back();
|
|
1175
|
+
|
|
1176
|
+
auto copy_result = index.copy();
|
|
1177
|
+
expect(copy_result);
|
|
1178
|
+
index_punned_t& copy = copy_result.index;
|
|
1179
|
+
expect_eq(copy.size(), live_keys.size());
|
|
1180
|
+
for (key_at key : live_keys)
|
|
1181
|
+
expect(copy.contains(key));
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1076
1184
|
template <typename key_at, typename slot_at> void test_replacing_update() {
|
|
1077
1185
|
|
|
1078
1186
|
using vector_key_t = key_at;
|
|
@@ -1264,6 +1372,61 @@ static void install_crash_handlers() {
|
|
|
1264
1372
|
std::signal(signal_number, &usearch_crash_handler);
|
|
1265
1373
|
}
|
|
1266
1374
|
|
|
1375
|
+
/**
|
|
1376
|
+
* @brief Regression test: `make(metric, config)` must return an index that is
|
|
1377
|
+
* immediately usable - no explicit `reserve` required before `load` /
|
|
1378
|
+
* `view` / `search`. Previously the typed graph's `{0, 0}` thread
|
|
1379
|
+
* limits leaked into `load_from_stream`, leaving `available_threads_`
|
|
1380
|
+
* empty and making the first `search` throw "No available threads to
|
|
1381
|
+
* lock".
|
|
1382
|
+
*/
|
|
1383
|
+
void test_load_after_metric_make() {
|
|
1384
|
+
std::printf("Testing load and view into a metric-made index\n");
|
|
1385
|
+
|
|
1386
|
+
using index_t = index_dense_gt<std::int64_t, std::uint32_t>;
|
|
1387
|
+
std::size_t const dimensions = 32;
|
|
1388
|
+
std::size_t const collection = 64;
|
|
1389
|
+
|
|
1390
|
+
std::default_random_engine rng(7);
|
|
1391
|
+
std::uniform_real_distribution<float> distribution(-1.f, 1.f);
|
|
1392
|
+
std::vector<std::vector<float>> data(collection);
|
|
1393
|
+
for (auto& vector : data) {
|
|
1394
|
+
vector.resize(dimensions);
|
|
1395
|
+
for (auto& value : vector)
|
|
1396
|
+
value = distribution(rng);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
metric_punned_t metric(dimensions, metric_kind_t::cos_k, scalar_kind<f32_t>());
|
|
1400
|
+
index_dense_config_t config(16);
|
|
1401
|
+
|
|
1402
|
+
// Build an index and persist it to disk.
|
|
1403
|
+
index_t::state_result_t built = index_t::make(metric, config);
|
|
1404
|
+
expect(built);
|
|
1405
|
+
expect(built.index.try_reserve(collection));
|
|
1406
|
+
for (std::size_t i = 0; i != collection; ++i)
|
|
1407
|
+
expect(built.index.add(static_cast<std::int64_t>(i), data[i].data()));
|
|
1408
|
+
char const* path = "tmp_metric_make.usearch";
|
|
1409
|
+
expect(built.index.save(path));
|
|
1410
|
+
|
|
1411
|
+
// Load into a fresh, metric-made index that was never explicitly reserved.
|
|
1412
|
+
// The first `search` must not throw "No available threads to lock".
|
|
1413
|
+
index_t::state_result_t loaded = index_t::make(metric, config);
|
|
1414
|
+
expect(loaded);
|
|
1415
|
+
expect(loaded.index.load(path));
|
|
1416
|
+
expect_eq(loaded.index.size(), collection);
|
|
1417
|
+
std::int64_t found[8];
|
|
1418
|
+
expect(loaded.index.search(data[0].data(), 5).dump_to(found) != 0);
|
|
1419
|
+
|
|
1420
|
+
// Same check for the memory-mapped `view` path.
|
|
1421
|
+
index_t::state_result_t viewed = index_t::make(metric, config);
|
|
1422
|
+
expect(viewed);
|
|
1423
|
+
expect(viewed.index.view(path));
|
|
1424
|
+
expect_eq(viewed.index.size(), collection);
|
|
1425
|
+
expect(viewed.index.search(data[0].data(), 5).dump_to(found) != 0);
|
|
1426
|
+
|
|
1427
|
+
std::remove(path);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1267
1430
|
int main(int, char**) {
|
|
1268
1431
|
install_crash_handlers();
|
|
1269
1432
|
|
|
@@ -1272,6 +1435,7 @@ int main(int, char**) {
|
|
|
1272
1435
|
|
|
1273
1436
|
// Non-default floating-point types may result in many compilation & rounding issues.
|
|
1274
1437
|
test_uint40();
|
|
1438
|
+
test_checked_size_arithmetic();
|
|
1275
1439
|
test_cosine<f32_t, std::int64_t, uint40_t>(10, 10);
|
|
1276
1440
|
test_cosine<bf16_t, std::int64_t, uint40_t>(10, 10);
|
|
1277
1441
|
test_cosine<f16_t, std::int64_t, uint40_t>(10, 10);
|
|
@@ -1352,7 +1516,12 @@ int main(int, char**) {
|
|
|
1352
1516
|
test_sets<std::int64_t, slot32_t>(set_size, 20, 30);
|
|
1353
1517
|
test_strings<std::int64_t, slot32_t>();
|
|
1354
1518
|
|
|
1519
|
+
std::printf("Testing key lookups under churn\n");
|
|
1520
|
+
test_slot_lookup_churn<std::int64_t, std::uint32_t>();
|
|
1521
|
+
test_slot_lookup_churn<std::int64_t, uint40_t>();
|
|
1522
|
+
|
|
1355
1523
|
test_filtered_search();
|
|
1356
1524
|
test_isolate();
|
|
1525
|
+
test_load_after_metric_make();
|
|
1357
1526
|
return 0;
|
|
1358
1527
|
}
|