usearch 0.2.0 → 0.2.3

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.
@@ -130,6 +130,17 @@ jobs:
130
130
  env:
131
131
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
132
132
 
133
+ publish_swift:
134
+ name: Publish ObjC & Swift
135
+ runs-on: macos-latest
136
+ steps:
137
+ - uses: actions/checkout@v3
138
+ - run: git submodule update --init --recursive
139
+ - name: Build
140
+ run: swift build
141
+ - name: Run tests
142
+ run: swift test
143
+
133
144
  deploy_docs:
134
145
  name: Deploy Docs
135
146
  environment:
@@ -36,18 +36,19 @@
36
36
  }
37
37
  },
38
38
  {
39
- "name": "Debug C++ Bench on Text-to-Image 1M @Cos",
39
+ "name": "Debug C++ Bench on Text-to-Image 1B @Cos",
40
40
  "type": "cppdbg",
41
41
  "request": "launch",
42
42
  "program": "${workspaceFolder}/build_debug/bench",
43
43
  "cwd": "${workspaceFolder}",
44
44
  "args": [
45
45
  "--vectors",
46
- "datasets/t2i_1M/base.1M.fbin",
46
+ "datasets/t2i_1B/base.1B.fbin",
47
47
  "--queries",
48
- "datasets/t2i_1M/query.public.100K.fbin",
48
+ "datasets/t2i_1B/query.public.100K.fbin",
49
49
  "--neighbors",
50
- "datasets/t2i_1M/groundtruth.public.100K.ibin",
50
+ "datasets/t2i_1B/groundtruth.public.100K.ibin",
51
+ "--cos"
51
52
  ],
52
53
  "environment": [
53
54
  {
@@ -97,7 +97,8 @@
97
97
  "__memory": "cpp",
98
98
  "filesystem": "cpp",
99
99
  "__availability": "cpp",
100
- "version": "cpp"
100
+ "version": "cpp",
101
+ "future": "cpp"
101
102
  },
102
103
  "cSpell.words": [
103
104
  "astype",
package/CMakeLists.txt CHANGED
@@ -17,22 +17,18 @@ if(NOT CMAKE_BUILD_TYPE)
17
17
  set(CMAKE_BUILD_TYPE Release)
18
18
  endif()
19
19
 
20
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
21
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
22
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -pg -g")
23
-
24
20
  # List of all possible compiler IDs:
25
21
  # https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
26
22
  if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
27
23
  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address")
28
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-conversion -Wno-unknown-pragmas")
24
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wno-conversion -Wno-unknown-pragmas")
29
25
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
30
26
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmax-errors=1")
31
27
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
32
28
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
33
29
 
34
30
  elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
35
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wfatal-errors")
31
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wfatal-errors")
36
32
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
37
33
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
38
34
 
@@ -46,6 +42,15 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "NVIDIA" OR CMAKE_CXX_COMPILER_ID STREQUAL
46
42
  elseif(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
47
43
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w")
48
44
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ferror-limit=1")
45
+
46
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
47
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DEBUG")
48
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2")
49
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /O2 /DEBUG")
50
+ else()
51
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
52
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
53
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -pg -g")
49
54
  endif()
50
55
 
51
56
  if(APPLE)
@@ -12,6 +12,7 @@ git submodule update --init --recursive
12
12
 
13
13
  ```sh
14
14
  cmake -B ./build_release \
15
+ -DCMAKE_CXX_COMPILER="g++-12" \
15
16
  -DCMAKE_BUILD_TYPE=Release \
16
17
  -DUSEARCH_USE_SIMD=1 \
17
18
  -DUSEARCH_USE_OPENMP=1 \
@@ -24,6 +25,14 @@ cmake -B ./build_release \
24
25
  --queries datasets/wiki_1M/query.public.100K.fbin \
25
26
  --neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
26
27
 
28
+ # Large benchmark on a 1TB dataset:
29
+ ./build_release/bench \
30
+ --vectors datasets/t2i_1B/base.1B.fbin \
31
+ --queries datasets/t2i_1B/query.public.100K.fbin \
32
+ --neighbors datasets/t2i_1B/groundtruth.public.100K.ibin \
33
+ --output datasets/t2i_1B/index.usearch \
34
+ --cos
35
+
27
36
  # To benchmark in Python:
28
37
  python python/bench.py \
29
38
  --vectors datasets/wiki_1M/base.1M.fbin \
@@ -110,44 +119,57 @@ brew install --cask wolfram-engine
110
119
  BigANN benchmark is a good starting point, if you are searching for large collections of high-dimensional vectors.
111
120
  Those often come with precomputed ground-truth neighbors, which is handy for recall evaluation.
112
121
 
113
- | Dataset | Scalar Type | Dimensions | Metric | Size |
114
- | :------------------------------ | :---------: | :--------: | :----: | :----: |
115
- | [Microsoft SPACEV][spacev] | int8 | 100 | L2 | 93 GB |
116
- | [Microsoft Turing-ANNS][turing] | float32 | 100 | L2 | 373 GB |
117
- | [Yandex Deep1B][deep] | float32 | 96 | L2 | 358 GB |
118
- | [Yandex Text-to-Image][t2i] | float32 | 200 | Cos | 750 GB |
122
+ | Dataset | Scalar Type | Dimensions | Metric | Size |
123
+ | :-------------------------------------- | :---------: | :--------: | :----: | :-------: |
124
+ | [Unum UForm Wiki][unum-wiki] | float32 | 256 | IP | 1 GB |
125
+ | [Yandex Text-to-Image Sample][unum-t2i] | float32 | 200 | Cos | 1 GB |
126
+ | | | | | |
127
+ | [Microsoft SPACEV][spacev] | int8 | 100 | L2 | 93 GB |
128
+ | [Microsoft Turing-ANNS][turing] | float32 | 100 | L2 | 373 GB |
129
+ | [Yandex Deep1B][deep] | float32 | 96 | L2 | 358 GB |
130
+ | [Yandex Text-to-Image][t2i] | float32 | 200 | Cos | 750 GB |
131
+ | | | | | |
132
+ | [ViT-L/12 LAION][laion] | float32 | 2048 | Cos | 2 - 10 TB |
119
133
 
120
134
  Luckily, smaller samples of those datasets are available.
121
135
 
136
+ [unum-wiki]: https://huggingface.co/datasets/unum-cloud/ann-wiki-1m
137
+ [unum-t2i]: https://huggingface.co/datasets/unum-cloud/ann-t2i-1m
122
138
  [spacev]: https://github.com/microsoft/SPTAG/tree/main/datasets/SPACEV1B
123
139
  [turing]: https://learning2hash.github.io/publications/microsoftturinganns1B/
124
140
  [t2i]: https://research.yandex.com/blog/benchmarks-for-billion-scale-similarity-search
125
141
  [deep]: https://research.yandex.com/blog/benchmarks-for-billion-scale-similarity-search
142
+ [laion]: https://laion.ai/blog/laion-5b/#download-the-data
126
143
 
127
- ### Yandex Deep1B
128
-
129
- There is a 10M subset available.
144
+ ### Unum UForm Wiki
130
145
 
131
146
  ```sh
132
- mkdir -p datasets/deep/ && \
133
- wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/base.1B.fbin -P datasets/deep_1B/ &&
134
- wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/base.10M.fbin -P datasets/deep_1B/ &&
135
- wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/query.public.10K.fbin -P datasets/deep_1B/ &&
136
- wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/groundtruth.public.10K.ibin -P datasets/deep_1B/
147
+ mkdir -p datasets/wiki_1M/ && \
148
+ wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/base.1M.fbin -P datasets/wiki_1M/ &&
149
+ wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/query.public.100K.fbin -P datasets/wiki_1M/ &&
150
+ wget -nc https://huggingface.co/datasets/unum-cloud/ann-wiki-1m/resolve/main/groundtruth.public.100K.ibin -P datasets/wiki_1M/
137
151
  ```
138
152
 
139
153
  ### Yandex Text-to-Image
140
154
 
141
- There is a 1M subset available.
142
-
143
155
  ```sh
144
- mkdir -p datasets/t2i/ && \
156
+ mkdir -p datasets/t2i_1B/ && \
145
157
  wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/base.1B.fbin -P datasets/t2i_1B/ &&
146
158
  wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/base.1M.fbin -P datasets/t2i_1B/ &&
147
159
  wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/query.public.100K.fbin -P datasets/t2i_1B/ &&
148
160
  wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/T2I/groundtruth.public.100K.ibin -P datasets/t2i_1B/
149
161
  ```
150
162
 
163
+ ### Yandex Deep1B
164
+
165
+ ```sh
166
+ mkdir -p datasets/deep_1B/ && \
167
+ wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/base.1B.fbin -P datasets/deep_1B/ &&
168
+ wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/base.10M.fbin -P datasets/deep_1B/ &&
169
+ wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/query.public.10K.fbin -P datasets/deep_1B/ &&
170
+ wget -nc https://storage.yandexcloud.net/yandex-research/ann-datasets/DEEP/groundtruth.public.10K.ibin -P datasets/deep_1B/
171
+ ```
172
+
151
173
  ### Profiling
152
174
 
153
175
  With `perf`:
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "usearch"
3
- version = "0.2.0"
3
+ version = "0.2.3"
4
4
  authors = ["Ashot Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
5
5
  description = "Smaller & Faster Single-File Vector Search Engine from Unum"
6
6
  edition = "2021"
package/Package.swift ADDED
@@ -0,0 +1,40 @@
1
+ // swift-tools-version:5.3
2
+
3
+ import PackageDescription
4
+
5
+ let package = Package(
6
+ name: "USearch",
7
+ products: [
8
+ .library(
9
+ name: "USearch",
10
+ targets: ["USearchObjective", "USearch"]
11
+ )
12
+ ],
13
+ dependencies: [],
14
+ targets: [
15
+ .target(
16
+ name: "USearchObjective",
17
+ path: "objc",
18
+ sources: ["USearchObjective.mm"],
19
+ cxxSettings: [
20
+ .headerSearchPath("../include/"),
21
+ .headerSearchPath("../src/"),
22
+ .headerSearchPath("../fp16/include/"),
23
+ .headerSearchPath("../simismd/include/")
24
+ ]
25
+ ),
26
+ .target(
27
+ name: "USearch",
28
+ dependencies: ["USearchObjective"],
29
+ path: "swift",
30
+ sources: ["USearch.swift", "Index+Sugar.swift"]
31
+ ),
32
+ .testTarget(
33
+ name: "USearchTests",
34
+ dependencies: ["USearch"],
35
+ path: "swift",
36
+ sources: ["Test.swift"]
37
+ )
38
+ ],
39
+ cxxLanguageStandard: CXXLanguageStandard.cxx11
40
+ )
package/README.md CHANGED
@@ -17,30 +17,33 @@ Vector Search Engine<br/>
17
17
  <a href="https://github.com/unum-cloud/usearch"><img height="25" src="https://github.com/unum-cloud/.github/raw/main/assets/github.svg" alt="GitHub"></a>
18
18
  </p>
19
19
 
20
+ <p align="center">
21
+ Euclidean • Angular • Jaccard • Hamming • Haversine • User-Defined Metrics
22
+ <br/>
23
+ <a href="#c++">C++11</a> •
24
+ <a href="#python">Python</a> •
25
+ <a href="#javascript">JavaScript</a> •
26
+ <a href="#java">Java</a> •
27
+ <a href="#rust">Rust</a> •
28
+ <a href="#objective-c">Objective-C</a> •
29
+ <a href="#swift">Swift</a> •
30
+ <a href="#golang">GoLang</a> •
31
+ <a href="#wolfram">Wolfram</a>
32
+ <br/>
33
+ Linux • MacOS • Windows
34
+ </p>
35
+
20
36
  - [x] [Single C++11 header][usearch-header] implementation, easily extendible.
21
37
  - [x] [4B+](#go-beyond-4b-entries) sized space efficient point-clouds with `uint40_t`.
22
- - [x] [Half-precision](#quantize-on-the-fly) support with [`maratyszcza/fp16`](https://github.com/maratyszcza/fp16).
38
+ - [x] [Half-precision](#quantize-on-the-fly) support with [`fp16`](https://github.com/maratyszcza/fp16).
23
39
  - [x] [View from disk](#view-larger-indexes-from-disk), without loading into RAM.
24
- - [x] [Any metric](#define-custom-metrics), includes:
25
- - [x] Euclidean, Dot-product, Cosine,
26
- - [x] Jaccard, Hamming, Haversine.
27
- - [x] Hardware-accelerated [`ashvardanian/simsimd`](https://github.com/ashvardanian/simsimd).
40
+ - [x] [User-defined](#define-custom-metrics) and hardware-accelerated metrics with [`simsimd`](https://github.com/ashvardanian/simsimd).
28
41
  - [x] Variable dimensionality vectors.
29
42
  - [x] Don't copy vectors if not needed.
30
43
  - [x] [Bring your threads](#bring-your-threads), like OpenMP.
31
44
  - [x] Multiple vectors per label.
32
- - [x] [Python](#python) bindings: `pip install usearch`.
33
- - [x] [JavaScript](#java) bindings: `npm install usearch`.
34
- - [x] [Rust](#rust) bindings: `cargo add usearch`.
35
- - [x] [Java](#java) bindings: `cloud.unum:usearch` on GitHub.
36
- - [ ] GoLang bindings.
37
- - [x] Wolfram language bindings.
38
- - [x] For Linux: GCC, Clang.
39
- - [x] For MacOS: Apple Clang.
40
- - [ ] For Windows.
41
- - [ ] Multi-index lookups in Python.
42
45
  - [ ] Thread-safe `reserve`.
43
- - [ ] Distributed construction with MPI.
46
+ - [x] Compatible with Linux, MacOS, and Windows.
44
47
  - [x] AI + Vector Search = Semantic Search.
45
48
 
46
49
  [usearch-header]: https://github.com/unum-cloud/usearch/blob/main/include/usearch/usearch.hpp
@@ -108,7 +111,7 @@ So, if you are working on large datasets, but don't need the in-RAM throughput,
108
111
  ### Quantize on the Fly
109
112
 
110
113
  Most modern CPU have at least partial support for `half`-precision `f16_t` arithmetic.
111
- USearch supports automatic down-casting and up-casting between `f32_t`, `f16_t`, `f64_t`, and `i8q100_t` representations.
114
+ USearch supports automatic down-casting and up-casting between `f32_t`, `f16_t`, `f64_t`, and `f8_t` representations.
112
115
 
113
116
  > Making vectors smaller will help pack more of them in-memory, while also increasing performance on CPUs implementing native support for target type.
114
117
 
@@ -160,7 +163,7 @@ That can be one of the following templates:
160
163
 
161
164
  - `cos_gt<float>` for "Cosine" or "Angular" distance.
162
165
  - `ip_gt<float>` for "Inner Product" or "Dot Product" distance.
163
- - `l2_squared_gt<float>` for the squared "L2" or "Euclidean" distance.
166
+ - `l2sq_gt<float>` for the squared "L2" or "Euclidean" distance.
164
167
  - `jaccard_gt<int>` for "Jaccard" distance between two ordered sets of unique elements.
165
168
  - `bit_hamming_gt<uint>` for "Hamming" distance, as the number of shared bits in hashes.
166
169
  - `pearson_correlation_gt<float>` for "Pearson" correlation between probability distributions.
@@ -209,19 +212,21 @@ struct custom_metric_t {
209
212
 
210
213
  ### Python
211
214
 
215
+ ```sh
216
+ pip install usearch
217
+ ```
218
+
212
219
  Python bindings are implemented with [`pybind/pybind11`](https://github.com/pybind/pybind11).
213
220
  Assuming the presence of Global Interpreter Lock in Python, on large insertions we spawn threads in the C++ layer.
214
221
 
215
222
  ```python
216
- $ pip install usearch
217
-
218
223
  import numpy as np
219
- import usearch
224
+ from usearch.index import Index
220
225
 
221
- index = usearch.Index(
226
+ index = Index(
222
227
  ndim=256, # Define the number of dimensions in input vectors
223
228
  metric='cos', # Choose the "metric" or "distance", default = 'ip', optional
224
- dtype='f32', # Quantize to 'f16' or 'i8q100' if needed, default = 'f32', optional
229
+ dtype='f32', # Quantize to 'f16' or 'f8' if needed, default = 'f32', optional
225
230
  connectivity=16, # How frequent should the connections in the graph be, optional
226
231
  expansion_add=128, # Control the recall of indexing, optional
227
232
  expansion_search=64, # Control the quality of search, optional
@@ -232,6 +237,8 @@ index.add(42, vector)
232
237
  matches, distances, count = index.search(vector, 10)
233
238
  ```
234
239
 
240
+ #### Batch Operations
241
+
235
242
  Same can be done with batches, rather than single entries.
236
243
  Under the hood, worker threads will be spawned, to parallelize the procedure.
237
244
 
@@ -240,17 +247,31 @@ n = 100
240
247
  labels = np.array(range(n), dtype=np.longlong)
241
248
  vectors = np.random.uniform(0, 0.3, (n, index.ndim)).astype(np.float32)
242
249
 
243
- # You can avoid copying the data
244
- # Handy when build 1B+ indexes of memory-mapped files
245
- index.add(labels, vectors, copy=True)
250
+ index.add(labels, vectors)
246
251
  matches, distances, counts = index.search(vectors, 10)
247
252
  ```
248
253
 
254
+ #### Performance
255
+
256
+ To maximize performance, you can:
257
+
258
+ - adjust the number of threads passed to `index.add(threads=)`.
259
+ - downcast to half-precision with `Index(accuracy=)`.
260
+ - JIT-compile your metrics for hardware and pass to `Index(matric_pointer=)`.
261
+
262
+ For a dataset with 1 Million 256-dimensional embeddings at single precision, the performance would be:
263
+
264
+ - FAISS: 77'563 vectors/s.
265
+ - USearch precompiled for old hardware: 53'198 vectors/s (-32%).
266
+ - USearch with Numba JIT for target hardware: 88'658 vectors/s (+14%).
267
+
249
268
  ### JavaScript
250
269
 
251
- ```js
252
- // npm install usearch
270
+ ```sh
271
+ npm install usearch
272
+ ```
253
273
 
274
+ ```js
254
275
  var index = new usearch.Index({ metric: 'cos', connectivity: 16, dimensions: 2 })
255
276
  assert.equal(index.connectivity(), 16)
256
277
  assert.equal(index.dimensions(), 2)
@@ -266,14 +287,16 @@ assert.deepEqual(results.distances, new Float32Array([45, 130]))
266
287
 
267
288
  ### Rust
268
289
 
290
+ ```sh
291
+ cargo add usearch
292
+ ```
293
+
269
294
  Being a systems-programming language, Rust has better control over memory management and concurrency, but lacks function overloading.
270
295
  Aside from the `add` and `search`, it also provides `add_in_thread` and `search_in_thread` which let users identify the calling thread to use underlying temporary memory more efficiently.
271
296
 
272
297
  ```rust
273
- // cargo add usearch
274
-
275
298
  let quant: &str = "f16";
276
- let index = new_ip(5, &quant, 0, 0, 0).unwrap();
299
+ let index = new_ip(5, &quant, 0, 0, 0).unwrap();
277
300
 
278
301
  assert!(index.reserve(10).is_ok());
279
302
  assert!(index.capacity() >= 10);
@@ -298,13 +321,23 @@ assert!(index.load("index.usearch").is_ok());
298
321
  assert!(index.view("index.usearch").is_ok());
299
322
 
300
323
  // There are more "metrics" available
301
- assert!(new_l2(5, &quant, 0, 0, 0).is_ok());
302
- assert!(new_cos(5, &quant, 0, 0, 0).is_ok());
324
+ assert!(new_l2(5, &quant, 0, 0, 0).is_ok());
325
+ assert!(new_cos(5, &quant, 0, 0, 0).is_ok());
303
326
  assert!(new_haversine(&quant, 0, 0, 0).is_ok());
304
327
  ```
305
328
 
306
329
  ### Java
307
330
 
331
+ ```xml
332
+ <dependency>
333
+ <groupId>cloud.unum.usearch</groupId>
334
+ <artifactId>usearch</artifactId>
335
+ <version>0.2.3</version>
336
+ </dependency>
337
+ ```
338
+
339
+ Add that snippet to your `pom.xml` and hit `mvn install`.
340
+
308
341
  ```java
309
342
  Index index = new Index.Config().metric("cos").dimensions(2).build();
310
343
  float vec[] = {10, 20};
@@ -312,6 +345,19 @@ index.add(42, vec);
312
345
  int[] labels = index.search(vec, 5);
313
346
  ```
314
347
 
348
+ ### Swift
349
+
350
+ ```swift
351
+ let index = Index.l2(dimensions: 4, connectivity: 8)
352
+ let vectorA: [Float32] = [0.3, 0.5, 1.2, 1.4]
353
+ let vectorB: [Float32] = [0.4, 0.2, 1.2, 1.1]
354
+ index.add(label: 42, vector: vectorA[...])
355
+ index.add(label: 43, vector: vectorB[...])
356
+
357
+ let results = index.search(vector: vectorA[...], count: 10)
358
+ assert(results.0[0] == 42)
359
+ ```
360
+
315
361
  ### GoLang
316
362
 
317
363
  ### Wolfram
@@ -400,14 +446,14 @@ One can take an encoder model, like the multi-modal UForm, and a web-programming
400
446
  ```python
401
447
  import ucall.rich_posix as ucall
402
448
  import uform
403
- import usearch
449
+ from usearch.index import Index
404
450
 
405
451
  import numpy as np
406
452
  from PIL import Image
407
453
 
408
454
  server = ucall.Server()
409
455
  model = uform.get_model('unum-cloud/uform-vl-multilingual')
410
- index = usearch.Index(ndim=256)
456
+ index = Index(ndim=256)
411
457
 
412
458
  @server
413
459
  def add(label: int, photo: Image.Image):
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.3
package/build.gradle CHANGED
@@ -56,11 +56,15 @@ model {
56
56
  if (targetPlatform.operatingSystem.linux) {
57
57
  cppCompiler.args '-I', "${Jvm.current().javaHome}/include/linux"
58
58
  cppCompiler.args '-D_FILE_OFFSET_BITS=64'
59
+ cppCompiler.args '-std=c++11'
59
60
  } else if (targetPlatform.operatingSystem.macOsX) {
60
61
  cppCompiler.args '-I', "${Jvm.current().javaHome}/include/darwin"
61
62
  cppCompiler.args '-D_FILE_OFFSET_BITS=64'
63
+ cppCompiler.args '-std=c++11'
64
+ } else if (targetPlatform.operatingSystem.windows){
65
+ cppCompiler.args "-I${Jvm.current().javaHome}/include/win32"
66
+ cppCompiler.args '/std:c++11'
62
67
  }
63
- cppCompiler.args '-std=c++11'
64
68
  }
65
69
  }
66
70
  }
@@ -76,5 +76,3 @@ else()
76
76
  JEMALLOC_INCLUDE_DIR
77
77
  )
78
78
  endif()
79
-
80
- message("JEMALLOC_LIBRARIES:" ${JEMALLOC_LIBRARIES})
package/conanfile.py ADDED
@@ -0,0 +1,19 @@
1
+ from conans import ConanFile
2
+
3
+
4
+ class USearchConan(ConanFile):
5
+
6
+ name = 'USearch'
7
+ version = '0.2.3'
8
+ license = 'Apache 2.0'
9
+ url = 'https://github.com/unum-cloud/usearch'
10
+ description = 'Smaller & Faster Single-File Vector Search Engine from Unum'
11
+
12
+ # No settings/options are necessary, this is header only
13
+ # Potentially add unit-tests in the future:
14
+ # https://docs.conan.io/1/howtos/header_only.html#with-unit-tests
15
+ exports_sources = 'include/*'
16
+ no_copy_source = True
17
+
18
+ def package(self):
19
+ self.copy('*.h')