usearch 2.21.4 → 2.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (604) hide show
  1. package/README.md +65 -69
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +8 -8
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +124 -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 +224 -48
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/README.md +1 -1
  16. package/javascript/dist/cjs/usearch.d.ts +8 -3
  17. package/javascript/dist/cjs/usearch.js +12 -4
  18. package/javascript/dist/esm/usearch.d.ts +8 -3
  19. package/javascript/dist/esm/usearch.js +12 -4
  20. package/javascript/lib.cpp +17 -0
  21. package/javascript/usearch.test.js +117 -94
  22. package/javascript/usearch.ts +14 -6
  23. package/numkong/.clang-tidy +30 -0
  24. package/{simsimd → numkong}/.cmake-format.py +18 -0
  25. package/numkong/.editorconfig +12 -0
  26. package/numkong/.git-blame-ignore-revs +123 -0
  27. package/numkong/.mailmap +15 -0
  28. package/numkong/.spi.yml +11 -0
  29. package/numkong/.swift-format +14 -0
  30. package/numkong/CITATION.cff +81 -0
  31. package/numkong/CONTRIBUTING.md +500 -0
  32. package/numkong/Cargo.toml +54 -0
  33. package/numkong/MANIFEST.in +8 -0
  34. package/numkong/Package.swift +84 -0
  35. package/numkong/README.md +569 -0
  36. package/numkong/bench/README.md +217 -0
  37. package/numkong/bench/bench-browser.html +323 -0
  38. package/numkong/bench/bench.cpp +344 -0
  39. package/numkong/bench/bench.hpp +816 -0
  40. package/numkong/bench/bench.js +148 -0
  41. package/numkong/bench/bench.mjs +616 -0
  42. package/numkong/bench/bench_attention.cpp +113 -0
  43. package/numkong/bench/bench_cast.cpp +264 -0
  44. package/numkong/bench/bench_cross_amx.cpp +62 -0
  45. package/numkong/bench/bench_cross_arm.cpp +245 -0
  46. package/numkong/bench/bench_cross_blas.cpp +309 -0
  47. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  48. package/numkong/bench/bench_cross_power.cpp +84 -0
  49. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  50. package/numkong/bench/bench_cross_serial.cpp +151 -0
  51. package/numkong/bench/bench_cross_sme.cpp +163 -0
  52. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  53. package/numkong/bench/bench_cross_x86.cpp +455 -0
  54. package/numkong/bench/bench_curved.cpp +210 -0
  55. package/numkong/bench/bench_dot.cpp +315 -0
  56. package/numkong/bench/bench_each.cpp +503 -0
  57. package/numkong/bench/bench_geospatial.cpp +112 -0
  58. package/numkong/bench/bench_maxsim.cpp +154 -0
  59. package/numkong/bench/bench_mesh.cpp +148 -0
  60. package/numkong/bench/bench_probability.cpp +60 -0
  61. package/numkong/bench/bench_reduce.cpp +371 -0
  62. package/numkong/bench/bench_set.cpp +73 -0
  63. package/numkong/bench/bench_sparse.cpp +198 -0
  64. package/numkong/bench/bench_spatial.cpp +347 -0
  65. package/numkong/bench/bench_trigonometry.cpp +137 -0
  66. package/numkong/bench/swift/Bench.swift +506 -0
  67. package/numkong/binding.gyp +169 -0
  68. package/numkong/build.rs +484 -0
  69. package/numkong/c/dispatch.h +512 -0
  70. package/numkong/c/dispatch_bf16.c +447 -0
  71. package/numkong/c/dispatch_bf16c.c +52 -0
  72. package/numkong/c/dispatch_e2m3.c +296 -0
  73. package/numkong/c/dispatch_e3m2.c +284 -0
  74. package/numkong/c/dispatch_e4m3.c +318 -0
  75. package/numkong/c/dispatch_e5m2.c +316 -0
  76. package/numkong/c/dispatch_f16.c +452 -0
  77. package/numkong/c/dispatch_f16c.c +58 -0
  78. package/numkong/c/dispatch_f32.c +434 -0
  79. package/numkong/c/dispatch_f32c.c +99 -0
  80. package/numkong/c/dispatch_f64.c +348 -0
  81. package/numkong/c/dispatch_f64c.c +98 -0
  82. package/numkong/c/dispatch_i16.c +96 -0
  83. package/numkong/c/dispatch_i32.c +89 -0
  84. package/numkong/c/dispatch_i4.c +153 -0
  85. package/numkong/c/dispatch_i64.c +86 -0
  86. package/numkong/c/dispatch_i8.c +348 -0
  87. package/numkong/c/dispatch_other.c +348 -0
  88. package/numkong/c/dispatch_u1.c +193 -0
  89. package/numkong/c/dispatch_u16.c +124 -0
  90. package/numkong/c/dispatch_u32.c +118 -0
  91. package/numkong/c/dispatch_u4.c +153 -0
  92. package/numkong/c/dispatch_u64.c +102 -0
  93. package/numkong/c/dispatch_u8.c +364 -0
  94. package/numkong/c/numkong.c +940 -0
  95. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  96. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  97. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_math_lib.cmake +46 -0
  99. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  100. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  101. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  102. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  103. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  104. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  105. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  106. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  107. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  108. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  109. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  110. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  111. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  112. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  113. package/numkong/include/README.md +643 -0
  114. package/numkong/include/module.modulemap +129 -0
  115. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  116. package/numkong/include/numkong/attention/sme.h +2075 -0
  117. package/numkong/include/numkong/attention.h +49 -0
  118. package/numkong/include/numkong/capabilities.h +930 -0
  119. package/numkong/include/numkong/cast/README.md +262 -0
  120. package/numkong/include/numkong/cast/diamond.h +64 -0
  121. package/numkong/include/numkong/cast/haswell.h +823 -0
  122. package/numkong/include/numkong/cast/icelake.h +475 -0
  123. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  124. package/numkong/include/numkong/cast/neon.h +1174 -0
  125. package/numkong/include/numkong/cast/powervsx.h +449 -0
  126. package/numkong/include/numkong/cast/rvv.h +970 -0
  127. package/numkong/include/numkong/cast/sapphire.h +262 -0
  128. package/numkong/include/numkong/cast/serial.h +2336 -0
  129. package/numkong/include/numkong/cast/skylake.h +915 -0
  130. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  131. package/numkong/include/numkong/cast.h +254 -0
  132. package/numkong/include/numkong/cast.hpp +44 -0
  133. package/numkong/include/numkong/curved/README.md +223 -0
  134. package/numkong/include/numkong/curved/genoa.h +182 -0
  135. package/numkong/include/numkong/curved/haswell.h +276 -0
  136. package/numkong/include/numkong/curved/neon.h +329 -0
  137. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  138. package/numkong/include/numkong/curved/rvv.h +305 -0
  139. package/numkong/include/numkong/curved/serial.h +207 -0
  140. package/numkong/include/numkong/curved/skylake.h +457 -0
  141. package/numkong/include/numkong/curved/smef64.h +530 -0
  142. package/numkong/include/numkong/curved.h +513 -0
  143. package/numkong/include/numkong/curved.hpp +144 -0
  144. package/numkong/include/numkong/dot/README.md +442 -0
  145. package/numkong/include/numkong/dot/alder.h +563 -0
  146. package/numkong/include/numkong/dot/diamond.h +158 -0
  147. package/numkong/include/numkong/dot/genoa.h +289 -0
  148. package/numkong/include/numkong/dot/haswell.h +1723 -0
  149. package/numkong/include/numkong/dot/icelake.h +997 -0
  150. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  151. package/numkong/include/numkong/dot/neon.h +869 -0
  152. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  153. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  154. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  155. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  156. package/numkong/include/numkong/dot/powervsx.h +752 -0
  157. package/numkong/include/numkong/dot/rvv.h +722 -0
  158. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  159. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  160. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  161. package/numkong/include/numkong/dot/sapphire.h +141 -0
  162. package/numkong/include/numkong/dot/serial.h +874 -0
  163. package/numkong/include/numkong/dot/sierra.h +405 -0
  164. package/numkong/include/numkong/dot/skylake.h +1116 -0
  165. package/numkong/include/numkong/dot/sve.h +420 -0
  166. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  167. package/numkong/include/numkong/dot/svehalf.h +168 -0
  168. package/numkong/include/numkong/dot/svesdot.h +90 -0
  169. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  170. package/numkong/include/numkong/dot.h +1136 -0
  171. package/numkong/include/numkong/dot.hpp +94 -0
  172. package/numkong/include/numkong/dots/README.md +496 -0
  173. package/numkong/include/numkong/dots/alder.h +117 -0
  174. package/numkong/include/numkong/dots/diamond.h +86 -0
  175. package/numkong/include/numkong/dots/genoa.h +100 -0
  176. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  177. package/numkong/include/numkong/dots/haswell.h +310 -0
  178. package/numkong/include/numkong/dots/icelake.h +180 -0
  179. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  180. package/numkong/include/numkong/dots/neon.h +123 -0
  181. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  182. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  183. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  184. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  185. package/numkong/include/numkong/dots/powervsx.h +194 -0
  186. package/numkong/include/numkong/dots/rvv.h +2593 -0
  187. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  188. package/numkong/include/numkong/dots/serial.h +2867 -0
  189. package/numkong/include/numkong/dots/sierra.h +100 -0
  190. package/numkong/include/numkong/dots/skylake.h +207 -0
  191. package/numkong/include/numkong/dots/sme.h +5041 -0
  192. package/numkong/include/numkong/dots/smebi32.h +477 -0
  193. package/numkong/include/numkong/dots/smef64.h +1328 -0
  194. package/numkong/include/numkong/dots/smehalf.h +47 -0
  195. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  196. package/numkong/include/numkong/dots.h +3110 -0
  197. package/numkong/include/numkong/dots.hpp +641 -0
  198. package/numkong/include/numkong/each/README.md +465 -0
  199. package/numkong/include/numkong/each/haswell.h +1658 -0
  200. package/numkong/include/numkong/each/icelake.h +272 -0
  201. package/numkong/include/numkong/each/neon.h +1138 -0
  202. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  203. package/numkong/include/numkong/each/neonhalf.h +318 -0
  204. package/numkong/include/numkong/each/rvv.h +1121 -0
  205. package/numkong/include/numkong/each/sapphire.h +343 -0
  206. package/numkong/include/numkong/each/serial.h +282 -0
  207. package/numkong/include/numkong/each/skylake.h +1562 -0
  208. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  209. package/numkong/include/numkong/each.h +2232 -0
  210. package/numkong/include/numkong/each.hpp +434 -0
  211. package/numkong/include/numkong/geospatial/README.md +147 -0
  212. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  213. package/numkong/include/numkong/geospatial/neon.h +615 -0
  214. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  215. package/numkong/include/numkong/geospatial/serial.h +309 -0
  216. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  217. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  218. package/numkong/include/numkong/geospatial.h +453 -0
  219. package/numkong/include/numkong/geospatial.hpp +235 -0
  220. package/numkong/include/numkong/matrix.hpp +336 -0
  221. package/numkong/include/numkong/maxsim/README.md +187 -0
  222. package/numkong/include/numkong/maxsim/alder.h +511 -0
  223. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  224. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  225. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  226. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  227. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  228. package/numkong/include/numkong/maxsim/serial.h +490 -0
  229. package/numkong/include/numkong/maxsim/sme.h +993 -0
  230. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  231. package/numkong/include/numkong/maxsim.h +571 -0
  232. package/numkong/include/numkong/maxsim.hpp +133 -0
  233. package/numkong/include/numkong/mesh/README.md +219 -0
  234. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  235. package/numkong/include/numkong/mesh/neon.h +1821 -0
  236. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  237. package/numkong/include/numkong/mesh/rvv.h +936 -0
  238. package/numkong/include/numkong/mesh/serial.h +721 -0
  239. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  240. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  241. package/numkong/include/numkong/mesh.h +666 -0
  242. package/numkong/include/numkong/mesh.hpp +701 -0
  243. package/numkong/include/numkong/numkong.h +78 -0
  244. package/numkong/include/numkong/numkong.hpp +58 -0
  245. package/numkong/include/numkong/probability/README.md +177 -0
  246. package/numkong/include/numkong/probability/haswell.h +267 -0
  247. package/numkong/include/numkong/probability/neon.h +255 -0
  248. package/numkong/include/numkong/probability/rvv.h +414 -0
  249. package/numkong/include/numkong/probability/serial.h +181 -0
  250. package/numkong/include/numkong/probability/skylake.h +324 -0
  251. package/numkong/include/numkong/probability.h +380 -0
  252. package/numkong/include/numkong/probability.hpp +120 -0
  253. package/numkong/include/numkong/random.h +50 -0
  254. package/numkong/include/numkong/random.hpp +285 -0
  255. package/numkong/include/numkong/reduce/README.md +552 -0
  256. package/numkong/include/numkong/reduce/alder.h +636 -0
  257. package/numkong/include/numkong/reduce/genoa.h +201 -0
  258. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  259. package/numkong/include/numkong/reduce/icelake.h +549 -0
  260. package/numkong/include/numkong/reduce/neon.h +3980 -0
  261. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  262. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  263. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  264. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  265. package/numkong/include/numkong/reduce/serial.h +753 -0
  266. package/numkong/include/numkong/reduce/sierra.h +338 -0
  267. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  268. package/numkong/include/numkong/reduce/sve.h +52 -0
  269. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  270. package/numkong/include/numkong/reduce.h +1582 -0
  271. package/numkong/include/numkong/reduce.hpp +778 -0
  272. package/numkong/include/numkong/scalar/README.md +89 -0
  273. package/numkong/include/numkong/scalar/haswell.h +122 -0
  274. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  275. package/numkong/include/numkong/scalar/neon.h +122 -0
  276. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  277. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  278. package/numkong/include/numkong/scalar/rvv.h +211 -0
  279. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  280. package/numkong/include/numkong/scalar/serial.h +332 -0
  281. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  282. package/numkong/include/numkong/scalar.h +696 -0
  283. package/numkong/include/numkong/set/README.md +179 -0
  284. package/numkong/include/numkong/set/haswell.h +334 -0
  285. package/numkong/include/numkong/set/icelake.h +485 -0
  286. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  287. package/numkong/include/numkong/set/neon.h +363 -0
  288. package/numkong/include/numkong/set/powervsx.h +326 -0
  289. package/numkong/include/numkong/set/rvv.h +226 -0
  290. package/numkong/include/numkong/set/rvvbb.h +117 -0
  291. package/numkong/include/numkong/set/serial.h +174 -0
  292. package/numkong/include/numkong/set/sve.h +187 -0
  293. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  294. package/numkong/include/numkong/set.h +471 -0
  295. package/numkong/include/numkong/set.hpp +114 -0
  296. package/numkong/include/numkong/sets/README.md +149 -0
  297. package/numkong/include/numkong/sets/haswell.h +63 -0
  298. package/numkong/include/numkong/sets/icelake.h +66 -0
  299. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  300. package/numkong/include/numkong/sets/neon.h +61 -0
  301. package/numkong/include/numkong/sets/powervsx.h +65 -0
  302. package/numkong/include/numkong/sets/serial.h +43 -0
  303. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  304. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  305. package/numkong/include/numkong/sets.h +382 -0
  306. package/numkong/include/numkong/sparse/README.md +156 -0
  307. package/numkong/include/numkong/sparse/icelake.h +463 -0
  308. package/numkong/include/numkong/sparse/neon.h +288 -0
  309. package/numkong/include/numkong/sparse/serial.h +117 -0
  310. package/numkong/include/numkong/sparse/sve2.h +504 -0
  311. package/numkong/include/numkong/sparse/turin.h +322 -0
  312. package/numkong/include/numkong/sparse.h +363 -0
  313. package/numkong/include/numkong/sparse.hpp +113 -0
  314. package/numkong/include/numkong/spatial/README.md +439 -0
  315. package/numkong/include/numkong/spatial/alder.h +604 -0
  316. package/numkong/include/numkong/spatial/diamond.h +240 -0
  317. package/numkong/include/numkong/spatial/genoa.h +222 -0
  318. package/numkong/include/numkong/spatial/haswell.h +979 -0
  319. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  320. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  321. package/numkong/include/numkong/spatial/neon.h +846 -0
  322. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  323. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  324. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  325. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  326. package/numkong/include/numkong/spatial/rvv.h +991 -0
  327. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  328. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  329. package/numkong/include/numkong/spatial/serial.h +347 -0
  330. package/numkong/include/numkong/spatial/sierra.h +516 -0
  331. package/numkong/include/numkong/spatial/skylake.h +605 -0
  332. package/numkong/include/numkong/spatial/sve.h +246 -0
  333. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  334. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  335. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  336. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  337. package/numkong/include/numkong/spatial.h +1681 -0
  338. package/numkong/include/numkong/spatial.hpp +183 -0
  339. package/numkong/include/numkong/spatials/README.md +580 -0
  340. package/numkong/include/numkong/spatials/alder.h +94 -0
  341. package/numkong/include/numkong/spatials/diamond.h +82 -0
  342. package/numkong/include/numkong/spatials/genoa.h +94 -0
  343. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  344. package/numkong/include/numkong/spatials/haswell.h +219 -0
  345. package/numkong/include/numkong/spatials/icelake.h +113 -0
  346. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  347. package/numkong/include/numkong/spatials/neon.h +109 -0
  348. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  349. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  350. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  351. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  352. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  353. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  354. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  355. package/numkong/include/numkong/spatials/serial.h +248 -0
  356. package/numkong/include/numkong/spatials/sierra.h +96 -0
  357. package/numkong/include/numkong/spatials/skylake.h +184 -0
  358. package/numkong/include/numkong/spatials/sme.h +1927 -0
  359. package/numkong/include/numkong/spatials/smef64.h +483 -0
  360. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  361. package/numkong/include/numkong/spatials.h +3374 -0
  362. package/numkong/include/numkong/spatials.hpp +509 -0
  363. package/numkong/include/numkong/tensor.hpp +1981 -0
  364. package/numkong/include/numkong/trigonometry/README.md +184 -0
  365. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  366. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  367. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  368. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  369. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  370. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  371. package/numkong/include/numkong/trigonometry.h +467 -0
  372. package/numkong/include/numkong/trigonometry.hpp +166 -0
  373. package/numkong/include/numkong/types.h +1695 -0
  374. package/numkong/include/numkong/types.hpp +6027 -0
  375. package/numkong/include/numkong/vector.hpp +766 -0
  376. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  377. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  378. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  380. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  381. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  382. package/numkong/javascript/README.md +254 -0
  383. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  384. package/numkong/javascript/numkong-browser.ts +40 -0
  385. package/numkong/javascript/numkong-wasm.ts +750 -0
  386. package/numkong/javascript/numkong.c +712 -0
  387. package/numkong/javascript/numkong.ts +613 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  389. package/numkong/javascript/tsconfig-cjs.json +13 -0
  390. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  391. package/numkong/javascript/types.ts +784 -0
  392. package/numkong/numkong.gypi +104 -0
  393. package/numkong/package.json +108 -0
  394. package/numkong/probes/arm_neon.c +8 -0
  395. package/numkong/probes/arm_neon_bfdot.c +9 -0
  396. package/numkong/probes/arm_neon_fhm.c +9 -0
  397. package/numkong/probes/arm_neon_half.c +8 -0
  398. package/numkong/probes/arm_neon_sdot.c +9 -0
  399. package/numkong/probes/arm_neonfp8.c +9 -0
  400. package/numkong/probes/arm_sme.c +16 -0
  401. package/numkong/probes/arm_sme2.c +16 -0
  402. package/numkong/probes/arm_sme2p1.c +16 -0
  403. package/numkong/probes/arm_sme_bf16.c +16 -0
  404. package/numkong/probes/arm_sme_bi32.c +16 -0
  405. package/numkong/probes/arm_sme_f64.c +16 -0
  406. package/numkong/probes/arm_sme_fa64.c +14 -0
  407. package/numkong/probes/arm_sme_half.c +16 -0
  408. package/numkong/probes/arm_sme_lut2.c +15 -0
  409. package/numkong/probes/arm_sve.c +18 -0
  410. package/numkong/probes/arm_sve2.c +20 -0
  411. package/numkong/probes/arm_sve2p1.c +18 -0
  412. package/numkong/probes/arm_sve_bfdot.c +20 -0
  413. package/numkong/probes/arm_sve_half.c +18 -0
  414. package/numkong/probes/arm_sve_sdot.c +21 -0
  415. package/numkong/probes/loongarch_lasx.c +12 -0
  416. package/numkong/probes/power_vsx.c +12 -0
  417. package/numkong/probes/probe.js +127 -0
  418. package/numkong/probes/riscv_rvv.c +14 -0
  419. package/numkong/probes/riscv_rvv_bb.c +15 -0
  420. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  421. package/numkong/probes/riscv_rvv_half.c +14 -0
  422. package/numkong/probes/wasm_v128relaxed.c +11 -0
  423. package/numkong/probes/x86_alder.c +17 -0
  424. package/numkong/probes/x86_diamond.c +17 -0
  425. package/numkong/probes/x86_genoa.c +17 -0
  426. package/numkong/probes/x86_graniteamx.c +19 -0
  427. package/numkong/probes/x86_haswell.c +11 -0
  428. package/numkong/probes/x86_icelake.c +17 -0
  429. package/numkong/probes/x86_sapphire.c +16 -0
  430. package/numkong/probes/x86_sapphireamx.c +18 -0
  431. package/numkong/probes/x86_sierra.c +17 -0
  432. package/numkong/probes/x86_skylake.c +15 -0
  433. package/numkong/probes/x86_turin.c +17 -0
  434. package/numkong/rust/README.md +698 -0
  435. package/numkong/rust/capabilities.rs +96 -0
  436. package/numkong/rust/cast.rs +314 -0
  437. package/numkong/rust/curved.rs +391 -0
  438. package/numkong/rust/each.rs +2721 -0
  439. package/numkong/rust/geospatial.rs +343 -0
  440. package/numkong/rust/matrix.rs +5424 -0
  441. package/numkong/rust/maxsim.rs +540 -0
  442. package/numkong/rust/mesh.rs +837 -0
  443. package/numkong/rust/numkong.rs +409 -0
  444. package/numkong/rust/probability.rs +272 -0
  445. package/numkong/rust/reduce.rs +1249 -0
  446. package/numkong/rust/set.rs +194 -0
  447. package/numkong/rust/sparse.rs +513 -0
  448. package/numkong/rust/spatial.rs +1815 -0
  449. package/numkong/rust/tensor.rs +7565 -0
  450. package/numkong/rust/types.rs +3666 -0
  451. package/numkong/rust/vector.rs +1899 -0
  452. package/numkong/rustfmt.toml +2 -0
  453. package/numkong/swift/Matrix.swift +1388 -0
  454. package/numkong/swift/MaxSim.swift +151 -0
  455. package/numkong/swift/NumKong.swift +283 -0
  456. package/numkong/swift/Numerics.swift +329 -0
  457. package/numkong/swift/README.md +433 -0
  458. package/numkong/swift/Scalar.swift +741 -0
  459. package/numkong/swift/Tensor.swift +209 -0
  460. package/numkong/test/README.md +315 -0
  461. package/numkong/test/playwright.config.ts +16 -0
  462. package/numkong/test/swift/Test.swift +534 -0
  463. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  464. package/numkong/test/test-browser-bundle.html +188 -0
  465. package/numkong/test/test-browser-runner.mjs +43 -0
  466. package/numkong/test/test-browser.html +305 -0
  467. package/numkong/test/test-dtypes.mjs +453 -0
  468. package/numkong/test/test-wasm.mjs +267 -0
  469. package/numkong/test/test.cpp +442 -0
  470. package/numkong/test/test.hpp +580 -0
  471. package/numkong/test/test.mjs +363 -0
  472. package/numkong/test/test_base.py +1041 -0
  473. package/numkong/test/test_cast.cpp +242 -0
  474. package/numkong/test/test_cross.hpp +551 -0
  475. package/numkong/test/test_cross.py +467 -0
  476. package/numkong/test/test_cross_amx.cpp +50 -0
  477. package/numkong/test/test_cross_arm.cpp +225 -0
  478. package/numkong/test/test_cross_blas.cpp +354 -0
  479. package/numkong/test/test_cross_loongarch.cpp +90 -0
  480. package/numkong/test/test_cross_power.cpp +73 -0
  481. package/numkong/test/test_cross_rvv.cpp +109 -0
  482. package/numkong/test/test_cross_serial.cpp +181 -0
  483. package/numkong/test/test_cross_sme.cpp +148 -0
  484. package/numkong/test/test_cross_wasm.cpp +141 -0
  485. package/numkong/test/test_cross_x86.cpp +442 -0
  486. package/numkong/test/test_curved.cpp +182 -0
  487. package/numkong/test/test_curved.py +207 -0
  488. package/numkong/test/test_dot.cpp +353 -0
  489. package/numkong/test/test_dot.py +296 -0
  490. package/numkong/test/test_each.cpp +437 -0
  491. package/numkong/test/test_each.py +756 -0
  492. package/numkong/test/test_geospatial.cpp +155 -0
  493. package/numkong/test/test_geospatial.py +241 -0
  494. package/numkong/test/test_maxsim.cpp +138 -0
  495. package/numkong/test/test_maxsim.py +209 -0
  496. package/numkong/test/test_mesh.cpp +203 -0
  497. package/numkong/test/test_mesh.py +394 -0
  498. package/numkong/test/test_probability.cpp +136 -0
  499. package/numkong/test/test_probability.py +166 -0
  500. package/numkong/test/test_reduce.cpp +563 -0
  501. package/numkong/test/test_reduce.py +781 -0
  502. package/numkong/test/test_set.cpp +151 -0
  503. package/numkong/test/test_set.py +120 -0
  504. package/numkong/test/test_similarities.py +579 -0
  505. package/numkong/test/test_sparse.cpp +121 -0
  506. package/numkong/test/test_sparse.py +118 -0
  507. package/numkong/test/test_spatial.cpp +518 -0
  508. package/numkong/test/test_spatial.py +269 -0
  509. package/numkong/test/test_tensor.cpp +884 -0
  510. package/numkong/test/test_tensor.py +1417 -0
  511. package/numkong/test/test_trigonometry.cpp +156 -0
  512. package/numkong/test/test_trigonometry.py +180 -0
  513. package/package.json +7 -8
  514. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  515. package/prebuilds/linux-arm64/usearch.node +0 -0
  516. package/prebuilds/linux-x64/usearch.node +0 -0
  517. package/fp16/CMakeLists.txt +0 -176
  518. package/fp16/LICENSE +0 -11
  519. package/fp16/README.md +0 -20
  520. package/fp16/bench/alt-element.cc +0 -89
  521. package/fp16/bench/from-alt-array.cc +0 -175
  522. package/fp16/bench/from-ieee-array.cc +0 -399
  523. package/fp16/bench/ieee-element.cc +0 -272
  524. package/fp16/bench/to-alt-array.cc +0 -91
  525. package/fp16/bench/to-ieee-array.cc +0 -303
  526. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  527. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  528. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  529. package/fp16/configure.py +0 -65
  530. package/fp16/confu.yaml +0 -8
  531. package/fp16/include/fp16/__init__.py +0 -0
  532. package/fp16/include/fp16/avx.py +0 -50
  533. package/fp16/include/fp16/avx2.py +0 -53
  534. package/fp16/include/fp16/bitcasts.h +0 -92
  535. package/fp16/include/fp16/fp16.h +0 -451
  536. package/fp16/include/fp16/psimd.h +0 -131
  537. package/fp16/include/fp16.h +0 -11
  538. package/fp16/jni/Android.mk +0 -6
  539. package/fp16/jni/Application.mk +0 -4
  540. package/fp16/test/alt-from-fp32-value.cc +0 -498
  541. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  542. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  543. package/fp16/test/alt-to-fp32-value.cc +0 -348
  544. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  545. package/fp16/test/bitcasts.cc +0 -56
  546. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  547. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  548. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  549. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  550. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  551. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  552. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  553. package/fp16/test/peachpy/stubs.py +0 -38
  554. package/fp16/test/tables.cc +0 -530
  555. package/fp16/test/tables.h +0 -13
  556. package/fp16/third-party/THHalf.h +0 -92
  557. package/fp16/third-party/eigen-half.h +0 -170
  558. package/fp16/third-party/float16-compressor.h +0 -80
  559. package/fp16/third-party/half.hpp +0 -2916
  560. package/fp16/third-party/npy-halffloat.h +0 -328
  561. package/simsimd/.git-blame-ignore-revs +0 -2
  562. package/simsimd/CONTRIBUTING.md +0 -321
  563. package/simsimd/Cargo.toml +0 -49
  564. package/simsimd/MANIFEST.in +0 -4
  565. package/simsimd/Package.swift +0 -28
  566. package/simsimd/README.md +0 -1493
  567. package/simsimd/binding.gyp +0 -35
  568. package/simsimd/build.rs +0 -70
  569. package/simsimd/c/lib.c +0 -374
  570. package/simsimd/include/module.modulemap +0 -4
  571. package/simsimd/include/simsimd/binary.h +0 -486
  572. package/simsimd/include/simsimd/curved.h +0 -1541
  573. package/simsimd/include/simsimd/dot.h +0 -1853
  574. package/simsimd/include/simsimd/elementwise.h +0 -2465
  575. package/simsimd/include/simsimd/geospatial.h +0 -43
  576. package/simsimd/include/simsimd/mesh.h +0 -69
  577. package/simsimd/include/simsimd/probability.h +0 -606
  578. package/simsimd/include/simsimd/simsimd.h +0 -2567
  579. package/simsimd/include/simsimd/sparse.h +0 -1384
  580. package/simsimd/include/simsimd/spatial.h +0 -2335
  581. package/simsimd/include/simsimd/types.h +0 -666
  582. package/simsimd/javascript/fallback.ts +0 -233
  583. package/simsimd/javascript/lib.c +0 -125
  584. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  585. package/simsimd/javascript/simsimd.ts +0 -179
  586. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  587. package/simsimd/package-lock.json +0 -1761
  588. package/simsimd/package.json +0 -61
  589. package/simsimd/rust/lib.rs +0 -1821
  590. package/simsimd/scripts/bench.cxx +0 -1170
  591. package/simsimd/scripts/bench.ipynb +0 -187
  592. package/simsimd/scripts/bench.js +0 -127
  593. package/simsimd/scripts/bench.rs +0 -876
  594. package/simsimd/scripts/bench_vectors.py +0 -734
  595. package/simsimd/scripts/bench_vectors_live.py +0 -213
  596. package/simsimd/scripts/test.c +0 -187
  597. package/simsimd/scripts/test.mjs +0 -220
  598. package/simsimd/scripts/test.py +0 -1505
  599. package/simsimd/swift/SimSIMD.swift +0 -149
  600. package/simsimd/swift/Test.swift +0 -128
  601. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  602. /package/{simsimd → numkong}/LICENSE +0 -0
  603. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  604. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,181 @@
1
+ /**
2
+ * @brief Serial Probability Distribution Similarity Measures.
3
+ * @file include/numkong/probability/serial.h
4
+ * @author Ash Vardanian
5
+ * @date February 6, 2026
6
+ *
7
+ * @sa include/numkong/probability.h
8
+ */
9
+ #ifndef NK_PROBABILITY_SERIAL_H
10
+ #define NK_PROBABILITY_SERIAL_H
11
+
12
+ #include "numkong/types.h"
13
+ #include "numkong/cast/serial.h" // `nk_f16_to_f32_serial`, `nk_bf16_to_f32_serial`, `nk_assign_from_to_`
14
+ #include "numkong/spatial/serial.h" // `nk_f32_sqrt_serial`, `nk_f64_sqrt_serial`
15
+
16
+ #if defined(__cplusplus)
17
+ extern "C" {
18
+ #endif
19
+
20
+ #define nk_define_kld_(input_type, unpacked_type, accumulator_type, output_type, load_and_convert, epsilon, \
21
+ compute_log) \
22
+ NK_PUBLIC void nk_kld_##input_type##_serial(nk_##input_type##_t const *a, nk_##input_type##_t const *b, \
23
+ nk_size_t n, output_type *result) { \
24
+ nk_##accumulator_type##_t sum = 0; \
25
+ nk_##unpacked_type##_t a_value, b_value; \
26
+ for (nk_size_t i = 0; i != n; ++i) { \
27
+ load_and_convert(a + i, &a_value); \
28
+ load_and_convert(b + i, &b_value); \
29
+ sum += a_value * compute_log((a_value + epsilon) / (b_value + epsilon)); \
30
+ } \
31
+ *result = (output_type)sum; \
32
+ }
33
+
34
+ #define nk_define_jsd_(input_type, unpacked_type, accumulator_type, output_type, load_and_convert, epsilon, \
35
+ compute_log, compute_sqrt) \
36
+ NK_PUBLIC void nk_jsd_##input_type##_serial(nk_##input_type##_t const *a, nk_##input_type##_t const *b, \
37
+ nk_size_t n, output_type *result) { \
38
+ nk_##accumulator_type##_t sum = 0; \
39
+ nk_##unpacked_type##_t a_value, b_value; \
40
+ for (nk_size_t i = 0; i != n; ++i) { \
41
+ load_and_convert(a + i, &a_value); \
42
+ load_and_convert(b + i, &b_value); \
43
+ nk_##unpacked_type##_t midpoint_value = (a_value + b_value) / 2; \
44
+ sum += a_value * compute_log((a_value + epsilon) / (midpoint_value + epsilon)); \
45
+ sum += b_value * compute_log((b_value + epsilon) / (midpoint_value + epsilon)); \
46
+ } \
47
+ output_type sum_half = ((output_type)sum / 2); \
48
+ *result = sum_half > 0 ? compute_sqrt(sum_half) : 0; \
49
+ }
50
+
51
+ /**
52
+ * @brief Computes `log(x)` for any positive float using IEEE 754 bit extraction
53
+ * and a fast-converging series expansion.
54
+ *
55
+ * Exploits the IEEE 754 representation to extract the exponent and mantissa:
56
+ * `log(x) = log(2) * exponent + log(mantissa)`. The mantissa is reduced to the
57
+ * range `[√2/2, √2]` for optimal convergence. Uses the transformation
58
+ * `u = (m-1)/(m+1)` which converges much faster than the classic Mercator series,
59
+ * since `u` is bounded to approximately `[-0.17, 0.17]` after range reduction.
60
+ *
61
+ * Maximum relative error is approximately 0.00001% across all positive floats,
62
+ * roughly 300,000x more accurate than the 3-term Mercator series (which also
63
+ * only converges for inputs in `(0, 2)`).
64
+ *
65
+ * https://en.wikipedia.org/wiki/Logarithm#Power_series
66
+ */
67
+ NK_INTERNAL nk_f32_t nk_f32_log_serial_(nk_f32_t x) {
68
+ nk_fui32_t conv;
69
+ conv.f = x;
70
+ int exp = ((conv.u >> 23) & 0xFF) - 127;
71
+ conv.u = (conv.u & 0x007FFFFF) | 0x3F800000; // mantissa ∈ [1, 2)
72
+ nk_f32_t m = conv.f;
73
+ // Range reduction: if m > √2, halve it and increment exponent
74
+ if (m > 1.41421356f) m *= 0.5f, exp++;
75
+ // Use (m-1)/(m+1) transformation for faster convergence
76
+ nk_f32_t u = (m - 1.0f) / (m + 1.0f);
77
+ nk_f32_t u2 = u * u;
78
+ // log(m) = 2 × (u + u³/3 + u⁵/5 + u⁷/7)
79
+ nk_f32_t log_m = 2.0f * u * (1.0f + u2 * (0.3333333333f + u2 * (0.2f + u2 * 0.142857143f)));
80
+ return (nk_f32_t)exp * 0.6931471805599453f + log_m;
81
+ }
82
+
83
+ /**
84
+ * @brief Computes `log(x)` for any positive double using IEEE 754 bit extraction
85
+ * and a fast-converging series expansion.
86
+ *
87
+ * Exploits the IEEE 754 representation to extract the 11-bit exponent and 52-bit mantissa:
88
+ * `log(x) = log(2) * exponent + log(mantissa)`. The mantissa is reduced to the
89
+ * range `[√2/2, √2]` for optimal convergence. Uses the transformation
90
+ * `u = (m-1)/(m+1)` which converges much faster than the classic Mercator series,
91
+ * since `u` is bounded to approximately `[-0.17, 0.17]` after range reduction.
92
+ *
93
+ * Uses more series terms than the f32 version to achieve near-full f64 precision,
94
+ * with maximum relative error approximately 0.00000000000001% across all positive doubles.
95
+ *
96
+ * https://en.wikipedia.org/wiki/Logarithm#Power_series
97
+ */
98
+ NK_INTERNAL nk_f64_t nk_f64_log_serial_(nk_f64_t x) {
99
+ nk_fui64_t conv;
100
+ conv.f = x;
101
+ int exp = ((conv.u >> 52) & 0x7FF) - 1023;
102
+ conv.u = (conv.u & 0x000FFFFFFFFFFFFFULL) | 0x3FF0000000000000ULL; // mantissa ∈ [1, 2)
103
+ nk_f64_t m = conv.f;
104
+ // Range reduction: if m > √2, halve it and increment exponent
105
+ if (m > 1.4142135623730950488) m *= 0.5, exp++;
106
+ // Use (m-1)/(m+1) transformation for faster convergence
107
+ nk_f64_t u = (m - 1.0) / (m + 1.0);
108
+ nk_f64_t u2 = u * u;
109
+ // 14-term Horner: P(u²) = 1 + u²/3 + u⁴/5 + ... + u²⁶/27, matching SIMD
110
+ nk_f64_t poly = 1.0 / 27.0;
111
+ poly = u2 * poly + 1.0 / 25.0;
112
+ poly = u2 * poly + 1.0 / 23.0;
113
+ poly = u2 * poly + 1.0 / 21.0;
114
+ poly = u2 * poly + 1.0 / 19.0;
115
+ poly = u2 * poly + 1.0 / 17.0;
116
+ poly = u2 * poly + 1.0 / 15.0;
117
+ poly = u2 * poly + 1.0 / 13.0;
118
+ poly = u2 * poly + 1.0 / 11.0;
119
+ poly = u2 * poly + 1.0 / 9.0;
120
+ poly = u2 * poly + 1.0 / 7.0;
121
+ poly = u2 * poly + 1.0 / 5.0;
122
+ poly = u2 * poly + 1.0 / 3.0;
123
+ poly = u2 * poly + 1.0;
124
+ return (nk_f64_t)exp * 0.6931471805599453 + 2.0 * u * poly;
125
+ }
126
+
127
+ nk_define_kld_(f32, f32, f64, nk_f64_t, nk_assign_from_to_, NK_F32_DIVISION_EPSILON, nk_f32_log_serial_)
128
+ nk_define_jsd_(f32, f32, f64, nk_f64_t, nk_assign_from_to_, NK_F32_DIVISION_EPSILON, nk_f32_log_serial_,
129
+ nk_f64_sqrt_serial)
130
+
131
+ nk_define_kld_(f16, f32, f32, nk_f32_t, nk_f16_to_f32_serial, NK_F32_DIVISION_EPSILON, nk_f32_log_serial_)
132
+ nk_define_jsd_(f16, f32, f32, nk_f32_t, nk_f16_to_f32_serial, NK_F32_DIVISION_EPSILON, nk_f32_log_serial_,
133
+ nk_f32_sqrt_serial)
134
+
135
+ nk_define_kld_(bf16, f32, f32, nk_f32_t, nk_bf16_to_f32_serial, NK_F32_DIVISION_EPSILON, nk_f32_log_serial_)
136
+ nk_define_jsd_(bf16, f32, f32, nk_f32_t, nk_bf16_to_f32_serial, NK_F32_DIVISION_EPSILON, nk_f32_log_serial_,
137
+ nk_f32_sqrt_serial)
138
+
139
+ NK_PUBLIC void nk_kld_f64_serial(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
140
+ // Use Kahan summation for higher numerical stability in long distributions
141
+ nk_f64_t sum = 0, compensation = 0;
142
+ for (nk_size_t i = 0; i != n; ++i) {
143
+ nk_f64_t a_value = a[i], b_value = b[i];
144
+ nk_f64_t term = a_value *
145
+ nk_f64_log_serial_((a_value + NK_F64_DIVISION_EPSILON) / (b_value + NK_F64_DIVISION_EPSILON));
146
+ nk_f64_t provisional_sum = sum + term;
147
+ compensation += (nk_f64_abs_(sum) >= nk_f64_abs_(term)) ? ((sum - provisional_sum) + term)
148
+ : ((term - provisional_sum) + sum);
149
+ sum = provisional_sum;
150
+ }
151
+ *result = sum + compensation;
152
+ }
153
+
154
+ NK_PUBLIC void nk_jsd_f64_serial(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
155
+ // Use Kahan summation for higher numerical stability in long distributions
156
+ nk_f64_t sum = 0, compensation = 0;
157
+ for (nk_size_t i = 0; i != n; ++i) {
158
+ nk_f64_t a_value = a[i], b_value = b[i];
159
+ nk_f64_t mi = (a_value + b_value) / 2;
160
+ nk_f64_t term_a = a_value *
161
+ nk_f64_log_serial_((a_value + NK_F64_DIVISION_EPSILON) / (mi + NK_F64_DIVISION_EPSILON));
162
+ nk_f64_t provisional_sum = sum + term_a;
163
+ compensation += (nk_f64_abs_(sum) >= nk_f64_abs_(term_a)) ? ((sum - provisional_sum) + term_a)
164
+ : ((term_a - provisional_sum) + sum);
165
+ sum = provisional_sum;
166
+ nk_f64_t term_b = b_value *
167
+ nk_f64_log_serial_((b_value + NK_F64_DIVISION_EPSILON) / (mi + NK_F64_DIVISION_EPSILON));
168
+ provisional_sum = sum + term_b;
169
+ compensation += (nk_f64_abs_(sum) >= nk_f64_abs_(term_b)) ? ((sum - provisional_sum) + term_b)
170
+ : ((term_b - provisional_sum) + sum);
171
+ sum = provisional_sum;
172
+ }
173
+ nk_f64_t sum_half = (sum + compensation) / 2;
174
+ *result = sum_half > 0 ? nk_f64_sqrt_serial(sum_half) : 0;
175
+ }
176
+
177
+ #if defined(__cplusplus)
178
+ } // extern "C"
179
+ #endif
180
+
181
+ #endif // NK_PROBABILITY_SERIAL_H
@@ -0,0 +1,324 @@
1
+ /**
2
+ * @brief Skylake-accelerated Probability Distribution Similarity Measures.
3
+ * @file include/numkong/probability/skylake.h
4
+ * @author Ash Vardanian
5
+ * @date February 6, 2026
6
+ *
7
+ * @sa include/numkong/probability.h
8
+ */
9
+ #ifndef NK_PROBABILITY_SKYLAKE_H
10
+ #define NK_PROBABILITY_SKYLAKE_H
11
+
12
+ #if NK_TARGET_X8664_
13
+ #if NK_TARGET_SKYLAKE
14
+
15
+ #include "numkong/types.h"
16
+ #include "numkong/spatial/haswell.h" // `nk_f32_sqrt_haswell`, `nk_f64_sqrt_haswell`
17
+ #include "numkong/spatial/skylake.h" // `nk_f32_sqrt_skylake`, `nk_f64_sqrt_skylake`
18
+
19
+ #if defined(__cplusplus)
20
+ extern "C" {
21
+ #endif
22
+
23
+ #if defined(__clang__)
24
+ #pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,avx512bw,avx512dq,f16c,fma,bmi,bmi2"))), \
25
+ apply_to = function)
26
+ #elif defined(__GNUC__)
27
+ #pragma GCC push_options
28
+ #pragma GCC target("avx2", "avx512f", "avx512vl", "avx512bw", "avx512dq", "f16c", "fma", "bmi", "bmi2")
29
+ #endif
30
+
31
+ NK_INTERNAL __m512 nk_log2_f32x16_skylake_(__m512 x) {
32
+ // Extract the exponent and mantissa: x = 2^exp × m, m ∈ [1, 2)
33
+ __m512 one_f32x16 = _mm512_set1_ps(1.0f);
34
+ __m512 exponent_f32x16 = _mm512_getexp_ps(x);
35
+ __m512 mantissa_f32x16 = _mm512_getmant_ps(x, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_src);
36
+
37
+ // Compute log2(m) using the s-series: s = (m-1)/(m+1), s ∈ [0, 1/3] for m ∈ [1, 2)
38
+ // log2(m) = (2/ln2) × s × (1 + s²/3 + s⁴/5 + s⁶/7 + s⁸/9)
39
+ __m512 s_f32x16 = _mm512_div_ps(_mm512_sub_ps(mantissa_f32x16, one_f32x16),
40
+ _mm512_add_ps(mantissa_f32x16, one_f32x16));
41
+ __m512 s2_f32x16 = _mm512_mul_ps(s_f32x16, s_f32x16);
42
+ __m512 series_f32x16 = _mm512_set1_ps(0.111111111f); // 1/9
43
+ series_f32x16 = _mm512_fmadd_ps(series_f32x16, s2_f32x16, _mm512_set1_ps(0.142857143f)); // 1/7
44
+ series_f32x16 = _mm512_fmadd_ps(series_f32x16, s2_f32x16, _mm512_set1_ps(0.2f)); // 1/5
45
+ series_f32x16 = _mm512_fmadd_ps(series_f32x16, s2_f32x16, _mm512_set1_ps(0.333333333f)); // 1/3
46
+ series_f32x16 = _mm512_fmadd_ps(series_f32x16, s2_f32x16, one_f32x16); // 1
47
+ // log2(m) = (2/ln2) × s × series
48
+ __m512 log2m_f32x16 = _mm512_mul_ps(_mm512_set1_ps(2.885390081777927f), _mm512_mul_ps(s_f32x16, series_f32x16));
49
+ return _mm512_add_ps(log2m_f32x16, exponent_f32x16);
50
+ }
51
+
52
+ NK_PUBLIC void nk_kld_f32_skylake(nk_f32_t const *a, nk_f32_t const *b, nk_size_t n, nk_f64_t *result) {
53
+ __m512 sum_f32x16 = _mm512_setzero_ps();
54
+ nk_f32_t epsilon = NK_F32_DIVISION_EPSILON;
55
+ __m512 epsilon_f32x16 = _mm512_set1_ps(epsilon);
56
+ __m512 a_f32x16, b_f32x16;
57
+
58
+ nk_kld_f32_skylake_cycle:
59
+ if (n < 16) {
60
+ __mmask16 mask = (__mmask16)_bzhi_u32(0xFFFF, n);
61
+ a_f32x16 = _mm512_maskz_loadu_ps(mask, a);
62
+ b_f32x16 = _mm512_maskz_loadu_ps(mask, b);
63
+ n = 0;
64
+ }
65
+ else {
66
+ a_f32x16 = _mm512_loadu_ps(a);
67
+ b_f32x16 = _mm512_loadu_ps(b);
68
+ a += 16, b += 16, n -= 16;
69
+ }
70
+ __m512 ratio_f32x16 = _mm512_div_ps(_mm512_add_ps(a_f32x16, epsilon_f32x16),
71
+ _mm512_add_ps(b_f32x16, epsilon_f32x16));
72
+ __m512 log_ratio_f32x16 = nk_log2_f32x16_skylake_(ratio_f32x16);
73
+ sum_f32x16 = _mm512_fmadd_ps(a_f32x16, log_ratio_f32x16, sum_f32x16);
74
+ if (n) goto nk_kld_f32_skylake_cycle;
75
+
76
+ __m256 lower_f32x8 = _mm512_castps512_ps256(sum_f32x16);
77
+ __m256 upper_f32x8 = _mm512_extractf32x8_ps(sum_f32x16, 1);
78
+ nk_f64_t sum = _mm512_reduce_add_pd(_mm512_cvtps_pd(lower_f32x8)) +
79
+ _mm512_reduce_add_pd(_mm512_cvtps_pd(upper_f32x8));
80
+ nk_f64_t log2_normalizer = 0.6931471805599453;
81
+ *result = sum * log2_normalizer;
82
+ }
83
+
84
+ NK_PUBLIC void nk_jsd_f32_skylake(nk_f32_t const *a, nk_f32_t const *b, nk_size_t n, nk_f64_t *result) {
85
+ __m512 sum_f32x16 = _mm512_setzero_ps();
86
+ nk_f32_t epsilon = NK_F32_DIVISION_EPSILON;
87
+ __m512 epsilon_f32x16 = _mm512_set1_ps(epsilon);
88
+ __m512 a_f32x16, b_f32x16;
89
+
90
+ nk_jsd_f32_skylake_cycle:
91
+ if (n < 16) {
92
+ __mmask16 mask = (__mmask16)_bzhi_u32(0xFFFF, n);
93
+ a_f32x16 = _mm512_maskz_loadu_ps(mask, a);
94
+ b_f32x16 = _mm512_maskz_loadu_ps(mask, b);
95
+ n = 0;
96
+ }
97
+ else {
98
+ a_f32x16 = _mm512_loadu_ps(a);
99
+ b_f32x16 = _mm512_loadu_ps(b);
100
+ a += 16, b += 16, n -= 16;
101
+ }
102
+ __m512 mean_f32x16 = _mm512_mul_ps(_mm512_add_ps(a_f32x16, b_f32x16), _mm512_set1_ps(0.5f));
103
+ __mmask16 nonzero_mask_a = _mm512_cmp_ps_mask(a_f32x16, epsilon_f32x16, _CMP_GE_OQ);
104
+ __mmask16 nonzero_mask_b = _mm512_cmp_ps_mask(b_f32x16, epsilon_f32x16, _CMP_GE_OQ);
105
+ __mmask16 nonzero_mask = nonzero_mask_a & nonzero_mask_b;
106
+ __m512 mean_with_epsilon_f32x16 = _mm512_add_ps(mean_f32x16, epsilon_f32x16);
107
+ __m512 ratio_a_f32x16 = _mm512_div_ps(_mm512_add_ps(a_f32x16, epsilon_f32x16), mean_with_epsilon_f32x16);
108
+ __m512 ratio_b_f32x16 = _mm512_div_ps(_mm512_add_ps(b_f32x16, epsilon_f32x16), mean_with_epsilon_f32x16);
109
+ __m512 log_ratio_a_f32x16 = nk_log2_f32x16_skylake_(ratio_a_f32x16);
110
+ __m512 log_ratio_b_f32x16 = nk_log2_f32x16_skylake_(ratio_b_f32x16);
111
+ __m512 contribution_a_f32x16 = _mm512_maskz_mul_ps(nonzero_mask, a_f32x16, log_ratio_a_f32x16);
112
+ __m512 contribution_b_f32x16 = _mm512_maskz_mul_ps(nonzero_mask, b_f32x16, log_ratio_b_f32x16);
113
+ sum_f32x16 = _mm512_add_ps(sum_f32x16, _mm512_add_ps(contribution_a_f32x16, contribution_b_f32x16));
114
+ if (n) goto nk_jsd_f32_skylake_cycle;
115
+
116
+ __m256 lower_f32x8 = _mm512_castps512_ps256(sum_f32x16);
117
+ __m256 upper_f32x8 = _mm512_extractf32x8_ps(sum_f32x16, 1);
118
+ nk_f64_t sum = (_mm512_reduce_add_pd(_mm512_cvtps_pd(lower_f32x8)) +
119
+ _mm512_reduce_add_pd(_mm512_cvtps_pd(upper_f32x8))) *
120
+ 0.6931471805599453 / 2.0;
121
+ nk_f64_t log2_normalizer = 0.6931471805599453;
122
+ nk_unused_(log2_normalizer);
123
+ *result = sum > 0 ? nk_f64_sqrt_haswell(sum) : 0;
124
+ }
125
+
126
+ NK_INTERNAL __m512d nk_log2_f64x8_skylake_(__m512d x) {
127
+ // Extract the exponent and mantissa: x = 2^exp × m, m ∈ [1, 2)
128
+ __m512d one_f64x8 = _mm512_set1_pd(1.0);
129
+ __m512d two_f64x8 = _mm512_set1_pd(2.0);
130
+ __m512d exponent_f64x8 = _mm512_getexp_pd(x);
131
+ __m512d mantissa_f64x8 = _mm512_getmant_pd(x, _MM_MANT_NORM_1_2, _MM_MANT_SIGN_src);
132
+
133
+ // Compute log2(m) using the s-series: s = (m-1)/(m+1), s ∈ [0, 1/3] for m ∈ [1, 2)
134
+ // ln(m) = 2 × s × (1 + s²/3 + s⁴/5 + s⁶/7 + ...) converges fast since s² ≤ 1/9
135
+ // log2(m) = ln(m) × log2(e)
136
+ __m512d s_f64x8 = _mm512_div_pd(_mm512_sub_pd(mantissa_f64x8, one_f64x8), _mm512_add_pd(mantissa_f64x8, one_f64x8));
137
+ __m512d s2_f64x8 = _mm512_mul_pd(s_f64x8, s_f64x8);
138
+
139
+ // Polynomial P(s²) = 1 + s²/3 + s⁴/5 + ... using Horner's method
140
+ // 14 terms (k=0..13) achieves ~1 ULP accuracy for f64
141
+ __m512d poly_f64x8 = _mm512_set1_pd(1.0 / 27.0); // 1/(2*13+1)
142
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 25.0));
143
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 23.0));
144
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 21.0));
145
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 19.0));
146
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 17.0));
147
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 15.0));
148
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 13.0));
149
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 11.0));
150
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 9.0));
151
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 7.0));
152
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 5.0));
153
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0 / 3.0));
154
+ poly_f64x8 = _mm512_fmadd_pd(s2_f64x8, poly_f64x8, _mm512_set1_pd(1.0));
155
+
156
+ // ln(m) = 2 × s × P(s²), then log2(m) = ln(m) × log2(e)
157
+ __m512d ln_m_f64x8 = _mm512_mul_pd(_mm512_mul_pd(two_f64x8, s_f64x8), poly_f64x8);
158
+ __m512d log2e_f64x8 = _mm512_set1_pd(1.4426950408889634); // 1/ln(2)
159
+ __m512d log2_m_f64x8 = _mm512_mul_pd(ln_m_f64x8, log2e_f64x8);
160
+
161
+ // log2(x) = exponent + log2(m)
162
+ return _mm512_add_pd(exponent_f64x8, log2_m_f64x8);
163
+ }
164
+
165
+ NK_PUBLIC void nk_kld_f64_skylake(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
166
+ __m512d sum_f64x8 = _mm512_setzero_pd();
167
+ __m512d compensation_f64x8 = _mm512_setzero_pd();
168
+ nk_f64_t epsilon = NK_F64_DIVISION_EPSILON;
169
+ __m512d epsilon_f64x8 = _mm512_set1_pd(epsilon);
170
+ __m512d a_f64x8, b_f64x8;
171
+
172
+ nk_kld_f64_skylake_cycle:
173
+ if (n < 8) {
174
+ __mmask8 mask = (__mmask8)_bzhi_u32(0xFF, n);
175
+ a_f64x8 = _mm512_maskz_loadu_pd(mask, a);
176
+ b_f64x8 = _mm512_maskz_loadu_pd(mask, b);
177
+ n = 0;
178
+ }
179
+ else {
180
+ a_f64x8 = _mm512_loadu_pd(a);
181
+ b_f64x8 = _mm512_loadu_pd(b);
182
+ a += 8, b += 8, n -= 8;
183
+ }
184
+ __m512d ratio_f64x8 = _mm512_div_pd(_mm512_add_pd(a_f64x8, epsilon_f64x8), _mm512_add_pd(b_f64x8, epsilon_f64x8));
185
+ __m512d log_ratio_f64x8 = nk_log2_f64x8_skylake_(ratio_f64x8);
186
+ __m512d contribution_f64x8 = _mm512_mul_pd(a_f64x8, log_ratio_f64x8);
187
+ // Kahan compensated summation
188
+ __m512d compensated_f64x8 = _mm512_sub_pd(contribution_f64x8, compensation_f64x8);
189
+ __m512d tentative_f64x8 = _mm512_add_pd(sum_f64x8, compensated_f64x8);
190
+ compensation_f64x8 = _mm512_sub_pd(_mm512_sub_pd(tentative_f64x8, sum_f64x8), compensated_f64x8);
191
+ sum_f64x8 = tentative_f64x8;
192
+ if (n) goto nk_kld_f64_skylake_cycle;
193
+
194
+ nk_f64_t log2_normalizer = 0.6931471805599453;
195
+ *result = _mm512_reduce_add_pd(sum_f64x8) * log2_normalizer;
196
+ }
197
+
198
+ NK_PUBLIC void nk_jsd_f64_skylake(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
199
+ __m512d sum_f64x8 = _mm512_setzero_pd();
200
+ __m512d compensation_f64x8 = _mm512_setzero_pd();
201
+ nk_f64_t epsilon = NK_F64_DIVISION_EPSILON;
202
+ __m512d epsilon_f64x8 = _mm512_set1_pd(epsilon);
203
+ __m512d a_f64x8, b_f64x8;
204
+
205
+ nk_jsd_f64_skylake_cycle:
206
+ if (n < 8) {
207
+ __mmask8 mask = (__mmask8)_bzhi_u32(0xFF, n);
208
+ a_f64x8 = _mm512_maskz_loadu_pd(mask, a);
209
+ b_f64x8 = _mm512_maskz_loadu_pd(mask, b);
210
+ n = 0;
211
+ }
212
+ else {
213
+ a_f64x8 = _mm512_loadu_pd(a);
214
+ b_f64x8 = _mm512_loadu_pd(b);
215
+ a += 8, b += 8, n -= 8;
216
+ }
217
+ __m512d mean_f64x8 = _mm512_mul_pd(_mm512_add_pd(a_f64x8, b_f64x8), _mm512_set1_pd(0.5));
218
+ __mmask8 nonzero_mask_a = _mm512_cmp_pd_mask(a_f64x8, epsilon_f64x8, _CMP_GE_OQ);
219
+ __mmask8 nonzero_mask_b = _mm512_cmp_pd_mask(b_f64x8, epsilon_f64x8, _CMP_GE_OQ);
220
+ __mmask8 nonzero_mask = nonzero_mask_a & nonzero_mask_b;
221
+ __m512d mean_with_epsilon_f64x8 = _mm512_add_pd(mean_f64x8, epsilon_f64x8);
222
+ __m512d ratio_a_f64x8 = _mm512_div_pd(_mm512_add_pd(a_f64x8, epsilon_f64x8), mean_with_epsilon_f64x8);
223
+ __m512d ratio_b_f64x8 = _mm512_div_pd(_mm512_add_pd(b_f64x8, epsilon_f64x8), mean_with_epsilon_f64x8);
224
+ __m512d log_ratio_a_f64x8 = nk_log2_f64x8_skylake_(ratio_a_f64x8);
225
+ __m512d log_ratio_b_f64x8 = nk_log2_f64x8_skylake_(ratio_b_f64x8);
226
+ __m512d contribution_a_f64x8 = _mm512_maskz_mul_pd(nonzero_mask, a_f64x8, log_ratio_a_f64x8);
227
+ __m512d contribution_b_f64x8 = _mm512_maskz_mul_pd(nonzero_mask, b_f64x8, log_ratio_b_f64x8);
228
+ // Kahan compensated summation for contribution a
229
+ __m512d compensated_a_f64x8 = _mm512_sub_pd(contribution_a_f64x8, compensation_f64x8);
230
+ __m512d tentative_a_f64x8 = _mm512_add_pd(sum_f64x8, compensated_a_f64x8);
231
+ compensation_f64x8 = _mm512_sub_pd(_mm512_sub_pd(tentative_a_f64x8, sum_f64x8), compensated_a_f64x8);
232
+ sum_f64x8 = tentative_a_f64x8;
233
+ // Kahan compensated summation for contribution b
234
+ __m512d compensated_b_f64x8 = _mm512_sub_pd(contribution_b_f64x8, compensation_f64x8);
235
+ __m512d tentative_b_f64x8 = _mm512_add_pd(sum_f64x8, compensated_b_f64x8);
236
+ compensation_f64x8 = _mm512_sub_pd(_mm512_sub_pd(tentative_b_f64x8, sum_f64x8), compensated_b_f64x8);
237
+ sum_f64x8 = tentative_b_f64x8;
238
+ if (n) goto nk_jsd_f64_skylake_cycle;
239
+
240
+ nk_f64_t log2_normalizer = 0.6931471805599453;
241
+ nk_f64_t sum = _mm512_reduce_add_pd(sum_f64x8);
242
+ sum *= log2_normalizer / 2;
243
+ *result = sum > 0 ? nk_f64_sqrt_haswell(sum) : 0;
244
+ }
245
+
246
+ NK_PUBLIC void nk_kld_f16_skylake(nk_f16_t const *a, nk_f16_t const *b, nk_size_t n, nk_f32_t *result) {
247
+ __m512 sum_f32x16 = _mm512_setzero_ps();
248
+ __m512 epsilon_f32x16 = _mm512_set1_ps(NK_F32_DIVISION_EPSILON);
249
+ __m512 a_f32x16, b_f32x16;
250
+
251
+ nk_kld_f16_skylake_cycle:
252
+ if (n < 16) {
253
+ __mmask16 mask = (__mmask16)_bzhi_u32(0xFFFF, n);
254
+ a_f32x16 = _mm512_cvtph_ps(_mm256_maskz_loadu_epi16(mask, a));
255
+ b_f32x16 = _mm512_cvtph_ps(_mm256_maskz_loadu_epi16(mask, b));
256
+ n = 0;
257
+ }
258
+ else {
259
+ a_f32x16 = _mm512_cvtph_ps(_mm256_loadu_si256((__m256i const *)a));
260
+ b_f32x16 = _mm512_cvtph_ps(_mm256_loadu_si256((__m256i const *)b));
261
+ a += 16, b += 16, n -= 16;
262
+ }
263
+ __m512 ratio_f32x16 = _mm512_div_ps(_mm512_add_ps(a_f32x16, epsilon_f32x16),
264
+ _mm512_add_ps(b_f32x16, epsilon_f32x16));
265
+ __m512 log_ratio_f32x16 = nk_log2_f32x16_skylake_(ratio_f32x16);
266
+ __m512 contribution_f32x16 = _mm512_mul_ps(a_f32x16, log_ratio_f32x16);
267
+ sum_f32x16 = _mm512_add_ps(sum_f32x16, contribution_f32x16);
268
+ if (n) goto nk_kld_f16_skylake_cycle;
269
+
270
+ nk_f32_t log2_normalizer = 0.6931471805599453f;
271
+ *result = _mm512_reduce_add_ps(sum_f32x16) * log2_normalizer;
272
+ }
273
+
274
+ NK_PUBLIC void nk_jsd_f16_skylake(nk_f16_t const *a, nk_f16_t const *b, nk_size_t n, nk_f32_t *result) {
275
+ __m512 sum_a_f32x16 = _mm512_setzero_ps();
276
+ __m512 sum_b_f32x16 = _mm512_setzero_ps();
277
+ __m512 epsilon_f32x16 = _mm512_set1_ps(NK_F32_DIVISION_EPSILON);
278
+ __m512 half_f32x16 = _mm512_set1_ps(0.5f);
279
+ __m512 a_f32x16, b_f32x16;
280
+
281
+ nk_jsd_f16_skylake_cycle:
282
+ if (n < 16) {
283
+ __mmask16 mask = (__mmask16)_bzhi_u32(0xFFFF, n);
284
+ a_f32x16 = _mm512_cvtph_ps(_mm256_maskz_loadu_epi16(mask, a));
285
+ b_f32x16 = _mm512_cvtph_ps(_mm256_maskz_loadu_epi16(mask, b));
286
+ n = 0;
287
+ }
288
+ else {
289
+ a_f32x16 = _mm512_cvtph_ps(_mm256_loadu_si256((__m256i const *)a));
290
+ b_f32x16 = _mm512_cvtph_ps(_mm256_loadu_si256((__m256i const *)b));
291
+ a += 16, b += 16, n -= 16;
292
+ }
293
+ __m512 mean_f32x16 = _mm512_mul_ps(_mm512_add_ps(a_f32x16, b_f32x16), half_f32x16);
294
+ __mmask16 nonzero_mask_a = _mm512_cmp_ps_mask(a_f32x16, epsilon_f32x16, _CMP_GE_OQ);
295
+ __mmask16 nonzero_mask_b = _mm512_cmp_ps_mask(b_f32x16, epsilon_f32x16, _CMP_GE_OQ);
296
+ __mmask16 nonzero_mask = nonzero_mask_a & nonzero_mask_b;
297
+ __m512 mean_with_epsilon_f32x16 = _mm512_add_ps(mean_f32x16, epsilon_f32x16);
298
+ __m512 ratio_a_f32x16 = _mm512_div_ps(_mm512_add_ps(a_f32x16, epsilon_f32x16), mean_with_epsilon_f32x16);
299
+ __m512 ratio_b_f32x16 = _mm512_div_ps(_mm512_add_ps(b_f32x16, epsilon_f32x16), mean_with_epsilon_f32x16);
300
+ __m512 log_ratio_a_f32x16 = nk_log2_f32x16_skylake_(ratio_a_f32x16);
301
+ __m512 log_ratio_b_f32x16 = nk_log2_f32x16_skylake_(ratio_b_f32x16);
302
+ sum_a_f32x16 = _mm512_mask3_fmadd_ps(a_f32x16, log_ratio_a_f32x16, sum_a_f32x16, nonzero_mask);
303
+ sum_b_f32x16 = _mm512_mask3_fmadd_ps(b_f32x16, log_ratio_b_f32x16, sum_b_f32x16, nonzero_mask);
304
+ if (n) goto nk_jsd_f16_skylake_cycle;
305
+
306
+ nk_f32_t log2_normalizer = 0.6931471805599453f;
307
+ nk_f32_t sum = _mm512_reduce_add_ps(_mm512_add_ps(sum_a_f32x16, sum_b_f32x16));
308
+ sum *= log2_normalizer / 2;
309
+ *result = sum > 0 ? nk_f32_sqrt_haswell(sum) : 0;
310
+ }
311
+
312
+ #if defined(__clang__)
313
+ #pragma clang attribute pop
314
+ #elif defined(__GNUC__)
315
+ #pragma GCC pop_options
316
+ #endif
317
+
318
+ #if defined(__cplusplus)
319
+ } // extern "C"
320
+ #endif
321
+
322
+ #endif // NK_TARGET_SKYLAKE
323
+ #endif // NK_TARGET_X8664_
324
+ #endif // NK_PROBABILITY_SKYLAKE_H