usearch 0.4.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.clang-tidy +60 -0
- package/.github/workflows/release.yml +42 -16
- package/.github/workflows/update_version.sh +1 -0
- package/.vscode/launch.json +22 -0
- package/.vscode/settings.json +5 -0
- package/.vscode/tasks.json +4 -4
- package/CITATION.cff +11 -0
- package/CMakeLists.txt +108 -95
- package/Cargo.toml +1 -1
- package/Dockerfile +14 -0
- package/README.md +8 -7
- package/VERSION +1 -1
- package/binding.gyp +2 -2
- package/build.rs +2 -2
- package/cmake/config.cmake.in +15 -0
- package/cmake/pkg-config.pc.in +4 -0
- package/cmake/usearchConfigVersion.cmake.in +20 -0
- package/conanfile.py +1 -1
- package/docs/benchmarks.md +11 -2
- package/docs/{Compilation.md → compilation.md} +54 -27
- package/include/usearch/usearch.hpp +664 -390
- package/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp +17 -16
- package/javascript/lib.cpp +13 -13
- package/javascript/test.js +1 -1
- package/objc/USearchObjective.mm +46 -29
- package/objc/include/USearchObjective.h +18 -26
- package/package.json +1 -1
- package/pyproject.toml +3 -2
- package/python/lib.cpp +179 -120
- package/python/scripts/bench.py +188 -0
- package/python/scripts/bench_params.py +113 -0
- package/python/{test.py → scripts/test.py} +32 -13
- package/python/usearch/client.py +100 -14
- package/python/usearch/server.py +104 -23
- package/rust/lib.cpp +15 -14
- package/rust/lib.hpp +5 -5
- package/rust/lib.rs +3 -3
- package/setup.py +7 -0
- package/src/CMakeLists.txt +107 -0
- package/src/bench.cpp +45 -15
- package/src/{advanced.hpp → punned.hpp} +227 -199
- package/src/test.cpp +62 -0
- package/swift/Test.swift +1 -1
- package/wolfram/lib.cpp +14 -14
- package/python/bench.py +0 -146
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
#include <thread>
|
|
6
6
|
|
|
7
|
-
#include "
|
|
7
|
+
#include "punned.hpp"
|
|
8
8
|
|
|
9
9
|
using namespace unum::usearch;
|
|
10
10
|
using namespace unum;
|
|
11
11
|
|
|
12
12
|
using label_t = jint;
|
|
13
13
|
using distance_t = punned_distance_t;
|
|
14
|
-
using
|
|
14
|
+
using punned_t = punned_gt<label_t>;
|
|
15
15
|
using span_t = span_gt<float>;
|
|
16
16
|
|
|
17
17
|
JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
|
|
@@ -39,10 +39,10 @@ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
|
|
|
39
39
|
std::size_t accuracy_length = (*env).GetStringUTFLength(accuracy);
|
|
40
40
|
|
|
41
41
|
accuracy_t accuracy = accuracy_from_name(accuracy_cstr, accuracy_length);
|
|
42
|
-
|
|
42
|
+
punned_t index = index_from_name<punned_t>( //
|
|
43
43
|
metric_cstr, metric_length, static_cast<std::size_t>(dimensions), accuracy, config);
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
punned_t* result_ptr = new punned_t(std::move(index));
|
|
46
46
|
std::memcpy(&result, &result_ptr, sizeof(jlong));
|
|
47
47
|
} catch (...) {
|
|
48
48
|
jclass jc = (*env).FindClass("java/lang/Error");
|
|
@@ -59,7 +59,7 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1save(JNIEnv* env, jclass
|
|
|
59
59
|
char const* path_cstr{};
|
|
60
60
|
try {
|
|
61
61
|
path_cstr = (*env).GetStringUTFChars(path, 0);
|
|
62
|
-
reinterpret_cast<
|
|
62
|
+
reinterpret_cast<punned_t*>(c_ptr)->save(path_cstr);
|
|
63
63
|
} catch (...) {
|
|
64
64
|
jclass jc = (*env).FindClass("java/lang/Error");
|
|
65
65
|
if (jc)
|
|
@@ -72,7 +72,7 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1load(JNIEnv* env, jclass
|
|
|
72
72
|
char const* path_cstr{};
|
|
73
73
|
try {
|
|
74
74
|
path_cstr = (*env).GetStringUTFChars(path, 0);
|
|
75
|
-
reinterpret_cast<
|
|
75
|
+
reinterpret_cast<punned_t*>(c_ptr)->load(path_cstr);
|
|
76
76
|
} catch (...) {
|
|
77
77
|
jclass jc = (*env).FindClass("java/lang/Error");
|
|
78
78
|
if (jc)
|
|
@@ -85,7 +85,7 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1view(JNIEnv* env, jclass
|
|
|
85
85
|
char const* path_cstr{};
|
|
86
86
|
try {
|
|
87
87
|
path_cstr = (*env).GetStringUTFChars(path, 0);
|
|
88
|
-
reinterpret_cast<
|
|
88
|
+
reinterpret_cast<punned_t*>(c_ptr)->view(path_cstr);
|
|
89
89
|
} catch (...) {
|
|
90
90
|
jclass jc = (*env).FindClass("java/lang/Error");
|
|
91
91
|
if (jc)
|
|
@@ -95,28 +95,28 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1view(JNIEnv* env, jclass
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1destroy(JNIEnv*, jclass, jlong c_ptr) {
|
|
98
|
-
delete reinterpret_cast<
|
|
98
|
+
delete reinterpret_cast<punned_t*>(c_ptr);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1size(JNIEnv*, jclass, jlong c_ptr) {
|
|
102
|
-
return reinterpret_cast<
|
|
102
|
+
return reinterpret_cast<punned_t*>(c_ptr)->size();
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1connectivity(JNIEnv*, jclass, jlong c_ptr) {
|
|
106
|
-
return reinterpret_cast<
|
|
106
|
+
return reinterpret_cast<punned_t*>(c_ptr)->connectivity();
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1dimensions(JNIEnv*, jclass, jlong c_ptr) {
|
|
110
|
-
return reinterpret_cast<
|
|
110
|
+
return reinterpret_cast<punned_t*>(c_ptr)->dimensions();
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1capacity(JNIEnv*, jclass, jlong c_ptr) {
|
|
114
|
-
return reinterpret_cast<
|
|
114
|
+
return reinterpret_cast<punned_t*>(c_ptr)->capacity();
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1reserve(JNIEnv* env, jclass, jlong c_ptr, jlong capacity) {
|
|
118
118
|
try {
|
|
119
|
-
return reinterpret_cast<
|
|
119
|
+
return reinterpret_cast<punned_t*>(c_ptr)->reserve(static_cast<std::size_t>(capacity));
|
|
120
120
|
} catch (...) {
|
|
121
121
|
jclass jc = (*env).FindClass("java/lang/Error");
|
|
122
122
|
if (jc)
|
|
@@ -132,7 +132,7 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1add( //
|
|
|
132
132
|
vector_data = (*env).GetFloatArrayElements(vector, 0);
|
|
133
133
|
jsize vector_dims = (*env).GetArrayLength(vector);
|
|
134
134
|
span_t vector_span = span_t{vector_data, static_cast<std::size_t>(vector_dims)};
|
|
135
|
-
reinterpret_cast<
|
|
135
|
+
reinterpret_cast<punned_t*>(c_ptr)->add(label, vector_span);
|
|
136
136
|
} catch (...) {
|
|
137
137
|
jclass jc = (*env).FindClass("java/lang/Error");
|
|
138
138
|
if (jc)
|
|
@@ -159,8 +159,9 @@ JNIEXPORT jintArray JNICALL Java_cloud_unum_usearch_Index_c_1search( //
|
|
|
159
159
|
vector_data = (*env).GetFloatArrayElements(vector, 0);
|
|
160
160
|
jsize vector_dims = (*env).GetArrayLength(vector);
|
|
161
161
|
span_t vector_span = span_t{vector_data, static_cast<std::size_t>(vector_dims)};
|
|
162
|
-
found = reinterpret_cast<
|
|
163
|
-
|
|
162
|
+
found = reinterpret_cast<punned_t*>(c_ptr)
|
|
163
|
+
->search(vector_span, static_cast<std::size_t>(wanted))
|
|
164
|
+
.dump_to(matches_data, NULL);
|
|
164
165
|
(*env).SetIntArrayRegion(matches, 0, found, matches_data);
|
|
165
166
|
} catch (...) {
|
|
166
167
|
jclass jc = (*env).FindClass("java/lang/Error");
|
package/javascript/lib.cpp
CHANGED
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
#include <napi.h>
|
|
21
21
|
#include <node_api.h>
|
|
22
22
|
|
|
23
|
-
#include "
|
|
23
|
+
#include "punned.hpp"
|
|
24
24
|
|
|
25
25
|
using namespace unum::usearch;
|
|
26
26
|
using namespace unum;
|
|
27
27
|
|
|
28
28
|
using label_t = std::uint32_t;
|
|
29
29
|
using distance_t = punned_distance_t;
|
|
30
|
-
using
|
|
30
|
+
using punned_t = punned_gt<label_t>;
|
|
31
31
|
|
|
32
32
|
class Index : public Napi::ObjectWrap<Index> {
|
|
33
33
|
public:
|
|
@@ -47,7 +47,7 @@ class Index : public Napi::ObjectWrap<Index> {
|
|
|
47
47
|
void Add(Napi::CallbackInfo const& ctx);
|
|
48
48
|
Napi::Value Search(Napi::CallbackInfo const& ctx);
|
|
49
49
|
|
|
50
|
-
std::unique_ptr<
|
|
50
|
+
std::unique_ptr<punned_t> native_;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
Napi::Object Index::Init(Napi::Env env, Napi::Object exports) {
|
|
@@ -79,7 +79,7 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
|
|
|
79
79
|
int length = ctx.Length();
|
|
80
80
|
if (length == 0 || length >= 2 || !ctx[0].IsObject()) {
|
|
81
81
|
Napi::TypeError::New(
|
|
82
|
-
env, "Pass args as named objects: dimensions: uint, capacity: uint, metric: [ip, cos,
|
|
82
|
+
env, "Pass args as named objects: dimensions: uint, capacity: uint, metric: [ip, cos, l2sq, haversine]")
|
|
83
83
|
.ThrowAsJavaScriptException();
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
@@ -105,7 +105,7 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
|
|
|
105
105
|
else if (accuracy_str == "f8")
|
|
106
106
|
accuracy = accuracy_t::f8_k;
|
|
107
107
|
else {
|
|
108
|
-
Napi::TypeError::New(env, "Supported metrics are: [ip, cos,
|
|
108
|
+
Napi::TypeError::New(env, "Supported metrics are: [ip, cos, l2sq, haversine]")
|
|
109
109
|
.ThrowAsJavaScriptException();
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
@@ -114,28 +114,28 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
|
|
|
114
114
|
// By default we use the Inner Product similarity
|
|
115
115
|
if (params.Has("metric")) {
|
|
116
116
|
std::string name = params.Get("metric").As<Napi::String>().Utf8Value();
|
|
117
|
-
if (name == "
|
|
117
|
+
if (name == "l2sq" || name == "euclidean_sq") {
|
|
118
118
|
if (!dimensions) {
|
|
119
119
|
Napi::TypeError::New(env, "Please define the number of dimensions").ThrowAsJavaScriptException();
|
|
120
120
|
return;
|
|
121
121
|
}
|
|
122
|
-
native_.reset(new
|
|
122
|
+
native_.reset(new punned_t(punned_t::l2sq(dimensions, accuracy, config)));
|
|
123
123
|
} else if (name == "ip" || name == "inner" || name == "dot") {
|
|
124
124
|
if (!dimensions) {
|
|
125
125
|
Napi::TypeError::New(env, "Please define the number of dimensions").ThrowAsJavaScriptException();
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
|
-
native_.reset(new
|
|
128
|
+
native_.reset(new punned_t(punned_t::ip(dimensions, accuracy, config)));
|
|
129
129
|
} else if (name == "cos" || name == "angular") {
|
|
130
130
|
if (!dimensions) {
|
|
131
131
|
Napi::TypeError::New(env, "Please define the number of dimensions").ThrowAsJavaScriptException();
|
|
132
132
|
return;
|
|
133
133
|
}
|
|
134
|
-
native_.reset(new
|
|
134
|
+
native_.reset(new punned_t(punned_t::cos(dimensions, accuracy, config)));
|
|
135
135
|
} else if (name == "haversine") {
|
|
136
|
-
native_.reset(new
|
|
136
|
+
native_.reset(new punned_t(punned_t::haversine(accuracy, config)));
|
|
137
137
|
} else {
|
|
138
|
-
Napi::TypeError::New(env, "Supported metrics are: [ip, cos,
|
|
138
|
+
Napi::TypeError::New(env, "Supported metrics are: [ip, cos, l2sq, haversine]")
|
|
139
139
|
.ThrowAsJavaScriptException();
|
|
140
140
|
return;
|
|
141
141
|
}
|
|
@@ -144,7 +144,7 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
|
|
|
144
144
|
Napi::TypeError::New(env, "Please define the number of dimensions").ThrowAsJavaScriptException();
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
native_.reset(new
|
|
147
|
+
native_.reset(new punned_t(punned_t::ip(dimensions, accuracy, config)));
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -258,7 +258,7 @@ Napi::Value Index::Search(Napi::CallbackInfo const& ctx) {
|
|
|
258
258
|
Napi::Uint32Array matches_js = Napi::Uint32Array::New(env, wanted);
|
|
259
259
|
Napi::Float32Array distances_js = Napi::Float32Array::New(env, wanted);
|
|
260
260
|
try {
|
|
261
|
-
std::size_t count = native_->search(vector, wanted
|
|
261
|
+
std::size_t count = native_->search(vector, wanted).dump_to(matches_js.Data(), distances_js.Data());
|
|
262
262
|
Napi::Object result_js = Napi::Object::New(env);
|
|
263
263
|
result_js.Set("labels", matches_js);
|
|
264
264
|
result_js.Set("distances", distances_js);
|
package/javascript/test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var assert = require('assert');
|
|
2
2
|
var usearch = require('bindings')('usearch');
|
|
3
3
|
|
|
4
|
-
var index = new usearch.Index({ metric: '
|
|
4
|
+
var index = new usearch.Index({ metric: 'l2sq', connectivity: 16, dimensions: 2 })
|
|
5
5
|
assert.equal(index.connectivity(), 16)
|
|
6
6
|
assert.equal(index.dimensions(), 2)
|
|
7
7
|
assert.equal(index.size(), 0)
|
package/objc/USearchObjective.mm
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
#pragma clang diagnostic push
|
|
4
4
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
|
5
|
-
#import "
|
|
5
|
+
#import "punned.hpp"
|
|
6
6
|
#pragma clang diagnostic pop
|
|
7
7
|
|
|
8
8
|
using namespace unum::usearch;
|
|
9
9
|
using namespace unum;
|
|
10
10
|
|
|
11
11
|
using distance_t = punned_distance_t;
|
|
12
|
-
using
|
|
13
|
-
using shared_index_t = std::shared_ptr<
|
|
12
|
+
using punned_t = punned_gt<UInt32>;
|
|
13
|
+
using shared_index_t = std::shared_ptr<punned_t>;
|
|
14
14
|
|
|
15
15
|
@interface Index ()
|
|
16
16
|
|
|
@@ -59,91 +59,108 @@ using shared_index_t = std::shared_ptr<native_index_t>;
|
|
|
59
59
|
+ (instancetype)indexIP:(UInt32)dimensions connectivity:(UInt32)connectivity {
|
|
60
60
|
std::size_t dims = static_cast<std::size_t>(dimensions);
|
|
61
61
|
config_t config;
|
|
62
|
+
|
|
62
63
|
config.connectivity = static_cast<std::size_t>(connectivity);
|
|
63
|
-
shared_index_t ptr = std::make_shared<
|
|
64
|
+
shared_index_t ptr = std::make_shared<punned_t>(punned_t::ip(dims, accuracy_t::f32_k, config));
|
|
64
65
|
return [[Index alloc] initWithIndex:ptr];
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
+ (instancetype)
|
|
68
|
+
+ (instancetype)indexL2sq:(UInt32)dimensions connectivity:(UInt32)connectivity {
|
|
68
69
|
std::size_t dims = static_cast<std::size_t>(dimensions);
|
|
69
70
|
config_t config;
|
|
71
|
+
|
|
70
72
|
config.connectivity = static_cast<std::size_t>(connectivity);
|
|
71
|
-
shared_index_t ptr = std::make_shared<
|
|
73
|
+
shared_index_t ptr = std::make_shared<punned_t>(punned_t::l2sq(dims, accuracy_t::f32_k, config));
|
|
72
74
|
return [[Index alloc] initWithIndex:ptr];
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
+ (instancetype)indexHaversine:(UInt32)connectivity {
|
|
76
78
|
config_t config;
|
|
79
|
+
|
|
77
80
|
config.connectivity = static_cast<std::size_t>(connectivity);
|
|
78
|
-
shared_index_t ptr = std::make_shared<
|
|
81
|
+
shared_index_t ptr = std::make_shared<punned_t>(punned_t::haversine(accuracy_t::f32_k, config));
|
|
79
82
|
return [[Index alloc] initWithIndex:ptr];
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
- (void)addSingle:(UInt32)label
|
|
83
|
-
vector:(Float32 const *
|
|
86
|
+
vector:(Float32 const *_Nonnull)vector {
|
|
84
87
|
_native->add(label, vector);
|
|
85
88
|
}
|
|
86
89
|
|
|
87
|
-
- (UInt32)searchSingle:(Float32 const*
|
|
90
|
+
- (UInt32)searchSingle:(Float32 const *_Nonnull)vector
|
|
88
91
|
count:(UInt32)wanted
|
|
89
|
-
labels:(UInt32*
|
|
90
|
-
distances:(Float32*
|
|
91
|
-
std::size_t found = _native->search(vector, static_cast<std::size_t>(wanted)
|
|
92
|
+
labels:(UInt32 *_Nullable)labels
|
|
93
|
+
distances:(Float32 *_Nullable)distances {
|
|
94
|
+
std::size_t found = _native->search(vector, static_cast<std::size_t>(wanted)).dump_to(labels, distances);
|
|
95
|
+
|
|
92
96
|
return static_cast<UInt32>(found);
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
- (void)addPrecise:(UInt32)label
|
|
96
|
-
vector:(Float64 const *
|
|
100
|
+
vector:(Float64 const *_Nonnull)vector {
|
|
97
101
|
_native->add(label, (f64_t const *)vector);
|
|
98
102
|
}
|
|
99
103
|
|
|
100
|
-
- (UInt32)searchPrecise:(Float64 const*
|
|
104
|
+
- (UInt32)searchPrecise:(Float64 const *_Nonnull)vector
|
|
101
105
|
count:(UInt32)wanted
|
|
102
|
-
labels:(UInt32*
|
|
103
|
-
distances:(Float32*
|
|
104
|
-
std::size_t found = _native->search((f64_t const *)vector, static_cast<std::size_t>(wanted)
|
|
106
|
+
labels:(UInt32 *_Nullable)labels
|
|
107
|
+
distances:(Float32 *_Nullable)distances {
|
|
108
|
+
std::size_t found = _native->search((f64_t const *)vector, static_cast<std::size_t>(wanted)).dump_to(labels, distances);
|
|
109
|
+
|
|
105
110
|
return static_cast<UInt32>(found);
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
- (void)addImprecise:(UInt32)label
|
|
109
|
-
vector:(void const *
|
|
114
|
+
vector:(void const *_Nonnull)vector {
|
|
110
115
|
_native->add(label, (f16_bits_t const *)vector);
|
|
111
116
|
}
|
|
112
117
|
|
|
113
|
-
- (UInt32)searchImprecise:(void const*
|
|
118
|
+
- (UInt32)searchImprecise:(void const *_Nonnull)vector
|
|
114
119
|
count:(UInt32)wanted
|
|
115
|
-
labels:(UInt32*
|
|
116
|
-
distances:(Float32*
|
|
117
|
-
std::size_t found = _native->search((f16_bits_t const *)vector, static_cast<std::size_t>(wanted)
|
|
120
|
+
labels:(UInt32 *_Nullable)labels
|
|
121
|
+
distances:(Float32 *_Nullable)distances {
|
|
122
|
+
std::size_t found = _native->search((f16_bits_t const *)vector, static_cast<std::size_t>(wanted)).dump_to(labels, distances);
|
|
123
|
+
|
|
118
124
|
return static_cast<UInt32>(found);
|
|
119
125
|
}
|
|
120
126
|
|
|
121
|
-
- (void)clear {
|
|
127
|
+
- (void)clear {
|
|
128
|
+
_native->clear();
|
|
129
|
+
}
|
|
122
130
|
|
|
123
|
-
- (void)save:(NSString*)path {
|
|
131
|
+
- (void)save:(NSString *)path {
|
|
124
132
|
char const *path_c = [path UTF8String];
|
|
125
|
-
|
|
133
|
+
|
|
134
|
+
if (!path_c) {
|
|
126
135
|
@throw [NSException exceptionWithName:@"Can't save to disk"
|
|
127
136
|
reason:@"The path must be convertible to UTF8"
|
|
128
137
|
userInfo:nil];
|
|
138
|
+
}
|
|
139
|
+
|
|
129
140
|
_native->save(path_c);
|
|
130
141
|
}
|
|
131
142
|
|
|
132
|
-
- (void)load:(NSString*)path {
|
|
143
|
+
- (void)load:(NSString *)path {
|
|
133
144
|
char const *path_c = [path UTF8String];
|
|
134
|
-
|
|
145
|
+
|
|
146
|
+
if (!path_c) {
|
|
135
147
|
@throw [NSException exceptionWithName:@"Can't load from disk"
|
|
136
148
|
reason:@"The path must be convertible to UTF8"
|
|
137
149
|
userInfo:nil];
|
|
150
|
+
}
|
|
151
|
+
|
|
138
152
|
_native->load(path_c);
|
|
139
153
|
}
|
|
140
154
|
|
|
141
|
-
- (void)view:(NSString*)path {
|
|
155
|
+
- (void)view:(NSString *)path {
|
|
142
156
|
char const *path_c = [path UTF8String];
|
|
143
|
-
|
|
157
|
+
|
|
158
|
+
if (!path_c) {
|
|
144
159
|
@throw [NSException exceptionWithName:@"Can't view from disk"
|
|
145
160
|
reason:@"The path must be convertible to UTF8"
|
|
146
161
|
userInfo:nil];
|
|
162
|
+
}
|
|
163
|
+
|
|
147
164
|
_native->view(path_c);
|
|
148
165
|
}
|
|
149
166
|
|
|
@@ -11,7 +11,7 @@ typedef NS_ENUM(NSUInteger, Quantization) {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0))
|
|
14
|
-
@interface Index: NSObject
|
|
14
|
+
@interface Index : NSObject
|
|
15
15
|
|
|
16
16
|
@property (readonly) UInt32 dimensions;
|
|
17
17
|
@property (readonly) UInt32 connectivity;
|
|
@@ -22,47 +22,39 @@ API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0))
|
|
|
22
22
|
@property (readonly) UInt32 capacity;
|
|
23
23
|
@property (readonly) Boolean isEmpty;
|
|
24
24
|
|
|
25
|
-
- (instancetype)init
|
|
26
|
-
NS_UNAVAILABLE;
|
|
25
|
+
- (instancetype)init NS_UNAVAILABLE;
|
|
27
26
|
|
|
28
27
|
+ (instancetype)indexIP:(UInt32)dimensions connectivity:(UInt32)connectivity NS_SWIFT_NAME(indexIP(dimensions:connectivity:));
|
|
29
|
-
+ (instancetype)
|
|
28
|
+
+ (instancetype)indexL2sq:(UInt32)dimensions connectivity:(UInt32)connectivity NS_SWIFT_NAME(l2sq(dimensions:connectivity:));
|
|
30
29
|
+ (instancetype)indexHaversine:(UInt32)connectivity NS_SWIFT_NAME(indexHaversine(connectivity:));
|
|
31
30
|
|
|
32
31
|
- (void)addSingle:(UInt32)label
|
|
33
|
-
vector:(Float32 const*
|
|
34
|
-
NS_SWIFT_NAME(addSingle(label:vector:));
|
|
32
|
+
vector:(Float32 const *_Nonnull)vector NS_SWIFT_NAME(addSingle(label:vector:));
|
|
35
33
|
|
|
36
|
-
- (UInt32)searchSingle:(Float32 const*
|
|
34
|
+
- (UInt32)searchSingle:(Float32 const *_Nonnull)vector
|
|
37
35
|
count:(UInt32)count
|
|
38
|
-
labels:(UInt32*
|
|
39
|
-
distances:(Float32*
|
|
40
|
-
NS_SWIFT_NAME(searchSingle(vector:count:labels:distances:));
|
|
36
|
+
labels:(UInt32 *_Nullable)labels
|
|
37
|
+
distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchSingle(vector:count:labels:distances:));
|
|
41
38
|
|
|
42
39
|
- (void)addPrecise:(UInt32)label
|
|
43
|
-
vector:(Float64 const*
|
|
44
|
-
NS_SWIFT_NAME(addPrecise(label:vector:));
|
|
40
|
+
vector:(Float64 const *_Nonnull)vector NS_SWIFT_NAME(addPrecise(label:vector:));
|
|
45
41
|
|
|
46
|
-
- (UInt32)searchPrecise:(Float64 const*
|
|
42
|
+
- (UInt32)searchPrecise:(Float64 const *_Nonnull)vector
|
|
47
43
|
count:(UInt32)count
|
|
48
|
-
labels:(UInt32*
|
|
49
|
-
distances:(Float32*
|
|
50
|
-
NS_SWIFT_NAME(searchPrecise(vector:count:labels:distances:));
|
|
44
|
+
labels:(UInt32 *_Nullable)labels
|
|
45
|
+
distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchPrecise(vector:count:labels:distances:));
|
|
51
46
|
|
|
52
47
|
- (void)addImprecise:(UInt32)label
|
|
53
|
-
vector:(void const*
|
|
54
|
-
NS_SWIFT_NAME(addImprecise(label:vector:));
|
|
48
|
+
vector:(void const *_Nonnull)vector NS_SWIFT_NAME(addImprecise(label:vector:));
|
|
55
49
|
|
|
56
|
-
- (UInt32)searchImprecise:(void const*
|
|
50
|
+
- (UInt32)searchImprecise:(void const *_Nonnull)vector
|
|
57
51
|
count:(UInt32)count
|
|
58
|
-
labels:(UInt32*
|
|
59
|
-
distances:(Float32*
|
|
60
|
-
NS_SWIFT_NAME(searchImprecise(vector:count:labels:distances:));
|
|
52
|
+
labels:(UInt32 *_Nullable)labels
|
|
53
|
+
distances:(Float32 *_Nullable)distances NS_SWIFT_NAME(searchImprecise(vector:count:labels:distances:));
|
|
61
54
|
|
|
62
|
-
|
|
63
|
-
- (void)
|
|
64
|
-
- (void)
|
|
65
|
-
- (void)view:(NSString*)path NS_SWIFT_NAME(view(path:));
|
|
55
|
+
- (void)save:(NSString *)path NS_SWIFT_NAME(dump(path:));
|
|
56
|
+
- (void)load:(NSString *)path NS_SWIFT_NAME(load(path:));
|
|
57
|
+
- (void)view:(NSString *)path NS_SWIFT_NAME(view(path:));
|
|
66
58
|
- (void)clear NS_SWIFT_NAME(clear());
|
|
67
59
|
|
|
68
60
|
@end
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools>=42", "wheel", "cmake>=3.22", "pybind11"]
|
|
2
|
+
requires = ["setuptools>=42", "wheel", "cmake>=3.22", "pybind11", "numpy"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[tool.pytest.ini_options]
|
|
@@ -9,8 +9,9 @@ xfail_strict = true
|
|
|
9
9
|
filterwarnings = ["error"]
|
|
10
10
|
|
|
11
11
|
[tool.cibuildwheel]
|
|
12
|
+
test-requires = ["pytest", "numpy"]
|
|
13
|
+
test-command = "pytest {project}/python/scripts/test.py"
|
|
12
14
|
build-verbosity = 0
|
|
13
|
-
|
|
14
15
|
skip = ["*musllinux*", "*i686*", "pp*"]
|
|
15
16
|
|
|
16
17
|
[tool.cibuildwheel.linux]
|