usearch 2.8.3 → 2.8.5
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/.github/workflows/release.yml +4 -2
- package/.vscode/settings.json +179 -179
- package/CITATION.cff +1 -1
- package/CONTRIBUTING.md +268 -6
- package/Cargo.toml +1 -1
- package/README.md +64 -59
- package/build.gradle +7 -9
- package/conanfile.py +1 -1
- package/cpp/README.md +89 -21
- package/csharp/DEV_SETUP.md +1 -1
- package/csharp/nuget/nuget-package.props +1 -1
- package/docs/{compilation.rst → contributing.rst} +2 -2
- package/docs/index.rst +1 -1
- package/include/usearch/index.hpp +1 -1
- package/include/usearch/index_dense.hpp +11 -7
- package/java/cloud/unum/usearch/Index.java +119 -53
- package/package.json +1 -1
- package/python/README.md +1 -1
- package/simsimd/CMakeLists.txt +1 -1
- package/simsimd/README.md +7 -1
- package/simsimd/include/simsimd/probability.h +24 -24
- package/simsimd/include/simsimd/types.h +8 -0
- package/simsimd/javascript/{test.js → test/simsimd.test.js} +15 -15
- package/simsimd/package.json +4 -8
- package/simsimd/setup.py +3 -0
- package/wasmer.toml +1 -1
- package/docs/compilation.md +0 -215
- package/simsimd/.clang-format +0 -10
- package/simsimd/.github/workflows/prerelease.yml +0 -89
- package/simsimd/.github/workflows/release.yml +0 -141
- package/simsimd/.github/workflows/update_version.sh +0 -5
- package/simsimd/.vscode/launch.json +0 -53
- package/simsimd/.vscode/settings.json +0 -114
- package/simsimd/.vscode/tasks.json +0 -23
- package/simsimd/go.mod +0 -3
- package/simsimd/golang/bench_test.go +0 -40
- package/simsimd/golang/simsimd.go +0 -47
- package/simsimd/golang/unit_test.go +0 -40
- package/simsimd/pyproject.toml +0 -42
- package/simsimd/python/bench.ipynb +0 -187
- package/simsimd/python/bench.py +0 -268
- package/simsimd/python/lib.c +0 -492
- package/simsimd/python/test.py +0 -195
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
package cloud.unum.usearch;
|
|
2
2
|
|
|
3
|
-
import java.io.File;
|
|
4
|
-
import java.io.InputStream;
|
|
5
|
-
import java.nio.file.Files;
|
|
6
|
-
import java.nio.file.StandardCopyOption;
|
|
7
|
-
|
|
8
3
|
/**
|
|
9
4
|
* Java bindings for Unum USearch.
|
|
10
5
|
* <p>
|
|
11
|
-
* Provides interface to interact with USearch library and perform various
|
|
6
|
+
* Provides interface to interact with USearch library and perform various
|
|
7
|
+
* operations related to indexing and searching.
|
|
12
8
|
*
|
|
13
|
-
* @see <a href=
|
|
14
|
-
*
|
|
9
|
+
* @see <a href=
|
|
10
|
+
* "https://nachtimwald.com/2017/06/06/wrapping-a-c-library-in-java/">Wrapping
|
|
11
|
+
* a C library in Java</a>
|
|
12
|
+
* @see <a href=
|
|
13
|
+
* "https://www3.ntu.edu.sg/home/ehchua/programming/java/javanativeinterface.html">Java
|
|
14
|
+
* Native Interface tutorial</a>
|
|
15
15
|
*/
|
|
16
16
|
public class Index {
|
|
17
17
|
|
|
@@ -20,33 +20,34 @@ public class Index {
|
|
|
20
20
|
/**
|
|
21
21
|
* Creates a new instance of Index with specified parameters.
|
|
22
22
|
*
|
|
23
|
-
* @param metric
|
|
24
|
-
*
|
|
25
|
-
* @param
|
|
26
|
-
* @param
|
|
27
|
-
* @param
|
|
28
|
-
* @param
|
|
29
|
-
*
|
|
23
|
+
* @param metric the metric type for distance calculation between
|
|
24
|
+
* vectors
|
|
25
|
+
* @param quantization the scalar type for quantization of vector data
|
|
26
|
+
* @param dimensions the number of dimensions in the vectors
|
|
27
|
+
* @param capacity the initial capacity of the index
|
|
28
|
+
* @param connectivity the connectivity parameter that limits
|
|
29
|
+
* connections-per-node in graph
|
|
30
|
+
* @param expansion_add the expansion factor used for index construction when
|
|
31
|
+
* adding vectors
|
|
32
|
+
* @param expansion_search the expansion factor used for index construction
|
|
33
|
+
* during search operations
|
|
30
34
|
*/
|
|
31
35
|
public Index(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
c_ptr =
|
|
41
|
-
c_create(
|
|
36
|
+
String metric,
|
|
37
|
+
String quantization,
|
|
38
|
+
long dimensions,
|
|
39
|
+
long capacity,
|
|
40
|
+
long connectivity,
|
|
41
|
+
long expansion_add,
|
|
42
|
+
long expansion_search) {
|
|
43
|
+
c_ptr = c_create(
|
|
42
44
|
metric,
|
|
43
45
|
quantization,
|
|
44
46
|
dimensions,
|
|
45
47
|
capacity,
|
|
46
48
|
connectivity,
|
|
47
49
|
expansion_add,
|
|
48
|
-
expansion_search
|
|
49
|
-
);
|
|
50
|
+
expansion_search);
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
/**
|
|
@@ -97,8 +98,8 @@ public class Index {
|
|
|
97
98
|
/**
|
|
98
99
|
* Adds a vector with a specified key to the index.
|
|
99
100
|
*
|
|
100
|
-
* @param key
|
|
101
|
-
* @param vector
|
|
101
|
+
* @param key the key associated with the vector
|
|
102
|
+
* @param vector the vector data
|
|
102
103
|
*/
|
|
103
104
|
public void add(int key, float vector[]) {
|
|
104
105
|
c_add(c_ptr, key, vector);
|
|
@@ -107,9 +108,9 @@ public class Index {
|
|
|
107
108
|
/**
|
|
108
109
|
* Searches for closest vectors to the specified query vector.
|
|
109
110
|
*
|
|
110
|
-
* @param vector
|
|
111
|
-
* @param count
|
|
112
|
-
* @return
|
|
111
|
+
* @param vector the query vector data
|
|
112
|
+
* @param count the number of nearest neighbors to search
|
|
113
|
+
* @return an array of keys of the nearest neighbors
|
|
113
114
|
*/
|
|
114
115
|
public int[] search(float vector[], long count) {
|
|
115
116
|
return c_search(c_ptr, vector, count);
|
|
@@ -146,7 +147,8 @@ public class Index {
|
|
|
146
147
|
* Removes the vector associated with the given key from the index.
|
|
147
148
|
*
|
|
148
149
|
* @param key the key of the vector to be removed.
|
|
149
|
-
* @return {@code true} if the vector was successfully removed, {@code false}
|
|
150
|
+
* @return {@code true} if the vector was successfully removed, {@code false}
|
|
151
|
+
* otherwise.
|
|
150
152
|
*/
|
|
151
153
|
public boolean remove(int key) {
|
|
152
154
|
return c_remove(c_ptr, key);
|
|
@@ -156,13 +158,21 @@ public class Index {
|
|
|
156
158
|
* Renames the vector to map to a different key.
|
|
157
159
|
*
|
|
158
160
|
* @param from the key of the vector to be renamed.
|
|
159
|
-
* @param to
|
|
160
|
-
* @return {@code true} if the vector was successfully renamed, {@code false}
|
|
161
|
+
* @param to the new key for the vector.
|
|
162
|
+
* @return {@code true} if the vector was successfully renamed, {@code false}
|
|
163
|
+
* otherwise.
|
|
161
164
|
*/
|
|
162
165
|
public boolean rename(int from, int to) {
|
|
163
166
|
return c_rename(c_ptr, from, to);
|
|
164
167
|
}
|
|
165
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Configuration class for building an Index instance.
|
|
171
|
+
* <p>
|
|
172
|
+
* This class provides a builder pattern to set various configurations for an
|
|
173
|
+
* Index. Once all configurations
|
|
174
|
+
* are set, calling {@link #build()} will produce an instance of {@link Index}.
|
|
175
|
+
*/
|
|
166
176
|
public static class Config {
|
|
167
177
|
|
|
168
178
|
private String _metric = "ip";
|
|
@@ -173,50 +183,102 @@ public class Index {
|
|
|
173
183
|
private long _expansion_add = 0;
|
|
174
184
|
private long _expansion_search = 0;
|
|
175
185
|
|
|
176
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Default constructor for the Config class.
|
|
188
|
+
*/
|
|
189
|
+
public Config() {
|
|
190
|
+
}
|
|
177
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Constructs an Index instance based on the current configuration settings.
|
|
194
|
+
*
|
|
195
|
+
* @return a newly constructed Index instance.
|
|
196
|
+
*/
|
|
178
197
|
public Index build() {
|
|
179
198
|
return new Index(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
);
|
|
199
|
+
_metric,
|
|
200
|
+
_quantization,
|
|
201
|
+
_dimensions,
|
|
202
|
+
_capacity,
|
|
203
|
+
_connectivity,
|
|
204
|
+
_expansion_add,
|
|
205
|
+
_expansion_search);
|
|
188
206
|
}
|
|
189
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Sets the metric for distance calculation between vectors.
|
|
210
|
+
*
|
|
211
|
+
* @param _metric the metric type
|
|
212
|
+
* @return this configuration instance
|
|
213
|
+
*/
|
|
190
214
|
public Config metric(String _metric) {
|
|
191
215
|
this._metric = _metric;
|
|
192
216
|
return this;
|
|
193
217
|
}
|
|
194
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Sets the scalar type for quantization of vector data.
|
|
221
|
+
*
|
|
222
|
+
* @param _quantization the quantization type
|
|
223
|
+
* @return this configuration instance
|
|
224
|
+
*/
|
|
195
225
|
public Config quantization(String _quantization) {
|
|
196
226
|
this._quantization = _quantization;
|
|
197
227
|
return this;
|
|
198
228
|
}
|
|
199
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Sets the number of dimensions in the vectors.
|
|
232
|
+
*
|
|
233
|
+
* @param _dimensions the number of dimensions
|
|
234
|
+
* @return this configuration instance
|
|
235
|
+
*/
|
|
200
236
|
public Config dimensions(long _dimensions) {
|
|
201
237
|
this._dimensions = _dimensions;
|
|
202
238
|
return this;
|
|
203
239
|
}
|
|
204
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Sets the initial capacity of the index.
|
|
243
|
+
*
|
|
244
|
+
* @param _capacity the index capacity
|
|
245
|
+
* @return this configuration instance
|
|
246
|
+
*/
|
|
205
247
|
public Config capacity(long _capacity) {
|
|
206
248
|
this._capacity = _capacity;
|
|
207
249
|
return this;
|
|
208
250
|
}
|
|
209
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Sets the connectivity parameter that limits connections-per-node in the
|
|
254
|
+
* graph.
|
|
255
|
+
*
|
|
256
|
+
* @param _connectivity the connectivity value
|
|
257
|
+
* @return this configuration instance
|
|
258
|
+
*/
|
|
210
259
|
public Config connectivity(long _connectivity) {
|
|
211
260
|
this._connectivity = _connectivity;
|
|
212
261
|
return this;
|
|
213
262
|
}
|
|
214
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Sets the expansion factor used for index construction when adding vectors.
|
|
266
|
+
*
|
|
267
|
+
* @param _expansion_add the expansion factor for adding vectors
|
|
268
|
+
* @return this configuration instance
|
|
269
|
+
*/
|
|
215
270
|
public Config expansion_add(long _expansion_add) {
|
|
216
271
|
this._expansion_add = _expansion_add;
|
|
217
272
|
return this;
|
|
218
273
|
}
|
|
219
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Sets the expansion factor used for index construction during search
|
|
277
|
+
* operations.
|
|
278
|
+
*
|
|
279
|
+
* @param _expansion_search the expansion factor for search
|
|
280
|
+
* @return this configuration instance
|
|
281
|
+
*/
|
|
220
282
|
public Config expansion_search(long _expansion_search) {
|
|
221
283
|
this._expansion_search = _expansion_search;
|
|
222
284
|
return this;
|
|
@@ -227,21 +289,25 @@ public class Index {
|
|
|
227
289
|
System.loadLibrary("usearch");
|
|
228
290
|
}
|
|
229
291
|
|
|
292
|
+
/**
|
|
293
|
+
* A simple main method to test the Index functionalities.
|
|
294
|
+
*
|
|
295
|
+
* @param args command line arguments (not used in this case)
|
|
296
|
+
*/
|
|
230
297
|
public static void main(String[] args) {
|
|
231
298
|
Index index = new Index.Config().metric("cos").dimensions(100).build();
|
|
232
299
|
index.size();
|
|
233
300
|
System.out.println("Java tests passed!");
|
|
234
301
|
}
|
|
235
302
|
|
|
236
|
-
private static native long c_create(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
);
|
|
303
|
+
private static native long c_create(
|
|
304
|
+
String metric,
|
|
305
|
+
String quantization,
|
|
306
|
+
long dimensions,
|
|
307
|
+
long capacity,
|
|
308
|
+
long connectivity,
|
|
309
|
+
long expansion_add,
|
|
310
|
+
long expansion_search);
|
|
245
311
|
|
|
246
312
|
private static native void c_destroy(long ptr);
|
|
247
313
|
|
package/package.json
CHANGED
package/python/README.md
CHANGED
package/simsimd/CMakeLists.txt
CHANGED
|
@@ -48,7 +48,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "^(Apple)?Clang$")
|
|
|
48
48
|
endif()
|
|
49
49
|
add_compile_options(-pedantic -ferror-limit=1)
|
|
50
50
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|
51
|
-
add_compile_options(-march=native -pedantic -fmax-errors=1)
|
|
51
|
+
add_compile_options(-march=native -pedantic -fmax-errors=1 -Wno-tautological-constant-compare)
|
|
52
52
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
|
|
53
53
|
add_compile_options(-w -ferror-limit=1)
|
|
54
54
|
endif()
|
package/simsimd/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# SimSIMD 📏
|
|
2
2
|
|
|
3
|
+
<div>
|
|
4
|
+
<a href="https://pypi.org/project/simsimd/"> <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/simsimd?label=pypi%20downloads"> </a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/simsimd"> <img alt="npm" src="https://img.shields.io/npm/dy/simsimd?label=npm%20dowloads"> </a>
|
|
6
|
+
<img alt="GitHub code size in bytes" src="https://img.shields.io/github/languages/code-size/ashvardanian/simsimd">
|
|
7
|
+
</div>
|
|
8
|
+
|
|
3
9
|
## Efficient Alternative to [`scipy.spatial.distance`][scipy] and [`numpy.inner`][numpy]
|
|
4
10
|
|
|
5
11
|
SimSIMD leverages SIMD intrinsics, capabilities that only select compilers effectively utilize. This framework supports conventional AVX2 instructions on x86, NEON on Arm, as well as __rare__ AVX-512 FP16 instructions on x86 and Scalable Vector Extensions (SVE) on Arm. Designed specifically for Machine Learning contexts, it's optimized for handling high-dimensional vector embeddings.
|
|
@@ -189,7 +195,7 @@ __To test and benchmark JavaScript bindings__:
|
|
|
189
195
|
```sh
|
|
190
196
|
npm install --dev
|
|
191
197
|
npm test
|
|
192
|
-
npm bench
|
|
198
|
+
npm run bench
|
|
193
199
|
```
|
|
194
200
|
|
|
195
201
|
__To test and benchmark GoLang bindings__:
|
|
@@ -52,17 +52,17 @@
|
|
|
52
52
|
extern "C" {
|
|
53
53
|
#endif
|
|
54
54
|
|
|
55
|
-
SIMSIMD_MAKE_KL(serial, f32, f32, SIMSIMD_IDENTIFY,
|
|
56
|
-
SIMSIMD_MAKE_JS(serial, f32, f32, SIMSIMD_IDENTIFY,
|
|
55
|
+
SIMSIMD_MAKE_KL(serial, f32, f32, SIMSIMD_IDENTIFY, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f32_kl
|
|
56
|
+
SIMSIMD_MAKE_JS(serial, f32, f32, SIMSIMD_IDENTIFY, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f32_js
|
|
57
57
|
|
|
58
|
-
SIMSIMD_MAKE_KL(serial, f16, f32, SIMSIMD_UNCOMPRESS_F16,
|
|
59
|
-
SIMSIMD_MAKE_JS(serial, f16, f32, SIMSIMD_UNCOMPRESS_F16,
|
|
58
|
+
SIMSIMD_MAKE_KL(serial, f16, f32, SIMSIMD_UNCOMPRESS_F16, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f16_kl
|
|
59
|
+
SIMSIMD_MAKE_JS(serial, f16, f32, SIMSIMD_UNCOMPRESS_F16, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f16_js
|
|
60
60
|
|
|
61
|
-
SIMSIMD_MAKE_KL(accurate, f32, f64, SIMSIMD_IDENTIFY,
|
|
62
|
-
SIMSIMD_MAKE_JS(accurate, f32, f64, SIMSIMD_IDENTIFY,
|
|
61
|
+
SIMSIMD_MAKE_KL(accurate, f32, f64, SIMSIMD_IDENTIFY, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_accurate_f32_kl
|
|
62
|
+
SIMSIMD_MAKE_JS(accurate, f32, f64, SIMSIMD_IDENTIFY, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_accurate_f32_js
|
|
63
63
|
|
|
64
|
-
SIMSIMD_MAKE_KL(accurate, f16, f64, SIMSIMD_UNCOMPRESS_F16,
|
|
65
|
-
SIMSIMD_MAKE_JS(accurate, f16, f64, SIMSIMD_UNCOMPRESS_F16,
|
|
64
|
+
SIMSIMD_MAKE_KL(accurate, f16, f64, SIMSIMD_UNCOMPRESS_F16, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_accurate_f16_kl
|
|
65
|
+
SIMSIMD_MAKE_JS(accurate, f16, f64, SIMSIMD_UNCOMPRESS_F16, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_accurate_f16_js
|
|
66
66
|
|
|
67
67
|
#if SIMSIMD_TARGET_ARM
|
|
68
68
|
#if SIMSIMD_TARGET_ARM_NEON
|
|
@@ -108,7 +108,7 @@ __attribute__((target("+simd"))) //
|
|
|
108
108
|
inline static simsimd_f32_t
|
|
109
109
|
simsimd_neon_f32_kl(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
|
|
110
110
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
111
|
-
simsimd_f32_t epsilon =
|
|
111
|
+
simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
|
|
112
112
|
float32x4_t epsilon_vec = vdupq_n_f32(epsilon);
|
|
113
113
|
simsimd_size_t i = 0;
|
|
114
114
|
for (; i + 4 <= n; i += 4) {
|
|
@@ -129,7 +129,7 @@ simsimd_neon_f32_kl(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size
|
|
|
129
129
|
__attribute__((target("+simd"))) inline static simsimd_f32_t
|
|
130
130
|
simsimd_neon_f32_js(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
|
|
131
131
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
132
|
-
simsimd_f32_t epsilon =
|
|
132
|
+
simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
|
|
133
133
|
float32x4_t epsilon_vec = vdupq_n_f32(epsilon);
|
|
134
134
|
simsimd_size_t i = 0;
|
|
135
135
|
for (; i + 4 <= n; i += 4) {
|
|
@@ -147,11 +147,11 @@ simsimd_neon_f32_js(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size
|
|
|
147
147
|
simsimd_f32_t log2_normalizer = 0.693147181f;
|
|
148
148
|
simsimd_f32_t sum = vaddvq_f32(sum_vec) * log2_normalizer;
|
|
149
149
|
for (; i < n; ++i) {
|
|
150
|
-
simsimd_f32_t mi = a[i] + b[i];
|
|
150
|
+
simsimd_f32_t mi = 0.5f * (a[i] + b[i]);
|
|
151
151
|
sum += a[i] * SIMSIMD_LOG((a[i] + epsilon) / (mi + epsilon));
|
|
152
152
|
sum += b[i] * SIMSIMD_LOG((b[i] + epsilon) / (mi + epsilon));
|
|
153
153
|
}
|
|
154
|
-
return sum
|
|
154
|
+
return sum;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
/*
|
|
@@ -168,7 +168,7 @@ __attribute__((target("+simd+fp16"))) //
|
|
|
168
168
|
inline static simsimd_f32_t
|
|
169
169
|
simsimd_neon_f16_kl(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
170
170
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
171
|
-
simsimd_f32_t epsilon =
|
|
171
|
+
simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
|
|
172
172
|
float32x4_t epsilon_vec = vdupq_n_f32(epsilon);
|
|
173
173
|
simsimd_size_t i = 0;
|
|
174
174
|
for (; i + 4 <= n; i += 4) {
|
|
@@ -191,7 +191,7 @@ __attribute__((target("+simd+fp16"))) //
|
|
|
191
191
|
inline static simsimd_f32_t
|
|
192
192
|
simsimd_neon_f16_js(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
193
193
|
float32x4_t sum_vec = vdupq_n_f32(0);
|
|
194
|
-
simsimd_f32_t epsilon =
|
|
194
|
+
simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
|
|
195
195
|
float32x4_t epsilon_vec = vdupq_n_f32(epsilon);
|
|
196
196
|
simsimd_size_t i = 0;
|
|
197
197
|
for (; i + 4 <= n; i += 4) {
|
|
@@ -211,11 +211,11 @@ simsimd_neon_f16_js(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size
|
|
|
211
211
|
for (; i < n; ++i) {
|
|
212
212
|
simsimd_f32_t ai = SIMSIMD_UNCOMPRESS_F16(a[i]);
|
|
213
213
|
simsimd_f32_t bi = SIMSIMD_UNCOMPRESS_F16(b[i]);
|
|
214
|
-
simsimd_f32_t mi = ai + bi;
|
|
214
|
+
simsimd_f32_t mi = 0.5f * (ai + bi);
|
|
215
215
|
sum += ai * SIMSIMD_LOG((ai + epsilon) / (mi + epsilon));
|
|
216
216
|
sum += bi * SIMSIMD_LOG((bi + epsilon) / (mi + epsilon));
|
|
217
217
|
}
|
|
218
|
-
return sum
|
|
218
|
+
return sum;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
#endif // SIMSIMD_TARGET_ARM_NEON
|
|
@@ -268,7 +268,7 @@ __attribute__((target("avx2,f16c,fma"))) //
|
|
|
268
268
|
inline static simsimd_f32_t
|
|
269
269
|
simsimd_avx2_f16_kl(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
270
270
|
__m256 sum_vec = _mm256_set1_ps(0);
|
|
271
|
-
simsimd_f32_t epsilon =
|
|
271
|
+
simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
|
|
272
272
|
__m256 epsilon_vec = _mm256_set1_ps(epsilon);
|
|
273
273
|
simsimd_size_t i = 0;
|
|
274
274
|
for (; i + 8 <= n; i += 8) {
|
|
@@ -300,7 +300,7 @@ __attribute__((target("avx2,f16c,fma"))) //
|
|
|
300
300
|
inline static simsimd_f32_t
|
|
301
301
|
simsimd_avx2_f16_js(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
302
302
|
__m256 sum_vec = _mm256_set1_ps(0);
|
|
303
|
-
simsimd_f32_t epsilon =
|
|
303
|
+
simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
|
|
304
304
|
__m256 epsilon_vec = _mm256_set1_ps(epsilon);
|
|
305
305
|
simsimd_size_t i = 0;
|
|
306
306
|
for (; i + 8 <= n; i += 8) {
|
|
@@ -374,7 +374,7 @@ __attribute__((target("avx512f,avx512vl,bmi2"))) //
|
|
|
374
374
|
inline static simsimd_f32_t
|
|
375
375
|
simsimd_avx512_f32_kl(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
|
|
376
376
|
__m512 sum_vec = _mm512_set1_ps(0);
|
|
377
|
-
simsimd_f32_t epsilon =
|
|
377
|
+
simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
|
|
378
378
|
__m512 epsilon_vec = _mm512_set1_ps(epsilon);
|
|
379
379
|
__m512 a_vec, b_vec;
|
|
380
380
|
|
|
@@ -405,7 +405,7 @@ inline static simsimd_f32_t
|
|
|
405
405
|
simsimd_avx512_f32_js(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n) {
|
|
406
406
|
__m512 sum_a_vec = _mm512_set1_ps(0);
|
|
407
407
|
__m512 sum_b_vec = _mm512_set1_ps(0);
|
|
408
|
-
simsimd_f32_t epsilon =
|
|
408
|
+
simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
|
|
409
409
|
__m512 epsilon_vec = _mm512_set1_ps(epsilon);
|
|
410
410
|
__m512 a_vec, b_vec;
|
|
411
411
|
|
|
@@ -425,8 +425,8 @@ simsimd_avx512_f32_js_cycle:
|
|
|
425
425
|
__mmask16 nonzero_mask_b = _mm512_cmp_ps_mask(b_vec, epsilon_vec, _CMP_GE_OQ);
|
|
426
426
|
__mmask16 nonzero_mask = nonzero_mask_a & nonzero_mask_b;
|
|
427
427
|
__m512 m_recip_approx = _mm512_rcp14_ps(m_vec);
|
|
428
|
-
__m512 ratio_a_vec =
|
|
429
|
-
__m512 ratio_b_vec =
|
|
428
|
+
__m512 ratio_a_vec = _mm512_div_ps(a_vec, m_vec);
|
|
429
|
+
__m512 ratio_b_vec = _mm512_div_ps(b_vec, m_vec);
|
|
430
430
|
__m512 log_ratio_a_vec = simsimd_avx512_f32_log2(ratio_a_vec);
|
|
431
431
|
__m512 log_ratio_b_vec = simsimd_avx512_f32_log2(ratio_b_vec);
|
|
432
432
|
sum_a_vec = _mm512_maskz_fmadd_ps(nonzero_mask, a_vec, log_ratio_a_vec, sum_a_vec);
|
|
@@ -472,7 +472,7 @@ __attribute__((target("avx512f,avx512vl,avx512fp16,bmi2"))) //
|
|
|
472
472
|
inline static simsimd_f32_t
|
|
473
473
|
simsimd_avx512_f16_kl(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
474
474
|
__m512h sum_vec = _mm512_set1_ph((_Float16)0);
|
|
475
|
-
__m512h epsilon_vec = _mm512_set1_ph((_Float16)
|
|
475
|
+
__m512h epsilon_vec = _mm512_set1_ph((_Float16)SIMSIMD_F16_DIVISION_EPSILON);
|
|
476
476
|
__m512h a_vec, b_vec;
|
|
477
477
|
|
|
478
478
|
simsimd_avx512_f16_kl_cycle:
|
|
@@ -502,7 +502,7 @@ inline static simsimd_f32_t
|
|
|
502
502
|
simsimd_avx512_f16_js(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n) {
|
|
503
503
|
__m512h sum_a_vec = _mm512_set1_ph((_Float16)0);
|
|
504
504
|
__m512h sum_b_vec = _mm512_set1_ph((_Float16)0);
|
|
505
|
-
__m512h epsilon_vec = _mm512_set1_ph((_Float16)
|
|
505
|
+
__m512h epsilon_vec = _mm512_set1_ph((_Float16)SIMSIMD_F16_DIVISION_EPSILON);
|
|
506
506
|
__m512h a_vec, b_vec;
|
|
507
507
|
|
|
508
508
|
simsimd_avx512_f16_js_cycle:
|
|
@@ -91,6 +91,14 @@
|
|
|
91
91
|
#define SIMSIMD_LOG(x) (logf(x))
|
|
92
92
|
#endif
|
|
93
93
|
|
|
94
|
+
#ifndef SIMSIMD_F32_DIVISION_EPSILON
|
|
95
|
+
#define SIMSIMD_F32_DIVISION_EPSILON 1e-7
|
|
96
|
+
#endif
|
|
97
|
+
|
|
98
|
+
#ifndef SIMSIMD_F16_DIVISION_EPSILON
|
|
99
|
+
#define SIMSIMD_F16_DIVISION_EPSILON 1e-3
|
|
100
|
+
#endif
|
|
101
|
+
|
|
94
102
|
#ifdef __cplusplus
|
|
95
103
|
extern "C" {
|
|
96
104
|
#endif
|
|
@@ -4,12 +4,6 @@ import assert from 'node:assert';
|
|
|
4
4
|
|
|
5
5
|
const simsimd = bindings('simsimd');
|
|
6
6
|
|
|
7
|
-
const f32Array1 = new Float32Array([1.0, 2.0, 3.0]);
|
|
8
|
-
const f32Array2 = new Float32Array([4.0, 5.0, 6.0]);
|
|
9
|
-
|
|
10
|
-
const u8Array1 = new Uint8Array([1, 2, 3]);
|
|
11
|
-
const u8Array2 = new Uint8Array([4, 5, 6]);
|
|
12
|
-
|
|
13
7
|
function assertAlmostEqual(actual, expected, tolerance = 1e-6) {
|
|
14
8
|
const lowerBound = expected - tolerance;
|
|
15
9
|
const upperBound = expected + tolerance;
|
|
@@ -17,20 +11,26 @@ function assertAlmostEqual(actual, expected, tolerance = 1e-6) {
|
|
|
17
11
|
}
|
|
18
12
|
|
|
19
13
|
test('Distance from itself', () => {
|
|
20
|
-
assertAlmostEqual(simsimd.sqeuclidean(f32Array1, f32Array1), 0.0, 0.01);
|
|
21
|
-
assertAlmostEqual(simsimd.cosine(f32Array1, f32Array1), 0.0, 0.01);
|
|
22
14
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
assertAlmostEqual(simsimd.
|
|
15
|
+
const f32s = new Float32Array([1.0, 2.0, 3.0]);
|
|
16
|
+
assertAlmostEqual(simsimd.sqeuclidean(f32s, f32s), 0.0, 0.01);
|
|
17
|
+
assertAlmostEqual(simsimd.cosine(f32s, f32s), 0.0, 0.01);
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
assertAlmostEqual(simsimd.
|
|
19
|
+
const f32sNormalized = new Float32Array([1.0 / Math.sqrt(14), 2.0 / Math.sqrt(14), 3.0 / Math.sqrt(14)]);
|
|
20
|
+
assertAlmostEqual(simsimd.inner(f32sNormalized, f32sNormalized), 0.0, 0.01);
|
|
29
21
|
|
|
30
|
-
|
|
31
|
-
assertAlmostEqual(simsimd.
|
|
22
|
+
const f32sDistribution = new Float32Array([1.0 / 6, 2.0 / 6, 3.0 / 6]);
|
|
23
|
+
assertAlmostEqual(simsimd.kullbackleibler(f32sDistribution, f32sDistribution), 0.0, 0.01);
|
|
24
|
+
assertAlmostEqual(simsimd.jensenshannon(f32sDistribution, f32sDistribution), 0.0, 0.01);
|
|
25
|
+
|
|
26
|
+
const u8s = new Uint8Array([1, 2, 3]);
|
|
27
|
+
assertAlmostEqual(simsimd.hamming(u8s, u8s), 0.0, 0.01);
|
|
28
|
+
assertAlmostEqual(simsimd.jaccard(u8s, u8s), 0.0, 0.01);
|
|
32
29
|
});
|
|
33
30
|
|
|
31
|
+
const f32Array1 = new Float32Array([1.0, 2.0, 3.0]);
|
|
32
|
+
const f32Array2 = new Float32Array([4.0, 5.0, 6.0]);
|
|
33
|
+
|
|
34
34
|
test('Squared Euclidean Distance', () => {
|
|
35
35
|
const result = simsimd.sqeuclidean(f32Array1, f32Array2);
|
|
36
36
|
assertAlmostEqual(result, 27.0, 0.01);
|
package/simsimd/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "simsimd",
|
|
3
|
-
"version": "3.3
|
|
3
|
+
"version": "3.5.3",
|
|
4
4
|
"description": "Vector Similarity Functions 3x-200x Faster than SciPy and NumPy",
|
|
5
5
|
"author": "Ash Vardanian",
|
|
6
6
|
"license": "Apache 2.0",
|
|
7
7
|
"main": "javascript/simsimd.js",
|
|
8
8
|
"type": "module",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node --test ./javascript/test",
|
|
11
|
+
"bench": "node ./javascript/bench.js"
|
|
12
12
|
},
|
|
13
13
|
"gypfile": true,
|
|
14
14
|
"engines": {
|
|
@@ -19,10 +19,6 @@
|
|
|
19
19
|
"bindings": "~1.2.1",
|
|
20
20
|
"node-addon-api": "^3.0.0"
|
|
21
21
|
},
|
|
22
|
-
"scripts": {
|
|
23
|
-
"test": "node --test ./javascript/test.js",
|
|
24
|
-
"bench": "node ./javascript/bench.js"
|
|
25
|
-
},
|
|
26
22
|
"devDependencies": {
|
|
27
23
|
"benchmark": "^2.1.4",
|
|
28
24
|
"mathjs": "^11.11.2",
|
package/simsimd/setup.py
CHANGED
|
@@ -27,6 +27,9 @@ if sys.platform == "linux":
|
|
|
27
27
|
compile_args.append("-fopenmp")
|
|
28
28
|
link_args.append("-lgomp")
|
|
29
29
|
|
|
30
|
+
# Add vectorized `logf` implementation from the `glibc`
|
|
31
|
+
link_args.append("-lm")
|
|
32
|
+
|
|
30
33
|
if sys.platform == "darwin":
|
|
31
34
|
compile_args.append("-std=c11")
|
|
32
35
|
compile_args.append("-O3")
|