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,537 @@
1
+ /**
2
+ * @brief SIMD-accelerated Type Conversions for WASM.
3
+ * @file include/numkong/cast/v128relaxed.h
4
+ */
5
+
6
+ #ifndef NK_CAST_V128RELAXED_H
7
+ #define NK_CAST_V128RELAXED_H
8
+
9
+ #if NK_TARGET_V128RELAXED
10
+
11
+ #include "numkong/types.h"
12
+ #include "numkong/cast/serial.h"
13
+
14
+ #if defined(__cplusplus)
15
+ extern "C" {
16
+ #endif
17
+
18
+ #if defined(__clang__)
19
+ #pragma clang attribute push(__attribute__((target("relaxed-simd"))), apply_to = function)
20
+ #endif
21
+
22
+ /** @brief Native WASM SIMD 128-bit load. */
23
+ NK_INTERNAL void nk_load_b128_v128relaxed_(void const *src, nk_b128_vec_t *dst) { dst->v128 = wasm_v128_load(src); }
24
+ /** @brief Native WASM SIMD 256-bit load using two v128 loads. */
25
+ NK_INTERNAL void nk_load_b256_v128relaxed_(void const *src, nk_b256_vec_t *dst) {
26
+ dst->v128s[0] = wasm_v128_load(src);
27
+ dst->v128s[1] = wasm_v128_load((char const *)src + 16);
28
+ }
29
+ /** @brief Native WASM SIMD 128-bit store. */
30
+ NK_INTERNAL void nk_store_b128_v128relaxed_(nk_b128_vec_t const *src, void *dst) { wasm_v128_store(dst, src->v128); }
31
+ /** @brief Native WASM SIMD 256-bit store using two v128 stores. */
32
+ NK_INTERNAL void nk_store_b256_v128relaxed_(nk_b256_vec_t const *src, void *dst) {
33
+ wasm_v128_store(dst, src->v128s[0]);
34
+ wasm_v128_store((char *)dst + 16, src->v128s[1]);
35
+ }
36
+
37
+ /** @brief BF16 is the upper 16 bits of F32, so zero-extend to u32 and shift left by 16. */
38
+ NK_INTERNAL nk_b128_vec_t nk_bf16x4_to_f32x4_v128relaxed_(nk_b64_vec_t bf16_vec) {
39
+ v128_t bf16_u16x4_in_u64 = wasm_i64x2_splat(bf16_vec.u64);
40
+ v128_t bf16_u32x4_low = wasm_u32x4_extend_low_u16x8(bf16_u16x4_in_u64);
41
+ nk_b128_vec_t result;
42
+ result.v128 = wasm_i32x4_shl(bf16_u32x4_low, 16);
43
+ return result;
44
+ }
45
+
46
+ /**
47
+ * @brief F16→F32 via Giesen's magic-number multiply trick.
48
+ * @see https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
49
+ *
50
+ * Shifts the 15-bit magnitude into F32 exponent+mantissa position, then multiplies
51
+ * by 2^112 (magic = 0x77800000) to rebias the exponent. This single multiply also
52
+ * correctly normalizes F16 subnormals into F32 normals — no branching or FPU
53
+ * integer-to-float conversion needed. Inf/NaN (exp=31) overflows the multiply and
54
+ * is fixed with a comparison + blend.
55
+ */
56
+ NK_INTERNAL nk_b128_vec_t nk_f16x4_to_f32x4_v128relaxed_(nk_b64_vec_t f16_vec) {
57
+ v128_t raw_u16x4_in_u64 = wasm_i64x2_splat(f16_vec.u64);
58
+ v128_t raw_u32x4 = wasm_u32x4_extend_low_u16x8(raw_u16x4_in_u64);
59
+
60
+ // Extract sign and unsigned magnitude
61
+ v128_t sign_u32x4 = wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x8000));
62
+ v128_t sign_f32_u32x4 = wasm_i32x4_shl(sign_u32x4, 16);
63
+ v128_t magnitude_u32x4 = wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x7FFF));
64
+
65
+ // Shift mantissa+exponent into F32 position and multiply by magic 2^112
66
+ v128_t shifted_u32x4 = wasm_i32x4_shl(magnitude_u32x4, 13);
67
+ v128_t magic_f32x4 = wasm_i32x4_splat(0x77800000);
68
+ v128_t rebiased_f32x4 = wasm_f32x4_mul((v128_t)shifted_u32x4, (v128_t)magic_f32x4);
69
+
70
+ // Fix inf/NaN: exp=31 after shift becomes 0x1F<<13 = 0x000F8000, ×2^112 overflows.
71
+ // Detect via threshold on shifted magnitude and apply direct rebias instead.
72
+ v128_t infnan_threshold_u32x4 = wasm_i32x4_splat(0x38800000);
73
+ v128_t infnan_mask_u32x4 = wasm_u32x4_ge(shifted_u32x4, infnan_threshold_u32x4);
74
+ v128_t direct_u32x4 = wasm_v128_or(shifted_u32x4, wasm_i32x4_splat(0x70000000));
75
+ v128_t result_u32x4 = wasm_i32x4_relaxed_laneselect(direct_u32x4, rebiased_f32x4, infnan_mask_u32x4);
76
+
77
+ // Apply sign
78
+ result_u32x4 = wasm_v128_or(result_u32x4, sign_f32_u32x4);
79
+
80
+ nk_b128_vec_t result;
81
+ result.v128 = result_u32x4;
82
+ return result;
83
+ }
84
+
85
+ /**
86
+ * @brief E4M3→F32 via Giesen's magic multiply (×2^120).
87
+ * Shift 7-bit magnitude left by 20 into f32 position, multiply by 2^120 to rebias exponent.
88
+ * The multiply also normalizes subnormals. NaN fixup for magnitude 0x7F only.
89
+ */
90
+ NK_INTERNAL nk_b128_vec_t nk_e4m3x4_to_f32x4_v128relaxed_(nk_b32_vec_t e4m3_vec) {
91
+ v128_t raw_u32x4 = wasm_u32x4_extend_low_u16x8(wasm_u16x8_extend_low_u8x16(wasm_i32x4_splat(e4m3_vec.u32)));
92
+ v128_t sign_u32x4 = wasm_i32x4_shl(wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x80)), 24);
93
+ v128_t nonsign_u32x4 = wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x7F));
94
+ v128_t shifted_u32x4 = wasm_i32x4_shl(nonsign_u32x4, 20);
95
+ v128_t rebiased_f32x4 = wasm_f32x4_mul((v128_t)shifted_u32x4, (v128_t)wasm_i32x4_splat(0x7B800000)); // 2^120
96
+ v128_t is_nan_u32x4 = wasm_i32x4_eq(nonsign_u32x4, wasm_i32x4_splat(0x7F));
97
+ v128_t nan_u32x4 = wasm_v128_or(sign_u32x4, wasm_i32x4_splat(0x7FC00000));
98
+ v128_t result_u32x4 = wasm_i32x4_relaxed_laneselect(nan_u32x4, rebiased_f32x4, is_nan_u32x4);
99
+ nk_b128_vec_t result_vec;
100
+ result_vec.v128 = wasm_v128_or(result_u32x4, sign_u32x4);
101
+ return result_vec;
102
+ }
103
+
104
+ /**
105
+ * @brief E5M2→F32 via Giesen's magic multiply (×2^112).
106
+ * Same exponent encoding as F16 (5-bit, bias=15). Shift 7-bit magnitude left by 21,
107
+ * multiply by 2^112 to rebias. Inf/NaN fixup for exp=31 (nonsign > 123).
108
+ */
109
+ NK_INTERNAL nk_b128_vec_t nk_e5m2x4_to_f32x4_v128relaxed_(nk_b32_vec_t e5m2_vec) {
110
+ v128_t raw_u32x4 = wasm_u32x4_extend_low_u16x8(wasm_u16x8_extend_low_u8x16(wasm_i32x4_splat(e5m2_vec.u32)));
111
+ v128_t sign_u32x4 = wasm_i32x4_shl(wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x80)), 24);
112
+ v128_t nonsign_u32x4 = wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x7F));
113
+ v128_t shifted_u32x4 = wasm_i32x4_shl(nonsign_u32x4, 21);
114
+ v128_t rebiased_f32x4 = wasm_f32x4_mul((v128_t)shifted_u32x4, (v128_t)wasm_i32x4_splat(0x77800000)); // 2^112
115
+ v128_t is_infnan_u32x4 = wasm_u32x4_gt(nonsign_u32x4, wasm_i32x4_splat(123));
116
+ v128_t result_u32x4 = wasm_v128_or(rebiased_f32x4, wasm_v128_and(is_infnan_u32x4, wasm_i32x4_splat(0x7F800000)));
117
+ nk_b128_vec_t result_vec;
118
+ result_vec.v128 = wasm_v128_or(result_u32x4, sign_u32x4);
119
+ return result_vec;
120
+ }
121
+
122
+ /**
123
+ * @brief E2M3→F32 via Giesen's magic multiply (×2^126).
124
+ * S EE MMM (bias=1). Shift 5-bit magnitude left by 20, multiply by 2^126 to rebias.
125
+ * No inf/NaN in E2M3FN format, so no fixup needed.
126
+ */
127
+ NK_INTERNAL nk_b128_vec_t nk_e2m3x4_to_f32x4_v128relaxed_(nk_b32_vec_t e2m3_vec) {
128
+ v128_t raw_u32x4 = wasm_u32x4_extend_low_u16x8(wasm_u16x8_extend_low_u8x16(wasm_i32x4_splat(e2m3_vec.u32)));
129
+ v128_t sign_u32x4 = wasm_i32x4_shl(wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x20)), 26);
130
+ v128_t nonsign_u32x4 = wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x1F));
131
+ v128_t shifted_u32x4 = wasm_i32x4_shl(nonsign_u32x4, 20);
132
+ v128_t rebiased_f32x4 = wasm_f32x4_mul((v128_t)shifted_u32x4, (v128_t)wasm_i32x4_splat(0x7E800000)); // 2^126
133
+ nk_b128_vec_t result_vec;
134
+ result_vec.v128 = wasm_v128_or(rebiased_f32x4, sign_u32x4);
135
+ return result_vec;
136
+ }
137
+
138
+ /**
139
+ * @brief E3M2→F32 via Giesen's magic multiply (×2^124).
140
+ * S EEE MM (bias=3). Shift 5-bit magnitude left by 21, multiply by 2^124 to rebias.
141
+ * No inf/NaN in E3M2FN format, so no fixup needed.
142
+ */
143
+ NK_INTERNAL nk_b128_vec_t nk_e3m2x4_to_f32x4_v128relaxed_(nk_b32_vec_t e3m2_vec) {
144
+ v128_t raw_u32x4 = wasm_u32x4_extend_low_u16x8(wasm_u16x8_extend_low_u8x16(wasm_i32x4_splat(e3m2_vec.u32)));
145
+ v128_t sign_u32x4 = wasm_i32x4_shl(wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x20)), 26);
146
+ v128_t nonsign_u32x4 = wasm_v128_and(raw_u32x4, wasm_i32x4_splat(0x1F));
147
+ v128_t shifted_u32x4 = wasm_i32x4_shl(nonsign_u32x4, 21);
148
+ v128_t rebiased_f32x4 = wasm_f32x4_mul((v128_t)shifted_u32x4, (v128_t)wasm_i32x4_splat(0x7D800000)); // 2^124
149
+ nk_b128_vec_t result_vec;
150
+ result_vec.v128 = wasm_v128_or(rebiased_f32x4, sign_u32x4);
151
+ return result_vec;
152
+ }
153
+
154
+ /** @brief Convert 4x i8 → f32x4 (WASM). Widen i8→i16→i32, convert to f32. */
155
+ NK_INTERNAL nk_b128_vec_t nk_i8x4_to_f32x4_v128relaxed_(nk_b32_vec_t in_vec) {
156
+ v128_t in_i8x16 = wasm_i32x4_splat(in_vec.u32);
157
+ v128_t in_i16x8 = wasm_i16x8_extend_low_i8x16(in_i8x16);
158
+ v128_t in_i32x4 = wasm_i32x4_extend_low_i16x8(in_i16x8);
159
+ nk_b128_vec_t result_vec;
160
+ result_vec.v128 = wasm_f32x4_convert_i32x4(in_i32x4);
161
+ return result_vec;
162
+ }
163
+
164
+ /** @brief Convert 4x u8 → f32x4 (WASM). Widen u8→u16→u32, convert to f32. */
165
+ NK_INTERNAL nk_b128_vec_t nk_u8x4_to_f32x4_v128relaxed_(nk_b32_vec_t in_vec) {
166
+ v128_t in_u8x16 = wasm_i32x4_splat(in_vec.u32);
167
+ v128_t in_u16x8 = wasm_u16x8_extend_low_u8x16(in_u8x16);
168
+ v128_t in_u32x4 = wasm_u32x4_extend_low_u16x8(in_u16x8);
169
+ nk_b128_vec_t result_vec;
170
+ result_vec.v128 = wasm_f32x4_convert_u32x4(in_u32x4);
171
+ return result_vec;
172
+ }
173
+
174
+ /** @brief Convert f32x4 → 4x bf16 via RNE rounding (WASM). */
175
+ NK_INTERNAL nk_b64_vec_t nk_f32x4_to_bf16x4_v128relaxed_(nk_b128_vec_t hub_vec) {
176
+ v128_t bits_u32x4 = hub_vec.v128;
177
+ v128_t lsb_u32x4 = wasm_v128_and(wasm_u32x4_shr(bits_u32x4, 16), wasm_i32x4_splat(1));
178
+ v128_t rounded_u32x4 = wasm_i32x4_add(bits_u32x4, wasm_i32x4_add(wasm_i32x4_splat(0x7FFF), lsb_u32x4));
179
+ v128_t bf16_u32x4 = wasm_u32x4_shr(rounded_u32x4, 16);
180
+ v128_t packed_u16x8 = wasm_u16x8_narrow_i32x4(bf16_u32x4, bf16_u32x4);
181
+ nk_b64_vec_t result_vec;
182
+ result_vec.u64 = (nk_u64_t)wasm_i64x2_extract_lane(packed_u16x8, 0);
183
+ return result_vec;
184
+ }
185
+
186
+ /**
187
+ * @brief F32→F16 via bit manipulation with RNE (WASM).
188
+ * Handles normal, subnormal, overflow (→inf), and inf/NaN cases.
189
+ */
190
+ NK_INTERNAL nk_b64_vec_t nk_f32x4_to_f16x4_v128relaxed_(nk_b128_vec_t hub_vec) {
191
+ v128_t bits_u32x4 = hub_vec.v128;
192
+ v128_t sign_u32x4 = wasm_i32x4_shl(wasm_u32x4_shr(bits_u32x4, 31), 15);
193
+ v128_t f32_exp_u32x4 = wasm_v128_and(wasm_u32x4_shr(bits_u32x4, 23), wasm_i32x4_splat(0xFF));
194
+ v128_t f32_mant_u32x4 = wasm_v128_and(bits_u32x4, wasm_i32x4_splat(0x007FFFFF));
195
+
196
+ // Normal path: rebias exponent (127→15), RNE round mantissa 23→10 bits
197
+ v128_t f16_exp_i32x4 = wasm_i32x4_sub(f32_exp_u32x4, wasm_i32x4_splat(112));
198
+ v128_t significand_u32x4 = wasm_v128_or(f32_mant_u32x4, wasm_i32x4_splat(0x00800000));
199
+ v128_t lsb_u32x4 = wasm_v128_and(wasm_u32x4_shr(significand_u32x4, 13), wasm_i32x4_splat(1));
200
+ v128_t rounded_u32x4 = wasm_i32x4_add(significand_u32x4, wasm_i32x4_add(wasm_i32x4_splat(0x0FFF), lsb_u32x4));
201
+ v128_t carry_u32x4 = wasm_u32x4_shr(rounded_u32x4, 24);
202
+ v128_t f16_mant_u32x4 = wasm_v128_and(wasm_u32x4_shr(rounded_u32x4, 13), wasm_i32x4_splat(0x3FF));
203
+ v128_t carry_mask_u32x4 = wasm_i32x4_eq(carry_u32x4, wasm_i32x4_splat(1));
204
+ f16_mant_u32x4 = wasm_v128_andnot(f16_mant_u32x4, carry_mask_u32x4);
205
+ f16_exp_i32x4 = wasm_i32x4_add(f16_exp_i32x4, carry_u32x4);
206
+
207
+ // Clamp exponent and assemble normal result
208
+ v128_t clamped_exp_i32x4 = wasm_i32x4_max(f16_exp_i32x4, wasm_i32x4_splat(1));
209
+ clamped_exp_i32x4 = wasm_i32x4_min(clamped_exp_i32x4, wasm_i32x4_splat(30));
210
+ v128_t normal_result_u32x4 = wasm_v128_or(sign_u32x4,
211
+ wasm_v128_or(wasm_i32x4_shl(clamped_exp_i32x4, 10), f16_mant_u32x4));
212
+
213
+ // Overflow → infinity
214
+ v128_t overflow_mask_u32x4 = wasm_i32x4_gt(f16_exp_i32x4, wasm_i32x4_splat(30));
215
+ v128_t inf_result_u32x4 = wasm_v128_or(sign_u32x4, wasm_i32x4_splat(0x7C00));
216
+ normal_result_u32x4 = wasm_i32x4_relaxed_laneselect(inf_result_u32x4, normal_result_u32x4, overflow_mask_u32x4);
217
+
218
+ // Underflow → zero (exp <= 0 after rebias, ignoring subnormals for simplicity)
219
+ v128_t underflow_mask_u32x4 = wasm_i32x4_lt(f16_exp_i32x4, wasm_i32x4_splat(1));
220
+ normal_result_u32x4 = wasm_i32x4_relaxed_laneselect(sign_u32x4, normal_result_u32x4, underflow_mask_u32x4);
221
+
222
+ // Inf/NaN passthrough: f32 exp=255
223
+ v128_t infnan_mask_u32x4 = wasm_i32x4_eq(f32_exp_u32x4, wasm_i32x4_splat(255));
224
+ v128_t nan_payload_u32x4 = wasm_v128_or(wasm_u32x4_shr(f32_mant_u32x4, 13), wasm_i32x4_splat(1));
225
+ v128_t mant_nonzero_u32x4 = wasm_i32x4_ne(f32_mant_u32x4, wasm_i32x4_splat(0));
226
+ v128_t nan_result_u32x4 = wasm_v128_or(
227
+ sign_u32x4, wasm_v128_or(wasm_i32x4_splat(0x7C00), wasm_v128_and(nan_payload_u32x4, mant_nonzero_u32x4)));
228
+ normal_result_u32x4 = wasm_i32x4_relaxed_laneselect(nan_result_u32x4, normal_result_u32x4, infnan_mask_u32x4);
229
+
230
+ // F32 zero/denorm → f16 zero
231
+ v128_t f32_zero_mask_u32x4 = wasm_i32x4_eq(f32_exp_u32x4, wasm_i32x4_splat(0));
232
+ normal_result_u32x4 = wasm_i32x4_relaxed_laneselect(sign_u32x4, normal_result_u32x4, f32_zero_mask_u32x4);
233
+
234
+ // Pack 4x u32 → 4x u16
235
+ v128_t packed_u16x8 = wasm_u16x8_narrow_i32x4(normal_result_u32x4, normal_result_u32x4);
236
+ nk_b64_vec_t result_vec;
237
+ result_vec.u64 = (nk_u64_t)wasm_i64x2_extract_lane(packed_u16x8, 0);
238
+ return result_vec;
239
+ }
240
+
241
+ /** @brief Convert f32x4 → 4x e4m3 via bit manipulation with RNE (WASM). */
242
+ NK_INTERNAL nk_b32_vec_t nk_f32x4_to_e4m3x4_v128relaxed_(nk_b128_vec_t hub_vec) {
243
+ v128_t bits_u32x4 = hub_vec.v128;
244
+ v128_t sign_u32x4 = wasm_u32x4_shr(bits_u32x4, 31);
245
+ v128_t f32_exp_u32x4 = wasm_v128_and(wasm_u32x4_shr(bits_u32x4, 23), wasm_i32x4_splat(0xFF));
246
+
247
+ // RNE mantissa rounding from 23 to 3 bits
248
+ v128_t significand_u32x4 = wasm_v128_or(wasm_v128_and(bits_u32x4, wasm_i32x4_splat(0x007FFFFF)),
249
+ wasm_i32x4_splat(0x00800000));
250
+ v128_t lsb_u32x4 = wasm_v128_and(wasm_u32x4_shr(significand_u32x4, 20), wasm_i32x4_splat(1));
251
+ v128_t rounded_u32x4 = wasm_i32x4_add(significand_u32x4, wasm_i32x4_add(wasm_i32x4_splat(0x0007FFFF), lsb_u32x4));
252
+ v128_t carry_u32x4 = wasm_u32x4_shr(rounded_u32x4, 24);
253
+ v128_t f32_mant_u32x4 = wasm_v128_and(wasm_u32x4_shr(rounded_u32x4, 20), wasm_i32x4_splat(0x07));
254
+ v128_t carry_mask_u32x4 = wasm_i32x4_eq(carry_u32x4, wasm_i32x4_splat(1));
255
+ f32_mant_u32x4 = wasm_v128_andnot(f32_mant_u32x4, carry_mask_u32x4);
256
+ v128_t e4m3_exp_i32x4 = wasm_i32x4_sub(wasm_i32x4_add(f32_exp_u32x4, carry_u32x4), wasm_i32x4_splat(120));
257
+
258
+ v128_t is_subnormal_u32x4 = wasm_i32x4_lt(e4m3_exp_i32x4, wasm_i32x4_splat(1));
259
+ v128_t overflow_u32x4 = wasm_i32x4_gt(e4m3_exp_i32x4, wasm_i32x4_splat(15));
260
+
261
+ // Normal path
262
+ v128_t clamped_exp_i32x4 = wasm_i32x4_max(e4m3_exp_i32x4, wasm_i32x4_splat(1));
263
+ clamped_exp_i32x4 = wasm_i32x4_min(clamped_exp_i32x4, wasm_i32x4_splat(15));
264
+ v128_t is_max_exp_u32x4 = wasm_i32x4_eq(clamped_exp_i32x4, wasm_i32x4_splat(15));
265
+ v128_t max_mant_u32x4 = wasm_i32x4_relaxed_laneselect(wasm_i32x4_splat(6), wasm_i32x4_splat(7), is_max_exp_u32x4);
266
+ v128_t normal_mant_u32x4 = wasm_i32x4_min(f32_mant_u32x4, max_mant_u32x4);
267
+ normal_mant_u32x4 = wasm_i32x4_relaxed_laneselect(wasm_i32x4_splat(0x06), normal_mant_u32x4, overflow_u32x4);
268
+ v128_t normal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 7),
269
+ wasm_v128_or(wasm_i32x4_shl(clamped_exp_i32x4, 3), normal_mant_u32x4));
270
+
271
+ // Subnormal path
272
+ v128_t abs_f32x4 = wasm_v128_and(hub_vec.v128, wasm_i32x4_splat(0x7FFFFFFF));
273
+ v128_t scaled_f32x4 = wasm_f32x4_mul((v128_t)abs_f32x4, wasm_f32x4_splat(512.0f));
274
+ v128_t sub_mant_i32x4 = wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_nearest(scaled_f32x4));
275
+ v128_t promotes_u32x4 = wasm_i32x4_gt(sub_mant_i32x4, wasm_i32x4_splat(7));
276
+ sub_mant_i32x4 = wasm_i32x4_min(sub_mant_i32x4, wasm_i32x4_splat(7));
277
+ sub_mant_i32x4 = wasm_i32x4_max(sub_mant_i32x4, wasm_i32x4_splat(0));
278
+ v128_t subnormal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 7), sub_mant_i32x4);
279
+ v128_t first_normal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 7), wasm_i32x4_splat(0x08));
280
+ subnormal_u32x4 = wasm_i32x4_relaxed_laneselect(first_normal_u32x4, subnormal_u32x4, promotes_u32x4);
281
+
282
+ v128_t e4m3_u32x4 = wasm_i32x4_relaxed_laneselect(subnormal_u32x4, normal_u32x4, is_subnormal_u32x4);
283
+
284
+ // Pack 4x u32 → 4x u8
285
+ v128_t packed_u16 = wasm_u16x8_narrow_i32x4(e4m3_u32x4, e4m3_u32x4);
286
+ v128_t packed_u8 = wasm_u8x16_narrow_i16x8(packed_u16, packed_u16);
287
+ nk_b32_vec_t result_vec;
288
+ result_vec.u32 = (nk_u32_t)wasm_i32x4_extract_lane(packed_u8, 0);
289
+ return result_vec;
290
+ }
291
+
292
+ /** @brief Convert f32x4 → 4x e5m2 via bit manipulation with RNE (WASM). */
293
+ NK_INTERNAL nk_b32_vec_t nk_f32x4_to_e5m2x4_v128relaxed_(nk_b128_vec_t hub_vec) {
294
+ v128_t bits_u32x4 = hub_vec.v128;
295
+ v128_t sign_u32x4 = wasm_u32x4_shr(bits_u32x4, 31);
296
+ v128_t f32_exp_u32x4 = wasm_v128_and(wasm_u32x4_shr(bits_u32x4, 23), wasm_i32x4_splat(0xFF));
297
+
298
+ // RNE mantissa rounding from 23 to 2 bits
299
+ v128_t significand_u32x4 = wasm_v128_or(wasm_v128_and(bits_u32x4, wasm_i32x4_splat(0x007FFFFF)),
300
+ wasm_i32x4_splat(0x00800000));
301
+ v128_t lsb_u32x4 = wasm_v128_and(wasm_u32x4_shr(significand_u32x4, 21), wasm_i32x4_splat(1));
302
+ v128_t rounded_u32x4 = wasm_i32x4_add(significand_u32x4, wasm_i32x4_add(wasm_i32x4_splat(0x000FFFFF), lsb_u32x4));
303
+ v128_t carry_u32x4 = wasm_u32x4_shr(rounded_u32x4, 24);
304
+ v128_t f32_mant_u32x4 = wasm_v128_and(wasm_u32x4_shr(rounded_u32x4, 21), wasm_i32x4_splat(0x03));
305
+ v128_t carry_mask_u32x4 = wasm_i32x4_eq(carry_u32x4, wasm_i32x4_splat(1));
306
+ f32_mant_u32x4 = wasm_v128_andnot(f32_mant_u32x4, carry_mask_u32x4);
307
+ v128_t e5m2_exp_i32x4 = wasm_i32x4_sub(wasm_i32x4_add(f32_exp_u32x4, carry_u32x4), wasm_i32x4_splat(112));
308
+
309
+ v128_t is_subnormal_u32x4 = wasm_i32x4_lt(e5m2_exp_i32x4, wasm_i32x4_splat(1));
310
+ v128_t overflow_u32x4 = wasm_i32x4_gt(e5m2_exp_i32x4, wasm_i32x4_splat(31));
311
+
312
+ // Normal path: overflow → infinity (exp=31, mant=0)
313
+ v128_t clamped_exp_i32x4 = wasm_i32x4_max(e5m2_exp_i32x4, wasm_i32x4_splat(1));
314
+ clamped_exp_i32x4 = wasm_i32x4_min(clamped_exp_i32x4, wasm_i32x4_splat(31));
315
+ v128_t normal_mant_u32x4 = wasm_i32x4_relaxed_laneselect(wasm_i32x4_splat(0), f32_mant_u32x4, overflow_u32x4);
316
+ v128_t normal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 7),
317
+ wasm_v128_or(wasm_i32x4_shl(clamped_exp_i32x4, 2), normal_mant_u32x4));
318
+
319
+ // Subnormal path
320
+ v128_t abs_f32x4 = wasm_v128_and(hub_vec.v128, wasm_i32x4_splat(0x7FFFFFFF));
321
+ v128_t scaled_f32x4 = wasm_f32x4_mul((v128_t)abs_f32x4, wasm_f32x4_splat(65536.0f));
322
+ v128_t sub_mant_i32x4 = wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_nearest(scaled_f32x4));
323
+ v128_t promotes_u32x4 = wasm_i32x4_gt(sub_mant_i32x4, wasm_i32x4_splat(3));
324
+ sub_mant_i32x4 = wasm_i32x4_min(sub_mant_i32x4, wasm_i32x4_splat(3));
325
+ sub_mant_i32x4 = wasm_i32x4_max(sub_mant_i32x4, wasm_i32x4_splat(0));
326
+ v128_t subnormal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 7), sub_mant_i32x4);
327
+ v128_t first_normal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 7), wasm_i32x4_splat(0x04));
328
+ subnormal_u32x4 = wasm_i32x4_relaxed_laneselect(first_normal_u32x4, subnormal_u32x4, promotes_u32x4);
329
+
330
+ v128_t e5m2_u32x4 = wasm_i32x4_relaxed_laneselect(subnormal_u32x4, normal_u32x4, is_subnormal_u32x4);
331
+
332
+ v128_t packed_u16 = wasm_u16x8_narrow_i32x4(e5m2_u32x4, e5m2_u32x4);
333
+ v128_t packed_u8 = wasm_u8x16_narrow_i16x8(packed_u16, packed_u16);
334
+ nk_b32_vec_t result_vec;
335
+ result_vec.u32 = (nk_u32_t)wasm_i32x4_extract_lane(packed_u8, 0);
336
+ return result_vec;
337
+ }
338
+
339
+ /** @brief Convert f32x4 → 4x e2m3 via bit manipulation with RNE (WASM). */
340
+ NK_INTERNAL nk_b32_vec_t nk_f32x4_to_e2m3x4_v128relaxed_(nk_b128_vec_t hub_vec) {
341
+ v128_t bits_u32x4 = hub_vec.v128;
342
+ v128_t sign_u32x4 = wasm_u32x4_shr(bits_u32x4, 31);
343
+ v128_t f32_exp_u32x4 = wasm_v128_and(wasm_u32x4_shr(bits_u32x4, 23), wasm_i32x4_splat(0xFF));
344
+
345
+ v128_t significand_u32x4 = wasm_v128_or(wasm_v128_and(bits_u32x4, wasm_i32x4_splat(0x007FFFFF)),
346
+ wasm_i32x4_splat(0x00800000));
347
+ v128_t lsb_u32x4 = wasm_v128_and(wasm_u32x4_shr(significand_u32x4, 20), wasm_i32x4_splat(1));
348
+ v128_t rounded_u32x4 = wasm_i32x4_add(significand_u32x4, wasm_i32x4_add(wasm_i32x4_splat(0x0007FFFF), lsb_u32x4));
349
+ v128_t carry_u32x4 = wasm_u32x4_shr(rounded_u32x4, 24);
350
+ v128_t f32_mant_u32x4 = wasm_v128_and(wasm_u32x4_shr(rounded_u32x4, 20), wasm_i32x4_splat(0x07));
351
+ v128_t carry_mask_u32x4 = wasm_i32x4_eq(carry_u32x4, wasm_i32x4_splat(1));
352
+ f32_mant_u32x4 = wasm_v128_andnot(f32_mant_u32x4, carry_mask_u32x4);
353
+ v128_t e2m3_exp_i32x4 = wasm_i32x4_sub(wasm_i32x4_add(f32_exp_u32x4, carry_u32x4), wasm_i32x4_splat(126));
354
+
355
+ v128_t is_subnormal_u32x4 = wasm_i32x4_lt(e2m3_exp_i32x4, wasm_i32x4_splat(1));
356
+ v128_t overflow_u32x4 = wasm_i32x4_gt(e2m3_exp_i32x4, wasm_i32x4_splat(3));
357
+
358
+ v128_t clamped_exp_i32x4 = wasm_i32x4_max(e2m3_exp_i32x4, wasm_i32x4_splat(1));
359
+ clamped_exp_i32x4 = wasm_i32x4_min(clamped_exp_i32x4, wasm_i32x4_splat(3));
360
+ v128_t normal_mant_u32x4 = wasm_i32x4_relaxed_laneselect(wasm_i32x4_splat(0x07), f32_mant_u32x4, overflow_u32x4);
361
+ v128_t normal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 5),
362
+ wasm_v128_or(wasm_i32x4_shl(clamped_exp_i32x4, 3), normal_mant_u32x4));
363
+
364
+ v128_t abs_f32x4 = wasm_v128_and(hub_vec.v128, wasm_i32x4_splat(0x7FFFFFFF));
365
+ v128_t scaled_f32x4 = wasm_f32x4_mul((v128_t)abs_f32x4, wasm_f32x4_splat(8.0f));
366
+ v128_t sub_mant_i32x4 = wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_nearest(scaled_f32x4));
367
+ v128_t promotes_u32x4 = wasm_i32x4_gt(sub_mant_i32x4, wasm_i32x4_splat(7));
368
+ sub_mant_i32x4 = wasm_i32x4_min(sub_mant_i32x4, wasm_i32x4_splat(7));
369
+ sub_mant_i32x4 = wasm_i32x4_max(sub_mant_i32x4, wasm_i32x4_splat(0));
370
+ v128_t subnormal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 5), sub_mant_i32x4);
371
+ v128_t first_normal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 5), wasm_i32x4_splat(0x08));
372
+ subnormal_u32x4 = wasm_i32x4_relaxed_laneselect(first_normal_u32x4, subnormal_u32x4, promotes_u32x4);
373
+
374
+ v128_t e2m3_u32x4 = wasm_i32x4_relaxed_laneselect(subnormal_u32x4, normal_u32x4, is_subnormal_u32x4);
375
+
376
+ v128_t packed_u16 = wasm_u16x8_narrow_i32x4(e2m3_u32x4, e2m3_u32x4);
377
+ v128_t packed_u8 = wasm_u8x16_narrow_i16x8(packed_u16, packed_u16);
378
+ nk_b32_vec_t result_vec;
379
+ result_vec.u32 = (nk_u32_t)wasm_i32x4_extract_lane(packed_u8, 0);
380
+ return result_vec;
381
+ }
382
+
383
+ /** @brief Convert f32x4 → 4x e3m2 via bit manipulation with RNE (WASM). */
384
+ NK_INTERNAL nk_b32_vec_t nk_f32x4_to_e3m2x4_v128relaxed_(nk_b128_vec_t hub_vec) {
385
+ v128_t bits_u32x4 = hub_vec.v128;
386
+ v128_t sign_u32x4 = wasm_u32x4_shr(bits_u32x4, 31);
387
+ v128_t f32_exp_u32x4 = wasm_v128_and(wasm_u32x4_shr(bits_u32x4, 23), wasm_i32x4_splat(0xFF));
388
+
389
+ v128_t significand_u32x4 = wasm_v128_or(wasm_v128_and(bits_u32x4, wasm_i32x4_splat(0x007FFFFF)),
390
+ wasm_i32x4_splat(0x00800000));
391
+ v128_t lsb_u32x4 = wasm_v128_and(wasm_u32x4_shr(significand_u32x4, 21), wasm_i32x4_splat(1));
392
+ v128_t rounded_u32x4 = wasm_i32x4_add(significand_u32x4, wasm_i32x4_add(wasm_i32x4_splat(0x000FFFFF), lsb_u32x4));
393
+ v128_t carry_u32x4 = wasm_u32x4_shr(rounded_u32x4, 24);
394
+ v128_t f32_mant_u32x4 = wasm_v128_and(wasm_u32x4_shr(rounded_u32x4, 21), wasm_i32x4_splat(0x03));
395
+ v128_t carry_mask_u32x4 = wasm_i32x4_eq(carry_u32x4, wasm_i32x4_splat(1));
396
+ f32_mant_u32x4 = wasm_v128_andnot(f32_mant_u32x4, carry_mask_u32x4);
397
+ v128_t e3m2_exp_i32x4 = wasm_i32x4_sub(wasm_i32x4_add(f32_exp_u32x4, carry_u32x4), wasm_i32x4_splat(124));
398
+
399
+ v128_t is_subnormal_u32x4 = wasm_i32x4_lt(e3m2_exp_i32x4, wasm_i32x4_splat(1));
400
+ v128_t overflow_u32x4 = wasm_i32x4_gt(e3m2_exp_i32x4, wasm_i32x4_splat(7));
401
+
402
+ v128_t clamped_exp_i32x4 = wasm_i32x4_max(e3m2_exp_i32x4, wasm_i32x4_splat(1));
403
+ clamped_exp_i32x4 = wasm_i32x4_min(clamped_exp_i32x4, wasm_i32x4_splat(7));
404
+ v128_t normal_mant_u32x4 = wasm_i32x4_relaxed_laneselect(wasm_i32x4_splat(0x03), f32_mant_u32x4, overflow_u32x4);
405
+ v128_t normal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 5),
406
+ wasm_v128_or(wasm_i32x4_shl(clamped_exp_i32x4, 2), normal_mant_u32x4));
407
+
408
+ v128_t abs_f32x4 = wasm_v128_and(hub_vec.v128, wasm_i32x4_splat(0x7FFFFFFF));
409
+ v128_t scaled_f32x4 = wasm_f32x4_mul((v128_t)abs_f32x4, wasm_f32x4_splat(16.0f));
410
+ v128_t sub_mant_i32x4 = wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_nearest(scaled_f32x4));
411
+ v128_t promotes_u32x4 = wasm_i32x4_gt(sub_mant_i32x4, wasm_i32x4_splat(3));
412
+ sub_mant_i32x4 = wasm_i32x4_min(sub_mant_i32x4, wasm_i32x4_splat(3));
413
+ sub_mant_i32x4 = wasm_i32x4_max(sub_mant_i32x4, wasm_i32x4_splat(0));
414
+ v128_t subnormal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 5), sub_mant_i32x4);
415
+ v128_t first_normal_u32x4 = wasm_v128_or(wasm_i32x4_shl(sign_u32x4, 5), wasm_i32x4_splat(0x04));
416
+ subnormal_u32x4 = wasm_i32x4_relaxed_laneselect(first_normal_u32x4, subnormal_u32x4, promotes_u32x4);
417
+
418
+ v128_t e3m2_u32x4 = wasm_i32x4_relaxed_laneselect(subnormal_u32x4, normal_u32x4, is_subnormal_u32x4);
419
+
420
+ v128_t packed_u16 = wasm_u16x8_narrow_i32x4(e3m2_u32x4, e3m2_u32x4);
421
+ v128_t packed_u8 = wasm_u8x16_narrow_i16x8(packed_u16, packed_u16);
422
+ nk_b32_vec_t result_vec;
423
+ result_vec.u32 = (nk_u32_t)wasm_i32x4_extract_lane(packed_u8, 0);
424
+ return result_vec;
425
+ }
426
+
427
+ /** @brief Convert f32x4 → 4x i8 with saturation (WASM). */
428
+ NK_INTERNAL nk_b32_vec_t nk_f32x4_to_i8x4_v128relaxed_(nk_b128_vec_t hub_vec) {
429
+ v128_t clamped_f32x4 = wasm_f32x4_min(wasm_f32x4_max(hub_vec.v128, wasm_f32x4_splat(-128.0f)),
430
+ wasm_f32x4_splat(127.0f));
431
+ v128_t result_i32x4 = wasm_i32x4_trunc_sat_f32x4(wasm_f32x4_nearest(clamped_f32x4));
432
+ v128_t result_i16x8 = wasm_i16x8_narrow_i32x4(result_i32x4, result_i32x4);
433
+ v128_t result_i8x16 = wasm_i8x16_narrow_i16x8(result_i16x8, result_i16x8);
434
+ nk_b32_vec_t result_vec;
435
+ result_vec.u32 = (nk_u32_t)wasm_i32x4_extract_lane(result_i8x16, 0);
436
+ return result_vec;
437
+ }
438
+
439
+ /** @brief Convert f32x4 → 4x u8 with saturation (WASM). */
440
+ NK_INTERNAL nk_b32_vec_t nk_f32x4_to_u8x4_v128relaxed_(nk_b128_vec_t hub_vec) {
441
+ v128_t clamped_f32x4 = wasm_f32x4_min(wasm_f32x4_max(hub_vec.v128, wasm_f32x4_splat(0.0f)),
442
+ wasm_f32x4_splat(255.0f));
443
+ v128_t result_u32x4 = wasm_u32x4_trunc_sat_f32x4(wasm_f32x4_nearest(clamped_f32x4));
444
+ v128_t result_u16x8 = wasm_u16x8_narrow_i32x4(result_u32x4, result_u32x4);
445
+ v128_t result_u8x16 = wasm_u8x16_narrow_i16x8(result_u16x8, result_u16x8);
446
+ nk_b32_vec_t result_vec;
447
+ result_vec.u32 = (nk_u32_t)wasm_i32x4_extract_lane(result_u8x16, 0);
448
+ return result_vec;
449
+ }
450
+
451
+ NK_PUBLIC void nk_cast_v128relaxed(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type) {
452
+ // Same-type fast path
453
+ if (from_type == to_type) {
454
+ nk_size_t size_bits = nk_dtype_bits(from_type);
455
+ if (size_bits > 0) nk_copy_bytes_(to, from, nk_size_divide_round_up_(n * size_bits, 8));
456
+ return;
457
+ }
458
+
459
+ // Validate supported types
460
+ int from_ok = (from_type == nk_f32_k || from_type == nk_f16_k || from_type == nk_bf16_k || from_type == nk_e4m3_k ||
461
+ from_type == nk_e5m2_k || from_type == nk_e2m3_k || from_type == nk_e3m2_k || from_type == nk_i8_k ||
462
+ from_type == nk_u8_k);
463
+ int to_ok = (to_type == nk_f32_k || to_type == nk_f16_k || to_type == nk_bf16_k || to_type == nk_e4m3_k ||
464
+ to_type == nk_e5m2_k || to_type == nk_e2m3_k || to_type == nk_e3m2_k || to_type == nk_i8_k ||
465
+ to_type == nk_u8_k);
466
+
467
+ if (!from_ok || !to_ok) {
468
+ nk_cast_serial(from, from_type, n, to, to_type);
469
+ return;
470
+ }
471
+
472
+ // F32 hub: 4 elements per iteration
473
+ nk_size_t batches = n / 4;
474
+ nk_size_t tail = n % 4;
475
+ nk_size_t from_step = 4 * nk_dtype_bits(from_type) / 8;
476
+ nk_size_t to_step = 4 * nk_dtype_bits(to_type) / 8;
477
+ nk_u8_t const *from_ptr = (nk_u8_t const *)from;
478
+ nk_u8_t *to_ptr = (nk_u8_t *)to;
479
+
480
+ for (nk_size_t idx = 0; idx < batches; ++idx, from_ptr += from_step, to_ptr += to_step) {
481
+ nk_b128_vec_t hub_vec;
482
+
483
+ // Upcast to f32x4 hub using size-appropriate loads
484
+ if (from_step == 16) { hub_vec.v128 = wasm_v128_load(from_ptr); }
485
+ else if (from_step == 8) {
486
+ nk_b64_vec_t raw64_vec;
487
+ raw64_vec.u64 = (nk_u64_t)wasm_i64x2_extract_lane(wasm_v128_load64_zero(from_ptr), 0);
488
+ switch (from_type) {
489
+ case nk_f16_k: hub_vec = nk_f16x4_to_f32x4_v128relaxed_(raw64_vec); break;
490
+ case nk_bf16_k: hub_vec = nk_bf16x4_to_f32x4_v128relaxed_(raw64_vec); break;
491
+ default: break;
492
+ }
493
+ }
494
+ else if (from_step == 4) {
495
+ nk_b32_vec_t raw32_vec;
496
+ raw32_vec.u32 = (nk_u32_t)wasm_i32x4_extract_lane(wasm_v128_load32_zero(from_ptr), 0);
497
+ switch (from_type) {
498
+ case nk_e4m3_k: hub_vec = nk_e4m3x4_to_f32x4_v128relaxed_(raw32_vec); break;
499
+ case nk_e5m2_k: hub_vec = nk_e5m2x4_to_f32x4_v128relaxed_(raw32_vec); break;
500
+ case nk_e2m3_k: hub_vec = nk_e2m3x4_to_f32x4_v128relaxed_(raw32_vec); break;
501
+ case nk_e3m2_k: hub_vec = nk_e3m2x4_to_f32x4_v128relaxed_(raw32_vec); break;
502
+ case nk_i8_k: hub_vec = nk_i8x4_to_f32x4_v128relaxed_(raw32_vec); break;
503
+ case nk_u8_k: hub_vec = nk_u8x4_to_f32x4_v128relaxed_(raw32_vec); break;
504
+ default: break;
505
+ }
506
+ }
507
+ else hub_vec.v128 = wasm_f32x4_splat(0);
508
+
509
+ // Downcast from f32x4 hub and store using half-register stores
510
+ switch (to_type) {
511
+ case nk_f32_k: wasm_v128_store(to_ptr, hub_vec.v128); break;
512
+ case nk_f16_k: *(nk_u64_t *)to_ptr = nk_f32x4_to_f16x4_v128relaxed_(hub_vec).u64; break;
513
+ case nk_bf16_k: *(nk_u64_t *)to_ptr = nk_f32x4_to_bf16x4_v128relaxed_(hub_vec).u64; break;
514
+ case nk_e4m3_k: *(nk_u32_t *)to_ptr = nk_f32x4_to_e4m3x4_v128relaxed_(hub_vec).u32; break;
515
+ case nk_e5m2_k: *(nk_u32_t *)to_ptr = nk_f32x4_to_e5m2x4_v128relaxed_(hub_vec).u32; break;
516
+ case nk_e2m3_k: *(nk_u32_t *)to_ptr = nk_f32x4_to_e2m3x4_v128relaxed_(hub_vec).u32; break;
517
+ case nk_e3m2_k: *(nk_u32_t *)to_ptr = nk_f32x4_to_e3m2x4_v128relaxed_(hub_vec).u32; break;
518
+ case nk_i8_k: *(nk_u32_t *)to_ptr = nk_f32x4_to_i8x4_v128relaxed_(hub_vec).u32; break;
519
+ case nk_u8_k: *(nk_u32_t *)to_ptr = nk_f32x4_to_u8x4_v128relaxed_(hub_vec).u32; break;
520
+ default: break;
521
+ }
522
+ }
523
+
524
+ // Handle tail elements with serial fallback
525
+ if (tail) nk_cast_serial(from_ptr, from_type, tail, to_ptr, to_type);
526
+ }
527
+
528
+ #if defined(__clang__)
529
+ #pragma clang attribute pop
530
+ #endif
531
+
532
+ #if defined(__cplusplus)
533
+ } // extern "C"
534
+ #endif
535
+
536
+ #endif // NK_TARGET_V128RELAXED
537
+ #endif // NK_CAST_V128RELAXED_H