usearch 2.9.2 → 2.10.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.
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,245 +0,0 @@
1
- /**
2
- * @brief SIMD-accelerated Binary Similarity Measures.
3
- * @author Ash Vardanian
4
- * @date July 1, 2023
5
- *
6
- * Contains:
7
- * - Hamming distance
8
- * - Jaccard similarity (Tanimoto coefficient)
9
- *
10
- * For datatypes:
11
- * - 8-bit bitsets
12
- *
13
- * For hardware architectures:
14
- * - Arm (NEON, SVE)
15
- * - x86 (AVX512)
16
- *
17
- * x86 intrinsics: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/
18
- * Arm intrinsics: https://developer.arm.com/architectures/instruction-sets/intrinsics/
19
- */
20
- #ifndef SIMSIMD_BINARY_H
21
- #define SIMSIMD_BINARY_H
22
-
23
- #include "types.h"
24
-
25
- #ifdef __cplusplus
26
- extern "C" {
27
- #endif
28
-
29
- inline static unsigned char simsimd_popcount_b8(simsimd_b8_t x) {
30
- static unsigned char lookup_table[] = {
31
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, //
32
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
33
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
34
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
35
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
36
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
37
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
38
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
39
- return lookup_table[x];
40
- }
41
-
42
- inline static simsimd_f32_t simsimd_serial_b8_hamming( //
43
- simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
44
- simsimd_i32_t differences = 0;
45
- for (simsimd_size_t i = 0; i != n_words; ++i)
46
- differences += simsimd_popcount_b8(a[i] ^ b[i]);
47
- return (simsimd_f32_t)differences;
48
- }
49
-
50
- inline static simsimd_f32_t simsimd_serial_b8_jaccard( //
51
- simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
52
- simsimd_i32_t intersection = 0, union_ = 0;
53
- for (simsimd_size_t i = 0; i != n_words; ++i)
54
- intersection += simsimd_popcount_b8(a[i] & b[i]), union_ += simsimd_popcount_b8(a[i] | b[i]);
55
- return (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 0;
56
- }
57
-
58
- #if SIMSIMD_TARGET_ARM
59
- #if SIMSIMD_TARGET_ARM_NEON
60
-
61
- __attribute__((target("+simd"))) //
62
- inline static simsimd_f32_t
63
- simsimd_neon_b8_hamming(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
64
- simsimd_i32_t differences = 0;
65
- simsimd_size_t i = 0;
66
- for (; i + 16 <= n_words; i += 16) {
67
- uint8x16_t a_first = vld1q_u8(a + i);
68
- uint8x16_t b_first = vld1q_u8(b + i);
69
- differences += vaddvq_u8(vcntq_u8(veorq_u8(a_first, b_first)));
70
- }
71
- // Handle the tail
72
- for (; i != n_words; ++i)
73
- differences += simsimd_popcount_b8(a[i] ^ b[i]);
74
- return (simsimd_f32_t)differences;
75
- }
76
-
77
- __attribute__((target("+simd"))) //
78
- inline static simsimd_f32_t
79
- simsimd_neon_b8_jaccard(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
80
- simsimd_i32_t intersection = 0, union_ = 0;
81
- simsimd_size_t i = 0;
82
- for (; i + 16 <= n_words; i += 16) {
83
- uint8x16_t a_first = vld1q_u8(a + i);
84
- uint8x16_t b_first = vld1q_u8(b + i);
85
- intersection += vaddvq_u8(vcntq_u8(vandq_u8(a_first, b_first)));
86
- union_ += vaddvq_u8(vcntq_u8(vorrq_u8(a_first, b_first)));
87
- }
88
- // Handle the tail
89
- for (; i != n_words; ++i)
90
- intersection += simsimd_popcount_b8(a[i] & b[i]), union_ += simsimd_popcount_b8(a[i] | b[i]);
91
- return (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 0;
92
- }
93
-
94
- #endif // SIMSIMD_TARGET_ARM_NEON
95
-
96
- #if SIMSIMD_TARGET_ARM_SVE
97
-
98
- __attribute__((target("+sve"))) //
99
- inline static simsimd_f32_t
100
- simsimd_sve_b8_hamming(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
101
- simsimd_size_t i = 0;
102
- simsimd_i32_t differences = 0;
103
- do {
104
- svbool_t pg_vec = svwhilelt_b8((unsigned int)i, (unsigned int)n_words);
105
- svuint8_t a_vec = svld1_u8(pg_vec, a + i);
106
- svuint8_t b_vec = svld1_u8(pg_vec, b + i);
107
- differences += svaddv_u8(svptrue_b8(), svcnt_u8_x(svptrue_b8(), sveor_u8_m(svptrue_b8(), a_vec, b_vec)));
108
- i += svcntb();
109
- } while (i < n_words);
110
- return (simsimd_f32_t)differences;
111
- }
112
-
113
- __attribute__((target("+sve"))) //
114
- inline static simsimd_f32_t
115
- simsimd_sve_b8_jaccard(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
116
- simsimd_size_t i = 0;
117
- simsimd_i32_t intersection = 0, union_ = 0;
118
- do {
119
- svbool_t pg_vec = svwhilelt_b8((unsigned int)i, (unsigned int)n_words);
120
- svuint8_t a_vec = svld1_u8(pg_vec, a + i);
121
- svuint8_t b_vec = svld1_u8(pg_vec, b + i);
122
- intersection += svaddv_u8(svptrue_b8(), svcnt_u8_x(svptrue_b8(), svand_u8_m(svptrue_b8(), a_vec, b_vec)));
123
- union_ += svaddv_u8(svptrue_b8(), svcnt_u8_x(svptrue_b8(), svorr_u8_m(svptrue_b8(), a_vec, b_vec)));
124
- i += svcntb();
125
- } while (i < n_words);
126
- return (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 0;
127
- }
128
-
129
- #endif // SIMSIMD_TARGET_ARM_SVE
130
-
131
- #endif // SIMSIMD_TARGET_ARM
132
-
133
- #if SIMSIMD_TARGET_X86
134
-
135
- #if SIMSIMD_TARGET_X86_AVX512
136
-
137
- __attribute__((target("avx512vpopcntdq,avx512vl,avx512bw,avx512f,bmi2"))) //
138
- inline static simsimd_f32_t
139
- simsimd_avx512_b8_hamming(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
140
- __m512i differences_vec = _mm512_setzero_si512();
141
- __m512i a_vec, b_vec;
142
-
143
- simsimd_avx512_b8_hamming_cycle:
144
- if (n_words < 64) {
145
- __mmask64 mask = _bzhi_u64(0xFFFFFFFFFFFFFFFF, n_words);
146
- a_vec = _mm512_maskz_loadu_epi8(mask, a);
147
- b_vec = _mm512_maskz_loadu_epi8(mask, b);
148
- n_words = 0;
149
- } else {
150
- a_vec = _mm512_loadu_epi8(a);
151
- b_vec = _mm512_loadu_epi8(b);
152
- a += 64, b += 64, n_words -= 64;
153
- }
154
- __m512i xor_vec = _mm512_xor_si512(a_vec, b_vec);
155
- differences_vec = _mm512_add_epi64(differences_vec, _mm512_popcnt_epi64(xor_vec));
156
- if (n_words)
157
- goto simsimd_avx512_b8_hamming_cycle;
158
-
159
- simsimd_size_t differences = _mm512_reduce_add_epi64(differences_vec);
160
- return (simsimd_f32_t)differences;
161
- }
162
-
163
- __attribute__((target("avx512vpopcntdq,avx512vl,avx512bw,avx512f,bmi2"))) //
164
- inline static simsimd_f32_t
165
- simsimd_avx512_b8_jaccard(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
166
- __m512i intersection_vec = _mm512_setzero_si512(), union_vec = _mm512_setzero_si512();
167
- __m512i a_vec, b_vec;
168
-
169
- simsimd_avx512_b8_jaccard_cycle:
170
- if (n_words < 64) {
171
- __mmask64 mask = _bzhi_u64(0xFFFFFFFFFFFFFFFF, n_words);
172
- a_vec = _mm512_maskz_loadu_epi8(mask, a);
173
- b_vec = _mm512_maskz_loadu_epi8(mask, b);
174
- n_words = 0;
175
- } else {
176
- a_vec = _mm512_loadu_epi8(a);
177
- b_vec = _mm512_loadu_epi8(b);
178
- a += 64, b += 64, n_words -= 64;
179
- }
180
- __m512i and_vec = _mm512_and_si512(a_vec, b_vec);
181
- __m512i or_vec = _mm512_or_si512(a_vec, b_vec);
182
- intersection_vec = _mm512_add_epi64(intersection_vec, _mm512_popcnt_epi64(and_vec));
183
- union_vec = _mm512_add_epi64(union_vec, _mm512_popcnt_epi64(or_vec));
184
- if (n_words)
185
- goto simsimd_avx512_b8_jaccard_cycle;
186
-
187
- simsimd_size_t intersection = _mm512_reduce_add_epi64(intersection_vec),
188
- union_ = _mm512_reduce_add_epi64(union_vec);
189
- return (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 0;
190
- }
191
-
192
- #endif // SIMSIMD_TARGET_X86_AVX512
193
-
194
- /*
195
- * @file x86_avx2_b8.h
196
- * @brief x86 AVX2 implementation of the most common similarity metrics for bitsets.
197
- * @author Ash Vardanian
198
- *
199
- * - Implements: Hamming and Jaccard similarity.
200
- * - Requires compiler capabilities: avx2.
201
- *
202
- * AVX2 provides no built-in functionality for popcount, so we use the BMI2 instruction set.
203
- * Wojciech Mu la, Nathan Kurz and Daniel Lemire propose an alternative solution based on Harley-Seal
204
- * transforms and lookup tables. Those are very fast on large vectors, but on short vectors they lose
205
- * to built-in scalar population counts. https://arxiv.org/pdf/1611.07612.pdf
206
- */
207
-
208
- #if SIMSIMD_TARGET_X86_AVX2
209
-
210
- __attribute__((target("popcnt"))) //
211
- inline static simsimd_f32_t
212
- simsimd_avx2_b8_hamming(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
213
- // x86 supports unaligned loads and works just fine with the scalar version for small vectors.
214
- simsimd_size_t differences = 0;
215
- for (; n_words >= 8; n_words -= 8, a += 8, b += 8)
216
- differences += _mm_popcnt_u64(*(simsimd_u64_t const*)a ^ *(simsimd_u64_t const*)b);
217
- for (; n_words; --n_words, ++a, ++b)
218
- differences += _mm_popcnt_u32(*a ^ *b);
219
- return (simsimd_f32_t)differences;
220
- }
221
-
222
- __attribute__((target("popcnt"))) //
223
- inline static simsimd_f32_t
224
- simsimd_avx2_b8_jaccard(simsimd_b8_t const* a, simsimd_b8_t const* b, simsimd_size_t n_words) {
225
- // x86 supports unaligned loads and works just fine with the scalar version for small vectors.
226
- simsimd_size_t intersection = 0, union_ = 0;
227
- for (; n_words >= 8; n_words -= 8, a += 8, b += 8)
228
- intersection += _mm_popcnt_u64(*(simsimd_u64_t const*)a & *(simsimd_u64_t const*)b),
229
- union_ += _mm_popcnt_u64(*(simsimd_u64_t const*)a | *(simsimd_u64_t const*)b);
230
- for (; n_words; --n_words, ++a, ++b)
231
- intersection += _mm_popcnt_u32(*a & *b), union_ += _mm_popcnt_u32(*a | *b);
232
- return (union_ != 0) ? 1 - (simsimd_f32_t)intersection / (simsimd_f32_t)union_ : 0;
233
- }
234
-
235
- #endif // SIMSIMD_TARGET_X86_AVX2
236
-
237
- #endif // SIMSIMD_TARGET_X86
238
-
239
- #undef popcount64
240
-
241
- #ifdef __cplusplus
242
- }
243
- #endif
244
-
245
- #endif
@@ -1,174 +0,0 @@
1
- /**
2
- * @brief SIMD-accelerated Similarity Measures for Complex Vectors.
3
- * @author Ash Vardanian
4
- * @date February 24, 2024
5
- *
6
- * Contains:
7
- * - Inner Product
8
- * - Cosine Distance
9
- *
10
- * For datatypes:
11
- * - 32-bit floating point numbers
12
- * - 16-bit floating point numbers
13
- *
14
- * For hardware architectures:
15
- * - Arm (NEON, SVE?)
16
- * - x86 (AVX2?, AVX512?)
17
- *
18
- * x86 intrinsics: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/
19
- * Arm intrinsics: https://developer.arm.com/architectures/instruction-sets/intrinsics/
20
- */
21
- #ifndef SIMSIMD_COMPLEX_H
22
- #define SIMSIMD_COMPLEX_H
23
-
24
- #include "types.h"
25
-
26
- #define SIMSIMD_MAKE_COMPLEX_IP(name, input_type, accumulator_type, converter, epsilon) \
27
- inline static simsimd_f32_t simsimd_##name##_##input_type##_complex_ip( \
28
- simsimd_##input_type##_t const* a, simsimd_##input_type##_t const* b, simsimd_size_t n, \
29
- simsimd_f32_t* real_out, simsimd_f32_t* imag_out) { \
30
- simsimd_##accumulator_type##_t ab_real, ab_imag; \
31
- for (simsimd_size_t i = 0; i + 2 <= n; i += 2) { \
32
- simsimd_##accumulator_type##_t ar = converter(a[i]); \
33
- simsimd_##accumulator_type##_t br = converter(b[i]); \
34
- simsimd_##accumulator_type##_t ai = converter(a[i + 1]); \
35
- simsimd_##accumulator_type##_t bi = converter(b[i + 1]); \
36
- ab_real += ar * br + ai * bi; \
37
- ab_imag += ai * br - ar * bi; \
38
- } \
39
- *real_out = ab_real; \
40
- *imag_out = ab_imag; \
41
- return 1 - ab_real; \
42
- }
43
-
44
- #define SIMSIMD_MAKE_COMPLEX_COS(name, input_type, accumulator_type, converter, epsilon) \
45
- inline static simsimd_f32_t simsimd_##name##_##input_type##_complex_cos( \
46
- simsimd_##input_type##_t const* a, simsimd_##input_type##_t const* b, simsimd_size_t n, \
47
- simsimd_f32_t* real_out, simsimd_f32_t* imag_out) { \
48
- simsimd_##accumulator_type##_t ab_real, ab_imag, a2_sum, b2_sum; \
49
- for (simsimd_size_t i = 0; i + 2 <= n; i += 2) { \
50
- simsimd_##accumulator_type##_t ar = converter(a[i]); \
51
- simsimd_##accumulator_type##_t br = converter(b[i]); \
52
- simsimd_##accumulator_type##_t ai = converter(a[i + 1]); \
53
- simsimd_##accumulator_type##_t bi = converter(b[i + 1]); \
54
- ab_real += ar * br + ai * bi; \
55
- ab_imag += ai * br - ar * bi; \
56
- a2_sum += ar * ar + ai * ai; \
57
- b2_sum += br * br + bi * bi; \
58
- } \
59
- *real_out = ab_real; \
60
- *imag_out = ab_imag; \
61
- simsimd_##accumulator_type##_t ab_angle = ab_real * SIMSIMD_RSQRT(a2_sum) * SIMSIMD_RSQRT(b2_sum); \
62
- return 1 - ab_angle; \
63
- }
64
-
65
- #ifdef __cplusplus
66
- extern "C" {
67
- #endif
68
-
69
- SIMSIMD_MAKE_COMPLEX_IP(serial, f64, f64, SIMSIMD_IDENTIFY,
70
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f64_complex_ip
71
- SIMSIMD_MAKE_COMPLEX_COS(serial, f64, f64, SIMSIMD_IDENTIFY,
72
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f64_complex_cos
73
-
74
- SIMSIMD_MAKE_COMPLEX_IP(serial, f32, f32, SIMSIMD_IDENTIFY,
75
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f32_complex_ip
76
- SIMSIMD_MAKE_COMPLEX_COS(serial, f32, f32, SIMSIMD_IDENTIFY,
77
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f32_complex_cos
78
-
79
- SIMSIMD_MAKE_COMPLEX_IP(serial, f16, f32, SIMSIMD_UNCOMPRESS_F16,
80
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f16_complex_ip
81
- SIMSIMD_MAKE_COMPLEX_COS(serial, f16, f32, SIMSIMD_UNCOMPRESS_F16,
82
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_serial_f16_complex_cos
83
-
84
- SIMSIMD_MAKE_COMPLEX_IP(accurate, f32, f64, SIMSIMD_IDENTIFY,
85
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_accurate_f32_complex_ip
86
- SIMSIMD_MAKE_COMPLEX_COS(accurate, f32, f64, SIMSIMD_IDENTIFY,
87
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_accurate_f32_complex_cos
88
-
89
- SIMSIMD_MAKE_COMPLEX_IP(accurate, f16, f64, SIMSIMD_UNCOMPRESS_F16,
90
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_accurate_f16_complex_ip
91
- SIMSIMD_MAKE_COMPLEX_COS(accurate, f16, f64, SIMSIMD_UNCOMPRESS_F16,
92
- SIMSIMD_F32_DIVISION_EPSILON) // simsimd_accurate_f16_complex_cos
93
-
94
- #if SIMSIMD_TARGET_ARM
95
- #if SIMSIMD_TARGET_ARM_NEON
96
-
97
- /*
98
- * @file arm_neon_f32.h
99
- * @brief Arm NEON implementation of the most common similarity metrics for 32-bit floating point numbers.
100
- * @author Ash Vardanian
101
- *
102
- * - Implements: Kullback-Leibler and Jensen–Shannon divergence.
103
- * - Uses `f32` for storage and `f32` for accumulation.
104
- * - Requires compiler capabilities: +simd.
105
- */
106
-
107
- __attribute__((target("+simd"))) //
108
- inline static simsimd_f32_t
109
- simsimd_neon_f32_complex_cos(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, //
110
- simsimd_f32_t* real_out, simsimd_f32_t* imag_out) {
111
- float32x4_t ab_real_vec = vdupq_n_f32(0);
112
- float32x4_t ab_imag_vec = vdupq_n_f32(0);
113
- float32x4_t a2_vec = vdupq_n_f32(0);
114
- float32x4_t b2_vec = vdupq_n_f32(0);
115
- simsimd_size_t i = 0;
116
- for (; i + 8 <= n; i += 8) {
117
- // Unpack the input arrays into real and imaginary parts:
118
- // a_real = a[::2]
119
- // a_imag = a[1::2]
120
- // b_real = b[::2]
121
- // b_imag = b[1::2]
122
- float32x4x2_t a_vec = vld2q_f32(a + i);
123
- float32x4x2_t b_vec = vld2q_f32(b + i);
124
- float32x4_t a_real_vec = a_vec.val[0];
125
- float32x4_t a_imag_vec = a_vec.val[1];
126
- float32x4_t b_real_vec = b_vec.val[0];
127
- float32x4_t b_imag_vec = b_vec.val[1];
128
-
129
- // Compute the dot product:
130
- // ab_real = sum(ar * br + ai * bi for ar, ai, br, bi in zip(a_real, a_imag, b_real, b_imag))
131
- // ab_imag = sum(ai * br - ar * bi for ar, ai, br, bi in zip(a_real, a_imag, b_real, b_imag))
132
- ab_real_vec = vfmaq_f32(ab_real_vec, a_real_vec, b_real_vec);
133
- ab_real_vec = vfmaq_f32(ab_real_vec, a_imag_vec, b_imag_vec);
134
- ab_imag_vec = vfmaq_f32(ab_imag_vec, a_imag_vec, b_real_vec);
135
- ab_imag_vec = vfmsq_f32(ab_imag_vec, a_real_vec, b_imag_vec);
136
-
137
- // Compute the vector norms:
138
- // a2 = sum(ar * ar + ai * ai for ar, ai in zip(a_real, a_imag))
139
- // b2 = sum(br * br + bi * bi for br, bi in zip(b_real, b_imag))
140
- a2_vec = vfmaq_f32(a2_vec, a_real_vec, a_real_vec);
141
- a2_vec = vfmaq_f32(a2_vec, a_imag_vec, a_imag_vec);
142
- b2_vec = vfmaq_f32(b2_vec, b_real_vec, b_real_vec);
143
- b2_vec = vfmaq_f32(b2_vec, b_imag_vec, b_imag_vec);
144
- }
145
-
146
- // Reduce horizontal sums:
147
- simsimd_f32_t ab_real = vaddvq_f32(ab_real_vec);
148
- simsimd_f32_t ab_imag = vaddvq_f32(ab_imag_vec);
149
- simsimd_f32_t a2 = vaddvq_f32(a2_vec);
150
- simsimd_f32_t b2 = vaddvq_f32(b2_vec);
151
-
152
- // Handle the tail:
153
- for (; i < n; i += 2) {
154
- simsimd_f32_t ar = a[i], ai = a[i + 1], br = b[i], bi = b[i + 1];
155
- ab_real += ar * br + ai * bi, ab_imag += ai * br - ar * bi;
156
- a2 += ar * ar + ai * ai, b2 += br * br + bi * bi;
157
- }
158
- *real_out = ab_real;
159
- *imag_out = ab_imag;
160
-
161
- // Avoid `simsimd_approximate_inverse_square_root` on Arm NEON
162
- simsimd_f32_t a2_b2_arr[2] = {a2, b2};
163
- vst1_f32(a2_b2_arr, vrsqrte_f32(vld1_f32(a2_b2_arr)));
164
- return ab_real != 0 ? 1 - ab_real * a2_b2_arr[0] * a2_b2_arr[1] : 1;
165
- }
166
-
167
- #endif // SIMSIMD_TARGET_ARM_NEON
168
- #endif // SIMSIMD_TARGET_ARM
169
-
170
- #ifdef __cplusplus
171
- }
172
- #endif
173
-
174
- #endif