usearch 2.21.3 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) hide show
  1. package/README.md +24 -24
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +7 -7
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +83 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +235 -52
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/dist/cjs/usearch.d.ts +8 -3
  16. package/javascript/dist/cjs/usearch.js +12 -4
  17. package/javascript/dist/esm/usearch.d.ts +8 -3
  18. package/javascript/dist/esm/usearch.js +12 -4
  19. package/javascript/lib.cpp +17 -0
  20. package/javascript/usearch.ts +14 -6
  21. package/numkong/.clang-tidy +30 -0
  22. package/{simsimd → numkong}/.cmake-format.py +18 -0
  23. package/numkong/.editorconfig +12 -0
  24. package/numkong/.git-blame-ignore-revs +123 -0
  25. package/numkong/.mailmap +15 -0
  26. package/numkong/.spi.yml +11 -0
  27. package/numkong/.swift-format +14 -0
  28. package/numkong/CITATION.cff +81 -0
  29. package/numkong/CONTRIBUTING.md +500 -0
  30. package/numkong/Cargo.toml +54 -0
  31. package/numkong/MANIFEST.in +8 -0
  32. package/numkong/Package.swift +84 -0
  33. package/numkong/README.md +569 -0
  34. package/numkong/bench/README.md +217 -0
  35. package/numkong/bench/bench-browser.html +323 -0
  36. package/numkong/bench/bench.cpp +344 -0
  37. package/numkong/bench/bench.hpp +816 -0
  38. package/numkong/bench/bench.js +148 -0
  39. package/numkong/bench/bench.mjs +616 -0
  40. package/numkong/bench/bench_attention.cpp +113 -0
  41. package/numkong/bench/bench_cast.cpp +264 -0
  42. package/numkong/bench/bench_cross_amx.cpp +62 -0
  43. package/numkong/bench/bench_cross_arm.cpp +245 -0
  44. package/numkong/bench/bench_cross_blas.cpp +309 -0
  45. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  46. package/numkong/bench/bench_cross_power.cpp +84 -0
  47. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  48. package/numkong/bench/bench_cross_serial.cpp +151 -0
  49. package/numkong/bench/bench_cross_sme.cpp +163 -0
  50. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  51. package/numkong/bench/bench_cross_x86.cpp +455 -0
  52. package/numkong/bench/bench_curved.cpp +210 -0
  53. package/numkong/bench/bench_dot.cpp +315 -0
  54. package/numkong/bench/bench_each.cpp +503 -0
  55. package/numkong/bench/bench_geospatial.cpp +112 -0
  56. package/numkong/bench/bench_maxsim.cpp +154 -0
  57. package/numkong/bench/bench_mesh.cpp +148 -0
  58. package/numkong/bench/bench_probability.cpp +60 -0
  59. package/numkong/bench/bench_reduce.cpp +371 -0
  60. package/numkong/bench/bench_set.cpp +73 -0
  61. package/numkong/bench/bench_sparse.cpp +198 -0
  62. package/numkong/bench/bench_spatial.cpp +347 -0
  63. package/numkong/bench/bench_trigonometry.cpp +137 -0
  64. package/numkong/bench/swift/Bench.swift +506 -0
  65. package/numkong/binding.gyp +169 -0
  66. package/numkong/build.rs +484 -0
  67. package/numkong/c/dispatch.h +512 -0
  68. package/numkong/c/dispatch_bf16.c +447 -0
  69. package/numkong/c/dispatch_bf16c.c +52 -0
  70. package/numkong/c/dispatch_e2m3.c +296 -0
  71. package/numkong/c/dispatch_e3m2.c +284 -0
  72. package/numkong/c/dispatch_e4m3.c +318 -0
  73. package/numkong/c/dispatch_e5m2.c +316 -0
  74. package/numkong/c/dispatch_f16.c +452 -0
  75. package/numkong/c/dispatch_f16c.c +58 -0
  76. package/numkong/c/dispatch_f32.c +434 -0
  77. package/numkong/c/dispatch_f32c.c +99 -0
  78. package/numkong/c/dispatch_f64.c +348 -0
  79. package/numkong/c/dispatch_f64c.c +98 -0
  80. package/numkong/c/dispatch_i16.c +96 -0
  81. package/numkong/c/dispatch_i32.c +89 -0
  82. package/numkong/c/dispatch_i4.c +153 -0
  83. package/numkong/c/dispatch_i64.c +86 -0
  84. package/numkong/c/dispatch_i8.c +348 -0
  85. package/numkong/c/dispatch_other.c +348 -0
  86. package/numkong/c/dispatch_u1.c +193 -0
  87. package/numkong/c/dispatch_u16.c +124 -0
  88. package/numkong/c/dispatch_u32.c +118 -0
  89. package/numkong/c/dispatch_u4.c +153 -0
  90. package/numkong/c/dispatch_u64.c +102 -0
  91. package/numkong/c/dispatch_u8.c +364 -0
  92. package/numkong/c/numkong.c +940 -0
  93. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  94. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  95. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  96. package/numkong/cmake/nk_math_lib.cmake +46 -0
  97. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  99. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  100. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  101. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  102. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  103. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  104. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  105. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  106. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  107. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  108. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  109. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  110. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  111. package/numkong/include/README.md +643 -0
  112. package/numkong/include/module.modulemap +129 -0
  113. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  114. package/numkong/include/numkong/attention/sme.h +2075 -0
  115. package/numkong/include/numkong/attention.h +49 -0
  116. package/numkong/include/numkong/capabilities.h +930 -0
  117. package/numkong/include/numkong/cast/README.md +262 -0
  118. package/numkong/include/numkong/cast/diamond.h +64 -0
  119. package/numkong/include/numkong/cast/haswell.h +823 -0
  120. package/numkong/include/numkong/cast/icelake.h +475 -0
  121. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  122. package/numkong/include/numkong/cast/neon.h +1174 -0
  123. package/numkong/include/numkong/cast/powervsx.h +449 -0
  124. package/numkong/include/numkong/cast/rvv.h +970 -0
  125. package/numkong/include/numkong/cast/sapphire.h +262 -0
  126. package/numkong/include/numkong/cast/serial.h +2336 -0
  127. package/numkong/include/numkong/cast/skylake.h +915 -0
  128. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  129. package/numkong/include/numkong/cast.h +254 -0
  130. package/numkong/include/numkong/cast.hpp +44 -0
  131. package/numkong/include/numkong/curved/README.md +223 -0
  132. package/numkong/include/numkong/curved/genoa.h +182 -0
  133. package/numkong/include/numkong/curved/haswell.h +276 -0
  134. package/numkong/include/numkong/curved/neon.h +329 -0
  135. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  136. package/numkong/include/numkong/curved/rvv.h +305 -0
  137. package/numkong/include/numkong/curved/serial.h +207 -0
  138. package/numkong/include/numkong/curved/skylake.h +457 -0
  139. package/numkong/include/numkong/curved/smef64.h +530 -0
  140. package/numkong/include/numkong/curved.h +513 -0
  141. package/numkong/include/numkong/curved.hpp +144 -0
  142. package/numkong/include/numkong/dot/README.md +442 -0
  143. package/numkong/include/numkong/dot/alder.h +563 -0
  144. package/numkong/include/numkong/dot/diamond.h +158 -0
  145. package/numkong/include/numkong/dot/genoa.h +289 -0
  146. package/numkong/include/numkong/dot/haswell.h +1723 -0
  147. package/numkong/include/numkong/dot/icelake.h +997 -0
  148. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  149. package/numkong/include/numkong/dot/neon.h +869 -0
  150. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  151. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  152. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  153. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  154. package/numkong/include/numkong/dot/powervsx.h +752 -0
  155. package/numkong/include/numkong/dot/rvv.h +722 -0
  156. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  157. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  158. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  159. package/numkong/include/numkong/dot/sapphire.h +141 -0
  160. package/numkong/include/numkong/dot/serial.h +874 -0
  161. package/numkong/include/numkong/dot/sierra.h +405 -0
  162. package/numkong/include/numkong/dot/skylake.h +1116 -0
  163. package/numkong/include/numkong/dot/sve.h +420 -0
  164. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  165. package/numkong/include/numkong/dot/svehalf.h +168 -0
  166. package/numkong/include/numkong/dot/svesdot.h +90 -0
  167. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  168. package/numkong/include/numkong/dot.h +1136 -0
  169. package/numkong/include/numkong/dot.hpp +94 -0
  170. package/numkong/include/numkong/dots/README.md +496 -0
  171. package/numkong/include/numkong/dots/alder.h +117 -0
  172. package/numkong/include/numkong/dots/diamond.h +86 -0
  173. package/numkong/include/numkong/dots/genoa.h +100 -0
  174. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  175. package/numkong/include/numkong/dots/haswell.h +310 -0
  176. package/numkong/include/numkong/dots/icelake.h +180 -0
  177. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  178. package/numkong/include/numkong/dots/neon.h +123 -0
  179. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  180. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  181. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  182. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  183. package/numkong/include/numkong/dots/powervsx.h +194 -0
  184. package/numkong/include/numkong/dots/rvv.h +2593 -0
  185. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  186. package/numkong/include/numkong/dots/serial.h +2867 -0
  187. package/numkong/include/numkong/dots/sierra.h +100 -0
  188. package/numkong/include/numkong/dots/skylake.h +207 -0
  189. package/numkong/include/numkong/dots/sme.h +5041 -0
  190. package/numkong/include/numkong/dots/smebi32.h +477 -0
  191. package/numkong/include/numkong/dots/smef64.h +1328 -0
  192. package/numkong/include/numkong/dots/smehalf.h +47 -0
  193. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  194. package/numkong/include/numkong/dots.h +3110 -0
  195. package/numkong/include/numkong/dots.hpp +641 -0
  196. package/numkong/include/numkong/each/README.md +465 -0
  197. package/numkong/include/numkong/each/haswell.h +1658 -0
  198. package/numkong/include/numkong/each/icelake.h +272 -0
  199. package/numkong/include/numkong/each/neon.h +1138 -0
  200. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  201. package/numkong/include/numkong/each/neonhalf.h +318 -0
  202. package/numkong/include/numkong/each/rvv.h +1121 -0
  203. package/numkong/include/numkong/each/sapphire.h +343 -0
  204. package/numkong/include/numkong/each/serial.h +282 -0
  205. package/numkong/include/numkong/each/skylake.h +1562 -0
  206. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  207. package/numkong/include/numkong/each.h +2232 -0
  208. package/numkong/include/numkong/each.hpp +434 -0
  209. package/numkong/include/numkong/geospatial/README.md +147 -0
  210. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  211. package/numkong/include/numkong/geospatial/neon.h +615 -0
  212. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  213. package/numkong/include/numkong/geospatial/serial.h +309 -0
  214. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  215. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  216. package/numkong/include/numkong/geospatial.h +453 -0
  217. package/numkong/include/numkong/geospatial.hpp +235 -0
  218. package/numkong/include/numkong/matrix.hpp +336 -0
  219. package/numkong/include/numkong/maxsim/README.md +187 -0
  220. package/numkong/include/numkong/maxsim/alder.h +511 -0
  221. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  222. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  223. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  224. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  225. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  226. package/numkong/include/numkong/maxsim/serial.h +490 -0
  227. package/numkong/include/numkong/maxsim/sme.h +993 -0
  228. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  229. package/numkong/include/numkong/maxsim.h +571 -0
  230. package/numkong/include/numkong/maxsim.hpp +133 -0
  231. package/numkong/include/numkong/mesh/README.md +219 -0
  232. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  233. package/numkong/include/numkong/mesh/neon.h +1821 -0
  234. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  235. package/numkong/include/numkong/mesh/rvv.h +936 -0
  236. package/numkong/include/numkong/mesh/serial.h +721 -0
  237. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  238. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  239. package/numkong/include/numkong/mesh.h +666 -0
  240. package/numkong/include/numkong/mesh.hpp +701 -0
  241. package/numkong/include/numkong/numkong.h +78 -0
  242. package/numkong/include/numkong/numkong.hpp +58 -0
  243. package/numkong/include/numkong/probability/README.md +177 -0
  244. package/numkong/include/numkong/probability/haswell.h +267 -0
  245. package/numkong/include/numkong/probability/neon.h +255 -0
  246. package/numkong/include/numkong/probability/rvv.h +414 -0
  247. package/numkong/include/numkong/probability/serial.h +181 -0
  248. package/numkong/include/numkong/probability/skylake.h +324 -0
  249. package/numkong/include/numkong/probability.h +380 -0
  250. package/numkong/include/numkong/probability.hpp +120 -0
  251. package/numkong/include/numkong/random.h +50 -0
  252. package/numkong/include/numkong/random.hpp +285 -0
  253. package/numkong/include/numkong/reduce/README.md +552 -0
  254. package/numkong/include/numkong/reduce/alder.h +636 -0
  255. package/numkong/include/numkong/reduce/genoa.h +201 -0
  256. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  257. package/numkong/include/numkong/reduce/icelake.h +549 -0
  258. package/numkong/include/numkong/reduce/neon.h +3980 -0
  259. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  260. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  261. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  262. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  263. package/numkong/include/numkong/reduce/serial.h +753 -0
  264. package/numkong/include/numkong/reduce/sierra.h +338 -0
  265. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  266. package/numkong/include/numkong/reduce/sve.h +52 -0
  267. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  268. package/numkong/include/numkong/reduce.h +1582 -0
  269. package/numkong/include/numkong/reduce.hpp +778 -0
  270. package/numkong/include/numkong/scalar/README.md +89 -0
  271. package/numkong/include/numkong/scalar/haswell.h +122 -0
  272. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  273. package/numkong/include/numkong/scalar/neon.h +122 -0
  274. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  275. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  276. package/numkong/include/numkong/scalar/rvv.h +211 -0
  277. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  278. package/numkong/include/numkong/scalar/serial.h +332 -0
  279. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  280. package/numkong/include/numkong/scalar.h +696 -0
  281. package/numkong/include/numkong/set/README.md +179 -0
  282. package/numkong/include/numkong/set/haswell.h +334 -0
  283. package/numkong/include/numkong/set/icelake.h +485 -0
  284. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  285. package/numkong/include/numkong/set/neon.h +363 -0
  286. package/numkong/include/numkong/set/powervsx.h +326 -0
  287. package/numkong/include/numkong/set/rvv.h +226 -0
  288. package/numkong/include/numkong/set/rvvbb.h +117 -0
  289. package/numkong/include/numkong/set/serial.h +174 -0
  290. package/numkong/include/numkong/set/sve.h +187 -0
  291. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  292. package/numkong/include/numkong/set.h +471 -0
  293. package/numkong/include/numkong/set.hpp +114 -0
  294. package/numkong/include/numkong/sets/README.md +149 -0
  295. package/numkong/include/numkong/sets/haswell.h +63 -0
  296. package/numkong/include/numkong/sets/icelake.h +66 -0
  297. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  298. package/numkong/include/numkong/sets/neon.h +61 -0
  299. package/numkong/include/numkong/sets/powervsx.h +65 -0
  300. package/numkong/include/numkong/sets/serial.h +43 -0
  301. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  302. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  303. package/numkong/include/numkong/sets.h +382 -0
  304. package/numkong/include/numkong/sparse/README.md +156 -0
  305. package/numkong/include/numkong/sparse/icelake.h +463 -0
  306. package/numkong/include/numkong/sparse/neon.h +288 -0
  307. package/numkong/include/numkong/sparse/serial.h +117 -0
  308. package/numkong/include/numkong/sparse/sve2.h +504 -0
  309. package/numkong/include/numkong/sparse/turin.h +322 -0
  310. package/numkong/include/numkong/sparse.h +363 -0
  311. package/numkong/include/numkong/sparse.hpp +113 -0
  312. package/numkong/include/numkong/spatial/README.md +439 -0
  313. package/numkong/include/numkong/spatial/alder.h +604 -0
  314. package/numkong/include/numkong/spatial/diamond.h +240 -0
  315. package/numkong/include/numkong/spatial/genoa.h +222 -0
  316. package/numkong/include/numkong/spatial/haswell.h +979 -0
  317. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  318. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  319. package/numkong/include/numkong/spatial/neon.h +846 -0
  320. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  321. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  322. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  323. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  324. package/numkong/include/numkong/spatial/rvv.h +991 -0
  325. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  326. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  327. package/numkong/include/numkong/spatial/serial.h +347 -0
  328. package/numkong/include/numkong/spatial/sierra.h +516 -0
  329. package/numkong/include/numkong/spatial/skylake.h +605 -0
  330. package/numkong/include/numkong/spatial/sve.h +246 -0
  331. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  332. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  333. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  334. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  335. package/numkong/include/numkong/spatial.h +1681 -0
  336. package/numkong/include/numkong/spatial.hpp +183 -0
  337. package/numkong/include/numkong/spatials/README.md +580 -0
  338. package/numkong/include/numkong/spatials/alder.h +94 -0
  339. package/numkong/include/numkong/spatials/diamond.h +82 -0
  340. package/numkong/include/numkong/spatials/genoa.h +94 -0
  341. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  342. package/numkong/include/numkong/spatials/haswell.h +219 -0
  343. package/numkong/include/numkong/spatials/icelake.h +113 -0
  344. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  345. package/numkong/include/numkong/spatials/neon.h +109 -0
  346. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  347. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  348. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  349. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  350. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  351. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  352. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  353. package/numkong/include/numkong/spatials/serial.h +248 -0
  354. package/numkong/include/numkong/spatials/sierra.h +96 -0
  355. package/numkong/include/numkong/spatials/skylake.h +184 -0
  356. package/numkong/include/numkong/spatials/sme.h +1927 -0
  357. package/numkong/include/numkong/spatials/smef64.h +483 -0
  358. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  359. package/numkong/include/numkong/spatials.h +3374 -0
  360. package/numkong/include/numkong/spatials.hpp +509 -0
  361. package/numkong/include/numkong/tensor.hpp +1981 -0
  362. package/numkong/include/numkong/trigonometry/README.md +184 -0
  363. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  364. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  365. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  366. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  367. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  368. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  369. package/numkong/include/numkong/trigonometry.h +467 -0
  370. package/numkong/include/numkong/trigonometry.hpp +166 -0
  371. package/numkong/include/numkong/types.h +1695 -0
  372. package/numkong/include/numkong/types.hpp +6027 -0
  373. package/numkong/include/numkong/vector.hpp +766 -0
  374. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  375. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  376. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  377. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  378. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  380. package/numkong/javascript/README.md +254 -0
  381. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  382. package/numkong/javascript/numkong-browser.ts +40 -0
  383. package/numkong/javascript/numkong-wasm.ts +750 -0
  384. package/numkong/javascript/numkong.c +712 -0
  385. package/numkong/javascript/numkong.ts +613 -0
  386. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  387. package/numkong/javascript/tsconfig-cjs.json +13 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  389. package/numkong/javascript/types.ts +784 -0
  390. package/numkong/numkong.gypi +104 -0
  391. package/numkong/package.json +108 -0
  392. package/numkong/probes/arm_neon.c +8 -0
  393. package/numkong/probes/arm_neon_bfdot.c +9 -0
  394. package/numkong/probes/arm_neon_fhm.c +9 -0
  395. package/numkong/probes/arm_neon_half.c +8 -0
  396. package/numkong/probes/arm_neon_sdot.c +9 -0
  397. package/numkong/probes/arm_neonfp8.c +9 -0
  398. package/numkong/probes/arm_sme.c +16 -0
  399. package/numkong/probes/arm_sme2.c +16 -0
  400. package/numkong/probes/arm_sme2p1.c +16 -0
  401. package/numkong/probes/arm_sme_bf16.c +16 -0
  402. package/numkong/probes/arm_sme_bi32.c +16 -0
  403. package/numkong/probes/arm_sme_f64.c +16 -0
  404. package/numkong/probes/arm_sme_fa64.c +14 -0
  405. package/numkong/probes/arm_sme_half.c +16 -0
  406. package/numkong/probes/arm_sme_lut2.c +15 -0
  407. package/numkong/probes/arm_sve.c +18 -0
  408. package/numkong/probes/arm_sve2.c +20 -0
  409. package/numkong/probes/arm_sve2p1.c +18 -0
  410. package/numkong/probes/arm_sve_bfdot.c +20 -0
  411. package/numkong/probes/arm_sve_half.c +18 -0
  412. package/numkong/probes/arm_sve_sdot.c +21 -0
  413. package/numkong/probes/loongarch_lasx.c +12 -0
  414. package/numkong/probes/power_vsx.c +12 -0
  415. package/numkong/probes/probe.js +127 -0
  416. package/numkong/probes/riscv_rvv.c +14 -0
  417. package/numkong/probes/riscv_rvv_bb.c +15 -0
  418. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  419. package/numkong/probes/riscv_rvv_half.c +14 -0
  420. package/numkong/probes/wasm_v128relaxed.c +11 -0
  421. package/numkong/probes/x86_alder.c +17 -0
  422. package/numkong/probes/x86_diamond.c +17 -0
  423. package/numkong/probes/x86_genoa.c +17 -0
  424. package/numkong/probes/x86_graniteamx.c +19 -0
  425. package/numkong/probes/x86_haswell.c +11 -0
  426. package/numkong/probes/x86_icelake.c +17 -0
  427. package/numkong/probes/x86_sapphire.c +16 -0
  428. package/numkong/probes/x86_sapphireamx.c +18 -0
  429. package/numkong/probes/x86_sierra.c +17 -0
  430. package/numkong/probes/x86_skylake.c +15 -0
  431. package/numkong/probes/x86_turin.c +17 -0
  432. package/numkong/rust/README.md +698 -0
  433. package/numkong/rust/capabilities.rs +96 -0
  434. package/numkong/rust/cast.rs +314 -0
  435. package/numkong/rust/curved.rs +391 -0
  436. package/numkong/rust/each.rs +2721 -0
  437. package/numkong/rust/geospatial.rs +343 -0
  438. package/numkong/rust/matrix.rs +5424 -0
  439. package/numkong/rust/maxsim.rs +540 -0
  440. package/numkong/rust/mesh.rs +837 -0
  441. package/numkong/rust/numkong.rs +409 -0
  442. package/numkong/rust/probability.rs +272 -0
  443. package/numkong/rust/reduce.rs +1249 -0
  444. package/numkong/rust/set.rs +194 -0
  445. package/numkong/rust/sparse.rs +513 -0
  446. package/numkong/rust/spatial.rs +1815 -0
  447. package/numkong/rust/tensor.rs +7565 -0
  448. package/numkong/rust/types.rs +3666 -0
  449. package/numkong/rust/vector.rs +1899 -0
  450. package/numkong/rustfmt.toml +2 -0
  451. package/numkong/swift/Matrix.swift +1388 -0
  452. package/numkong/swift/MaxSim.swift +151 -0
  453. package/numkong/swift/NumKong.swift +283 -0
  454. package/numkong/swift/Numerics.swift +329 -0
  455. package/numkong/swift/README.md +433 -0
  456. package/numkong/swift/Scalar.swift +741 -0
  457. package/numkong/swift/Tensor.swift +209 -0
  458. package/numkong/test/README.md +315 -0
  459. package/numkong/test/playwright.config.ts +16 -0
  460. package/numkong/test/swift/Test.swift +534 -0
  461. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  462. package/numkong/test/test-browser-bundle.html +188 -0
  463. package/numkong/test/test-browser-runner.mjs +43 -0
  464. package/numkong/test/test-browser.html +305 -0
  465. package/numkong/test/test-dtypes.mjs +453 -0
  466. package/numkong/test/test-wasm.mjs +267 -0
  467. package/numkong/test/test.cpp +442 -0
  468. package/numkong/test/test.hpp +580 -0
  469. package/numkong/test/test.mjs +363 -0
  470. package/numkong/test/test_base.py +1041 -0
  471. package/numkong/test/test_cast.cpp +242 -0
  472. package/numkong/test/test_cross.hpp +551 -0
  473. package/numkong/test/test_cross.py +467 -0
  474. package/numkong/test/test_cross_amx.cpp +50 -0
  475. package/numkong/test/test_cross_arm.cpp +225 -0
  476. package/numkong/test/test_cross_blas.cpp +354 -0
  477. package/numkong/test/test_cross_loongarch.cpp +90 -0
  478. package/numkong/test/test_cross_power.cpp +73 -0
  479. package/numkong/test/test_cross_rvv.cpp +109 -0
  480. package/numkong/test/test_cross_serial.cpp +181 -0
  481. package/numkong/test/test_cross_sme.cpp +148 -0
  482. package/numkong/test/test_cross_wasm.cpp +141 -0
  483. package/numkong/test/test_cross_x86.cpp +442 -0
  484. package/numkong/test/test_curved.cpp +182 -0
  485. package/numkong/test/test_curved.py +207 -0
  486. package/numkong/test/test_dot.cpp +353 -0
  487. package/numkong/test/test_dot.py +296 -0
  488. package/numkong/test/test_each.cpp +437 -0
  489. package/numkong/test/test_each.py +756 -0
  490. package/numkong/test/test_geospatial.cpp +155 -0
  491. package/numkong/test/test_geospatial.py +241 -0
  492. package/numkong/test/test_maxsim.cpp +138 -0
  493. package/numkong/test/test_maxsim.py +209 -0
  494. package/numkong/test/test_mesh.cpp +203 -0
  495. package/numkong/test/test_mesh.py +394 -0
  496. package/numkong/test/test_probability.cpp +136 -0
  497. package/numkong/test/test_probability.py +166 -0
  498. package/numkong/test/test_reduce.cpp +563 -0
  499. package/numkong/test/test_reduce.py +781 -0
  500. package/numkong/test/test_set.cpp +151 -0
  501. package/numkong/test/test_set.py +120 -0
  502. package/numkong/test/test_similarities.py +579 -0
  503. package/numkong/test/test_sparse.cpp +121 -0
  504. package/numkong/test/test_sparse.py +118 -0
  505. package/numkong/test/test_spatial.cpp +518 -0
  506. package/numkong/test/test_spatial.py +269 -0
  507. package/numkong/test/test_tensor.cpp +884 -0
  508. package/numkong/test/test_tensor.py +1417 -0
  509. package/numkong/test/test_trigonometry.cpp +156 -0
  510. package/numkong/test/test_trigonometry.py +180 -0
  511. package/package.json +7 -8
  512. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  513. package/prebuilds/linux-arm64/usearch.node +0 -0
  514. package/prebuilds/linux-x64/usearch.node +0 -0
  515. package/fp16/CMakeLists.txt +0 -176
  516. package/fp16/LICENSE +0 -11
  517. package/fp16/README.md +0 -20
  518. package/fp16/bench/alt-element.cc +0 -89
  519. package/fp16/bench/from-alt-array.cc +0 -175
  520. package/fp16/bench/from-ieee-array.cc +0 -399
  521. package/fp16/bench/ieee-element.cc +0 -272
  522. package/fp16/bench/to-alt-array.cc +0 -91
  523. package/fp16/bench/to-ieee-array.cc +0 -303
  524. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  525. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  526. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  527. package/fp16/configure.py +0 -65
  528. package/fp16/confu.yaml +0 -8
  529. package/fp16/include/fp16/__init__.py +0 -0
  530. package/fp16/include/fp16/avx.py +0 -50
  531. package/fp16/include/fp16/avx2.py +0 -53
  532. package/fp16/include/fp16/bitcasts.h +0 -92
  533. package/fp16/include/fp16/fp16.h +0 -451
  534. package/fp16/include/fp16/psimd.h +0 -131
  535. package/fp16/include/fp16.h +0 -11
  536. package/fp16/jni/Android.mk +0 -6
  537. package/fp16/jni/Application.mk +0 -4
  538. package/fp16/test/alt-from-fp32-value.cc +0 -498
  539. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  540. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  541. package/fp16/test/alt-to-fp32-value.cc +0 -348
  542. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  543. package/fp16/test/bitcasts.cc +0 -56
  544. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  545. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  546. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  547. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  548. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  549. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  550. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  551. package/fp16/test/peachpy/stubs.py +0 -38
  552. package/fp16/test/tables.cc +0 -530
  553. package/fp16/test/tables.h +0 -13
  554. package/fp16/third-party/THHalf.h +0 -92
  555. package/fp16/third-party/eigen-half.h +0 -170
  556. package/fp16/third-party/float16-compressor.h +0 -80
  557. package/fp16/third-party/half.hpp +0 -2916
  558. package/fp16/third-party/npy-halffloat.h +0 -328
  559. package/simsimd/.git-blame-ignore-revs +0 -2
  560. package/simsimd/CONTRIBUTING.md +0 -321
  561. package/simsimd/Cargo.toml +0 -49
  562. package/simsimd/MANIFEST.in +0 -4
  563. package/simsimd/Package.swift +0 -28
  564. package/simsimd/README.md +0 -1493
  565. package/simsimd/binding.gyp +0 -35
  566. package/simsimd/build.rs +0 -70
  567. package/simsimd/c/lib.c +0 -374
  568. package/simsimd/include/module.modulemap +0 -4
  569. package/simsimd/include/simsimd/binary.h +0 -486
  570. package/simsimd/include/simsimd/curved.h +0 -1541
  571. package/simsimd/include/simsimd/dot.h +0 -1853
  572. package/simsimd/include/simsimd/elementwise.h +0 -2465
  573. package/simsimd/include/simsimd/geospatial.h +0 -43
  574. package/simsimd/include/simsimd/mesh.h +0 -69
  575. package/simsimd/include/simsimd/probability.h +0 -606
  576. package/simsimd/include/simsimd/simsimd.h +0 -2567
  577. package/simsimd/include/simsimd/sparse.h +0 -1384
  578. package/simsimd/include/simsimd/spatial.h +0 -2335
  579. package/simsimd/include/simsimd/types.h +0 -666
  580. package/simsimd/javascript/fallback.ts +0 -233
  581. package/simsimd/javascript/lib.c +0 -125
  582. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  583. package/simsimd/javascript/simsimd.ts +0 -179
  584. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  585. package/simsimd/package-lock.json +0 -1761
  586. package/simsimd/package.json +0 -61
  587. package/simsimd/rust/lib.rs +0 -1821
  588. package/simsimd/scripts/bench.cxx +0 -1170
  589. package/simsimd/scripts/bench.ipynb +0 -187
  590. package/simsimd/scripts/bench.js +0 -127
  591. package/simsimd/scripts/bench.rs +0 -876
  592. package/simsimd/scripts/bench_vectors.py +0 -734
  593. package/simsimd/scripts/bench_vectors_live.py +0 -213
  594. package/simsimd/scripts/test.c +0 -187
  595. package/simsimd/scripts/test.mjs +0 -220
  596. package/simsimd/scripts/test.py +0 -1505
  597. package/simsimd/swift/SimSIMD.swift +0 -149
  598. package/simsimd/swift/Test.swift +0 -128
  599. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  600. /package/{simsimd → numkong}/LICENSE +0 -0
  601. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  602. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,750 @@
1
+ /**
2
+ * @brief WASM wrapper for NumKong providing N-API compatible interface
3
+ * @file javascript/numkong-wasm.ts
4
+ * @date February 6, 2026
5
+ *
6
+ * This module wraps the Emscripten-compiled WASM module to provide the same
7
+ * TypeScript API as the native N-API bindings. It handles:
8
+ * - Zero-copy TensorBase interop for cross-module WASM sharing
9
+ * - TypedArray type detection and dispatch
10
+ * - Result extraction from WASM heap
11
+ * - Error handling
12
+ * - Both wasm32 and wasm64 (memory64) modes
13
+ */
14
+
15
+ import { TensorBase, Matrix, PackedMatrix, DType, dtypeToString, outputDtype, KernelFamily } from './types.js';
16
+
17
+ /**
18
+ * Emscripten module interface.
19
+ * In wasm64 (memory64) mode, pointer/size params and returns become bigint.
20
+ * We use `any` for pointer arguments to support both modes uniformly.
21
+ */
22
+ interface EmscriptenModule {
23
+ _malloc(size: any): any;
24
+ _free(ptr: any): void;
25
+ wasmMemory: { buffer: ArrayBuffer };
26
+
27
+ // Distance functions - all use `any` for pointer/size args to support wasm32 (number) and wasm64 (bigint)
28
+ _nk_dot_f32(a: any, b: any, n: any, result: any): void;
29
+ _nk_angular_f32(a: any, b: any, n: any, result: any): void;
30
+ _nk_sqeuclidean_f32(a: any, b: any, n: any, result: any): void;
31
+ _nk_euclidean_f32(a: any, b: any, n: any, result: any): void;
32
+ _nk_dot_f64(a: any, b: any, n: any, result: any): void;
33
+ _nk_angular_f64(a: any, b: any, n: any, result: any): void;
34
+ _nk_sqeuclidean_f64(a: any, b: any, n: any, result: any): void;
35
+ _nk_euclidean_f64(a: any, b: any, n: any, result: any): void;
36
+ _nk_dot_f16(a: any, b: any, n: any, result: any): void;
37
+ _nk_angular_f16(a: any, b: any, n: any, result: any): void;
38
+ _nk_sqeuclidean_f16(a: any, b: any, n: any, result: any): void;
39
+ _nk_euclidean_f16(a: any, b: any, n: any, result: any): void;
40
+ _nk_dot_bf16(a: any, b: any, n: any, result: any): void;
41
+ _nk_angular_bf16(a: any, b: any, n: any, result: any): void;
42
+ _nk_sqeuclidean_bf16(a: any, b: any, n: any, result: any): void;
43
+ _nk_euclidean_bf16(a: any, b: any, n: any, result: any): void;
44
+ _nk_dot_i8(a: any, b: any, n: any, result: any): void;
45
+ _nk_angular_i8(a: any, b: any, n: any, result: any): void;
46
+ _nk_sqeuclidean_i8(a: any, b: any, n: any, result: any): void;
47
+ _nk_euclidean_i8(a: any, b: any, n: any, result: any): void;
48
+ _nk_dot_u8(a: any, b: any, n: any, result: any): void;
49
+ _nk_angular_u8(a: any, b: any, n: any, result: any): void;
50
+ _nk_sqeuclidean_u8(a: any, b: any, n: any, result: any): void;
51
+ _nk_euclidean_u8(a: any, b: any, n: any, result: any): void;
52
+ _nk_hamming_u1(a: any, b: any, n: any, result: any): void;
53
+ _nk_hamming_u8(a: any, b: any, n: any, result: any): void;
54
+ _nk_jaccard_u1(a: any, b: any, n: any, result: any): void;
55
+ _nk_jaccard_u16(a: any, b: any, n: any, result: any): void;
56
+ _nk_kld_f32(a: any, b: any, n: any, result: any): void;
57
+ _nk_kld_f64(a: any, b: any, n: any, result: any): void;
58
+ _nk_jsd_f32(a: any, b: any, n: any, result: any): void;
59
+ _nk_jsd_f64(a: any, b: any, n: any, result: any): void;
60
+ _nk_capabilities(): any;
61
+
62
+ [key: string]: any;
63
+ }
64
+
65
+ /** Pointer type passed to raw C functions: number in wasm32, bigint in wasm64 */
66
+ type WasmPtr = number | bigint;
67
+
68
+ let Module: EmscriptenModule | null = null;
69
+
70
+ /**
71
+ * Whether the WASM module uses memory64.
72
+ * In memory64 mode, Emscripten wraps _malloc/_free to accept/return number,
73
+ * but raw C function exports expect BigInt (i64) for pointer parameters.
74
+ * nk_size_t is always i32 (number) in WASM since NK_IS_64BIT_=0.
75
+ */
76
+ let isMemory64 = false;
77
+
78
+ // Pre-allocated 8-byte result buffer (covers f64/f32/i32/u32), allocated once in initWasm()
79
+ // Always a number (from Emscripten-wrapped _malloc), converted to WasmPtr for C calls
80
+ let resultPtr: number = 0;
81
+
82
+ // Heap views (created from wasmMemory buffer)
83
+ let HEAP32: Int32Array;
84
+ let HEAPU8: Uint8Array;
85
+ let HEAPU32: Uint32Array;
86
+ let HEAPF32: Float32Array;
87
+ let HEAPF64: Float64Array;
88
+
89
+ /**
90
+ * Convert a number (e.g. from _malloc or byteOffset) to the pointer type
91
+ * expected by raw C function exports. In wasm64, pointers are i64 (BigInt).
92
+ */
93
+ function toWasmPtr(n: number): WasmPtr {
94
+ return isMemory64 ? BigInt(n) : n;
95
+ }
96
+
97
+ /**
98
+ * Initializes the WASM backend with an Emscripten module instance.
99
+ * @param wasmModule - The Emscripten-compiled WASM module to use.
100
+ */
101
+ export function initWasm(wasmModule: EmscriptenModule): void {
102
+ Module = wasmModule;
103
+
104
+ // Create heap views from the WASM memory buffer
105
+ const buffer = wasmModule.wasmMemory.buffer;
106
+ HEAP32 = new Int32Array(buffer);
107
+ HEAPU8 = new Uint8Array(buffer);
108
+ HEAPU32 = new Uint32Array(buffer);
109
+ HEAPF32 = new Float32Array(buffer);
110
+ HEAPF64 = new Float64Array(buffer);
111
+
112
+ // Detect memory64 mode by probing whether raw C functions expect BigInt pointers.
113
+ // Emscripten wraps _malloc/_free to always use number, but raw C exports use i64
114
+ // (BigInt) for pointers in memory64 mode. We probe by calling a distance function
115
+ // with BigInt(0) args — if it doesn't throw, we're in memory64 mode.
116
+ try {
117
+ const probe = wasmModule._malloc(8);
118
+ wasmModule._nk_dot_f32(BigInt(probe), BigInt(probe), 0, BigInt(probe));
119
+ isMemory64 = true;
120
+ wasmModule._free(probe);
121
+ } catch {
122
+ isMemory64 = false;
123
+ }
124
+
125
+ // Pre-allocate an 8-byte result buffer (never freed during module lifetime)
126
+ // _malloc always returns number (Emscripten-wrapped in both modes)
127
+ resultPtr = wasmModule._malloc(8);
128
+ }
129
+
130
+ /**
131
+ * Type information for dispatching
132
+ */
133
+ interface TypeInfo {
134
+ dtype: DType;
135
+ bytesPerElement: number;
136
+ heapView: 'HEAP32' | 'HEAPU8' | 'HEAPU32' | 'HEAPF32' | 'HEAPF64';
137
+ resultType: 'f32' | 'f64' | 'i32' | 'u32';
138
+ }
139
+
140
+ /**
141
+ * Detect dtype from TypedArray constructor
142
+ */
143
+ function detectType(arr: any): TypeInfo {
144
+ if (arr instanceof Float64Array) {
145
+ return { dtype: DType.F64, bytesPerElement: 8, heapView: 'HEAPF64', resultType: 'f64' };
146
+ } else if (arr instanceof Float32Array) {
147
+ return { dtype: DType.F32, bytesPerElement: 4, heapView: 'HEAPF32', resultType: 'f64' };
148
+ } else if (arr instanceof Int8Array) {
149
+ return { dtype: DType.I8, bytesPerElement: 1, heapView: 'HEAPU8', resultType: 'i32' };
150
+ } else if (arr instanceof Uint8Array) {
151
+ return { dtype: DType.U8, bytesPerElement: 1, heapView: 'HEAPU8', resultType: 'u32' };
152
+ }
153
+
154
+ // Check for custom typed arrays from types.ts
155
+ const constructorName = arr.constructor.name;
156
+
157
+ if (constructorName === 'Float16Array') {
158
+ return { dtype: DType.F16, bytesPerElement: 2, heapView: 'HEAPU8', resultType: 'f32' };
159
+ } else if (constructorName === 'BFloat16Array') {
160
+ return { dtype: DType.BF16, bytesPerElement: 2, heapView: 'HEAPU8', resultType: 'f32' };
161
+ } else if (constructorName === 'E4M3Array') {
162
+ throw new Error('E4M3 not yet supported in WASM backend');
163
+ } else if (constructorName === 'E5M2Array') {
164
+ throw new Error('E5M2 not yet supported in WASM backend');
165
+ } else if (constructorName === 'BinaryArray') {
166
+ return { dtype: DType.U1, bytesPerElement: 1, heapView: 'HEAPU8', resultType: 'u32' };
167
+ }
168
+
169
+ throw new Error(`Unsupported array type: ${constructorName}`);
170
+ }
171
+
172
+ /**
173
+ * Get TypeInfo from a DType enum value.
174
+ */
175
+ function typeInfoFromDtype(dtype: DType): TypeInfo {
176
+ switch (dtype) {
177
+ case DType.F64: return { dtype, bytesPerElement: 8, heapView: 'HEAPF64', resultType: 'f64' };
178
+ case DType.F32: return { dtype, bytesPerElement: 4, heapView: 'HEAPF32', resultType: 'f64' };
179
+ case DType.F16: return { dtype, bytesPerElement: 2, heapView: 'HEAPU8', resultType: 'f32' };
180
+ case DType.BF16: return { dtype, bytesPerElement: 2, heapView: 'HEAPU8', resultType: 'f32' };
181
+ case DType.I8: return { dtype, bytesPerElement: 1, heapView: 'HEAPU8', resultType: 'i32' };
182
+ case DType.U8: return { dtype, bytesPerElement: 1, heapView: 'HEAPU8', resultType: 'u32' };
183
+ case DType.U1: return { dtype, bytesPerElement: 1, heapView: 'HEAPU8', resultType: 'u32' };
184
+ default: throw new Error(`Unsupported dtype: ${dtype}`);
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Flat struct carrying the fields needed for distance dispatch,
190
+ * avoiding the VectorView constructor chain for raw TypedArrays.
191
+ */
192
+ interface ResolvedInput {
193
+ buffer: ArrayBuffer;
194
+ byteOffset: number;
195
+ length: number;
196
+ byteLength: number;
197
+ typeInfo: TypeInfo;
198
+ }
199
+
200
+ /**
201
+ * Resolve an input that may be a TensorBase or a TypedArray into a uniform
202
+ * ResolvedInput for distance dispatch.
203
+ */
204
+ function resolveInput(a: TensorBase | any): ResolvedInput {
205
+ if (a instanceof TensorBase) {
206
+ return {
207
+ buffer: a.buffer, byteOffset: a.byteOffset,
208
+ length: a.length, byteLength: a.byteLength,
209
+ typeInfo: typeInfoFromDtype(a.dtype),
210
+ };
211
+ }
212
+ const typeInfo = detectType(a);
213
+ return {
214
+ buffer: a.buffer, byteOffset: a.byteOffset,
215
+ length: a.length, byteLength: a.length * typeInfo.bytesPerElement,
216
+ typeInfo,
217
+ };
218
+ }
219
+
220
+ /**
221
+ * Allocate WASM memory and copy data into it.
222
+ * Returns a number byte-offset (from Emscripten-wrapped _malloc).
223
+ */
224
+ function allocAndCopyResolved(buffer: ArrayBuffer, byteOffset: number, byteLength: number): number {
225
+ if (!Module) throw new Error('WASM module not initialized');
226
+ const ptr = Module._malloc(byteLength);
227
+ const src = new Uint8Array(buffer, byteOffset, byteLength);
228
+ HEAPU8.set(src, ptr);
229
+ return ptr;
230
+ }
231
+
232
+ /**
233
+ * Read result from WASM heap. ptr is a number byte-offset.
234
+ */
235
+ function readResult(ptr: number, resultType: 'f32' | 'f64' | 'i32' | 'u32'): number {
236
+ if (!Module) throw new Error('WASM module not initialized');
237
+
238
+ switch (resultType) {
239
+ case 'f64':
240
+ return HEAPF64[ptr / 8];
241
+ case 'f32':
242
+ return HEAPF32[ptr / 4];
243
+ case 'i32':
244
+ return HEAP32[ptr / 4];
245
+ case 'u32':
246
+ return HEAPU32[ptr / 4];
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Generic distance function wrapper.
252
+ * Uses zero-copy when arrays already live on the WASM heap.
253
+ */
254
+ function distance(metric: string, a: TensorBase | any, b: TensorBase | any): number {
255
+ if (!Module) {
256
+ throw new Error('WASM module not initialized. Call initWasm() first.');
257
+ }
258
+
259
+ const resolvedA = resolveInput(a);
260
+ const resolvedB = resolveInput(b);
261
+
262
+ if (resolvedA.length !== resolvedB.length) {
263
+ throw new Error(`Array length mismatch: ${resolvedA.length} !== ${resolvedB.length}`);
264
+ }
265
+
266
+ const n = resolvedA.length;
267
+
268
+ // Zero-copy: if the buffer IS the WASM memory, byteOffset is the pointer (number)
269
+ const isOnHeapA = resolvedA.buffer === Module.wasmMemory.buffer;
270
+ const isOnHeapB = resolvedB.buffer === Module.wasmMemory.buffer;
271
+ const aOff = isOnHeapA ? resolvedA.byteOffset : allocAndCopyResolved(resolvedA.buffer, resolvedA.byteOffset, resolvedA.byteLength);
272
+ const bOff = isOnHeapB ? resolvedB.byteOffset : allocAndCopyResolved(resolvedB.buffer, resolvedB.byteOffset, resolvedB.byteLength);
273
+
274
+ try {
275
+ // Call C function
276
+ const fnName = `_nk_${metric}_${dtypeToString(resolvedA.typeInfo.dtype)}` as keyof EmscriptenModule;
277
+ const fn = Module[fnName] as any;
278
+
279
+ if (!fn || typeof fn !== 'function') {
280
+ throw new Error(`Function ${fnName} not available in WASM module`);
281
+ }
282
+
283
+ // In wasm64, raw C exports expect BigInt for pointer args; nk_size_t is always i32 (number)
284
+ fn(toWasmPtr(aOff), toWasmPtr(bOff), n, toWasmPtr(resultPtr));
285
+
286
+ // Read result
287
+ return readResult(resultPtr, resolvedA.typeInfo.resultType);
288
+ } finally {
289
+ // _free is Emscripten-wrapped: always takes number
290
+ if (!isOnHeapA) Module._free(aOff);
291
+ if (!isOnHeapB) Module._free(bOff);
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Computes the squared Euclidean distance between two vectors.
297
+ * @param a - First vector (TypedArray or TensorBase).
298
+ * @param b - Second vector (must match type and length of a).
299
+ * @returns The squared Euclidean distance between a and b.
300
+ */
301
+ export function sqeuclidean(a: TensorBase | any, b: TensorBase | any): number {
302
+ return distance('sqeuclidean', a, b);
303
+ }
304
+
305
+ /**
306
+ * Computes the Euclidean distance between two vectors.
307
+ * @param a - First vector (TypedArray or TensorBase).
308
+ * @param b - Second vector (must match type and length of a).
309
+ * @returns The Euclidean distance between a and b.
310
+ */
311
+ export function euclidean(a: TensorBase | any, b: TensorBase | any): number {
312
+ return distance('euclidean', a, b);
313
+ }
314
+
315
+ /**
316
+ * Computes the angular distance between two vectors.
317
+ * @param a - First vector (TypedArray or TensorBase).
318
+ * @param b - Second vector (must match type and length of a).
319
+ * @returns The angular distance between a and b.
320
+ */
321
+ export function angular(a: TensorBase | any, b: TensorBase | any): number {
322
+ return distance('angular', a, b);
323
+ }
324
+
325
+ /**
326
+ * Computes the dot product of two vectors.
327
+ * @param a - First vector (TypedArray or TensorBase).
328
+ * @param b - Second vector (must match type and length of a).
329
+ * @returns The dot product of a and b.
330
+ */
331
+ export function dot(a: TensorBase | any, b: TensorBase | any): number {
332
+ return distance('dot', a, b);
333
+ }
334
+
335
+ /** Alias for {@link dot}. */
336
+ export const inner = dot;
337
+
338
+ /**
339
+ * Computes the bitwise Hamming distance between two vectors.
340
+ *
341
+ * Following N-API behavior, always treats input as u1 (binary/bit-packed),
342
+ * even if passed as Uint8Array. Each byte represents 8 bits.
343
+ *
344
+ * @param a - First bit-packed vector (Uint8Array or TensorBase).
345
+ * @param b - Second bit-packed vector (must match length of a).
346
+ * @returns The Hamming distance (number of differing bits) between a and b.
347
+ */
348
+ export function hamming(a: TensorBase | Uint8Array | any, b: TensorBase | Uint8Array | any): number {
349
+ if (!Module) {
350
+ throw new Error('WASM module not initialized');
351
+ }
352
+
353
+ // Extract flat fields; for raw TypedArrays treat as u1 (binary/bit-packed)
354
+ const bufferA = a.buffer as ArrayBuffer, offsetA = a.byteOffset as number, lengthA = a.length as number;
355
+ const bufferB = b.buffer as ArrayBuffer, offsetB = b.byteOffset as number, lengthB = b.length as number;
356
+ const byteLengthA = a instanceof TensorBase ? a.byteLength : lengthA;
357
+ const byteLengthB = b instanceof TensorBase ? b.byteLength : lengthB;
358
+
359
+ if (lengthA !== lengthB) {
360
+ throw new Error(`Array length mismatch: ${lengthA} !== ${lengthB}`);
361
+ }
362
+
363
+ const isOnHeapA = bufferA === Module.wasmMemory.buffer;
364
+ const isOnHeapB = bufferB === Module.wasmMemory.buffer;
365
+ const aOff = isOnHeapA ? offsetA : allocAndCopyResolved(bufferA, offsetA, byteLengthA);
366
+ const bOff = isOnHeapB ? offsetB : allocAndCopyResolved(bufferB, offsetB, byteLengthB);
367
+
368
+ try {
369
+ const fn = Module._nk_hamming_u1 as any;
370
+
371
+ if (!fn || typeof fn !== 'function') {
372
+ throw new Error('Function _nk_hamming_u1 not available in WASM module');
373
+ }
374
+
375
+ fn(toWasmPtr(aOff), toWasmPtr(bOff), lengthA, toWasmPtr(resultPtr));
376
+
377
+ return readResult(resultPtr, 'u32');
378
+ } finally {
379
+ if (!isOnHeapA) Module._free(aOff);
380
+ if (!isOnHeapB) Module._free(bOff);
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Computes the bitwise Jaccard distance between two vectors.
386
+ *
387
+ * Following N-API behavior, always treats input as u1 (binary/bit-packed),
388
+ * even if passed as Uint8Array. Each byte represents 8 bits.
389
+ *
390
+ * @param a - First bit-packed vector (Uint8Array or TensorBase).
391
+ * @param b - Second bit-packed vector (must match length of a).
392
+ * @returns The Jaccard distance (1 - Jaccard similarity) between a and b.
393
+ */
394
+ export function jaccard(a: TensorBase | Uint8Array | any, b: TensorBase | Uint8Array | any): number {
395
+ if (!Module) {
396
+ throw new Error('WASM module not initialized');
397
+ }
398
+
399
+ // Extract flat fields; for raw TypedArrays treat as u1 (binary/bit-packed)
400
+ const bufferA = a.buffer as ArrayBuffer, offsetA = a.byteOffset as number, lengthA = a.length as number;
401
+ const bufferB = b.buffer as ArrayBuffer, offsetB = b.byteOffset as number, lengthB = b.length as number;
402
+ const byteLengthA = a instanceof TensorBase ? a.byteLength : lengthA;
403
+ const byteLengthB = b instanceof TensorBase ? b.byteLength : lengthB;
404
+
405
+ if (lengthA !== lengthB) {
406
+ throw new Error(`Array length mismatch: ${lengthA} !== ${lengthB}`);
407
+ }
408
+
409
+ const isOnHeapA = bufferA === Module.wasmMemory.buffer;
410
+ const isOnHeapB = bufferB === Module.wasmMemory.buffer;
411
+ const aOff = isOnHeapA ? offsetA : allocAndCopyResolved(bufferA, offsetA, byteLengthA);
412
+ const bOff = isOnHeapB ? offsetB : allocAndCopyResolved(bufferB, offsetB, byteLengthB);
413
+
414
+ try {
415
+ const fn = Module._nk_jaccard_u1 as any;
416
+
417
+ if (!fn || typeof fn !== 'function') {
418
+ throw new Error('Function _nk_jaccard_u1 not available in WASM module');
419
+ }
420
+
421
+ fn(toWasmPtr(aOff), toWasmPtr(bOff), lengthA, toWasmPtr(resultPtr));
422
+
423
+ return readResult(resultPtr, 'f32');
424
+ } finally {
425
+ if (!isOnHeapA) Module._free(aOff);
426
+ if (!isOnHeapB) Module._free(bOff);
427
+ }
428
+ }
429
+
430
+ /**
431
+ * Computes the Kullback-Leibler divergence between two probability distributions.
432
+ * @param a - First probability distribution (Float32Array, Float64Array, or TensorBase).
433
+ * @param b - Second probability distribution (must match type and length of a).
434
+ * @returns The KL divergence KL(a || b).
435
+ */
436
+ export function kullbackleibler(a: TensorBase | Float64Array | Float32Array, b: TensorBase | Float64Array | Float32Array): number {
437
+ if (!Module) {
438
+ throw new Error('WASM module not initialized');
439
+ }
440
+
441
+ const resolvedA = resolveInput(a);
442
+ const resolvedB = resolveInput(b);
443
+
444
+ if (resolvedA.length !== resolvedB.length) {
445
+ throw new Error(`Array length mismatch: ${resolvedA.length} !== ${resolvedB.length}`);
446
+ }
447
+
448
+ const n = resolvedA.length;
449
+ const isOnHeapA = resolvedA.buffer === Module.wasmMemory.buffer;
450
+ const isOnHeapB = resolvedB.buffer === Module.wasmMemory.buffer;
451
+ const aOff = isOnHeapA ? resolvedA.byteOffset : allocAndCopyResolved(resolvedA.buffer, resolvedA.byteOffset, resolvedA.byteLength);
452
+ const bOff = isOnHeapB ? resolvedB.byteOffset : allocAndCopyResolved(resolvedB.buffer, resolvedB.byteOffset, resolvedB.byteLength);
453
+
454
+ try {
455
+ const fnName = `_nk_kld_${dtypeToString(resolvedA.typeInfo.dtype)}` as keyof EmscriptenModule;
456
+ const fn = Module[fnName] as any;
457
+
458
+ if (!fn || typeof fn !== 'function') {
459
+ throw new Error(`Function ${fnName} not available in WASM module`);
460
+ }
461
+
462
+ fn(toWasmPtr(aOff), toWasmPtr(bOff), n, toWasmPtr(resultPtr));
463
+
464
+ return readResult(resultPtr, resolvedA.typeInfo.resultType);
465
+ } finally {
466
+ if (!isOnHeapA) Module._free(aOff);
467
+ if (!isOnHeapB) Module._free(bOff);
468
+ }
469
+ }
470
+
471
+ /**
472
+ * Computes the Jensen-Shannon distance between two probability distributions.
473
+ * @param a - First probability distribution (Float32Array, Float64Array, or TensorBase).
474
+ * @param b - Second probability distribution (must match type and length of a).
475
+ * @returns The Jensen-Shannon distance between a and b.
476
+ */
477
+ export function jensenshannon(a: TensorBase | Float64Array | Float32Array, b: TensorBase | Float64Array | Float32Array): number {
478
+ if (!Module) {
479
+ throw new Error('WASM module not initialized');
480
+ }
481
+
482
+ const resolvedA = resolveInput(a);
483
+ const resolvedB = resolveInput(b);
484
+
485
+ if (resolvedA.length !== resolvedB.length) {
486
+ throw new Error(`Array length mismatch: ${resolvedA.length} !== ${resolvedB.length}`);
487
+ }
488
+
489
+ const n = resolvedA.length;
490
+ const isOnHeapA = resolvedA.buffer === Module.wasmMemory.buffer;
491
+ const isOnHeapB = resolvedB.buffer === Module.wasmMemory.buffer;
492
+ const aOff = isOnHeapA ? resolvedA.byteOffset : allocAndCopyResolved(resolvedA.buffer, resolvedA.byteOffset, resolvedA.byteLength);
493
+ const bOff = isOnHeapB ? resolvedB.byteOffset : allocAndCopyResolved(resolvedB.buffer, resolvedB.byteOffset, resolvedB.byteLength);
494
+
495
+ try {
496
+ const fnName = `_nk_jsd_${dtypeToString(resolvedA.typeInfo.dtype)}` as keyof EmscriptenModule;
497
+ const fn = Module[fnName] as any;
498
+
499
+ if (!fn || typeof fn !== 'function') {
500
+ throw new Error(`Function ${fnName} not available in WASM module`);
501
+ }
502
+
503
+ fn(toWasmPtr(aOff), toWasmPtr(bOff), n, toWasmPtr(resultPtr));
504
+
505
+ return readResult(resultPtr, resolvedA.typeInfo.resultType);
506
+ } finally {
507
+ if (!isOnHeapA) Module._free(aOff);
508
+ if (!isOnHeapB) Module._free(bOff);
509
+ }
510
+ }
511
+
512
+ /**
513
+ * Returns the runtime-detected SIMD capabilities as a bitmask.
514
+ * @returns Bitmask of capability flags (use with Capability constants).
515
+ */
516
+ export function getCapabilities(): bigint {
517
+ if (!Module) {
518
+ throw new Error('WASM module not initialized');
519
+ }
520
+
521
+ // nk_capabilities returns a 64-bit value
522
+ const caps = Module._nk_capabilities();
523
+
524
+ // In wasm64, caps is already bigint; in wasm32, it's a number
525
+ return typeof caps === 'bigint' ? caps : BigInt(caps);
526
+ }
527
+
528
+ /**
529
+ * Checks if a specific SIMD capability is available at runtime.
530
+ * @param cap - Capability flag to check (from Capability constants).
531
+ * @returns True if the capability is available.
532
+ */
533
+ export function hasCapability(cap: bigint): boolean {
534
+ return (getCapabilities() & cap) !== 0n;
535
+ }
536
+
537
+ // FinalizationRegistry for WASM PackedMatrix cleanup (ES2021+, available in Node 14+)
538
+ declare class FinalizationRegistry<T> { constructor(callback: (value: T) => void); register(target: object, value: T): void; }
539
+ let packedRegistry: FinalizationRegistry<number> | null = null;
540
+
541
+ /**
542
+ * WASM-backed PackedMatrix that owns a WASM heap allocation.
543
+ */
544
+ class WasmPackedMatrix extends PackedMatrix {
545
+ private _heapPointer: number;
546
+ private _wasmDisposed: boolean = false;
547
+
548
+ constructor(heapPointer: number, byteLength: number, width: number, depth: number, dtype: DType) {
549
+ // Create a JS ArrayBuffer that is a copy of the WASM heap region for read access
550
+ const buffer = new ArrayBuffer(byteLength);
551
+ new Uint8Array(buffer).set(HEAPU8.subarray(heapPointer, heapPointer + byteLength));
552
+ super(buffer, width, depth, dtype, byteLength);
553
+ this._heapPointer = heapPointer;
554
+
555
+ // Register with FinalizationRegistry as safety net
556
+ if (!packedRegistry && typeof FinalizationRegistry !== 'undefined') {
557
+ packedRegistry = new FinalizationRegistry((ptr: number) => {
558
+ if (Module) Module._free(ptr);
559
+ });
560
+ }
561
+ if (packedRegistry) {
562
+ packedRegistry.register(this, heapPointer);
563
+ }
564
+ }
565
+
566
+ get heapPointer(): number { return this._heapPointer; }
567
+
568
+ dispose(): void {
569
+ if (!this._wasmDisposed && Module) {
570
+ Module._free(this._heapPointer);
571
+ this._wasmDisposed = true;
572
+ }
573
+ // Call parent dispose to set disposed flag
574
+ super.dispose();
575
+ }
576
+ }
577
+
578
+ /**
579
+ * Allocate WASM heap, copy matrix data, return pointer. Caller must free.
580
+ */
581
+ function allocAndCopyMatrix(matrix: Matrix): number {
582
+ const byteLength = matrix.rows * matrix.rowStride;
583
+ return allocAndCopyResolved(matrix.buffer, matrix.byteOffset, byteLength);
584
+ }
585
+
586
+ /**
587
+ * Query the packed buffer byte count for a given matrix shape and dtype.
588
+ */
589
+ export function dotsPackedSize(width: number, depth: number, dtype: DType): number {
590
+ if (!Module) throw new Error('WASM module not initialized');
591
+
592
+ const fnName = `_nk_dots_packed_size_${dtypeToString(dtype)}`;
593
+ const fn = Module[fnName] as any;
594
+ if (!fn || typeof fn !== 'function') {
595
+ throw new Error(`Function ${fnName} not available in WASM module`);
596
+ }
597
+ return fn(width, depth);
598
+ }
599
+
600
+ /**
601
+ * Pack a Matrix for use with packed GEMM-like operations.
602
+ */
603
+ export function dotsPack(matrix: Matrix): PackedMatrix {
604
+ if (!Module) throw new Error('WASM module not initialized');
605
+
606
+ const dtypeStr = dtypeToString(matrix.dtype);
607
+ const sizeFnName = `_nk_dots_packed_size_${dtypeStr}`;
608
+ const packFnName = `_nk_dots_pack_${dtypeStr}`;
609
+
610
+ const sizeFn = Module[sizeFnName] as any;
611
+ const packFn = Module[packFnName] as any;
612
+ if (!sizeFn || !packFn) {
613
+ throw new Error(`Pack functions not available for dtype ${dtypeStr}`);
614
+ }
615
+
616
+ const packedByteCount = sizeFn(matrix.rows, matrix.cols) as number;
617
+ const packedPtr = Module._malloc(packedByteCount);
618
+ const matrixPtr = allocAndCopyMatrix(matrix);
619
+
620
+ try {
621
+ packFn(
622
+ toWasmPtr(matrixPtr),
623
+ matrix.rows, matrix.cols,
624
+ matrix.rowStride,
625
+ toWasmPtr(packedPtr),
626
+ );
627
+ } finally {
628
+ Module._free(matrixPtr);
629
+ }
630
+
631
+ return new WasmPackedMatrix(packedPtr, packedByteCount, matrix.rows, matrix.cols, matrix.dtype);
632
+ }
633
+
634
+ function wasmPackedOperation(metricPrefix: string, family: KernelFamily, a: Matrix, packed: PackedMatrix, out?: Matrix): Matrix {
635
+ if (!Module) throw new Error('WASM module not initialized');
636
+ if (a.cols !== packed.depth) {
637
+ throw new Error(`Matrix cols (${a.cols}) must match packed depth (${packed.depth})`);
638
+ }
639
+
640
+ const outDtype = outputDtype(family, a.dtype);
641
+ if (!out) {
642
+ out = new Matrix(a.rows, packed.width, outDtype);
643
+ }
644
+
645
+ const dtypeStr = dtypeToString(a.dtype);
646
+ const fnName = `_nk_${metricPrefix}_${dtypeStr}`;
647
+ const fn = Module[fnName] as any;
648
+ if (!fn || typeof fn !== 'function') {
649
+ throw new Error(`Function ${fnName} not available in WASM module`);
650
+ }
651
+
652
+ const outBpe = out.bytesPerElement;
653
+ const resultByteLength = out.rows * out.cols * outBpe;
654
+ const aPtr = allocAndCopyMatrix(a);
655
+ const resultPtr = Module._malloc(resultByteLength);
656
+
657
+ // For WasmPackedMatrix, copy the packed data to heap; otherwise use the buffer directly
658
+ let packedPtr: number;
659
+ let packedAllocated = false;
660
+ if (packed instanceof WasmPackedMatrix) {
661
+ // The heap pointer may have been freed if disposed; re-copy from JS buffer
662
+ packedPtr = allocAndCopyResolved(packed.buffer, 0, packed.byteLength);
663
+ packedAllocated = true;
664
+ } else {
665
+ packedPtr = allocAndCopyResolved(packed.buffer, 0, packed.byteLength);
666
+ packedAllocated = true;
667
+ }
668
+
669
+ try {
670
+ fn(
671
+ toWasmPtr(aPtr), toWasmPtr(packedPtr), toWasmPtr(resultPtr),
672
+ a.rows, packed.width, a.cols,
673
+ a.rowStride, out.rowStride,
674
+ );
675
+
676
+ // Copy result back
677
+ const outArray = new Uint8Array(out.buffer, out.byteOffset, resultByteLength);
678
+ outArray.set(HEAPU8.subarray(resultPtr, resultPtr + resultByteLength));
679
+ } finally {
680
+ Module._free(aPtr);
681
+ Module._free(resultPtr);
682
+ if (packedAllocated) Module._free(packedPtr);
683
+ }
684
+
685
+ return out;
686
+ }
687
+
688
+ function wasmSymmetricOperation(metricPrefix: string, family: KernelFamily, vectors: Matrix, out?: Matrix, rowStart = 0, rowCount?: number): Matrix {
689
+ if (!Module) throw new Error('WASM module not initialized');
690
+
691
+ const count = rowCount ?? vectors.rows - rowStart;
692
+ const outDtype = outputDtype(family, vectors.dtype);
693
+ if (!out) {
694
+ out = new Matrix(vectors.rows, vectors.rows, outDtype);
695
+ }
696
+
697
+ const dtypeStr = dtypeToString(vectors.dtype);
698
+ const fnName = `_nk_${metricPrefix}_${dtypeStr}`;
699
+ const fn = Module[fnName] as any;
700
+ if (!fn || typeof fn !== 'function') {
701
+ throw new Error(`Function ${fnName} not available in WASM module`);
702
+ }
703
+
704
+ const resultByteLength = out.rows * out.cols * out.bytesPerElement;
705
+ const vectorsPtr = allocAndCopyMatrix(vectors);
706
+ const resultPtr = Module._malloc(resultByteLength);
707
+
708
+ try {
709
+ fn(
710
+ toWasmPtr(vectorsPtr),
711
+ vectors.rows, vectors.cols,
712
+ vectors.rowStride,
713
+ toWasmPtr(resultPtr), out.rowStride,
714
+ rowStart, count,
715
+ );
716
+
717
+ // Copy result back
718
+ const outArray = new Uint8Array(out.buffer, out.byteOffset, resultByteLength);
719
+ outArray.set(HEAPU8.subarray(resultPtr, resultPtr + resultByteLength));
720
+ } finally {
721
+ Module._free(vectorsPtr);
722
+ Module._free(resultPtr);
723
+ }
724
+
725
+ return out;
726
+ }
727
+
728
+ export function dotsPacked(a: Matrix, packed: PackedMatrix, out?: Matrix): Matrix {
729
+ return wasmPackedOperation('dots_packed', 'dots', a, packed, out);
730
+ }
731
+
732
+ export function angularsPacked(a: Matrix, packed: PackedMatrix, out?: Matrix): Matrix {
733
+ return wasmPackedOperation('angulars_packed', 'angulars', a, packed, out);
734
+ }
735
+
736
+ export function euclideansPacked(a: Matrix, packed: PackedMatrix, out?: Matrix): Matrix {
737
+ return wasmPackedOperation('euclideans_packed', 'euclideans', a, packed, out);
738
+ }
739
+
740
+ export function dotsSymmetric(vectors: Matrix, out?: Matrix, options?: { rowStart?: number; rowCount?: number }): Matrix {
741
+ return wasmSymmetricOperation('dots_symmetric', 'dots', vectors, out, options?.rowStart ?? 0, options?.rowCount);
742
+ }
743
+
744
+ export function angularsSymmetric(vectors: Matrix, out?: Matrix, options?: { rowStart?: number; rowCount?: number }): Matrix {
745
+ return wasmSymmetricOperation('angulars_symmetric', 'angulars', vectors, out, options?.rowStart ?? 0, options?.rowCount);
746
+ }
747
+
748
+ export function euclideansSymmetric(vectors: Matrix, out?: Matrix, options?: { rowStart?: number; rowCount?: number }): Matrix {
749
+ return wasmSymmetricOperation('euclideans_symmetric', 'euclideans', vectors, out, options?.rowStart ?? 0, options?.rowCount);
750
+ }