usearch 2.15.3 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/cpp/test.cpp +16 -0
- package/include/usearch/index.hpp +21 -5
- package/include/usearch/index_dense.hpp +6 -1
- package/include/usearch/index_plugins.hpp +345 -8
- package/javascript/lib.cpp +17 -5
- package/javascript/usearch.test.js +190 -21
- package/package.json +1 -1
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/simsimd/.git-blame-ignore-revs +2 -0
- package/simsimd/CONTRIBUTING.md +71 -23
- package/simsimd/Cargo.lock +1 -1
- package/simsimd/Cargo.toml +4 -4
- package/simsimd/MANIFEST.in +2 -1
- package/simsimd/Package.swift +15 -3
- package/simsimd/README.md +104 -35
- package/simsimd/binding.gyp +6 -2
- package/simsimd/build.rs +2 -0
- package/simsimd/c/lib.c +180 -99
- package/simsimd/include/simsimd/binary.h +311 -102
- package/simsimd/include/simsimd/curved.h +134 -135
- package/simsimd/include/simsimd/dot.h +448 -274
- package/simsimd/include/simsimd/elementwise.h +1437 -0
- package/simsimd/include/simsimd/geospatial.h +2 -2
- package/simsimd/include/simsimd/mesh.h +2 -2
- package/simsimd/include/simsimd/probability.h +88 -88
- package/simsimd/include/simsimd/simsimd.h +1157 -772
- package/simsimd/include/simsimd/sparse.h +768 -147
- package/simsimd/include/simsimd/spatial.h +955 -376
- package/simsimd/include/simsimd/types.h +145 -71
- package/simsimd/javascript/lib.c +1 -2
- package/simsimd/package.json +4 -4
- package/simsimd/rust/lib.rs +14 -1
- package/simsimd/scripts/bench.cxx +1070 -0
- package/simsimd/scripts/bench.ipynb +187 -0
- package/simsimd/{javascript → scripts}/bench.js +1 -1
- package/simsimd/{rust/benches/sqeuclidean.rs → scripts/bench_sqeuclidean.rs} +6 -6
- package/simsimd/scripts/bench_vectors.py +700 -0
- package/simsimd/scripts/bench_vectors_live.py +213 -0
- package/simsimd/scripts/test.c +155 -0
- package/simsimd/{javascript → scripts}/test.mjs +2 -2
- package/simsimd/scripts/test.py +1410 -0
- package/simsimd/swift/{source/SimSIMD.swift → SimSIMD.swift} +6 -2
- package/simsimd/swift/{tests/SimSIMDTests.swift → Test.swift} +1 -1
- /package/simsimd/{rust/benches/cosine.rs → scripts/bench_cosine.rs} +0 -0
- /package/simsimd/{rust/benches/native.rs → scripts/bench_native.rs} +0 -0
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
const test = require('node:test');
|
|
2
2
|
const assert = require('node:assert');
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const os = require('node:os');
|
|
5
|
+
const path = require('node:path');
|
|
3
6
|
const usearch = require('./dist/cjs/usearch.js');
|
|
4
7
|
|
|
5
8
|
function assertAlmostEqual(actual, expected, tolerance = 1e-6) {
|
|
@@ -12,38 +15,84 @@ function assertAlmostEqual(actual, expected, tolerance = 1e-6) {
|
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
|
|
15
|
-
test('Single-entry operations', () => {
|
|
16
|
-
|
|
18
|
+
test('Single-entry operations', async (t) => {
|
|
19
|
+
await t.test('index info', () => {
|
|
20
|
+
const index = new usearch.Index(2, 'l2sq');
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
assert.equal(index.connectivity(), 16, 'connectivity should be 16');
|
|
23
|
+
assert.equal(index.dimensions(), 2, 'dimensions should be 2');
|
|
24
|
+
assert.equal(index.size(), 0, 'initial size should be 0');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
await t.test('add', () => {
|
|
28
|
+
const index = new usearch.Index(2, 'l2sq');
|
|
29
|
+
|
|
30
|
+
index.add(15n, new Float32Array([10, 20]));
|
|
31
|
+
index.add(16n, new Float32Array([10, 25]));
|
|
32
|
+
|
|
33
|
+
assert.equal(index.size(), 2, 'size after adding elements should be 2');
|
|
34
|
+
assert.equal(index.contains(15), true, 'entry must be present after insertion');
|
|
35
|
+
|
|
36
|
+
const results = index.search(new Float32Array([13, 14]), 2);
|
|
37
|
+
|
|
38
|
+
assert.deepEqual(results.keys, new BigUint64Array([15n, 16n]), 'keys should be 15 and 16');
|
|
39
|
+
assert.deepEqual(results.distances, new Float32Array([45, 130]), 'distances should be 45 and 130');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await t.test('remove', () => {
|
|
43
|
+
const index = new usearch.Index(2, 'l2sq');
|
|
44
|
+
|
|
45
|
+
index.add(15n, new Float32Array([10, 20]));
|
|
46
|
+
index.add(16n, new Float32Array([10, 25]));
|
|
47
|
+
index.add(25n, new Float32Array([20, 40]));
|
|
48
|
+
index.add(26n, new Float32Array([20, 45]));
|
|
21
49
|
|
|
22
|
-
|
|
23
|
-
index.add(16n, new Float32Array([10, 25]));
|
|
50
|
+
assert.equal(index.remove(15n), 1);
|
|
24
51
|
|
|
25
|
-
|
|
26
|
-
|
|
52
|
+
assert.equal(index.size(), 3, 'size after remoing elements should be 3');
|
|
53
|
+
assert.equal(index.contains(15), false, 'entry must be absent after insertion');
|
|
27
54
|
|
|
28
|
-
|
|
55
|
+
const results = index.search(new Float32Array([13, 14]), 2);
|
|
29
56
|
|
|
30
|
-
|
|
31
|
-
|
|
57
|
+
assert.deepEqual(results.keys, new BigUint64Array([16n, 25n]), 'keys should not include 15');
|
|
58
|
+
});
|
|
32
59
|
});
|
|
33
60
|
|
|
34
|
-
test('Batch operations', () => {
|
|
35
|
-
|
|
61
|
+
test('Batch operations', async (t) => {
|
|
62
|
+
await t.test('add', () => {
|
|
63
|
+
const indexBatch = new usearch.Index(2, 'l2sq');
|
|
36
64
|
|
|
37
|
-
|
|
38
|
-
|
|
65
|
+
const keys = [15n, 16n];
|
|
66
|
+
const vectors = [new Float32Array([10, 20]), new Float32Array([10, 25])];
|
|
39
67
|
|
|
40
|
-
|
|
41
|
-
|
|
68
|
+
indexBatch.add(keys, vectors);
|
|
69
|
+
assert.equal(indexBatch.size(), 2, 'size after adding batch should be 2');
|
|
42
70
|
|
|
43
|
-
|
|
71
|
+
const results = indexBatch.search(new Float32Array([13, 14]), 2);
|
|
44
72
|
|
|
45
|
-
|
|
46
|
-
|
|
73
|
+
assert.deepEqual(results.keys, new BigUint64Array([15n, 16n]), 'keys should be 15 and 16');
|
|
74
|
+
assert.deepEqual(results.distances, new Float32Array([45, 130]), 'distances should be 45 and 130');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await t.test('remove', () => {
|
|
78
|
+
const indexBatch = new usearch.Index(2, 'l2sq');
|
|
79
|
+
|
|
80
|
+
const keys = [15n, 16n, 25n, 26n];
|
|
81
|
+
const vectors = [
|
|
82
|
+
new Float32Array([10, 20]),
|
|
83
|
+
new Float32Array([10, 25]),
|
|
84
|
+
new Float32Array([20, 40]),
|
|
85
|
+
new Float32Array([20, 45])
|
|
86
|
+
];
|
|
87
|
+
indexBatch.add(keys, vectors);
|
|
88
|
+
|
|
89
|
+
assert.deepEqual(indexBatch.remove([15n, 25n]), [1, 1])
|
|
90
|
+
assert.equal(indexBatch.size(), 2, 'size after removing batch should be 2');
|
|
91
|
+
|
|
92
|
+
const results = indexBatch.search(new Float32Array([13, 14]), 2);
|
|
93
|
+
|
|
94
|
+
assert.deepEqual(results.keys, new BigUint64Array([16n, 26n]), 'keys should not include 15 and 25');
|
|
95
|
+
});
|
|
47
96
|
});
|
|
48
97
|
|
|
49
98
|
test("Expected results", () => {
|
|
@@ -60,7 +109,27 @@ test("Expected results", () => {
|
|
|
60
109
|
assertAlmostEqual(results.distances[0], new Float32Array([0]));
|
|
61
110
|
});
|
|
62
111
|
|
|
112
|
+
test('Expected count()', async (t) => {
|
|
113
|
+
const index = new usearch.Index({
|
|
114
|
+
metric: 'l2sq',
|
|
115
|
+
connectivity: 16,
|
|
116
|
+
dimensions: 3,
|
|
117
|
+
});
|
|
118
|
+
index.add(
|
|
119
|
+
[42n, 43n],
|
|
120
|
+
[new Float32Array([0.2, 0.6, 0.4]), new Float32Array([0.2, 0.6, 0.4])]
|
|
121
|
+
);
|
|
63
122
|
|
|
123
|
+
await t.test('Argument is a number', () => {
|
|
124
|
+
assert.equal(1, index.count(43n));
|
|
125
|
+
});
|
|
126
|
+
await t.test('Argument is a number (does not exist)', () => {
|
|
127
|
+
assert.equal(0, index.count(44n));
|
|
128
|
+
});
|
|
129
|
+
await t.test('Argument is an array', () => {
|
|
130
|
+
assert.deepEqual([1, 1, 0], index.count([42n, 43n, 44n]));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
64
133
|
|
|
65
134
|
test('Operations with invalid values', () => {
|
|
66
135
|
const indexBatch = new usearch.Index(2, 'l2sq');
|
|
@@ -84,3 +153,103 @@ test('Operations with invalid values', () => {
|
|
|
84
153
|
}
|
|
85
154
|
);
|
|
86
155
|
});
|
|
156
|
+
|
|
157
|
+
test('Invalid operations', async (t) => {
|
|
158
|
+
await t.test('Add the same keys', () => {
|
|
159
|
+
const index = new usearch.Index({
|
|
160
|
+
metric: "l2sq",
|
|
161
|
+
connectivity: 16,
|
|
162
|
+
dimensions: 3,
|
|
163
|
+
});
|
|
164
|
+
index.add(42n, new Float32Array([0.2, 0.6, 0.4]));
|
|
165
|
+
assert.throws(
|
|
166
|
+
() => index.add(42n, new Float32Array([0.2, 0.6, 0.4])),
|
|
167
|
+
{
|
|
168
|
+
name: 'Error',
|
|
169
|
+
message: 'Duplicate keys not allowed in high-level wrappers'
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
test('Serialization', async (t) => {
|
|
177
|
+
const indexPath = path.join(os.tmpdir(), 'usearch.test.index')
|
|
178
|
+
|
|
179
|
+
t.beforeEach(() => {
|
|
180
|
+
const index = new usearch.Index({
|
|
181
|
+
metric: "l2sq",
|
|
182
|
+
connectivity: 16,
|
|
183
|
+
dimensions: 3,
|
|
184
|
+
});
|
|
185
|
+
index.add(42n, new Float32Array([0.2, 0.6, 0.4]));
|
|
186
|
+
index.save(indexPath);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
t.afterEach(() => {
|
|
190
|
+
fs.unlinkSync(indexPath);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
await t.test('load', () => {
|
|
194
|
+
const index = new usearch.Index({
|
|
195
|
+
metric: "l2sq",
|
|
196
|
+
connectivity: 16,
|
|
197
|
+
dimensions: 3,
|
|
198
|
+
});
|
|
199
|
+
index.load(indexPath);
|
|
200
|
+
const results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
|
|
201
|
+
|
|
202
|
+
assert.equal(index.size(), 1);
|
|
203
|
+
assert.deepEqual(results.keys, new BigUint64Array([42n]));
|
|
204
|
+
assertAlmostEqual(results.distances[0], new Float32Array([0]));
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// todo: Skip as the test fails only on windows.
|
|
208
|
+
// The following error in afterEach().
|
|
209
|
+
// `error: "EBUSY: resource busy or locked, unlink`
|
|
210
|
+
await t.test('view: Read data', {skip: process.platform === 'win32'}, () => {
|
|
211
|
+
const index = new usearch.Index({
|
|
212
|
+
metric: "l2sq",
|
|
213
|
+
connectivity: 16,
|
|
214
|
+
dimensions: 3,
|
|
215
|
+
});
|
|
216
|
+
index.view(indexPath);
|
|
217
|
+
const results = index.search(new Float32Array([0.2, 0.6, 0.4]), 10);
|
|
218
|
+
|
|
219
|
+
assert.equal(index.size(), 1);
|
|
220
|
+
assert.deepEqual(results.keys, new BigUint64Array([42n]));
|
|
221
|
+
assertAlmostEqual(results.distances[0], new Float32Array([0]));
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
await t.test('view: Invalid operations: add', {skip: process.platform === 'win32'}, () => {
|
|
225
|
+
const index = new usearch.Index({
|
|
226
|
+
metric: "l2sq",
|
|
227
|
+
connectivity: 16,
|
|
228
|
+
dimensions: 3,
|
|
229
|
+
});
|
|
230
|
+
index.view(indexPath);
|
|
231
|
+
assert.throws(
|
|
232
|
+
() => index.add(43n, new Float32Array([0.2, 0.6, 0.4])),
|
|
233
|
+
{
|
|
234
|
+
name: 'Error',
|
|
235
|
+
message: "Can't add to an immutable index"
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
await t.test('view: Invalid operations: remove', {skip: process.platform === 'win32'}, () => {
|
|
241
|
+
const index = new usearch.Index({
|
|
242
|
+
metric: "l2sq",
|
|
243
|
+
connectivity: 16,
|
|
244
|
+
dimensions: 3,
|
|
245
|
+
});
|
|
246
|
+
index.view(indexPath);
|
|
247
|
+
assert.throws(
|
|
248
|
+
() => index.remove(42n),
|
|
249
|
+
{
|
|
250
|
+
name: 'Error',
|
|
251
|
+
message: "Can't remove from an immutable index"
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
});
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/simsimd/CONTRIBUTING.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Contributing
|
|
2
2
|
|
|
3
|
+
To keep the quality of the code high, we have a set of [guidelines](https://github.com/unum-cloud).
|
|
4
|
+
|
|
5
|
+
- [What's the procedure?](https://github.com/unum-cloud/awesome/blob/main/Workflow.md#organizing-software-development)
|
|
6
|
+
- [How to organize branches?](https://github.com/unum-cloud/awesome/blob/main/Workflow.md#branches)
|
|
7
|
+
- [How to style commits?](https://github.com/unum-cloud/awesome/blob/main/Workflow.md#commits)
|
|
8
|
+
|
|
3
9
|
## C and C++
|
|
4
10
|
|
|
5
11
|
To rerun experiments utilize the following command:
|
|
@@ -23,15 +29,37 @@ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100
|
|
|
23
29
|
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100
|
|
24
30
|
```
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
Replacing the default compiler is not recommended, as it may break the system, but you can pass it as an environment variable:
|
|
32
|
+
To compile with the default Apple Clang on MacOS, use:
|
|
28
33
|
|
|
29
34
|
```sh
|
|
30
|
-
brew install
|
|
31
|
-
cmake -D CMAKE_BUILD_TYPE=Release
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
brew install openblas
|
|
36
|
+
cmake -D CMAKE_BUILD_TYPE=Release \
|
|
37
|
+
-D SIMSIMD_BUILD_TESTS=1 \
|
|
38
|
+
-D SIMSIMD_BUILD_BENCHMARKS=1 \
|
|
39
|
+
-D SIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS=1 \
|
|
40
|
+
-D CMAKE_PREFIX_PATH="$(brew --prefix openblas)" \
|
|
41
|
+
-D CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES="$(brew --prefix openblas)/include" \
|
|
42
|
+
-B build_release
|
|
43
|
+
cmake --build build_release --config Release
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
On MacOS it's recommended to use Homebrew and install Clang, as opposed to "Apple Clang".
|
|
47
|
+
Replacing the default compiler across the entire system is not recommended on MacOS, as it may break the system, but you can pass it as an environment variable:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
brew install llvm openblas
|
|
51
|
+
cmake -D CMAKE_BUILD_TYPE=Release \
|
|
52
|
+
-D SIMSIMD_BUILD_TESTS=1 \
|
|
53
|
+
-D SIMSIMD_BUILD_BENCHMARKS=1 \
|
|
54
|
+
-D SIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS=1 \
|
|
55
|
+
-D CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES="$(brew --prefix openblas)/include" \
|
|
56
|
+
-D CMAKE_C_LINK_FLAGS="-L$(xcrun --sdk macosx --show-sdk-path)/usr/lib" \
|
|
57
|
+
-D CMAKE_EXE_LINKER_FLAGS="-L$(xcrun --sdk macosx --show-sdk-path)/usr/lib" \
|
|
58
|
+
-D CMAKE_C_COMPILER="$(brew --prefix llvm)/bin/clang" \
|
|
59
|
+
-D CMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++" \
|
|
60
|
+
-D CMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" \
|
|
61
|
+
-D CMAKE_OSX_DEPLOYMENT_TARGET=$(sw_vers -productVersion) \
|
|
62
|
+
-B build_release
|
|
35
63
|
cmake --build build_release --config Release
|
|
36
64
|
```
|
|
37
65
|
|
|
@@ -42,7 +70,7 @@ Testing:
|
|
|
42
70
|
```sh
|
|
43
71
|
pip install -e . # to install the package in editable mode
|
|
44
72
|
pip install pytest pytest-repeat tabulate # testing dependencies
|
|
45
|
-
pytest
|
|
73
|
+
pytest scripts/test.py -s -x -Wd # to run tests
|
|
46
74
|
|
|
47
75
|
# to check supported SIMD instructions:
|
|
48
76
|
python -c "import simsimd; print(simsimd.get_capabilities())"
|
|
@@ -62,28 +90,42 @@ CC=$(brew --prefix llvm)/bin/clang CXX=$(brew --prefix llvm)/bin/clang++ pip ins
|
|
|
62
90
|
Benchmarking:
|
|
63
91
|
|
|
64
92
|
```sh
|
|
65
|
-
pip install numpy scipy scikit-learn
|
|
66
|
-
python
|
|
67
|
-
python
|
|
93
|
+
pip install numpy scipy scikit-learn # for comparison baselines
|
|
94
|
+
python scripts/bench_vectors.py # to run default benchmarks
|
|
95
|
+
python scripts/bench_vectors.py --n 1000 --ndim 1536 # batch size and dimensions
|
|
68
96
|
```
|
|
69
97
|
|
|
70
|
-
You can also benchmark against other libraries:
|
|
98
|
+
You can also benchmark against other libraries, filter the numeric types, and distance metrics:
|
|
71
99
|
|
|
72
100
|
```sh
|
|
73
|
-
$ python
|
|
74
|
-
> usage: bench.py [-h] [--
|
|
101
|
+
$ python scripts/bench_vectors.py --help
|
|
102
|
+
> usage: bench.py [-h] [--ndim NDIM] [-n COUNT]
|
|
103
|
+
> [--metric {all,dot,spatial,binary,probability,sparse}]
|
|
104
|
+
> [--dtype {all,bits,int8,uint16,uint32,float16,float32,float64,bfloat16,complex32,complex64,complex128}]
|
|
105
|
+
> [--scipy] [--scikit] [--torch] [--tf] [--jax]
|
|
75
106
|
>
|
|
76
107
|
> Benchmark SimSIMD vs. other libraries
|
|
77
108
|
>
|
|
78
|
-
>
|
|
79
|
-
> -h, --help
|
|
80
|
-
> --
|
|
81
|
-
>
|
|
82
|
-
>
|
|
83
|
-
> --
|
|
84
|
-
>
|
|
85
|
-
>
|
|
86
|
-
>
|
|
109
|
+
> optional arguments:
|
|
110
|
+
> -h, --help show this help message and exit
|
|
111
|
+
> --ndim NDIM Number of dimensions in vectors (default: 1536) For binary vectors (e.g., Hamming, Jaccard), this is the number of bits. In
|
|
112
|
+
> case of SimSIMD, the inputs will be treated at the bit-level. Other packages will be matching/comparing 8-bit integers. The
|
|
113
|
+
> volume of exchanged data will be identical, but the results will differ.
|
|
114
|
+
> -n COUNT, --count COUNT
|
|
115
|
+
> Number of vectors per batch (default: 1) By default, when set to 1 the benchmark will generate many vectors of size (ndim, )
|
|
116
|
+
> and call the functions on pairs of single vectors: both directly, and through `cdist`. Alternatively, for larger batch sizes
|
|
117
|
+
> the benchmark will generate two matrices of size (n, ndim) and compute: - batch mode: (n) distances between vectors in
|
|
118
|
+
> identical rows of the two matrices, - all-pairs mode: (n^2) distances between all pairs of vectors in the two matrices via
|
|
119
|
+
> `cdist`.
|
|
120
|
+
> --metric {all,dot,spatial,binary,probability,sparse}
|
|
121
|
+
> Distance metric to use, profiles everything by default
|
|
122
|
+
> --dtype {all,bits,int8,uint16,uint32,float16,float32,float64,bfloat16,complex32,complex64,complex128}
|
|
123
|
+
> Defines numeric types to benchmark, profiles everything by default
|
|
124
|
+
> --scipy Profile SciPy, must be installed
|
|
125
|
+
> --scikit Profile scikit-learn, must be installed
|
|
126
|
+
> --torch Profile PyTorch, must be installed
|
|
127
|
+
> --tf Profile TensorFlow, must be installed
|
|
128
|
+
> --jax Profile JAX, must be installed
|
|
87
129
|
```
|
|
88
130
|
|
|
89
131
|
|
|
@@ -155,6 +197,12 @@ npm install -g bun
|
|
|
155
197
|
bun test
|
|
156
198
|
```
|
|
157
199
|
|
|
200
|
+
## Swift
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
swift build && swift test -v
|
|
204
|
+
```
|
|
205
|
+
|
|
158
206
|
## GoLang
|
|
159
207
|
|
|
160
208
|
```sh
|
package/simsimd/Cargo.lock
CHANGED
package/simsimd/Cargo.toml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "simsimd"
|
|
3
|
-
description = "
|
|
4
|
-
version = "5.6
|
|
3
|
+
description = "Portable mixed-precision BLAS-like vector math library for x86 and ARM"
|
|
4
|
+
version = "5.9.6"
|
|
5
5
|
edition = "2021"
|
|
6
6
|
license = "Apache-2.0"
|
|
7
7
|
authors = ["Ash Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
|
|
@@ -30,12 +30,12 @@ cc = "1.0.83"
|
|
|
30
30
|
[[bench]]
|
|
31
31
|
name = "cosine"
|
|
32
32
|
harness = false
|
|
33
|
-
path = "
|
|
33
|
+
path = "scripts/bench_cosine.rs"
|
|
34
34
|
|
|
35
35
|
[[bench]]
|
|
36
36
|
name = "sqeuclidean"
|
|
37
37
|
harness = false
|
|
38
|
-
path = "
|
|
38
|
+
path = "scripts/bench_sqeuclidean.rs"
|
|
39
39
|
|
|
40
40
|
[profile.bench]
|
|
41
41
|
opt-level = 3 # Corresponds to -O3
|
package/simsimd/MANIFEST.in
CHANGED
package/simsimd/Package.swift
CHANGED
|
@@ -9,8 +9,20 @@ let package = Package(
|
|
|
9
9
|
.library(name: "SimSIMD", targets: ["SimSIMD"]),
|
|
10
10
|
],
|
|
11
11
|
targets: [
|
|
12
|
-
.testTarget(name: "
|
|
13
|
-
.target(name: "SimSIMD", dependencies: ["CSimSIMD"], path: "swift
|
|
14
|
-
.
|
|
12
|
+
.testTarget(name: "Test", dependencies: ["SimSIMD"], path: "swift", exclude:["SimSIMD.swift"]),
|
|
13
|
+
.target(name: "SimSIMD", dependencies: ["CSimSIMD"], path: "swift", exclude:["Test.swift"]),
|
|
14
|
+
.target(
|
|
15
|
+
name: "CSimSIMD",
|
|
16
|
+
path: "include/simsimd/", // Adjust the path to include your C source files
|
|
17
|
+
sources: ["../../c/lib.c"], // Include the source file here
|
|
18
|
+
publicHeadersPath: ".",
|
|
19
|
+
cSettings: [
|
|
20
|
+
.define("SIMSIMD_DYNAMIC_DISPATCH", to: "1"), // Define a C macro
|
|
21
|
+
.define("SIMSIMD_NATIVE_F16", to: "0"), // Define a C macro
|
|
22
|
+
.define("SIMSIMD_NATIVE_BF16", to: "0"), // Define a C macro
|
|
23
|
+
.headerSearchPath("include/"), // Specify header search paths
|
|
24
|
+
.unsafeFlags(["-Wall"]) // Use with caution: specify custom compiler flags
|
|
25
|
+
]
|
|
26
|
+
),
|
|
15
27
|
]
|
|
16
28
|
)
|