usearch 2.15.3 → 2.16.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/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
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Module: bench_vectors_live.py
|
|
5
|
+
|
|
6
|
+
This script visualizes the performance difference between SimSIMD and default
|
|
7
|
+
numerics libraries like NumPy and SimSIMD for the most common kernels.
|
|
8
|
+
|
|
9
|
+
One plot contains information about one distance function, but many data types
|
|
10
|
+
and libraries. For each benchmark, the baseline is the NumPy/SciPy distance function
|
|
11
|
+
applied to `float64` input data. The "x" axis represents the growth in the number of
|
|
12
|
+
dimensions of the input vectors, while the "y" axis represents the speedup factor
|
|
13
|
+
of every kernel against the baseline.
|
|
14
|
+
"""
|
|
15
|
+
import os
|
|
16
|
+
import argparse
|
|
17
|
+
from typing import List
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
import perfplot
|
|
22
|
+
|
|
23
|
+
from bench_vectors import (
|
|
24
|
+
metric_families,
|
|
25
|
+
dtype_names,
|
|
26
|
+
Kernel,
|
|
27
|
+
yield_kernels,
|
|
28
|
+
random_matrix,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def ndim_argument(value):
|
|
33
|
+
if value == "default":
|
|
34
|
+
return [2**k for k in range(16)]
|
|
35
|
+
try:
|
|
36
|
+
# Split the input string by commas and convert each part to an integer
|
|
37
|
+
return [int(x) for x in value.split(",")]
|
|
38
|
+
except ValueError:
|
|
39
|
+
raise argparse.ArgumentTypeError("Value must be 'default' or a comma-separated list of integers")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def main():
|
|
43
|
+
# Argument parsing
|
|
44
|
+
parser = argparse.ArgumentParser(description="Visualize Performance Difference between SimSIMD and other libraries")
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
"--ndim-min",
|
|
47
|
+
type=int,
|
|
48
|
+
default=2,
|
|
49
|
+
help="",
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--ndim-max",
|
|
53
|
+
type=int,
|
|
54
|
+
default=1024 * 1024,
|
|
55
|
+
help="",
|
|
56
|
+
)
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"-o",
|
|
59
|
+
"--output-path",
|
|
60
|
+
type=str,
|
|
61
|
+
default=None,
|
|
62
|
+
help="File to save the plot to (default: None, plot is shown live)",
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
"-n",
|
|
66
|
+
"--count",
|
|
67
|
+
type=int,
|
|
68
|
+
default=1,
|
|
69
|
+
help="""Number of vectors per batch (default: 1)
|
|
70
|
+
|
|
71
|
+
By default, when set to 1 the benchmark will generate many vectors of size (ndim, )
|
|
72
|
+
and call the functions on pairs of single vectors: both directly, and through `cdist`.
|
|
73
|
+
Alternatively, for larger batch sizes the benchmark will generate two matrices of
|
|
74
|
+
size (n, ndim) and compute:
|
|
75
|
+
|
|
76
|
+
- batch mode: (n) distances between vectors in identical rows of the two matrices,
|
|
77
|
+
- all-pairs mode: (n^2) distances between all pairs of vectors in the two matrices via `cdist`.
|
|
78
|
+
""",
|
|
79
|
+
)
|
|
80
|
+
parser.add_argument(
|
|
81
|
+
"--mode",
|
|
82
|
+
choices=["batch", "all-pairs"],
|
|
83
|
+
default="batch",
|
|
84
|
+
help="""Choose between 'batch' and 'all-pairs' mode (default: batch)
|
|
85
|
+
|
|
86
|
+
In 'batch' mode, the latency will generate two matrices of size (n, ndim)
|
|
87
|
+
and compute (n) distances between vectors in identical rows of the two matrices.
|
|
88
|
+
In 'all-pairs' mode, the latency will generate two matrices of size (n, ndim)
|
|
89
|
+
and compute (n^2) distances between all pairs of vectors in the two matrices via `cdist`.
|
|
90
|
+
""",
|
|
91
|
+
)
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"--metric",
|
|
94
|
+
choices=metric_families,
|
|
95
|
+
default="dot",
|
|
96
|
+
help=f"Distance metric to use, profiles `dot` by default",
|
|
97
|
+
)
|
|
98
|
+
parser.add_argument(
|
|
99
|
+
"--dtype",
|
|
100
|
+
choices=dtype_names,
|
|
101
|
+
default="float64",
|
|
102
|
+
help=f"Defines numeric types to latency, profiles `float64` by default",
|
|
103
|
+
)
|
|
104
|
+
parser.add_argument("--scipy", action="store_true", help="Profile SciPy, must be installed")
|
|
105
|
+
parser.add_argument("--scikit", action="store_true", help="Profile scikit-learn, must be installed")
|
|
106
|
+
parser.add_argument("--torch", action="store_true", help="Profile PyTorch, must be installed")
|
|
107
|
+
parser.add_argument("--tf", action="store_true", help="Profile TensorFlow, must be installed")
|
|
108
|
+
parser.add_argument("--jax", action="store_true", help="Profile JAX, must be installed")
|
|
109
|
+
|
|
110
|
+
args = parser.parse_args()
|
|
111
|
+
assert args.count > 0, "Number of vectors per batch must be greater than 0"
|
|
112
|
+
assert args.ndim_min > 0, "Number of dimensions must be greater than 0"
|
|
113
|
+
assert args.ndim_max > 0, "Number of dimensions must be greater than 0"
|
|
114
|
+
|
|
115
|
+
ndim_range = [args.ndim_min]
|
|
116
|
+
while ndim_range[-1] <= args.ndim_max:
|
|
117
|
+
ndim_range.append(ndim_range[-1] * 2)
|
|
118
|
+
|
|
119
|
+
kernels: List[Kernel] = list(
|
|
120
|
+
yield_kernels(
|
|
121
|
+
[args.metric],
|
|
122
|
+
dtype_names,
|
|
123
|
+
include_scipy=args.scipy,
|
|
124
|
+
include_scikit=args.scikit,
|
|
125
|
+
include_torch=args.torch,
|
|
126
|
+
include_tf=args.tf,
|
|
127
|
+
include_jax=args.jax,
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
if len(kernels) == 0:
|
|
131
|
+
raise RuntimeError("No kernels found!")
|
|
132
|
+
|
|
133
|
+
def precomputed_flops(ndim: int) -> int:
|
|
134
|
+
if args.mode == "all-pairs":
|
|
135
|
+
return ndim * (args.count**2)
|
|
136
|
+
else:
|
|
137
|
+
return ndim * (args.count)
|
|
138
|
+
|
|
139
|
+
def generate_matrix(ndim: int) -> np.ndarray:
|
|
140
|
+
if args.count == 1:
|
|
141
|
+
return random_matrix(1, ndim, dtype=args.dtype).flatten()
|
|
142
|
+
else:
|
|
143
|
+
return random_matrix(args.count, ndim, dtype=args.dtype)
|
|
144
|
+
|
|
145
|
+
def wrap_binary_function(function):
|
|
146
|
+
def wrapped(A):
|
|
147
|
+
return function(A, A)
|
|
148
|
+
|
|
149
|
+
return wrapped
|
|
150
|
+
|
|
151
|
+
kernel_labels: List[str] = []
|
|
152
|
+
kernel_callables: List[callable] = []
|
|
153
|
+
|
|
154
|
+
# Add SimSIMD kernels
|
|
155
|
+
for kernel in kernels:
|
|
156
|
+
if not kernel.name.startswith("numpy.") and not kernel.name.startswith("scipy."):
|
|
157
|
+
continue
|
|
158
|
+
_, _, function_name = kernel.name.partition(".")
|
|
159
|
+
kernel_labels.append(f"simsimd.{function_name}<{kernel.dtype}>")
|
|
160
|
+
if args.mode == "all-pairs":
|
|
161
|
+
kernel_callables.append(wrap_binary_function(kernel.simsimd_all_pairs_func))
|
|
162
|
+
else:
|
|
163
|
+
kernel_callables.append(wrap_binary_function(kernel.simsimd_func))
|
|
164
|
+
|
|
165
|
+
# Add other kernels
|
|
166
|
+
for kernel in kernels:
|
|
167
|
+
kernel_labels.append(f"{kernel.name}<{kernel.dtype}>")
|
|
168
|
+
if args.mode == "all-pairs":
|
|
169
|
+
kernel_callables.append(wrap_binary_function(kernel.baseline_all_pairs_func))
|
|
170
|
+
elif args.count == 1:
|
|
171
|
+
kernel_callables.append(wrap_binary_function(kernel.baseline_one_to_one_func))
|
|
172
|
+
else:
|
|
173
|
+
kernel_callables.append(wrap_binary_function(kernel.baseline_many_to_many_func))
|
|
174
|
+
|
|
175
|
+
# Filter-out kernels that raise any exceptions
|
|
176
|
+
safe_callables = []
|
|
177
|
+
safe_labels = []
|
|
178
|
+
for kernel_label, kernel_callable in zip(kernel_labels, kernel_callables):
|
|
179
|
+
try:
|
|
180
|
+
kernel_callable(generate_matrix(ndim_range[0]))
|
|
181
|
+
safe_callables.append(kernel_callable)
|
|
182
|
+
safe_labels.append(kernel_label)
|
|
183
|
+
except:
|
|
184
|
+
print(f"Skipping {kernel_label}")
|
|
185
|
+
|
|
186
|
+
print(safe_callables)
|
|
187
|
+
print(safe_labels)
|
|
188
|
+
|
|
189
|
+
# Settings are mostly the same for live charts and exported ones
|
|
190
|
+
profiler_settings = dict(
|
|
191
|
+
setup=generate_matrix,
|
|
192
|
+
kernels=safe_callables,
|
|
193
|
+
labels=safe_labels,
|
|
194
|
+
n_range=ndim_range,
|
|
195
|
+
flops=precomputed_flops,
|
|
196
|
+
xlabel="ndim",
|
|
197
|
+
equality_check=None, # bypass correctness check, we have tests for that
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Plot the results
|
|
201
|
+
if args.output_path is not None:
|
|
202
|
+
plot_fp = os.path.abspath(args.output_path)
|
|
203
|
+
profiler_settings["filename"] = plot_fp
|
|
204
|
+
profiler_settings["show_progress"] = False
|
|
205
|
+
results = perfplot.bench(**profiler_settings)
|
|
206
|
+
results.save(plot_fp, transparent=False, bbox_inches="tight", relative_to=0, logy="auto")
|
|
207
|
+
else:
|
|
208
|
+
profiler_settings.pop("flops")
|
|
209
|
+
perfplot.live(**profiler_settings)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
if __name__ == "__main__":
|
|
213
|
+
main()
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file test.c
|
|
3
|
+
* @brief Test focusing only on the simplest functionality.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include <assert.h> // `assert`
|
|
7
|
+
#include <math.h> // `sqrtf`
|
|
8
|
+
#include <stdio.h> // `printf`
|
|
9
|
+
|
|
10
|
+
#define SIMSIMD_NATIVE_F16 0
|
|
11
|
+
#define SIMSIMD_NATIVE_BF16 0
|
|
12
|
+
#include <simsimd/simsimd.h>
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @brief Logs CPU capabilities supported by the current build (compile-time) and runtime.
|
|
16
|
+
*/
|
|
17
|
+
void print_capabilities(void) {
|
|
18
|
+
simsimd_capability_t runtime_caps = simsimd_capabilities();
|
|
19
|
+
|
|
20
|
+
// Log supported functionality
|
|
21
|
+
char const *flags[2] = {"false", "true"};
|
|
22
|
+
printf("Benchmarking Similarity Measures\n");
|
|
23
|
+
printf("- Compiler used native F16: %s\n", flags[SIMSIMD_NATIVE_F16]);
|
|
24
|
+
printf("- Compiler used native BF16: %s\n", flags[SIMSIMD_NATIVE_BF16]);
|
|
25
|
+
printf("\n");
|
|
26
|
+
printf("Compile-time settings:\n");
|
|
27
|
+
printf("- Arm NEON support enabled: %s\n", flags[SIMSIMD_TARGET_NEON]);
|
|
28
|
+
printf("- Arm SVE support enabled: %s\n", flags[SIMSIMD_TARGET_SVE]);
|
|
29
|
+
printf("- Arm SVE2 support enabled: %s\n", flags[SIMSIMD_TARGET_SVE2]);
|
|
30
|
+
printf("- x86 Haswell support enabled: %s\n", flags[SIMSIMD_TARGET_HASWELL]);
|
|
31
|
+
printf("- x86 Skylake support enabled: %s\n", flags[SIMSIMD_TARGET_SKYLAKE]);
|
|
32
|
+
printf("- x86 Ice Lake support enabled: %s\n", flags[SIMSIMD_TARGET_ICE]);
|
|
33
|
+
printf("- x86 Genoa support enabled: %s\n", flags[SIMSIMD_TARGET_GENOA]);
|
|
34
|
+
printf("- x86 Sapphire Rapids support enabled: %s\n", flags[SIMSIMD_TARGET_SAPPHIRE]);
|
|
35
|
+
printf("- x86 Turin support enabled: %s\n", flags[SIMSIMD_TARGET_TURIN]);
|
|
36
|
+
printf("- x86 Sierra Forest support enabled: %s\n", flags[SIMSIMD_TARGET_SIERRA]);
|
|
37
|
+
printf("\n");
|
|
38
|
+
printf("Run-time settings:\n");
|
|
39
|
+
printf("- Arm NEON support enabled: %s\n", flags[(runtime_caps & simsimd_cap_neon_k) != 0]);
|
|
40
|
+
printf("- Arm NEON F16 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_neon_f16_k) != 0]);
|
|
41
|
+
printf("- Arm NEON BF16 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_neon_bf16_k) != 0]);
|
|
42
|
+
printf("- Arm NEON I8 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_neon_i8_k) != 0]);
|
|
43
|
+
printf("- Arm SVE support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve_k) != 0]);
|
|
44
|
+
printf("- Arm SVE F16 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve_f16_k) != 0]);
|
|
45
|
+
printf("- Arm SVE BF16 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve_bf16_k) != 0]);
|
|
46
|
+
printf("- Arm SVE I8 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve_i8_k) != 0]);
|
|
47
|
+
printf("- Arm SVE2 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve2_k) != 0]);
|
|
48
|
+
printf("- x86 Haswell support enabled: %s\n", flags[(runtime_caps & simsimd_cap_haswell_k) != 0]);
|
|
49
|
+
printf("- x86 Skylake support enabled: %s\n", flags[(runtime_caps & simsimd_cap_skylake_k) != 0]);
|
|
50
|
+
printf("- x86 Ice Lake support enabled: %s\n", flags[(runtime_caps & simsimd_cap_ice_k) != 0]);
|
|
51
|
+
printf("- x86 Genoa support enabled: %s\n", flags[(runtime_caps & simsimd_cap_genoa_k) != 0]);
|
|
52
|
+
printf("- x86 Sapphire Rapids support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sapphire_k) != 0]);
|
|
53
|
+
printf("- x86 Turin support enabled: %s\n", flags[(runtime_caps & simsimd_cap_turin_k) != 0]);
|
|
54
|
+
printf("\n");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @brief A trivial test that checks if the utility functions return the expected values.
|
|
59
|
+
*/
|
|
60
|
+
void test_utilities(void) {
|
|
61
|
+
simsimd_capability_t capabilities = simsimd_capabilities();
|
|
62
|
+
|
|
63
|
+
int uses_neon = simsimd_uses_neon();
|
|
64
|
+
int uses_sve = simsimd_uses_sve();
|
|
65
|
+
int uses_haswell = simsimd_uses_haswell();
|
|
66
|
+
int uses_skylake = simsimd_uses_skylake();
|
|
67
|
+
int uses_ice = simsimd_uses_ice();
|
|
68
|
+
int uses_genoa = simsimd_uses_genoa();
|
|
69
|
+
int uses_sapphire = simsimd_uses_sapphire();
|
|
70
|
+
int uses_turin = simsimd_uses_turin();
|
|
71
|
+
int uses_sierra = simsimd_uses_sierra();
|
|
72
|
+
|
|
73
|
+
assert(uses_neon == ((capabilities & simsimd_cap_neon_k) != 0));
|
|
74
|
+
assert(uses_sve == ((capabilities & simsimd_cap_sve_k) != 0));
|
|
75
|
+
assert(uses_haswell == ((capabilities & simsimd_cap_haswell_k) != 0));
|
|
76
|
+
assert(uses_skylake == ((capabilities & simsimd_cap_skylake_k) != 0));
|
|
77
|
+
assert(uses_ice == ((capabilities & simsimd_cap_ice_k) != 0));
|
|
78
|
+
assert(uses_genoa == ((capabilities & simsimd_cap_genoa_k) != 0));
|
|
79
|
+
assert(uses_sapphire == ((capabilities & simsimd_cap_sapphire_k) != 0));
|
|
80
|
+
assert(uses_turin == ((capabilities & simsimd_cap_turin_k) != 0));
|
|
81
|
+
assert(uses_sierra == ((capabilities & simsimd_cap_sierra_k) != 0));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @brief A trivial test that calls every implemented distance function and their dispatch versions
|
|
86
|
+
* on vectors A and B, where A and B are equal.
|
|
87
|
+
*/
|
|
88
|
+
void test_distance_from_itself(void) {
|
|
89
|
+
simsimd_f64_t f64s[1536];
|
|
90
|
+
simsimd_f32_t f32s[1536];
|
|
91
|
+
simsimd_f16_t f16s[1536];
|
|
92
|
+
simsimd_bf16_t bf16s[1536];
|
|
93
|
+
simsimd_i8_t i8s[1536];
|
|
94
|
+
simsimd_b8_t b8s[1536 / 8]; // 8 bits per word
|
|
95
|
+
simsimd_distance_t distance;
|
|
96
|
+
|
|
97
|
+
// Cosine distance between two vectors
|
|
98
|
+
simsimd_cos_i8(i8s, i8s, 1536, &distance);
|
|
99
|
+
simsimd_cos_f16(f16s, f16s, 1536, &distance);
|
|
100
|
+
simsimd_cos_bf16(bf16s, bf16s, 1536, &distance);
|
|
101
|
+
simsimd_cos_f32(f32s, f32s, 1536, &distance);
|
|
102
|
+
simsimd_cos_f64(f64s, f64s, 1536, &distance);
|
|
103
|
+
|
|
104
|
+
// Euclidean distance between two vectors
|
|
105
|
+
simsimd_l2sq_i8(i8s, i8s, 1536, &distance);
|
|
106
|
+
simsimd_l2sq_f16(f16s, f16s, 1536, &distance);
|
|
107
|
+
simsimd_l2sq_bf16(bf16s, bf16s, 1536, &distance);
|
|
108
|
+
simsimd_l2sq_f32(f32s, f32s, 1536, &distance);
|
|
109
|
+
simsimd_l2sq_f64(f64s, f64s, 1536, &distance);
|
|
110
|
+
|
|
111
|
+
// Inner product between two vectors
|
|
112
|
+
simsimd_dot_f16(f16s, f16s, 1536, &distance);
|
|
113
|
+
simsimd_dot_bf16(bf16s, bf16s, 1536, &distance);
|
|
114
|
+
simsimd_dot_f32(f32s, f32s, 1536, &distance);
|
|
115
|
+
simsimd_dot_f64(f64s, f64s, 1536, &distance);
|
|
116
|
+
|
|
117
|
+
// Complex inner product between two vectors
|
|
118
|
+
simsimd_dot_f16c(f16s, f16s, 1536, &distance);
|
|
119
|
+
simsimd_dot_bf16c(bf16s, bf16s, 1536, &distance);
|
|
120
|
+
// simsimd_dot_bf16c(bf16s, bf16s, 1536, &distance);
|
|
121
|
+
simsimd_dot_f32c(f32s, f32s, 1536, &distance);
|
|
122
|
+
simsimd_dot_f64c(f64s, f64s, 1536, &distance);
|
|
123
|
+
|
|
124
|
+
// Complex conjugate inner product between two vectors
|
|
125
|
+
simsimd_vdot_f16c(f16s, f16s, 1536, &distance);
|
|
126
|
+
simsimd_vdot_bf16c(bf16s, bf16s, 1536, &distance);
|
|
127
|
+
simsimd_vdot_f32c(f32s, f32s, 1536, &distance);
|
|
128
|
+
simsimd_vdot_f64c(f64s, f64s, 1536, &distance);
|
|
129
|
+
|
|
130
|
+
// Hamming distance between two vectors
|
|
131
|
+
simsimd_hamming_b8(b8s, b8s, 1536 / 8, &distance);
|
|
132
|
+
|
|
133
|
+
// Jaccard distance between two vectors
|
|
134
|
+
simsimd_jaccard_b8(b8s, b8s, 1536 / 8, &distance);
|
|
135
|
+
|
|
136
|
+
// Jensen-Shannon divergence between two vectors
|
|
137
|
+
simsimd_js_f16(f16s, f16s, 1536, &distance);
|
|
138
|
+
simsimd_js_bf16(bf16s, bf16s, 1536, &distance);
|
|
139
|
+
simsimd_js_f32(f32s, f32s, 1536, &distance);
|
|
140
|
+
simsimd_js_f64(f64s, f64s, 1536, &distance);
|
|
141
|
+
|
|
142
|
+
// Kullback-Leibler divergence between two vectors
|
|
143
|
+
simsimd_kl_f16(f16s, f16s, 1536, &distance);
|
|
144
|
+
simsimd_kl_bf16(bf16s, bf16s, 1536, &distance);
|
|
145
|
+
simsimd_kl_f32(f32s, f32s, 1536, &distance);
|
|
146
|
+
simsimd_kl_f64(f64s, f64s, 1536, &distance);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
int main(int argc, char **argv) {
|
|
150
|
+
|
|
151
|
+
print_capabilities();
|
|
152
|
+
test_utilities();
|
|
153
|
+
test_distance_from_itself();
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
import test from "node:test";
|
|
24
24
|
import assert from "node:assert";
|
|
25
25
|
|
|
26
|
-
import * as simsimd from "
|
|
26
|
+
import * as simsimd from "../javascript/dist/esm/simsimd.js";
|
|
27
27
|
|
|
28
|
-
import * as fallback from "
|
|
28
|
+
import * as fallback from "../javascript/dist/esm/fallback.js";
|
|
29
29
|
|
|
30
30
|
function assertAlmostEqual(actual, expected, tolerance = 1e-6) {
|
|
31
31
|
const lowerBound = expected - tolerance;
|