usearch 2.9.2 → 2.10.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.
Files changed (172) hide show
  1. package/README.md +39 -38
  2. package/javascript/{types → dist/cjs}/usearch.d.ts +90 -115
  3. package/javascript/dist/cjs/usearch.js +531 -0
  4. package/javascript/dist/esm/usearch.d.ts +212 -0
  5. package/javascript/{usearch.js → dist/esm/usearch.js} +199 -153
  6. package/package.json +25 -23
  7. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  8. package/prebuilds/linux-arm64/usearch.node +0 -0
  9. package/prebuilds/linux-x64/usearch.node +0 -0
  10. package/prebuilds/win32-ia32/usearch.node +0 -0
  11. package/prebuilds/win32-x64/usearch.node +0 -0
  12. package/.clang-format +0 -10
  13. package/.clang-tidy +0 -60
  14. package/.cmake-format.py +0 -19
  15. package/.dockerignore +0 -93
  16. package/.gitattributes +0 -9
  17. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
  18. package/.github/ISSUE_TEMPLATE/config.yml +0 -5
  19. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -64
  20. package/.github/workflows/Dockerfile.libs +0 -36
  21. package/.github/workflows/prerelease.yml +0 -331
  22. package/.github/workflows/release.yml +0 -722
  23. package/.github/workflows/update_version.sh +0 -15
  24. package/.gitmodules +0 -9
  25. package/.releaserc +0 -90
  26. package/CITATION.cff +0 -11
  27. package/CMakeLists.txt +0 -324
  28. package/CODE_OF_CONDUCT.md +0 -128
  29. package/CONTRIBUTING.md +0 -361
  30. package/Cargo.toml +0 -19
  31. package/Dockerfile +0 -16
  32. package/VERSION +0 -1
  33. package/assets/unum.png +0 -0
  34. package/assets/usearch-approaches-transparent.png +0 -0
  35. package/assets/usearch-approaches-white.png +0 -0
  36. package/assets/usearch-neighbor-types.png +0 -0
  37. package/binding.gyp +0 -87
  38. package/build.gradle +0 -204
  39. package/build.rs +0 -18
  40. package/c/CMakeLists.txt +0 -25
  41. package/c/README.md +0 -34
  42. package/c/lib.cpp +0 -358
  43. package/c/test.c +0 -382
  44. package/c/usearch.h +0 -311
  45. package/cmake/clipp.cmake +0 -7
  46. package/cmake/config.cmake.in +0 -15
  47. package/cmake/emscripten.cmake +0 -8
  48. package/cmake/jemalloc.cmake +0 -62
  49. package/cmake/pkg-config.pc.in +0 -4
  50. package/cmake/usearchConfigVersion.cmake.in +0 -20
  51. package/conanfile.py +0 -26
  52. package/cpp/CMakeLists.txt +0 -14
  53. package/cpp/README.md +0 -161
  54. package/cpp/bench.cpp +0 -618
  55. package/cpp/test.cpp +0 -323
  56. package/fp16/CMakeLists.txt +0 -176
  57. package/fp16/LICENSE +0 -11
  58. package/fp16/README.md +0 -20
  59. package/fp16/bench/alt-element.cc +0 -89
  60. package/fp16/bench/from-alt-array.cc +0 -175
  61. package/fp16/bench/from-ieee-array.cc +0 -399
  62. package/fp16/bench/ieee-element.cc +0 -272
  63. package/fp16/bench/to-alt-array.cc +0 -91
  64. package/fp16/bench/to-ieee-array.cc +0 -303
  65. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  66. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  67. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  68. package/fp16/configure.py +0 -65
  69. package/fp16/confu.yaml +0 -8
  70. package/fp16/include/fp16/__init__.py +0 -0
  71. package/fp16/include/fp16/avx.py +0 -50
  72. package/fp16/include/fp16/avx2.py +0 -53
  73. package/fp16/include/fp16/bitcasts.h +0 -92
  74. package/fp16/include/fp16/fp16.h +0 -451
  75. package/fp16/include/fp16/psimd.h +0 -131
  76. package/fp16/include/fp16.h +0 -11
  77. package/fp16/jni/Android.mk +0 -6
  78. package/fp16/jni/Application.mk +0 -4
  79. package/fp16/test/alt-from-fp32-value.cc +0 -498
  80. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  81. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  82. package/fp16/test/alt-to-fp32-value.cc +0 -348
  83. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  84. package/fp16/test/bitcasts.cc +0 -56
  85. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  86. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  87. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  88. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  89. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  90. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  91. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  92. package/fp16/test/peachpy/stubs.py +0 -38
  93. package/fp16/test/tables.cc +0 -530
  94. package/fp16/test/tables.h +0 -13
  95. package/fp16/third-party/THHalf.h +0 -92
  96. package/fp16/third-party/eigen-half.h +0 -170
  97. package/fp16/third-party/float16-compressor.h +0 -80
  98. package/fp16/third-party/half.hpp +0 -2916
  99. package/fp16/third-party/npy-halffloat.h +0 -328
  100. package/include/usearch/index.hpp +0 -3836
  101. package/include/usearch/index_dense.hpp +0 -2004
  102. package/include/usearch/index_plugins.hpp +0 -2213
  103. package/javascript/lib.cpp +0 -341
  104. package/javascript/types/usearch.d.ts.map +0 -1
  105. package/javascript/usearch.test.js +0 -74
  106. package/package-ci.json +0 -10
  107. package/pyproject.toml +0 -51
  108. package/setup.py +0 -201
  109. package/simsimd/.releaserc +0 -86
  110. package/simsimd/CONTRIBUTING.md +0 -88
  111. package/simsimd/Cargo.lock +0 -709
  112. package/simsimd/Cargo.toml +0 -44
  113. package/simsimd/LICENSE +0 -201
  114. package/simsimd/README.md +0 -317
  115. package/simsimd/binding.gyp +0 -36
  116. package/simsimd/build.rs +0 -20
  117. package/simsimd/include/simsimd/binary.h +0 -245
  118. package/simsimd/include/simsimd/complex.h +0 -174
  119. package/simsimd/include/simsimd/probability.h +0 -548
  120. package/simsimd/include/simsimd/simsimd.h +0 -465
  121. package/simsimd/include/simsimd/spatial.h +0 -1267
  122. package/simsimd/include/simsimd/types.h +0 -208
  123. package/simsimd/javascript/bench.js +0 -127
  124. package/simsimd/javascript/fallback.ts +0 -193
  125. package/simsimd/javascript/lib.c +0 -102
  126. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  127. package/simsimd/javascript/simsimd.ts +0 -124
  128. package/simsimd/javascript/test.mjs +0 -153
  129. package/simsimd/javascript/tsconfig-base.json +0 -25
  130. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  131. package/simsimd/javascript/tsconfig-esm.json +0 -8
  132. package/simsimd/package-lock.json +0 -1688
  133. package/simsimd/package.json +0 -61
  134. package/simsimd/rust/benches/cosine.rs +0 -27
  135. package/simsimd/rust/benches/native.rs +0 -30
  136. package/simsimd/rust/benches/sqeuclidean.rs +0 -27
  137. package/simsimd/rust/lib.c +0 -45
  138. package/simsimd/rust/lib.rs +0 -550
  139. package/sqlite/README.md +0 -178
  140. package/sqlite/lib.cpp +0 -325
  141. package/stringzilla/CONTRIBUTING.md +0 -446
  142. package/stringzilla/Cargo.lock +0 -25
  143. package/stringzilla/Cargo.toml +0 -26
  144. package/stringzilla/LICENSE +0 -201
  145. package/stringzilla/README.md +0 -1422
  146. package/stringzilla/VERSION +0 -1
  147. package/stringzilla/assets/cover-strinzilla.jpeg +0 -0
  148. package/stringzilla/assets/meme-stringzilla-v2.jpeg +0 -0
  149. package/stringzilla/assets/meme-stringzilla-v3.jpeg +0 -0
  150. package/stringzilla/binding.gyp +0 -16
  151. package/stringzilla/build.rs +0 -87
  152. package/stringzilla/c/lib.c +0 -337
  153. package/stringzilla/cli/README.md +0 -65
  154. package/stringzilla/cli/__init__.py +0 -0
  155. package/stringzilla/cli/split.py +0 -105
  156. package/stringzilla/cli/wc.py +0 -117
  157. package/stringzilla/include/stringzilla/experimental.h +0 -845
  158. package/stringzilla/include/stringzilla/module.modulemap +0 -9
  159. package/stringzilla/include/stringzilla/stringzilla.h +0 -5370
  160. package/stringzilla/include/stringzilla/stringzilla.hpp +0 -3838
  161. package/stringzilla/javascript/lib.c +0 -125
  162. package/stringzilla/javascript/stringzilla.js +0 -22
  163. package/stringzilla/package-ci.json +0 -10
  164. package/stringzilla/package.json +0 -32
  165. package/stringzilla/rust/lib.rs +0 -873
  166. package/stringzilla/swift/StringProtocol+StringZilla.swift +0 -280
  167. package/stringzilla/swift/Test.swift +0 -60
  168. package/tsconfig.json +0 -21
  169. package/wasmer.toml +0 -12
  170. package/winlibinstaller.bat +0 -42
  171. /package/{simsimd/javascript/dist-package-cjs.json → javascript/dist/cjs/package.json} +0 -0
  172. /package/{simsimd/javascript/dist-package-esm.json → javascript/dist/esm/package.json} +0 -0
@@ -1,550 +0,0 @@
1
- //! # SimSIMD - Hardware-Accelerated Similarity Metrics and Distance Functions
2
- //!
3
- //! * Targets ARM NEON, SVE, x86 AVX2, AVX-512 (VNNI, FP16) hardware backends.
4
- //! * Handles `f64` double-, `f32` single-, and `f16` half-precision, `i8` integral, and binary vectors.
5
- //! * Zero-dependency header-only C 99 library with bindings for Rust and other langauges.
6
- //!
7
- //! ## Implemented distance functions include:
8
- //!
9
- //! * Euclidean (L2), Inner Distance, and Cosine (Angular) spatial distances.
10
- //! * Hamming (~ Manhattan) and Jaccard (~ Tanimoto) binary distances.
11
- //! * Kullback-Leibler and Jensen-Shannon divergences for probability distributions.
12
- //!
13
- //! ## Example
14
- //!
15
- //! ```rust
16
- //! use simsimd::SpatialSimilarity;
17
- //!
18
- //! let a = &[1, 2, 3];
19
- //! let b = &[4, 5, 6];
20
- //!
21
- //! // Compute cosine similarity
22
- //! let cosine_sim = i8::cosine(a, b);
23
- //!
24
- //! // Compute inner product distance
25
- //! let inner_product = i8::inner(a, b);
26
- //!
27
- //! // Compute squared Euclidean distance
28
- //! let sqeuclidean_dist = i8::sqeuclidean(a, b);
29
- //! ```
30
- //!
31
- //! ## Traits
32
- //!
33
- //! The `SpatialSimilarity` trait covers following methods:
34
- //!
35
- //! - `cosine(a: &[Self], b: &[Self]) -> Option<f32>`: Computes cosine similarity between two slices.
36
- //! - `inner(a: &[Self], b: &[Self]) -> Option<f32>`: Computes inner product distance between two slices.
37
- //! - `sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32>`: Computes squared Euclidean distance between two slices.
38
- //!
39
- //! The `BinarySimilarity` trait covers following methods:
40
- //!
41
- //! - `hamming(a: &[Self], b: &[Self]) -> Option<f32>`: Computes Hamming distance between two slices.
42
- //! - `jaccard(a: &[Self], b: &[Self]) -> Option<f32>`: Computes Jaccard index between two slices.
43
- //!
44
- //! The `ProbabilitySimilarity` trait covers following methods:
45
- //!
46
- //! - `jensenshannon(a: &[Self], b: &[Self]) -> Option<f32>`: Computes Jensen-Shannon divergence between two slices.
47
- //! - `kullbackleibler(a: &[Self], b: &[Self]) -> Option<f32>`: Computes Kullback-Leibler divergence between two slices.
48
- //!
49
- #![allow(non_camel_case_types)]
50
-
51
- extern "C" {
52
- fn cosine_i8(a: *const i8, b: *const i8, c: usize) -> f32;
53
- fn cosine_f16(a: *const u16, b: *const u16, c: usize) -> f32;
54
- fn cosine_f32(a: *const f32, b: *const f32, c: usize) -> f32;
55
- fn cosine_f64(a: *const f64, b: *const f64, c: usize) -> f32;
56
-
57
- fn inner_i8(a: *const i8, b: *const i8, c: usize) -> f32;
58
- fn inner_f16(a: *const u16, b: *const u16, c: usize) -> f32;
59
- fn inner_f32(a: *const f32, b: *const f32, c: usize) -> f32;
60
- fn inner_f64(a: *const f64, b: *const f64, c: usize) -> f32;
61
-
62
- fn sqeuclidean_i8(a: *const i8, b: *const i8, c: usize) -> f32;
63
- fn sqeuclidean_f16(a: *const u16, b: *const u16, c: usize) -> f32;
64
- fn sqeuclidean_f32(a: *const f32, b: *const f32, c: usize) -> f32;
65
- fn sqeuclidean_f64(a: *const f64, b: *const f64, c: usize) -> f32;
66
-
67
- fn hamming_b8(a: *const u8, b: *const u8, c: usize) -> f32;
68
- fn jaccard_b8(a: *const u8, b: *const u8, c: usize) -> f32;
69
-
70
- fn js_f16(a: *const u16, b: *const u16, c: usize) -> f32;
71
- fn js_f32(a: *const f32, b: *const f32, c: usize) -> f32;
72
- fn js_f64(a: *const f64, b: *const f64, c: usize) -> f32;
73
-
74
- fn kl_f16(a: *const u16, b: *const u16, c: usize) -> f32;
75
- fn kl_f32(a: *const f32, b: *const f32, c: usize) -> f32;
76
- fn kl_f64(a: *const f64, b: *const f64, c: usize) -> f32;
77
- }
78
-
79
- /// A half-precision floating point number.
80
- #[repr(transparent)]
81
- pub struct f16(u16);
82
-
83
- impl f16 {}
84
-
85
- /// `SpatialSimilarity` provides a set of trait methods for computing similarity
86
- /// or distance between spatial data vectors in SIMD (Single Instruction, Multiple Data) context.
87
- /// These methods can be used to calculate metrics like cosine similarity, inner product,
88
- /// and squared Euclidean distance between two slices of data.
89
- ///
90
- /// Each method takes two slices of data (a and b) and returns an Option<f32>.
91
- /// The result is `None` if the slices are not of the same length, as these operations
92
- /// require one-to-one correspondence between the elements of the slices.
93
- /// Otherwise, it returns the computed similarity or distance as `Some(f32)`.
94
- pub trait SpatialSimilarity
95
- where
96
- Self: Sized,
97
- {
98
- /// Computes the cosine similarity between two slices.
99
- /// The cosine similarity is a measure of similarity between two non-zero vectors
100
- /// of an inner product space that measures the cosine of the angle between them.
101
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32>;
102
-
103
- /// Computes the inner product (also known as dot product) between two slices.
104
- /// The inner product is the sum of the products of the corresponding entries
105
- /// of the two sequences of numbers.
106
- fn inner(a: &[Self], b: &[Self]) -> Option<f32>;
107
-
108
- /// Computes the squared Euclidean distance between two slices.
109
- /// The squared Euclidean distance is the sum of the squared differences
110
- /// between corresponding elements of the two slices.
111
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32>;
112
- }
113
-
114
- /// `BinarySimilarity` provides trait methods for computing similarity metrics
115
- /// that are commonly used with binary data vectors, such as Hamming distance
116
- /// and Jaccard index.
117
- ///
118
- /// The methods accept two slices of binary data and return an Option<f32>
119
- /// indicating the computed similarity or distance, with `None` returned if the
120
- /// slices differ in length.
121
- pub trait BinarySimilarity
122
- where
123
- Self: Sized,
124
- {
125
- /// Computes the Hamming distance between two binary data slices.
126
- /// The Hamming distance between two strings of equal length is the number of
127
- /// bits at which the corresponding values are different.
128
- fn hamming(a: &[Self], b: &[Self]) -> Option<f32>;
129
-
130
- /// Computes the Jaccard index between two bitsets represented by binary data slices.
131
- /// The Jaccard index, also known as the Jaccard similarity coefficient, is a statistic
132
- /// used for gauging the similarity and diversity of sample sets.
133
- fn jaccard(a: &[Self], b: &[Self]) -> Option<f32>;
134
- }
135
-
136
- /// `ProbabilitySimilarity` provides trait methods for computing similarity or divergence
137
- /// measures between probability distributions, such as the Jensen-Shannon divergence
138
- /// and the Kullback-Leibler divergence.
139
- ///
140
- /// These methods are particularly useful in contexts such as information theory and
141
- /// machine learning, where one often needs to measure how one probability distribution
142
- /// differs from a second, reference probability distribution.
143
- pub trait ProbabilitySimilarity
144
- where
145
- Self: Sized,
146
- {
147
- /// Computes the Jensen-Shannon divergence between two probability distributions.
148
- /// The Jensen-Shannon divergence is a method of measuring the similarity between
149
- /// two probability distributions. It is based on the Kullback-Leibler divergence,
150
- /// but is symmetric and always has a finite value.
151
- fn jensenshannon(a: &[Self], b: &[Self]) -> Option<f32>;
152
-
153
- /// Computes the Kullback-Leibler divergence between two probability distributions.
154
- /// The Kullback-Leibler divergence is a measure of how one probability distribution
155
- /// diverges from a second, expected probability distribution.
156
- fn kullbackleibler(a: &[Self], b: &[Self]) -> Option<f32>;
157
- }
158
-
159
- impl BinarySimilarity for u8 {
160
- fn hamming(a: &[Self], b: &[Self]) -> Option<f32> {
161
- if a.len() != b.len() {
162
- return None;
163
- }
164
- let operation = unsafe { hamming_b8(a.as_ptr(), b.as_ptr(), a.len()) };
165
- Some(operation)
166
- }
167
-
168
- fn jaccard(a: &[Self], b: &[Self]) -> Option<f32> {
169
- if a.len() != b.len() {
170
- return None;
171
- }
172
- let operation = unsafe { jaccard_b8(a.as_ptr(), b.as_ptr(), a.len()) };
173
- Some(operation)
174
- }
175
- }
176
-
177
- impl SpatialSimilarity for i8 {
178
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32> {
179
- if a.len() != b.len() {
180
- return None;
181
- }
182
- let operation = unsafe { cosine_i8(a.as_ptr(), b.as_ptr(), a.len()) };
183
- Some(operation)
184
- }
185
-
186
- fn inner(a: &[Self], b: &[Self]) -> Option<f32> {
187
- if a.len() != b.len() {
188
- return None;
189
- }
190
- let operation = unsafe { inner_i8(a.as_ptr(), b.as_ptr(), a.len()) };
191
- Some(operation)
192
- }
193
-
194
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32> {
195
- if a.len() != b.len() {
196
- return None;
197
- }
198
- let operation = unsafe { sqeuclidean_i8(a.as_ptr(), b.as_ptr(), a.len()) };
199
- Some(operation)
200
- }
201
- }
202
-
203
- impl SpatialSimilarity for f16 {
204
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32> {
205
- if a.len() != b.len() {
206
- return None;
207
- }
208
-
209
- // Explicitly cast `*const f16` to `*const u16`
210
- let a_ptr = a.as_ptr() as *const u16;
211
- let b_ptr = b.as_ptr() as *const u16;
212
- let operation = unsafe { cosine_f16(a_ptr, b_ptr, a.len()) };
213
- Some(operation)
214
- }
215
-
216
- fn inner(a: &[Self], b: &[Self]) -> Option<f32> {
217
- if a.len() != b.len() {
218
- return None;
219
- }
220
-
221
- // Explicitly cast `*const f16` to `*const u16`
222
- let a_ptr = a.as_ptr() as *const u16;
223
- let b_ptr = b.as_ptr() as *const u16;
224
- let operation = unsafe { inner_f16(a_ptr, b_ptr, a.len()) };
225
- Some(operation)
226
- }
227
-
228
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32> {
229
- if a.len() != b.len() {
230
- return None;
231
- }
232
-
233
- // Explicitly cast `*const f16` to `*const u16`
234
- let a_ptr = a.as_ptr() as *const u16;
235
- let b_ptr = b.as_ptr() as *const u16;
236
- let operation = unsafe { sqeuclidean_f16(a_ptr, b_ptr, a.len()) };
237
- Some(operation)
238
- }
239
- }
240
-
241
- impl SpatialSimilarity for f32 {
242
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32> {
243
- if a.len() != b.len() {
244
- return None;
245
- }
246
- let operation = unsafe { cosine_f32(a.as_ptr(), b.as_ptr(), a.len()) };
247
- Some(operation)
248
- }
249
-
250
- fn inner(a: &[Self], b: &[Self]) -> Option<f32> {
251
- if a.len() != b.len() {
252
- return None;
253
- }
254
- let operation = unsafe { inner_f32(a.as_ptr(), b.as_ptr(), a.len()) };
255
- Some(operation)
256
- }
257
-
258
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32> {
259
- if a.len() != b.len() {
260
- return None;
261
- }
262
- let operation = unsafe { sqeuclidean_f32(a.as_ptr(), b.as_ptr(), a.len()) };
263
- Some(operation)
264
- }
265
- }
266
-
267
- impl SpatialSimilarity for f64 {
268
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32> {
269
- if a.len() != b.len() {
270
- return None;
271
- }
272
- let operation = unsafe { cosine_f64(a.as_ptr(), b.as_ptr(), a.len()) };
273
- Some(operation)
274
- }
275
-
276
- fn inner(a: &[Self], b: &[Self]) -> Option<f32> {
277
- if a.len() != b.len() {
278
- return None;
279
- }
280
- let operation = unsafe { inner_f64(a.as_ptr(), b.as_ptr(), a.len()) };
281
- Some(operation)
282
- }
283
-
284
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32> {
285
- if a.len() != b.len() {
286
- return None;
287
- }
288
- let operation = unsafe { sqeuclidean_f64(a.as_ptr(), b.as_ptr(), a.len()) };
289
- Some(operation)
290
- }
291
- }
292
-
293
- impl ProbabilitySimilarity for f16 {
294
- fn jensenshannon(a: &[Self], b: &[Self]) -> Option<f32> {
295
- if a.len() != b.len() {
296
- return None;
297
- }
298
-
299
- // Explicitly cast `*const f16` to `*const u16`
300
- let a_ptr = a.as_ptr() as *const u16;
301
- let b_ptr = b.as_ptr() as *const u16;
302
- let operation = unsafe { js_f16(a_ptr, b_ptr, a.len()) };
303
- Some(operation)
304
- }
305
-
306
- fn kullbackleibler(a: &[Self], b: &[Self]) -> Option<f32> {
307
- if a.len() != b.len() {
308
- return None;
309
- }
310
-
311
- // Explicitly cast `*const f16` to `*const u16`
312
- let a_ptr = a.as_ptr() as *const u16;
313
- let b_ptr = b.as_ptr() as *const u16;
314
- let operation = unsafe { kl_f16(a_ptr, b_ptr, a.len()) };
315
- Some(operation)
316
- }
317
- }
318
-
319
- impl ProbabilitySimilarity for f32 {
320
- fn jensenshannon(a: &[Self], b: &[Self]) -> Option<f32> {
321
- if a.len() != b.len() {
322
- return None;
323
- }
324
- let operation = unsafe { js_f32(a.as_ptr(), b.as_ptr(), a.len()) };
325
- Some(operation)
326
- }
327
-
328
- fn kullbackleibler(a: &[Self], b: &[Self]) -> Option<f32> {
329
- if a.len() != b.len() {
330
- return None;
331
- }
332
- let operation = unsafe { kl_f32(a.as_ptr(), b.as_ptr(), a.len()) };
333
- Some(operation)
334
- }
335
- }
336
-
337
- impl ProbabilitySimilarity for f64 {
338
- fn jensenshannon(a: &[Self], b: &[Self]) -> Option<f32> {
339
- if a.len() != b.len() {
340
- return None;
341
- }
342
- let operation = unsafe { js_f64(a.as_ptr(), b.as_ptr(), a.len()) };
343
- Some(operation)
344
- }
345
-
346
- fn kullbackleibler(a: &[Self], b: &[Self]) -> Option<f32> {
347
- if a.len() != b.len() {
348
- return None;
349
- }
350
- let operation = unsafe { kl_f64(a.as_ptr(), b.as_ptr(), a.len()) };
351
- Some(operation)
352
- }
353
- }
354
-
355
- // In the older revisions of the library, the `SpatialSimilarity`
356
- // trait was called `SimSIMD`. The following trait provides a compatibility layer.
357
- pub trait SimSIMD
358
- where
359
- Self: Sized,
360
- {
361
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32>;
362
- fn inner(a: &[Self], b: &[Self]) -> Option<f32>;
363
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32>;
364
- }
365
-
366
- impl<T: SpatialSimilarity> SimSIMD for T {
367
- fn cosine(a: &[Self], b: &[Self]) -> Option<f32> {
368
- SpatialSimilarity::cosine(a, b)
369
- }
370
- fn inner(a: &[Self], b: &[Self]) -> Option<f32> {
371
- SpatialSimilarity::inner(a, b)
372
- }
373
- fn sqeuclidean(a: &[Self], b: &[Self]) -> Option<f32> {
374
- SpatialSimilarity::sqeuclidean(a, b)
375
- }
376
- }
377
-
378
- #[cfg(test)]
379
- mod tests {
380
- use super::*;
381
- use half::f16 as HalfF16;
382
-
383
- //
384
- fn assert_almost_equal(left: f32, right: f32, tolerance: f32) {
385
- let lower = right - tolerance;
386
- let upper = right + tolerance;
387
-
388
- assert!(left >= lower && left <= upper);
389
- }
390
-
391
- #[test]
392
- fn test_cosine_i8() {
393
- let a = &[3, 97, 127];
394
- let b = &[3, 97, 127];
395
-
396
- if let Some(result) = SimSIMD::cosine(a, b) {
397
- println!("The result of cosine_i8 is {:.8}", result);
398
- assert_almost_equal(0.00012027938, result, 0.01);
399
- }
400
- }
401
-
402
- #[test]
403
- fn test_cosine_f32() {
404
- let a = &[1.0, 2.0, 3.0];
405
- let b = &[4.0, 5.0, 6.0];
406
-
407
- if let Some(result) = SimSIMD::cosine(a, b) {
408
- println!("The result of cosine_f32 is {:.8}", result);
409
- assert_almost_equal(0.025, result, 0.01);
410
- }
411
- }
412
-
413
- #[test]
414
- fn test_inner_i8() {
415
- let a = &[1, 2, 3];
416
- let b = &[4, 5, 6];
417
-
418
- if let Some(result) = SimSIMD::inner(a, b) {
419
- println!("The result of inner_i8 is {:.8}", result);
420
- assert_almost_equal(0.029403687, result, 0.01);
421
- }
422
- }
423
-
424
- #[test]
425
- fn test_inner_f32() {
426
- let a = &[1.0, 2.0, 3.0];
427
- let b = &[4.0, 5.0, 6.0];
428
-
429
- if let Some(result) = SimSIMD::inner(a, b) {
430
- println!("The result of inner_f32 is {:.8}", result);
431
- assert_almost_equal(-31.0, result, 0.01);
432
- }
433
- }
434
-
435
- #[test]
436
- fn test_sqeuclidean_i8() {
437
- let a = &[1, 2, 3];
438
- let b = &[4, 5, 6];
439
-
440
- if let Some(result) = SimSIMD::sqeuclidean(a, b) {
441
- println!("The result of sqeuclidean_i8 is {:.8}", result);
442
- assert_almost_equal(27.0, result, 0.01);
443
- }
444
- }
445
-
446
- #[test]
447
- fn test_sqeuclidean_f32() {
448
- let a = &[1.0, 2.0, 3.0];
449
- let b = &[4.0, 5.0, 6.0];
450
-
451
- if let Some(result) = SimSIMD::sqeuclidean(a, b) {
452
- println!("The result of sqeuclidean_f32 is {:.8}", result);
453
- assert_almost_equal(27.0, result, 0.01);
454
- }
455
- }
456
-
457
- // Adding new tests for bit-level distances
458
- #[test]
459
- fn test_hamming_u8() {
460
- let a = &[0b01010101, 0b11110000, 0b10101010]; // Binary representations for clarity
461
- let b = &[0b01010101, 0b11110000, 0b10101010];
462
-
463
- if let Some(result) = BinarySimilarity::hamming(a, b) {
464
- println!("The result of hamming_u8 is {:.8}", result);
465
- assert_almost_equal(0.0, result, 0.01); // Perfect match
466
- }
467
- }
468
-
469
- #[test]
470
- fn test_jaccard_u8() {
471
- // For binary data, treat each byte as a set of bits
472
- let a = &[0b11110000, 0b00001111, 0b10101010];
473
- let b = &[0b11110000, 0b00001111, 0b01010101];
474
-
475
- if let Some(result) = BinarySimilarity::jaccard(a, b) {
476
- println!("The result of jaccard_u8 is {:.8}", result);
477
- assert_almost_equal(0.5, result, 0.01); // Example value
478
- }
479
- }
480
-
481
- // Adding new tests for probability similarities
482
- #[test]
483
- fn test_js_f32() {
484
- let a = &[0.1, 0.9, 0.0];
485
- let b = &[0.2, 0.8, 0.0];
486
-
487
- if let Some(result) = ProbabilitySimilarity::jensenshannon(a, b) {
488
- println!("The result of js_f32 is {:.8}", result);
489
- assert_almost_equal(0.01, result, 0.01); // Example value
490
- }
491
- }
492
-
493
- #[test]
494
- fn test_kl_f32() {
495
- let a = &[0.1, 0.9, 0.0];
496
- let b = &[0.2, 0.8, 0.0];
497
-
498
- if let Some(result) = ProbabilitySimilarity::kullbackleibler(a, b) {
499
- println!("The result of kl_f32 is {:.8}", result);
500
- assert_almost_equal(0.036, result, 0.01); // Example value
501
- }
502
- }
503
-
504
- #[test]
505
- fn test_cosine_f16_same() {
506
- // Assuming these u16 values represent f16 bit patterns, and they are identical
507
- let a_u16: &[u16] = &[15360, 16384, 17408]; // Corresponding to some f16 values
508
- let b_u16: &[u16] = &[15360, 16384, 17408]; // Same as above for simplicity
509
-
510
- // Reinterpret cast from &[u16] to &[f16]
511
- // SAFETY: This is safe as long as the representations are guaranteed to be identical,
512
- // which they are for transparent structs wrapping the same type.
513
- let a_f16: &[f16] =
514
- unsafe { std::slice::from_raw_parts(a_u16.as_ptr() as *const f16, a_u16.len()) };
515
- let b_f16: &[f16] =
516
- unsafe { std::slice::from_raw_parts(b_u16.as_ptr() as *const f16, b_u16.len()) };
517
-
518
- if let Some(result) = SimSIMD::cosine(a_f16, b_f16) {
519
- println!("The result of cosine_f16 is {:.8}", result);
520
- assert_almost_equal(0.0, result, 0.01); // Example value, adjust according to actual expected value
521
- }
522
- }
523
-
524
- #[test]
525
- fn test_cosine_f16_interop() {
526
- let a_half: Vec<HalfF16> = vec![1.0, 2.0, 3.0]
527
- .iter()
528
- .map(|&x| HalfF16::from_f32(x))
529
- .collect();
530
- let b_half: Vec<HalfF16> = vec![4.0, 5.0, 6.0]
531
- .iter()
532
- .map(|&x| HalfF16::from_f32(x))
533
- .collect();
534
-
535
- // SAFETY: This is safe as long as the memory representations are guaranteed to be identical,
536
- // which they are due to both being #[repr(transparent)] wrappers around u16.
537
- let a_simsimd: &[f16] =
538
- unsafe { std::slice::from_raw_parts(a_half.as_ptr() as *const f16, a_half.len()) };
539
- let b_simsimd: &[f16] =
540
- unsafe { std::slice::from_raw_parts(b_half.as_ptr() as *const f16, b_half.len()) };
541
-
542
- // Use the reinterpret-casted slices with your SpatialSimilarity implementation
543
- if let Some(result) = SpatialSimilarity::cosine(a_simsimd, b_simsimd) {
544
- // Expected value might need adjustment depending on actual cosine functionality
545
- // Assuming identical vectors yield cosine similarity of 1.0
546
- println!("The result of cosine_f16 (interop) is {:.8}", result);
547
- assert_almost_equal(0.025, result, 0.01);
548
- }
549
- }
550
- }