usearch 2.21.4 → 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 +224 -48
  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
@@ -0,0 +1,616 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @brief Unified multi-runtime benchmark and reporting for NumKong
4
+ * @file bench/bench.mjs
5
+ * @author Claude & Ash Vardanian
6
+ * @date February 4, 2026
7
+ *
8
+ * All-in-one benchmark suite supporting multiple runtimes and report generation.
9
+ *
10
+ * Environment variables:
11
+ * - NK_DIMENSIONS: Vector dimensionality (default: 1536)
12
+ * - NK_ITERATIONS: Benchmark iterations (default: 1000)
13
+ * - NK_FILTER: Regex to filter tests (default: .*)
14
+ * - NK_RUNTIME: Runtime to use (default: native)
15
+ * - NK_SEED: Random seed (default: 42)
16
+ *
17
+ * Commands:
18
+ * - node bench.mjs → Run benchmarks for configured runtime
19
+ * - node bench.mjs --report → Generate comparison report from results
20
+ * - node bench.mjs --browser → Run browser benchmarks via Playwright
21
+ */
22
+
23
+ import { performance } from 'node:perf_hooks';
24
+ import { readFileSync, writeFileSync, readdirSync, existsSync, mkdirSync } from 'node:fs';
25
+ import { WASI } from 'node:wasi';
26
+ import build from 'node-gyp-build';
27
+ import * as path from 'node:path';
28
+ import { fileURLToPath, pathToFileURL } from 'node:url';
29
+
30
+ const __filename = fileURLToPath(import.meta.url);
31
+ const __dirname = path.dirname(__filename);
32
+ const rootDir = path.join(__dirname, '..');
33
+ const resultsDir = path.join(__dirname, 'results');
34
+
35
+
36
+ const CONFIG = {
37
+ dimensions: parseInt(process.env.NK_DIMENSIONS || '1536'),
38
+ iterations: parseInt(process.env.NK_ITERATIONS || '1000'),
39
+ filter: new RegExp(process.env.NK_FILTER || '.*'),
40
+ runtime: process.env.NK_RUNTIME || 'native',
41
+ seed: parseInt(process.env.NK_SEED || '42')
42
+ };
43
+
44
+ const BENCHMARK_MATRIX = {
45
+ functions: ['dot', 'inner', 'angular', 'sqeuclidean', 'euclidean', 'hamming', 'jaccard', 'kullbackleibler', 'jensenshannon'],
46
+ dtypes: ['f64', 'f32', 'f16', 'bf16', 'e4m3', 'e5m2', 'e2m3', 'e3m2', 'i8', 'u8', 'u1'],
47
+ };
48
+
49
+ const FUNCTION_DTYPE_SUPPORT = {
50
+ 'dot': ['f64', 'f32', 'f16', 'bf16', 'e4m3', 'e5m2', 'e2m3', 'e3m2', 'i8', 'u8'],
51
+ 'inner': ['f64', 'f32', 'f16', 'bf16', 'e4m3', 'e5m2', 'e2m3', 'e3m2', 'i8', 'u8'],
52
+ 'angular': ['f64', 'f32', 'f16', 'bf16', 'e4m3', 'e5m2', 'e2m3', 'e3m2', 'i8'],
53
+ 'sqeuclidean': ['f64', 'f32', 'f16', 'bf16', 'e4m3', 'e5m2', 'e2m3', 'e3m2', 'i8', 'u8'],
54
+ 'euclidean': ['f64', 'f32', 'f16', 'bf16', 'e4m3', 'e5m2', 'e2m3', 'e3m2', 'i8', 'u8'],
55
+ 'hamming': ['u1'],
56
+ 'jaccard': ['u1'],
57
+ 'kullbackleibler': ['f64', 'f32'],
58
+ 'jensenshannon': ['f64', 'f32']
59
+ };
60
+
61
+ const RUNTIME_INFO = {
62
+ native: {
63
+ name: 'Native Node.js Addon',
64
+ description: 'Compiled C code with SIMD optimizations',
65
+ expectedPerformance: '1.00x (baseline)',
66
+ },
67
+ emscripten: {
68
+ name: 'Emscripten WASM',
69
+ description: 'WebAssembly with SIMD support',
70
+ expectedPerformance: '0.60-0.80x of native',
71
+ },
72
+ wasi: {
73
+ name: 'WASI',
74
+ description: 'WebAssembly System Interface',
75
+ expectedPerformance: '0.50-0.70x of native',
76
+ },
77
+ browser: {
78
+ name: 'Browser (Chromium)',
79
+ description: 'WebAssembly in browser context',
80
+ expectedPerformance: '0.40-0.60x of native',
81
+ }
82
+ };
83
+
84
+
85
+ async function loadNumKong(runtime) {
86
+ switch (runtime) {
87
+ case 'native':
88
+ return loadNative();
89
+ case 'emscripten':
90
+ return loadEmscripten();
91
+ case 'wasi':
92
+ return loadWASI();
93
+ case 'browser':
94
+ throw new Error('Browser runtime requires --browser flag');
95
+ default:
96
+ throw new Error(`Unknown runtime: ${runtime}. Use: native, emscripten, wasi, or browser`);
97
+ }
98
+ }
99
+
100
+ function loadNative() {
101
+ try {
102
+ const builddir = rootDir;
103
+ const numkong = build(builddir);
104
+ console.log('✓ Loaded NumKong native addon');
105
+ return numkong;
106
+ } catch (e) {
107
+ throw new Error(`Failed to load native addon: ${e.message}`);
108
+ }
109
+ }
110
+
111
+ async function loadEmscripten() {
112
+ try {
113
+ const wasmPath = path.join(rootDir, 'build-wasm', 'numkong.js');
114
+ const wrapperPath = path.join(rootDir, 'javascript', 'dist', 'esm', 'numkong-wasm.js');
115
+ const wasmModule = await import(pathToFileURL(wasmPath).href);
116
+ const { initWasm } = await import(pathToFileURL(wrapperPath).href);
117
+ const numkong = await initWasm(wasmModule.default);
118
+ console.log('✓ Loaded NumKong Emscripten WASM');
119
+ return numkong;
120
+ } catch (e) {
121
+ throw new Error(`Failed to load Emscripten WASM: ${e.message}\nBuild with: cmake -B build-wasm -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-wasm.cmake && cmake --build build-wasm`);
122
+ }
123
+ }
124
+
125
+ async function loadWASI() {
126
+ try {
127
+ const wasiPath = path.join(rootDir, 'build-wasi', 'test.wasm');
128
+ if (!existsSync(wasiPath)) {
129
+ throw new Error('Missing build-wasi/test.wasm');
130
+ }
131
+
132
+ const hasV128 = WebAssembly.validate(new Uint8Array([
133
+ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
134
+ 0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7b,
135
+ 0x03, 0x02, 0x01, 0x00,
136
+ 0x0a, 0x09, 0x01, 0x07, 0x00, 0xfd, 0x0c,
137
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
139
+ ])) ? 1 : 0;
140
+ const hasRelaxed = WebAssembly.validate(new Uint8Array([
141
+ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
142
+ 0x01, 0x06, 0x01, 0x60, 0x01, 0x7b, 0x01, 0x7b,
143
+ 0x03, 0x02, 0x01, 0x00,
144
+ 0x0a, 0x07, 0x01, 0x05, 0x00, 0x20, 0x00,
145
+ 0xfd, 0x82, 0x02, 0x0b,
146
+ ])) ? 1 : 0;
147
+
148
+ console.log(` WASM SIMD capabilities: v128=${hasV128}, relaxed=${hasRelaxed}`);
149
+
150
+ const wasi = new WASI({
151
+ version: 'preview1',
152
+ args: [],
153
+ env: {},
154
+ });
155
+
156
+ const wasmBytes = readFileSync(wasiPath);
157
+
158
+ const { instance } = await WebAssembly.instantiate(wasmBytes, {
159
+ wasi_snapshot_preview1: wasi.wasiImport,
160
+ env: {
161
+ nk_has_v128: () => hasV128,
162
+ nk_has_relaxed: () => hasRelaxed
163
+ }
164
+ });
165
+
166
+ wasi.start(instance);
167
+ console.log('✓ Loaded NumKong WASI');
168
+ return instance.exports;
169
+ } catch (e) {
170
+ throw new Error(`Failed to load WASI: ${e.message}\nBuild with: cmake -B build-wasi -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-wasi.cmake -DNK_BUILD_TEST=ON && cmake --build build-wasi --target nk_test`);
171
+ }
172
+ }
173
+
174
+
175
+ class Random {
176
+ constructor(seed) {
177
+ this.seed = seed;
178
+ }
179
+
180
+ next() {
181
+ this.seed = (this.seed * 1103515245 + 12345) & 0x7fffffff;
182
+ return this.seed / 0x7fffffff;
183
+ }
184
+ }
185
+
186
+ function generateTestData(dtype, length, seed) {
187
+ const rng = new Random(seed);
188
+
189
+ switch (dtype) {
190
+ case 'f64':
191
+ return Float64Array.from({ length }, () => rng.next() * 2 - 1);
192
+ case 'f32':
193
+ return Float32Array.from({ length }, () => rng.next() * 2 - 1);
194
+ case 'f16':
195
+ case 'bf16':
196
+ case 'e4m3':
197
+ case 'e5m2':
198
+ case 'e2m3':
199
+ case 'e3m2':
200
+ return Float32Array.from({ length }, () => rng.next() * 2 - 1);
201
+ case 'i8':
202
+ return Int8Array.from({ length }, () => Math.floor(rng.next() * 256) - 128);
203
+ case 'u8':
204
+ return Uint8Array.from({ length }, () => Math.floor(rng.next() * 256));
205
+ case 'u1':
206
+ const byteLength = Math.ceil(length / 8);
207
+ return Uint8Array.from({ length: byteLength }, () => Math.floor(rng.next() * 256));
208
+ default:
209
+ throw new Error(`Unknown dtype: ${dtype}`);
210
+ }
211
+ }
212
+
213
+
214
+ function benchmarkOperation(fn, warmupMs = 200, samples = 5) {
215
+ // Warmup
216
+ const warmupEnd = performance.now() + warmupMs;
217
+ while (performance.now() < warmupEnd) fn();
218
+
219
+ // Collect samples
220
+ const times = [];
221
+ for (let s = 0; s < samples; s++) {
222
+ let ops = 0;
223
+ const start = performance.now();
224
+ const end = start + 200; // 200ms per sample
225
+ while (performance.now() < end) { fn(); ops++; }
226
+ const elapsed = performance.now() - start;
227
+ times.push(elapsed / ops);
228
+ }
229
+
230
+ const meanTime = times.reduce((a, b) => a + b, 0) / times.length;
231
+ const variance = times.reduce((a, t) => a + (t - meanTime) ** 2, 0) / times.length;
232
+ const stdDev = Math.sqrt(variance);
233
+ const opsPerSec = 1000 / meanTime;
234
+
235
+ return { opsPerSec, meanTime, stdDev };
236
+ }
237
+
238
+ async function runBenchmarks() {
239
+ console.log('╔════════════════════════════════════════════════════════════════╗');
240
+ console.log('║ NumKong JavaScript Multi-Runtime Benchmarks ║');
241
+ console.log('╚════════════════════════════════════════════════════════════════╝\n');
242
+
243
+ console.log('Configuration:');
244
+ console.log(` Dimensions: ${CONFIG.dimensions}`);
245
+ console.log(` Iterations: ${CONFIG.iterations}`);
246
+ console.log(` Runtime: ${CONFIG.runtime}`);
247
+ console.log(` Filter: ${CONFIG.filter.source}`);
248
+ console.log(` Seed: ${CONFIG.seed}\n`);
249
+
250
+ const runtimeInfo = RUNTIME_INFO[CONFIG.runtime];
251
+ console.log(`Runtime: ${runtimeInfo.name}`);
252
+ console.log(` ${runtimeInfo.description}`);
253
+ console.log(` Expected performance: ${runtimeInfo.expectedPerformance}\n`);
254
+
255
+ // Load NumKong module
256
+ let numkong;
257
+ try {
258
+ numkong = await loadNumKong(CONFIG.runtime);
259
+ } catch (e) {
260
+ console.error(`❌ Failed to load runtime: ${e.message}`);
261
+ process.exit(1);
262
+ }
263
+
264
+ const results = [];
265
+
266
+ // Iterate through benchmark matrix
267
+ for (const func of BENCHMARK_MATRIX.functions) {
268
+ const supportedDtypes = FUNCTION_DTYPE_SUPPORT[func] || [];
269
+
270
+ for (const dtype of supportedDtypes) {
271
+ const testName = `${func}-${dtype}`;
272
+
273
+ // Apply filter
274
+ if (!CONFIG.filter.test(testName)) {
275
+ continue;
276
+ }
277
+
278
+ // Generate test data
279
+ const a = generateTestData(dtype, CONFIG.dimensions, CONFIG.seed);
280
+ const b = generateTestData(dtype, CONFIG.dimensions, CONFIG.seed + 1);
281
+
282
+ // Run benchmark
283
+ const bench = benchmarkOperation(() => numkong[func](a, b));
284
+ const opsPerSec = bench.opsPerSec;
285
+ const meanTime = bench.meanTime;
286
+ const stdDev = bench.stdDev;
287
+
288
+ console.log(`✓ ${testName.padEnd(30)} ${opsPerSec.toFixed(0).padStart(10)} ops/sec (${meanTime.toFixed(3)}ms ± ${stdDev.toFixed(3)}ms)`);
289
+
290
+ results.push({
291
+ function: func,
292
+ dtype: dtype,
293
+ runtime: CONFIG.runtime,
294
+ dimensions: CONFIG.dimensions,
295
+ opsPerSec: opsPerSec,
296
+ meanTime: meanTime,
297
+ stdDev: stdDev,
298
+ timestamp: new Date().toISOString()
299
+ });
300
+ }
301
+ }
302
+
303
+ // Save results
304
+ mkdirSync(resultsDir, { recursive: true });
305
+
306
+ const resultsFile = path.join(resultsDir, `${CONFIG.runtime}.json`);
307
+ writeFileSync(resultsFile, JSON.stringify(results, null, 2));
308
+
309
+ console.log(`\n✅ Benchmark complete! Results saved to: ${resultsFile}`);
310
+ console.log(` Total tests run: ${results.length}`);
311
+
312
+ return results;
313
+ }
314
+
315
+
316
+ async function runBrowserBenchmarks() {
317
+ console.log('╔════════════════════════════════════════════════════════════════╗');
318
+ console.log('║ NumKong Browser Benchmark Runner ║');
319
+ console.log('╚════════════════════════════════════════════════════════════════╝\n');
320
+
321
+ console.log('Configuration:');
322
+ console.log(` Dimensions: ${CONFIG.dimensions}`);
323
+ console.log(` Filter: ${CONFIG.filter.source}`);
324
+ console.log(` Seed: ${CONFIG.seed}\n`);
325
+
326
+ // Check if WASM build exists
327
+ const wasmPath = path.join(rootDir, 'build-wasm', 'numkong.js');
328
+ if (!existsSync(wasmPath)) {
329
+ console.error('❌ Emscripten WASM build not found!');
330
+ console.error(` Expected: ${wasmPath}`);
331
+ console.error(' Build it with:');
332
+ console.error(' source ~/emsdk/emsdk_env.sh');
333
+ console.error(' cmake -B build-wasm -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-wasm.cmake');
334
+ console.error(' cmake --build build-wasm');
335
+ process.exit(1);
336
+ }
337
+
338
+ console.log('✓ Found Emscripten WASM build');
339
+
340
+ // Dynamic import of Playwright
341
+ console.log('\nLaunching Chromium...');
342
+ const { chromium } = await import('playwright');
343
+
344
+ const browser = await chromium.launch({
345
+ headless: true,
346
+ args: [
347
+ '--enable-features=WebAssemblySimd',
348
+ '--enable-features=WebAssemblyRelaxedSimd',
349
+ ]
350
+ });
351
+
352
+ const context = await browser.newContext();
353
+ const page = await context.newPage();
354
+
355
+ // Set up console logging from browser
356
+ page.on('console', msg => {
357
+ const text = msg.text();
358
+ if (text.includes('Error') || text.includes('Failed')) {
359
+ console.error(` Browser: ${text}`);
360
+ }
361
+ });
362
+
363
+ // Build URL with query parameters
364
+ const benchmarkUrl = `http://127.0.0.1:8888/bench/bench-browser.html?dimensions=${CONFIG.dimensions}&iterations=${CONFIG.iterations}&filter=${encodeURIComponent(CONFIG.filter.source)}&seed=${CONFIG.seed}`;
365
+
366
+ console.log('✓ Chromium launched');
367
+ console.log(`\nNavigating to: ${benchmarkUrl}`);
368
+
369
+ try {
370
+ await page.goto(benchmarkUrl);
371
+ console.log('✓ Page loaded');
372
+ console.log('\nRunning benchmarks (this may take several minutes)...\n');
373
+
374
+ // Wait for benchmarks to complete (timeout: 10 minutes)
375
+ await page.waitForFunction(
376
+ () => window.benchmarkComplete === true,
377
+ { timeout: 600000 }
378
+ );
379
+
380
+ // Check for errors
381
+ const error = await page.evaluate(() => window.benchmarkError);
382
+ if (error) {
383
+ throw new Error(error);
384
+ }
385
+
386
+ // Get results
387
+ const results = await page.evaluate(() => window.benchmarkResults);
388
+
389
+ if (!results || results.length === 0) {
390
+ throw new Error('No benchmark results returned');
391
+ }
392
+
393
+ console.log(`\n✅ Browser benchmarks complete! Total tests: ${results.length}`);
394
+
395
+ // Print summary
396
+ console.log('\nQuick Summary:');
397
+ const avgOps = results.reduce((sum, r) => sum + r.opsPerSec, 0) / results.length;
398
+ console.log(` Average: ${avgOps.toFixed(0)} ops/sec (${results.length} tests)`);
399
+
400
+ // Save results
401
+ mkdirSync(resultsDir, { recursive: true });
402
+ const resultsFile = path.join(resultsDir, 'browser.json');
403
+ writeFileSync(resultsFile, JSON.stringify(results, null, 2));
404
+
405
+ console.log(`\n✓ Results saved to: ${resultsFile}`);
406
+ console.log('\nGenerate comparison report with: node bench.mjs --report');
407
+
408
+ } catch (error) {
409
+ console.error(`\n❌ Benchmark failed: ${error.message}`);
410
+
411
+ // Take screenshot for debugging
412
+ const screenshotPath = path.join(resultsDir, 'error-screenshot.png');
413
+ mkdirSync(path.dirname(screenshotPath), { recursive: true });
414
+ await page.screenshot({ path: screenshotPath });
415
+ console.error(` Screenshot saved to: ${screenshotPath}`);
416
+
417
+ await browser.close();
418
+ process.exit(1);
419
+ }
420
+
421
+ await browser.close();
422
+ }
423
+
424
+
425
+ function loadAllResults() {
426
+ if (!existsSync(resultsDir)) {
427
+ throw new Error(`Results directory not found: ${resultsDir}\nRun benchmarks first with: node bench.mjs`);
428
+ }
429
+
430
+ const files = readdirSync(resultsDir).filter(f => f.endsWith('.json'));
431
+ const allResults = {};
432
+
433
+ for (const file of files) {
434
+ const runtime = path.basename(file, '.json');
435
+ const filepath = path.join(resultsDir, file);
436
+ const data = JSON.parse(readFileSync(filepath, 'utf-8'));
437
+ allResults[runtime] = data;
438
+ }
439
+
440
+ return allResults;
441
+ }
442
+
443
+ function generateMarkdownReport(allResults) {
444
+ const runtimes = Object.keys(allResults);
445
+
446
+ if (runtimes.length === 0) {
447
+ return '# No benchmark results found\n\nRun benchmarks with: node bench.mjs';
448
+ }
449
+
450
+ // Get configuration from first result
451
+ const firstResult = allResults[runtimes[0]][0];
452
+ const dimensions = firstResult?.dimensions || 'unknown';
453
+ const timestamp = firstResult?.timestamp ? new Date(firstResult.timestamp).toLocaleString() : 'unknown';
454
+
455
+ let report = '# NumKong JavaScript Benchmark Results\n\n';
456
+ report += '## Configuration\n\n';
457
+ report += `- **Dimensions**: ${dimensions}\n`;
458
+ report += `- **Date**: ${timestamp}\n`;
459
+ report += `- **Node.js**: ${process.version}\n`;
460
+ report += `- **Runtimes**: ${runtimes.join(', ')}\n\n`;
461
+
462
+ // Group results by function and dtype
463
+ const grouped = {};
464
+
465
+ for (const runtime of runtimes) {
466
+ for (const result of allResults[runtime]) {
467
+ const key = `${result.function}-${result.dtype}`;
468
+ if (!grouped[key]) {
469
+ grouped[key] = {
470
+ function: result.function,
471
+ dtype: result.dtype,
472
+ results: {}
473
+ };
474
+ }
475
+ grouped[key].results[runtime] = result.opsPerSec;
476
+ }
477
+ }
478
+
479
+ // Generate comparison tables by function
480
+ const functions = [...new Set(Object.values(grouped).map(g => g.function))];
481
+
482
+ for (const func of functions) {
483
+ report += `## ${func.charAt(0).toUpperCase() + func.slice(1)}\n\n`;
484
+ report += '| DType | ' + runtimes.map(r => r.charAt(0).toUpperCase() + r.slice(1)).join(' | ') + ' | Best |\n';
485
+ report += '|-------|' + runtimes.map(() => '--------').join('|') + '|------|\n';
486
+
487
+ const funcResults = Object.values(grouped).filter(g => g.function === func);
488
+
489
+ for (const { dtype, results } of funcResults) {
490
+ const values = runtimes.map(r => results[r]);
491
+ const maxVal = Math.max(...values.filter(v => v !== undefined));
492
+ const bestRuntime = runtimes[values.indexOf(maxVal)];
493
+
494
+ const row = [
495
+ dtype,
496
+ ...runtimes.map(r => {
497
+ const val = results[r];
498
+ if (!val) return '-';
499
+ const formatted = val >= 1000 ? `${(val / 1000).toFixed(1)}k` : val.toFixed(0);
500
+ return val === maxVal ? `**${formatted}**` : formatted;
501
+ }),
502
+ bestRuntime
503
+ ];
504
+
505
+ report += '| ' + row.join(' | ') + ' |\n';
506
+ }
507
+
508
+ report += '\n';
509
+ }
510
+
511
+ // Summary section
512
+ report += '## Summary\n\n';
513
+
514
+ if (runtimes.includes('native')) {
515
+ const nativeResults = allResults['native'];
516
+ const avgNative = nativeResults.reduce((sum, r) => sum + r.opsPerSec, 0) / nativeResults.length;
517
+
518
+ for (const runtime of runtimes) {
519
+ if (runtime === 'native') continue;
520
+
521
+ const runtimeResults = allResults[runtime];
522
+ const avgRuntime = runtimeResults.reduce((sum, r) => sum + r.opsPerSec, 0) / runtimeResults.length;
523
+ const ratio = (avgRuntime / avgNative * 100).toFixed(0);
524
+
525
+ report += `- **${runtime}**: ${ratio}% of native performance\n`;
526
+ }
527
+ }
528
+
529
+ report += '\n---\n\n';
530
+ report += `*Generated with NumKong benchmark suite on ${new Date().toLocaleString()}*\n`;
531
+
532
+ return report;
533
+ }
534
+
535
+ function generateJSONSummary(allResults) {
536
+ const summary = {
537
+ timestamp: new Date().toISOString(),
538
+ node_version: process.version,
539
+ runtimes: {}
540
+ };
541
+
542
+ for (const [runtime, results] of Object.entries(allResults)) {
543
+ const opsPerSec = results.map(r => r.opsPerSec);
544
+ summary.runtimes[runtime] = {
545
+ count: results.length,
546
+ avgOpsPerSec: opsPerSec.reduce((a, b) => a + b, 0) / opsPerSec.length,
547
+ minOpsPerSec: Math.min(...opsPerSec),
548
+ maxOpsPerSec: Math.max(...opsPerSec)
549
+ };
550
+ }
551
+
552
+ return summary;
553
+ }
554
+
555
+ function generateReport() {
556
+ console.log('╔════════════════════════════════════════════════════════════════╗');
557
+ console.log('║ NumKong Benchmark Report Generator ║');
558
+ console.log('╚════════════════════════════════════════════════════════════════╝\n');
559
+
560
+ try {
561
+ const allResults = loadAllResults();
562
+ const runtimes = Object.keys(allResults);
563
+
564
+ console.log(`Found results for ${runtimes.length} runtime(s): ${runtimes.join(', ')}\n`);
565
+
566
+ // Generate markdown report
567
+ const markdown = generateMarkdownReport(allResults);
568
+ const markdownPath = path.join(resultsDir, 'report.md');
569
+ writeFileSync(markdownPath, markdown);
570
+ console.log(`✓ Markdown report: ${markdownPath}`);
571
+
572
+ // Generate JSON summary
573
+ const summary = generateJSONSummary(allResults);
574
+ const summaryPath = path.join(resultsDir, 'summary.json');
575
+ writeFileSync(summaryPath, JSON.stringify(summary, null, 2));
576
+ console.log(`✓ JSON summary: ${summaryPath}`);
577
+
578
+ console.log('\n✅ Report generation complete!');
579
+
580
+ // Print quick summary
581
+ console.log('\nQuick Summary:');
582
+ for (const [runtime, stats] of Object.entries(summary.runtimes)) {
583
+ console.log(` ${runtime}: ${stats.avgOpsPerSec.toFixed(0)} ops/sec avg (${stats.count} tests)`);
584
+ }
585
+
586
+ } catch (e) {
587
+ console.error(`❌ Error: ${e.message}`);
588
+ process.exit(1);
589
+ }
590
+ }
591
+
592
+
593
+ async function main() {
594
+ const args = process.argv.slice(2);
595
+
596
+ if (args.includes('--report')) {
597
+ // Generate report from existing results
598
+ generateReport();
599
+ } else if (args.includes('--browser')) {
600
+ // Run browser benchmarks
601
+ await runBrowserBenchmarks();
602
+ } else {
603
+ // Run benchmarks for configured runtime
604
+ await runBenchmarks();
605
+ }
606
+ }
607
+
608
+ // Run if called directly
609
+ if (process.argv[1] && path.resolve(fileURLToPath(import.meta.url)) === path.resolve(process.argv[1])) {
610
+ main().catch((e) => {
611
+ console.error('❌ Fatal error:', e.message);
612
+ process.exit(1);
613
+ });
614
+ }
615
+
616
+ export { runBenchmarks, generateReport, loadNumKong };