usearch 0.11.1 → 0.12.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.
@@ -133,7 +133,7 @@ public class Index {
133
133
  }
134
134
 
135
135
  public static void main(String[] args) {
136
- Index index = new Index.Config().metric("cos").build();
136
+ Index index = new Index.Config().metric("cos").dimensions(100).build();
137
137
  index.size();
138
138
  }
139
139
 
@@ -10,9 +10,13 @@ using namespace unum::usearch;
10
10
  using namespace unum;
11
11
 
12
12
  using label_t = jint;
13
+ using span_t = span_gt<float>;
13
14
  using distance_t = punned_distance_t;
14
15
  using punned_t = punned_gt<label_t>;
15
- using span_t = span_gt<float>;
16
+
17
+ using add_result_t = typename punned_t::add_result_t;
18
+ using search_result_t = typename punned_t::search_result_t;
19
+ using serialization_result_t = typename punned_t::serialization_result_t;
16
20
 
17
21
  JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
18
22
  JNIEnv* env, jclass, //
@@ -25,13 +29,10 @@ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
25
29
  char const* accuracy_cstr{};
26
30
  try {
27
31
 
28
- config_t config;
32
+ index_config_t config;
29
33
  config.expansion_add = static_cast<std::size_t>(expansion_add);
30
34
  config.expansion_search = static_cast<std::size_t>(expansion_search);
31
35
  config.connectivity = static_cast<std::size_t>(connectivity);
32
- config.max_elements = static_cast<std::size_t>(capacity);
33
- config.max_threads_add = std::thread::hardware_concurrency();
34
- config.max_threads_search = std::thread::hardware_concurrency();
35
36
 
36
37
  metric_cstr = (*env).GetStringUTFChars(metric, 0);
37
38
  std::size_t metric_length = (*env).GetStringUTFLength(metric);
@@ -39,11 +40,17 @@ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
39
40
  std::size_t accuracy_length = (*env).GetStringUTFLength(accuracy);
40
41
 
41
42
  accuracy_t accuracy = accuracy_from_name(accuracy_cstr, accuracy_length);
42
- punned_t index = index_from_name<punned_t>( //
43
- metric_cstr, metric_length, static_cast<std::size_t>(dimensions), accuracy, config);
43
+ common_metric_kind_t metric_kind = common_metric_from_name(metric_cstr, metric_length);
44
+ punned_t index = make_punned<punned_t>(metric_kind, static_cast<std::size_t>(dimensions), accuracy, config);
45
+ if (!index.reserve(static_cast<std::size_t>(capacity))) {
46
+ jclass jc = (*env).FindClass("java/lang/Error");
47
+ if (jc)
48
+ (*env).ThrowNew(jc, "Failed to reserve desired capacity!");
49
+ } else {
50
+ punned_t* result_ptr = new punned_t(std::move(index));
51
+ std::memcpy(&result, &result_ptr, sizeof(jlong));
52
+ }
44
53
 
45
- punned_t* result_ptr = new punned_t(std::move(index));
46
- std::memcpy(&result, &result_ptr, sizeof(jlong));
47
54
  } catch (...) {
48
55
  jclass jc = (*env).FindClass("java/lang/Error");
49
56
  if (jc)
@@ -56,11 +63,8 @@ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
56
63
  }
57
64
 
58
65
  JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1save(JNIEnv* env, jclass, jlong c_ptr, jstring path) {
59
- char const* path_cstr{};
60
- try {
61
- path_cstr = (*env).GetStringUTFChars(path, 0);
62
- reinterpret_cast<punned_t*>(c_ptr)->save(path_cstr);
63
- } catch (...) {
66
+ char const* path_cstr = (*env).GetStringUTFChars(path, 0);
67
+ if (!reinterpret_cast<punned_t*>(c_ptr)->save(path_cstr)) {
64
68
  jclass jc = (*env).FindClass("java/lang/Error");
65
69
  if (jc)
66
70
  (*env).ThrowNew(jc, "Failed to dump vector index to path!");
@@ -69,11 +73,8 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1save(JNIEnv* env, jclass
69
73
  }
70
74
 
71
75
  JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1load(JNIEnv* env, jclass, jlong c_ptr, jstring path) {
72
- char const* path_cstr{};
73
- try {
74
- path_cstr = (*env).GetStringUTFChars(path, 0);
75
- reinterpret_cast<punned_t*>(c_ptr)->load(path_cstr);
76
- } catch (...) {
76
+ char const* path_cstr = (*env).GetStringUTFChars(path, 0);
77
+ if (!reinterpret_cast<punned_t*>(c_ptr)->load(path_cstr)) {
77
78
  jclass jc = (*env).FindClass("java/lang/Error");
78
79
  if (jc)
79
80
  (*env).ThrowNew(jc, "Failed to load vector index from path!");
@@ -82,11 +83,8 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1load(JNIEnv* env, jclass
82
83
  }
83
84
 
84
85
  JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1view(JNIEnv* env, jclass, jlong c_ptr, jstring path) {
85
- char const* path_cstr{};
86
- try {
87
- path_cstr = (*env).GetStringUTFChars(path, 0);
88
- reinterpret_cast<punned_t*>(c_ptr)->view(path_cstr);
89
- } catch (...) {
86
+ char const* path_cstr = (*env).GetStringUTFChars(path, 0);
87
+ if (!reinterpret_cast<punned_t*>(c_ptr)->view(path_cstr)) {
90
88
  jclass jc = (*env).FindClass("java/lang/Error");
91
89
  if (jc)
92
90
  (*env).ThrowNew(jc, "Failed to view vector index from path!");
@@ -115,9 +113,7 @@ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1capacity(JNIEnv*, jclas
115
113
  }
116
114
 
117
115
  JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1reserve(JNIEnv* env, jclass, jlong c_ptr, jlong capacity) {
118
- try {
119
- return reinterpret_cast<punned_t*>(c_ptr)->reserve(static_cast<std::size_t>(capacity));
120
- } catch (...) {
116
+ if (!reinterpret_cast<punned_t*>(c_ptr)->reserve(static_cast<std::size_t>(capacity))) {
121
117
  jclass jc = (*env).FindClass("java/lang/Error");
122
118
  if (jc)
123
119
  (*env).ThrowNew(jc, "Failed to grow vector index!");
@@ -127,13 +123,11 @@ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1reserve(JNIEnv* env, jcl
127
123
  JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1add( //
128
124
  JNIEnv* env, jclass, jlong c_ptr, jint label, jfloatArray vector) {
129
125
 
130
- jfloat* vector_data{};
131
- try {
132
- vector_data = (*env).GetFloatArrayElements(vector, 0);
133
- jsize vector_dims = (*env).GetArrayLength(vector);
134
- span_t vector_span = span_t{vector_data, static_cast<std::size_t>(vector_dims)};
135
- reinterpret_cast<punned_t*>(c_ptr)->add(label, vector_span);
136
- } catch (...) {
126
+ jfloat* vector_data = (*env).GetFloatArrayElements(vector, 0);
127
+ jsize vector_dims = (*env).GetArrayLength(vector);
128
+ span_t vector_span = span_t{vector_data, static_cast<std::size_t>(vector_dims)};
129
+
130
+ if (!reinterpret_cast<punned_t*>(c_ptr)->add(label, vector_span)) {
137
131
  jclass jc = (*env).FindClass("java/lang/Error");
138
132
  if (jc)
139
133
  (*env).ThrowNew(jc, "Failed to insert a new point in vector index!");
@@ -153,21 +147,19 @@ JNIEXPORT jintArray JNICALL Java_cloud_unum_usearch_Index_c_1search( //
153
147
  if (matches_data == NULL)
154
148
  return NULL;
155
149
 
156
- jfloat* vector_data{};
157
- std::size_t found{};
158
- try {
159
- vector_data = (*env).GetFloatArrayElements(vector, 0);
160
- jsize vector_dims = (*env).GetArrayLength(vector);
161
- span_t vector_span = span_t{vector_data, static_cast<std::size_t>(vector_dims)};
162
- found = reinterpret_cast<punned_t*>(c_ptr)
163
- ->search(vector_span, static_cast<std::size_t>(wanted))
164
- .dump_to(matches_data, NULL);
150
+ jfloat* vector_data = (*env).GetFloatArrayElements(vector, 0);
151
+ jsize vector_dims = (*env).GetArrayLength(vector);
152
+ span_t vector_span = span_t{vector_data, static_cast<std::size_t>(vector_dims)};
153
+ search_result_t result = reinterpret_cast<punned_t*>(c_ptr)->search(vector_span, static_cast<std::size_t>(wanted));
154
+ if (result) {
155
+ std::size_t found = result.dump_to(matches_data, NULL);
165
156
  (*env).SetIntArrayRegion(matches, 0, found, matches_data);
166
- } catch (...) {
157
+ } else {
167
158
  jclass jc = (*env).FindClass("java/lang/Error");
168
159
  if (jc)
169
160
  (*env).ThrowNew(jc, "Failed to find in vector index!");
170
161
  }
162
+
171
163
  (*env).ReleaseFloatArrayElements(vector, vector_data, 0);
172
164
  std::free(matches_data);
173
165
  return matches;
@@ -87,9 +87,10 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
87
87
  Napi::Object params = ctx[0].As<Napi::Object>();
88
88
  std::size_t dimensions = params.Has("dimensions") ? params.Get("dimensions").As<Napi::Number>().Uint32Value() : 0;
89
89
 
90
- config_t config;
90
+ index_config_t config;
91
+ index_limits_t limits;
91
92
  if (params.Has("capacity"))
92
- config.max_elements = params.Get("capacity").As<Napi::Number>().Uint32Value();
93
+ limits.elements = params.Get("capacity").As<Napi::Number>().Uint32Value();
93
94
  if (params.Has("connectivity"))
94
95
  config.connectivity = params.Get("connectivity").As<Napi::Number>().Uint32Value();
95
96
 
@@ -105,8 +106,7 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
105
106
  else if (accuracy_str == "f8")
106
107
  accuracy = accuracy_t::f8_k;
107
108
  else {
108
- Napi::TypeError::New(env, "Supported metrics are: [ip, cos, l2sq, haversine]")
109
- .ThrowAsJavaScriptException();
109
+ Napi::TypeError::New(env, "Supported metrics are: [ip, cos, l2sq, haversine]").ThrowAsJavaScriptException();
110
110
  return;
111
111
  }
112
112
  }
@@ -120,23 +120,26 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
120
120
  return;
121
121
  }
122
122
  native_.reset(new punned_t(punned_t::l2sq(dimensions, accuracy, config)));
123
+ native_->reserve(limits);
123
124
  } else if (name == "ip" || name == "inner" || name == "dot") {
124
125
  if (!dimensions) {
125
126
  Napi::TypeError::New(env, "Please define the number of dimensions").ThrowAsJavaScriptException();
126
127
  return;
127
128
  }
128
129
  native_.reset(new punned_t(punned_t::ip(dimensions, accuracy, config)));
130
+ native_->reserve(limits);
129
131
  } else if (name == "cos" || name == "angular") {
130
132
  if (!dimensions) {
131
133
  Napi::TypeError::New(env, "Please define the number of dimensions").ThrowAsJavaScriptException();
132
134
  return;
133
135
  }
134
136
  native_.reset(new punned_t(punned_t::cos(dimensions, accuracy, config)));
137
+ native_->reserve(limits);
135
138
  } else if (name == "haversine") {
136
139
  native_.reset(new punned_t(punned_t::haversine(accuracy, config)));
140
+ native_->reserve(limits);
137
141
  } else {
138
- Napi::TypeError::New(env, "Supported metrics are: [ip, cos, l2sq, haversine]")
139
- .ThrowAsJavaScriptException();
142
+ Napi::TypeError::New(env, "Supported metrics are: [ip, cos, l2sq, haversine]").ThrowAsJavaScriptException();
140
143
  return;
141
144
  }
142
145
  } else {
@@ -145,6 +148,7 @@ Index::Index(Napi::CallbackInfo const& ctx) : Napi::ObjectWrap<Index>(ctx) {
145
148
  return;
146
149
  }
147
150
  native_.reset(new punned_t(punned_t::ip(dimensions, accuracy, config)));
151
+ native_->reserve(limits);
148
152
  }
149
153
  }
150
154
 
@@ -0,0 +1,3 @@
1
+ const usearch = require('bindings')('usearch');
2
+
3
+ module.exports = usearch;
@@ -58,7 +58,7 @@ using shared_index_t = std::shared_ptr<punned_t>;
58
58
 
59
59
  + (instancetype)indexIP:(UInt32)dimensions connectivity:(UInt32)connectivity {
60
60
  std::size_t dims = static_cast<std::size_t>(dimensions);
61
- config_t config;
61
+ index_config_t config;
62
62
 
63
63
  config.connectivity = static_cast<std::size_t>(connectivity);
64
64
  shared_index_t ptr = std::make_shared<punned_t>(punned_t::ip(dims, accuracy_t::f32_k, config));
@@ -67,7 +67,7 @@ using shared_index_t = std::shared_ptr<punned_t>;
67
67
 
68
68
  + (instancetype)indexL2sq:(UInt32)dimensions connectivity:(UInt32)connectivity {
69
69
  std::size_t dims = static_cast<std::size_t>(dimensions);
70
- config_t config;
70
+ index_config_t config;
71
71
 
72
72
  config.connectivity = static_cast<std::size_t>(connectivity);
73
73
  shared_index_t ptr = std::make_shared<punned_t>(punned_t::l2sq(dims, accuracy_t::f32_k, config));
@@ -75,7 +75,7 @@ using shared_index_t = std::shared_ptr<punned_t>;
75
75
  }
76
76
 
77
77
  + (instancetype)indexHaversine:(UInt32)connectivity {
78
- config_t config;
78
+ index_config_t config;
79
79
 
80
80
  config.connectivity = static_cast<std::size_t>(connectivity);
81
81
  shared_index_t ptr = std::make_shared<punned_t>(punned_t::haversine(accuracy_t::f32_k, config));
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "description": "Smaller & Faster Single-File Vector Search Engine from Unum",
5
5
  "author": "Ashot Vardanian",
6
6
  "license": "Apache 2.0",
7
+ "main": "javascript/usearch.js",
7
8
  "repository": {
8
9
  "type": "git",
9
10
  "url": "https://github.com/unum-cloud/usearch.git"
@@ -23,6 +24,6 @@
23
24
  "@semantic-release/exec": "^6.0.3",
24
25
  "@semantic-release/git": "^10.0.1",
25
26
  "conventional-changelog-eslint": "^3.0.9",
26
- "semantic-release": "^21.0.2"
27
+ "semantic-release": "^21.0.3"
27
28
  }
28
- }
29
+ }
package/pyproject.toml CHANGED
@@ -9,7 +9,7 @@ xfail_strict = true
9
9
  filterwarnings = ["error"]
10
10
 
11
11
  [tool.cibuildwheel]
12
- test-requires = ["pytest", "numpy"]
12
+ test-requires = ["pytest", "numpy", "numba"]
13
13
  test-command = "pytest {project}/python/scripts/test.py"
14
14
  build-verbosity = 0
15
15
  skip = ["*musllinux*", "*i686*", "pp*"]