usearch 2.21.3 → 2.25.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 (602) hide show
  1. package/README.md +24 -24
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +7 -7
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +83 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +235 -52
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/dist/cjs/usearch.d.ts +8 -3
  16. package/javascript/dist/cjs/usearch.js +12 -4
  17. package/javascript/dist/esm/usearch.d.ts +8 -3
  18. package/javascript/dist/esm/usearch.js +12 -4
  19. package/javascript/lib.cpp +17 -0
  20. package/javascript/usearch.ts +14 -6
  21. package/numkong/.clang-tidy +30 -0
  22. package/{simsimd → numkong}/.cmake-format.py +18 -0
  23. package/numkong/.editorconfig +12 -0
  24. package/numkong/.git-blame-ignore-revs +123 -0
  25. package/numkong/.mailmap +15 -0
  26. package/numkong/.spi.yml +11 -0
  27. package/numkong/.swift-format +14 -0
  28. package/numkong/CITATION.cff +81 -0
  29. package/numkong/CONTRIBUTING.md +500 -0
  30. package/numkong/Cargo.toml +54 -0
  31. package/numkong/MANIFEST.in +8 -0
  32. package/numkong/Package.swift +84 -0
  33. package/numkong/README.md +569 -0
  34. package/numkong/bench/README.md +217 -0
  35. package/numkong/bench/bench-browser.html +323 -0
  36. package/numkong/bench/bench.cpp +344 -0
  37. package/numkong/bench/bench.hpp +816 -0
  38. package/numkong/bench/bench.js +148 -0
  39. package/numkong/bench/bench.mjs +616 -0
  40. package/numkong/bench/bench_attention.cpp +113 -0
  41. package/numkong/bench/bench_cast.cpp +264 -0
  42. package/numkong/bench/bench_cross_amx.cpp +62 -0
  43. package/numkong/bench/bench_cross_arm.cpp +245 -0
  44. package/numkong/bench/bench_cross_blas.cpp +309 -0
  45. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  46. package/numkong/bench/bench_cross_power.cpp +84 -0
  47. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  48. package/numkong/bench/bench_cross_serial.cpp +151 -0
  49. package/numkong/bench/bench_cross_sme.cpp +163 -0
  50. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  51. package/numkong/bench/bench_cross_x86.cpp +455 -0
  52. package/numkong/bench/bench_curved.cpp +210 -0
  53. package/numkong/bench/bench_dot.cpp +315 -0
  54. package/numkong/bench/bench_each.cpp +503 -0
  55. package/numkong/bench/bench_geospatial.cpp +112 -0
  56. package/numkong/bench/bench_maxsim.cpp +154 -0
  57. package/numkong/bench/bench_mesh.cpp +148 -0
  58. package/numkong/bench/bench_probability.cpp +60 -0
  59. package/numkong/bench/bench_reduce.cpp +371 -0
  60. package/numkong/bench/bench_set.cpp +73 -0
  61. package/numkong/bench/bench_sparse.cpp +198 -0
  62. package/numkong/bench/bench_spatial.cpp +347 -0
  63. package/numkong/bench/bench_trigonometry.cpp +137 -0
  64. package/numkong/bench/swift/Bench.swift +506 -0
  65. package/numkong/binding.gyp +169 -0
  66. package/numkong/build.rs +484 -0
  67. package/numkong/c/dispatch.h +512 -0
  68. package/numkong/c/dispatch_bf16.c +447 -0
  69. package/numkong/c/dispatch_bf16c.c +52 -0
  70. package/numkong/c/dispatch_e2m3.c +296 -0
  71. package/numkong/c/dispatch_e3m2.c +284 -0
  72. package/numkong/c/dispatch_e4m3.c +318 -0
  73. package/numkong/c/dispatch_e5m2.c +316 -0
  74. package/numkong/c/dispatch_f16.c +452 -0
  75. package/numkong/c/dispatch_f16c.c +58 -0
  76. package/numkong/c/dispatch_f32.c +434 -0
  77. package/numkong/c/dispatch_f32c.c +99 -0
  78. package/numkong/c/dispatch_f64.c +348 -0
  79. package/numkong/c/dispatch_f64c.c +98 -0
  80. package/numkong/c/dispatch_i16.c +96 -0
  81. package/numkong/c/dispatch_i32.c +89 -0
  82. package/numkong/c/dispatch_i4.c +153 -0
  83. package/numkong/c/dispatch_i64.c +86 -0
  84. package/numkong/c/dispatch_i8.c +348 -0
  85. package/numkong/c/dispatch_other.c +348 -0
  86. package/numkong/c/dispatch_u1.c +193 -0
  87. package/numkong/c/dispatch_u16.c +124 -0
  88. package/numkong/c/dispatch_u32.c +118 -0
  89. package/numkong/c/dispatch_u4.c +153 -0
  90. package/numkong/c/dispatch_u64.c +102 -0
  91. package/numkong/c/dispatch_u8.c +364 -0
  92. package/numkong/c/numkong.c +940 -0
  93. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  94. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  95. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  96. package/numkong/cmake/nk_math_lib.cmake +46 -0
  97. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  99. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  100. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  101. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  102. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  103. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  104. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  105. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  106. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  107. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  108. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  109. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  110. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  111. package/numkong/include/README.md +643 -0
  112. package/numkong/include/module.modulemap +129 -0
  113. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  114. package/numkong/include/numkong/attention/sme.h +2075 -0
  115. package/numkong/include/numkong/attention.h +49 -0
  116. package/numkong/include/numkong/capabilities.h +930 -0
  117. package/numkong/include/numkong/cast/README.md +262 -0
  118. package/numkong/include/numkong/cast/diamond.h +64 -0
  119. package/numkong/include/numkong/cast/haswell.h +823 -0
  120. package/numkong/include/numkong/cast/icelake.h +475 -0
  121. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  122. package/numkong/include/numkong/cast/neon.h +1174 -0
  123. package/numkong/include/numkong/cast/powervsx.h +449 -0
  124. package/numkong/include/numkong/cast/rvv.h +970 -0
  125. package/numkong/include/numkong/cast/sapphire.h +262 -0
  126. package/numkong/include/numkong/cast/serial.h +2336 -0
  127. package/numkong/include/numkong/cast/skylake.h +915 -0
  128. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  129. package/numkong/include/numkong/cast.h +254 -0
  130. package/numkong/include/numkong/cast.hpp +44 -0
  131. package/numkong/include/numkong/curved/README.md +223 -0
  132. package/numkong/include/numkong/curved/genoa.h +182 -0
  133. package/numkong/include/numkong/curved/haswell.h +276 -0
  134. package/numkong/include/numkong/curved/neon.h +329 -0
  135. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  136. package/numkong/include/numkong/curved/rvv.h +305 -0
  137. package/numkong/include/numkong/curved/serial.h +207 -0
  138. package/numkong/include/numkong/curved/skylake.h +457 -0
  139. package/numkong/include/numkong/curved/smef64.h +530 -0
  140. package/numkong/include/numkong/curved.h +513 -0
  141. package/numkong/include/numkong/curved.hpp +144 -0
  142. package/numkong/include/numkong/dot/README.md +442 -0
  143. package/numkong/include/numkong/dot/alder.h +563 -0
  144. package/numkong/include/numkong/dot/diamond.h +158 -0
  145. package/numkong/include/numkong/dot/genoa.h +289 -0
  146. package/numkong/include/numkong/dot/haswell.h +1723 -0
  147. package/numkong/include/numkong/dot/icelake.h +997 -0
  148. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  149. package/numkong/include/numkong/dot/neon.h +869 -0
  150. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  151. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  152. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  153. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  154. package/numkong/include/numkong/dot/powervsx.h +752 -0
  155. package/numkong/include/numkong/dot/rvv.h +722 -0
  156. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  157. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  158. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  159. package/numkong/include/numkong/dot/sapphire.h +141 -0
  160. package/numkong/include/numkong/dot/serial.h +874 -0
  161. package/numkong/include/numkong/dot/sierra.h +405 -0
  162. package/numkong/include/numkong/dot/skylake.h +1116 -0
  163. package/numkong/include/numkong/dot/sve.h +420 -0
  164. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  165. package/numkong/include/numkong/dot/svehalf.h +168 -0
  166. package/numkong/include/numkong/dot/svesdot.h +90 -0
  167. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  168. package/numkong/include/numkong/dot.h +1136 -0
  169. package/numkong/include/numkong/dot.hpp +94 -0
  170. package/numkong/include/numkong/dots/README.md +496 -0
  171. package/numkong/include/numkong/dots/alder.h +117 -0
  172. package/numkong/include/numkong/dots/diamond.h +86 -0
  173. package/numkong/include/numkong/dots/genoa.h +100 -0
  174. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  175. package/numkong/include/numkong/dots/haswell.h +310 -0
  176. package/numkong/include/numkong/dots/icelake.h +180 -0
  177. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  178. package/numkong/include/numkong/dots/neon.h +123 -0
  179. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  180. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  181. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  182. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  183. package/numkong/include/numkong/dots/powervsx.h +194 -0
  184. package/numkong/include/numkong/dots/rvv.h +2593 -0
  185. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  186. package/numkong/include/numkong/dots/serial.h +2867 -0
  187. package/numkong/include/numkong/dots/sierra.h +100 -0
  188. package/numkong/include/numkong/dots/skylake.h +207 -0
  189. package/numkong/include/numkong/dots/sme.h +5041 -0
  190. package/numkong/include/numkong/dots/smebi32.h +477 -0
  191. package/numkong/include/numkong/dots/smef64.h +1328 -0
  192. package/numkong/include/numkong/dots/smehalf.h +47 -0
  193. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  194. package/numkong/include/numkong/dots.h +3110 -0
  195. package/numkong/include/numkong/dots.hpp +641 -0
  196. package/numkong/include/numkong/each/README.md +465 -0
  197. package/numkong/include/numkong/each/haswell.h +1658 -0
  198. package/numkong/include/numkong/each/icelake.h +272 -0
  199. package/numkong/include/numkong/each/neon.h +1138 -0
  200. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  201. package/numkong/include/numkong/each/neonhalf.h +318 -0
  202. package/numkong/include/numkong/each/rvv.h +1121 -0
  203. package/numkong/include/numkong/each/sapphire.h +343 -0
  204. package/numkong/include/numkong/each/serial.h +282 -0
  205. package/numkong/include/numkong/each/skylake.h +1562 -0
  206. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  207. package/numkong/include/numkong/each.h +2232 -0
  208. package/numkong/include/numkong/each.hpp +434 -0
  209. package/numkong/include/numkong/geospatial/README.md +147 -0
  210. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  211. package/numkong/include/numkong/geospatial/neon.h +615 -0
  212. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  213. package/numkong/include/numkong/geospatial/serial.h +309 -0
  214. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  215. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  216. package/numkong/include/numkong/geospatial.h +453 -0
  217. package/numkong/include/numkong/geospatial.hpp +235 -0
  218. package/numkong/include/numkong/matrix.hpp +336 -0
  219. package/numkong/include/numkong/maxsim/README.md +187 -0
  220. package/numkong/include/numkong/maxsim/alder.h +511 -0
  221. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  222. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  223. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  224. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  225. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  226. package/numkong/include/numkong/maxsim/serial.h +490 -0
  227. package/numkong/include/numkong/maxsim/sme.h +993 -0
  228. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  229. package/numkong/include/numkong/maxsim.h +571 -0
  230. package/numkong/include/numkong/maxsim.hpp +133 -0
  231. package/numkong/include/numkong/mesh/README.md +219 -0
  232. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  233. package/numkong/include/numkong/mesh/neon.h +1821 -0
  234. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  235. package/numkong/include/numkong/mesh/rvv.h +936 -0
  236. package/numkong/include/numkong/mesh/serial.h +721 -0
  237. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  238. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  239. package/numkong/include/numkong/mesh.h +666 -0
  240. package/numkong/include/numkong/mesh.hpp +701 -0
  241. package/numkong/include/numkong/numkong.h +78 -0
  242. package/numkong/include/numkong/numkong.hpp +58 -0
  243. package/numkong/include/numkong/probability/README.md +177 -0
  244. package/numkong/include/numkong/probability/haswell.h +267 -0
  245. package/numkong/include/numkong/probability/neon.h +255 -0
  246. package/numkong/include/numkong/probability/rvv.h +414 -0
  247. package/numkong/include/numkong/probability/serial.h +181 -0
  248. package/numkong/include/numkong/probability/skylake.h +324 -0
  249. package/numkong/include/numkong/probability.h +380 -0
  250. package/numkong/include/numkong/probability.hpp +120 -0
  251. package/numkong/include/numkong/random.h +50 -0
  252. package/numkong/include/numkong/random.hpp +285 -0
  253. package/numkong/include/numkong/reduce/README.md +552 -0
  254. package/numkong/include/numkong/reduce/alder.h +636 -0
  255. package/numkong/include/numkong/reduce/genoa.h +201 -0
  256. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  257. package/numkong/include/numkong/reduce/icelake.h +549 -0
  258. package/numkong/include/numkong/reduce/neon.h +3980 -0
  259. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  260. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  261. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  262. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  263. package/numkong/include/numkong/reduce/serial.h +753 -0
  264. package/numkong/include/numkong/reduce/sierra.h +338 -0
  265. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  266. package/numkong/include/numkong/reduce/sve.h +52 -0
  267. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  268. package/numkong/include/numkong/reduce.h +1582 -0
  269. package/numkong/include/numkong/reduce.hpp +778 -0
  270. package/numkong/include/numkong/scalar/README.md +89 -0
  271. package/numkong/include/numkong/scalar/haswell.h +122 -0
  272. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  273. package/numkong/include/numkong/scalar/neon.h +122 -0
  274. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  275. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  276. package/numkong/include/numkong/scalar/rvv.h +211 -0
  277. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  278. package/numkong/include/numkong/scalar/serial.h +332 -0
  279. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  280. package/numkong/include/numkong/scalar.h +696 -0
  281. package/numkong/include/numkong/set/README.md +179 -0
  282. package/numkong/include/numkong/set/haswell.h +334 -0
  283. package/numkong/include/numkong/set/icelake.h +485 -0
  284. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  285. package/numkong/include/numkong/set/neon.h +363 -0
  286. package/numkong/include/numkong/set/powervsx.h +326 -0
  287. package/numkong/include/numkong/set/rvv.h +226 -0
  288. package/numkong/include/numkong/set/rvvbb.h +117 -0
  289. package/numkong/include/numkong/set/serial.h +174 -0
  290. package/numkong/include/numkong/set/sve.h +187 -0
  291. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  292. package/numkong/include/numkong/set.h +471 -0
  293. package/numkong/include/numkong/set.hpp +114 -0
  294. package/numkong/include/numkong/sets/README.md +149 -0
  295. package/numkong/include/numkong/sets/haswell.h +63 -0
  296. package/numkong/include/numkong/sets/icelake.h +66 -0
  297. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  298. package/numkong/include/numkong/sets/neon.h +61 -0
  299. package/numkong/include/numkong/sets/powervsx.h +65 -0
  300. package/numkong/include/numkong/sets/serial.h +43 -0
  301. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  302. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  303. package/numkong/include/numkong/sets.h +382 -0
  304. package/numkong/include/numkong/sparse/README.md +156 -0
  305. package/numkong/include/numkong/sparse/icelake.h +463 -0
  306. package/numkong/include/numkong/sparse/neon.h +288 -0
  307. package/numkong/include/numkong/sparse/serial.h +117 -0
  308. package/numkong/include/numkong/sparse/sve2.h +504 -0
  309. package/numkong/include/numkong/sparse/turin.h +322 -0
  310. package/numkong/include/numkong/sparse.h +363 -0
  311. package/numkong/include/numkong/sparse.hpp +113 -0
  312. package/numkong/include/numkong/spatial/README.md +439 -0
  313. package/numkong/include/numkong/spatial/alder.h +604 -0
  314. package/numkong/include/numkong/spatial/diamond.h +240 -0
  315. package/numkong/include/numkong/spatial/genoa.h +222 -0
  316. package/numkong/include/numkong/spatial/haswell.h +979 -0
  317. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  318. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  319. package/numkong/include/numkong/spatial/neon.h +846 -0
  320. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  321. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  322. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  323. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  324. package/numkong/include/numkong/spatial/rvv.h +991 -0
  325. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  326. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  327. package/numkong/include/numkong/spatial/serial.h +347 -0
  328. package/numkong/include/numkong/spatial/sierra.h +516 -0
  329. package/numkong/include/numkong/spatial/skylake.h +605 -0
  330. package/numkong/include/numkong/spatial/sve.h +246 -0
  331. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  332. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  333. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  334. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  335. package/numkong/include/numkong/spatial.h +1681 -0
  336. package/numkong/include/numkong/spatial.hpp +183 -0
  337. package/numkong/include/numkong/spatials/README.md +580 -0
  338. package/numkong/include/numkong/spatials/alder.h +94 -0
  339. package/numkong/include/numkong/spatials/diamond.h +82 -0
  340. package/numkong/include/numkong/spatials/genoa.h +94 -0
  341. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  342. package/numkong/include/numkong/spatials/haswell.h +219 -0
  343. package/numkong/include/numkong/spatials/icelake.h +113 -0
  344. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  345. package/numkong/include/numkong/spatials/neon.h +109 -0
  346. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  347. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  348. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  349. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  350. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  351. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  352. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  353. package/numkong/include/numkong/spatials/serial.h +248 -0
  354. package/numkong/include/numkong/spatials/sierra.h +96 -0
  355. package/numkong/include/numkong/spatials/skylake.h +184 -0
  356. package/numkong/include/numkong/spatials/sme.h +1927 -0
  357. package/numkong/include/numkong/spatials/smef64.h +483 -0
  358. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  359. package/numkong/include/numkong/spatials.h +3374 -0
  360. package/numkong/include/numkong/spatials.hpp +509 -0
  361. package/numkong/include/numkong/tensor.hpp +1981 -0
  362. package/numkong/include/numkong/trigonometry/README.md +184 -0
  363. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  364. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  365. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  366. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  367. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  368. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  369. package/numkong/include/numkong/trigonometry.h +467 -0
  370. package/numkong/include/numkong/trigonometry.hpp +166 -0
  371. package/numkong/include/numkong/types.h +1695 -0
  372. package/numkong/include/numkong/types.hpp +6027 -0
  373. package/numkong/include/numkong/vector.hpp +766 -0
  374. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  375. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  376. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  377. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  378. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  380. package/numkong/javascript/README.md +254 -0
  381. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  382. package/numkong/javascript/numkong-browser.ts +40 -0
  383. package/numkong/javascript/numkong-wasm.ts +750 -0
  384. package/numkong/javascript/numkong.c +712 -0
  385. package/numkong/javascript/numkong.ts +613 -0
  386. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  387. package/numkong/javascript/tsconfig-cjs.json +13 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  389. package/numkong/javascript/types.ts +784 -0
  390. package/numkong/numkong.gypi +104 -0
  391. package/numkong/package.json +108 -0
  392. package/numkong/probes/arm_neon.c +8 -0
  393. package/numkong/probes/arm_neon_bfdot.c +9 -0
  394. package/numkong/probes/arm_neon_fhm.c +9 -0
  395. package/numkong/probes/arm_neon_half.c +8 -0
  396. package/numkong/probes/arm_neon_sdot.c +9 -0
  397. package/numkong/probes/arm_neonfp8.c +9 -0
  398. package/numkong/probes/arm_sme.c +16 -0
  399. package/numkong/probes/arm_sme2.c +16 -0
  400. package/numkong/probes/arm_sme2p1.c +16 -0
  401. package/numkong/probes/arm_sme_bf16.c +16 -0
  402. package/numkong/probes/arm_sme_bi32.c +16 -0
  403. package/numkong/probes/arm_sme_f64.c +16 -0
  404. package/numkong/probes/arm_sme_fa64.c +14 -0
  405. package/numkong/probes/arm_sme_half.c +16 -0
  406. package/numkong/probes/arm_sme_lut2.c +15 -0
  407. package/numkong/probes/arm_sve.c +18 -0
  408. package/numkong/probes/arm_sve2.c +20 -0
  409. package/numkong/probes/arm_sve2p1.c +18 -0
  410. package/numkong/probes/arm_sve_bfdot.c +20 -0
  411. package/numkong/probes/arm_sve_half.c +18 -0
  412. package/numkong/probes/arm_sve_sdot.c +21 -0
  413. package/numkong/probes/loongarch_lasx.c +12 -0
  414. package/numkong/probes/power_vsx.c +12 -0
  415. package/numkong/probes/probe.js +127 -0
  416. package/numkong/probes/riscv_rvv.c +14 -0
  417. package/numkong/probes/riscv_rvv_bb.c +15 -0
  418. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  419. package/numkong/probes/riscv_rvv_half.c +14 -0
  420. package/numkong/probes/wasm_v128relaxed.c +11 -0
  421. package/numkong/probes/x86_alder.c +17 -0
  422. package/numkong/probes/x86_diamond.c +17 -0
  423. package/numkong/probes/x86_genoa.c +17 -0
  424. package/numkong/probes/x86_graniteamx.c +19 -0
  425. package/numkong/probes/x86_haswell.c +11 -0
  426. package/numkong/probes/x86_icelake.c +17 -0
  427. package/numkong/probes/x86_sapphire.c +16 -0
  428. package/numkong/probes/x86_sapphireamx.c +18 -0
  429. package/numkong/probes/x86_sierra.c +17 -0
  430. package/numkong/probes/x86_skylake.c +15 -0
  431. package/numkong/probes/x86_turin.c +17 -0
  432. package/numkong/rust/README.md +698 -0
  433. package/numkong/rust/capabilities.rs +96 -0
  434. package/numkong/rust/cast.rs +314 -0
  435. package/numkong/rust/curved.rs +391 -0
  436. package/numkong/rust/each.rs +2721 -0
  437. package/numkong/rust/geospatial.rs +343 -0
  438. package/numkong/rust/matrix.rs +5424 -0
  439. package/numkong/rust/maxsim.rs +540 -0
  440. package/numkong/rust/mesh.rs +837 -0
  441. package/numkong/rust/numkong.rs +409 -0
  442. package/numkong/rust/probability.rs +272 -0
  443. package/numkong/rust/reduce.rs +1249 -0
  444. package/numkong/rust/set.rs +194 -0
  445. package/numkong/rust/sparse.rs +513 -0
  446. package/numkong/rust/spatial.rs +1815 -0
  447. package/numkong/rust/tensor.rs +7565 -0
  448. package/numkong/rust/types.rs +3666 -0
  449. package/numkong/rust/vector.rs +1899 -0
  450. package/numkong/rustfmt.toml +2 -0
  451. package/numkong/swift/Matrix.swift +1388 -0
  452. package/numkong/swift/MaxSim.swift +151 -0
  453. package/numkong/swift/NumKong.swift +283 -0
  454. package/numkong/swift/Numerics.swift +329 -0
  455. package/numkong/swift/README.md +433 -0
  456. package/numkong/swift/Scalar.swift +741 -0
  457. package/numkong/swift/Tensor.swift +209 -0
  458. package/numkong/test/README.md +315 -0
  459. package/numkong/test/playwright.config.ts +16 -0
  460. package/numkong/test/swift/Test.swift +534 -0
  461. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  462. package/numkong/test/test-browser-bundle.html +188 -0
  463. package/numkong/test/test-browser-runner.mjs +43 -0
  464. package/numkong/test/test-browser.html +305 -0
  465. package/numkong/test/test-dtypes.mjs +453 -0
  466. package/numkong/test/test-wasm.mjs +267 -0
  467. package/numkong/test/test.cpp +442 -0
  468. package/numkong/test/test.hpp +580 -0
  469. package/numkong/test/test.mjs +363 -0
  470. package/numkong/test/test_base.py +1041 -0
  471. package/numkong/test/test_cast.cpp +242 -0
  472. package/numkong/test/test_cross.hpp +551 -0
  473. package/numkong/test/test_cross.py +467 -0
  474. package/numkong/test/test_cross_amx.cpp +50 -0
  475. package/numkong/test/test_cross_arm.cpp +225 -0
  476. package/numkong/test/test_cross_blas.cpp +354 -0
  477. package/numkong/test/test_cross_loongarch.cpp +90 -0
  478. package/numkong/test/test_cross_power.cpp +73 -0
  479. package/numkong/test/test_cross_rvv.cpp +109 -0
  480. package/numkong/test/test_cross_serial.cpp +181 -0
  481. package/numkong/test/test_cross_sme.cpp +148 -0
  482. package/numkong/test/test_cross_wasm.cpp +141 -0
  483. package/numkong/test/test_cross_x86.cpp +442 -0
  484. package/numkong/test/test_curved.cpp +182 -0
  485. package/numkong/test/test_curved.py +207 -0
  486. package/numkong/test/test_dot.cpp +353 -0
  487. package/numkong/test/test_dot.py +296 -0
  488. package/numkong/test/test_each.cpp +437 -0
  489. package/numkong/test/test_each.py +756 -0
  490. package/numkong/test/test_geospatial.cpp +155 -0
  491. package/numkong/test/test_geospatial.py +241 -0
  492. package/numkong/test/test_maxsim.cpp +138 -0
  493. package/numkong/test/test_maxsim.py +209 -0
  494. package/numkong/test/test_mesh.cpp +203 -0
  495. package/numkong/test/test_mesh.py +394 -0
  496. package/numkong/test/test_probability.cpp +136 -0
  497. package/numkong/test/test_probability.py +166 -0
  498. package/numkong/test/test_reduce.cpp +563 -0
  499. package/numkong/test/test_reduce.py +781 -0
  500. package/numkong/test/test_set.cpp +151 -0
  501. package/numkong/test/test_set.py +120 -0
  502. package/numkong/test/test_similarities.py +579 -0
  503. package/numkong/test/test_sparse.cpp +121 -0
  504. package/numkong/test/test_sparse.py +118 -0
  505. package/numkong/test/test_spatial.cpp +518 -0
  506. package/numkong/test/test_spatial.py +269 -0
  507. package/numkong/test/test_tensor.cpp +884 -0
  508. package/numkong/test/test_tensor.py +1417 -0
  509. package/numkong/test/test_trigonometry.cpp +156 -0
  510. package/numkong/test/test_trigonometry.py +180 -0
  511. package/package.json +7 -8
  512. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  513. package/prebuilds/linux-arm64/usearch.node +0 -0
  514. package/prebuilds/linux-x64/usearch.node +0 -0
  515. package/fp16/CMakeLists.txt +0 -176
  516. package/fp16/LICENSE +0 -11
  517. package/fp16/README.md +0 -20
  518. package/fp16/bench/alt-element.cc +0 -89
  519. package/fp16/bench/from-alt-array.cc +0 -175
  520. package/fp16/bench/from-ieee-array.cc +0 -399
  521. package/fp16/bench/ieee-element.cc +0 -272
  522. package/fp16/bench/to-alt-array.cc +0 -91
  523. package/fp16/bench/to-ieee-array.cc +0 -303
  524. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  525. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  526. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  527. package/fp16/configure.py +0 -65
  528. package/fp16/confu.yaml +0 -8
  529. package/fp16/include/fp16/__init__.py +0 -0
  530. package/fp16/include/fp16/avx.py +0 -50
  531. package/fp16/include/fp16/avx2.py +0 -53
  532. package/fp16/include/fp16/bitcasts.h +0 -92
  533. package/fp16/include/fp16/fp16.h +0 -451
  534. package/fp16/include/fp16/psimd.h +0 -131
  535. package/fp16/include/fp16.h +0 -11
  536. package/fp16/jni/Android.mk +0 -6
  537. package/fp16/jni/Application.mk +0 -4
  538. package/fp16/test/alt-from-fp32-value.cc +0 -498
  539. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  540. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  541. package/fp16/test/alt-to-fp32-value.cc +0 -348
  542. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  543. package/fp16/test/bitcasts.cc +0 -56
  544. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  545. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  546. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  547. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  548. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  549. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  550. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  551. package/fp16/test/peachpy/stubs.py +0 -38
  552. package/fp16/test/tables.cc +0 -530
  553. package/fp16/test/tables.h +0 -13
  554. package/fp16/third-party/THHalf.h +0 -92
  555. package/fp16/third-party/eigen-half.h +0 -170
  556. package/fp16/third-party/float16-compressor.h +0 -80
  557. package/fp16/third-party/half.hpp +0 -2916
  558. package/fp16/third-party/npy-halffloat.h +0 -328
  559. package/simsimd/.git-blame-ignore-revs +0 -2
  560. package/simsimd/CONTRIBUTING.md +0 -321
  561. package/simsimd/Cargo.toml +0 -49
  562. package/simsimd/MANIFEST.in +0 -4
  563. package/simsimd/Package.swift +0 -28
  564. package/simsimd/README.md +0 -1493
  565. package/simsimd/binding.gyp +0 -35
  566. package/simsimd/build.rs +0 -70
  567. package/simsimd/c/lib.c +0 -374
  568. package/simsimd/include/module.modulemap +0 -4
  569. package/simsimd/include/simsimd/binary.h +0 -486
  570. package/simsimd/include/simsimd/curved.h +0 -1541
  571. package/simsimd/include/simsimd/dot.h +0 -1853
  572. package/simsimd/include/simsimd/elementwise.h +0 -2465
  573. package/simsimd/include/simsimd/geospatial.h +0 -43
  574. package/simsimd/include/simsimd/mesh.h +0 -69
  575. package/simsimd/include/simsimd/probability.h +0 -606
  576. package/simsimd/include/simsimd/simsimd.h +0 -2567
  577. package/simsimd/include/simsimd/sparse.h +0 -1384
  578. package/simsimd/include/simsimd/spatial.h +0 -2335
  579. package/simsimd/include/simsimd/types.h +0 -666
  580. package/simsimd/javascript/fallback.ts +0 -233
  581. package/simsimd/javascript/lib.c +0 -125
  582. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  583. package/simsimd/javascript/simsimd.ts +0 -179
  584. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  585. package/simsimd/package-lock.json +0 -1761
  586. package/simsimd/package.json +0 -61
  587. package/simsimd/rust/lib.rs +0 -1821
  588. package/simsimd/scripts/bench.cxx +0 -1170
  589. package/simsimd/scripts/bench.ipynb +0 -187
  590. package/simsimd/scripts/bench.js +0 -127
  591. package/simsimd/scripts/bench.rs +0 -876
  592. package/simsimd/scripts/bench_vectors.py +0 -734
  593. package/simsimd/scripts/bench_vectors_live.py +0 -213
  594. package/simsimd/scripts/test.c +0 -187
  595. package/simsimd/scripts/test.mjs +0 -220
  596. package/simsimd/scripts/test.py +0 -1505
  597. package/simsimd/swift/SimSIMD.swift +0 -149
  598. package/simsimd/swift/Test.swift +0 -128
  599. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  600. /package/{simsimd → numkong}/LICENSE +0 -0
  601. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  602. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -1,1170 +0,0 @@
1
- /**
2
- * SimSIMD C++ Benchmark Suite
3
- *
4
- * Comprehensive benchmarks comparing SimSIMD SIMD-optimized functions against
5
- * baseline implementations using Google Benchmark framework. Run with:
6
- *
7
- * ```bash
8
- * cmake -B build_release -D SIMSIMD_BUILD_BENCHMARKS=1
9
- * cmake --build build_release
10
- * build_release/simsimd_bench
11
- * ```
12
- */
13
-
14
- #include <array> // `std::array`
15
- #include <cmath> // `std::sqrt`
16
- #include <cstdlib> // `std::aligned_alloc`
17
- #include <cstring> // `std::memcpy`
18
- #include <numeric> // `std::accumulate`
19
- #include <random> // `std::uniform_int_distribution`
20
- #include <thread> // `std::thread`
21
- #include <tuple> // `std::tuple` for callable introspection
22
- #include <type_traits> // `std::numeric_limits`
23
- #include <unordered_set> // `std::unordered_set`
24
- #include <vector> // `std::vector`
25
-
26
- #include <benchmark/benchmark.h>
27
-
28
- #if !defined(SIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS)
29
- #define SIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS 0
30
- #endif
31
- #if SIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS
32
- #include <cblas.h>
33
- #endif
34
-
35
- // It's important to note, that out compression/decompression routines
36
- // are quite inaccurate. They are not meant to be used in production code.
37
- // So when benchmarking, if possible, please use the native types, if those
38
- // are implemented.
39
- #define SIMSIMD_NATIVE_F16 1
40
- #define SIMSIMD_NATIVE_BF16 1
41
- #include <simsimd/simsimd.h>
42
-
43
- constexpr std::size_t default_seconds = 10;
44
- constexpr std::size_t default_threads = 1;
45
- constexpr simsimd_distance_t signaling_distance = std::numeric_limits<simsimd_distance_t>::signaling_NaN();
46
-
47
- /// For sub-byte data types
48
- /// Can be overridden at runtime via `SIMSIMD_BENCH_DENSE_DIMENSIONS` environment variable
49
- std::size_t dense_dimensions = 1536;
50
- /// Has quadratic impact on the number of operations
51
- /// Can be overridden at runtime via `SIMSIMD_BENCH_CURVED_DIMENSIONS` environment variable
52
- std::size_t curved_dimensions = 8;
53
-
54
- namespace bm = benchmark;
55
-
56
- // clang-format off
57
- template <simsimd_datatype_t> struct datatype_enum_to_type_gt { using value_t = void; using scalar_t = void; static constexpr std::size_t components_k = 1; };
58
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_f64_k> { using value_t = simsimd_f64_t; using scalar_t = simsimd_f64_t; static constexpr std::size_t components_k = 1; };
59
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_f32_k> { using value_t = simsimd_f32_t; using scalar_t = simsimd_f32_t; static constexpr std::size_t components_k = 1; };
60
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_f16_k> { using value_t = simsimd_f16_t; using scalar_t = simsimd_f16_t; static constexpr std::size_t components_k = 1; };
61
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_bf16_k> { using value_t = simsimd_bf16_t; using scalar_t = simsimd_bf16_t; static constexpr std::size_t components_k = 1; };
62
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_f64c_k> { using value_t = simsimd_f64c_t; using scalar_t = simsimd_f64_t; static constexpr std::size_t components_k = 2; };
63
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_f32c_k> { using value_t = simsimd_f32c_t; using scalar_t = simsimd_f32_t; static constexpr std::size_t components_k = 2; };
64
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_f16c_k> { using value_t = simsimd_f16c_t; using scalar_t = simsimd_f16_t; static constexpr std::size_t components_k = 2; };
65
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_bf16c_k> { using value_t = simsimd_bf16c_t; using scalar_t = simsimd_bf16_t; static constexpr std::size_t components_k = 2; };
66
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_b8_k> { using value_t = simsimd_b8_t; using scalar_t = simsimd_b8_t; static constexpr std::size_t components_k = 1; };
67
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_i8_k> { using value_t = simsimd_i8_t; using scalar_t = simsimd_i8_t; static constexpr std::size_t components_k = 1; };
68
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_u8_k> { using value_t = simsimd_u8_t; using scalar_t = simsimd_u8_t; static constexpr std::size_t components_k = 1; };
69
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_i16_k> { using value_t = simsimd_i16_t; using scalar_t = simsimd_i16_t; static constexpr std::size_t components_k = 1; };
70
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_u16_k> { using value_t = simsimd_u16_t; using scalar_t = simsimd_u16_t; static constexpr std::size_t components_k = 1; };
71
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_i32_k> { using value_t = simsimd_i32_t; using scalar_t = simsimd_i32_t; static constexpr std::size_t components_k = 1; };
72
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_u32_k> { using value_t = simsimd_u32_t; using scalar_t = simsimd_u32_t; static constexpr std::size_t components_k = 1; };
73
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_i64_k> { using value_t = simsimd_i64_t; using scalar_t = simsimd_i64_t; static constexpr std::size_t components_k = 1; };
74
- template <> struct datatype_enum_to_type_gt<simsimd_datatype_u64_k> { using value_t = simsimd_u64_t; using scalar_t = simsimd_u64_t; static constexpr std::size_t components_k = 1; };
75
- // clang-format on
76
-
77
- template <std::size_t multiple>
78
- constexpr std::size_t divide_round_up(std::size_t n) {
79
- return ((n + multiple - 1) / multiple) * multiple;
80
- }
81
-
82
- /**
83
- * @brief Vector-like fixed capacity buffer, ensuring cache-line alignment.
84
- * @tparam datatype_ak The data type of the vector elements, represented as a `simsimd_datatype_t`.
85
- */
86
- template <simsimd_datatype_t datatype_ak>
87
- struct vector_gt {
88
- using datatype_reflection_t = datatype_enum_to_type_gt<datatype_ak>;
89
- using scalar_t = typename datatype_reflection_t::scalar_t;
90
- using value_t = typename datatype_reflection_t::value_t;
91
- static constexpr std::size_t components_k = datatype_reflection_t::components_k;
92
-
93
- static constexpr bool is_integral =
94
- datatype_ak == datatype_ak == simsimd_datatype_b8_k || //
95
- datatype_ak == simsimd_datatype_i8_k || datatype_ak == simsimd_datatype_u8_k || //
96
- datatype_ak == simsimd_datatype_i16_k || datatype_ak == simsimd_datatype_u16_k || //
97
- datatype_ak == simsimd_datatype_i32_k || datatype_ak == simsimd_datatype_u32_k ||
98
- datatype_ak == simsimd_datatype_i64_k || datatype_ak == simsimd_datatype_u64_k;
99
- static constexpr std::size_t cacheline_length = 64;
100
-
101
- value_t *values_ptr_ = nullptr;
102
- std::size_t values_count_ = 0;
103
-
104
- vector_gt() = default;
105
- vector_gt(std::size_t values_count) noexcept(false)
106
- : values_count_(values_count),
107
- values_ptr_(static_cast<value_t *>(std::aligned_alloc(
108
- cacheline_length, divide_round_up<cacheline_length>(values_count * sizeof(value_t))))) {
109
- if (!values_ptr_) throw std::bad_alloc();
110
- }
111
-
112
- ~vector_gt() noexcept { std::free(values_ptr_); }
113
-
114
- vector_gt(vector_gt const &other) : vector_gt(other.size()) {
115
- std::memcpy(values_ptr_, other.values_ptr_, divide_round_up<cacheline_length>(values_count_ * sizeof(value_t)));
116
- }
117
- vector_gt &operator=(vector_gt const &other) {
118
- if (this != &other) {
119
- if (values_count_ != other.size()) {
120
- std::free(values_ptr_);
121
- values_count_ = other.size();
122
- values_ptr_ = static_cast<value_t *>(std::aligned_alloc(
123
- cacheline_length, divide_round_up<cacheline_length>(values_count_ * sizeof(value_t))));
124
- if (!values_ptr_) throw std::bad_alloc();
125
- }
126
- std::memcpy(values_ptr_, other.values_ptr_,
127
- divide_round_up<cacheline_length>(values_count_ * sizeof(value_t)));
128
- }
129
- return *this;
130
- }
131
-
132
- value_t *data() noexcept { return values_ptr_; }
133
- value_t const *data() const noexcept { return values_ptr_; }
134
- std::size_t size() const noexcept { return values_count_; }
135
- std::size_t size_bytes() const noexcept {
136
- return divide_round_up<cacheline_length>(values_count_ * sizeof(value_t));
137
- }
138
-
139
- scalar_t *data_scalars() noexcept { return reinterpret_cast<scalar_t *>(data()); }
140
- scalar_t const *data_scalars() const noexcept { return reinterpret_cast<scalar_t *>(data()); }
141
- std::size_t size_scalars() const noexcept { return size() * components_k; }
142
-
143
- /**
144
- * @brief Broadcast a scalar value to all elements of the vector.
145
- * @param v The scalar value to broadcast.
146
- */
147
- void set(scalar_t v) noexcept {
148
- for (std::size_t i = 0; i != size_scalars(); ++i) data_scalars()[i] = v;
149
- }
150
-
151
- /**
152
- * @brief Compresses a double value into the vector's scalar type.
153
- * @param from The double value to compress.
154
- * @param to The scalar type where the compressed value will be stored.
155
- */
156
- static void compress(double const &from, scalar_t &to) noexcept {
157
- // In a NaN, the sign bit is irrelevant, mantissa describes the kind of NaN,
158
- // and the exponent is all ones - we can only check the the exponent bits.
159
- // Brain float is similar: https://en.wikipedia.org/wiki/Bfloat16_floating-point_format
160
- constexpr unsigned short exponent_mask_f16 = 0b0111110000000000; // 1 sign, 5 exp, 10 mantissa
161
- constexpr unsigned short exponent_mask_bf16 = 0b0111111110000000; // 1 sign, 8 exp, 7 mantissa
162
- constexpr unsigned int exponent_mask_f32 = 0b01111111100000000000000000000000; // 1 sign, 8 exp, 23 mantissa
163
- constexpr unsigned long long exponent_mask_f64 = // 1 sign, 11 exp, 52 mantissa
164
- 0b011111111110000000000000000000000000000000000000000000000000000;
165
-
166
- #if !SIMSIMD_NATIVE_BF16
167
- if constexpr (datatype_ak == simsimd_datatype_bf16_k || datatype_ak == simsimd_datatype_bf16c_k) {
168
- simsimd_f32_to_bf16(from, &to);
169
- if ((to & exponent_mask_bf16) == exponent_mask_bf16) to = 0;
170
- static_assert(sizeof(scalar_t) == sizeof(simsimd_bf16_t));
171
- return;
172
- }
173
- #endif
174
- #if !SIMSIMD_NATIVE_F16
175
- if constexpr (datatype_ak == simsimd_datatype_f16_k || datatype_ak == simsimd_datatype_f16c_k) {
176
- simsimd_f32_to_f16(from, &to);
177
- if ((to & exponent_mask_f16) == exponent_mask_f16) to = 0;
178
- static_assert(sizeof(scalar_t) == sizeof(simsimd_f16_t));
179
- return;
180
- }
181
- #endif
182
- to = static_cast<scalar_t>(from);
183
- }
184
-
185
- /**
186
- * @brief Decompresses the vector's scalar type into a double value.
187
- * @param from The compressed scalar value to decompress.
188
- * @return The decompressed double value.
189
- */
190
- static double uncompress(scalar_t const &from) noexcept {
191
- #if !SIMSIMD_NATIVE_BF16
192
- if constexpr (datatype_ak == simsimd_datatype_bf16_k || datatype_ak == simsimd_datatype_bf16c_k) {
193
- return simsimd_bf16_to_f32((simsimd_bf16_t const *)&from);
194
- }
195
- #endif
196
- #if !SIMSIMD_NATIVE_F16
197
- if constexpr (datatype_ak == simsimd_datatype_f16_k || datatype_ak == simsimd_datatype_f16c_k) {
198
- return simsimd_f16_to_f32((simsimd_f16_t const *)&from);
199
- }
200
- #endif
201
- return from;
202
- }
203
-
204
- /**
205
- * @brief Randomizes the vector elements with normalized values.
206
- *
207
- * This method fills the vector with random values. For floating-point types, the vector is normalized
208
- * so that the sum of the squares of its elements equals 1. For integral types, the values are generated
209
- * within the range of the scalar type.
210
- */
211
- void randomize(std::uint32_t seed) noexcept {
212
-
213
- static std::mt19937 generator;
214
- generator.seed(seed);
215
-
216
- if constexpr (is_integral) {
217
- std::uniform_int_distribution<scalar_t> distribution(std::numeric_limits<scalar_t>::min(),
218
- std::numeric_limits<scalar_t>::max());
219
- for (std::size_t i = 0; i != size_scalars(); ++i) { data_scalars()[i] = distribution(generator); }
220
- }
221
- else {
222
- // Using non-uniform distribution helps detect tail errors
223
- std::normal_distribution<double> distribution(0.1, 1.0);
224
- double squared_sum = 0.0;
225
- for (std::size_t i = 0; i != size_scalars(); ++i) {
226
- double a_i = distribution(generator);
227
- squared_sum += a_i * a_i;
228
- compress(a_i, data_scalars()[i]);
229
- }
230
-
231
- // Normalize the vectors:
232
- squared_sum = std::sqrt(squared_sum);
233
- for (std::size_t i = 0; i != size_scalars(); ++i) {
234
- compress(uncompress(data_scalars()[i]) / squared_sum, data_scalars()[i]);
235
- // Zero out NaNs
236
- if (std::isnan(uncompress(data_scalars()[i]))) data_scalars()[i] = 0;
237
- }
238
- }
239
- }
240
- };
241
-
242
- template <simsimd_datatype_t datatype_ak>
243
- struct vectors_pair_gt {
244
- using vector_t = vector_gt<datatype_ak>;
245
- using scalar_t = typename vector_t::scalar_t;
246
- static constexpr bool is_integral = vector_t::is_integral;
247
-
248
- vector_t a;
249
- vector_t b;
250
-
251
- vectors_pair_gt() noexcept = default;
252
- vectors_pair_gt(std::size_t dimensions) noexcept : a(dimensions), b(dimensions) {}
253
- vectors_pair_gt(std::size_t size_a, std::size_t size_b) noexcept : a(size_a), b(size_b) {}
254
- vectors_pair_gt(vectors_pair_gt const &other) noexcept(false) : a(other.a), b(other.b) {}
255
- vectors_pair_gt &operator=(vectors_pair_gt const &other) noexcept(false) {
256
- if (this != &other) a = other.a, b = other.b;
257
- return *this;
258
- }
259
- };
260
-
261
- /**
262
- * @brief Measures the performance of a @b dense metric function against a baseline using Google Benchmark.
263
- * @tparam pair_at The type representing the vector pair used in the measurement.
264
- * @tparam metric_at The type of the metric function (default is void).
265
- * @param state The benchmark state object provided by Google Benchmark.
266
- * @param metric The metric function to benchmark.
267
- * @param baseline The baseline function to compare against.
268
- * @param dimensions The number of dimensions in the vectors.
269
- */
270
- template <typename pair_at, typename metric_at = void>
271
- void measure_dense(bm::State &state, metric_at metric, metric_at baseline, std::size_t dimensions) {
272
-
273
- using pair_t = pair_at;
274
- using vector_t = typename pair_at::vector_t;
275
-
276
- auto call_baseline = [&](pair_t &pair) -> double {
277
- // Output for real vectors have a single dimensions.
278
- // Output for complex vectors have two dimensions.
279
- simsimd_distance_t results[2] = {signaling_distance, signaling_distance};
280
- baseline(pair.a.data(), pair.b.data(), pair.a.size(), &results[0]);
281
- return results[0];
282
- };
283
- auto call_contender = [&](pair_t &pair) -> double {
284
- // Output for real vectors have a single dimensions.
285
- // Output for complex vectors have two dimensions.
286
- simsimd_distance_t results[2] = {signaling_distance, signaling_distance};
287
- metric(pair.a.data(), pair.b.data(), pair.a.size(), &results[0]);
288
- return results[0];
289
- };
290
-
291
- // Let's average the distance results over many pairs.
292
- constexpr std::size_t pairs_count = 128;
293
- std::vector<pair_t> pairs(pairs_count);
294
- for (std::size_t i = 0; i != pairs.size(); ++i) {
295
- auto &pair = pairs[i];
296
- pair.a = pair.b = vector_t(dimensions);
297
- pair.a.randomize(static_cast<std::uint32_t>(i)), pair.b.randomize(static_cast<std::uint32_t>(i) + 54321u);
298
- }
299
-
300
- // Initialize the output buffers for distance calculations.
301
- std::vector<double> results_baseline(pairs.size());
302
- std::vector<double> results_contender(pairs.size());
303
- for (std::size_t i = 0; i != pairs.size(); ++i)
304
- results_baseline[i] = call_baseline(pairs[i]), results_contender[i] = call_contender(pairs[i]);
305
-
306
- // The actual benchmarking loop.
307
- std::size_t iterations = 0;
308
- for (auto _ : state)
309
- bm::DoNotOptimize((results_contender[iterations & (pairs_count - 1)] =
310
- call_contender(pairs[iterations & (pairs_count - 1)]))),
311
- iterations++;
312
-
313
- // Measure the mean absolute delta and relative error.
314
- double mean_delta = 0, mean_relative_error = 0;
315
- for (std::size_t i = 0; i != pairs.size(); ++i) {
316
- auto abs_delta = std::abs(results_contender[i] - results_baseline[i]);
317
- mean_delta += abs_delta;
318
- double error = abs_delta != 0 && results_baseline[i] != 0 ? abs_delta / std::abs(results_baseline[i]) : 0;
319
- mean_relative_error += error;
320
- }
321
- mean_delta /= pairs.size();
322
- mean_relative_error /= pairs.size();
323
- state.counters["abs_delta"] = mean_delta;
324
- state.counters["relative_error"] = mean_relative_error;
325
- state.counters["bytes"] = bm::Counter(iterations * pairs[0].a.size_bytes() * 2, bm::Counter::kIsRate);
326
- state.counters["pairs"] = bm::Counter(iterations, bm::Counter::kIsRate);
327
- }
328
-
329
- /**
330
- * @brief Measures the performance of a @b curved metric function against a baseline using Google Benchmark.
331
- * @tparam pair_at The type representing the vector pair used in the measurement.
332
- * @tparam metric_at The type of the metric function (default is void).
333
- * @param state The benchmark state object provided by Google Benchmark.
334
- * @param metric The metric function to benchmark.
335
- * @param baseline The baseline function to compare against.
336
- * @param dimensions The number of dimensions in the vectors.
337
- */
338
- template <typename pair_at, typename metric_at = void>
339
- void measure_curved(bm::State &state, metric_at metric, metric_at baseline, std::size_t dimensions) {
340
-
341
- using pair_t = pair_at;
342
- using vector_t = typename pair_at::vector_t;
343
-
344
- auto call_baseline = [&](pair_t const &pair, vector_t const &tensor) -> double {
345
- simsimd_distance_t results[2] = {signaling_distance, 0};
346
- baseline(pair.a.data(), pair.b.data(), tensor.data(), pair.a.size(), &results[0]);
347
- return results[0] + results[1];
348
- };
349
- auto call_contender = [&](pair_t const &pair, vector_t const &tensor) -> double {
350
- simsimd_distance_t results[2] = {signaling_distance, 0};
351
- metric(pair.a.data(), pair.b.data(), tensor.data(), pair.a.size(), &results[0]);
352
- return results[0] + results[1];
353
- };
354
-
355
- // Let's average the distance results over many pairs.
356
- constexpr std::size_t pairs_count = 128;
357
- std::vector<pair_t> pairs(pairs_count);
358
- std::vector<vector_t> tensors(pairs_count);
359
- for (std::size_t i = 0; i != pairs.size(); ++i) {
360
- pair_t &pair = pairs[i];
361
- pair.a = pair.b = vector_t(dimensions);
362
- pair.a.randomize(static_cast<std::uint32_t>(i)), pair.b.randomize(static_cast<std::uint32_t>(i) + 54321u);
363
- vector_t &tensor = tensors[i];
364
- tensor = vector_t(dimensions * dimensions);
365
- tensor.randomize(static_cast<std::uint32_t>(i) + 123456u);
366
- }
367
-
368
- // Initialize the output buffers for distance calculations.
369
- std::vector<double> results_baseline(pairs.size());
370
- std::vector<double> results_contender(pairs.size());
371
- for (std::size_t i = 0; i != pairs.size(); ++i)
372
- results_baseline[i] = call_baseline(pairs[i], tensors[i]),
373
- results_contender[i] = call_contender(pairs[i], tensors[i]);
374
-
375
- // The actual benchmarking loop.
376
- std::size_t iterations = 0;
377
- for (auto _ : state)
378
- bm::DoNotOptimize((results_contender[iterations & (pairs_count - 1)] = call_contender(
379
- pairs[iterations & (pairs_count - 1)], tensors[iterations & (pairs_count - 1)]))),
380
- iterations++;
381
-
382
- // Measure the mean absolute delta and relative error.
383
- double mean_delta = 0, mean_relative_error = 0;
384
- for (std::size_t i = 0; i != pairs.size(); ++i) {
385
- auto abs_delta = std::abs(results_contender[i] - results_baseline[i]);
386
- mean_delta += abs_delta;
387
- double error = abs_delta != 0 && results_baseline[i] != 0 ? abs_delta / std::abs(results_baseline[i]) : 0;
388
- mean_relative_error += error;
389
- }
390
- mean_delta /= pairs.size();
391
- mean_relative_error /= pairs.size();
392
- state.counters["abs_delta"] = mean_delta;
393
- state.counters["relative_error"] = mean_relative_error;
394
- state.counters["bytes"] = bm::Counter(iterations * pairs[0].a.size_bytes() * 2, bm::Counter::kIsRate);
395
- state.counters["pairs"] = bm::Counter(iterations, bm::Counter::kIsRate);
396
- }
397
-
398
- /**
399
- * @brief Measures the performance of a @b sparse metric function against a baseline using Google Benchmark.
400
- * @tparam pair_at The type representing the vector pair used in the measurement.
401
- * @tparam metric_at The type of the metric function (default is void).
402
- * @param state The benchmark state object provided by Google Benchmark.
403
- * @param metric The metric function to benchmark.
404
- * @param baseline The baseline function to compare against.
405
- * @param size_a The number of elements in the smaller vector.
406
- * @param size_b The number of elements in the larger vector.
407
- * @param intersection_size The expected number of common scalars between the vectors.
408
- */
409
- template <typename pair_at, typename metric_at = void>
410
- void measure_sparse(bm::State &state, metric_at metric, metric_at baseline, std::size_t size_a, std::size_t size_b,
411
- std::size_t intersection_size) {
412
-
413
- using pair_t = pair_at;
414
- using vector_t = typename pair_at::vector_t;
415
- using scalar_t = typename vector_t::scalar_t;
416
-
417
- auto call_baseline = [&](pair_t &pair) -> double {
418
- simsimd_distance_t result = std::numeric_limits<simsimd_distance_t>::signaling_NaN();
419
- baseline(pair.a.data(), pair.b.data(), pair.a.size(), pair.b.size(), &result);
420
- return result;
421
- };
422
- auto call_contender = [&](pair_t &pair) -> double {
423
- simsimd_distance_t result = std::numeric_limits<simsimd_distance_t>::signaling_NaN();
424
- metric(pair.a.data(), pair.b.data(), pair.a.size(), pair.b.size(), &result);
425
- return result;
426
- };
427
-
428
- // Let's average the distance results over many pairs.
429
- constexpr std::size_t pairs_count = 128;
430
- std::vector<pair_t> pairs(pairs_count);
431
- std::random_device seed_source;
432
- std::mt19937 generator(seed_source());
433
- std::uniform_int_distribution<scalar_t> distribution(0, std::numeric_limits<scalar_t>::max());
434
-
435
- // Randomizing the vectors for sparse distances is a bit more complex then:
436
- //
437
- // pair.a.randomize(), pair.b.randomize();
438
- //
439
- // We need to ensure that the intersection is of the expected size.
440
- std::unordered_set<scalar_t> intersection_set, unique_a, unique_b;
441
- intersection_set.reserve(intersection_size);
442
- unique_a.reserve(size_a - intersection_size);
443
- unique_b.reserve(size_b - intersection_size);
444
-
445
- for (auto &pair : pairs) {
446
- pair.a = vector_t(size_a);
447
- pair.b = vector_t(size_b);
448
-
449
- // Step 1: Generate intersection set
450
- intersection_set.clear();
451
- while (intersection_set.size() < intersection_size) intersection_set.insert(distribution(generator));
452
-
453
- unique_a.clear();
454
- while (unique_a.size() < size_a - intersection_size) {
455
- scalar_t element = distribution(generator);
456
- if (intersection_set.find(element) == intersection_set.end()) unique_a.insert(element);
457
- }
458
-
459
- unique_b.clear();
460
- while (unique_b.size() < size_b - intersection_size) {
461
- scalar_t element = distribution(generator);
462
- if (intersection_set.find(element) == intersection_set.end() && unique_a.find(element) == unique_a.end())
463
- unique_b.insert(element);
464
- }
465
-
466
- // Step 2: Merge and sort
467
- std::copy(intersection_set.begin(), intersection_set.end(), pair.a.values_ptr_);
468
- std::copy(intersection_set.begin(), intersection_set.end(), pair.b.values_ptr_);
469
- std::copy(unique_a.begin(), unique_a.end(), pair.a.values_ptr_ + intersection_size);
470
- std::copy(unique_b.begin(), unique_b.end(), pair.b.values_ptr_ + intersection_size);
471
- std::sort(pair.a.values_ptr_, pair.a.values_ptr_ + size_a);
472
- std::sort(pair.b.values_ptr_, pair.b.values_ptr_ + size_b);
473
- }
474
-
475
- // Initialize the output buffers for distance calculations.
476
- std::vector<double> results_baseline(pairs.size());
477
- std::vector<double> results_contender(pairs.size());
478
- for (std::size_t i = 0; i != pairs.size(); ++i)
479
- results_baseline[i] = call_baseline(pairs[i]), results_contender[i] = call_contender(pairs[i]);
480
-
481
- // The actual benchmarking loop.
482
- std::size_t iterations = 0;
483
- for (auto _ : state)
484
- bm::DoNotOptimize((results_contender[iterations & (pairs_count - 1)] =
485
- call_contender(pairs[iterations & (pairs_count - 1)]))),
486
- iterations++;
487
-
488
- // Measure the mean absolute delta and relative error.
489
- double mean_error = 0;
490
- for (std::size_t i = 0; i != pairs.size(); ++i) {
491
- auto abs_error = std::abs(results_contender[i] - results_baseline[i]);
492
- mean_error += abs_error;
493
- }
494
- mean_error /= pairs.size();
495
- state.counters["error"] = mean_error;
496
- state.counters["bytes"] =
497
- bm::Counter(iterations * (pairs[0].a.size_bytes() + pairs[0].b.size_bytes()), bm::Counter::kIsRate);
498
- state.counters["pairs"] = bm::Counter(iterations, bm::Counter::kIsRate);
499
- state.counters["matches"] =
500
- std::accumulate(results_contender.begin(), results_contender.end(), 0.0) / results_contender.size();
501
- }
502
-
503
- template <typename... function_args_at>
504
- constexpr std::size_t function_args_count(void (*function)(function_args_at...)) {
505
- return sizeof...(function_args_at);
506
- }
507
-
508
- /**
509
- * @brief Measures the performance of a vector-vector @b FMA function against a baseline using Google Benchmark.
510
- * @tparam pair_at The type representing the vector pair used in the measurement.
511
- * @tparam kernel_at The type of the kernel function (default is void).
512
- * @param state The benchmark state object provided by Google Benchmark.
513
- * @param kernel The kernel function to benchmark.
514
- * @param baseline The baseline function to compare against.
515
- * @param dimensions The number of dimensions in the vectors.
516
- */
517
- template <typename pair_at, typename kernel_at = void, typename l2_metric_at = void>
518
- void measure_fma(bm::State &state, kernel_at kernel, kernel_at baseline, l2_metric_at l2_metric,
519
- std::size_t dimensions) {
520
-
521
- using pair_t = pair_at;
522
- using vector_t = typename pair_at::vector_t;
523
-
524
- constexpr simsimd_distance_t alpha = 0.2;
525
- constexpr simsimd_distance_t beta = 0.3;
526
- static_assert(function_args_count(kernel_at {}) >= 6 && function_args_count(kernel_at {}) <= 7,
527
- "Kernel must take two or three vectors.");
528
-
529
- auto call_baseline = [&](vector_t const &a, vector_t const &b, vector_t const &c, vector_t &d) {
530
- if constexpr (function_args_count(kernel_at {}) == 6) {
531
- baseline(a.data(), c.data(), a.size(), alpha, beta, d.data());
532
- }
533
- else { baseline(a.data(), b.data(), c.data(), a.size(), alpha, beta, d.data()); }
534
- };
535
- auto call_contender = [&](vector_t const &a, vector_t const &b, vector_t const &c, vector_t &d) {
536
- if constexpr (function_args_count(kernel_at {}) == 6) {
537
- kernel(a.data(), c.data(), a.size(), alpha, beta, d.data());
538
- }
539
- else { kernel(a.data(), b.data(), c.data(), a.size(), alpha, beta, d.data()); }
540
- };
541
-
542
- // Let's average the distance results over many quads.
543
- struct quad_t {
544
- vector_t a, b, c, d;
545
- };
546
- constexpr std::size_t quads_count = 128;
547
- std::vector<quad_t> quads(quads_count);
548
- for (std::size_t i = 0; i != quads.size(); ++i) {
549
- auto &quad = quads[i];
550
- quad.a = quad.b = quad.c = quad.d = vector_t(dimensions);
551
- quad.a.randomize(static_cast<std::uint32_t>(i));
552
- quad.b.set(2); // Having a small constant here will help avoid overflows
553
- quad.c.randomize(static_cast<std::uint32_t>(i) + 54321u);
554
- }
555
-
556
- // Initialize the output buffers for distance calculations.
557
- vector_t baseline_d(dimensions), contender_d(dimensions), zeros(dimensions);
558
- std::vector<simsimd_distance_t> l2_metric_from_baseline(quads.size());
559
- std::vector<simsimd_distance_t> l2_baseline_result_norm(quads.size());
560
- std::vector<simsimd_distance_t> l2_contender_result_norm(quads.size());
561
- zeros.set(0);
562
- double mean_delta = 0, mean_relative_error = 0;
563
- for (std::size_t i = 0; i != quads.size(); ++i) {
564
- quad_t &quad = quads[i];
565
- call_baseline(quad.a, quad.b, quad.c, baseline_d);
566
- call_contender(quad.a, quad.b, quad.c, contender_d);
567
- l2_metric(baseline_d.data(), contender_d.data(), dimensions, &l2_metric_from_baseline[i]);
568
- l2_metric(baseline_d.data(), zeros.data(), dimensions, &l2_baseline_result_norm[i]);
569
- l2_metric(contender_d.data(), zeros.data(), dimensions, &l2_contender_result_norm[i]);
570
-
571
- mean_delta += std::abs(l2_metric_from_baseline[i]);
572
- mean_relative_error +=
573
- std::abs(l2_metric_from_baseline[i]) / (std::max)(l2_baseline_result_norm[i], l2_contender_result_norm[i]);
574
- }
575
- mean_delta /= quads_count;
576
- mean_relative_error /= quads_count;
577
-
578
- // The actual benchmarking loop.
579
- std::size_t iterations = 0;
580
- for (auto _ : state) {
581
- quad_t &quad = quads[iterations & (quads_count - 1)];
582
- call_contender(quad.a, quad.b, quad.c, quad.d);
583
- iterations++;
584
- }
585
-
586
- // Measure the mean absolute delta and relative error.
587
- state.counters["abs_delta"] = mean_delta;
588
- state.counters["relative_error"] = mean_relative_error;
589
- state.counters["bytes"] = bm::Counter(
590
- iterations * quads[0].a.size_bytes() * (function_args_count(kernel_at {}) > 6 ? 3 : 2), bm::Counter::kIsRate);
591
- state.counters["pairs"] = bm::Counter(iterations, bm::Counter::kIsRate);
592
- }
593
-
594
- template <simsimd_datatype_t datatype_ak, typename metric_at = void>
595
- void dense_(std::string name, metric_at *distance_func, metric_at *baseline_func) {
596
- using pair_t = vectors_pair_gt<datatype_ak>;
597
- std::string bench_name = name + "<" + std::to_string(dense_dimensions) + "d>";
598
- bm::RegisterBenchmark(bench_name.c_str(), measure_dense<pair_t, metric_at *>, distance_func, baseline_func,
599
- dense_dimensions)
600
- ->MinTime(default_seconds)
601
- ->Threads(default_threads);
602
- }
603
-
604
- template <simsimd_datatype_t datatype_ak, typename kernel_at = void, typename l2_metric_at = void>
605
- void fma_(std::string name, kernel_at *kernel_func, kernel_at *baseline_func, l2_metric_at *l2_metric_func) {
606
- using pair_t = vectors_pair_gt<datatype_ak>;
607
- std::string bench_name = name + "<" + std::to_string(dense_dimensions) + "d>";
608
- bm::RegisterBenchmark(bench_name.c_str(), measure_fma<pair_t, kernel_at *, l2_metric_at *>, kernel_func,
609
- baseline_func, l2_metric_func, dense_dimensions)
610
- ->MinTime(default_seconds)
611
- ->Threads(default_threads);
612
- }
613
-
614
- template <simsimd_datatype_t datatype_ak, typename metric_at = void>
615
- void sparse_(std::string name, metric_at *distance_func, metric_at *baseline_func) {
616
-
617
- using pair_t = vectors_pair_gt<datatype_ak>;
618
-
619
- // Register different lengths, intersection sizes, and distributions
620
- // 2 first lengths * 3 second length multipliers * 4 intersection grades = 24 benchmarks for each metric.
621
- for (std::size_t first_len : {128, 1024}) { //< 2 lengths
622
- for (std::size_t second_len_multiplier : {1, 8, 64}) { //< 3 length multipliers
623
- for (double intersection_share : {0.01, 0.05, 0.5, 0.95}) { //< 4 intersection grades
624
- std::size_t intersection_size = static_cast<std::size_t>(first_len * intersection_share);
625
- std::size_t second_len = first_len * second_len_multiplier;
626
- std::string bench_name = name + "<|A|=" + std::to_string(first_len) +
627
- ",|B|=" + std::to_string(second_len) +
628
- ",|A∩B|=" + std::to_string(intersection_size) + ">";
629
- if (second_len > 8192) continue;
630
- bm::RegisterBenchmark(bench_name.c_str(), measure_sparse<pair_t, metric_at *>, distance_func,
631
- baseline_func, first_len, second_len, intersection_size)
632
- ->MinTime(default_seconds)
633
- ->Threads(default_threads);
634
- }
635
- }
636
- }
637
- }
638
-
639
- template <simsimd_datatype_t datatype_ak, typename metric_at = void>
640
- void curved_(std::string name, metric_at *distance_func, metric_at *baseline_func) {
641
-
642
- using pair_t = vectors_pair_gt<datatype_ak>;
643
- std::string bench_name = name + "<" + std::to_string(curved_dimensions) + "d>";
644
- bm::RegisterBenchmark(bench_name.c_str(), measure_curved<pair_t, metric_at *>, distance_func, baseline_func,
645
- curved_dimensions)
646
- ->MinTime(default_seconds)
647
- ->Threads(default_threads);
648
- }
649
-
650
- #if SIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS
651
-
652
- void dot_f32_blas(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n, simsimd_distance_t *result) {
653
- *result = cblas_sdot((int)n, a, 1, b, 1);
654
- }
655
-
656
- void dot_f64_blas(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n, simsimd_distance_t *result) {
657
- *result = cblas_ddot((int)n, a, 1, b, 1);
658
- }
659
-
660
- void dot_f32c_blas(simsimd_f32c_t const *a, simsimd_f32c_t const *b, simsimd_size_t n, simsimd_distance_t *result) {
661
- simsimd_f32_t f32_result[2] = {0, 0};
662
- cblas_cdotu_sub((int)n, (simsimd_f32_t const *)a, 1, (simsimd_f32_t const *)b, 1, f32_result);
663
- result[0] = f32_result[0];
664
- result[1] = f32_result[1];
665
- }
666
-
667
- void dot_f64c_blas(simsimd_f64c_t const *a, simsimd_f64c_t const *b, simsimd_size_t n, simsimd_distance_t *result) {
668
- cblas_zdotu_sub((int)n, (simsimd_f64_t const *)a, 1, (simsimd_f64_t const *)b, 1, result);
669
- }
670
-
671
- void vdot_f32c_blas(simsimd_f32c_t const *a, simsimd_f32c_t const *b, simsimd_size_t n, simsimd_distance_t *result) {
672
- simsimd_f32_t f32_result[2] = {0, 0};
673
- cblas_cdotc_sub((int)n, (simsimd_f32_t const *)a, 1, (simsimd_f32_t const *)b, 1, f32_result);
674
- result[0] = f32_result[0];
675
- result[1] = f32_result[1];
676
- }
677
-
678
- void vdot_f64c_blas(simsimd_f64c_t const *a, simsimd_f64c_t const *b, simsimd_size_t n, simsimd_distance_t *result) {
679
- cblas_zdotc_sub((int)n, (simsimd_f64_t const *)a, 1, (simsimd_f64_t const *)b, 1, result);
680
- }
681
-
682
- void bilinear_f32_blas(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c, simsimd_size_t n,
683
- simsimd_distance_t *result) {
684
- // Thread-local buffer to avoid allocation in hot path
685
- static thread_local std::vector<simsimd_f32_t> intermediate;
686
- if (intermediate.size() < n) intermediate.resize(n);
687
-
688
- simsimd_f32_t alpha = 1.0f, beta = 0.0f;
689
- cblas_sgemv(CblasRowMajor, CblasNoTrans, (int)n, (int)n, alpha, c, (int)n, b, 1, beta, intermediate.data(), 1);
690
- *result = cblas_sdot((int)n, a, 1, intermediate.data(), 1);
691
- }
692
-
693
- void bilinear_f64_blas(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_f64_t const *c, simsimd_size_t n,
694
- simsimd_distance_t *result) {
695
- // Thread-local buffer to avoid allocation in hot path
696
- static thread_local std::vector<simsimd_f64_t> intermediate;
697
- if (intermediate.size() < n) intermediate.resize(n);
698
-
699
- simsimd_f64_t alpha = 1.0, beta = 0.0;
700
- cblas_dgemv(CblasRowMajor, CblasNoTrans, (int)n, (int)n, alpha, c, n, b, 1, beta, intermediate.data(), 1);
701
- *result = cblas_ddot((int)n, a, 1, intermediate.data(), 1);
702
- }
703
-
704
- void bilinear_f32c_blas(simsimd_f32c_t const *a, simsimd_f32c_t const *b, simsimd_f32c_t const *c, simsimd_size_t n,
705
- simsimd_distance_t *results) {
706
- // Thread-local buffer to avoid allocation in hot path
707
- static thread_local std::vector<simsimd_f32c_t> intermediate;
708
- if (intermediate.size() < n) intermediate.resize(n);
709
-
710
- simsimd_f32c_t alpha = {1.0f, 0.0f}, beta = {0.0f, 0.0f};
711
- cblas_cgemv(CblasRowMajor, CblasNoTrans, (int)n, (int)n, &alpha, c, n, b, 1, &beta, intermediate.data(), 1);
712
- simsimd_f32_t f32_result[2] = {0, 0};
713
- cblas_cdotu_sub((int)n, (simsimd_f32_t const *)a, 1, (simsimd_f32_t const *)intermediate.data(), 1, f32_result);
714
- results[0] = f32_result[0];
715
- results[1] = f32_result[1];
716
- }
717
-
718
- void bilinear_f64c_blas(simsimd_f64c_t const *a, simsimd_f64c_t const *b, simsimd_f64c_t const *c, simsimd_size_t n,
719
- simsimd_distance_t *results) {
720
- // Thread-local buffer to avoid allocation in hot path
721
- static thread_local std::vector<simsimd_f64c_t> intermediate;
722
- if (intermediate.size() < n) intermediate.resize(n);
723
-
724
- simsimd_f64c_t alpha = {1.0, 0.0}, beta = {0.0, 0.0};
725
- cblas_zgemv(CblasRowMajor, CblasNoTrans, (int)n, (int)n, &alpha, c, n, b, 1, &beta, intermediate.data(), 1);
726
- cblas_zdotu_sub((int)n, (simsimd_f64_t const *)a, 1, (simsimd_f64_t const *)intermediate.data(), 1, results);
727
- }
728
-
729
- #endif
730
-
731
- int main(int argc, char **argv) {
732
- simsimd_capability_t runtime_caps = simsimd_capabilities();
733
-
734
- // Log supported functionality
735
- char const *flags[2] = {"false", "true"};
736
- std::printf("Benchmarking Similarity Measures\n");
737
- std::printf("- Compiler used native F16: %s\n", flags[SIMSIMD_NATIVE_F16]);
738
- std::printf("- Compiler used native BF16: %s\n", flags[SIMSIMD_NATIVE_BF16]);
739
- std::printf("- Benchmark against CBLAS: %s\n", flags[SIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS]);
740
- std::printf("\n");
741
- std::printf("Compile-time settings:\n");
742
- std::printf("- Arm NEON support enabled: %s\n", flags[SIMSIMD_TARGET_NEON]);
743
- std::printf("- Arm SVE support enabled: %s\n", flags[SIMSIMD_TARGET_SVE]);
744
- std::printf("- Arm SVE2 support enabled: %s\n", flags[SIMSIMD_TARGET_SVE2]);
745
- std::printf("- x86 Haswell support enabled: %s\n", flags[SIMSIMD_TARGET_HASWELL]);
746
- std::printf("- x86 Skylake support enabled: %s\n", flags[SIMSIMD_TARGET_SKYLAKE]);
747
- std::printf("- x86 Ice Lake support enabled: %s\n", flags[SIMSIMD_TARGET_ICE]);
748
- std::printf("- x86 Genoa support enabled: %s\n", flags[SIMSIMD_TARGET_GENOA]);
749
- std::printf("- x86 Sapphire Rapids support enabled: %s\n", flags[SIMSIMD_TARGET_SAPPHIRE]);
750
- std::printf("- x86 Turin support enabled: %s\n", flags[SIMSIMD_TARGET_TURIN]);
751
- std::printf("\n");
752
- std::printf("Run-time settings:\n");
753
- std::printf("- Arm NEON support enabled: %s\n", flags[(runtime_caps & simsimd_cap_neon_k) != 0]);
754
- std::printf("- Arm NEON F16 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_neon_f16_k) != 0]);
755
- std::printf("- Arm NEON BF16 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_neon_bf16_k) != 0]);
756
- std::printf("- Arm NEON I8 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_neon_i8_k) != 0]);
757
- std::printf("- Arm SVE support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve_k) != 0]);
758
- std::printf("- Arm SVE F16 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve_f16_k) != 0]);
759
- std::printf("- Arm SVE BF16 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve_bf16_k) != 0]);
760
- std::printf("- Arm SVE I8 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve_i8_k) != 0]);
761
- std::printf("- Arm SVE2 support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sve2_k) != 0]);
762
- std::printf("- x86 Haswell support enabled: %s\n", flags[(runtime_caps & simsimd_cap_haswell_k) != 0]);
763
- std::printf("- x86 Skylake support enabled: %s\n", flags[(runtime_caps & simsimd_cap_skylake_k) != 0]);
764
- std::printf("- x86 Ice Lake support enabled: %s\n", flags[(runtime_caps & simsimd_cap_ice_k) != 0]);
765
- std::printf("- x86 Genoa support enabled: %s\n", flags[(runtime_caps & simsimd_cap_genoa_k) != 0]);
766
- std::printf("- x86 Sapphire Rapids support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sapphire_k) != 0]);
767
- std::printf("- x86 Turin support enabled: %s\n", flags[(runtime_caps & simsimd_cap_turin_k) != 0]);
768
- std::printf("- x86 Sierra Forest support enabled: %s\n", flags[(runtime_caps & simsimd_cap_sierra_k) != 0]);
769
- std::printf("\n");
770
-
771
- // Override dimensions from environment variables if provided
772
- if (char const *env_dense = std::getenv("SIMSIMD_BENCH_DENSE_DIMENSIONS")) {
773
- std::size_t parsed_dense = std::atoi(env_dense);
774
- if (parsed_dense > 0) {
775
- dense_dimensions = parsed_dense;
776
- std::printf("Overriding `dense_dimensions` to %zu from SIMSIMD_BENCH_DENSE_DIMENSIONS\n", dense_dimensions);
777
- }
778
- }
779
- if (char const *env_curved = std::getenv("SIMSIMD_BENCH_CURVED_DIMENSIONS")) {
780
- std::size_t parsed_curved = std::atoi(env_curved);
781
- if (parsed_curved > 0) {
782
- curved_dimensions = parsed_curved;
783
- std::printf("Overriding `curved_dimensions` to %zu from SIMSIMD_BENCH_CURVED_DIMENSIONS\n",
784
- curved_dimensions);
785
- }
786
- }
787
- std::printf("\n");
788
-
789
- // Run the benchmarks
790
- bm::Initialize(&argc, argv);
791
- if (bm::ReportUnrecognizedArguments(argc, argv)) return 1;
792
-
793
- constexpr simsimd_datatype_t b8_k = simsimd_datatype_b8_k;
794
- constexpr simsimd_datatype_t i4x2_k = simsimd_datatype_i4x2_k;
795
- constexpr simsimd_datatype_t i8_k = simsimd_datatype_i8_k;
796
- constexpr simsimd_datatype_t i16_k = simsimd_datatype_i16_k;
797
- constexpr simsimd_datatype_t i32_k = simsimd_datatype_i32_k;
798
- constexpr simsimd_datatype_t i64_k = simsimd_datatype_i64_k;
799
- constexpr simsimd_datatype_t u8_k = simsimd_datatype_u8_k;
800
- constexpr simsimd_datatype_t u16_k = simsimd_datatype_u16_k;
801
- constexpr simsimd_datatype_t u32_k = simsimd_datatype_u32_k;
802
- constexpr simsimd_datatype_t u64_k = simsimd_datatype_u64_k;
803
- constexpr simsimd_datatype_t f64_k = simsimd_datatype_f64_k;
804
- constexpr simsimd_datatype_t f32_k = simsimd_datatype_f32_k;
805
- constexpr simsimd_datatype_t f16_k = simsimd_datatype_f16_k;
806
- constexpr simsimd_datatype_t bf16_k = simsimd_datatype_bf16_k;
807
- constexpr simsimd_datatype_t f64c_k = simsimd_datatype_f64c_k;
808
- constexpr simsimd_datatype_t f32c_k = simsimd_datatype_f32c_k;
809
- constexpr simsimd_datatype_t f16c_k = simsimd_datatype_f16c_k;
810
- constexpr simsimd_datatype_t bf16c_k = simsimd_datatype_bf16c_k;
811
-
812
- #if SIMSIMD_BUILD_BENCHMARKS_WITH_CBLAS
813
-
814
- dense_<f32_k>("dot_f32_blas", dot_f32_blas, simsimd_dot_f32_accurate);
815
- dense_<f64_k>("dot_f64_blas", dot_f64_blas, simsimd_dot_f64_serial);
816
- dense_<f32c_k>("dot_f32c_blas", dot_f32c_blas, simsimd_dot_f32c_accurate);
817
- dense_<f64c_k>("dot_f64c_blas", dot_f64c_blas, simsimd_dot_f64c_serial);
818
- dense_<f32c_k>("vdot_f32c_blas", vdot_f32c_blas, simsimd_vdot_f32c_accurate);
819
- dense_<f64c_k>("vdot_f64c_blas", vdot_f64c_blas, simsimd_vdot_f64c_serial);
820
-
821
- curved_<f64_k>("bilinear_f64_blas", bilinear_f64_blas, simsimd_bilinear_f64_serial);
822
- curved_<f64c_k>("bilinear_f64c_blas", bilinear_f64c_blas, simsimd_bilinear_f64c_serial);
823
- curved_<f32_k>("bilinear_f32_blas", bilinear_f32_blas, simsimd_bilinear_f32_accurate);
824
- curved_<f32c_k>("bilinear_f32c_blas", bilinear_f32c_blas, simsimd_bilinear_f32c_accurate);
825
-
826
- #endif
827
-
828
- #if SIMSIMD_TARGET_NEON
829
- dense_<f32_k>("dot_f32_neon", simsimd_dot_f32_neon, simsimd_dot_f32_accurate);
830
- dense_<f32_k>("cos_f32_neon", simsimd_cos_f32_neon, simsimd_cos_f32_accurate);
831
- dense_<f32_k>("l2sq_f32_neon", simsimd_l2sq_f32_neon, simsimd_l2sq_f32_accurate);
832
- dense_<f32_k>("l2_f32_neon", simsimd_l2_f32_neon, simsimd_l2_f32_accurate);
833
- dense_<f32_k>("kl_f32_neon", simsimd_kl_f32_neon, simsimd_kl_f32_accurate);
834
- dense_<f32_k>("js_f32_neon", simsimd_js_f32_neon, simsimd_js_f32_accurate);
835
-
836
- dense_<f64_k>("cos_f64_neon", simsimd_cos_f64_neon, simsimd_cos_f64_serial);
837
- dense_<f64_k>("l2sq_f64_neon", simsimd_l2sq_f64_neon, simsimd_l2sq_f64_serial);
838
- dense_<f64_k>("l2_f64_neon", simsimd_l2_f64_neon, simsimd_l2_f64_serial);
839
-
840
- dense_<i8_k>("cos_i8_neon", simsimd_cos_i8_neon, simsimd_cos_i8_serial);
841
- dense_<i8_k>("l2sq_i8_neon", simsimd_l2sq_i8_neon, simsimd_l2sq_i8_serial);
842
- dense_<i8_k>("l2_i8_neon", simsimd_l2_i8_neon, simsimd_l2_i8_serial);
843
- dense_<i8_k>("dot_i8_neon", simsimd_dot_i8_neon, simsimd_dot_i8_serial);
844
-
845
- dense_<u8_k>("cos_u8_neon", simsimd_cos_u8_neon, simsimd_cos_u8_serial);
846
- dense_<u8_k>("l2sq_u8_neon", simsimd_l2sq_u8_neon, simsimd_l2sq_u8_serial);
847
- dense_<u8_k>("l2_u8_neon", simsimd_l2_u8_neon, simsimd_l2_u8_serial);
848
- dense_<u8_k>("dot_u8_neon", simsimd_dot_u8_neon, simsimd_dot_u8_serial);
849
-
850
- dense_<b8_k>("hamming_b8_neon", simsimd_hamming_b8_neon, simsimd_hamming_b8_serial);
851
- dense_<b8_k>("jaccard_b8_neon", simsimd_jaccard_b8_neon, simsimd_jaccard_b8_serial);
852
-
853
- dense_<f32c_k>("dot_f32c_neon", simsimd_dot_f32c_neon, simsimd_dot_f32c_accurate);
854
- dense_<f32c_k>("vdot_f32c_neon", simsimd_vdot_f32c_neon, simsimd_vdot_f32c_accurate);
855
-
856
- curved_<f32_k>("bilinear_f32_neon", simsimd_bilinear_f32_neon, simsimd_bilinear_f32_accurate);
857
- curved_<f32_k>("mahalanobis_f32_neon", simsimd_mahalanobis_f32_neon, simsimd_mahalanobis_f32_accurate);
858
- curved_<f32c_k>("bilinear_f32c_neon", simsimd_bilinear_f32c_neon, simsimd_bilinear_f32c_accurate);
859
-
860
- sparse_<u16_k>("intersect_u16_neon", simsimd_intersect_u16_neon, simsimd_intersect_u16_accurate);
861
- sparse_<u32_k>("intersect_u32_neon", simsimd_intersect_u32_neon, simsimd_intersect_u32_accurate);
862
-
863
- fma_<f32_k>("fma_f32_neon", simsimd_fma_f32_neon, simsimd_fma_f32_accurate, simsimd_l2_f32_accurate);
864
- fma_<f32_k>("wsum_f32_neon", simsimd_wsum_f32_neon, simsimd_wsum_f32_accurate, simsimd_l2_f32_accurate);
865
- fma_<f32_k>("fma_f32_serial", simsimd_fma_f32_serial, simsimd_fma_f32_accurate, simsimd_l2_f32_accurate);
866
- fma_<f32_k>("wsum_f32_serial", simsimd_wsum_f32_serial, simsimd_wsum_f32_accurate, simsimd_l2_f32_accurate);
867
-
868
- #endif
869
-
870
- #if SIMSIMD_TARGET_NEON_F16
871
- dense_<f16c_k>("dot_f16c_neon", simsimd_dot_f16c_neon, simsimd_dot_f16c_accurate);
872
- dense_<f16c_k>("vdot_f16c_neon", simsimd_vdot_f16c_neon, simsimd_vdot_f16c_accurate);
873
-
874
- dense_<f16_k>("dot_f16_neon", simsimd_dot_f16_neon, simsimd_dot_f16_accurate);
875
- dense_<f16_k>("cos_f16_neon", simsimd_cos_f16_neon, simsimd_cos_f16_accurate);
876
- dense_<f16_k>("l2sq_f16_neon", simsimd_l2sq_f16_neon, simsimd_l2sq_f16_accurate);
877
- dense_<f16_k>("l2_f16_neon", simsimd_l2_f16_neon, simsimd_l2sq_f16_accurate);
878
- dense_<f16_k>("kl_f16_neon", simsimd_kl_f16_neon, simsimd_kl_f16_accurate);
879
- dense_<f16_k>("js_f16_neon", simsimd_js_f16_neon, simsimd_js_f16_accurate);
880
-
881
- curved_<f16_k>("bilinear_f16_neon", simsimd_bilinear_f16_neon, simsimd_bilinear_f16_accurate);
882
- curved_<f16_k>("mahalanobis_f16_neon", simsimd_mahalanobis_f16_neon, simsimd_mahalanobis_f16_accurate);
883
- curved_<f16c_k>("bilinear_f16c_neon", simsimd_bilinear_f16c_neon, simsimd_bilinear_f16c_accurate);
884
-
885
- fma_<f16_k>("fma_f16_neon", simsimd_fma_f16_neon, simsimd_fma_f16_accurate, simsimd_l2_f16_accurate);
886
- fma_<f16_k>("wsum_f16_neon", simsimd_wsum_f16_neon, simsimd_wsum_f16_accurate, simsimd_l2_f16_accurate);
887
-
888
- // FMA kernels for `u8` on NEON use `f16` arithmetic
889
- fma_<u8_k>("fma_u8_neon", simsimd_fma_u8_neon, simsimd_fma_u8_accurate, simsimd_l2_u8_serial);
890
- fma_<u8_k>("wsum_u8_neon", simsimd_wsum_u8_neon, simsimd_wsum_u8_accurate, simsimd_l2_u8_serial);
891
- fma_<i8_k>("fma_i8_neon", simsimd_fma_i8_neon, simsimd_fma_i8_accurate, simsimd_l2_i8_serial);
892
- fma_<i8_k>("wsum_i8_neon", simsimd_wsum_i8_neon, simsimd_wsum_i8_accurate, simsimd_l2_i8_serial);
893
- #endif
894
-
895
- #if SIMSIMD_TARGET_NEON_BF16
896
- dense_<bf16c_k>("dot_bf16c_neon", simsimd_dot_bf16c_neon, simsimd_dot_bf16c_accurate);
897
- dense_<bf16c_k>("vdot_bf16c_neon", simsimd_vdot_bf16c_neon, simsimd_vdot_bf16c_accurate);
898
-
899
- dense_<bf16_k>("dot_bf16_neon", simsimd_dot_bf16_neon, simsimd_dot_bf16_accurate);
900
- dense_<bf16_k>("cos_bf16_neon", simsimd_cos_bf16_neon, simsimd_cos_bf16_accurate);
901
- dense_<bf16_k>("l2sq_bf16_neon", simsimd_l2sq_bf16_neon, simsimd_l2sq_bf16_accurate);
902
- dense_<bf16_k>("l2_bf16_neon", simsimd_l2_bf16_neon, simsimd_l2_bf16_accurate);
903
-
904
- curved_<bf16_k>("bilinear_bf16_neon", simsimd_bilinear_bf16_neon, simsimd_bilinear_bf16_accurate);
905
- curved_<bf16_k>("mahalanobis_bf16_neon", simsimd_mahalanobis_bf16_neon, simsimd_mahalanobis_bf16_accurate);
906
- curved_<bf16c_k>("bilinear_bf16c_neon", simsimd_bilinear_bf16c_neon, simsimd_bilinear_bf16c_accurate);
907
-
908
- fma_<bf16_k>("fma_bf16_neon", simsimd_fma_bf16_neon, simsimd_fma_bf16_accurate, simsimd_l2_bf16_accurate);
909
- fma_<bf16_k>("wsum_bf16_neon", simsimd_wsum_bf16_neon, simsimd_wsum_bf16_accurate, simsimd_l2_bf16_accurate);
910
- #endif
911
-
912
- #if SIMSIMD_TARGET_SVE
913
- dense_<f32_k>("dot_f32_sve", simsimd_dot_f32_sve, simsimd_dot_f32_accurate);
914
- dense_<f32_k>("cos_f32_sve", simsimd_cos_f32_sve, simsimd_cos_f32_accurate);
915
- dense_<f32_k>("l2sq_f32_sve", simsimd_l2sq_f32_sve, simsimd_l2sq_f32_accurate);
916
- dense_<f32_k>("l2_f32_sve", simsimd_l2_f32_sve, simsimd_l2_f32_accurate);
917
-
918
- dense_<f64_k>("dot_f64_sve", simsimd_dot_f64_sve, simsimd_dot_f64_serial);
919
- dense_<f64_k>("cos_f64_sve", simsimd_cos_f64_sve, simsimd_cos_f64_serial);
920
- dense_<f64_k>("l2sq_f64_sve", simsimd_l2sq_f64_sve, simsimd_l2sq_f64_serial);
921
- dense_<f64_k>("l2_f64_sve", simsimd_l2_f64_sve, simsimd_l2_f64_serial);
922
-
923
- dense_<b8_k>("hamming_b8_sve", simsimd_hamming_b8_sve, simsimd_hamming_b8_serial);
924
- dense_<b8_k>("jaccard_b8_sve", simsimd_jaccard_b8_sve, simsimd_jaccard_b8_serial);
925
-
926
- dense_<f32c_k>("dot_f32c_sve", simsimd_dot_f32c_sve, simsimd_dot_f32c_accurate);
927
- dense_<f32c_k>("vdot_f32c_sve", simsimd_vdot_f32c_sve, simsimd_vdot_f32c_accurate);
928
- dense_<f64c_k>("dot_f64c_sve", simsimd_dot_f64c_sve, simsimd_dot_f64c_serial);
929
- dense_<f64c_k>("vdot_f64c_sve", simsimd_vdot_f64c_sve, simsimd_vdot_f64c_serial);
930
- #endif
931
-
932
- #if SIMSIMD_TARGET_SVE_F16
933
- dense_<f16_k>("dot_f16_sve", simsimd_dot_f16_sve, simsimd_dot_f16_accurate);
934
- dense_<f16_k>("cos_f16_sve", simsimd_cos_f16_sve, simsimd_cos_f16_accurate);
935
- dense_<f16_k>("l2sq_f16_sve", simsimd_l2sq_f16_sve, simsimd_l2sq_f16_accurate);
936
- dense_<f16_k>("l2_f16_sve", simsimd_l2_f16_sve, simsimd_l2sq_f16_accurate);
937
- dense_<f16c_k>("dot_f16c_sve", simsimd_dot_f16c_sve, simsimd_dot_f16c_accurate);
938
- dense_<f16c_k>("vdot_f16c_sve", simsimd_vdot_f16c_sve, simsimd_vdot_f16c_accurate);
939
- #endif
940
-
941
- #if SIMSIMD_TARGET_SVE_BF16
942
- dense_<bf16_k>("cos_bf16_sve", simsimd_cos_bf16_sve, simsimd_cos_bf16_accurate);
943
- dense_<bf16_k>("l2sq_bf16_sve", simsimd_l2sq_bf16_sve, simsimd_l2sq_bf16_accurate);
944
- dense_<bf16_k>("l2_bf16_sve", simsimd_l2_bf16_sve, simsimd_l2_bf16_accurate);
945
- #endif
946
-
947
- #if SIMSIMD_TARGET_SVE2
948
- sparse_<u16_k>("intersect_u16_sve2", simsimd_intersect_u16_sve2, simsimd_intersect_u16_accurate);
949
- sparse_<u32_k>("intersect_u32_sve2", simsimd_intersect_u32_sve2, simsimd_intersect_u32_accurate);
950
- #endif
951
-
952
- #if SIMSIMD_TARGET_HASWELL
953
- dense_<f16_k>("dot_f16_haswell", simsimd_dot_f16_haswell, simsimd_dot_f16_accurate);
954
- dense_<f16_k>("cos_f16_haswell", simsimd_cos_f16_haswell, simsimd_cos_f16_accurate);
955
- dense_<f16_k>("l2sq_f16_haswell", simsimd_l2sq_f16_haswell, simsimd_l2sq_f16_accurate);
956
- dense_<f16_k>("l2_f16_haswell", simsimd_l2_f16_haswell, simsimd_l2_f16_accurate);
957
- dense_<f16_k>("kl_f16_haswell", simsimd_kl_f16_haswell, simsimd_kl_f16_accurate);
958
- dense_<f16_k>("js_f16_haswell", simsimd_js_f16_haswell, simsimd_js_f16_accurate);
959
-
960
- dense_<bf16_k>("dot_bf16_haswell", simsimd_dot_bf16_haswell, simsimd_dot_bf16_accurate);
961
- dense_<bf16_k>("cos_bf16_haswell", simsimd_cos_bf16_haswell, simsimd_cos_bf16_accurate);
962
- dense_<bf16_k>("l2sq_bf16_haswell", simsimd_l2sq_bf16_haswell, simsimd_l2sq_bf16_accurate);
963
- dense_<bf16_k>("l2_bf16_haswell", simsimd_l2_bf16_haswell, simsimd_l2_bf16_accurate);
964
-
965
- dense_<i8_k>("cos_i8_haswell", simsimd_cos_i8_haswell, simsimd_cos_i8_serial);
966
- dense_<i8_k>("l2sq_i8_haswell", simsimd_l2sq_i8_haswell, simsimd_l2sq_i8_serial);
967
- dense_<i8_k>("l2_i8_haswell", simsimd_l2_i8_haswell, simsimd_l2_i8_serial);
968
- dense_<i8_k>("dot_i8_haswell", simsimd_dot_i8_haswell, simsimd_dot_i8_serial);
969
-
970
- dense_<u8_k>("cos_u8_haswell", simsimd_cos_u8_haswell, simsimd_cos_u8_serial);
971
- dense_<u8_k>("l2sq_u8_haswell", simsimd_l2sq_u8_haswell, simsimd_l2sq_u8_serial);
972
- dense_<u8_k>("l2_u8_haswell", simsimd_l2_u8_haswell, simsimd_l2_u8_serial);
973
- dense_<u8_k>("dot_u8_haswell", simsimd_dot_u8_haswell, simsimd_dot_u8_serial);
974
-
975
- dense_<b8_k>("hamming_b8_haswell", simsimd_hamming_b8_haswell, simsimd_hamming_b8_serial);
976
- dense_<b8_k>("jaccard_b8_haswell", simsimd_jaccard_b8_haswell, simsimd_jaccard_b8_serial);
977
-
978
- dense_<f16c_k>("dot_f16c_haswell", simsimd_dot_f16c_haswell, simsimd_dot_f16c_accurate);
979
- dense_<f16c_k>("vdot_f16c_haswell", simsimd_vdot_f16c_haswell, simsimd_vdot_f16c_accurate);
980
- dense_<f32c_k>("dot_f32c_haswell", simsimd_dot_f32c_haswell, simsimd_dot_f32c_accurate);
981
- dense_<f32c_k>("vdot_f32c_haswell", simsimd_vdot_f32c_haswell, simsimd_vdot_f32c_accurate);
982
-
983
- curved_<f16_k>("bilinear_f16_haswell", simsimd_bilinear_f16_haswell, simsimd_bilinear_f16_accurate);
984
- curved_<f16_k>("mahalanobis_f16_haswell", simsimd_mahalanobis_f16_haswell, simsimd_mahalanobis_f16_accurate);
985
- curved_<bf16_k>("bilinear_bf16_haswell", simsimd_bilinear_bf16_haswell, simsimd_bilinear_bf16_accurate);
986
- curved_<bf16_k>("mahalanobis_bf16_haswell", simsimd_mahalanobis_bf16_haswell, simsimd_mahalanobis_bf16_accurate);
987
-
988
- fma_<f64_k>("fma_f64_haswell", simsimd_fma_f64_haswell, simsimd_fma_f64_serial, simsimd_l2_f64_serial);
989
- fma_<f64_k>("wsum_f64_haswell", simsimd_wsum_f64_haswell, simsimd_wsum_f64_serial, simsimd_l2_f64_serial);
990
- fma_<f32_k>("fma_f32_haswell", simsimd_fma_f32_haswell, simsimd_fma_f32_accurate, simsimd_l2_f32_accurate);
991
- fma_<f32_k>("wsum_f32_haswell", simsimd_wsum_f32_haswell, simsimd_wsum_f32_accurate, simsimd_l2_f32_accurate);
992
- fma_<f16_k>("fma_f16_haswell", simsimd_fma_f16_haswell, simsimd_fma_f16_accurate, simsimd_l2_f16_accurate);
993
- fma_<f16_k>("wsum_f16_haswell", simsimd_wsum_f16_haswell, simsimd_wsum_f16_accurate, simsimd_l2_f16_accurate);
994
- fma_<bf16_k>("fma_bf16_haswell", simsimd_fma_bf16_haswell, simsimd_fma_bf16_accurate, simsimd_l2_bf16_accurate);
995
- fma_<bf16_k>("wsum_bf16_haswell", simsimd_wsum_bf16_haswell, simsimd_wsum_bf16_accurate, simsimd_l2_bf16_accurate);
996
- fma_<i8_k>("fma_i8_haswell", simsimd_fma_i8_haswell, simsimd_fma_i8_accurate, simsimd_l2_i8_serial);
997
- fma_<i8_k>("wsum_i8_haswell", simsimd_wsum_i8_haswell, simsimd_wsum_i8_accurate, simsimd_l2_i8_serial);
998
- fma_<u8_k>("fma_u8_haswell", simsimd_fma_u8_haswell, simsimd_fma_u8_accurate, simsimd_l2_u8_serial);
999
- fma_<u8_k>("wsum_u8_haswell", simsimd_wsum_u8_haswell, simsimd_wsum_u8_accurate, simsimd_l2_u8_serial);
1000
-
1001
- #endif
1002
-
1003
- #if SIMSIMD_TARGET_GENOA
1004
- dense_<bf16_k>("dot_bf16_genoa", simsimd_dot_bf16_genoa, simsimd_dot_bf16_accurate);
1005
- dense_<bf16_k>("cos_bf16_genoa", simsimd_cos_bf16_genoa, simsimd_cos_bf16_accurate);
1006
- dense_<bf16_k>("l2sq_bf16_genoa", simsimd_l2sq_bf16_genoa, simsimd_l2sq_bf16_accurate);
1007
- dense_<bf16_k>("l2_bf16_genoa", simsimd_l2_bf16_genoa, simsimd_l2_bf16_accurate);
1008
- dense_<bf16c_k>("dot_bf16c_genoa", simsimd_dot_bf16c_genoa, simsimd_dot_bf16c_accurate);
1009
- dense_<bf16c_k>("vdot_bf16c_genoa", simsimd_vdot_bf16c_genoa, simsimd_vdot_bf16c_accurate);
1010
-
1011
- curved_<bf16_k>("bilinear_bf16_genoa", simsimd_bilinear_bf16_genoa, simsimd_bilinear_bf16_accurate);
1012
- curved_<bf16_k>("mahalanobis_bf16_genoa", simsimd_mahalanobis_bf16_genoa, simsimd_mahalanobis_bf16_accurate);
1013
- curved_<bf16c_k>("bilinear_bf16c_genoa", simsimd_bilinear_bf16c_genoa, simsimd_bilinear_bf16c_accurate);
1014
- #endif
1015
-
1016
- #if SIMSIMD_TARGET_SAPPHIRE
1017
- dense_<f16_k>("dot_f16_sapphire", simsimd_dot_f16_sapphire, simsimd_dot_f16_accurate);
1018
- dense_<f16_k>("cos_f16_sapphire", simsimd_cos_f16_sapphire, simsimd_cos_f16_accurate);
1019
- dense_<f16_k>("l2sq_f16_sapphire", simsimd_l2sq_f16_sapphire, simsimd_l2sq_f16_accurate);
1020
- dense_<f16_k>("l2_f16_sapphire", simsimd_l2_f16_sapphire, simsimd_l2_f16_accurate);
1021
- dense_<f16_k>("kl_f16_sapphire", simsimd_kl_f16_sapphire, simsimd_kl_f16_accurate);
1022
- dense_<f16_k>("js_f16_sapphire", simsimd_js_f16_sapphire, simsimd_js_f16_accurate);
1023
-
1024
- dense_<f16c_k>("dot_f16c_sapphire", simsimd_dot_f16c_sapphire, simsimd_dot_f16c_accurate);
1025
- dense_<f16c_k>("vdot_f16c_sapphire", simsimd_vdot_f16c_sapphire, simsimd_vdot_f16c_accurate);
1026
-
1027
- fma_<u8_k>("fma_u8_sapphire", simsimd_fma_u8_sapphire, simsimd_fma_u8_accurate, simsimd_l2_u8_serial);
1028
- fma_<u8_k>("wsum_u8_sapphire", simsimd_wsum_u8_sapphire, simsimd_wsum_u8_accurate, simsimd_l2_u8_serial);
1029
- fma_<i8_k>("fma_i8_sapphire", simsimd_fma_i8_sapphire, simsimd_fma_i8_accurate, simsimd_l2_i8_serial);
1030
- fma_<i8_k>("wsum_i8_sapphire", simsimd_wsum_i8_sapphire, simsimd_wsum_i8_accurate, simsimd_l2_i8_serial);
1031
-
1032
- curved_<f16_k>("bilinear_f16_sapphire", simsimd_bilinear_f16_sapphire, simsimd_bilinear_f16_accurate);
1033
- curved_<f16_k>("mahalanobis_f16_sapphire", simsimd_mahalanobis_f16_sapphire, simsimd_mahalanobis_f16_accurate);
1034
- curved_<f16c_k>("bilinear_f16c_sapphire", simsimd_bilinear_f16c_sapphire, simsimd_bilinear_f16c_accurate);
1035
- #endif
1036
-
1037
- #if SIMSIMD_TARGET_ICE
1038
- dense_<i8_k>("cos_i8_ice", simsimd_cos_i8_ice, simsimd_cos_i8_serial);
1039
- dense_<i8_k>("l2sq_i8_ice", simsimd_l2sq_i8_ice, simsimd_l2sq_i8_serial);
1040
- dense_<i8_k>("l2_i8_ice", simsimd_l2_i8_ice, simsimd_l2_i8_serial);
1041
- dense_<i8_k>("dot_i8_ice", simsimd_dot_i8_ice, simsimd_dot_i8_serial);
1042
-
1043
- dense_<u8_k>("cos_u8_ice", simsimd_cos_u8_ice, simsimd_cos_u8_serial);
1044
- dense_<u8_k>("l2sq_u8_ice", simsimd_l2sq_u8_ice, simsimd_l2sq_u8_serial);
1045
- dense_<u8_k>("l2_u8_ice", simsimd_l2_u8_ice, simsimd_l2_u8_serial);
1046
- dense_<u8_k>("dot_u8_ice", simsimd_dot_u8_ice, simsimd_dot_u8_serial);
1047
-
1048
- dense_<f64_k>("dot_f64_skylake", simsimd_dot_f64_skylake, simsimd_dot_f64_serial);
1049
- dense_<f64_k>("cos_f64_skylake", simsimd_cos_f64_skylake, simsimd_cos_f64_serial);
1050
- dense_<f64_k>("l2sq_f64_skylake", simsimd_l2sq_f64_skylake, simsimd_l2sq_f64_serial);
1051
- dense_<f64_k>("l2_f64_skylake", simsimd_l2_f64_skylake, simsimd_l2_f64_serial);
1052
-
1053
- dense_<b8_k>("hamming_b8_ice", simsimd_hamming_b8_ice, simsimd_hamming_b8_serial);
1054
- dense_<b8_k>("jaccard_b8_ice", simsimd_jaccard_b8_ice, simsimd_jaccard_b8_serial);
1055
-
1056
- sparse_<u16_k>("intersect_u16_ice", simsimd_intersect_u16_ice, simsimd_intersect_u16_accurate);
1057
- sparse_<u32_k>("intersect_u32_ice", simsimd_intersect_u32_ice, simsimd_intersect_u32_accurate);
1058
- #endif
1059
-
1060
- #if SIMSIMD_TARGET_TURIN
1061
- sparse_<u16_k>("intersect_u16_turin", simsimd_intersect_u16_turin, simsimd_intersect_u16_accurate);
1062
- sparse_<u32_k>("intersect_u32_turin", simsimd_intersect_u32_turin, simsimd_intersect_u32_accurate);
1063
- #endif
1064
-
1065
- #if SIMSIMD_TARGET_SKYLAKE
1066
- dense_<f32_k>("dot_f32_skylake", simsimd_dot_f32_skylake, simsimd_dot_f32_accurate);
1067
- dense_<f32_k>("cos_f32_skylake", simsimd_cos_f32_skylake, simsimd_cos_f32_accurate);
1068
- dense_<f32_k>("l2sq_f32_skylake", simsimd_l2sq_f32_skylake, simsimd_l2sq_f32_accurate);
1069
- dense_<f32_k>("l2_f32_skylake", simsimd_l2_f32_skylake, simsimd_l2_f32_accurate);
1070
- dense_<f32_k>("kl_f32_skylake", simsimd_kl_f32_skylake, simsimd_kl_f32_accurate);
1071
- dense_<f32_k>("js_f32_skylake", simsimd_js_f32_skylake, simsimd_js_f32_accurate);
1072
-
1073
- dense_<f32c_k>("dot_f32c_skylake", simsimd_dot_f32c_skylake, simsimd_dot_f32c_accurate);
1074
- dense_<f32c_k>("vdot_f32c_skylake", simsimd_vdot_f32c_skylake, simsimd_vdot_f32c_accurate);
1075
- dense_<f64c_k>("dot_f64c_skylake", simsimd_dot_f64c_skylake, simsimd_dot_f64c_serial);
1076
- dense_<f64c_k>("vdot_f64c_skylake", simsimd_vdot_f64c_skylake, simsimd_vdot_f64c_serial);
1077
-
1078
- fma_<f64_k>("fma_f64_skylake", simsimd_fma_f64_skylake, simsimd_fma_f64_serial, simsimd_l2_f64_serial);
1079
- fma_<f64_k>("wsum_f64_skylake", simsimd_wsum_f64_skylake, simsimd_wsum_f64_serial, simsimd_l2_f64_serial);
1080
- fma_<f32_k>("fma_f32_skylake", simsimd_fma_f32_skylake, simsimd_fma_f32_accurate, simsimd_l2_f32_accurate);
1081
- fma_<f32_k>("wsum_f32_skylake", simsimd_wsum_f32_skylake, simsimd_wsum_f32_accurate, simsimd_l2_f32_accurate);
1082
- fma_<bf16_k>("fma_bf16_skylake", simsimd_fma_bf16_skylake, simsimd_fma_bf16_accurate, simsimd_l2_bf16_accurate);
1083
- fma_<bf16_k>("wsum_bf16_skylake", simsimd_wsum_bf16_skylake, simsimd_wsum_bf16_accurate, simsimd_l2_bf16_accurate);
1084
-
1085
- curved_<f32_k>("bilinear_f32_skylake", simsimd_bilinear_f32_skylake, simsimd_bilinear_f32_serial);
1086
- curved_<f32c_k>("bilinear_f32c_skylake", simsimd_bilinear_f32c_skylake, simsimd_bilinear_f32c_serial);
1087
- curved_<f64_k>("bilinear_f64_skylake", simsimd_bilinear_f64_skylake, simsimd_bilinear_f64_serial);
1088
- curved_<f64c_k>("bilinear_f64c_skylake", simsimd_bilinear_f64c_skylake, simsimd_bilinear_f64c_serial);
1089
- #endif
1090
-
1091
- sparse_<u16_k>("intersect_u16_serial", simsimd_intersect_u16_serial, simsimd_intersect_u16_accurate);
1092
- sparse_<u16_k>("intersect_u16_accurate", simsimd_intersect_u16_accurate, simsimd_intersect_u16_accurate);
1093
- sparse_<u32_k>("intersect_u32_serial", simsimd_intersect_u32_serial, simsimd_intersect_u32_accurate);
1094
- sparse_<u32_k>("intersect_u32_accurate", simsimd_intersect_u32_accurate, simsimd_intersect_u32_accurate);
1095
-
1096
- curved_<f64_k>("bilinear_f64_serial", simsimd_bilinear_f64_serial, simsimd_bilinear_f64_serial);
1097
- curved_<f64c_k>("bilinear_f64c_serial", simsimd_bilinear_f64c_serial, simsimd_bilinear_f64c_serial);
1098
- curved_<f64_k>("mahalanobis_f64_serial", simsimd_mahalanobis_f64_serial, simsimd_mahalanobis_f64_serial);
1099
- curved_<f32_k>("bilinear_f32_serial", simsimd_bilinear_f32_serial, simsimd_bilinear_f32_accurate);
1100
- curved_<f32c_k>("bilinear_f32c_serial", simsimd_bilinear_f32c_serial, simsimd_bilinear_f32c_accurate);
1101
- curved_<f32_k>("mahalanobis_f32_serial", simsimd_mahalanobis_f32_serial, simsimd_mahalanobis_f32_accurate);
1102
- curved_<f16_k>("bilinear_f16_serial", simsimd_bilinear_f16_serial, simsimd_bilinear_f16_accurate);
1103
- curved_<f16c_k>("bilinear_f16c_serial", simsimd_bilinear_f16c_serial, simsimd_bilinear_f16c_accurate);
1104
- curved_<f16_k>("mahalanobis_f16_serial", simsimd_mahalanobis_f16_serial, simsimd_mahalanobis_f16_accurate);
1105
- curved_<bf16_k>("bilinear_bf16_serial", simsimd_bilinear_bf16_serial, simsimd_bilinear_bf16_accurate);
1106
- curved_<bf16c_k>("bilinear_bf16c_serial", simsimd_bilinear_bf16c_serial, simsimd_bilinear_bf16c_accurate);
1107
- curved_<bf16_k>("mahalanobis_bf16_serial", simsimd_mahalanobis_bf16_serial, simsimd_mahalanobis_bf16_accurate);
1108
-
1109
- dense_<bf16_k>("dot_bf16_serial", simsimd_dot_bf16_serial, simsimd_dot_bf16_accurate);
1110
- dense_<bf16_k>("cos_bf16_serial", simsimd_cos_bf16_serial, simsimd_cos_bf16_accurate);
1111
- dense_<bf16_k>("l2sq_bf16_serial", simsimd_l2sq_bf16_serial, simsimd_l2sq_bf16_accurate);
1112
- dense_<bf16_k>("l2_bf16_serial", simsimd_l2_bf16_serial, simsimd_l2_bf16_accurate);
1113
- dense_<bf16_k>("kl_bf16_serial", simsimd_kl_bf16_serial, simsimd_kl_bf16_accurate);
1114
- dense_<bf16_k>("js_bf16_serial", simsimd_js_bf16_serial, simsimd_js_bf16_accurate);
1115
-
1116
- dense_<f16_k>("dot_f16_serial", simsimd_dot_f16_serial, simsimd_dot_f16_accurate);
1117
- dense_<f16_k>("cos_f16_serial", simsimd_cos_f16_serial, simsimd_cos_f16_accurate);
1118
- dense_<f16_k>("l2sq_f16_serial", simsimd_l2sq_f16_serial, simsimd_l2sq_f16_accurate);
1119
- dense_<f16_k>("l2_f16_serial", simsimd_l2_f16_serial, simsimd_l2_f16_accurate);
1120
- dense_<f16_k>("kl_f16_serial", simsimd_kl_f16_serial, simsimd_kl_f16_accurate);
1121
- dense_<f16_k>("js_f16_serial", simsimd_js_f16_serial, simsimd_js_f16_accurate);
1122
-
1123
- dense_<f32_k>("dot_f32_serial", simsimd_dot_f32_serial, simsimd_dot_f32_accurate);
1124
- dense_<f32_k>("cos_f32_serial", simsimd_cos_f32_serial, simsimd_cos_f32_accurate);
1125
- dense_<f32_k>("l2sq_f32_serial", simsimd_l2sq_f32_serial, simsimd_l2sq_f32_accurate);
1126
- dense_<f32_k>("l2_f32_serial", simsimd_l2_f32_serial, simsimd_l2_f32_accurate);
1127
- dense_<f32_k>("kl_f32_serial", simsimd_kl_f32_serial, simsimd_kl_f32_accurate);
1128
- dense_<f32_k>("js_f32_serial", simsimd_js_f32_serial, simsimd_js_f32_accurate);
1129
-
1130
- dense_<f64_k>("dot_f64_serial", simsimd_dot_f64_serial, simsimd_dot_f64_serial);
1131
- dense_<f64_k>("cos_f64_serial", simsimd_cos_f64_serial, simsimd_cos_f64_serial);
1132
- dense_<f64_k>("l2sq_f64_serial", simsimd_l2sq_f64_serial, simsimd_l2sq_f64_serial);
1133
- dense_<f64_k>("l2_f64_serial", simsimd_l2_f64_serial, simsimd_l2_f64_serial);
1134
-
1135
- dense_<i8_k>("cos_i8_serial", simsimd_cos_i8_serial, simsimd_cos_i8_serial);
1136
- dense_<i8_k>("l2sq_i8_serial", simsimd_l2sq_i8_serial, simsimd_l2sq_i8_serial);
1137
- dense_<i8_k>("l2_i8_serial", simsimd_l2_i8_serial, simsimd_l2_i8_serial);
1138
- dense_<i8_k>("dot_i8_serial", simsimd_dot_i8_serial, simsimd_dot_i8_serial);
1139
-
1140
- dense_<u8_k>("cos_u8_serial", simsimd_cos_u8_serial, simsimd_cos_u8_serial);
1141
- dense_<u8_k>("l2sq_u8_serial", simsimd_l2sq_u8_serial, simsimd_l2sq_u8_serial);
1142
- dense_<u8_k>("l2_u8_serial", simsimd_l2_u8_serial, simsimd_l2_u8_serial);
1143
- dense_<u8_k>("dot_u8_serial", simsimd_dot_u8_serial, simsimd_dot_u8_serial);
1144
-
1145
- dense_<f64c_k>("dot_f64c_serial", simsimd_dot_f64c_serial, simsimd_dot_f64c_serial);
1146
- dense_<f32c_k>("dot_f32c_serial", simsimd_dot_f32c_serial, simsimd_dot_f32c_accurate);
1147
- dense_<f16c_k>("dot_f16c_serial", simsimd_dot_f16c_serial, simsimd_dot_f16c_accurate);
1148
- dense_<bf16c_k>("dot_bf16c_serial", simsimd_dot_bf16c_serial, simsimd_dot_bf16c_accurate);
1149
- dense_<f64c_k>("vdot_f64c_serial", simsimd_vdot_f64c_serial, simsimd_vdot_f64c_serial);
1150
- dense_<f32c_k>("vdot_f32c_serial", simsimd_vdot_f32c_serial, simsimd_vdot_f32c_accurate);
1151
- dense_<f16c_k>("vdot_f16c_serial", simsimd_vdot_f16c_serial, simsimd_vdot_f16c_accurate);
1152
- dense_<bf16c_k>("vdot_bf16c_serial", simsimd_vdot_bf16c_serial, simsimd_vdot_bf16c_accurate);
1153
-
1154
- dense_<f16c_k>("vdot_f16c_serial", simsimd_vdot_f16c_serial, simsimd_vdot_f16c_accurate);
1155
- dense_<bf16c_k>("vdot_bf16c_serial", simsimd_vdot_bf16c_serial, simsimd_vdot_bf16c_accurate);
1156
-
1157
- dense_<b8_k>("hamming_b8_serial", simsimd_hamming_b8_serial, simsimd_hamming_b8_serial);
1158
- dense_<b8_k>("jaccard_b8_serial", simsimd_jaccard_b8_serial, simsimd_jaccard_b8_serial);
1159
-
1160
- fma_<f16_k>("fma_f16_serial", simsimd_fma_f16_serial, simsimd_fma_f16_accurate, simsimd_l2_f16_accurate);
1161
- fma_<f16_k>("wsum_f16_serial", simsimd_wsum_f16_serial, simsimd_wsum_f16_accurate, simsimd_l2_f16_accurate);
1162
- fma_<u8_k>("fma_u8_serial", simsimd_fma_u8_serial, simsimd_fma_u8_accurate, simsimd_l2_u8_serial);
1163
- fma_<u8_k>("wsum_u8_serial", simsimd_wsum_u8_serial, simsimd_wsum_u8_accurate, simsimd_l2_u8_serial);
1164
- fma_<i8_k>("fma_i8_serial", simsimd_fma_i8_serial, simsimd_fma_i8_accurate, simsimd_l2_i8_serial);
1165
- fma_<i8_k>("wsum_i8_serial", simsimd_wsum_i8_serial, simsimd_wsum_i8_accurate, simsimd_l2_i8_serial);
1166
-
1167
- bm::RunSpecifiedBenchmarks();
1168
- bm::Shutdown();
1169
- return 0;
1170
- }