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,606 +0,0 @@
1
- /**
2
- * @file probability.h
3
- * @brief SIMD-accelerated Similarity Measures for Probability Distributions.
4
- * @author Ash Vardanian
5
- * @date October 20, 2023
6
- *
7
- * Contains:
8
- * - Kullback-Leibler divergence
9
- * - Jensen–Shannon divergence
10
- *
11
- * For datatypes:
12
- * - 32-bit floating point numbers
13
- * - 16-bit floating point numbers
14
- * - 16-bit brain-floating point numbers
15
- *
16
- * For hardware architectures:
17
- * - Arm: NEON
18
- * - x86: Haswell, Skylake, Sapphire
19
- *
20
- * x86 intrinsics: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/
21
- * Arm intrinsics: https://developer.arm.com/architectures/instruction-sets/intrinsics/
22
- */
23
- #ifndef SIMSIMD_PROBABILITY_H
24
- #define SIMSIMD_PROBABILITY_H
25
-
26
- #include "types.h"
27
-
28
- #ifdef __cplusplus
29
- extern "C" {
30
- #endif
31
-
32
- // clang-format off
33
-
34
- /* Serial backends for all numeric types.
35
- * By default they use 32-bit arithmetic, unless the arguments themselves contain 64-bit floats.
36
- * For double-precision computation check out the "*_accurate" variants of those "*_serial" functions.
37
- */
38
- SIMSIMD_PUBLIC void simsimd_kl_f64_serial(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
39
- SIMSIMD_PUBLIC void simsimd_js_f64_serial(simsimd_f64_t const* a, simsimd_f64_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
40
- SIMSIMD_PUBLIC void simsimd_kl_f32_serial(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
41
- SIMSIMD_PUBLIC void simsimd_js_f32_serial(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
42
- SIMSIMD_PUBLIC void simsimd_kl_f16_serial(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
43
- SIMSIMD_PUBLIC void simsimd_js_f16_serial(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
44
- SIMSIMD_PUBLIC void simsimd_kl_bf16_serial(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
45
- SIMSIMD_PUBLIC void simsimd_js_bf16_serial(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
46
-
47
- /* Double-precision serial backends for all numeric types.
48
- * For single-precision computation check out the "*_serial" counterparts of those "*_accurate" functions.
49
- */
50
- SIMSIMD_PUBLIC void simsimd_kl_f32_accurate(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
51
- SIMSIMD_PUBLIC void simsimd_js_f32_accurate(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
52
- SIMSIMD_PUBLIC void simsimd_kl_f16_accurate(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
53
- SIMSIMD_PUBLIC void simsimd_js_f16_accurate(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
54
- SIMSIMD_PUBLIC void simsimd_kl_bf16_accurate(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
55
- SIMSIMD_PUBLIC void simsimd_js_bf16_accurate(simsimd_bf16_t const* a, simsimd_bf16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
56
-
57
- /* SIMD-powered backends for Arm NEON, mostly using 32-bit arithmetic over 128-bit words.
58
- * By far the most portable backend, covering most Arm v8 devices, over a billion phones, and almost all
59
- * server CPUs produced before 2023.
60
- */
61
- SIMSIMD_PUBLIC void simsimd_kl_f32_neon(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
62
- SIMSIMD_PUBLIC void simsimd_js_f32_neon(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
63
- SIMSIMD_PUBLIC void simsimd_kl_f16_neon(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
64
- SIMSIMD_PUBLIC void simsimd_js_f16_neon(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
65
-
66
- /* SIMD-powered backends for AVX2 CPUs of Haswell generation and newer, using 32-bit arithmetic over 256-bit words.
67
- * First demonstrated in 2011, at least one Haswell-based processor was still being sold in 2022 — the Pentium G3420.
68
- * Practically all modern x86 CPUs support AVX2, FMA, and F16C, making it a perfect baseline for SIMD algorithms.
69
- * On other hand, there is no need to implement AVX2 versions of `f32` and `f64` functions, as those are
70
- * properly vectorized by recent compilers.
71
- */
72
- SIMSIMD_PUBLIC void simsimd_kl_f16_haswell(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
73
- SIMSIMD_PUBLIC void simsimd_js_f16_haswell(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
74
-
75
- /* SIMD-powered backends for various generations of AVX512 CPUs.
76
- * Skylake is handy, as it supports masked loads and other operations, avoiding the need for the tail loop.
77
- * Ice Lake added VNNI, VPOPCNTDQ, IFMA, VBMI, VAES, GFNI, VBMI2, BITALG, VPCLMULQDQ, and other extensions for integral operations.
78
- * Sapphire Rapids added tiled matrix operations, but we are most interested in the new mixed-precision FMA instructions.
79
- */
80
- SIMSIMD_PUBLIC void simsimd_kl_f32_skylake(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
81
- SIMSIMD_PUBLIC void simsimd_js_f32_skylake(simsimd_f32_t const* a, simsimd_f32_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
82
- SIMSIMD_PUBLIC void simsimd_kl_f16_sapphire(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
83
- SIMSIMD_PUBLIC void simsimd_js_f16_sapphire(simsimd_f16_t const* a, simsimd_f16_t const* b, simsimd_size_t n, simsimd_distance_t* divergence);
84
- // clang-format on
85
-
86
- #define SIMSIMD_MAKE_KL(name, input_type, accumulator_type, load_and_convert, epsilon) \
87
- SIMSIMD_PUBLIC void simsimd_kl_##input_type##_##name(simsimd_##input_type##_t const *a, \
88
- simsimd_##input_type##_t const *b, simsimd_size_t n, \
89
- simsimd_distance_t *result) { \
90
- simsimd_##accumulator_type##_t d = 0; \
91
- for (simsimd_size_t i = 0; i != n; ++i) { \
92
- simsimd_##accumulator_type##_t ai = load_and_convert(a + i); \
93
- simsimd_##accumulator_type##_t bi = load_and_convert(b + i); \
94
- d += ai * SIMSIMD_LOG((ai + epsilon) / (bi + epsilon)); \
95
- } \
96
- *result = (simsimd_distance_t)d; \
97
- }
98
-
99
- #define SIMSIMD_MAKE_JS(name, input_type, accumulator_type, load_and_convert, epsilon) \
100
- SIMSIMD_PUBLIC void simsimd_js_##input_type##_##name(simsimd_##input_type##_t const *a, \
101
- simsimd_##input_type##_t const *b, simsimd_size_t n, \
102
- simsimd_distance_t *result) { \
103
- simsimd_##accumulator_type##_t d = 0; \
104
- for (simsimd_size_t i = 0; i != n; ++i) { \
105
- simsimd_##accumulator_type##_t ai = load_and_convert(a + i); \
106
- simsimd_##accumulator_type##_t bi = load_and_convert(b + i); \
107
- simsimd_##accumulator_type##_t mi = (ai + bi) / 2; \
108
- d += ai * SIMSIMD_LOG((ai + epsilon) / (mi + epsilon)); \
109
- d += bi * SIMSIMD_LOG((bi + epsilon) / (mi + epsilon)); \
110
- } \
111
- *result = SIMSIMD_SQRT(((simsimd_distance_t)d / 2)); \
112
- }
113
-
114
- SIMSIMD_MAKE_KL(serial, f64, f64, SIMSIMD_DEREFERENCE, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_kl_f64_serial
115
- SIMSIMD_MAKE_JS(serial, f64, f64, SIMSIMD_DEREFERENCE, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_js_f64_serial
116
-
117
- SIMSIMD_MAKE_KL(serial, f32, f32, SIMSIMD_DEREFERENCE, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_kl_f32_serial
118
- SIMSIMD_MAKE_JS(serial, f32, f32, SIMSIMD_DEREFERENCE, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_js_f32_serial
119
-
120
- SIMSIMD_MAKE_KL(serial, f16, f32, SIMSIMD_F16_TO_F32, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_kl_f16_serial
121
- SIMSIMD_MAKE_JS(serial, f16, f32, SIMSIMD_F16_TO_F32, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_js_f16_serial
122
-
123
- SIMSIMD_MAKE_KL(serial, bf16, f32, SIMSIMD_BF16_TO_F32, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_kl_bf16_serial
124
- SIMSIMD_MAKE_JS(serial, bf16, f32, SIMSIMD_BF16_TO_F32, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_js_bf16_serial
125
-
126
- SIMSIMD_MAKE_KL(accurate, f32, f64, SIMSIMD_DEREFERENCE, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_kl_f32_accurate
127
- SIMSIMD_MAKE_JS(accurate, f32, f64, SIMSIMD_DEREFERENCE, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_js_f32_accurate
128
-
129
- SIMSIMD_MAKE_KL(accurate, f16, f64, SIMSIMD_F16_TO_F32, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_kl_f16_accurate
130
- SIMSIMD_MAKE_JS(accurate, f16, f64, SIMSIMD_F16_TO_F32, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_js_f16_accurate
131
-
132
- SIMSIMD_MAKE_KL(accurate, bf16, f64, SIMSIMD_BF16_TO_F32, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_kl_bf16_accurate
133
- SIMSIMD_MAKE_JS(accurate, bf16, f64, SIMSIMD_BF16_TO_F32, SIMSIMD_F32_DIVISION_EPSILON) // simsimd_js_bf16_accurate
134
-
135
- #if _SIMSIMD_TARGET_ARM
136
- #if SIMSIMD_TARGET_NEON
137
- #pragma GCC push_options
138
- #pragma GCC target("arch=armv8.2-a+simd")
139
- #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+simd"))), apply_to = function)
140
-
141
- SIMSIMD_PUBLIC float32x4_t _simsimd_log2_f32_neon(float32x4_t x) {
142
- // Extracting the exponent
143
- int32x4_t i = vreinterpretq_s32_f32(x);
144
- int32x4_t e = vsubq_s32(vshrq_n_s32(vandq_s32(i, vdupq_n_s32(0x7F800000)), 23), vdupq_n_s32(127));
145
- float32x4_t e_float = vcvtq_f32_s32(e);
146
-
147
- // Extracting the mantissa
148
- float32x4_t m = vreinterpretq_f32_s32(vorrq_s32(vandq_s32(i, vdupq_n_s32(0x007FFFFF)), vdupq_n_s32(0x3F800000)));
149
-
150
- // Constants for polynomial
151
- float32x4_t one = vdupq_n_f32(1.0f);
152
- float32x4_t p = vdupq_n_f32(-3.4436006e-2f);
153
-
154
- // Compute polynomial using Horner's method
155
- p = vmlaq_f32(vdupq_n_f32(3.1821337e-1f), m, p);
156
- p = vmlaq_f32(vdupq_n_f32(-1.2315303f), m, p);
157
- p = vmlaq_f32(vdupq_n_f32(2.5988452f), m, p);
158
- p = vmlaq_f32(vdupq_n_f32(-3.3241990f), m, p);
159
- p = vmlaq_f32(vdupq_n_f32(3.1157899f), m, p);
160
-
161
- // Final computation
162
- float32x4_t result = vaddq_f32(vmulq_f32(p, vsubq_f32(m, one)), e_float);
163
- return result;
164
- }
165
-
166
- SIMSIMD_PUBLIC void simsimd_kl_f32_neon(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
167
- simsimd_distance_t *result) {
168
- simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
169
- float32x4_t epsilon_vec = vdupq_n_f32(epsilon);
170
- float32x4_t sum_vec = vdupq_n_f32(0);
171
- float32x4_t a_vec, b_vec;
172
-
173
- simsimd_kl_f32_neon_cycle:
174
- if (n < 4) {
175
- a_vec = _simsimd_partial_load_f32x4_neon(a, n);
176
- b_vec = _simsimd_partial_load_f32x4_neon(b, n);
177
- n = 0;
178
- }
179
- else {
180
- a_vec = vld1q_f32(a);
181
- b_vec = vld1q_f32(b);
182
- n -= 4, a += 4, b += 4;
183
- }
184
-
185
- float32x4_t ratio_vec = vdivq_f32(vaddq_f32(a_vec, epsilon_vec), vaddq_f32(b_vec, epsilon_vec));
186
- float32x4_t log_ratio_vec = _simsimd_log2_f32_neon(ratio_vec);
187
- float32x4_t prod_vec = vmulq_f32(a_vec, log_ratio_vec);
188
- sum_vec = vaddq_f32(sum_vec, prod_vec);
189
- if (n != 0) goto simsimd_kl_f32_neon_cycle;
190
-
191
- simsimd_f32_t log2_normalizer = 0.693147181f;
192
- simsimd_f32_t sum = vaddvq_f32(sum_vec) * log2_normalizer;
193
- *result = sum;
194
- }
195
-
196
- SIMSIMD_PUBLIC void simsimd_js_f32_neon(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
197
- simsimd_distance_t *result) {
198
- simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
199
- float32x4_t epsilon_vec = vdupq_n_f32(epsilon);
200
- float32x4_t sum_vec = vdupq_n_f32(0);
201
- float32x4_t a_vec, b_vec;
202
-
203
- simsimd_js_f32_neon_cycle:
204
- if (n < 4) {
205
- a_vec = _simsimd_partial_load_f32x4_neon(a, n);
206
- b_vec = _simsimd_partial_load_f32x4_neon(b, n);
207
- n = 0;
208
- }
209
- else {
210
- a_vec = vld1q_f32(a);
211
- b_vec = vld1q_f32(b);
212
- n -= 4, a += 4, b += 4;
213
- }
214
-
215
- float32x4_t m_vec = vmulq_f32(vaddq_f32(a_vec, b_vec), vdupq_n_f32(0.5));
216
- float32x4_t ratio_a_vec = vdivq_f32(vaddq_f32(a_vec, epsilon_vec), vaddq_f32(m_vec, epsilon_vec));
217
- float32x4_t ratio_b_vec = vdivq_f32(vaddq_f32(b_vec, epsilon_vec), vaddq_f32(m_vec, epsilon_vec));
218
- float32x4_t log_ratio_a_vec = _simsimd_log2_f32_neon(ratio_a_vec);
219
- float32x4_t log_ratio_b_vec = _simsimd_log2_f32_neon(ratio_b_vec);
220
- float32x4_t prod_a_vec = vmulq_f32(a_vec, log_ratio_a_vec);
221
- float32x4_t prod_b_vec = vmulq_f32(b_vec, log_ratio_b_vec);
222
-
223
- sum_vec = vaddq_f32(sum_vec, vaddq_f32(prod_a_vec, prod_b_vec));
224
- if (n != 0) goto simsimd_js_f32_neon_cycle;
225
-
226
- simsimd_f32_t log2_normalizer = 0.693147181f;
227
- simsimd_f32_t sum = vaddvq_f32(sum_vec) * log2_normalizer / 2;
228
- *result = _simsimd_sqrt_f32_neon(sum);
229
- }
230
-
231
- #pragma clang attribute pop
232
- #pragma GCC pop_options
233
- #endif // SIMSIMD_TARGET_NEON
234
-
235
- #if SIMSIMD_TARGET_NEON_F16
236
- #pragma GCC push_options
237
- #pragma GCC target("arch=armv8.2-a+simd+fp16")
238
- #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+simd+fp16"))), apply_to = function)
239
-
240
- SIMSIMD_PUBLIC void simsimd_kl_f16_neon(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
241
- simsimd_distance_t *result) {
242
- float32x4_t sum_vec = vdupq_n_f32(0);
243
- simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
244
- float32x4_t epsilon_vec = vdupq_n_f32(epsilon);
245
- float32x4_t a_vec, b_vec;
246
-
247
- simsimd_kl_f16_neon_cycle:
248
- if (n < 4) {
249
- a_vec = vcvt_f32_f16(_simsimd_partial_load_f16x4_neon(a, n));
250
- b_vec = vcvt_f32_f16(_simsimd_partial_load_f16x4_neon(b, n));
251
- n = 0;
252
- }
253
- else {
254
- a_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)a));
255
- b_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)b));
256
- n -= 4, a += 4, b += 4;
257
- }
258
-
259
- float32x4_t ratio_vec = vdivq_f32(vaddq_f32(a_vec, epsilon_vec), vaddq_f32(b_vec, epsilon_vec));
260
- float32x4_t log_ratio_vec = _simsimd_log2_f32_neon(ratio_vec);
261
- float32x4_t prod_vec = vmulq_f32(a_vec, log_ratio_vec);
262
- sum_vec = vaddq_f32(sum_vec, prod_vec);
263
- if (n) goto simsimd_kl_f16_neon_cycle;
264
-
265
- simsimd_f32_t log2_normalizer = 0.693147181f;
266
- simsimd_f32_t sum = vaddvq_f32(sum_vec) * log2_normalizer;
267
- *result = sum;
268
- }
269
-
270
- SIMSIMD_PUBLIC void simsimd_js_f16_neon(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
271
- simsimd_distance_t *result) {
272
- float32x4_t sum_vec = vdupq_n_f32(0);
273
- simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
274
- float32x4_t epsilon_vec = vdupq_n_f32(epsilon);
275
- float32x4_t a_vec, b_vec;
276
-
277
- simsimd_js_f16_neon_cycle:
278
- if (n < 4) {
279
- a_vec = vcvt_f32_f16(_simsimd_partial_load_f16x4_neon(a, n));
280
- b_vec = vcvt_f32_f16(_simsimd_partial_load_f16x4_neon(b, n));
281
- n = 0;
282
- }
283
- else {
284
- a_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)a));
285
- b_vec = vcvt_f32_f16(vld1_f16((simsimd_f16_for_arm_simd_t const *)b));
286
- n -= 4, a += 4, b += 4;
287
- }
288
-
289
- float32x4_t m_vec = vmulq_f32(vaddq_f32(a_vec, b_vec), vdupq_n_f32(0.5));
290
- float32x4_t ratio_a_vec = vdivq_f32(vaddq_f32(a_vec, epsilon_vec), vaddq_f32(m_vec, epsilon_vec));
291
- float32x4_t ratio_b_vec = vdivq_f32(vaddq_f32(b_vec, epsilon_vec), vaddq_f32(m_vec, epsilon_vec));
292
- float32x4_t log_ratio_a_vec = _simsimd_log2_f32_neon(ratio_a_vec);
293
- float32x4_t log_ratio_b_vec = _simsimd_log2_f32_neon(ratio_b_vec);
294
- float32x4_t prod_a_vec = vmulq_f32(a_vec, log_ratio_a_vec);
295
- float32x4_t prod_b_vec = vmulq_f32(b_vec, log_ratio_b_vec);
296
- sum_vec = vaddq_f32(sum_vec, vaddq_f32(prod_a_vec, prod_b_vec));
297
- if (n) goto simsimd_js_f16_neon_cycle;
298
-
299
- simsimd_f32_t log2_normalizer = 0.693147181f;
300
- simsimd_f32_t sum = vaddvq_f32(sum_vec) * log2_normalizer / 2;
301
- *result = _simsimd_sqrt_f32_neon(sum);
302
- }
303
-
304
- #pragma clang attribute pop
305
- #pragma GCC pop_options
306
- #endif // SIMSIMD_TARGET_NEON_F16
307
- #endif // _SIMSIMD_TARGET_ARM
308
-
309
- #if _SIMSIMD_TARGET_X86
310
- #if SIMSIMD_TARGET_HASWELL
311
- #pragma GCC push_options
312
- #pragma GCC target("avx2", "f16c", "fma")
313
- #pragma clang attribute push(__attribute__((target("avx2,f16c,fma"))), apply_to = function)
314
-
315
- SIMSIMD_INTERNAL __m256 _simsimd_log2_f32_haswell(__m256 x) {
316
- // Extracting the exponent
317
- __m256i i = _mm256_castps_si256(x);
318
- __m256i e = _mm256_srli_epi32(_mm256_and_si256(i, _mm256_set1_epi32(0x7F800000)), 23);
319
- e = _mm256_sub_epi32(e, _mm256_set1_epi32(127)); // removing the bias
320
- __m256 e_float = _mm256_cvtepi32_ps(e);
321
-
322
- // Extracting the mantissa
323
- __m256 m = _mm256_castsi256_ps(
324
- _mm256_or_si256(_mm256_and_si256(i, _mm256_set1_epi32(0x007FFFFF)), _mm256_set1_epi32(0x3F800000)));
325
-
326
- // Constants for polynomial
327
- __m256 one = _mm256_set1_ps(1.0f);
328
- __m256 p = _mm256_set1_ps(-3.4436006e-2f);
329
-
330
- // Compute the polynomial using Horner's method
331
- p = _mm256_fmadd_ps(m, p, _mm256_set1_ps(3.1821337e-1f));
332
- p = _mm256_fmadd_ps(m, p, _mm256_set1_ps(-1.2315303f));
333
- p = _mm256_fmadd_ps(m, p, _mm256_set1_ps(2.5988452f));
334
- p = _mm256_fmadd_ps(m, p, _mm256_set1_ps(-3.3241990f));
335
- p = _mm256_fmadd_ps(m, p, _mm256_set1_ps(3.1157899f));
336
-
337
- // Final computation
338
- __m256 result = _mm256_add_ps(_mm256_mul_ps(p, _mm256_sub_ps(m, one)), e_float);
339
- return result;
340
- }
341
-
342
- SIMSIMD_PUBLIC void simsimd_kl_f16_haswell(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
343
- simsimd_distance_t *result) {
344
- __m256 sum_vec = _mm256_setzero_ps();
345
- simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
346
- __m256 epsilon_vec = _mm256_set1_ps(epsilon);
347
- __m256 a_vec, b_vec;
348
-
349
- simsimd_kl_f16_haswell_cycle:
350
- if (n < 8) {
351
- a_vec = _simsimd_partial_load_f16x8_haswell(a, n);
352
- b_vec = _simsimd_partial_load_f16x8_haswell(b, n);
353
- n = 0;
354
- }
355
- else {
356
- a_vec = _mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)a));
357
- b_vec = _mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)b));
358
- n -= 8, a += 8, b += 8;
359
- }
360
- a_vec = _mm256_add_ps(a_vec, epsilon_vec);
361
- b_vec = _mm256_add_ps(b_vec, epsilon_vec);
362
- __m256 ratio_vec = _mm256_div_ps(a_vec, b_vec);
363
- __m256 log_ratio_vec = _simsimd_log2_f32_haswell(ratio_vec);
364
- __m256 prod_vec = _mm256_mul_ps(a_vec, log_ratio_vec);
365
- sum_vec = _mm256_add_ps(sum_vec, prod_vec);
366
- if (n) goto simsimd_kl_f16_haswell_cycle;
367
-
368
- simsimd_f32_t log2_normalizer = 0.693147181f;
369
- simsimd_f32_t sum = _simsimd_reduce_f32x8_haswell(sum_vec);
370
- sum *= log2_normalizer;
371
- *result = sum;
372
- }
373
-
374
- SIMSIMD_PUBLIC void simsimd_js_f16_haswell(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
375
- simsimd_distance_t *result) {
376
- simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
377
- __m256 epsilon_vec = _mm256_set1_ps(epsilon);
378
- __m256 sum_vec = _mm256_setzero_ps();
379
- __m256 a_vec, b_vec;
380
-
381
- simsimd_js_f16_haswell_cycle:
382
- if (n < 8) {
383
- a_vec = _simsimd_partial_load_f16x8_haswell(a, n);
384
- b_vec = _simsimd_partial_load_f16x8_haswell(b, n);
385
- n = 0;
386
- }
387
- else {
388
- a_vec = _mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)a));
389
- b_vec = _mm256_cvtph_ps(_mm_lddqu_si128((__m128i const *)b));
390
- n -= 8, a += 8, b += 8;
391
- }
392
- __m256 m_vec = _mm256_mul_ps(_mm256_add_ps(a_vec, b_vec), _mm256_set1_ps(0.5f)); // M = (P + Q) / 2
393
- __m256 ratio_a_vec = _mm256_div_ps(_mm256_add_ps(a_vec, epsilon_vec), _mm256_add_ps(m_vec, epsilon_vec));
394
- __m256 ratio_b_vec = _mm256_div_ps(_mm256_add_ps(b_vec, epsilon_vec), _mm256_add_ps(m_vec, epsilon_vec));
395
- __m256 log_ratio_a_vec = _simsimd_log2_f32_haswell(ratio_a_vec);
396
- __m256 log_ratio_b_vec = _simsimd_log2_f32_haswell(ratio_b_vec);
397
- __m256 prod_a_vec = _mm256_mul_ps(a_vec, log_ratio_a_vec);
398
- __m256 prod_b_vec = _mm256_mul_ps(b_vec, log_ratio_b_vec);
399
- sum_vec = _mm256_add_ps(sum_vec, prod_a_vec);
400
- sum_vec = _mm256_add_ps(sum_vec, prod_b_vec);
401
- if (n) goto simsimd_js_f16_haswell_cycle;
402
-
403
- simsimd_f32_t log2_normalizer = 0.693147181f;
404
- simsimd_f32_t sum = _simsimd_reduce_f32x8_haswell(sum_vec);
405
- sum *= log2_normalizer / 2;
406
- *result = _simsimd_sqrt_f32_haswell(sum);
407
- }
408
-
409
- #pragma clang attribute pop
410
- #pragma GCC pop_options
411
- #endif // SIMSIMD_TARGET_HASWELL
412
-
413
- #if SIMSIMD_TARGET_SKYLAKE
414
- #pragma GCC push_options
415
- #pragma GCC target("avx2", "avx512f", "avx512vl", "bmi2")
416
- #pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,bmi2"))), apply_to = function)
417
-
418
- SIMSIMD_INTERNAL __m512 _simsimd_log2_f32_skylake(__m512 x) {
419
- // Extract the exponent and mantissa
420
- __m512 one = _mm512_set1_ps(1.0f);
421
- __m512 e = _mm512_getexp_ps(x);
422
- __m512 m = _mm512_getmant_ps(x, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_src);
423
-
424
- // Compute the polynomial using Horner's method
425
- __m512 p = _mm512_set1_ps(-3.4436006e-2f);
426
- p = _mm512_fmadd_ps(m, p, _mm512_set1_ps(3.1821337e-1f));
427
- p = _mm512_fmadd_ps(m, p, _mm512_set1_ps(-1.2315303f));
428
- p = _mm512_fmadd_ps(m, p, _mm512_set1_ps(2.5988452f));
429
- p = _mm512_fmadd_ps(m, p, _mm512_set1_ps(-3.3241990f));
430
- p = _mm512_fmadd_ps(m, p, _mm512_set1_ps(3.1157899f));
431
-
432
- return _mm512_add_ps(_mm512_mul_ps(p, _mm512_sub_ps(m, one)), e);
433
- }
434
-
435
- SIMSIMD_PUBLIC void simsimd_kl_f32_skylake(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
436
- simsimd_distance_t *result) {
437
- __m512 sum_vec = _mm512_setzero();
438
- simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
439
- __m512 epsilon_vec = _mm512_set1_ps(epsilon);
440
- __m512 a_vec, b_vec;
441
-
442
- simsimd_kl_f32_skylake_cycle:
443
- if (n < 16) {
444
- __mmask16 mask = (__mmask16)_bzhi_u32(0xFFFFFFFF, n);
445
- a_vec = _mm512_add_ps(_mm512_maskz_loadu_ps(mask, a), epsilon_vec);
446
- b_vec = _mm512_add_ps(_mm512_maskz_loadu_ps(mask, b), epsilon_vec);
447
- n = 0;
448
- }
449
- else {
450
- a_vec = _mm512_add_ps(_mm512_loadu_ps(a), epsilon_vec);
451
- b_vec = _mm512_add_ps(_mm512_loadu_ps(b), epsilon_vec);
452
- a += 16, b += 16, n -= 16;
453
- }
454
- __m512 ratio_vec = _mm512_div_ps(a_vec, b_vec);
455
- __m512 log_ratio_vec = _simsimd_log2_f32_skylake(ratio_vec);
456
- __m512 prod_vec = _mm512_mul_ps(a_vec, log_ratio_vec);
457
- sum_vec = _mm512_add_ps(sum_vec, prod_vec);
458
- if (n) goto simsimd_kl_f32_skylake_cycle;
459
-
460
- simsimd_f32_t log2_normalizer = 0.693147181f;
461
- *result = _mm512_reduce_add_ps(sum_vec) * log2_normalizer;
462
- }
463
-
464
- SIMSIMD_PUBLIC void simsimd_js_f32_skylake(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
465
- simsimd_distance_t *result) {
466
- __m512 sum_a_vec = _mm512_setzero();
467
- __m512 sum_b_vec = _mm512_setzero();
468
- simsimd_f32_t epsilon = SIMSIMD_F32_DIVISION_EPSILON;
469
- __m512 epsilon_vec = _mm512_set1_ps(epsilon);
470
- __m512 a_vec, b_vec;
471
-
472
- simsimd_js_f32_skylake_cycle:
473
- if (n < 16) {
474
- __mmask16 mask = (__mmask16)_bzhi_u32(0xFFFFFFFF, n);
475
- a_vec = _mm512_maskz_loadu_ps(mask, a);
476
- b_vec = _mm512_maskz_loadu_ps(mask, b);
477
- n = 0;
478
- }
479
- else {
480
- a_vec = _mm512_loadu_ps(a);
481
- b_vec = _mm512_loadu_ps(b);
482
- a += 16, b += 16, n -= 16;
483
- }
484
- __m512 m_vec = _mm512_mul_ps(_mm512_add_ps(a_vec, b_vec), _mm512_set1_ps(0.5f));
485
- __mmask16 nonzero_mask_a = _mm512_cmp_ps_mask(a_vec, epsilon_vec, _CMP_GE_OQ);
486
- __mmask16 nonzero_mask_b = _mm512_cmp_ps_mask(b_vec, epsilon_vec, _CMP_GE_OQ);
487
- __mmask16 nonzero_mask = nonzero_mask_a & nonzero_mask_b;
488
- __m512 m_with_epsilon = _mm512_add_ps(m_vec, epsilon_vec);
489
- __m512 m_recip_approx = _mm512_rcp14_ps(m_with_epsilon);
490
- __m512 ratio_a_vec = _mm512_mul_ps(_mm512_add_ps(a_vec, epsilon_vec), m_recip_approx);
491
- __m512 ratio_b_vec = _mm512_mul_ps(_mm512_add_ps(b_vec, epsilon_vec), m_recip_approx);
492
- __m512 log_ratio_a_vec = _simsimd_log2_f32_skylake(ratio_a_vec);
493
- __m512 log_ratio_b_vec = _simsimd_log2_f32_skylake(ratio_b_vec);
494
- sum_a_vec = _mm512_mask3_fmadd_ps(a_vec, log_ratio_a_vec, sum_a_vec, nonzero_mask);
495
- sum_b_vec = _mm512_mask3_fmadd_ps(b_vec, log_ratio_b_vec, sum_b_vec, nonzero_mask);
496
- if (n) goto simsimd_js_f32_skylake_cycle;
497
-
498
- simsimd_f32_t log2_normalizer = 0.693147181f;
499
- simsimd_f32_t sum = _mm512_reduce_add_ps(_mm512_add_ps(sum_a_vec, sum_b_vec));
500
- sum *= log2_normalizer / 2;
501
- *result = _simsimd_sqrt_f32_haswell(sum);
502
- }
503
-
504
- #pragma clang attribute pop
505
- #pragma GCC pop_options
506
- #endif // SIMSIMD_TARGET_HASWELL
507
-
508
- #if SIMSIMD_TARGET_SAPPHIRE
509
- #pragma GCC push_options
510
- #pragma GCC target("avx2", "avx512f", "avx512vl", "bmi2", "avx512fp16")
511
- #pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,bmi2,avx512fp16"))), apply_to = function)
512
-
513
- SIMSIMD_INTERNAL __m512h _simsimd_log2_f16_sapphire(__m512h x) {
514
- // Extract the exponent and mantissa
515
- __m512h one = _mm512_set1_ph((simsimd_f16_t)1);
516
- __m512h e = _mm512_getexp_ph(x);
517
- __m512h m = _mm512_getmant_ph(x, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_src);
518
-
519
- // Compute the polynomial using Horner's method
520
- __m512h p = _mm512_set1_ph((simsimd_f16_t)-3.4436006e-2f);
521
- p = _mm512_fmadd_ph(m, p, _mm512_set1_ph((simsimd_f16_t)3.1821337e-1f));
522
- p = _mm512_fmadd_ph(m, p, _mm512_set1_ph((simsimd_f16_t)-1.2315303f));
523
- p = _mm512_fmadd_ph(m, p, _mm512_set1_ph((simsimd_f16_t)2.5988452f));
524
- p = _mm512_fmadd_ph(m, p, _mm512_set1_ph((simsimd_f16_t)-3.3241990f));
525
- p = _mm512_fmadd_ph(m, p, _mm512_set1_ph((simsimd_f16_t)3.1157899f));
526
-
527
- return _mm512_add_ph(_mm512_mul_ph(p, _mm512_sub_ph(m, one)), e);
528
- }
529
-
530
- SIMSIMD_PUBLIC void simsimd_kl_f16_sapphire(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
531
- simsimd_distance_t *result) {
532
- __m512h sum_vec = _mm512_setzero_ph();
533
- __m512h epsilon_vec = _mm512_set1_ph((simsimd_f16_t)SIMSIMD_F16_DIVISION_EPSILON);
534
- __m512h a_vec, b_vec;
535
-
536
- simsimd_kl_f16_sapphire_cycle:
537
- if (n < 32) {
538
- __mmask32 mask = (__mmask32)_bzhi_u32(0xFFFFFFFF, n);
539
- a_vec = _mm512_maskz_add_ph(mask, _mm512_castsi512_ph(_mm512_maskz_loadu_epi16(mask, a)), epsilon_vec);
540
- b_vec = _mm512_maskz_add_ph(mask, _mm512_castsi512_ph(_mm512_maskz_loadu_epi16(mask, b)), epsilon_vec);
541
- n = 0;
542
- }
543
- else {
544
- a_vec = _mm512_add_ph(_mm512_castsi512_ph(_mm512_loadu_epi16(a)), epsilon_vec);
545
- b_vec = _mm512_add_ph(_mm512_castsi512_ph(_mm512_loadu_epi16(b)), epsilon_vec);
546
- a += 32, b += 32, n -= 32;
547
- }
548
- __m512h ratio_vec = _mm512_div_ph(a_vec, b_vec);
549
- __m512h log_ratio_vec = _simsimd_log2_f16_sapphire(ratio_vec);
550
- __m512h prod_vec = _mm512_mul_ph(a_vec, log_ratio_vec);
551
- sum_vec = _mm512_add_ph(sum_vec, prod_vec);
552
- if (n) goto simsimd_kl_f16_sapphire_cycle;
553
-
554
- simsimd_f32_t log2_normalizer = 0.693147181f;
555
- *result = _mm512_reduce_add_ph(sum_vec) * log2_normalizer;
556
- }
557
-
558
- SIMSIMD_PUBLIC void simsimd_js_f16_sapphire(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
559
- simsimd_distance_t *result) {
560
- __m512h sum_a_vec = _mm512_setzero_ph();
561
- __m512h sum_b_vec = _mm512_setzero_ph();
562
- __m512h epsilon_vec = _mm512_set1_ph((simsimd_f16_t)SIMSIMD_F16_DIVISION_EPSILON);
563
- __m512h a_vec, b_vec;
564
-
565
- simsimd_js_f16_sapphire_cycle:
566
- if (n < 32) {
567
- __mmask32 mask = (__mmask32)_bzhi_u32(0xFFFFFFFF, n);
568
- a_vec = _mm512_castsi512_ph(_mm512_maskz_loadu_epi16(mask, a));
569
- b_vec = _mm512_castsi512_ph(_mm512_maskz_loadu_epi16(mask, b));
570
- n = 0;
571
- }
572
- else {
573
- a_vec = _mm512_castsi512_ph(_mm512_loadu_epi16(a));
574
- b_vec = _mm512_castsi512_ph(_mm512_loadu_epi16(b));
575
- a += 32, b += 32, n -= 32;
576
- }
577
- __m512h m_vec = _mm512_mul_ph(_mm512_add_ph(a_vec, b_vec), _mm512_set1_ph((simsimd_f16_t)0.5f));
578
- __mmask32 nonzero_mask_a = _mm512_cmp_ph_mask(a_vec, epsilon_vec, _CMP_GE_OQ);
579
- __mmask32 nonzero_mask_b = _mm512_cmp_ph_mask(b_vec, epsilon_vec, _CMP_GE_OQ);
580
- __mmask32 nonzero_mask = nonzero_mask_a & nonzero_mask_b;
581
- __m512h m_with_epsilon = _mm512_add_ph(m_vec, epsilon_vec);
582
- __m512h m_recip_approx = _mm512_rcp_ph(m_with_epsilon);
583
- __m512h ratio_a_vec = _mm512_mul_ph(_mm512_add_ph(a_vec, epsilon_vec), m_recip_approx);
584
- __m512h ratio_b_vec = _mm512_mul_ph(_mm512_add_ph(b_vec, epsilon_vec), m_recip_approx);
585
- __m512h log_ratio_a_vec = _simsimd_log2_f16_sapphire(ratio_a_vec);
586
- __m512h log_ratio_b_vec = _simsimd_log2_f16_sapphire(ratio_b_vec);
587
- sum_a_vec = _mm512_mask3_fmadd_ph(a_vec, log_ratio_a_vec, sum_a_vec, nonzero_mask);
588
- sum_b_vec = _mm512_mask3_fmadd_ph(b_vec, log_ratio_b_vec, sum_b_vec, nonzero_mask);
589
- if (n) goto simsimd_js_f16_sapphire_cycle;
590
-
591
- simsimd_f32_t log2_normalizer = 0.693147181f;
592
- simsimd_f32_t sum = _mm512_reduce_add_ph(_mm512_add_ph(sum_a_vec, sum_b_vec));
593
- sum *= log2_normalizer / 2;
594
- *result = _simsimd_sqrt_f32_haswell(sum);
595
- }
596
-
597
- #pragma clang attribute pop
598
- #pragma GCC pop_options
599
- #endif // SIMSIMD_TARGET_SAPPHIRE
600
- #endif // _SIMSIMD_TARGET_X86
601
-
602
- #ifdef __cplusplus
603
- }
604
- #endif
605
-
606
- #endif