usearch 2.21.4 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) hide show
  1. package/README.md +24 -24
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +7 -7
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +83 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +224 -48
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/dist/cjs/usearch.d.ts +8 -3
  16. package/javascript/dist/cjs/usearch.js +12 -4
  17. package/javascript/dist/esm/usearch.d.ts +8 -3
  18. package/javascript/dist/esm/usearch.js +12 -4
  19. package/javascript/lib.cpp +17 -0
  20. package/javascript/usearch.ts +14 -6
  21. package/numkong/.clang-tidy +30 -0
  22. package/{simsimd → numkong}/.cmake-format.py +18 -0
  23. package/numkong/.editorconfig +12 -0
  24. package/numkong/.git-blame-ignore-revs +123 -0
  25. package/numkong/.mailmap +15 -0
  26. package/numkong/.spi.yml +11 -0
  27. package/numkong/.swift-format +14 -0
  28. package/numkong/CITATION.cff +81 -0
  29. package/numkong/CONTRIBUTING.md +500 -0
  30. package/numkong/Cargo.toml +54 -0
  31. package/numkong/MANIFEST.in +8 -0
  32. package/numkong/Package.swift +84 -0
  33. package/numkong/README.md +569 -0
  34. package/numkong/bench/README.md +217 -0
  35. package/numkong/bench/bench-browser.html +323 -0
  36. package/numkong/bench/bench.cpp +344 -0
  37. package/numkong/bench/bench.hpp +816 -0
  38. package/numkong/bench/bench.js +148 -0
  39. package/numkong/bench/bench.mjs +616 -0
  40. package/numkong/bench/bench_attention.cpp +113 -0
  41. package/numkong/bench/bench_cast.cpp +264 -0
  42. package/numkong/bench/bench_cross_amx.cpp +62 -0
  43. package/numkong/bench/bench_cross_arm.cpp +245 -0
  44. package/numkong/bench/bench_cross_blas.cpp +309 -0
  45. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  46. package/numkong/bench/bench_cross_power.cpp +84 -0
  47. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  48. package/numkong/bench/bench_cross_serial.cpp +151 -0
  49. package/numkong/bench/bench_cross_sme.cpp +163 -0
  50. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  51. package/numkong/bench/bench_cross_x86.cpp +455 -0
  52. package/numkong/bench/bench_curved.cpp +210 -0
  53. package/numkong/bench/bench_dot.cpp +315 -0
  54. package/numkong/bench/bench_each.cpp +503 -0
  55. package/numkong/bench/bench_geospatial.cpp +112 -0
  56. package/numkong/bench/bench_maxsim.cpp +154 -0
  57. package/numkong/bench/bench_mesh.cpp +148 -0
  58. package/numkong/bench/bench_probability.cpp +60 -0
  59. package/numkong/bench/bench_reduce.cpp +371 -0
  60. package/numkong/bench/bench_set.cpp +73 -0
  61. package/numkong/bench/bench_sparse.cpp +198 -0
  62. package/numkong/bench/bench_spatial.cpp +347 -0
  63. package/numkong/bench/bench_trigonometry.cpp +137 -0
  64. package/numkong/bench/swift/Bench.swift +506 -0
  65. package/numkong/binding.gyp +169 -0
  66. package/numkong/build.rs +484 -0
  67. package/numkong/c/dispatch.h +512 -0
  68. package/numkong/c/dispatch_bf16.c +447 -0
  69. package/numkong/c/dispatch_bf16c.c +52 -0
  70. package/numkong/c/dispatch_e2m3.c +296 -0
  71. package/numkong/c/dispatch_e3m2.c +284 -0
  72. package/numkong/c/dispatch_e4m3.c +318 -0
  73. package/numkong/c/dispatch_e5m2.c +316 -0
  74. package/numkong/c/dispatch_f16.c +452 -0
  75. package/numkong/c/dispatch_f16c.c +58 -0
  76. package/numkong/c/dispatch_f32.c +434 -0
  77. package/numkong/c/dispatch_f32c.c +99 -0
  78. package/numkong/c/dispatch_f64.c +348 -0
  79. package/numkong/c/dispatch_f64c.c +98 -0
  80. package/numkong/c/dispatch_i16.c +96 -0
  81. package/numkong/c/dispatch_i32.c +89 -0
  82. package/numkong/c/dispatch_i4.c +153 -0
  83. package/numkong/c/dispatch_i64.c +86 -0
  84. package/numkong/c/dispatch_i8.c +348 -0
  85. package/numkong/c/dispatch_other.c +348 -0
  86. package/numkong/c/dispatch_u1.c +193 -0
  87. package/numkong/c/dispatch_u16.c +124 -0
  88. package/numkong/c/dispatch_u32.c +118 -0
  89. package/numkong/c/dispatch_u4.c +153 -0
  90. package/numkong/c/dispatch_u64.c +102 -0
  91. package/numkong/c/dispatch_u8.c +364 -0
  92. package/numkong/c/numkong.c +940 -0
  93. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  94. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  95. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  96. package/numkong/cmake/nk_math_lib.cmake +46 -0
  97. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  99. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  100. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  101. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  102. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  103. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  104. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  105. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  106. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  107. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  108. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  109. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  110. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  111. package/numkong/include/README.md +643 -0
  112. package/numkong/include/module.modulemap +129 -0
  113. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  114. package/numkong/include/numkong/attention/sme.h +2075 -0
  115. package/numkong/include/numkong/attention.h +49 -0
  116. package/numkong/include/numkong/capabilities.h +930 -0
  117. package/numkong/include/numkong/cast/README.md +262 -0
  118. package/numkong/include/numkong/cast/diamond.h +64 -0
  119. package/numkong/include/numkong/cast/haswell.h +823 -0
  120. package/numkong/include/numkong/cast/icelake.h +475 -0
  121. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  122. package/numkong/include/numkong/cast/neon.h +1174 -0
  123. package/numkong/include/numkong/cast/powervsx.h +449 -0
  124. package/numkong/include/numkong/cast/rvv.h +970 -0
  125. package/numkong/include/numkong/cast/sapphire.h +262 -0
  126. package/numkong/include/numkong/cast/serial.h +2336 -0
  127. package/numkong/include/numkong/cast/skylake.h +915 -0
  128. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  129. package/numkong/include/numkong/cast.h +254 -0
  130. package/numkong/include/numkong/cast.hpp +44 -0
  131. package/numkong/include/numkong/curved/README.md +223 -0
  132. package/numkong/include/numkong/curved/genoa.h +182 -0
  133. package/numkong/include/numkong/curved/haswell.h +276 -0
  134. package/numkong/include/numkong/curved/neon.h +329 -0
  135. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  136. package/numkong/include/numkong/curved/rvv.h +305 -0
  137. package/numkong/include/numkong/curved/serial.h +207 -0
  138. package/numkong/include/numkong/curved/skylake.h +457 -0
  139. package/numkong/include/numkong/curved/smef64.h +530 -0
  140. package/numkong/include/numkong/curved.h +513 -0
  141. package/numkong/include/numkong/curved.hpp +144 -0
  142. package/numkong/include/numkong/dot/README.md +442 -0
  143. package/numkong/include/numkong/dot/alder.h +563 -0
  144. package/numkong/include/numkong/dot/diamond.h +158 -0
  145. package/numkong/include/numkong/dot/genoa.h +289 -0
  146. package/numkong/include/numkong/dot/haswell.h +1723 -0
  147. package/numkong/include/numkong/dot/icelake.h +997 -0
  148. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  149. package/numkong/include/numkong/dot/neon.h +869 -0
  150. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  151. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  152. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  153. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  154. package/numkong/include/numkong/dot/powervsx.h +752 -0
  155. package/numkong/include/numkong/dot/rvv.h +722 -0
  156. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  157. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  158. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  159. package/numkong/include/numkong/dot/sapphire.h +141 -0
  160. package/numkong/include/numkong/dot/serial.h +874 -0
  161. package/numkong/include/numkong/dot/sierra.h +405 -0
  162. package/numkong/include/numkong/dot/skylake.h +1116 -0
  163. package/numkong/include/numkong/dot/sve.h +420 -0
  164. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  165. package/numkong/include/numkong/dot/svehalf.h +168 -0
  166. package/numkong/include/numkong/dot/svesdot.h +90 -0
  167. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  168. package/numkong/include/numkong/dot.h +1136 -0
  169. package/numkong/include/numkong/dot.hpp +94 -0
  170. package/numkong/include/numkong/dots/README.md +496 -0
  171. package/numkong/include/numkong/dots/alder.h +117 -0
  172. package/numkong/include/numkong/dots/diamond.h +86 -0
  173. package/numkong/include/numkong/dots/genoa.h +100 -0
  174. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  175. package/numkong/include/numkong/dots/haswell.h +310 -0
  176. package/numkong/include/numkong/dots/icelake.h +180 -0
  177. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  178. package/numkong/include/numkong/dots/neon.h +123 -0
  179. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  180. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  181. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  182. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  183. package/numkong/include/numkong/dots/powervsx.h +194 -0
  184. package/numkong/include/numkong/dots/rvv.h +2593 -0
  185. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  186. package/numkong/include/numkong/dots/serial.h +2867 -0
  187. package/numkong/include/numkong/dots/sierra.h +100 -0
  188. package/numkong/include/numkong/dots/skylake.h +207 -0
  189. package/numkong/include/numkong/dots/sme.h +5041 -0
  190. package/numkong/include/numkong/dots/smebi32.h +477 -0
  191. package/numkong/include/numkong/dots/smef64.h +1328 -0
  192. package/numkong/include/numkong/dots/smehalf.h +47 -0
  193. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  194. package/numkong/include/numkong/dots.h +3110 -0
  195. package/numkong/include/numkong/dots.hpp +641 -0
  196. package/numkong/include/numkong/each/README.md +465 -0
  197. package/numkong/include/numkong/each/haswell.h +1658 -0
  198. package/numkong/include/numkong/each/icelake.h +272 -0
  199. package/numkong/include/numkong/each/neon.h +1138 -0
  200. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  201. package/numkong/include/numkong/each/neonhalf.h +318 -0
  202. package/numkong/include/numkong/each/rvv.h +1121 -0
  203. package/numkong/include/numkong/each/sapphire.h +343 -0
  204. package/numkong/include/numkong/each/serial.h +282 -0
  205. package/numkong/include/numkong/each/skylake.h +1562 -0
  206. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  207. package/numkong/include/numkong/each.h +2232 -0
  208. package/numkong/include/numkong/each.hpp +434 -0
  209. package/numkong/include/numkong/geospatial/README.md +147 -0
  210. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  211. package/numkong/include/numkong/geospatial/neon.h +615 -0
  212. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  213. package/numkong/include/numkong/geospatial/serial.h +309 -0
  214. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  215. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  216. package/numkong/include/numkong/geospatial.h +453 -0
  217. package/numkong/include/numkong/geospatial.hpp +235 -0
  218. package/numkong/include/numkong/matrix.hpp +336 -0
  219. package/numkong/include/numkong/maxsim/README.md +187 -0
  220. package/numkong/include/numkong/maxsim/alder.h +511 -0
  221. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  222. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  223. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  224. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  225. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  226. package/numkong/include/numkong/maxsim/serial.h +490 -0
  227. package/numkong/include/numkong/maxsim/sme.h +993 -0
  228. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  229. package/numkong/include/numkong/maxsim.h +571 -0
  230. package/numkong/include/numkong/maxsim.hpp +133 -0
  231. package/numkong/include/numkong/mesh/README.md +219 -0
  232. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  233. package/numkong/include/numkong/mesh/neon.h +1821 -0
  234. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  235. package/numkong/include/numkong/mesh/rvv.h +936 -0
  236. package/numkong/include/numkong/mesh/serial.h +721 -0
  237. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  238. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  239. package/numkong/include/numkong/mesh.h +666 -0
  240. package/numkong/include/numkong/mesh.hpp +701 -0
  241. package/numkong/include/numkong/numkong.h +78 -0
  242. package/numkong/include/numkong/numkong.hpp +58 -0
  243. package/numkong/include/numkong/probability/README.md +177 -0
  244. package/numkong/include/numkong/probability/haswell.h +267 -0
  245. package/numkong/include/numkong/probability/neon.h +255 -0
  246. package/numkong/include/numkong/probability/rvv.h +414 -0
  247. package/numkong/include/numkong/probability/serial.h +181 -0
  248. package/numkong/include/numkong/probability/skylake.h +324 -0
  249. package/numkong/include/numkong/probability.h +380 -0
  250. package/numkong/include/numkong/probability.hpp +120 -0
  251. package/numkong/include/numkong/random.h +50 -0
  252. package/numkong/include/numkong/random.hpp +285 -0
  253. package/numkong/include/numkong/reduce/README.md +552 -0
  254. package/numkong/include/numkong/reduce/alder.h +636 -0
  255. package/numkong/include/numkong/reduce/genoa.h +201 -0
  256. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  257. package/numkong/include/numkong/reduce/icelake.h +549 -0
  258. package/numkong/include/numkong/reduce/neon.h +3980 -0
  259. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  260. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  261. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  262. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  263. package/numkong/include/numkong/reduce/serial.h +753 -0
  264. package/numkong/include/numkong/reduce/sierra.h +338 -0
  265. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  266. package/numkong/include/numkong/reduce/sve.h +52 -0
  267. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  268. package/numkong/include/numkong/reduce.h +1582 -0
  269. package/numkong/include/numkong/reduce.hpp +778 -0
  270. package/numkong/include/numkong/scalar/README.md +89 -0
  271. package/numkong/include/numkong/scalar/haswell.h +122 -0
  272. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  273. package/numkong/include/numkong/scalar/neon.h +122 -0
  274. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  275. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  276. package/numkong/include/numkong/scalar/rvv.h +211 -0
  277. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  278. package/numkong/include/numkong/scalar/serial.h +332 -0
  279. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  280. package/numkong/include/numkong/scalar.h +696 -0
  281. package/numkong/include/numkong/set/README.md +179 -0
  282. package/numkong/include/numkong/set/haswell.h +334 -0
  283. package/numkong/include/numkong/set/icelake.h +485 -0
  284. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  285. package/numkong/include/numkong/set/neon.h +363 -0
  286. package/numkong/include/numkong/set/powervsx.h +326 -0
  287. package/numkong/include/numkong/set/rvv.h +226 -0
  288. package/numkong/include/numkong/set/rvvbb.h +117 -0
  289. package/numkong/include/numkong/set/serial.h +174 -0
  290. package/numkong/include/numkong/set/sve.h +187 -0
  291. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  292. package/numkong/include/numkong/set.h +471 -0
  293. package/numkong/include/numkong/set.hpp +114 -0
  294. package/numkong/include/numkong/sets/README.md +149 -0
  295. package/numkong/include/numkong/sets/haswell.h +63 -0
  296. package/numkong/include/numkong/sets/icelake.h +66 -0
  297. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  298. package/numkong/include/numkong/sets/neon.h +61 -0
  299. package/numkong/include/numkong/sets/powervsx.h +65 -0
  300. package/numkong/include/numkong/sets/serial.h +43 -0
  301. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  302. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  303. package/numkong/include/numkong/sets.h +382 -0
  304. package/numkong/include/numkong/sparse/README.md +156 -0
  305. package/numkong/include/numkong/sparse/icelake.h +463 -0
  306. package/numkong/include/numkong/sparse/neon.h +288 -0
  307. package/numkong/include/numkong/sparse/serial.h +117 -0
  308. package/numkong/include/numkong/sparse/sve2.h +504 -0
  309. package/numkong/include/numkong/sparse/turin.h +322 -0
  310. package/numkong/include/numkong/sparse.h +363 -0
  311. package/numkong/include/numkong/sparse.hpp +113 -0
  312. package/numkong/include/numkong/spatial/README.md +439 -0
  313. package/numkong/include/numkong/spatial/alder.h +604 -0
  314. package/numkong/include/numkong/spatial/diamond.h +240 -0
  315. package/numkong/include/numkong/spatial/genoa.h +222 -0
  316. package/numkong/include/numkong/spatial/haswell.h +979 -0
  317. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  318. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  319. package/numkong/include/numkong/spatial/neon.h +846 -0
  320. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  321. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  322. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  323. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  324. package/numkong/include/numkong/spatial/rvv.h +991 -0
  325. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  326. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  327. package/numkong/include/numkong/spatial/serial.h +347 -0
  328. package/numkong/include/numkong/spatial/sierra.h +516 -0
  329. package/numkong/include/numkong/spatial/skylake.h +605 -0
  330. package/numkong/include/numkong/spatial/sve.h +246 -0
  331. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  332. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  333. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  334. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  335. package/numkong/include/numkong/spatial.h +1681 -0
  336. package/numkong/include/numkong/spatial.hpp +183 -0
  337. package/numkong/include/numkong/spatials/README.md +580 -0
  338. package/numkong/include/numkong/spatials/alder.h +94 -0
  339. package/numkong/include/numkong/spatials/diamond.h +82 -0
  340. package/numkong/include/numkong/spatials/genoa.h +94 -0
  341. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  342. package/numkong/include/numkong/spatials/haswell.h +219 -0
  343. package/numkong/include/numkong/spatials/icelake.h +113 -0
  344. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  345. package/numkong/include/numkong/spatials/neon.h +109 -0
  346. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  347. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  348. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  349. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  350. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  351. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  352. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  353. package/numkong/include/numkong/spatials/serial.h +248 -0
  354. package/numkong/include/numkong/spatials/sierra.h +96 -0
  355. package/numkong/include/numkong/spatials/skylake.h +184 -0
  356. package/numkong/include/numkong/spatials/sme.h +1927 -0
  357. package/numkong/include/numkong/spatials/smef64.h +483 -0
  358. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  359. package/numkong/include/numkong/spatials.h +3374 -0
  360. package/numkong/include/numkong/spatials.hpp +509 -0
  361. package/numkong/include/numkong/tensor.hpp +1981 -0
  362. package/numkong/include/numkong/trigonometry/README.md +184 -0
  363. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  364. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  365. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  366. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  367. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  368. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  369. package/numkong/include/numkong/trigonometry.h +467 -0
  370. package/numkong/include/numkong/trigonometry.hpp +166 -0
  371. package/numkong/include/numkong/types.h +1695 -0
  372. package/numkong/include/numkong/types.hpp +6027 -0
  373. package/numkong/include/numkong/vector.hpp +766 -0
  374. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  375. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  376. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  377. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  378. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  380. package/numkong/javascript/README.md +254 -0
  381. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  382. package/numkong/javascript/numkong-browser.ts +40 -0
  383. package/numkong/javascript/numkong-wasm.ts +750 -0
  384. package/numkong/javascript/numkong.c +712 -0
  385. package/numkong/javascript/numkong.ts +613 -0
  386. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  387. package/numkong/javascript/tsconfig-cjs.json +13 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  389. package/numkong/javascript/types.ts +784 -0
  390. package/numkong/numkong.gypi +104 -0
  391. package/numkong/package.json +108 -0
  392. package/numkong/probes/arm_neon.c +8 -0
  393. package/numkong/probes/arm_neon_bfdot.c +9 -0
  394. package/numkong/probes/arm_neon_fhm.c +9 -0
  395. package/numkong/probes/arm_neon_half.c +8 -0
  396. package/numkong/probes/arm_neon_sdot.c +9 -0
  397. package/numkong/probes/arm_neonfp8.c +9 -0
  398. package/numkong/probes/arm_sme.c +16 -0
  399. package/numkong/probes/arm_sme2.c +16 -0
  400. package/numkong/probes/arm_sme2p1.c +16 -0
  401. package/numkong/probes/arm_sme_bf16.c +16 -0
  402. package/numkong/probes/arm_sme_bi32.c +16 -0
  403. package/numkong/probes/arm_sme_f64.c +16 -0
  404. package/numkong/probes/arm_sme_fa64.c +14 -0
  405. package/numkong/probes/arm_sme_half.c +16 -0
  406. package/numkong/probes/arm_sme_lut2.c +15 -0
  407. package/numkong/probes/arm_sve.c +18 -0
  408. package/numkong/probes/arm_sve2.c +20 -0
  409. package/numkong/probes/arm_sve2p1.c +18 -0
  410. package/numkong/probes/arm_sve_bfdot.c +20 -0
  411. package/numkong/probes/arm_sve_half.c +18 -0
  412. package/numkong/probes/arm_sve_sdot.c +21 -0
  413. package/numkong/probes/loongarch_lasx.c +12 -0
  414. package/numkong/probes/power_vsx.c +12 -0
  415. package/numkong/probes/probe.js +127 -0
  416. package/numkong/probes/riscv_rvv.c +14 -0
  417. package/numkong/probes/riscv_rvv_bb.c +15 -0
  418. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  419. package/numkong/probes/riscv_rvv_half.c +14 -0
  420. package/numkong/probes/wasm_v128relaxed.c +11 -0
  421. package/numkong/probes/x86_alder.c +17 -0
  422. package/numkong/probes/x86_diamond.c +17 -0
  423. package/numkong/probes/x86_genoa.c +17 -0
  424. package/numkong/probes/x86_graniteamx.c +19 -0
  425. package/numkong/probes/x86_haswell.c +11 -0
  426. package/numkong/probes/x86_icelake.c +17 -0
  427. package/numkong/probes/x86_sapphire.c +16 -0
  428. package/numkong/probes/x86_sapphireamx.c +18 -0
  429. package/numkong/probes/x86_sierra.c +17 -0
  430. package/numkong/probes/x86_skylake.c +15 -0
  431. package/numkong/probes/x86_turin.c +17 -0
  432. package/numkong/rust/README.md +698 -0
  433. package/numkong/rust/capabilities.rs +96 -0
  434. package/numkong/rust/cast.rs +314 -0
  435. package/numkong/rust/curved.rs +391 -0
  436. package/numkong/rust/each.rs +2721 -0
  437. package/numkong/rust/geospatial.rs +343 -0
  438. package/numkong/rust/matrix.rs +5424 -0
  439. package/numkong/rust/maxsim.rs +540 -0
  440. package/numkong/rust/mesh.rs +837 -0
  441. package/numkong/rust/numkong.rs +409 -0
  442. package/numkong/rust/probability.rs +272 -0
  443. package/numkong/rust/reduce.rs +1249 -0
  444. package/numkong/rust/set.rs +194 -0
  445. package/numkong/rust/sparse.rs +513 -0
  446. package/numkong/rust/spatial.rs +1815 -0
  447. package/numkong/rust/tensor.rs +7565 -0
  448. package/numkong/rust/types.rs +3666 -0
  449. package/numkong/rust/vector.rs +1899 -0
  450. package/numkong/rustfmt.toml +2 -0
  451. package/numkong/swift/Matrix.swift +1388 -0
  452. package/numkong/swift/MaxSim.swift +151 -0
  453. package/numkong/swift/NumKong.swift +283 -0
  454. package/numkong/swift/Numerics.swift +329 -0
  455. package/numkong/swift/README.md +433 -0
  456. package/numkong/swift/Scalar.swift +741 -0
  457. package/numkong/swift/Tensor.swift +209 -0
  458. package/numkong/test/README.md +315 -0
  459. package/numkong/test/playwright.config.ts +16 -0
  460. package/numkong/test/swift/Test.swift +534 -0
  461. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  462. package/numkong/test/test-browser-bundle.html +188 -0
  463. package/numkong/test/test-browser-runner.mjs +43 -0
  464. package/numkong/test/test-browser.html +305 -0
  465. package/numkong/test/test-dtypes.mjs +453 -0
  466. package/numkong/test/test-wasm.mjs +267 -0
  467. package/numkong/test/test.cpp +442 -0
  468. package/numkong/test/test.hpp +580 -0
  469. package/numkong/test/test.mjs +363 -0
  470. package/numkong/test/test_base.py +1041 -0
  471. package/numkong/test/test_cast.cpp +242 -0
  472. package/numkong/test/test_cross.hpp +551 -0
  473. package/numkong/test/test_cross.py +467 -0
  474. package/numkong/test/test_cross_amx.cpp +50 -0
  475. package/numkong/test/test_cross_arm.cpp +225 -0
  476. package/numkong/test/test_cross_blas.cpp +354 -0
  477. package/numkong/test/test_cross_loongarch.cpp +90 -0
  478. package/numkong/test/test_cross_power.cpp +73 -0
  479. package/numkong/test/test_cross_rvv.cpp +109 -0
  480. package/numkong/test/test_cross_serial.cpp +181 -0
  481. package/numkong/test/test_cross_sme.cpp +148 -0
  482. package/numkong/test/test_cross_wasm.cpp +141 -0
  483. package/numkong/test/test_cross_x86.cpp +442 -0
  484. package/numkong/test/test_curved.cpp +182 -0
  485. package/numkong/test/test_curved.py +207 -0
  486. package/numkong/test/test_dot.cpp +353 -0
  487. package/numkong/test/test_dot.py +296 -0
  488. package/numkong/test/test_each.cpp +437 -0
  489. package/numkong/test/test_each.py +756 -0
  490. package/numkong/test/test_geospatial.cpp +155 -0
  491. package/numkong/test/test_geospatial.py +241 -0
  492. package/numkong/test/test_maxsim.cpp +138 -0
  493. package/numkong/test/test_maxsim.py +209 -0
  494. package/numkong/test/test_mesh.cpp +203 -0
  495. package/numkong/test/test_mesh.py +394 -0
  496. package/numkong/test/test_probability.cpp +136 -0
  497. package/numkong/test/test_probability.py +166 -0
  498. package/numkong/test/test_reduce.cpp +563 -0
  499. package/numkong/test/test_reduce.py +781 -0
  500. package/numkong/test/test_set.cpp +151 -0
  501. package/numkong/test/test_set.py +120 -0
  502. package/numkong/test/test_similarities.py +579 -0
  503. package/numkong/test/test_sparse.cpp +121 -0
  504. package/numkong/test/test_sparse.py +118 -0
  505. package/numkong/test/test_spatial.cpp +518 -0
  506. package/numkong/test/test_spatial.py +269 -0
  507. package/numkong/test/test_tensor.cpp +884 -0
  508. package/numkong/test/test_tensor.py +1417 -0
  509. package/numkong/test/test_trigonometry.cpp +156 -0
  510. package/numkong/test/test_trigonometry.py +180 -0
  511. package/package.json +7 -8
  512. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  513. package/prebuilds/linux-arm64/usearch.node +0 -0
  514. package/prebuilds/linux-x64/usearch.node +0 -0
  515. package/fp16/CMakeLists.txt +0 -176
  516. package/fp16/LICENSE +0 -11
  517. package/fp16/README.md +0 -20
  518. package/fp16/bench/alt-element.cc +0 -89
  519. package/fp16/bench/from-alt-array.cc +0 -175
  520. package/fp16/bench/from-ieee-array.cc +0 -399
  521. package/fp16/bench/ieee-element.cc +0 -272
  522. package/fp16/bench/to-alt-array.cc +0 -91
  523. package/fp16/bench/to-ieee-array.cc +0 -303
  524. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  525. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  526. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  527. package/fp16/configure.py +0 -65
  528. package/fp16/confu.yaml +0 -8
  529. package/fp16/include/fp16/__init__.py +0 -0
  530. package/fp16/include/fp16/avx.py +0 -50
  531. package/fp16/include/fp16/avx2.py +0 -53
  532. package/fp16/include/fp16/bitcasts.h +0 -92
  533. package/fp16/include/fp16/fp16.h +0 -451
  534. package/fp16/include/fp16/psimd.h +0 -131
  535. package/fp16/include/fp16.h +0 -11
  536. package/fp16/jni/Android.mk +0 -6
  537. package/fp16/jni/Application.mk +0 -4
  538. package/fp16/test/alt-from-fp32-value.cc +0 -498
  539. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  540. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  541. package/fp16/test/alt-to-fp32-value.cc +0 -348
  542. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  543. package/fp16/test/bitcasts.cc +0 -56
  544. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  545. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  546. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  547. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  548. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  549. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  550. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  551. package/fp16/test/peachpy/stubs.py +0 -38
  552. package/fp16/test/tables.cc +0 -530
  553. package/fp16/test/tables.h +0 -13
  554. package/fp16/third-party/THHalf.h +0 -92
  555. package/fp16/third-party/eigen-half.h +0 -170
  556. package/fp16/third-party/float16-compressor.h +0 -80
  557. package/fp16/third-party/half.hpp +0 -2916
  558. package/fp16/third-party/npy-halffloat.h +0 -328
  559. package/simsimd/.git-blame-ignore-revs +0 -2
  560. package/simsimd/CONTRIBUTING.md +0 -321
  561. package/simsimd/Cargo.toml +0 -49
  562. package/simsimd/MANIFEST.in +0 -4
  563. package/simsimd/Package.swift +0 -28
  564. package/simsimd/README.md +0 -1493
  565. package/simsimd/binding.gyp +0 -35
  566. package/simsimd/build.rs +0 -70
  567. package/simsimd/c/lib.c +0 -374
  568. package/simsimd/include/module.modulemap +0 -4
  569. package/simsimd/include/simsimd/binary.h +0 -486
  570. package/simsimd/include/simsimd/curved.h +0 -1541
  571. package/simsimd/include/simsimd/dot.h +0 -1853
  572. package/simsimd/include/simsimd/elementwise.h +0 -2465
  573. package/simsimd/include/simsimd/geospatial.h +0 -43
  574. package/simsimd/include/simsimd/mesh.h +0 -69
  575. package/simsimd/include/simsimd/probability.h +0 -606
  576. package/simsimd/include/simsimd/simsimd.h +0 -2567
  577. package/simsimd/include/simsimd/sparse.h +0 -1384
  578. package/simsimd/include/simsimd/spatial.h +0 -2335
  579. package/simsimd/include/simsimd/types.h +0 -666
  580. package/simsimd/javascript/fallback.ts +0 -233
  581. package/simsimd/javascript/lib.c +0 -125
  582. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  583. package/simsimd/javascript/simsimd.ts +0 -179
  584. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  585. package/simsimd/package-lock.json +0 -1761
  586. package/simsimd/package.json +0 -61
  587. package/simsimd/rust/lib.rs +0 -1821
  588. package/simsimd/scripts/bench.cxx +0 -1170
  589. package/simsimd/scripts/bench.ipynb +0 -187
  590. package/simsimd/scripts/bench.js +0 -127
  591. package/simsimd/scripts/bench.rs +0 -876
  592. package/simsimd/scripts/bench_vectors.py +0 -734
  593. package/simsimd/scripts/bench_vectors_live.py +0 -213
  594. package/simsimd/scripts/test.c +0 -187
  595. package/simsimd/scripts/test.mjs +0 -220
  596. package/simsimd/scripts/test.py +0 -1505
  597. package/simsimd/swift/SimSIMD.swift +0 -149
  598. package/simsimd/swift/Test.swift +0 -128
  599. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  600. /package/{simsimd → numkong}/LICENSE +0 -0
  601. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  602. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,211 @@
1
+ /**
2
+ * @brief SIMD-accelerated Scalar Math Helpers for RISC-V.
3
+ * @file include/numkong/scalar/rvv.h
4
+ * @author Ash Vardanian
5
+ * @date March 1, 2026
6
+ *
7
+ * @sa include/numkong/scalar.h
8
+ *
9
+ * RVV scalar helpers use vector instructions with VL=1 for hardware sqrt/rsqrt.
10
+ * `vfrsqrt7` provides 7-bit mantissa precision; Newton-Raphson refines to full precision.
11
+ */
12
+ #ifndef NK_SCALAR_RVV_H
13
+ #define NK_SCALAR_RVV_H
14
+
15
+ #if NK_TARGET_RISCV64_
16
+ #if NK_TARGET_RVV
17
+
18
+ #include "numkong/types.h"
19
+
20
+ #if defined(__clang__)
21
+ #pragma clang attribute push(__attribute__((target("arch=+v"))), apply_to = function)
22
+ #elif defined(__GNUC__)
23
+ #pragma GCC push_options
24
+ #pragma GCC target("arch=+v")
25
+ #endif
26
+
27
+ #if defined(__cplusplus)
28
+ extern "C" {
29
+ #endif
30
+
31
+ NK_PUBLIC nk_f32_t nk_f32_rsqrt_rvv(nk_f32_t number) {
32
+ vfloat32m1_t x_f32m1 = __riscv_vfmv_s_f_f32m1(number, 1);
33
+ vfloat32m1_t estimate_f32m1 = __riscv_vfrsqrt7_v_f32m1(x_f32m1, 1);
34
+ vfloat32m1_t half_f32m1 = __riscv_vfmv_s_f_f32m1(0.5f, 1);
35
+ vfloat32m1_t three_half_f32m1 = __riscv_vfmv_s_f_f32m1(1.5f, 1);
36
+ vfloat32m1_t half_x_f32m1 = __riscv_vfmul_vv_f32m1(half_f32m1, x_f32m1, 1);
37
+ // Iteration 1
38
+ vfloat32m1_t estimate_sq_f32m1 = __riscv_vfmul_vv_f32m1(estimate_f32m1, estimate_f32m1, 1);
39
+ vfloat32m1_t correction_f32m1 = __riscv_vfmul_vv_f32m1(half_x_f32m1, estimate_sq_f32m1, 1);
40
+ vfloat32m1_t factor_f32m1 = __riscv_vfsub_vv_f32m1(three_half_f32m1, correction_f32m1, 1);
41
+ estimate_f32m1 = __riscv_vfmul_vv_f32m1(estimate_f32m1, factor_f32m1, 1);
42
+ // Iteration 2
43
+ estimate_sq_f32m1 = __riscv_vfmul_vv_f32m1(estimate_f32m1, estimate_f32m1, 1);
44
+ correction_f32m1 = __riscv_vfmul_vv_f32m1(half_x_f32m1, estimate_sq_f32m1, 1);
45
+ factor_f32m1 = __riscv_vfsub_vv_f32m1(three_half_f32m1, correction_f32m1, 1);
46
+ estimate_f32m1 = __riscv_vfmul_vv_f32m1(estimate_f32m1, factor_f32m1, 1);
47
+ return __riscv_vfmv_f_s_f32m1_f32(estimate_f32m1);
48
+ }
49
+
50
+ NK_PUBLIC nk_f32_t nk_f32_sqrt_rvv(nk_f32_t number) {
51
+ vfloat32m1_t x_f32m1 = __riscv_vfmv_s_f_f32m1(number, 1);
52
+ return __riscv_vfmv_f_s_f32m1_f32(__riscv_vfsqrt_v_f32m1(x_f32m1, 1));
53
+ }
54
+
55
+ NK_PUBLIC nk_f64_t nk_f64_rsqrt_rvv(nk_f64_t number) {
56
+ vfloat64m1_t x_f64m1 = __riscv_vfmv_s_f_f64m1(number, 1);
57
+ vfloat64m1_t estimate_f64m1 = __riscv_vfrsqrt7_v_f64m1(x_f64m1, 1);
58
+ vfloat64m1_t half_f64m1 = __riscv_vfmv_s_f_f64m1(0.5, 1);
59
+ vfloat64m1_t three_half_f64m1 = __riscv_vfmv_s_f_f64m1(1.5, 1);
60
+ vfloat64m1_t half_x_f64m1 = __riscv_vfmul_vv_f64m1(half_f64m1, x_f64m1, 1);
61
+ // Iteration 1
62
+ vfloat64m1_t estimate_sq_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, estimate_f64m1, 1);
63
+ vfloat64m1_t correction_f64m1 = __riscv_vfmul_vv_f64m1(half_x_f64m1, estimate_sq_f64m1, 1);
64
+ vfloat64m1_t factor_f64m1 = __riscv_vfsub_vv_f64m1(three_half_f64m1, correction_f64m1, 1);
65
+ estimate_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, factor_f64m1, 1);
66
+ // Iteration 2
67
+ estimate_sq_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, estimate_f64m1, 1);
68
+ correction_f64m1 = __riscv_vfmul_vv_f64m1(half_x_f64m1, estimate_sq_f64m1, 1);
69
+ factor_f64m1 = __riscv_vfsub_vv_f64m1(three_half_f64m1, correction_f64m1, 1);
70
+ estimate_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, factor_f64m1, 1);
71
+ // Iteration 3
72
+ estimate_sq_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, estimate_f64m1, 1);
73
+ correction_f64m1 = __riscv_vfmul_vv_f64m1(half_x_f64m1, estimate_sq_f64m1, 1);
74
+ factor_f64m1 = __riscv_vfsub_vv_f64m1(three_half_f64m1, correction_f64m1, 1);
75
+ estimate_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, factor_f64m1, 1);
76
+ return __riscv_vfmv_f_s_f64m1_f64(estimate_f64m1);
77
+ }
78
+
79
+ NK_PUBLIC nk_f64_t nk_f64_sqrt_rvv(nk_f64_t number) {
80
+ vfloat64m1_t x_f64m1 = __riscv_vfmv_s_f_f64m1(number, 1);
81
+ return __riscv_vfmv_f_s_f64m1_f64(__riscv_vfsqrt_v_f64m1(x_f64m1, 1));
82
+ }
83
+
84
+ NK_PUBLIC nk_f32_t nk_f32_fma_rvv(nk_f32_t a, nk_f32_t b, nk_f32_t c) {
85
+ vfloat32m1_t a_f32m1 = __riscv_vfmv_s_f_f32m1(a, 1);
86
+ vfloat32m1_t c_f32m1 = __riscv_vfmv_s_f_f32m1(c, 1);
87
+ return __riscv_vfmv_f_s_f32m1_f32(__riscv_vfmacc_vf_f32m1(c_f32m1, b, a_f32m1, 1));
88
+ }
89
+
90
+ NK_PUBLIC nk_f64_t nk_f64_fma_rvv(nk_f64_t a, nk_f64_t b, nk_f64_t c) {
91
+ vfloat64m1_t a_f64m1 = __riscv_vfmv_s_f_f64m1(a, 1);
92
+ vfloat64m1_t c_f64m1 = __riscv_vfmv_s_f_f64m1(c, 1);
93
+ return __riscv_vfmv_f_s_f64m1_f64(__riscv_vfmacc_vf_f64m1(c_f64m1, b, a_f64m1, 1));
94
+ }
95
+
96
+ NK_PUBLIC nk_u8_t nk_u8_saturating_add_rvv(nk_u8_t a, nk_u8_t b) {
97
+ vuint8m1_t a_u8m1 = __riscv_vmv_v_x_u8m1(a, 1);
98
+ vuint8m1_t b_u8m1 = __riscv_vmv_v_x_u8m1(b, 1);
99
+ return __riscv_vmv_x_s_u8m1_u8(__riscv_vsaddu_vv_u8m1(a_u8m1, b_u8m1, 1));
100
+ }
101
+
102
+ NK_PUBLIC nk_i8_t nk_i8_saturating_add_rvv(nk_i8_t a, nk_i8_t b) {
103
+ vint8m1_t a_i8m1 = __riscv_vmv_v_x_i8m1(a, 1);
104
+ vint8m1_t b_i8m1 = __riscv_vmv_v_x_i8m1(b, 1);
105
+ return __riscv_vmv_x_s_i8m1_i8(__riscv_vsadd_vv_i8m1(a_i8m1, b_i8m1, 1));
106
+ }
107
+
108
+ NK_PUBLIC nk_u16_t nk_u16_saturating_add_rvv(nk_u16_t a, nk_u16_t b) {
109
+ vuint16m1_t a_u16m1 = __riscv_vmv_v_x_u16m1(a, 1);
110
+ vuint16m1_t b_u16m1 = __riscv_vmv_v_x_u16m1(b, 1);
111
+ return __riscv_vmv_x_s_u16m1_u16(__riscv_vsaddu_vv_u16m1(a_u16m1, b_u16m1, 1));
112
+ }
113
+
114
+ NK_PUBLIC nk_i16_t nk_i16_saturating_add_rvv(nk_i16_t a, nk_i16_t b) {
115
+ vint16m1_t a_i16m1 = __riscv_vmv_v_x_i16m1(a, 1);
116
+ vint16m1_t b_i16m1 = __riscv_vmv_v_x_i16m1(b, 1);
117
+ return __riscv_vmv_x_s_i16m1_i16(__riscv_vsadd_vv_i16m1(a_i16m1, b_i16m1, 1));
118
+ }
119
+
120
+ NK_PUBLIC nk_u32_t nk_u32_saturating_add_rvv(nk_u32_t a, nk_u32_t b) {
121
+ vuint32m1_t a_u32m1 = __riscv_vmv_v_x_u32m1(a, 1);
122
+ vuint32m1_t b_u32m1 = __riscv_vmv_v_x_u32m1(b, 1);
123
+ return __riscv_vmv_x_s_u32m1_u32(__riscv_vsaddu_vv_u32m1(a_u32m1, b_u32m1, 1));
124
+ }
125
+
126
+ NK_PUBLIC nk_i32_t nk_i32_saturating_add_rvv(nk_i32_t a, nk_i32_t b) {
127
+ vint32m1_t a_i32m1 = __riscv_vmv_v_x_i32m1(a, 1);
128
+ vint32m1_t b_i32m1 = __riscv_vmv_v_x_i32m1(b, 1);
129
+ return __riscv_vmv_x_s_i32m1_i32(__riscv_vsadd_vv_i32m1(a_i32m1, b_i32m1, 1));
130
+ }
131
+
132
+ NK_PUBLIC nk_u64_t nk_u64_saturating_add_rvv(nk_u64_t a, nk_u64_t b) {
133
+ vuint64m1_t a_u64m1 = __riscv_vmv_v_x_u64m1(a, 1);
134
+ vuint64m1_t b_u64m1 = __riscv_vmv_v_x_u64m1(b, 1);
135
+ return __riscv_vmv_x_s_u64m1_u64(__riscv_vsaddu_vv_u64m1(a_u64m1, b_u64m1, 1));
136
+ }
137
+
138
+ NK_PUBLIC nk_i64_t nk_i64_saturating_add_rvv(nk_i64_t a, nk_i64_t b) {
139
+ vint64m1_t a_i64m1 = __riscv_vmv_v_x_i64m1(a, 1);
140
+ vint64m1_t b_i64m1 = __riscv_vmv_v_x_i64m1(b, 1);
141
+ return __riscv_vmv_x_s_i64m1_i64(__riscv_vsadd_vv_i64m1(a_i64m1, b_i64m1, 1));
142
+ }
143
+
144
+ NK_PUBLIC nk_u8_t nk_u8_saturating_mul_rvv(nk_u8_t a, nk_u8_t b) {
145
+ vuint8m1_t a_u8m1 = __riscv_vmv_v_x_u8m1(a, 1);
146
+ vuint8m1_t b_u8m1 = __riscv_vmv_v_x_u8m1(b, 1);
147
+ vuint16m2_t product_u16m2 = __riscv_vwmulu_vv_u16m2(a_u8m1, b_u8m1, 1);
148
+ return __riscv_vmv_x_s_u8m1_u8(__riscv_vnclipu_wx_u8m1(product_u16m2, 0, __RISCV_VXRM_RDN, 1));
149
+ }
150
+ NK_PUBLIC nk_i8_t nk_i8_saturating_mul_rvv(nk_i8_t a, nk_i8_t b) {
151
+ vint8m1_t a_i8m1 = __riscv_vmv_v_x_i8m1(a, 1);
152
+ vint8m1_t b_i8m1 = __riscv_vmv_v_x_i8m1(b, 1);
153
+ vint16m2_t product_i16m2 = __riscv_vwmul_vv_i16m2(a_i8m1, b_i8m1, 1);
154
+ return __riscv_vmv_x_s_i8m1_i8(__riscv_vnclip_wx_i8m1(product_i16m2, 0, __RISCV_VXRM_RDN, 1));
155
+ }
156
+ NK_PUBLIC nk_u16_t nk_u16_saturating_mul_rvv(nk_u16_t a, nk_u16_t b) {
157
+ vuint16m1_t a_u16m1 = __riscv_vmv_v_x_u16m1(a, 1);
158
+ vuint16m1_t b_u16m1 = __riscv_vmv_v_x_u16m1(b, 1);
159
+ vuint32m2_t product_u32m2 = __riscv_vwmulu_vv_u32m2(a_u16m1, b_u16m1, 1);
160
+ return __riscv_vmv_x_s_u16m1_u16(__riscv_vnclipu_wx_u16m1(product_u32m2, 0, __RISCV_VXRM_RDN, 1));
161
+ }
162
+ NK_PUBLIC nk_i16_t nk_i16_saturating_mul_rvv(nk_i16_t a, nk_i16_t b) {
163
+ vint16m1_t a_i16m1 = __riscv_vmv_v_x_i16m1(a, 1);
164
+ vint16m1_t b_i16m1 = __riscv_vmv_v_x_i16m1(b, 1);
165
+ vint32m2_t product_i32m2 = __riscv_vwmul_vv_i32m2(a_i16m1, b_i16m1, 1);
166
+ return __riscv_vmv_x_s_i16m1_i16(__riscv_vnclip_wx_i16m1(product_i32m2, 0, __RISCV_VXRM_RDN, 1));
167
+ }
168
+ NK_PUBLIC nk_u32_t nk_u32_saturating_mul_rvv(nk_u32_t a, nk_u32_t b) {
169
+ vuint32m1_t a_u32m1 = __riscv_vmv_v_x_u32m1(a, 1);
170
+ vuint32m1_t b_u32m1 = __riscv_vmv_v_x_u32m1(b, 1);
171
+ vuint64m2_t product_u64m2 = __riscv_vwmulu_vv_u64m2(a_u32m1, b_u32m1, 1);
172
+ return __riscv_vmv_x_s_u32m1_u32(__riscv_vnclipu_wx_u32m1(product_u64m2, 0, __RISCV_VXRM_RDN, 1));
173
+ }
174
+ NK_PUBLIC nk_i32_t nk_i32_saturating_mul_rvv(nk_i32_t a, nk_i32_t b) {
175
+ vint32m1_t a_i32m1 = __riscv_vmv_v_x_i32m1(a, 1);
176
+ vint32m1_t b_i32m1 = __riscv_vmv_v_x_i32m1(b, 1);
177
+ vint64m2_t product_i64m2 = __riscv_vwmul_vv_i64m2(a_i32m1, b_i32m1, 1);
178
+ return __riscv_vmv_x_s_i32m1_i32(__riscv_vnclip_wx_i32m1(product_i64m2, 0, __RISCV_VXRM_RDN, 1));
179
+ }
180
+ NK_PUBLIC nk_u64_t nk_u64_saturating_mul_rvv(nk_u64_t a, nk_u64_t b) {
181
+ vuint64m1_t a_u64m1 = __riscv_vmv_v_x_u64m1(a, 1);
182
+ vuint64m1_t b_u64m1 = __riscv_vmv_v_x_u64m1(b, 1);
183
+ nk_u64_t high = __riscv_vmv_x_s_u64m1_u64(__riscv_vmulhu_vv_u64m1(a_u64m1, b_u64m1, 1));
184
+ return high ? 18446744073709551615ull : (a * b);
185
+ }
186
+ NK_PUBLIC nk_i64_t nk_i64_saturating_mul_rvv(nk_i64_t a, nk_i64_t b) {
187
+ int sign = (a < 0) ^ (b < 0);
188
+ nk_u64_t abs_a = a < 0 ? (0u - (nk_u64_t)a) : (nk_u64_t)a;
189
+ nk_u64_t abs_b = b < 0 ? (0u - (nk_u64_t)b) : (nk_u64_t)b;
190
+ vuint64m1_t a_u64m1 = __riscv_vmv_v_x_u64m1(abs_a, 1);
191
+ vuint64m1_t b_u64m1 = __riscv_vmv_v_x_u64m1(abs_b, 1);
192
+ nk_u64_t high = __riscv_vmv_x_s_u64m1_u64(__riscv_vmulhu_vv_u64m1(a_u64m1, b_u64m1, 1));
193
+ nk_u64_t low = abs_a * abs_b;
194
+ if (high || (sign && low > 9223372036854775808ull) || (!sign && low > 9223372036854775807ull))
195
+ return sign ? (-9223372036854775807ll - 1ll) : 9223372036854775807ll;
196
+ return sign ? -(nk_i64_t)low : (nk_i64_t)low;
197
+ }
198
+
199
+ #if defined(__cplusplus)
200
+ } // extern "C"
201
+ #endif
202
+
203
+ #if defined(__clang__)
204
+ #pragma clang attribute pop
205
+ #elif defined(__GNUC__)
206
+ #pragma GCC pop_options
207
+ #endif
208
+
209
+ #endif // NK_TARGET_RVV
210
+ #endif // NK_TARGET_RISCV64_
211
+ #endif // NK_SCALAR_RVV_H
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @brief SIMD-accelerated Scalar Math Helpers for Sapphire Rapids.
3
+ * @file include/numkong/scalar/sapphire.h
4
+ * @author Ash Vardanian
5
+ * @date March 1, 2026
6
+ *
7
+ * @sa include/numkong/scalar.h
8
+ *
9
+ * Provides native AVX-512 FP16 scalar ordering via `VCOMISH`.
10
+ */
11
+ #ifndef NK_SCALAR_SAPPHIRE_H
12
+ #define NK_SCALAR_SAPPHIRE_H
13
+
14
+ #if NK_TARGET_X8664_
15
+ #if NK_TARGET_SAPPHIRE
16
+
17
+ #include "numkong/types.h"
18
+
19
+ #if defined(__cplusplus)
20
+ extern "C" {
21
+ #endif
22
+
23
+ #if defined(__clang__)
24
+ #pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,avx512bw,avx512fp16,f16c,fma,bmi,bmi2"))), \
25
+ apply_to = function)
26
+ #elif defined(__GNUC__)
27
+ #pragma GCC push_options
28
+ #pragma GCC target("avx2", "avx512f", "avx512vl", "avx512bw", "avx512fp16", "f16c", "fma", "bmi", "bmi2")
29
+ #endif
30
+
31
+ NK_PUBLIC int nk_f16_order_sapphire(nk_f16_t a, nk_f16_t b) {
32
+ nk_fui16_t a_fui, b_fui;
33
+ a_fui.f = a, b_fui.f = b;
34
+ __m128h a_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(a_fui.u));
35
+ __m128h b_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(b_fui.u));
36
+ return _mm_comigt_sh(a_f16x8, b_f16x8) - _mm_comilt_sh(a_f16x8, b_f16x8);
37
+ }
38
+ NK_PUBLIC nk_f16_t nk_f16_sqrt_sapphire(nk_f16_t x) {
39
+ nk_fui16_t x_fui, out_fui;
40
+ x_fui.f = x;
41
+ __m128h x_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(x_fui.u));
42
+ out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(_mm_castph_si128(_mm_sqrt_sh(x_f16x8, x_f16x8)));
43
+ return out_fui.f;
44
+ }
45
+ NK_PUBLIC nk_f16_t nk_f16_rsqrt_sapphire(nk_f16_t x) {
46
+ nk_fui16_t x_fui, out_fui;
47
+ x_fui.f = x;
48
+ __m128h x_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(x_fui.u));
49
+ out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(_mm_castph_si128(_mm_rsqrt_sh(x_f16x8, x_f16x8)));
50
+ return out_fui.f;
51
+ }
52
+ NK_PUBLIC nk_f16_t nk_f16_fma_sapphire(nk_f16_t a, nk_f16_t b, nk_f16_t c) {
53
+ nk_fui16_t a_fui, b_fui, c_fui, out_fui;
54
+ a_fui.f = a, b_fui.f = b, c_fui.f = c;
55
+ __m128h a_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(a_fui.u));
56
+ __m128h b_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(b_fui.u));
57
+ __m128h c_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(c_fui.u));
58
+ out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(_mm_castph_si128(_mm_fmadd_sh(a_f16x8, b_f16x8, c_f16x8)));
59
+ return out_fui.f;
60
+ }
61
+
62
+ #if defined(__clang__)
63
+ #pragma clang attribute pop
64
+ #elif defined(__GNUC__)
65
+ #pragma GCC pop_options
66
+ #endif
67
+
68
+ #if defined(__cplusplus)
69
+ } // extern "C"
70
+ #endif
71
+
72
+ #endif // NK_TARGET_SAPPHIRE
73
+ #endif // NK_TARGET_X8664_
74
+ #endif // NK_SCALAR_SAPPHIRE_H
@@ -0,0 +1,332 @@
1
+ /**
2
+ * @brief Software-emulated Scalar Math Helpers for SIMD-free CPUs.
3
+ * @file include/numkong/scalar/serial.h
4
+ * @author Ash Vardanian
5
+ * @date March 1, 2026
6
+ *
7
+ * @sa include/numkong/scalar.h
8
+ *
9
+ * Uses the Quake 3 fast inverse square root trick with Newton-Raphson refinement.
10
+ * Three iterations for f32 (~34.9 correct bits), four for f64 (~69.3 correct bits).
11
+ */
12
+ #ifndef NK_SCALAR_SERIAL_H
13
+ #define NK_SCALAR_SERIAL_H
14
+
15
+ #include "numkong/types.h"
16
+ #include "numkong/cast/serial.h"
17
+
18
+ #if defined(__cplusplus)
19
+ extern "C" {
20
+ #endif
21
+
22
+ NK_PUBLIC nk_f32_t nk_f32_rsqrt_serial(nk_f32_t number) {
23
+ nk_fui32_t conv;
24
+ conv.f = number;
25
+ conv.u = 0x5F375A86 - (conv.u >> 1);
26
+ nk_f32_t y = conv.f;
27
+ y = y * (1.5f - 0.5f * number * y * y);
28
+ y = y * (1.5f - 0.5f * number * y * y);
29
+ y = y * (1.5f - 0.5f * number * y * y);
30
+ return y;
31
+ }
32
+
33
+ NK_PUBLIC nk_f32_t nk_f32_sqrt_serial(nk_f32_t number) { return number > 0 ? number * nk_f32_rsqrt_serial(number) : 0; }
34
+
35
+ NK_PUBLIC nk_f64_t nk_f64_rsqrt_serial(nk_f64_t number) {
36
+ nk_fui64_t conv;
37
+ conv.f = number;
38
+ conv.u = 0x5FE6EB50C7B537A9ULL - (conv.u >> 1);
39
+ nk_f64_t y = conv.f;
40
+ y = y * (1.5 - 0.5 * number * y * y);
41
+ y = y * (1.5 - 0.5 * number * y * y);
42
+ y = y * (1.5 - 0.5 * number * y * y);
43
+ y = y * (1.5 - 0.5 * number * y * y);
44
+ return y;
45
+ }
46
+
47
+ NK_PUBLIC nk_f64_t nk_f64_sqrt_serial(nk_f64_t number) { return number > 0 ? number * nk_f64_rsqrt_serial(number) : 0; }
48
+
49
+ NK_PUBLIC nk_f16_t nk_f16_sqrt_serial(nk_f16_t x) {
50
+ nk_f32_t x_f32;
51
+ nk_f16_to_f32_serial(&x, &x_f32);
52
+ x_f32 = nk_f32_sqrt_serial(x_f32);
53
+ nk_f16_t result;
54
+ nk_f32_to_f16_serial(&x_f32, &result);
55
+ return result;
56
+ }
57
+
58
+ NK_PUBLIC nk_f16_t nk_f16_rsqrt_serial(nk_f16_t x) {
59
+ nk_f32_t x_f32;
60
+ nk_f16_to_f32_serial(&x, &x_f32);
61
+ x_f32 = nk_f32_rsqrt_serial(x_f32);
62
+ nk_f16_t result;
63
+ nk_f32_to_f16_serial(&x_f32, &result);
64
+ return result;
65
+ }
66
+
67
+ /**
68
+ * @brief Software FMA (Fused Multiply-Add) emulation for f64.
69
+ * Computes (multiplicand * multiplier + addend) with improved precision
70
+ * using Dekker's error-free multiplication and Knuth's TwoSum.
71
+ * @sa std::fma, @sa Rust f64::mul_add
72
+ */
73
+ NK_PUBLIC nk_f64_t nk_f64_fma_serial(nk_f64_t multiplicand, nk_f64_t multiplier, nk_f64_t addend) {
74
+ nk_f64_t product = multiplicand * multiplier;
75
+ // Dekker splitting: break each operand into non-overlapping high and low halves
76
+ nk_f64_t const dekker_split = 134217729.0; // 2^27 + 1 for double precision
77
+ nk_f64_t multiplicand_high = dekker_split * multiplicand;
78
+ nk_f64_t multiplicand_low = multiplicand - (multiplicand_high - (multiplicand_high - multiplicand));
79
+ multiplicand_high = multiplicand_high - (multiplicand_high - multiplicand);
80
+ nk_f64_t multiplier_high = dekker_split * multiplier;
81
+ nk_f64_t multiplier_low = multiplier - (multiplier_high - (multiplier_high - multiplier));
82
+ multiplier_high = multiplier_high - (multiplier_high - multiplier);
83
+ // Exact multiplication error from the four cross-products
84
+ nk_f64_t product_error = ((multiplicand_high * multiplier_high - product) + multiplicand_high * multiplier_low +
85
+ multiplicand_low * multiplier_high) +
86
+ multiplicand_low * multiplier_low;
87
+ // Knuth TwoSum: add the addend with error tracking
88
+ nk_f64_t result = product + addend;
89
+ nk_f64_t addend_recovered = result - product;
90
+ nk_f64_t product_recovered = result - addend_recovered;
91
+ nk_f64_t addition_error = (product - product_recovered) + (addend - addend_recovered);
92
+ return result + (product_error + addition_error);
93
+ }
94
+
95
+ /**
96
+ * @brief Software FMA (Fused Multiply-Add) emulation for f32.
97
+ * Computes (multiplicand * multiplier + addend) with improved precision
98
+ * using Dekker's error-free multiplication and Knuth's TwoSum.
99
+ * @sa std::fma, @sa Rust f32::mul_add
100
+ */
101
+ NK_PUBLIC nk_f32_t nk_f32_fma_serial(nk_f32_t multiplicand, nk_f32_t multiplier, nk_f32_t addend) {
102
+ nk_f32_t product = multiplicand * multiplier;
103
+ // Dekker splitting: break each operand into non-overlapping high and low halves
104
+ nk_f32_t const dekker_split = 4097.0f; // 2^12 + 1 for single precision
105
+ nk_f32_t multiplicand_high = dekker_split * multiplicand;
106
+ nk_f32_t multiplicand_low = multiplicand - (multiplicand_high - (multiplicand_high - multiplicand));
107
+ multiplicand_high = multiplicand_high - (multiplicand_high - multiplicand);
108
+ nk_f32_t multiplier_high = dekker_split * multiplier;
109
+ nk_f32_t multiplier_low = multiplier - (multiplier_high - (multiplier_high - multiplier));
110
+ multiplier_high = multiplier_high - (multiplier_high - multiplier);
111
+ // Exact multiplication error from the four cross-products
112
+ nk_f32_t product_error = ((multiplicand_high * multiplier_high - product) + multiplicand_high * multiplier_low +
113
+ multiplicand_low * multiplier_high) +
114
+ multiplicand_low * multiplier_low;
115
+ // Knuth TwoSum: add the addend with error tracking
116
+ nk_f32_t result = product + addend;
117
+ nk_f32_t addend_recovered = result - product;
118
+ nk_f32_t product_recovered = result - addend_recovered;
119
+ nk_f32_t addition_error = (product - product_recovered) + (addend - addend_recovered);
120
+ return result + (product_error + addition_error);
121
+ }
122
+
123
+ /**
124
+ * @brief Scalar Dot2 accumulator: sum += a * b with error compensation.
125
+ * Uses TwoProd (via FMA) and TwoSum error-free transformations.
126
+ * @see Ogita, T., Rump, S.M., Oishi, S. (2005). "Accurate Sum and Dot Product"
127
+ */
128
+ NK_INTERNAL void nk_f64_dot2_(nk_f64_t *sum, nk_f64_t *compensation, nk_f64_t a, nk_f64_t b) NK_STREAMING_COMPATIBLE_ {
129
+ nk_f64_t product = a * b;
130
+ nk_f64_t product_error = nk_f64_fma_serial(a, b, -product);
131
+ nk_f64_t running_sum = *sum + product;
132
+ nk_f64_t recovered_addend = running_sum - *sum;
133
+ nk_f64_t sum_error = (*sum - (running_sum - recovered_addend)) + (product - recovered_addend);
134
+ *sum = running_sum;
135
+ *compensation += sum_error + product_error;
136
+ }
137
+
138
+ NK_PUBLIC nk_f16_t nk_f16_fma_serial(nk_f16_t a, nk_f16_t b, nk_f16_t c) {
139
+ nk_f32_t a_f32, b_f32, c_f32;
140
+ nk_f16_to_f32_serial(&a, &a_f32);
141
+ nk_f16_to_f32_serial(&b, &b_f32);
142
+ nk_f16_to_f32_serial(&c, &c_f32);
143
+ nk_f32_t result_f32 = nk_f32_fma_serial(a_f32, b_f32, c_f32);
144
+ nk_f16_t result;
145
+ nk_f32_to_f16_serial(&result_f32, &result);
146
+ return result;
147
+ }
148
+
149
+ NK_PUBLIC nk_u8_t nk_u8_saturating_add_serial(nk_u8_t a, nk_u8_t b) {
150
+ nk_u16_t result = (nk_u16_t)a + (nk_u16_t)b;
151
+ return (result > 255u) ? (nk_u8_t)255u : (nk_u8_t)result;
152
+ }
153
+ NK_PUBLIC nk_u16_t nk_u16_saturating_add_serial(nk_u16_t a, nk_u16_t b) {
154
+ nk_u32_t result = (nk_u32_t)a + (nk_u32_t)b;
155
+ return (result > 65535u) ? (nk_u16_t)65535u : (nk_u16_t)result;
156
+ }
157
+ NK_PUBLIC nk_u32_t nk_u32_saturating_add_serial(nk_u32_t a, nk_u32_t b) {
158
+ nk_u64_t result = (nk_u64_t)a + (nk_u64_t)b;
159
+ return (result > 4294967295u) ? (nk_u32_t)4294967295u : (nk_u32_t)result;
160
+ }
161
+ NK_PUBLIC nk_u64_t nk_u64_saturating_add_serial(nk_u64_t a, nk_u64_t b) {
162
+ return (a + b < a) ? 18446744073709551615ull : (a + b);
163
+ }
164
+ NK_PUBLIC nk_i8_t nk_i8_saturating_add_serial(nk_i8_t a, nk_i8_t b) {
165
+ nk_i16_t result = (nk_i16_t)a + (nk_i16_t)b;
166
+ return (result > 127) ? 127 : (result < -128 ? -128 : result);
167
+ }
168
+ NK_PUBLIC nk_i16_t nk_i16_saturating_add_serial(nk_i16_t a, nk_i16_t b) {
169
+ nk_i32_t result = (nk_i32_t)a + (nk_i32_t)b;
170
+ return (result > 32767) ? 32767 : (result < -32768 ? -32768 : result);
171
+ }
172
+ NK_PUBLIC nk_i32_t nk_i32_saturating_add_serial(nk_i32_t a, nk_i32_t b) {
173
+ nk_i64_t result = (nk_i64_t)a + (nk_i64_t)b;
174
+ return (result > 2147483647ll) ? 2147483647ll : (result < -2147483648ll ? -2147483648ll : (nk_i32_t)result);
175
+ }
176
+ NK_PUBLIC nk_i64_t nk_i64_saturating_add_serial(nk_i64_t a, nk_i64_t b) {
177
+ //? We can't just write `-9223372036854775808ll`, even though it's the smallest signed 64-bit value.
178
+ //? The compiler will complain about the number being too large for the type, as it will process the
179
+ //? constant and the sign separately. So we use the same hint that compilers use to define the `INT64_MIN`.
180
+ if ((b > 0) && (a > (9223372036854775807ll) - b)) return 9223372036854775807ll;
181
+ if ((b < 0) && (a < (-9223372036854775807ll - 1ll) - b)) return -9223372036854775807ll - 1ll;
182
+ return a + b;
183
+ }
184
+
185
+ NK_PUBLIC nk_u8_t nk_u8_saturating_mul_serial(nk_u8_t a, nk_u8_t b) {
186
+ nk_u16_t result = (nk_u16_t)a * (nk_u16_t)b;
187
+ return (result > 255) ? 255 : (nk_u8_t)result;
188
+ }
189
+
190
+ NK_PUBLIC nk_u16_t nk_u16_saturating_mul_serial(nk_u16_t a, nk_u16_t b) {
191
+ nk_u32_t result = (nk_u32_t)a * (nk_u32_t)b;
192
+ return (result > 65535) ? 65535 : (nk_u16_t)result;
193
+ }
194
+
195
+ NK_PUBLIC nk_u32_t nk_u32_saturating_mul_serial(nk_u32_t a, nk_u32_t b) {
196
+ nk_u64_t result = (nk_u64_t)a * (nk_u64_t)b;
197
+ return (result > 4294967295u) ? 4294967295u : (nk_u32_t)result;
198
+ }
199
+
200
+ NK_PUBLIC nk_u64_t nk_u64_saturating_mul_serial(nk_u64_t a, nk_u64_t b) {
201
+ // Split the inputs into high and low 32-bit parts
202
+ nk_u64_t a_high = a >> 32;
203
+ nk_u64_t a_low = a & 0xFFFFFFFF;
204
+ nk_u64_t b_high = b >> 32;
205
+ nk_u64_t b_low = b & 0xFFFFFFFF;
206
+
207
+ // Compute partial products
208
+ nk_u64_t upper_product = a_high * b_high;
209
+ nk_u64_t cross_ab = a_high * b_low;
210
+ nk_u64_t cross_ba = a_low * b_high;
211
+ nk_u64_t lower_product = a_low * b_low;
212
+
213
+ // Check if the high part of the result overflows
214
+ nk_u64_t cross_sum = cross_ab + cross_ba;
215
+ if (upper_product || (cross_ab >> 32) || (cross_ba >> 32) || (cross_sum < cross_ab) || (cross_sum >> 32))
216
+ return 18446744073709551615ull;
217
+ nk_u64_t result = (cross_sum << 32) + lower_product;
218
+ if (result < lower_product) return 18446744073709551615ull;
219
+ return result;
220
+ }
221
+
222
+ NK_PUBLIC nk_i8_t nk_i8_saturating_mul_serial(nk_i8_t a, nk_i8_t b) {
223
+ nk_i16_t result = (nk_i16_t)a * (nk_i16_t)b;
224
+ return (result > 127) ? 127 : (result < -128 ? -128 : (nk_i8_t)result);
225
+ }
226
+
227
+ NK_PUBLIC nk_i16_t nk_i16_saturating_mul_serial(nk_i16_t a, nk_i16_t b) {
228
+ nk_i32_t result = (nk_i32_t)a * (nk_i32_t)b;
229
+ return (result > 32767) ? 32767 : (result < -32768 ? -32768 : (nk_i16_t)result);
230
+ }
231
+
232
+ NK_PUBLIC nk_i32_t nk_i32_saturating_mul_serial(nk_i32_t a, nk_i32_t b) {
233
+ nk_i64_t result = (nk_i64_t)a * (nk_i64_t)b;
234
+ return (result > 2147483647ll) ? 2147483647ll : (result < -2147483648ll ? -2147483648ll : (nk_i32_t)result);
235
+ }
236
+
237
+ NK_PUBLIC nk_i64_t nk_i64_saturating_mul_serial(nk_i64_t a, nk_i64_t b) {
238
+ int sign = ((a < 0) ^ (b < 0)) ? -1 : 1; // Track the sign of the result
239
+
240
+ // Take absolute values for easy multiplication and overflow detection
241
+ nk_u64_t abs_a = (a < 0) ? (0u - (nk_u64_t)a) : (nk_u64_t)a;
242
+ nk_u64_t abs_b = (b < 0) ? (0u - (nk_u64_t)b) : (nk_u64_t)b;
243
+
244
+ // Split the absolute values into high and low 32-bit parts
245
+ nk_u64_t a_high = abs_a >> 32;
246
+ nk_u64_t a_low = abs_a & 0xFFFFFFFF;
247
+ nk_u64_t b_high = abs_b >> 32;
248
+ nk_u64_t b_low = abs_b & 0xFFFFFFFF;
249
+
250
+ // Compute partial products
251
+ nk_u64_t upper_product = a_high * b_high;
252
+ nk_u64_t cross_ab = a_high * b_low;
253
+ nk_u64_t cross_ba = a_low * b_high;
254
+ nk_u64_t lower_product = a_low * b_low;
255
+
256
+ // Check for overflow and saturate based on sign
257
+ nk_u64_t cross_sum = cross_ab + cross_ba;
258
+ if (upper_product || (cross_ab >> 32) || (cross_ba >> 32) || (cross_sum < cross_ab) || (cross_sum >> 32))
259
+ return (sign > 0) ? 9223372036854775807ll : (-9223372036854775807ll - 1ll);
260
+ // Combine parts if no overflow, then apply the sign
261
+ nk_u64_t result = (cross_sum << 32) + lower_product;
262
+ return (sign < 0) ? -((nk_i64_t)result) : (nk_i64_t)result;
263
+ }
264
+
265
+ NK_PUBLIC nk_i4x2_t nk_i4x2_saturating_add_serial(nk_i4x2_t a, nk_i4x2_t b) {
266
+ nk_i8_t low = nk_i4x2_low_(a) + nk_i4x2_low_(b);
267
+ nk_i8_t high = nk_i4x2_high_(a) + nk_i4x2_high_(b);
268
+ low = (low > 7) ? 7 : (low < -8 ? -8 : low);
269
+ high = (high > 7) ? 7 : (high < -8 ? -8 : high);
270
+ return (nk_i4x2_t)((low & 0x0F) | ((high & 0x0F) << 4));
271
+ }
272
+ NK_PUBLIC nk_u4x2_t nk_u4x2_saturating_add_serial(nk_u4x2_t a, nk_u4x2_t b) {
273
+ nk_u8_t low = nk_u4x2_low_(a) + nk_u4x2_low_(b);
274
+ nk_u8_t high = nk_u4x2_high_(a) + nk_u4x2_high_(b);
275
+ low = (low > 15) ? 15 : low;
276
+ high = (high > 15) ? 15 : high;
277
+ return (nk_u4x2_t)((low & 0x0F) | ((high & 0x0F) << 4));
278
+ }
279
+ NK_PUBLIC nk_i4x2_t nk_i4x2_saturating_mul_serial(nk_i4x2_t a, nk_i4x2_t b) {
280
+ nk_i8_t low = nk_i4x2_low_(a) * nk_i4x2_low_(b);
281
+ nk_i8_t high = nk_i4x2_high_(a) * nk_i4x2_high_(b);
282
+ low = (low > 7) ? 7 : (low < -8 ? -8 : low);
283
+ high = (high > 7) ? 7 : (high < -8 ? -8 : high);
284
+ return (nk_i4x2_t)((low & 0x0F) | ((high & 0x0F) << 4));
285
+ }
286
+ NK_PUBLIC nk_u4x2_t nk_u4x2_saturating_mul_serial(nk_u4x2_t a, nk_u4x2_t b) {
287
+ nk_u8_t low = nk_u4x2_low_(a) * nk_u4x2_low_(b);
288
+ nk_u8_t high = nk_u4x2_high_(a) * nk_u4x2_high_(b);
289
+ low = (low > 15) ? 15 : low;
290
+ high = (high > 15) ? 15 : high;
291
+ return (nk_u4x2_t)((low & 0x0F) | ((high & 0x0F) << 4));
292
+ }
293
+
294
+ NK_PUBLIC int nk_e4m3_order_serial(nk_e4m3_t a, nk_e4m3_t b) {
295
+ int sign_a = a >> 7, sign_b = b >> 7;
296
+ return (a ^ -sign_a) - (b ^ -sign_b);
297
+ }
298
+ NK_PUBLIC int nk_e5m2_order_serial(nk_e5m2_t a, nk_e5m2_t b) {
299
+ int sign_a = a >> 7, sign_b = b >> 7;
300
+ return (a ^ -sign_a) - (b ^ -sign_b);
301
+ }
302
+
303
+ NK_PUBLIC int nk_e2m3_order_serial(nk_e2m3_t a, nk_e2m3_t b) {
304
+ int value_a = a & 0x3F, value_b = b & 0x3F;
305
+ int sign_a = value_a >> 5, sign_b = value_b >> 5;
306
+ return (value_a ^ -sign_a) - (value_b ^ -sign_b);
307
+ }
308
+ NK_PUBLIC int nk_e3m2_order_serial(nk_e3m2_t a, nk_e3m2_t b) {
309
+ int value_a = a & 0x3F, value_b = b & 0x3F;
310
+ int sign_a = value_a >> 5, sign_b = value_b >> 5;
311
+ return (value_a ^ -sign_a) - (value_b ^ -sign_b);
312
+ }
313
+
314
+ NK_PUBLIC int nk_bf16_order_serial(nk_bf16_t a, nk_bf16_t b) {
315
+ nk_fui16_t a_fui, b_fui;
316
+ a_fui.bf = a, b_fui.bf = b;
317
+ int sign_a = a_fui.u >> 15, sign_b = b_fui.u >> 15;
318
+ return ((int)a_fui.u ^ -sign_a) - ((int)b_fui.u ^ -sign_b);
319
+ }
320
+
321
+ NK_PUBLIC int nk_f16_order_serial(nk_f16_t a, nk_f16_t b) {
322
+ nk_fui16_t a_fui, b_fui;
323
+ a_fui.f = a, b_fui.f = b;
324
+ int sign_a = a_fui.u >> 15, sign_b = b_fui.u >> 15;
325
+ return ((int)a_fui.u ^ -sign_a) - ((int)b_fui.u ^ -sign_b);
326
+ }
327
+
328
+ #if defined(__cplusplus)
329
+ } // extern "C"
330
+ #endif
331
+
332
+ #endif // NK_SCALAR_SERIAL_H
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @brief SIMD-accelerated Scalar Math Helpers for WASM.
3
+ * @file include/numkong/scalar/v128relaxed.h
4
+ * @author Ash Vardanian
5
+ * @date March 1, 2026
6
+ *
7
+ * @sa include/numkong/scalar.h
8
+ */
9
+ #ifndef NK_SCALAR_V128RELAXED_H
10
+ #define NK_SCALAR_V128RELAXED_H
11
+
12
+ #if NK_TARGET_V128RELAXED
13
+
14
+ #include "numkong/types.h"
15
+
16
+ #if defined(__cplusplus)
17
+ extern "C" {
18
+ #endif
19
+
20
+ #if defined(__clang__)
21
+ #pragma clang attribute push(__attribute__((target("relaxed-simd"))), apply_to = function)
22
+ #endif
23
+
24
+ NK_PUBLIC nk_f32_t nk_f32_sqrt_v128relaxed(nk_f32_t x) {
25
+ return wasm_f32x4_extract_lane(wasm_f32x4_sqrt(wasm_f32x4_splat(x)), 0);
26
+ }
27
+ NK_PUBLIC nk_f64_t nk_f64_sqrt_v128relaxed(nk_f64_t x) {
28
+ return wasm_f64x2_extract_lane(wasm_f64x2_sqrt(wasm_f64x2_splat(x)), 0);
29
+ }
30
+ NK_PUBLIC nk_f32_t nk_f32_rsqrt_v128relaxed(nk_f32_t x) {
31
+ v128_t sqrt_f32x4 = wasm_f32x4_sqrt(wasm_f32x4_splat(x));
32
+ return wasm_f32x4_extract_lane(wasm_f32x4_div(wasm_f32x4_splat(1.0f), sqrt_f32x4), 0);
33
+ }
34
+ NK_PUBLIC nk_f64_t nk_f64_rsqrt_v128relaxed(nk_f64_t x) {
35
+ v128_t sqrt_f64x2 = wasm_f64x2_sqrt(wasm_f64x2_splat(x));
36
+ return wasm_f64x2_extract_lane(wasm_f64x2_div(wasm_f64x2_splat(1.0), sqrt_f64x2), 0);
37
+ }
38
+ NK_PUBLIC nk_f32_t nk_f32_fma_v128relaxed(nk_f32_t a, nk_f32_t b, nk_f32_t c) {
39
+ v128_t result_f32x4 = wasm_f32x4_relaxed_madd(wasm_f32x4_splat(a), wasm_f32x4_splat(b), wasm_f32x4_splat(c));
40
+ return wasm_f32x4_extract_lane(result_f32x4, 0);
41
+ }
42
+ NK_PUBLIC nk_f64_t nk_f64_fma_v128relaxed(nk_f64_t a, nk_f64_t b, nk_f64_t c) {
43
+ v128_t result_f64x2 = wasm_f64x2_relaxed_madd(wasm_f64x2_splat(a), wasm_f64x2_splat(b), wasm_f64x2_splat(c));
44
+ return wasm_f64x2_extract_lane(result_f64x2, 0);
45
+ }
46
+
47
+ #if defined(__clang__)
48
+ #pragma clang attribute pop
49
+ #endif
50
+
51
+ #if defined(__cplusplus)
52
+ } // extern "C"
53
+ #endif
54
+
55
+ #endif // NK_TARGET_V128RELAXED
56
+ #endif // NK_SCALAR_V128RELAXED_H