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,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 };