usearch 0.1.4 → 0.1.6

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/.gitattributes ADDED
@@ -0,0 +1,9 @@
1
+ #
2
+ # https://help.github.com/articles/dealing-with-line-endings/
3
+ #
4
+ # Linux start script should use lf
5
+ /gradlew text eol=lf
6
+
7
+ # These are Windows script files and should use crlf
8
+ *.bat text eol=crlf
9
+
@@ -47,10 +47,10 @@ cmake \
47
47
 
48
48
  ```sh
49
49
  pip install -e .
50
- python src/test.py
50
+ python python/test.py
51
51
 
52
52
  # To benchmark:
53
- python src/bench.py \
53
+ python python/bench.py \
54
54
  --vectors datasets/wiki_1M/base.1M.fbin \
55
55
  --queries datasets/wiki_1M/query.public.100K.fbin \
56
56
  --neighbors datasets/wiki_1M/groundtruth.public.100K.ibin \
@@ -61,7 +61,7 @@ python src/bench.py \
61
61
 
62
62
  ```sh
63
63
  npm install
64
- node src/test.js
64
+ node javascript/test.js
65
65
  npm publish
66
66
  ```
67
67
 
@@ -74,8 +74,34 @@ cargo publish
74
74
 
75
75
  ### Java
76
76
 
77
+ ```sh
78
+ cs java/unum/cloud/usearch
79
+ javac -h . Index.java
80
+
81
+ # Ubuntu:
82
+ g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
83
+ g++ -shared -fPIC -o libUSearchJNI.so cloud_unum_usearch_Index.o -lc
84
+
85
+ # Windows
86
+ g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
87
+ g++ -shared -o USearchJNI.dll cloud_unum_usearch_Index.o -Wl,--add-stdcall-alias
88
+
89
+ # MacOS
90
+ g++ -std=c++11 -c -fPIC \
91
+ -I../../../../include -I../../../../src -I../../../../fp16/include -I../../../../simsimd/include \
92
+ -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
93
+ g++ -dynamiclib -o libUSearchJNI.dylib cloud_unum_usearch_Index.o -lc
94
+ # Run linking to that directory
95
+ java -cp . -Djava.library.path=/Users/av/github/usearch/java/cloud/unum/usearch/ Index.java
96
+ java -cp . -Djava.library.path=/Users/av/github/usearch/java cloud.unum.usearch.Index
97
+ ```
98
+
77
99
  ### Wolfram
78
100
 
101
+ ```sh
102
+ brew install --cask wolfram-engine
103
+ ```
104
+
79
105
  ## Benchmarks
80
106
 
81
107
  ### Datasets
package/Cargo.toml CHANGED
@@ -1,8 +1,8 @@
1
1
  [package]
2
2
  name = "usearch"
3
- version = "0.1.4"
3
+ version = "0.1.6"
4
4
  authors = ["Ashot Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
5
- description = "The Tiny Vector Search Engine from Unum"
5
+ description = "The Mighty Tiny Vector Search Engine with Automatic Quantization and Hardware Acceleration"
6
6
  edition = "2021"
7
7
  license = "Apache-2.0"
8
8
  publish = true
@@ -10,7 +10,7 @@ repository = "https://github.com/unum-cloud/usearch"
10
10
 
11
11
  [lib]
12
12
  name = "usearch"
13
- path = "src/lib.rs"
13
+ path = "rust/lib.rs"
14
14
 
15
15
  [dependencies]
16
16
  cxx = "1.0"
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.1.6
package/binding.gyp CHANGED
@@ -3,11 +3,12 @@
3
3
  {
4
4
  "target_name": "usearch",
5
5
  "sources": [
6
- "src/javascript.cpp"
6
+ "javascript/lib.cpp"
7
7
  ],
8
8
  "include_dirs": [
9
9
  "<!@(node -p \"require('node-addon-api').include\")",
10
10
  "include",
11
+ "src",
11
12
  "fp16/include",
12
13
  "simsimd/include"
13
14
  ],
package/build.gradle ADDED
@@ -0,0 +1,111 @@
1
+ import org.gradle.internal.jvm.Jvm
2
+
3
+ plugins {
4
+ id 'java-library'
5
+ id 'c'
6
+ id 'cpp'
7
+ id 'maven-publish'
8
+ }
9
+
10
+ group "cloud.unum.usearch"
11
+ version = file("VERSION").text.trim()
12
+
13
+ sourceCompatibility = 1.8
14
+ targetCompatibility = 1.8
15
+
16
+ repositories {
17
+ mavenCentral()
18
+ }
19
+
20
+ sourceSets {
21
+ main {
22
+ java {
23
+ srcDir "java/"
24
+ exclude "java/test/"
25
+ }
26
+ }
27
+ test {
28
+ java {
29
+ srcDir "java/test"
30
+ }
31
+ }
32
+ }
33
+
34
+ dependencies {
35
+ testImplementation('junit:junit:4.13.2')
36
+ }
37
+
38
+ model {
39
+
40
+ components {
41
+ usearch(NativeLibrarySpec) {
42
+ sources {
43
+ cpp {
44
+ source {
45
+ srcDirs "cloud/unum/usearch"
46
+ include "**/*.cpp"
47
+ }
48
+ exportedHeaders {
49
+ srcDirs "include", "src", "${Jvm.current().javaHome}/include"
50
+ }
51
+ }
52
+ }
53
+ binaries.withType(StaticLibraryBinarySpec) {
54
+ buildable = false
55
+ }
56
+ binaries.withType(SharedLibraryBinarySpec) {
57
+ if (targetPlatform.operatingSystem.linux) {
58
+ cppCompiler.args '-I', "${Jvm.current().javaHome}/include/linux"
59
+ cppCompiler.args '-D_FILE_OFFSET_BITS=64'
60
+ } else if (targetPlatform.operatingSystem.macOsX) {
61
+ cppCompiler.args '-I', "${Jvm.current().javaHome}/include/darwin"
62
+ cppCompiler.args '-D_FILE_OFFSET_BITS=64'
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ test {
70
+ forkEvery 1
71
+
72
+ dependsOn jar
73
+
74
+ // Rearrange test classpath, add compiled JAR instead of main classes
75
+ classpath = project.sourceSets.test.output + configurations.testRuntimeClasspath + files(jar.archiveFile)
76
+ }
77
+
78
+ jar {
79
+ dependsOn("usearchSharedLibrary")
80
+ from("$buildDir/libs/usearch/shared/libUSearchJNI.dylib")
81
+ }
82
+
83
+ publishing {
84
+ publications {
85
+ library(MavenPublication) {
86
+ from components.java
87
+
88
+ pom {
89
+ name = "USearch"
90
+ description = "The Mighty Tiny Vector Search Engine with Automatic Quantization and Hardware Acceleration"
91
+ url = "https://github.com/unum-cloud/usearch"
92
+ licenses {
93
+ license {
94
+ name = 'The Apache License, Version 2.0'
95
+ url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ repositories {
102
+ maven {
103
+ name = "OSSRH"
104
+ url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
105
+ credentials {
106
+ username = System.getenv("MAVEN_USERNAME")
107
+ password = System.getenv("MAVEN_PASSWORD")
108
+ }
109
+ }
110
+ }
111
+ }
package/build.rs CHANGED
@@ -1,16 +1,17 @@
1
1
  fn main() {
2
- cxx_build::bridge("src/lib.rs")
3
- .file("src/rust.cpp")
2
+ cxx_build::bridge("rust/lib.rs")
3
+ .file("rust/lib.cpp")
4
4
  .flag_if_supported("-std=c++11")
5
5
  .include("include")
6
+ .include("rust")
6
7
  .include("src")
7
8
  .include("fp16/include")
8
9
  .include("simsimd/include")
9
10
  .compile("usearch");
10
11
 
11
- println!("cargo:rerun-if-changed=src/lib.rs");
12
- println!("cargo:rerun-if-changed=src/rust.cpp");
13
- println!("cargo:rerun-if-changed=src/rust.hpp");
12
+ println!("cargo:rerun-if-changed=rust/lib.rs");
13
+ println!("cargo:rerun-if-changed=rust/lib.cpp");
14
+ println!("cargo:rerun-if-changed=rust/lib.hpp");
14
15
  println!("cargo:rerun-if-changed=src/advanced.hpp");
15
16
  println!("cargo:rerun-if-changed=include/usearch/usearch.hpp");
16
17
  }
@@ -0,0 +1,161 @@
1
+ package cloud.unum.usearch;
2
+
3
+ /**
4
+ * @brief Java bindings for Unum USearch.
5
+ *
6
+ * @see Tutorials:
7
+ * https://nachtimwald.com/2017/06/06/wrapping-a-c-library-in-java/
8
+ * https://www3.ntu.edu.sg/home/ehchua/programming/java/javanativeinterface.html
9
+ */
10
+ public class Index {
11
+
12
+ private long c_ptr = 0;
13
+
14
+ public Index(String metric, String accuracy, //
15
+ long dimensions, long capacity, long connectivity, //
16
+ long expansion_add, long expansion_search) {
17
+ c_ptr = c_create(
18
+ metric,
19
+ accuracy,
20
+ dimensions,
21
+ capacity,
22
+ connectivity,
23
+ expansion_add,
24
+ expansion_search);
25
+ }
26
+
27
+ public long size() {
28
+ return c_size(c_ptr);
29
+ }
30
+
31
+ public long connectivity() {
32
+ return c_connectivity(c_ptr);
33
+ }
34
+
35
+ public long dimensions() {
36
+ return c_dimensions(c_ptr);
37
+ }
38
+
39
+ public long capacity() {
40
+ return c_capacity(c_ptr);
41
+ }
42
+
43
+ public void reserve(long capacity) {
44
+ c_reserve(c_ptr, capacity);
45
+ }
46
+
47
+ public void add(int label, float vector[]) {
48
+ c_add(c_ptr, label, vector);
49
+ }
50
+
51
+ public int[] search(float vector[], long count) {
52
+ return c_search(c_ptr, vector, count);
53
+ }
54
+
55
+ public void save(String path) {
56
+ c_save(c_ptr, path);
57
+ }
58
+
59
+ public void load(String path) {
60
+ c_load(c_ptr, path);
61
+ }
62
+
63
+ public void view(String path) {
64
+ c_view(c_ptr, path);
65
+ }
66
+
67
+ public static class Config {
68
+ private String _metric = "ip";
69
+ private String _accuracy = "f32";
70
+ private long _dimensions = 0;
71
+ private long _capacity = 0;
72
+ private long _connectivity = 0;
73
+ private long _expansion_add = 0;
74
+ private long _expansion_search = 0;
75
+
76
+ public Config() {
77
+ }
78
+
79
+ public Index build() {
80
+ return new Index(
81
+ _metric,
82
+ _accuracy,
83
+ _dimensions,
84
+ _capacity,
85
+ _connectivity,
86
+ _expansion_add,
87
+ _expansion_search);
88
+ }
89
+
90
+ public Config metric(String _metric) {
91
+ this._metric = _metric;
92
+ return this;
93
+ }
94
+
95
+ public Config accuracy(String _accuracy) {
96
+ this._accuracy = _accuracy;
97
+ return this;
98
+ }
99
+
100
+ public Config dimensions(long _dimensions) {
101
+ this._dimensions = _dimensions;
102
+ return this;
103
+ }
104
+
105
+ public Config capacity(long _capacity) {
106
+ this._capacity = _capacity;
107
+ return this;
108
+ }
109
+
110
+ public Config connectivity(long _connectivity) {
111
+ this._connectivity = _connectivity;
112
+ return this;
113
+ }
114
+
115
+ public Config expansion_add(long _expansion_add) {
116
+ this._expansion_add = _expansion_add;
117
+ return this;
118
+ }
119
+
120
+ public Config expansion_search(long _expansion_search) {
121
+ this._expansion_search = _expansion_search;
122
+ return this;
123
+ }
124
+ }
125
+
126
+ static {
127
+ System.loadLibrary("USearchJNI");
128
+ }
129
+
130
+ public static void main(String[] args) {
131
+ Index index = new Index.Config().metric("cos").build();
132
+ index.size();
133
+ }
134
+
135
+ private static native long c_create(//
136
+ String metric, String accuracy, //
137
+ long dimensions, long capacity, long connectivity, //
138
+ long expansion_add, long expansion_search);
139
+
140
+ private static native void c_destroy(long ptr);
141
+
142
+ private static native long c_size(long ptr);
143
+
144
+ private static native long c_connectivity(long ptr);
145
+
146
+ private static native long c_dimensions(long ptr);
147
+
148
+ private static native long c_capacity(long ptr);
149
+
150
+ private static native void c_reserve(long ptr, long capacity);
151
+
152
+ private static native void c_add(long ptr, int label, float vector[]);
153
+
154
+ private static native int[] c_search(long ptr, float vector[], long count);
155
+
156
+ private static native void c_save(long ptr, String path);
157
+
158
+ private static native void c_load(long ptr, String path);
159
+
160
+ private static native void c_view(long ptr, String path);
161
+ }
@@ -0,0 +1,173 @@
1
+ #include <jni.h>
2
+
3
+ #include "cloud_unum_usearch_Index.h"
4
+
5
+ #include <thread>
6
+
7
+ #include "advanced.hpp"
8
+
9
+ using namespace unum::usearch;
10
+ using namespace unum;
11
+
12
+ using label_t = jint;
13
+ using distance_t = punned_distance_t;
14
+ using native_index_t = auto_index_gt<label_t>;
15
+ using span_t = span_gt<float>;
16
+
17
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create( //
18
+ JNIEnv* env, jclass, //
19
+ jstring metric, jstring accuracy, //
20
+ jlong dimensions, jlong capacity, jlong connectivity, //
21
+ jlong expansion_add, jlong expansion_search) {
22
+
23
+ jlong result{};
24
+ char const* metric_cstr{};
25
+ char const* accuracy_cstr{};
26
+ try {
27
+
28
+ config_t config;
29
+ config.expansion_add = static_cast<std::size_t>(expansion_add);
30
+ config.expansion_search = static_cast<std::size_t>(expansion_search);
31
+ 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
+ metric_cstr = (*env).GetStringUTFChars(metric, 0);
37
+ std::size_t metric_length = (*env).GetStringUTFLength(metric);
38
+ accuracy_cstr = (*env).GetStringUTFChars(accuracy, 0);
39
+ std::size_t accuracy_length = (*env).GetStringUTFLength(accuracy);
40
+
41
+ accuracy_t accuracy = accuracy_from_name(accuracy_cstr, accuracy_length);
42
+ native_index_t index = index_from_name<native_index_t>( //
43
+ metric_cstr, metric_length, static_cast<std::size_t>(dimensions), accuracy, config);
44
+
45
+ native_index_t* result_ptr = new native_index_t(std::move(index));
46
+ std::memcpy(&result, &result_ptr, sizeof(jlong));
47
+ } catch (...) {
48
+ jclass jc = (*env).FindClass("java/lang/Error");
49
+ if (jc)
50
+ (*env).ThrowNew(jc, "Failed to initialize the vector index!");
51
+ }
52
+
53
+ (*env).ReleaseStringUTFChars(metric, metric_cstr);
54
+ (*env).ReleaseStringUTFChars(accuracy, accuracy_cstr);
55
+ return result;
56
+ }
57
+
58
+ 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<native_index_t*>(c_ptr)->save(path_cstr);
63
+ } catch (...) {
64
+ jclass jc = (*env).FindClass("java/lang/Error");
65
+ if (jc)
66
+ (*env).ThrowNew(jc, "Failed to dump vector index to path!");
67
+ }
68
+ (*env).ReleaseStringUTFChars(path, path_cstr);
69
+ }
70
+
71
+ 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<native_index_t*>(c_ptr)->load(path_cstr);
76
+ } catch (...) {
77
+ jclass jc = (*env).FindClass("java/lang/Error");
78
+ if (jc)
79
+ (*env).ThrowNew(jc, "Failed to load vector index from path!");
80
+ }
81
+ (*env).ReleaseStringUTFChars(path, path_cstr);
82
+ }
83
+
84
+ 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<native_index_t*>(c_ptr)->view(path_cstr);
89
+ } catch (...) {
90
+ jclass jc = (*env).FindClass("java/lang/Error");
91
+ if (jc)
92
+ (*env).ThrowNew(jc, "Failed to view vector index from path!");
93
+ }
94
+ (*env).ReleaseStringUTFChars(path, path_cstr);
95
+ }
96
+
97
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1destroy(JNIEnv*, jclass, jlong c_ptr) {
98
+ delete reinterpret_cast<native_index_t*>(c_ptr);
99
+ }
100
+
101
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1size(JNIEnv*, jclass, jlong c_ptr) {
102
+ return reinterpret_cast<native_index_t*>(c_ptr)->size();
103
+ }
104
+
105
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1connectivity(JNIEnv*, jclass, jlong c_ptr) {
106
+ return reinterpret_cast<native_index_t*>(c_ptr)->connectivity();
107
+ }
108
+
109
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1dimensions(JNIEnv*, jclass, jlong c_ptr) {
110
+ return reinterpret_cast<native_index_t*>(c_ptr)->dimensions();
111
+ }
112
+
113
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1capacity(JNIEnv*, jclass, jlong c_ptr) {
114
+ return reinterpret_cast<native_index_t*>(c_ptr)->capacity();
115
+ }
116
+
117
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1reserve(JNIEnv* env, jclass, jlong c_ptr, jlong capacity) {
118
+ try {
119
+ return reinterpret_cast<native_index_t*>(c_ptr)->reserve(static_cast<std::size_t>(capacity));
120
+ } catch (...) {
121
+ jclass jc = (*env).FindClass("java/lang/Error");
122
+ if (jc)
123
+ (*env).ThrowNew(jc, "Failed to grow vector index!");
124
+ }
125
+ }
126
+
127
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1add( //
128
+ JNIEnv* env, jclass, jlong c_ptr, jint label, jfloatArray vector) {
129
+
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<native_index_t*>(c_ptr)->add(label, vector_span);
136
+ } catch (...) {
137
+ jclass jc = (*env).FindClass("java/lang/Error");
138
+ if (jc)
139
+ (*env).ThrowNew(jc, "Failed to insert a new point in vector index!");
140
+ }
141
+ (*env).ReleaseFloatArrayElements(vector, vector_data, 0);
142
+ }
143
+
144
+ JNIEXPORT jintArray JNICALL Java_cloud_unum_usearch_Index_c_1search( //
145
+ JNIEnv* env, jclass, jlong c_ptr, jfloatArray vector, jlong wanted) {
146
+
147
+ jintArray matches;
148
+ matches = (*env).NewIntArray(wanted);
149
+ if (matches == NULL)
150
+ return NULL;
151
+
152
+ jint* matches_data = (jint*)std::malloc(sizeof(jint) * wanted);
153
+ if (matches_data == NULL)
154
+ return NULL;
155
+
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<native_index_t*>(c_ptr)->search( //
163
+ vector_span, static_cast<std::size_t>(wanted), matches_data, NULL);
164
+ (*env).SetIntArrayRegion(matches, 0, found, matches_data);
165
+ } catch (...) {
166
+ jclass jc = (*env).FindClass("java/lang/Error");
167
+ if (jc)
168
+ (*env).ThrowNew(jc, "Failed to find in vector index!");
169
+ }
170
+ (*env).ReleaseFloatArrayElements(vector, vector_data, 0);
171
+ std::free(matches_data);
172
+ return matches;
173
+ }
@@ -0,0 +1,109 @@
1
+ /* DO NOT EDIT THIS FILE - it is machine generated */
2
+ #include <jni.h>
3
+ /* Header for class cloud_unum_usearch_Index */
4
+
5
+ #ifndef _Included_cloud_unum_usearch_Index
6
+ #define _Included_cloud_unum_usearch_Index
7
+ #ifdef __cplusplus
8
+ extern "C" {
9
+ #endif
10
+ /*
11
+ * Class: cloud_unum_usearch_Index
12
+ * Method: c_create
13
+ * Signature: (Ljava/lang/String;Ljava/lang/String;JJJJJ)J
14
+ */
15
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1create
16
+ (JNIEnv *, jclass, jstring, jstring, jlong, jlong, jlong, jlong, jlong);
17
+
18
+ /*
19
+ * Class: cloud_unum_usearch_Index
20
+ * Method: c_destroy
21
+ * Signature: (J)V
22
+ */
23
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1destroy
24
+ (JNIEnv *, jclass, jlong);
25
+
26
+ /*
27
+ * Class: cloud_unum_usearch_Index
28
+ * Method: c_size
29
+ * Signature: (J)J
30
+ */
31
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1size
32
+ (JNIEnv *, jclass, jlong);
33
+
34
+ /*
35
+ * Class: cloud_unum_usearch_Index
36
+ * Method: c_connectivity
37
+ * Signature: (J)J
38
+ */
39
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1connectivity
40
+ (JNIEnv *, jclass, jlong);
41
+
42
+ /*
43
+ * Class: cloud_unum_usearch_Index
44
+ * Method: c_dimensions
45
+ * Signature: (J)J
46
+ */
47
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1dimensions
48
+ (JNIEnv *, jclass, jlong);
49
+
50
+ /*
51
+ * Class: cloud_unum_usearch_Index
52
+ * Method: c_capacity
53
+ * Signature: (J)J
54
+ */
55
+ JNIEXPORT jlong JNICALL Java_cloud_unum_usearch_Index_c_1capacity
56
+ (JNIEnv *, jclass, jlong);
57
+
58
+ /*
59
+ * Class: cloud_unum_usearch_Index
60
+ * Method: c_reserve
61
+ * Signature: (JJ)V
62
+ */
63
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1reserve
64
+ (JNIEnv *, jclass, jlong, jlong);
65
+
66
+ /*
67
+ * Class: cloud_unum_usearch_Index
68
+ * Method: c_add
69
+ * Signature: (JI[F)V
70
+ */
71
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1add
72
+ (JNIEnv *, jclass, jlong, jint, jfloatArray);
73
+
74
+ /*
75
+ * Class: cloud_unum_usearch_Index
76
+ * Method: c_search
77
+ * Signature: (J[FJ)[I
78
+ */
79
+ JNIEXPORT jintArray JNICALL Java_cloud_unum_usearch_Index_c_1search
80
+ (JNIEnv *, jclass, jlong, jfloatArray, jlong);
81
+
82
+ /*
83
+ * Class: cloud_unum_usearch_Index
84
+ * Method: c_save
85
+ * Signature: (JLjava/lang/String;)V
86
+ */
87
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1save
88
+ (JNIEnv *, jclass, jlong, jstring);
89
+
90
+ /*
91
+ * Class: cloud_unum_usearch_Index
92
+ * Method: c_load
93
+ * Signature: (JLjava/lang/String;)V
94
+ */
95
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1load
96
+ (JNIEnv *, jclass, jlong, jstring);
97
+
98
+ /*
99
+ * Class: cloud_unum_usearch_Index
100
+ * Method: c_view
101
+ * Signature: (JLjava/lang/String;)V
102
+ */
103
+ JNIEXPORT void JNICALL Java_cloud_unum_usearch_Index_c_1view
104
+ (JNIEnv *, jclass, jlong, jstring);
105
+
106
+ #ifdef __cplusplus
107
+ }
108
+ #endif
109
+ #endif
@@ -0,0 +1,26 @@
1
+ import java.io.File;
2
+ import java.util.Arrays;
3
+
4
+ import org.junit.Test;
5
+
6
+ import cloud.unum.usearch.Index;
7
+
8
+ public class IndexTest {
9
+
10
+ public static void deleteDirectoryFiles(String path) {
11
+ File directory = new File(path);
12
+ if (!directory.isDirectory())
13
+ return;
14
+
15
+ for (File f : directory.listFiles())
16
+ f.delete();
17
+ }
18
+
19
+ @Test
20
+ public void test() {
21
+ String path = "./tmp/";
22
+ deleteDirectoryFiles(path);
23
+ new Index();
24
+ System.out.println("Java Tests Passed!");
25
+ }
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "The Mighty Tiny Vector Search Engine with Automatic Quantization and Hardware Acceleration",
5
5
  "author": "Ashot Vardanian",
6
6
  "license": "Apache 2.0",
@@ -17,6 +17,6 @@
17
17
  "node-addon-api": "^3.0.0"
18
18
  },
19
19
  "scripts": {
20
- "test": "node src/test.js"
20
+ "test": "node javascript/test.js"
21
21
  }
22
22
  }
package/pom.xml ADDED
@@ -0,0 +1,8 @@
1
+ <dependencies>
2
+ <dependency>
3
+ <groupId>junit</groupId>
4
+ <artifactId>junit</artifactId>
5
+ <version>4.12</version>
6
+ <scope>test</scope>
7
+ </dependency>
8
+ </dependencies>
@@ -47,30 +47,8 @@ static native_index_t make_index( //
47
47
  config.max_threads_add = std::thread::hardware_concurrency();
48
48
  config.max_threads_search = std::thread::hardware_concurrency();
49
49
 
50
- accuracy_t accuracy;
51
- if (scalar_type == "f32")
52
- accuracy = accuracy_t::f32_k;
53
- else if (scalar_type == "f64")
54
- accuracy = accuracy_t::f64_k;
55
- else if (scalar_type == "f16")
56
- accuracy = accuracy_t::f16_k;
57
- else if (scalar_type == "i8q100")
58
- accuracy = accuracy_t::i8q100_k;
59
- else
60
- throw std::runtime_error("Unknown type, choose: f32, f16, f64, i8q100");
61
-
62
- if (metric == "l2_sq" || metric == "euclidean_sq")
63
- return native_index_t::l2(dimensions, accuracy, config);
64
- else if (metric == "ip" || metric == "inner" || metric == "dot")
65
- return native_index_t::ip(dimensions, accuracy, config);
66
- else if (metric == "cos" || metric == "angular")
67
- return native_index_t::cos(dimensions, accuracy, config);
68
- else if (metric == "haversine")
69
- return native_index_t::haversine(accuracy, config);
70
- else
71
- throw std::runtime_error("Unknown distance, choose: l2_sq, ip, cos, hamming, jaccard");
72
-
73
- return {};
50
+ accuracy_t accuracy = accuracy_from_name(scalar_type.c_str(), scalar_type.size());
51
+ return index_from_name<native_index_t>(metric.c_str(), metric.size(), dimensions, accuracy, config);
74
52
  }
75
53
 
76
54
  static void add_to_index(native_index_t& index, py::buffer labels, py::buffer vectors, bool copy) {
@@ -1,5 +1,5 @@
1
- #include "usearch/src/rust.hpp"
2
- #include "usearch/src/lib.rs.h"
1
+ #include "lib.hpp"
2
+ #include "usearch/rust/lib.rs.h"
3
3
 
4
4
  using namespace unum::usearch;
5
5
  using namespace unum;
@@ -40,7 +40,7 @@ void Index::save(rust::Str path) const { index_->save(std::string(path).c_str())
40
40
  void Index::load(rust::Str path) const { index_->load(std::string(path).c_str()); }
41
41
  void Index::view(rust::Str path) const { index_->view(std::string(path).c_str()); }
42
42
 
43
- accuracy_t accuracy(rust::Str quant) { return accuracy(quant.data(), quant.size()); }
43
+ accuracy_t accuracy(rust::Str quant) { return accuracy_from_name(quant.data(), quant.size()); }
44
44
 
45
45
  std::unique_ptr<Index> wrap(native_index_t&& index) {
46
46
  std::shared_ptr<native_index_t> native = std::make_shared<native_index_t>(std::move(index));
@@ -10,7 +10,7 @@ pub mod ffi {
10
10
 
11
11
  // C++ types and signatures exposed to Rust.
12
12
  unsafe extern "C++" {
13
- include!("rust.hpp");
13
+ include!("lib.hpp");
14
14
 
15
15
  type Index;
16
16
 
package/setup.py CHANGED
@@ -12,7 +12,7 @@ if sys.platform == 'darwin':
12
12
  ext_modules = [
13
13
  Pybind11Extension(
14
14
  'usearch',
15
- ['src/python.cpp'],
15
+ ['python/lib.cpp'],
16
16
  extra_compile_args=compile_args,
17
17
  ),
18
18
  ]
@@ -58,6 +58,6 @@ setup(
58
58
  'Topic :: Scientific/Engineering :: Artificial Intelligence',
59
59
  ],
60
60
 
61
- include_dirs=['include', 'fp16/include', 'simsimd/include'],
61
+ include_dirs=['include', 'fp16/include', 'simsimd/include', 'src'],
62
62
  ext_modules=ext_modules,
63
63
  )
package/src/advanced.hpp CHANGED
@@ -172,26 +172,43 @@ enum class accuracy_t {
172
172
  i8q100_k,
173
173
  };
174
174
 
175
- inline bool str_equals(char const* begin, size_t len, char const* other_begin) noexcept {
176
- size_t other_len = strlen(other_begin);
175
+ inline bool str_equals(char const* begin, std::size_t len, char const* other_begin) noexcept {
176
+ std::size_t other_len = strlen(other_begin);
177
177
  return len == other_len && strncmp(begin, other_begin, len) == 0;
178
178
  }
179
179
 
180
- inline accuracy_t accuracy(char const* str, size_t len) {
180
+ inline accuracy_t accuracy_from_name(char const* name, std::size_t len) {
181
181
  accuracy_t accuracy;
182
- if (str_equals(str, len, "f32"))
182
+ if (str_equals(name, len, "f32"))
183
183
  accuracy = accuracy_t::f32_k;
184
- else if (str_equals(str, len, "f64"))
184
+ else if (str_equals(name, len, "f64"))
185
185
  accuracy = accuracy_t::f64_k;
186
- else if (str_equals(str, len, "f16"))
186
+ else if (str_equals(name, len, "f16"))
187
187
  accuracy = accuracy_t::f16_k;
188
- else if (str_equals(str, len, "i8q100"))
188
+ else if (str_equals(name, len, "i8q100"))
189
189
  accuracy = accuracy_t::i8q100_k;
190
190
  else
191
191
  throw std::runtime_error("Unknown type, choose: f32, f16, f64, i8q100");
192
192
  return accuracy;
193
193
  }
194
194
 
195
+ template <typename index_at>
196
+ inline index_at index_from_name( //
197
+ char const* name, std::size_t len, std::size_t dimensions, accuracy_t accuracy, config_t const& config) {
198
+
199
+ if (str_equals(name, len, "l2_sq") || str_equals(name, len, "euclidean_sq"))
200
+ return index_at::l2(dimensions, accuracy, config);
201
+ else if (str_equals(name, len, "ip") || str_equals(name, len, "inner") || str_equals(name, len, "dot"))
202
+ return index_at::ip(dimensions, accuracy, config);
203
+ else if (str_equals(name, len, "cos") || str_equals(name, len, "angular"))
204
+ return index_at::cos(dimensions, accuracy, config);
205
+ else if (str_equals(name, len, "haversine"))
206
+ return index_at::haversine(accuracy, config);
207
+ else
208
+ throw std::runtime_error("Unknown distance, choose: l2_sq, ip, cos, hamming, jaccard");
209
+ return {};
210
+ }
211
+
195
212
  enum class isa_t {
196
213
  auto_k,
197
214
  neon_k,
@@ -0,0 +1,21 @@
1
+ #include "WolframLibrary.h"
2
+
3
+ EXTERN_C DLLEXPORT mint WolframLibrary_getVersion() { return WolframLibraryVersion; }
4
+ EXTERN_C DLLEXPORT int WolframLibrary_initialize(WolframLibraryData libData) { return 0; }
5
+ EXTERN_C DLLEXPORT void WolframLibrary_uninitialize(WolframLibraryData libData) { return; }
6
+
7
+ EXTERN_C DLLEXPORT int IndexInit(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res) {
8
+ return LIBRARY_NO_ERROR;
9
+ }
10
+
11
+ EXTERN_C DLLEXPORT int IndexReserve(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res) {
12
+ return LIBRARY_NO_ERROR;
13
+ }
14
+
15
+ EXTERN_C DLLEXPORT int IndexAdd(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res) {
16
+ return LIBRARY_NO_ERROR;
17
+ }
18
+
19
+ EXTERN_C DLLEXPORT int IndexSearch(WolframLibraryData libData, mint Argc, MArgument* Args, MArgument Res) {
20
+ return LIBRARY_NO_ERROR;
21
+ }
File without changes
File without changes
File without changes
File without changes
File without changes