usearch 0.18.8 → 0.19.1
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/Cargo.toml +1 -1
- package/README.md +187 -40
- package/c/lib.cpp +71 -51
- package/c/test.c +182 -0
- package/c/usearch.h +11 -5
- package/conanfile.py +1 -1
- package/cpp/bench.cpp +6 -6
- package/cpp/test.cpp +11 -9
- package/docs/compilation.md +1 -0
- package/include/usearch/index.hpp +290 -54
- package/include/usearch/index_punned_dense.hpp +125 -108
- package/include/usearch/index_punned_helpers.hpp +2 -12
- package/objc/USearchObjective.mm +4 -0
- package/objc/include/USearchObjective.h +5 -0
- package/package.json +2 -2
- package/python/lib.cpp +234 -199
- package/python/scripts/bench.ipynb +13 -2113
- package/python/scripts/bench.py +45 -29
- package/python/scripts/index_faiss.py +19 -19
- package/python/scripts/test.py +320 -61
- package/python/usearch/eval.py +100 -49
- package/python/usearch/index.py +245 -129
- package/python/usearch/io.py +25 -25
- package/python/usearch/join.py +2 -4
- package/python/usearch/numba.py +22 -18
- package/python/usearch/server.py +38 -26
- package/setup.py +56 -59
- package/simsimd/.vscode/settings.json +2 -1
- package/simsimd/CMakeLists.txt +1 -1
- package/simsimd/README.md +14 -2
- package/simsimd/bench.cxx +44 -27
- package/simsimd/include/simsimd/simsimd.h +2 -1
- package/swift/Test.swift +13 -9
- package/simsimd/include/simsimd/simsimd.hpp +0 -443
package/python/usearch/numba.py
CHANGED
|
@@ -3,34 +3,34 @@
|
|
|
3
3
|
# Python tooling, linters, and static analyzers. It also embeds JIT
|
|
4
4
|
# into the primary `Index` class, connecting USearch with Numba.
|
|
5
5
|
from math import sqrt
|
|
6
|
-
from typing import Callable
|
|
7
6
|
|
|
8
|
-
import numpy as np
|
|
9
7
|
from numba import cfunc, types, carray
|
|
10
8
|
|
|
11
|
-
from usearch.
|
|
9
|
+
from usearch.index import MetricKind, ScalarKind, MetricSignature, CompiledMetric
|
|
12
10
|
|
|
13
11
|
|
|
14
|
-
signature_i8args = types.float32(types.CPointer(
|
|
15
|
-
types.int8), types.CPointer(types.int8))
|
|
12
|
+
signature_i8args = types.float32(types.CPointer(types.int8), types.CPointer(types.int8))
|
|
16
13
|
|
|
17
|
-
signature_f16args = types.float32(
|
|
18
|
-
types.float16), types.CPointer(types.float16)
|
|
14
|
+
signature_f16args = types.float32(
|
|
15
|
+
types.CPointer(types.float16), types.CPointer(types.float16)
|
|
16
|
+
)
|
|
19
17
|
|
|
20
|
-
signature_f32args = types.float32(
|
|
21
|
-
types.float32), types.CPointer(types.float32)
|
|
18
|
+
signature_f32args = types.float32(
|
|
19
|
+
types.CPointer(types.float32), types.CPointer(types.float32)
|
|
20
|
+
)
|
|
22
21
|
|
|
23
|
-
signature_f64args = types.float32(
|
|
24
|
-
types.float64), types.CPointer(types.float64)
|
|
22
|
+
signature_f64args = types.float32(
|
|
23
|
+
types.CPointer(types.float64), types.CPointer(types.float64)
|
|
24
|
+
)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def jit(
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
def jit(
|
|
28
|
+
ndim: int, metric: MetricKind = MetricKind.Cos, dtype: ScalarKind = ScalarKind.F32
|
|
29
|
+
) -> CompiledMetric:
|
|
30
30
|
"""JIT-compiles a distance metric specifically tuned for the target hardware
|
|
31
31
|
and number of dimensions.
|
|
32
32
|
|
|
33
|
-
Uses Numba `cfunc` functionality, annotating it with Numba `types` instead
|
|
33
|
+
Uses Numba `cfunc` functionality, annotating it with Numba `types` instead
|
|
34
34
|
of `ctypes` to support half-precision.
|
|
35
35
|
https://numba.readthedocs.io/en/stable/reference/jit-compilation.html#c-callbacks
|
|
36
36
|
"""
|
|
@@ -88,8 +88,7 @@ def jit(ndim: int,
|
|
|
88
88
|
b_array = carray(b, ndim)
|
|
89
89
|
ab_delta_sq = accumulator(0)
|
|
90
90
|
for i in range(ndim):
|
|
91
|
-
ab_delta_sq += (a_array[i] - b_array[i]) *
|
|
92
|
-
(a_array[i] - b_array[i])
|
|
91
|
+
ab_delta_sq += (a_array[i] - b_array[i]) * (a_array[i] - b_array[i])
|
|
93
92
|
return types.float32(ab_delta_sq)
|
|
94
93
|
|
|
95
94
|
scalar_kind_to_signature = {
|
|
@@ -108,4 +107,9 @@ def jit(ndim: int,
|
|
|
108
107
|
if dtype == ScalarKind.F8 and metric == MetricKind.IP:
|
|
109
108
|
metric = MetricKind.Cos
|
|
110
109
|
|
|
111
|
-
|
|
110
|
+
pointer = cfunc(scalar_kind_to_signature[dtype])(metric_kind_to_function[metric])
|
|
111
|
+
return CompiledMetric(
|
|
112
|
+
pointer=pointer,
|
|
113
|
+
kind=metric,
|
|
114
|
+
signature=MetricSignature.ArrayArray,
|
|
115
|
+
)
|
package/python/usearch/server.py
CHANGED
|
@@ -26,10 +26,13 @@ def _ascii_to_vector(string: str) -> np.ndarray:
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def serve(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
ndim_: int,
|
|
30
|
+
metric: str = "ip",
|
|
31
|
+
port: int = 8545,
|
|
32
|
+
threads: int = 1,
|
|
33
|
+
path: str = "index.usearch",
|
|
34
|
+
immutable: bool = False,
|
|
35
|
+
):
|
|
33
36
|
server = Server(port=port)
|
|
34
37
|
index = Index(ndim=ndim_, metric=metric)
|
|
35
38
|
|
|
@@ -57,7 +60,7 @@ def serve(
|
|
|
57
60
|
|
|
58
61
|
@server
|
|
59
62
|
def add_one(label: int, vector: np.ndarray):
|
|
60
|
-
print(
|
|
63
|
+
print("adding", label, vector)
|
|
61
64
|
labels = np.array([label], dtype=Label)
|
|
62
65
|
vectors = vector.flatten().reshape(vector.shape[0], 1)
|
|
63
66
|
index.add(labels, vectors)
|
|
@@ -68,7 +71,7 @@ def serve(
|
|
|
68
71
|
|
|
69
72
|
@server
|
|
70
73
|
def search_one(vector: np.ndarray, count: int) -> List[dict]:
|
|
71
|
-
print(
|
|
74
|
+
print("search", vector, count)
|
|
72
75
|
vectors = vector.reshape(vector.shape[0], 1)
|
|
73
76
|
results: Matches = index.search(vectors, count)
|
|
74
77
|
return results.to_list()
|
|
@@ -93,33 +96,42 @@ def serve(
|
|
|
93
96
|
index.save(path)
|
|
94
97
|
|
|
95
98
|
|
|
96
|
-
if __name__ ==
|
|
97
|
-
|
|
99
|
+
if __name__ == "__main__":
|
|
98
100
|
parser = argparse.ArgumentParser()
|
|
99
|
-
parser.add_argument(
|
|
100
|
-
parser.add_argument(
|
|
101
|
-
'--ndim', type=int,
|
|
102
|
-
help='dimensionality of the vectors')
|
|
101
|
+
parser.add_argument("-v", "--verbose", help="log server activity")
|
|
102
|
+
parser.add_argument("--ndim", type=int, help="dimensionality of the vectors")
|
|
103
103
|
parser.add_argument(
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
"--immutable", type=bool, default=False, help="the index can not be updated"
|
|
105
|
+
)
|
|
106
106
|
|
|
107
107
|
parser.add_argument(
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
"--metric",
|
|
109
|
+
type=str,
|
|
110
|
+
default="ip",
|
|
111
|
+
choices=["ip", "cos", "l2sq", "haversine"],
|
|
112
|
+
help="distance function to compare vectors",
|
|
113
|
+
)
|
|
110
114
|
parser.add_argument(
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
"-p",
|
|
116
|
+
"--port",
|
|
117
|
+
type=int,
|
|
118
|
+
default=8545,
|
|
119
|
+
help="port to open for client connections",
|
|
120
|
+
)
|
|
113
121
|
parser.add_argument(
|
|
114
|
-
|
|
115
|
-
|
|
122
|
+
"-j", "--threads", type=int, default=1, help="number of CPU threads to use"
|
|
123
|
+
)
|
|
116
124
|
parser.add_argument(
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
"--path", type=str, default="index.usearch", help="where to store the index"
|
|
126
|
+
)
|
|
119
127
|
|
|
120
128
|
args = parser.parse_args()
|
|
121
|
-
assert args.ndim is not None,
|
|
129
|
+
assert args.ndim is not None, "Define the number of dimensions!"
|
|
122
130
|
serve(
|
|
123
|
-
ndim_=args.ndim,
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
ndim_=args.ndim,
|
|
132
|
+
metric=args.metric,
|
|
133
|
+
threads=args.threads,
|
|
134
|
+
port=args.port,
|
|
135
|
+
path=args.path,
|
|
136
|
+
immutable=args.immutable,
|
|
137
|
+
)
|
package/setup.py
CHANGED
|
@@ -5,97 +5,94 @@ from setuptools import setup
|
|
|
5
5
|
from pybind11.setup_helpers import Pybind11Extension
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
compile_args = [
|
|
8
|
+
compile_args = []
|
|
9
9
|
link_args = []
|
|
10
10
|
macros_args = [
|
|
11
|
-
(
|
|
12
|
-
(
|
|
11
|
+
("USEARCH_USE_NATIVE_F16", "0"),
|
|
12
|
+
("USEARCH_USE_SIMSIMD", "0"),
|
|
13
13
|
]
|
|
14
14
|
|
|
15
|
-
if sys.platform ==
|
|
16
|
-
compile_args.append(
|
|
17
|
-
|
|
18
|
-
compile_args.append(
|
|
19
|
-
macros_args.append(('USEARCH_USE_OPENMP', '1'))
|
|
15
|
+
if sys.platform == "linux":
|
|
16
|
+
compile_args.append("-std=c++11")
|
|
17
|
+
compile_args.append("-O3")
|
|
18
|
+
compile_args.append("-Wno-unknown-pragmas")
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
macros_args.append(("USEARCH_USE_OPENMP", "1"))
|
|
21
|
+
compile_args.append("-fopenmp")
|
|
22
|
+
link_args.append("-lgomp")
|
|
23
|
+
|
|
24
|
+
if sys.platform == "darwin":
|
|
22
25
|
# MacOS 10.15 or higher is needed for `aligned_alloc` support.
|
|
23
26
|
# https://github.com/unum-cloud/usearch/actions/runs/4975434891/jobs/8902603392
|
|
24
|
-
compile_args.append(
|
|
25
|
-
compile_args.append(
|
|
27
|
+
compile_args.append("-mmacosx-version-min=10.15")
|
|
28
|
+
compile_args.append("-std=c++11")
|
|
29
|
+
compile_args.append("-O3")
|
|
30
|
+
compile_args.append("-Wno-unknown-pragmas")
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
# Linking OpenMP requires additional preparion in CIBuildWheel
|
|
33
|
+
# macros_args.append(("USEARCH_USE_OPENMP", "1"))
|
|
34
|
+
# compile_args.append("-Xpreprocessor -fopenmp")
|
|
35
|
+
# link_args.append("-Xpreprocessor -lomp")
|
|
29
36
|
|
|
37
|
+
if sys.platform == "win32":
|
|
38
|
+
compile_args.append("/std:c++14")
|
|
39
|
+
compile_args.append("/O2")
|
|
30
40
|
|
|
31
41
|
ext_modules = [
|
|
32
42
|
Pybind11Extension(
|
|
33
|
-
|
|
34
|
-
[
|
|
43
|
+
"usearch.compiled",
|
|
44
|
+
["python/lib.cpp"],
|
|
35
45
|
extra_compile_args=compile_args,
|
|
36
46
|
extra_link_args=link_args,
|
|
37
47
|
define_macros=macros_args,
|
|
38
48
|
),
|
|
39
49
|
]
|
|
40
50
|
|
|
41
|
-
__version__ = open(
|
|
42
|
-
__lib_name__ =
|
|
51
|
+
__version__ = open("VERSION", "r").read().strip()
|
|
52
|
+
__lib_name__ = "usearch"
|
|
43
53
|
|
|
44
54
|
|
|
45
55
|
this_directory = os.path.abspath(os.path.dirname(__file__))
|
|
46
|
-
with open(os.path.join(this_directory,
|
|
56
|
+
with open(os.path.join(this_directory, "README.md")) as f:
|
|
47
57
|
long_description = f.read()
|
|
48
58
|
|
|
49
59
|
|
|
50
60
|
setup(
|
|
51
|
-
|
|
52
61
|
name=__lib_name__,
|
|
53
62
|
version=__version__,
|
|
54
|
-
packages=[
|
|
55
|
-
package_dir={
|
|
56
|
-
|
|
57
|
-
description='Smaller & Faster Single-File Vector Search Engine from Unum',
|
|
63
|
+
packages=["usearch"],
|
|
64
|
+
package_dir={"usearch": "python/usearch"},
|
|
65
|
+
description="Smaller & Faster Single-File Vector Search Engine from Unum",
|
|
58
66
|
long_description=long_description,
|
|
59
|
-
long_description_content_type=
|
|
60
|
-
license=
|
|
61
|
-
|
|
67
|
+
long_description_content_type="text/markdown",
|
|
68
|
+
license="Apache-2.0",
|
|
62
69
|
classifiers=[
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
'Topic :: System :: Clustering',
|
|
84
|
-
'Topic :: Database :: Database Engines/Servers',
|
|
85
|
-
'Topic :: Scientific/Engineering :: Artificial Intelligence',
|
|
70
|
+
"Development Status :: 5 - Production/Stable",
|
|
71
|
+
"Natural Language :: English",
|
|
72
|
+
"Intended Audience :: Developers",
|
|
73
|
+
"Intended Audience :: Information Technology",
|
|
74
|
+
"License :: OSI Approved :: Apache Software License",
|
|
75
|
+
"Programming Language :: C++",
|
|
76
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
77
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
78
|
+
"Programming Language :: Java",
|
|
79
|
+
"Programming Language :: JavaScript",
|
|
80
|
+
"Programming Language :: Objective C",
|
|
81
|
+
"Programming Language :: Rust",
|
|
82
|
+
"Programming Language :: Other",
|
|
83
|
+
"Operating System :: MacOS",
|
|
84
|
+
"Operating System :: Unix",
|
|
85
|
+
"Operating System :: Microsoft :: Windows",
|
|
86
|
+
"Topic :: System :: Clustering",
|
|
87
|
+
"Topic :: Database :: Database Engines/Servers",
|
|
88
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
86
89
|
],
|
|
87
|
-
|
|
88
|
-
include_dirs=[
|
|
89
|
-
'include',
|
|
90
|
-
'fp16/include', 'robin-map/include', 'simsimd/include'],
|
|
91
|
-
|
|
90
|
+
include_dirs=["include", "fp16/include", "robin-map/include", "simsimd/include"],
|
|
92
91
|
ext_modules=ext_modules,
|
|
93
92
|
install_requires=[
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
"numpy",
|
|
94
|
+
"pandas",
|
|
95
|
+
"tqdm",
|
|
96
96
|
'ucall; python_version >= "3.9"',
|
|
97
97
|
],
|
|
98
|
-
extras_require={
|
|
99
|
-
'jit': ['numba', 'cppyy'],
|
|
100
|
-
},
|
|
101
98
|
)
|
package/simsimd/CMakeLists.txt
CHANGED
|
@@ -52,7 +52,7 @@ endif()
|
|
|
52
52
|
|
|
53
53
|
# Define our header-only library.
|
|
54
54
|
add_library(simsimd INTERFACE)
|
|
55
|
-
target_sources(simsimd INTERFACE include/simsimd/simsimd.
|
|
55
|
+
target_sources(simsimd INTERFACE include/simsimd/simsimd.h)
|
|
56
56
|
target_include_directories(simsimd INTERFACE "${PROJECT_SOURCE_DIR}/include")
|
|
57
57
|
|
|
58
58
|
# Build the benchmarks if needed.
|
package/simsimd/README.md
CHANGED
|
@@ -66,8 +66,20 @@ With AVX2 and 256-bit registers the results should be better, but would be less
|
|
|
66
66
|
|
|
67
67
|
---
|
|
68
68
|
|
|
69
|
-
To replicate on your hardware, please run:
|
|
69
|
+
To replicate on your hardware, please run following on Linux:
|
|
70
70
|
|
|
71
71
|
```sh
|
|
72
|
-
cmake -DCMAKE_BUILD_TYPE=Release -
|
|
72
|
+
cmake -DCMAKE_BUILD_TYPE=Release -DSIMSIMD_BUILD_BENCHMARKS=1 -B ./build && make -C ./build && ./build/simsimd_bench
|
|
73
73
|
```
|
|
74
|
+
|
|
75
|
+
MacOS:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
brew install llvm
|
|
79
|
+
cmake -B ./build \
|
|
80
|
+
-DCMAKE_C_COMPILER="/opt/homebrew/opt/llvm/bin/clang" \
|
|
81
|
+
-DCMAKE_CXX_COMPILER="/opt/homebrew/opt/llvm/bin/clang++" \
|
|
82
|
+
-DSIMSIMD_BUILD_BENCHMARKS=1 \
|
|
83
|
+
&& \
|
|
84
|
+
make -C ./build -j && ./build/simsimd_bench
|
|
85
|
+
```
|
package/simsimd/bench.cxx
CHANGED
|
@@ -1,46 +1,35 @@
|
|
|
1
|
+
#include <thread>
|
|
2
|
+
|
|
1
3
|
#include <benchmark/benchmark.h>
|
|
2
4
|
|
|
3
|
-
#include <simsimd/simsimd.
|
|
5
|
+
#include <simsimd/simsimd.h>
|
|
4
6
|
|
|
5
7
|
namespace bm = benchmark;
|
|
6
|
-
using namespace av::simsimd;
|
|
7
8
|
|
|
8
|
-
static
|
|
9
|
-
static
|
|
9
|
+
static const std::size_t threads_k = std::thread::hardware_concurrency();
|
|
10
|
+
static const std::size_t time_k = 10;
|
|
10
11
|
|
|
11
|
-
template <typename
|
|
12
|
+
template <typename scalar_at, typename metric_at, std::size_t bytes_per_vector_ak = 256,
|
|
12
13
|
std::size_t dimensions_ak = bytes_per_vector_ak / sizeof(scalar_at)> //
|
|
13
|
-
static void measure(bm::State& state) {
|
|
14
|
+
static void measure(bm::State& state, metric_at metric) {
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
alignas(64) scalar_at
|
|
17
|
-
|
|
18
|
-
scalar_at c{};
|
|
16
|
+
alignas(64) scalar_at a[dimensions_ak]{};
|
|
17
|
+
alignas(64) scalar_at b[dimensions_ak]{};
|
|
18
|
+
float c{};
|
|
19
19
|
|
|
20
|
-
std::fill_n(a,
|
|
21
|
-
std::fill_n(b,
|
|
20
|
+
std::fill_n(a, dimensions_ak, static_cast<scalar_at>(1));
|
|
21
|
+
std::fill_n(b, dimensions_ak, static_cast<scalar_at>(2));
|
|
22
22
|
|
|
23
23
|
for (auto _ : state)
|
|
24
|
-
bm::DoNotOptimize((c =
|
|
24
|
+
bm::DoNotOptimize((c = metric(a, b, dimensions_ak)));
|
|
25
25
|
|
|
26
26
|
state.SetBytesProcessed(state.iterations() * bytes_per_vector_ak * 2u);
|
|
27
27
|
state.SetItemsProcessed(state.iterations());
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
BENCHMARK_TEMPLATE(measure, euclidean_distance_t, f16_t, 256)->Threads(threads_k)->MinTime(time_k);
|
|
34
|
-
|
|
35
|
-
BENCHMARK_TEMPLATE(measure, cosine_similarity_t, f32_t, 32)->Threads(threads_k)->MinTime(time_k);
|
|
36
|
-
BENCHMARK_TEMPLATE(measure, cosine_similarity_t, f32_t, 256)->Threads(threads_k)->MinTime(time_k);
|
|
37
|
-
BENCHMARK_TEMPLATE(measure, cosine_similarity_f32x4k_t, f32_t, 32)->Threads(threads_k)->MinTime(time_k);
|
|
38
|
-
BENCHMARK_TEMPLATE(measure, cosine_similarity_f32x4k_t, f32_t, 256)->Threads(threads_k)->MinTime(time_k);
|
|
39
|
-
|
|
40
|
-
BENCHMARK_TEMPLATE(measure, hamming_bits_distance_t, u64_t, 32, 256)->Threads(threads_k)->MinTime(time_k);
|
|
41
|
-
BENCHMARK_TEMPLATE(measure, hamming_bits_distance_t, u64_t, 256, 2048)->Threads(threads_k)->MinTime(time_k);
|
|
42
|
-
BENCHMARK_TEMPLATE(measure, hamming_bits_distance_u1x128k_t, u64_t, 32, 256)->Threads(threads_k)->MinTime(time_k);
|
|
43
|
-
BENCHMARK_TEMPLATE(measure, hamming_bits_distance_u1x128k_t, u64_t, 256, 2048)->Threads(threads_k)->MinTime(time_k);
|
|
30
|
+
template <typename scalar_at, typename metric_at> void register_(char const* name, metric_at distance_func) {
|
|
31
|
+
bm::RegisterBenchmark(name, measure<scalar_at, metric_at>, distance_func)->Threads(threads_k)->MinTime(time_k);
|
|
32
|
+
}
|
|
44
33
|
|
|
45
34
|
int main(int argc, char** argv) {
|
|
46
35
|
|
|
@@ -76,6 +65,34 @@ int main(int argc, char** argv) {
|
|
|
76
65
|
bm::Initialize(&argc, argv);
|
|
77
66
|
if (bm::ReportUnrecognizedArguments(argc, argv))
|
|
78
67
|
return 1;
|
|
68
|
+
|
|
69
|
+
#if defined(__ARM_FEATURE_SVE)
|
|
70
|
+
register_<simsimd_f32_t>("dot_f32sve", simsimd_dot_f32sve);
|
|
71
|
+
register_<simsimd_f32_t>("cos_f32sve", simsimd_cos_f32sve);
|
|
72
|
+
register_<simsimd_f32_t>("l2sq_f32sve", simsimd_l2sq_f32sve);
|
|
73
|
+
register_<std::int16_t>("l2sq_f16sve", simsimd_l2sq_f16sve);
|
|
74
|
+
register_<std::uint8_t>("hamming_b1x8sve", simsimd_hamming_b1x8sve);
|
|
75
|
+
register_<std::uint8_t>("hamming_b1x128sve", simsimd_hamming_b1x128sve);
|
|
76
|
+
#endif
|
|
77
|
+
|
|
78
|
+
#if defined(__ARM_NEON)
|
|
79
|
+
register_<simsimd_f32_t>("dot_f32x4neon", simsimd_dot_f32x4neon);
|
|
80
|
+
register_<std::int16_t>("cos_f16x4neon", simsimd_cos_f16x4neon);
|
|
81
|
+
register_<std::int8_t>("cos_i8x16neon", simsimd_cos_i8x16neon);
|
|
82
|
+
register_<simsimd_f32_t>("cos_f32x4neon", simsimd_cos_f32x4neon);
|
|
83
|
+
#endif
|
|
84
|
+
|
|
85
|
+
#if defined(__AVX2__)
|
|
86
|
+
register_<simsimd_f32_t>("dot_f32x4avx2", simsimd_dot_f32x4avx2);
|
|
87
|
+
register_<std::int8_t>("dot_i8x16avx2", simsimd_dot_i8x16avx2);
|
|
88
|
+
register_<simsimd_f32_t>("cos_f32x4avx2", simsimd_cos_f32x4avx2);
|
|
89
|
+
#endif
|
|
90
|
+
|
|
91
|
+
#if defined(__AVX512F__)
|
|
92
|
+
register_<std::int16_t>("cos_f16x16avx512", simsimd_cos_f16x16avx512);
|
|
93
|
+
register_<std::uint8_t>("hamming_b1x128avx512", simsimd_hamming_b1x128avx512);
|
|
94
|
+
#endif
|
|
95
|
+
|
|
79
96
|
bm::RunSpecifiedBenchmarks();
|
|
80
97
|
bm::Shutdown();
|
|
81
98
|
return 0;
|
package/swift/Test.swift
CHANGED
|
@@ -6,16 +6,20 @@
|
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
import Foundation
|
|
9
|
+
import XCTest
|
|
9
10
|
import USearch
|
|
10
11
|
|
|
11
12
|
@available(iOS 13, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
class Test: XCTestCase {
|
|
14
|
+
func testUnit() throws {
|
|
15
|
+
let index = USearchIndex.make(metric:USearchMetric.l2sq, dimensions: 4, connectivity: 8, quantization:USearchScalar.F32)
|
|
16
|
+
let vectorA: [Float32] = [0.3, 0.5, 1.2, 1.4]
|
|
17
|
+
let vectorB: [Float32] = [0.4, 0.2, 1.2, 1.1]
|
|
18
|
+
index.reserve(2)
|
|
19
|
+
index.add(label: 42, vector: vectorA[...])
|
|
20
|
+
index.add(label: 43, vector: vectorB[...])
|
|
21
|
+
|
|
22
|
+
let results = index.search(vector: vectorA[...], count: 10)
|
|
23
|
+
assert(results.0[0] == 42)
|
|
24
|
+
}
|
|
21
25
|
}
|