usearch 2.21.3 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) hide show
  1. package/README.md +24 -24
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +7 -7
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +83 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +235 -52
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/dist/cjs/usearch.d.ts +8 -3
  16. package/javascript/dist/cjs/usearch.js +12 -4
  17. package/javascript/dist/esm/usearch.d.ts +8 -3
  18. package/javascript/dist/esm/usearch.js +12 -4
  19. package/javascript/lib.cpp +17 -0
  20. package/javascript/usearch.ts +14 -6
  21. package/numkong/.clang-tidy +30 -0
  22. package/{simsimd → numkong}/.cmake-format.py +18 -0
  23. package/numkong/.editorconfig +12 -0
  24. package/numkong/.git-blame-ignore-revs +123 -0
  25. package/numkong/.mailmap +15 -0
  26. package/numkong/.spi.yml +11 -0
  27. package/numkong/.swift-format +14 -0
  28. package/numkong/CITATION.cff +81 -0
  29. package/numkong/CONTRIBUTING.md +500 -0
  30. package/numkong/Cargo.toml +54 -0
  31. package/numkong/MANIFEST.in +8 -0
  32. package/numkong/Package.swift +84 -0
  33. package/numkong/README.md +569 -0
  34. package/numkong/bench/README.md +217 -0
  35. package/numkong/bench/bench-browser.html +323 -0
  36. package/numkong/bench/bench.cpp +344 -0
  37. package/numkong/bench/bench.hpp +816 -0
  38. package/numkong/bench/bench.js +148 -0
  39. package/numkong/bench/bench.mjs +616 -0
  40. package/numkong/bench/bench_attention.cpp +113 -0
  41. package/numkong/bench/bench_cast.cpp +264 -0
  42. package/numkong/bench/bench_cross_amx.cpp +62 -0
  43. package/numkong/bench/bench_cross_arm.cpp +245 -0
  44. package/numkong/bench/bench_cross_blas.cpp +309 -0
  45. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  46. package/numkong/bench/bench_cross_power.cpp +84 -0
  47. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  48. package/numkong/bench/bench_cross_serial.cpp +151 -0
  49. package/numkong/bench/bench_cross_sme.cpp +163 -0
  50. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  51. package/numkong/bench/bench_cross_x86.cpp +455 -0
  52. package/numkong/bench/bench_curved.cpp +210 -0
  53. package/numkong/bench/bench_dot.cpp +315 -0
  54. package/numkong/bench/bench_each.cpp +503 -0
  55. package/numkong/bench/bench_geospatial.cpp +112 -0
  56. package/numkong/bench/bench_maxsim.cpp +154 -0
  57. package/numkong/bench/bench_mesh.cpp +148 -0
  58. package/numkong/bench/bench_probability.cpp +60 -0
  59. package/numkong/bench/bench_reduce.cpp +371 -0
  60. package/numkong/bench/bench_set.cpp +73 -0
  61. package/numkong/bench/bench_sparse.cpp +198 -0
  62. package/numkong/bench/bench_spatial.cpp +347 -0
  63. package/numkong/bench/bench_trigonometry.cpp +137 -0
  64. package/numkong/bench/swift/Bench.swift +506 -0
  65. package/numkong/binding.gyp +169 -0
  66. package/numkong/build.rs +484 -0
  67. package/numkong/c/dispatch.h +512 -0
  68. package/numkong/c/dispatch_bf16.c +447 -0
  69. package/numkong/c/dispatch_bf16c.c +52 -0
  70. package/numkong/c/dispatch_e2m3.c +296 -0
  71. package/numkong/c/dispatch_e3m2.c +284 -0
  72. package/numkong/c/dispatch_e4m3.c +318 -0
  73. package/numkong/c/dispatch_e5m2.c +316 -0
  74. package/numkong/c/dispatch_f16.c +452 -0
  75. package/numkong/c/dispatch_f16c.c +58 -0
  76. package/numkong/c/dispatch_f32.c +434 -0
  77. package/numkong/c/dispatch_f32c.c +99 -0
  78. package/numkong/c/dispatch_f64.c +348 -0
  79. package/numkong/c/dispatch_f64c.c +98 -0
  80. package/numkong/c/dispatch_i16.c +96 -0
  81. package/numkong/c/dispatch_i32.c +89 -0
  82. package/numkong/c/dispatch_i4.c +153 -0
  83. package/numkong/c/dispatch_i64.c +86 -0
  84. package/numkong/c/dispatch_i8.c +348 -0
  85. package/numkong/c/dispatch_other.c +348 -0
  86. package/numkong/c/dispatch_u1.c +193 -0
  87. package/numkong/c/dispatch_u16.c +124 -0
  88. package/numkong/c/dispatch_u32.c +118 -0
  89. package/numkong/c/dispatch_u4.c +153 -0
  90. package/numkong/c/dispatch_u64.c +102 -0
  91. package/numkong/c/dispatch_u8.c +364 -0
  92. package/numkong/c/numkong.c +940 -0
  93. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  94. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  95. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  96. package/numkong/cmake/nk_math_lib.cmake +46 -0
  97. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  99. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  100. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  101. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  102. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  103. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  104. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  105. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  106. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  107. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  108. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  109. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  110. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  111. package/numkong/include/README.md +643 -0
  112. package/numkong/include/module.modulemap +129 -0
  113. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  114. package/numkong/include/numkong/attention/sme.h +2075 -0
  115. package/numkong/include/numkong/attention.h +49 -0
  116. package/numkong/include/numkong/capabilities.h +930 -0
  117. package/numkong/include/numkong/cast/README.md +262 -0
  118. package/numkong/include/numkong/cast/diamond.h +64 -0
  119. package/numkong/include/numkong/cast/haswell.h +823 -0
  120. package/numkong/include/numkong/cast/icelake.h +475 -0
  121. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  122. package/numkong/include/numkong/cast/neon.h +1174 -0
  123. package/numkong/include/numkong/cast/powervsx.h +449 -0
  124. package/numkong/include/numkong/cast/rvv.h +970 -0
  125. package/numkong/include/numkong/cast/sapphire.h +262 -0
  126. package/numkong/include/numkong/cast/serial.h +2336 -0
  127. package/numkong/include/numkong/cast/skylake.h +915 -0
  128. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  129. package/numkong/include/numkong/cast.h +254 -0
  130. package/numkong/include/numkong/cast.hpp +44 -0
  131. package/numkong/include/numkong/curved/README.md +223 -0
  132. package/numkong/include/numkong/curved/genoa.h +182 -0
  133. package/numkong/include/numkong/curved/haswell.h +276 -0
  134. package/numkong/include/numkong/curved/neon.h +329 -0
  135. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  136. package/numkong/include/numkong/curved/rvv.h +305 -0
  137. package/numkong/include/numkong/curved/serial.h +207 -0
  138. package/numkong/include/numkong/curved/skylake.h +457 -0
  139. package/numkong/include/numkong/curved/smef64.h +530 -0
  140. package/numkong/include/numkong/curved.h +513 -0
  141. package/numkong/include/numkong/curved.hpp +144 -0
  142. package/numkong/include/numkong/dot/README.md +442 -0
  143. package/numkong/include/numkong/dot/alder.h +563 -0
  144. package/numkong/include/numkong/dot/diamond.h +158 -0
  145. package/numkong/include/numkong/dot/genoa.h +289 -0
  146. package/numkong/include/numkong/dot/haswell.h +1723 -0
  147. package/numkong/include/numkong/dot/icelake.h +997 -0
  148. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  149. package/numkong/include/numkong/dot/neon.h +869 -0
  150. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  151. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  152. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  153. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  154. package/numkong/include/numkong/dot/powervsx.h +752 -0
  155. package/numkong/include/numkong/dot/rvv.h +722 -0
  156. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  157. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  158. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  159. package/numkong/include/numkong/dot/sapphire.h +141 -0
  160. package/numkong/include/numkong/dot/serial.h +874 -0
  161. package/numkong/include/numkong/dot/sierra.h +405 -0
  162. package/numkong/include/numkong/dot/skylake.h +1116 -0
  163. package/numkong/include/numkong/dot/sve.h +420 -0
  164. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  165. package/numkong/include/numkong/dot/svehalf.h +168 -0
  166. package/numkong/include/numkong/dot/svesdot.h +90 -0
  167. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  168. package/numkong/include/numkong/dot.h +1136 -0
  169. package/numkong/include/numkong/dot.hpp +94 -0
  170. package/numkong/include/numkong/dots/README.md +496 -0
  171. package/numkong/include/numkong/dots/alder.h +117 -0
  172. package/numkong/include/numkong/dots/diamond.h +86 -0
  173. package/numkong/include/numkong/dots/genoa.h +100 -0
  174. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  175. package/numkong/include/numkong/dots/haswell.h +310 -0
  176. package/numkong/include/numkong/dots/icelake.h +180 -0
  177. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  178. package/numkong/include/numkong/dots/neon.h +123 -0
  179. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  180. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  181. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  182. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  183. package/numkong/include/numkong/dots/powervsx.h +194 -0
  184. package/numkong/include/numkong/dots/rvv.h +2593 -0
  185. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  186. package/numkong/include/numkong/dots/serial.h +2867 -0
  187. package/numkong/include/numkong/dots/sierra.h +100 -0
  188. package/numkong/include/numkong/dots/skylake.h +207 -0
  189. package/numkong/include/numkong/dots/sme.h +5041 -0
  190. package/numkong/include/numkong/dots/smebi32.h +477 -0
  191. package/numkong/include/numkong/dots/smef64.h +1328 -0
  192. package/numkong/include/numkong/dots/smehalf.h +47 -0
  193. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  194. package/numkong/include/numkong/dots.h +3110 -0
  195. package/numkong/include/numkong/dots.hpp +641 -0
  196. package/numkong/include/numkong/each/README.md +465 -0
  197. package/numkong/include/numkong/each/haswell.h +1658 -0
  198. package/numkong/include/numkong/each/icelake.h +272 -0
  199. package/numkong/include/numkong/each/neon.h +1138 -0
  200. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  201. package/numkong/include/numkong/each/neonhalf.h +318 -0
  202. package/numkong/include/numkong/each/rvv.h +1121 -0
  203. package/numkong/include/numkong/each/sapphire.h +343 -0
  204. package/numkong/include/numkong/each/serial.h +282 -0
  205. package/numkong/include/numkong/each/skylake.h +1562 -0
  206. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  207. package/numkong/include/numkong/each.h +2232 -0
  208. package/numkong/include/numkong/each.hpp +434 -0
  209. package/numkong/include/numkong/geospatial/README.md +147 -0
  210. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  211. package/numkong/include/numkong/geospatial/neon.h +615 -0
  212. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  213. package/numkong/include/numkong/geospatial/serial.h +309 -0
  214. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  215. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  216. package/numkong/include/numkong/geospatial.h +453 -0
  217. package/numkong/include/numkong/geospatial.hpp +235 -0
  218. package/numkong/include/numkong/matrix.hpp +336 -0
  219. package/numkong/include/numkong/maxsim/README.md +187 -0
  220. package/numkong/include/numkong/maxsim/alder.h +511 -0
  221. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  222. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  223. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  224. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  225. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  226. package/numkong/include/numkong/maxsim/serial.h +490 -0
  227. package/numkong/include/numkong/maxsim/sme.h +993 -0
  228. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  229. package/numkong/include/numkong/maxsim.h +571 -0
  230. package/numkong/include/numkong/maxsim.hpp +133 -0
  231. package/numkong/include/numkong/mesh/README.md +219 -0
  232. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  233. package/numkong/include/numkong/mesh/neon.h +1821 -0
  234. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  235. package/numkong/include/numkong/mesh/rvv.h +936 -0
  236. package/numkong/include/numkong/mesh/serial.h +721 -0
  237. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  238. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  239. package/numkong/include/numkong/mesh.h +666 -0
  240. package/numkong/include/numkong/mesh.hpp +701 -0
  241. package/numkong/include/numkong/numkong.h +78 -0
  242. package/numkong/include/numkong/numkong.hpp +58 -0
  243. package/numkong/include/numkong/probability/README.md +177 -0
  244. package/numkong/include/numkong/probability/haswell.h +267 -0
  245. package/numkong/include/numkong/probability/neon.h +255 -0
  246. package/numkong/include/numkong/probability/rvv.h +414 -0
  247. package/numkong/include/numkong/probability/serial.h +181 -0
  248. package/numkong/include/numkong/probability/skylake.h +324 -0
  249. package/numkong/include/numkong/probability.h +380 -0
  250. package/numkong/include/numkong/probability.hpp +120 -0
  251. package/numkong/include/numkong/random.h +50 -0
  252. package/numkong/include/numkong/random.hpp +285 -0
  253. package/numkong/include/numkong/reduce/README.md +552 -0
  254. package/numkong/include/numkong/reduce/alder.h +636 -0
  255. package/numkong/include/numkong/reduce/genoa.h +201 -0
  256. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  257. package/numkong/include/numkong/reduce/icelake.h +549 -0
  258. package/numkong/include/numkong/reduce/neon.h +3980 -0
  259. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  260. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  261. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  262. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  263. package/numkong/include/numkong/reduce/serial.h +753 -0
  264. package/numkong/include/numkong/reduce/sierra.h +338 -0
  265. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  266. package/numkong/include/numkong/reduce/sve.h +52 -0
  267. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  268. package/numkong/include/numkong/reduce.h +1582 -0
  269. package/numkong/include/numkong/reduce.hpp +778 -0
  270. package/numkong/include/numkong/scalar/README.md +89 -0
  271. package/numkong/include/numkong/scalar/haswell.h +122 -0
  272. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  273. package/numkong/include/numkong/scalar/neon.h +122 -0
  274. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  275. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  276. package/numkong/include/numkong/scalar/rvv.h +211 -0
  277. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  278. package/numkong/include/numkong/scalar/serial.h +332 -0
  279. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  280. package/numkong/include/numkong/scalar.h +696 -0
  281. package/numkong/include/numkong/set/README.md +179 -0
  282. package/numkong/include/numkong/set/haswell.h +334 -0
  283. package/numkong/include/numkong/set/icelake.h +485 -0
  284. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  285. package/numkong/include/numkong/set/neon.h +363 -0
  286. package/numkong/include/numkong/set/powervsx.h +326 -0
  287. package/numkong/include/numkong/set/rvv.h +226 -0
  288. package/numkong/include/numkong/set/rvvbb.h +117 -0
  289. package/numkong/include/numkong/set/serial.h +174 -0
  290. package/numkong/include/numkong/set/sve.h +187 -0
  291. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  292. package/numkong/include/numkong/set.h +471 -0
  293. package/numkong/include/numkong/set.hpp +114 -0
  294. package/numkong/include/numkong/sets/README.md +149 -0
  295. package/numkong/include/numkong/sets/haswell.h +63 -0
  296. package/numkong/include/numkong/sets/icelake.h +66 -0
  297. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  298. package/numkong/include/numkong/sets/neon.h +61 -0
  299. package/numkong/include/numkong/sets/powervsx.h +65 -0
  300. package/numkong/include/numkong/sets/serial.h +43 -0
  301. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  302. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  303. package/numkong/include/numkong/sets.h +382 -0
  304. package/numkong/include/numkong/sparse/README.md +156 -0
  305. package/numkong/include/numkong/sparse/icelake.h +463 -0
  306. package/numkong/include/numkong/sparse/neon.h +288 -0
  307. package/numkong/include/numkong/sparse/serial.h +117 -0
  308. package/numkong/include/numkong/sparse/sve2.h +504 -0
  309. package/numkong/include/numkong/sparse/turin.h +322 -0
  310. package/numkong/include/numkong/sparse.h +363 -0
  311. package/numkong/include/numkong/sparse.hpp +113 -0
  312. package/numkong/include/numkong/spatial/README.md +439 -0
  313. package/numkong/include/numkong/spatial/alder.h +604 -0
  314. package/numkong/include/numkong/spatial/diamond.h +240 -0
  315. package/numkong/include/numkong/spatial/genoa.h +222 -0
  316. package/numkong/include/numkong/spatial/haswell.h +979 -0
  317. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  318. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  319. package/numkong/include/numkong/spatial/neon.h +846 -0
  320. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  321. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  322. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  323. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  324. package/numkong/include/numkong/spatial/rvv.h +991 -0
  325. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  326. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  327. package/numkong/include/numkong/spatial/serial.h +347 -0
  328. package/numkong/include/numkong/spatial/sierra.h +516 -0
  329. package/numkong/include/numkong/spatial/skylake.h +605 -0
  330. package/numkong/include/numkong/spatial/sve.h +246 -0
  331. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  332. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  333. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  334. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  335. package/numkong/include/numkong/spatial.h +1681 -0
  336. package/numkong/include/numkong/spatial.hpp +183 -0
  337. package/numkong/include/numkong/spatials/README.md +580 -0
  338. package/numkong/include/numkong/spatials/alder.h +94 -0
  339. package/numkong/include/numkong/spatials/diamond.h +82 -0
  340. package/numkong/include/numkong/spatials/genoa.h +94 -0
  341. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  342. package/numkong/include/numkong/spatials/haswell.h +219 -0
  343. package/numkong/include/numkong/spatials/icelake.h +113 -0
  344. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  345. package/numkong/include/numkong/spatials/neon.h +109 -0
  346. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  347. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  348. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  349. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  350. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  351. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  352. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  353. package/numkong/include/numkong/spatials/serial.h +248 -0
  354. package/numkong/include/numkong/spatials/sierra.h +96 -0
  355. package/numkong/include/numkong/spatials/skylake.h +184 -0
  356. package/numkong/include/numkong/spatials/sme.h +1927 -0
  357. package/numkong/include/numkong/spatials/smef64.h +483 -0
  358. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  359. package/numkong/include/numkong/spatials.h +3374 -0
  360. package/numkong/include/numkong/spatials.hpp +509 -0
  361. package/numkong/include/numkong/tensor.hpp +1981 -0
  362. package/numkong/include/numkong/trigonometry/README.md +184 -0
  363. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  364. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  365. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  366. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  367. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  368. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  369. package/numkong/include/numkong/trigonometry.h +467 -0
  370. package/numkong/include/numkong/trigonometry.hpp +166 -0
  371. package/numkong/include/numkong/types.h +1695 -0
  372. package/numkong/include/numkong/types.hpp +6027 -0
  373. package/numkong/include/numkong/vector.hpp +766 -0
  374. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  375. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  376. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  377. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  378. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  380. package/numkong/javascript/README.md +254 -0
  381. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  382. package/numkong/javascript/numkong-browser.ts +40 -0
  383. package/numkong/javascript/numkong-wasm.ts +750 -0
  384. package/numkong/javascript/numkong.c +712 -0
  385. package/numkong/javascript/numkong.ts +613 -0
  386. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  387. package/numkong/javascript/tsconfig-cjs.json +13 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  389. package/numkong/javascript/types.ts +784 -0
  390. package/numkong/numkong.gypi +104 -0
  391. package/numkong/package.json +108 -0
  392. package/numkong/probes/arm_neon.c +8 -0
  393. package/numkong/probes/arm_neon_bfdot.c +9 -0
  394. package/numkong/probes/arm_neon_fhm.c +9 -0
  395. package/numkong/probes/arm_neon_half.c +8 -0
  396. package/numkong/probes/arm_neon_sdot.c +9 -0
  397. package/numkong/probes/arm_neonfp8.c +9 -0
  398. package/numkong/probes/arm_sme.c +16 -0
  399. package/numkong/probes/arm_sme2.c +16 -0
  400. package/numkong/probes/arm_sme2p1.c +16 -0
  401. package/numkong/probes/arm_sme_bf16.c +16 -0
  402. package/numkong/probes/arm_sme_bi32.c +16 -0
  403. package/numkong/probes/arm_sme_f64.c +16 -0
  404. package/numkong/probes/arm_sme_fa64.c +14 -0
  405. package/numkong/probes/arm_sme_half.c +16 -0
  406. package/numkong/probes/arm_sme_lut2.c +15 -0
  407. package/numkong/probes/arm_sve.c +18 -0
  408. package/numkong/probes/arm_sve2.c +20 -0
  409. package/numkong/probes/arm_sve2p1.c +18 -0
  410. package/numkong/probes/arm_sve_bfdot.c +20 -0
  411. package/numkong/probes/arm_sve_half.c +18 -0
  412. package/numkong/probes/arm_sve_sdot.c +21 -0
  413. package/numkong/probes/loongarch_lasx.c +12 -0
  414. package/numkong/probes/power_vsx.c +12 -0
  415. package/numkong/probes/probe.js +127 -0
  416. package/numkong/probes/riscv_rvv.c +14 -0
  417. package/numkong/probes/riscv_rvv_bb.c +15 -0
  418. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  419. package/numkong/probes/riscv_rvv_half.c +14 -0
  420. package/numkong/probes/wasm_v128relaxed.c +11 -0
  421. package/numkong/probes/x86_alder.c +17 -0
  422. package/numkong/probes/x86_diamond.c +17 -0
  423. package/numkong/probes/x86_genoa.c +17 -0
  424. package/numkong/probes/x86_graniteamx.c +19 -0
  425. package/numkong/probes/x86_haswell.c +11 -0
  426. package/numkong/probes/x86_icelake.c +17 -0
  427. package/numkong/probes/x86_sapphire.c +16 -0
  428. package/numkong/probes/x86_sapphireamx.c +18 -0
  429. package/numkong/probes/x86_sierra.c +17 -0
  430. package/numkong/probes/x86_skylake.c +15 -0
  431. package/numkong/probes/x86_turin.c +17 -0
  432. package/numkong/rust/README.md +698 -0
  433. package/numkong/rust/capabilities.rs +96 -0
  434. package/numkong/rust/cast.rs +314 -0
  435. package/numkong/rust/curved.rs +391 -0
  436. package/numkong/rust/each.rs +2721 -0
  437. package/numkong/rust/geospatial.rs +343 -0
  438. package/numkong/rust/matrix.rs +5424 -0
  439. package/numkong/rust/maxsim.rs +540 -0
  440. package/numkong/rust/mesh.rs +837 -0
  441. package/numkong/rust/numkong.rs +409 -0
  442. package/numkong/rust/probability.rs +272 -0
  443. package/numkong/rust/reduce.rs +1249 -0
  444. package/numkong/rust/set.rs +194 -0
  445. package/numkong/rust/sparse.rs +513 -0
  446. package/numkong/rust/spatial.rs +1815 -0
  447. package/numkong/rust/tensor.rs +7565 -0
  448. package/numkong/rust/types.rs +3666 -0
  449. package/numkong/rust/vector.rs +1899 -0
  450. package/numkong/rustfmt.toml +2 -0
  451. package/numkong/swift/Matrix.swift +1388 -0
  452. package/numkong/swift/MaxSim.swift +151 -0
  453. package/numkong/swift/NumKong.swift +283 -0
  454. package/numkong/swift/Numerics.swift +329 -0
  455. package/numkong/swift/README.md +433 -0
  456. package/numkong/swift/Scalar.swift +741 -0
  457. package/numkong/swift/Tensor.swift +209 -0
  458. package/numkong/test/README.md +315 -0
  459. package/numkong/test/playwright.config.ts +16 -0
  460. package/numkong/test/swift/Test.swift +534 -0
  461. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  462. package/numkong/test/test-browser-bundle.html +188 -0
  463. package/numkong/test/test-browser-runner.mjs +43 -0
  464. package/numkong/test/test-browser.html +305 -0
  465. package/numkong/test/test-dtypes.mjs +453 -0
  466. package/numkong/test/test-wasm.mjs +267 -0
  467. package/numkong/test/test.cpp +442 -0
  468. package/numkong/test/test.hpp +580 -0
  469. package/numkong/test/test.mjs +363 -0
  470. package/numkong/test/test_base.py +1041 -0
  471. package/numkong/test/test_cast.cpp +242 -0
  472. package/numkong/test/test_cross.hpp +551 -0
  473. package/numkong/test/test_cross.py +467 -0
  474. package/numkong/test/test_cross_amx.cpp +50 -0
  475. package/numkong/test/test_cross_arm.cpp +225 -0
  476. package/numkong/test/test_cross_blas.cpp +354 -0
  477. package/numkong/test/test_cross_loongarch.cpp +90 -0
  478. package/numkong/test/test_cross_power.cpp +73 -0
  479. package/numkong/test/test_cross_rvv.cpp +109 -0
  480. package/numkong/test/test_cross_serial.cpp +181 -0
  481. package/numkong/test/test_cross_sme.cpp +148 -0
  482. package/numkong/test/test_cross_wasm.cpp +141 -0
  483. package/numkong/test/test_cross_x86.cpp +442 -0
  484. package/numkong/test/test_curved.cpp +182 -0
  485. package/numkong/test/test_curved.py +207 -0
  486. package/numkong/test/test_dot.cpp +353 -0
  487. package/numkong/test/test_dot.py +296 -0
  488. package/numkong/test/test_each.cpp +437 -0
  489. package/numkong/test/test_each.py +756 -0
  490. package/numkong/test/test_geospatial.cpp +155 -0
  491. package/numkong/test/test_geospatial.py +241 -0
  492. package/numkong/test/test_maxsim.cpp +138 -0
  493. package/numkong/test/test_maxsim.py +209 -0
  494. package/numkong/test/test_mesh.cpp +203 -0
  495. package/numkong/test/test_mesh.py +394 -0
  496. package/numkong/test/test_probability.cpp +136 -0
  497. package/numkong/test/test_probability.py +166 -0
  498. package/numkong/test/test_reduce.cpp +563 -0
  499. package/numkong/test/test_reduce.py +781 -0
  500. package/numkong/test/test_set.cpp +151 -0
  501. package/numkong/test/test_set.py +120 -0
  502. package/numkong/test/test_similarities.py +579 -0
  503. package/numkong/test/test_sparse.cpp +121 -0
  504. package/numkong/test/test_sparse.py +118 -0
  505. package/numkong/test/test_spatial.cpp +518 -0
  506. package/numkong/test/test_spatial.py +269 -0
  507. package/numkong/test/test_tensor.cpp +884 -0
  508. package/numkong/test/test_tensor.py +1417 -0
  509. package/numkong/test/test_trigonometry.cpp +156 -0
  510. package/numkong/test/test_trigonometry.py +180 -0
  511. package/package.json +7 -8
  512. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  513. package/prebuilds/linux-arm64/usearch.node +0 -0
  514. package/prebuilds/linux-x64/usearch.node +0 -0
  515. package/fp16/CMakeLists.txt +0 -176
  516. package/fp16/LICENSE +0 -11
  517. package/fp16/README.md +0 -20
  518. package/fp16/bench/alt-element.cc +0 -89
  519. package/fp16/bench/from-alt-array.cc +0 -175
  520. package/fp16/bench/from-ieee-array.cc +0 -399
  521. package/fp16/bench/ieee-element.cc +0 -272
  522. package/fp16/bench/to-alt-array.cc +0 -91
  523. package/fp16/bench/to-ieee-array.cc +0 -303
  524. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  525. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  526. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  527. package/fp16/configure.py +0 -65
  528. package/fp16/confu.yaml +0 -8
  529. package/fp16/include/fp16/__init__.py +0 -0
  530. package/fp16/include/fp16/avx.py +0 -50
  531. package/fp16/include/fp16/avx2.py +0 -53
  532. package/fp16/include/fp16/bitcasts.h +0 -92
  533. package/fp16/include/fp16/fp16.h +0 -451
  534. package/fp16/include/fp16/psimd.h +0 -131
  535. package/fp16/include/fp16.h +0 -11
  536. package/fp16/jni/Android.mk +0 -6
  537. package/fp16/jni/Application.mk +0 -4
  538. package/fp16/test/alt-from-fp32-value.cc +0 -498
  539. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  540. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  541. package/fp16/test/alt-to-fp32-value.cc +0 -348
  542. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  543. package/fp16/test/bitcasts.cc +0 -56
  544. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  545. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  546. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  547. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  548. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  549. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  550. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  551. package/fp16/test/peachpy/stubs.py +0 -38
  552. package/fp16/test/tables.cc +0 -530
  553. package/fp16/test/tables.h +0 -13
  554. package/fp16/third-party/THHalf.h +0 -92
  555. package/fp16/third-party/eigen-half.h +0 -170
  556. package/fp16/third-party/float16-compressor.h +0 -80
  557. package/fp16/third-party/half.hpp +0 -2916
  558. package/fp16/third-party/npy-halffloat.h +0 -328
  559. package/simsimd/.git-blame-ignore-revs +0 -2
  560. package/simsimd/CONTRIBUTING.md +0 -321
  561. package/simsimd/Cargo.toml +0 -49
  562. package/simsimd/MANIFEST.in +0 -4
  563. package/simsimd/Package.swift +0 -28
  564. package/simsimd/README.md +0 -1493
  565. package/simsimd/binding.gyp +0 -35
  566. package/simsimd/build.rs +0 -70
  567. package/simsimd/c/lib.c +0 -374
  568. package/simsimd/include/module.modulemap +0 -4
  569. package/simsimd/include/simsimd/binary.h +0 -486
  570. package/simsimd/include/simsimd/curved.h +0 -1541
  571. package/simsimd/include/simsimd/dot.h +0 -1853
  572. package/simsimd/include/simsimd/elementwise.h +0 -2465
  573. package/simsimd/include/simsimd/geospatial.h +0 -43
  574. package/simsimd/include/simsimd/mesh.h +0 -69
  575. package/simsimd/include/simsimd/probability.h +0 -606
  576. package/simsimd/include/simsimd/simsimd.h +0 -2567
  577. package/simsimd/include/simsimd/sparse.h +0 -1384
  578. package/simsimd/include/simsimd/spatial.h +0 -2335
  579. package/simsimd/include/simsimd/types.h +0 -666
  580. package/simsimd/javascript/fallback.ts +0 -233
  581. package/simsimd/javascript/lib.c +0 -125
  582. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  583. package/simsimd/javascript/simsimd.ts +0 -179
  584. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  585. package/simsimd/package-lock.json +0 -1761
  586. package/simsimd/package.json +0 -61
  587. package/simsimd/rust/lib.rs +0 -1821
  588. package/simsimd/scripts/bench.cxx +0 -1170
  589. package/simsimd/scripts/bench.ipynb +0 -187
  590. package/simsimd/scripts/bench.js +0 -127
  591. package/simsimd/scripts/bench.rs +0 -876
  592. package/simsimd/scripts/bench_vectors.py +0 -734
  593. package/simsimd/scripts/bench_vectors_live.py +0 -213
  594. package/simsimd/scripts/test.c +0 -187
  595. package/simsimd/scripts/test.mjs +0 -220
  596. package/simsimd/scripts/test.py +0 -1505
  597. package/simsimd/swift/SimSIMD.swift +0 -149
  598. package/simsimd/swift/Test.swift +0 -128
  599. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  600. /package/{simsimd → numkong}/LICENSE +0 -0
  601. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  602. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,930 @@
1
+ /**
2
+ * @brief SIMD capability detection and thread configuration.
3
+ * @file include/numkong/capabilities.h
4
+ * @author Ash Vardanian
5
+ * @date February 6, 2026
6
+ *
7
+ * @section x86_targets Choosing x86 Target Generations
8
+ *
9
+ * It's important to provide fine-grained controls over AVX512 families, as they are very fragmented:
10
+ *
11
+ * - Intel Skylake servers: F, CD, VL, DQ, BW
12
+ * - Intel Cascade Lake workstations: F, CD, VL, DQ, BW, VNNI
13
+ * > In other words, it extends Skylake with VNNI support
14
+ * - Intel Sunny Cove (Ice Lake) servers:
15
+ * F, CD, VL, DQ, BW, VNNI, VPOPCNTDQ, IFMA, VBMI, VAES, GFNI, VBMI2, BITALG, VPCLMULQDQ
16
+ * - AMD Zen4 (Genoa):
17
+ * F, CD, VL, DQ, BW, VNNI, VPOPCNTDQ, IFMA, VBMI, VAES, GFNI, VBMI2, BITALG, VPCLMULQDQ, BF16
18
+ * > In other words, it extends Sunny Cove with BF16 support
19
+ * - Intel Golden Cove (Sapphire Rapids): extends Zen4 and Sunny Cove with FP16 support
20
+ * - AMD Zen5 (Turin): makes VP2INTERSECT cool again
21
+ *
22
+ * Intel Palm Cove was an irrelevant intermediate release extending Skylake with IFMA and VBMI.
23
+ * Intel Willow Cove was an irrelevant intermediate release extending Sunny Cove with VP2INTERSECT,
24
+ * which are not supported by other CPUs to date and are only available in Tiger Lake laptops.
25
+ * Intel Cooper Lake was the only intermediary platform, that supported BF16, but not FP16.
26
+ * It's mostly used in 4-socket and 8-socket high-memory configurations.
27
+ *
28
+ * For us, it makes sense to differentiate only these AVX512 generations:
29
+ *
30
+ * 1. Intel Skylake (pre 2019): supports single-precision dot-products.
31
+ * 2. Intel Ice Lake (2019-2021): advanced integer algorithms.
32
+ * 3. AMD Genoa (2023+): brain-floating point support.
33
+ * 4. Intel Sapphire Rapids (2023+): advanced mixed-precision float processing.
34
+ * 5. AMD Turin (2024+): advanced sparse algorithms.
35
+ *
36
+ * Beyond those, we support AVX2 for old Haswell generation CPUs, AVX2+VNNI for Alder Lake (12th/13th gen),
37
+ * and AVX2+VNNI-INT8 for Sierra Forest (adds native signed×signed and unsigned×unsigned 8-bit dot products).
38
+ *
39
+ * To list all available macros for x86, take a recent compiler, like GCC 12 and run:
40
+ * gcc-12 -march=sapphirerapids -dM -E - < /dev/null | egrep "SSE|AVX" | sort
41
+ * On Arm machines you may want to check for other flags:
42
+ * gcc-12 -march=native -dM -E - < /dev/null | egrep "NEON|SVE|FP16|FMA" | sort
43
+ *
44
+ * @section arm_targets Choosing Arm Target Generations
45
+ *
46
+ * Arm CPUs share design IP, but are produced by different vendors, potentially making the platform
47
+ * even more fragmented than x86. There are 2 important families of SIMD extensions - NEON and SVE.
48
+ *
49
+ * - Armv8-A: +fp, +simd
50
+ * - Armv8.1-A: armv8-a, +crc, +lse, +rdma
51
+ * - Armv8.2-A: armv8.1-a
52
+ * - Armv8.3-A: armv8.2-a, +pauth
53
+ * - Armv8.4-A: armv8.3-a, +flagm, +fp16fml, +dotprod
54
+ * - Armv8.5-A: armv8.4-a, +sb, +ssbs, +predres
55
+ * - Armv8.6-A: armv8.5-a, +bf16, +i8mm
56
+ * - Armv8.7-A: armv8.6-a, +ls64
57
+ * - Armv8.8-A: armv8.7-a, +mops
58
+ * - Armv8.9-A: armv8.8-a
59
+ * - Armv9-A: armv8.5-a, +sve, +sve2
60
+ * - Armv9.1-A: armv9-a, +bf16, +i8mm
61
+ * - Armv9.2-A: armv9.1-a, +ls64
62
+ * - Armv9.3-A: armv9.2-a, +mops
63
+ * - Armv9.4-A: armv9.3-a
64
+ *
65
+ * SVE has been optional since Armv8.2-A, but it's a requirement for Armv9.0-A.
66
+ * A 512-bit SVE variant has already been implemented on the Fugaku supercomputer.
67
+ * A more flexible version, 2x256 SVE, was implemented by the AWS Graviton3 ARM processor.
68
+ * Here are the most important recent families of CPU cores designed by Arm:
69
+ *
70
+ * - Neoverse N1: armv8.2-a, extended with Armv8.4 "dotprod" instructions.
71
+ * Used in AWS @b Graviton2 and Ampere @b Altra.
72
+ * https://developer.arm.com/Processors/Neoverse%20N1
73
+ * - Neoverse V1: armv8.4-a, extended with Armv8.6 bfloat/int8 "matmul" instructions.
74
+ * Used in AWS @b Graviton3, which also enables `sve`, `svebf16`, and `svei8mm`.
75
+ * https://developer.arm.com/Processors/Neoverse%20V1
76
+ * - Neoverse V2: armv9.0 with SVE2 and SVE bit-permutes
77
+ * Used in AWS @b Graviton4, NVIDIA @b Grace, Google @b Axion.
78
+ * https://developer.arm.com/Processors/Neoverse%20V2
79
+ * The N2 core is very similar to V2 and is used by Microsoft @b Cobalt.
80
+ * https://developer.arm.com/Processors/Neoverse%20N2
81
+ *
82
+ * On the consumer side, Apple is the biggest player with mobile @b A chips and desktop @b M chips.
83
+ * The M1 implements Armv8.5-A, both M2 and M3 implement Armv8.6-A, and M4 is expected to have Armv9.1-A.
84
+ *
85
+ * @section references References
86
+ *
87
+ * - x86 intrinsics: https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html
88
+ * - Arm intrinsics: https://developer.arm.com/architectures/instruction-sets/intrinsics
89
+ * - Detecting target CPU features at compile time: https://stackoverflow.com/a/28939692/2766161
90
+ */
91
+
92
+ #ifndef NK_CAPABILITIES_H
93
+ #define NK_CAPABILITIES_H
94
+
95
+ #include "numkong/types.h" // `nk_u64_t`, `NK_DEFINED_LINUX_`
96
+
97
+ #define NK_VERSION_MAJOR 7
98
+ #define NK_VERSION_MINOR 5
99
+ #define NK_VERSION_PATCH 0
100
+
101
+ /**
102
+ * @brief Removes compile-time dispatching, and replaces it with runtime dispatching.
103
+ * So the `nk_dot_f32` function will invoke the most advanced backend supported by the CPU,
104
+ * that runs the program, rather than the most advanced backend supported by the CPU
105
+ * used to compile the library or the downstream application.
106
+ */
107
+ #if !defined(NK_DYNAMIC_DISPATCH)
108
+ #define NK_DYNAMIC_DISPATCH (0) // true or false
109
+ #endif
110
+
111
+ // On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
112
+ #if defined(NK_DEFINED_APPLE_)
113
+ #include <fenv.h> // `fesetenv` - part of C 99 standard
114
+ #include <sys/sysctl.h> // `sysctlbyname`
115
+ #endif
116
+
117
+ // Detect POSIX extensions availability for signal handling.
118
+ // POSIX extensions provide `sigaction`, `sigjmp_buf`, and `sigsetjmp` for safe signal handling.
119
+ // These are needed on Linux ARM for safely testing `mrs` instruction availability.
120
+ #if defined(NK_DEFINED_LINUX_) || defined(NK_DEFINED_FREEBSD_)
121
+ #include <unistd.h> // `_POSIX_VERSION`
122
+ #endif
123
+ #if (defined(NK_DEFINED_LINUX_) || defined(NK_DEFINED_FREEBSD_)) && defined(_POSIX_VERSION)
124
+ #include <setjmp.h> // `sigjmp_buf`, `sigsetjmp`, `siglongjmp`
125
+ #include <signal.h> // `sigaction`, `SIGILL`
126
+ #define NK_HAS_POSIX_EXTENSIONS_ 1
127
+ #else
128
+ #define NK_HAS_POSIX_EXTENSIONS_ 0
129
+ #endif
130
+
131
+ // On Linux x86/RISC-V, we need `syscall()` for AMX permission and hwprobe.
132
+ // With `-std=c11` glibc hides `syscall()` behind `_GNU_SOURCE`, but if any
133
+ // system header was included before us, `<features.h>` is already locked.
134
+ // Forward-declare `syscall` directly — it always exists in glibc.
135
+ #if defined(NK_DEFINED_LINUX_) && (NK_TARGET_X8664_ || NK_TARGET_RISCV64_)
136
+ #include <sys/syscall.h> // `SYS_arch_prctl`, `SYS_riscv_hwprobe`
137
+ #ifdef __cplusplus
138
+ extern "C" long syscall(long, ...) noexcept;
139
+ #else
140
+ extern long syscall(long, ...);
141
+ #endif
142
+ #if NK_TARGET_RISCV64_
143
+ #include <sys/auxv.h> // `getauxval`, `AT_HWCAP`
144
+ #endif
145
+ #endif
146
+
147
+ #if defined(NK_DEFINED_LINUX_) && NK_TARGET_LOONGARCH64_
148
+ #include <sys/auxv.h> // `getauxval`, `AT_HWCAP`
149
+ #endif
150
+
151
+ #if defined(NK_DEFINED_LINUX_) && NK_TARGET_POWER64_
152
+ #include <sys/auxv.h> // `getauxval`, `AT_HWCAP`
153
+ #endif
154
+
155
+ // On FreeBSD RISC-V, we use elf_aux_info for capability detection
156
+ #if defined(NK_DEFINED_FREEBSD_) && NK_TARGET_RISCV64_
157
+ #include <sys/auxv.h> // `elf_aux_info`, `AT_HWCAP`
158
+ #endif
159
+
160
+ // On Windows ARM, we use IsProcessorFeaturePresent API for capability detection
161
+ #if defined(NK_DEFINED_WINDOWS_) && NK_TARGET_ARM64_
162
+ #include <processthreadsapi.h> // `IsProcessorFeaturePresent`
163
+ #endif
164
+
165
+ // On WASM with Emscripten, we use EM_JS for runtime capability detection
166
+ #if NK_TARGET_WASM_ && defined(__EMSCRIPTEN__)
167
+ #include <emscripten.h> // `EM_JS`
168
+ #endif
169
+
170
+ #ifdef __cplusplus
171
+ extern "C" {
172
+ #endif
173
+
174
+ /**
175
+ * @brief Enumeration of supported metric kinds.
176
+ * Some have aliases for convenience/discoverability.
177
+ */
178
+ typedef enum {
179
+ nk_kernel_unknown_k = 0, ///< Unknown kernel kind
180
+
181
+ // Classics:
182
+ nk_kernel_dot_k = 'i', ///< Inner product
183
+ nk_kernel_vdot_k = 'v', ///< Complex inner product
184
+ nk_kernel_angular_k = 'a', ///< Angular (cosine) distance
185
+ nk_kernel_euclidean_k = 'e', ///< Euclidean distance
186
+ nk_kernel_sqeuclidean_k = '2', ///< Squared Euclidean distance
187
+
188
+ // Binary:
189
+ nk_kernel_hamming_k = 'h', ///< Hamming (or Manhattan) distance
190
+ nk_kernel_jaccard_k = 'j', ///< Jaccard (or Tanimoto) coefficient
191
+
192
+ // Curved Spaces:
193
+ nk_kernel_bilinear_k = 'b', ///< Bilinear form
194
+ nk_kernel_mahalanobis_k = 'm', ///< Mahalanobis distance
195
+
196
+ // Geospatial:
197
+ nk_kernel_haversine_k = 'o', ///< Haversine distance
198
+ nk_kernel_vincenty_k = 'O', ///< Vincenty distance (ellipsoidal geodesic)
199
+
200
+ // Probability:
201
+ nk_kernel_kld_k = 'k', ///< Kullback-Leibler divergence
202
+ nk_kernel_jsd_k = 's', ///< Jensen-Shannon divergence
203
+
204
+ // Mesh superposition:
205
+ nk_kernel_rmsd_k = 'r', ///< RMSD without optimal superposition
206
+ nk_kernel_kabsch_k = 'K', ///< Kabsch RMSD with optimal rotation
207
+ nk_kernel_umeyama_k = 'U', ///< Umeyama RMSD with optimal rotation and scale
208
+
209
+ // Sparse Sets:
210
+ nk_kernel_sparse_dot_k = 'd', ///< Sparse dot product with weighted indices
211
+ nk_kernel_sparse_intersect_k = 'x', ///< Equivalent to unnormalized Jaccard
212
+
213
+ // BLAS-like operations:
214
+ nk_kernel_each_scale_k = '*', ///< Element-wise Scale
215
+ nk_kernel_each_sum_k = '+', ///< Element-wise Sum
216
+ nk_kernel_each_blend_k = 'w', ///< Element-wise Weighted Sum
217
+ nk_kernel_each_fma_k = 'f', ///< Element-wise Fused Multiply-Add
218
+
219
+ // Trigonometric functions:
220
+ nk_kernel_each_sin_k = 'S', ///< Element-wise sine
221
+ nk_kernel_each_cos_k = 'C', ///< Element-wise cosine
222
+ nk_kernel_each_atan_k = 'A', ///< Element-wise arctangent
223
+
224
+ // Horizontal reductions:
225
+ nk_kernel_reduce_moments_k = 'R', ///< Horizontal moments reduction (sum + sum-of-squares)
226
+ nk_kernel_reduce_minmax_k = 'X', ///< Horizontal minmax reduction (min + argmin + max + argmax)
227
+
228
+ // GEMM-like batched dot products:
229
+ nk_kernel_dots_packed_size_k = 'P', ///< GEMM packed buffer size
230
+ nk_kernel_dots_pack_k = 'Q', ///< GEMM B matrix packing
231
+ nk_kernel_dots_packed_k = 'G', ///< GEMM computation
232
+ nk_kernel_dots_symmetric_k = 'y', ///< Symmetric Gram matrix (A x At)
233
+
234
+ // GEMM-like batched set similarity functions:
235
+ nk_kernel_hammings_packed_k = 'M', ///< Hamming distance computation
236
+ nk_kernel_hammings_symmetric_k = 'Y', ///< Symmetric Hamming distance matrix (A x At)
237
+ nk_kernel_jaccards_packed_k = 'p', ///< Jaccard distance computation
238
+ nk_kernel_jaccards_symmetric_k = 'Z', ///< Symmetric Jaccard distance matrix
239
+
240
+ // GEMM-like batched spatial distances functions:
241
+ nk_kernel_angulars_packed_k = 'N', ///< Batched angular distances (packed B)
242
+ nk_kernel_angulars_symmetric_k = 'n', ///< Symmetric angular distance matrix
243
+ nk_kernel_euclideans_packed_k = 'E', ///< Batched euclidean distances (packed B)
244
+ nk_kernel_euclideans_symmetric_k = 'D', ///< Symmetric euclidean distance matrix
245
+
246
+ // MaxSim late-interaction functions:
247
+ nk_kernel_maxsim_packed_size_k = 'L', ///< MaxSim packed buffer size
248
+ nk_kernel_maxsim_pack_k = 'l', ///< MaxSim vector packing
249
+ nk_kernel_maxsim_packed_k = 'T', ///< MaxSim late-interaction computation
250
+
251
+ nk_kernel_cast_k = '-', ///< Type casting from one type to another
252
+
253
+ } nk_kernel_kind_t;
254
+
255
+ /**
256
+ * @brief 64-bit bitmask representing SIMD capabilities of the target architecture.
257
+ */
258
+ typedef nk_u64_t nk_capability_t;
259
+
260
+ /** @brief Serial (non-SIMD) fallback capability. Always available. */
261
+ #define nk_cap_serial_k ((nk_capability_t)1)
262
+
263
+ /** @brief Mask representing any capability. */
264
+ #define nk_cap_any_k ((nk_capability_t)NK_U64_MAX)
265
+
266
+ #define nk_cap_neon_k ((nk_capability_t)1 << 1)
267
+ #define nk_cap_haswell_k ((nk_capability_t)1 << 2)
268
+ #define nk_cap_skylake_k ((nk_capability_t)1 << 3)
269
+ #define nk_cap_neonhalf_k ((nk_capability_t)1 << 4)
270
+ #define nk_cap_neonsdot_k ((nk_capability_t)1 << 5)
271
+ #define nk_cap_neonfhm_k ((nk_capability_t)1 << 6)
272
+ #define nk_cap_icelake_k ((nk_capability_t)1 << 7)
273
+ #define nk_cap_genoa_k ((nk_capability_t)1 << 8)
274
+ #define nk_cap_neonbfdot_k ((nk_capability_t)1 << 9)
275
+ #define nk_cap_sve_k ((nk_capability_t)1 << 10)
276
+ #define nk_cap_svehalf_k ((nk_capability_t)1 << 11)
277
+ #define nk_cap_svesdot_k ((nk_capability_t)1 << 12)
278
+ #define nk_cap_alder_k ((nk_capability_t)1 << 13)
279
+ #define nk_cap_svebfdot_k ((nk_capability_t)1 << 14)
280
+ #define nk_cap_sve2_k ((nk_capability_t)1 << 15)
281
+ #define nk_cap_v128relaxed_k ((nk_capability_t)1 << 16)
282
+ #define nk_cap_sapphire_k ((nk_capability_t)1 << 17)
283
+ #define nk_cap_sapphireamx_k ((nk_capability_t)1 << 18)
284
+ #define nk_cap_rvv_k ((nk_capability_t)1 << 19)
285
+ #define nk_cap_rvvhalf_k ((nk_capability_t)1 << 20)
286
+ #define nk_cap_rvvbf16_k ((nk_capability_t)1 << 21)
287
+ #define nk_cap_graniteamx_k ((nk_capability_t)1 << 22)
288
+ #define nk_cap_turin_k ((nk_capability_t)1 << 23)
289
+ #define nk_cap_sme_k ((nk_capability_t)1 << 24)
290
+ #define nk_cap_sme2_k ((nk_capability_t)1 << 25)
291
+ #define nk_cap_smef64_k ((nk_capability_t)1 << 26)
292
+ #define nk_cap_smefa64_k ((nk_capability_t)1 << 27)
293
+ #define nk_cap_sve2p1_k ((nk_capability_t)1 << 28)
294
+ #define nk_cap_sme2p1_k ((nk_capability_t)1 << 29)
295
+ #define nk_cap_smehalf_k ((nk_capability_t)1 << 30)
296
+ #define nk_cap_smebf16_k ((nk_capability_t)1 << 31)
297
+ #define nk_cap_smelut2_k ((nk_capability_t)1 << 32)
298
+ #define nk_cap_rvvbb_k ((nk_capability_t)1 << 33)
299
+ #define nk_cap_sierra_k ((nk_capability_t)1 << 34)
300
+ #define nk_cap_smebi32_k ((nk_capability_t)1 << 35)
301
+ #define nk_cap_loongsonasx_k ((nk_capability_t)1 << 36)
302
+ #define nk_cap_powervsx_k ((nk_capability_t)1 << 37)
303
+ #define nk_cap_diamond_k ((nk_capability_t)1 << 38)
304
+ #define nk_cap_neonfp8_k ((nk_capability_t)1 << 39)
305
+
306
+ typedef void (*nk_metric_dense_punned_t)(void const *a, void const *b, nk_size_t dimensions, void *result);
307
+
308
+ typedef void (*nk_sparse_intersect_punned_t)(void const *a, void const *b, nk_size_t a_length, nk_size_t b_length,
309
+ void *result, nk_size_t *count);
310
+
311
+ typedef void (*nk_sparse_dot_punned_t)(void const *a, void const *b, void const *a_weights, void const *b_weights,
312
+ nk_size_t a_length, nk_size_t b_length, void *product);
313
+
314
+ typedef void (*nk_metric_curved_punned_t)(void const *a, void const *b, void const *c, nk_size_t dimensions,
315
+ void *result);
316
+
317
+ typedef void (*nk_metric_geospatial_punned_t)(void const *a_lats, void const *a_lons, void const *b_lats,
318
+ void const *b_lons, nk_size_t count, void *results);
319
+
320
+ typedef void (*nk_each_scale_punned_t)(void const *a, nk_size_t count, void const *alpha, void const *beta, void *y);
321
+
322
+ typedef void (*nk_each_sum_punned_t)(void const *a, void const *b, nk_size_t count, void *y);
323
+
324
+ typedef void (*nk_each_blend_punned_t)(void const *a, void const *b, nk_size_t count, void const *alpha,
325
+ void const *beta, void *y);
326
+
327
+ typedef void (*nk_each_fma_punned_t)(void const *a, void const *b, void const *c, nk_size_t count, void const *alpha,
328
+ void const *beta, void *y);
329
+
330
+ typedef void (*nk_kernel_trigonometry_punned_t)(void const *x, nk_size_t count, void *y);
331
+
332
+ typedef void (*nk_metric_mesh_punned_t)(void const *a, void const *b, nk_size_t points_count, void *a_centroid,
333
+ void *b_centroid, void *rotation, void *scale, void *result);
334
+
335
+ typedef void (*nk_kernel_reduce_moments_punned_t)(void const *data, nk_size_t count, nk_size_t stride_bytes,
336
+ void *sum_ptr, void *sumsq_ptr);
337
+
338
+ typedef void (*nk_kernel_reduce_minmax_punned_t)(void const *data, nk_size_t count, nk_size_t stride_bytes,
339
+ void *min_value, nk_size_t *min_index, void *max_value,
340
+ nk_size_t *max_index);
341
+
342
+ typedef nk_size_t (*nk_dots_packed_size_punned_t)(nk_size_t columns, nk_size_t depth);
343
+
344
+ typedef void (*nk_dots_pack_punned_t)(void const *b, nk_size_t columns, nk_size_t depth, nk_size_t b_stride_bytes,
345
+ void *b_packed);
346
+
347
+ typedef void (*nk_dots_packed_punned_t)(void const *a, void const *b_packed, void *c, nk_size_t rows, nk_size_t columns,
348
+ nk_size_t depth, nk_size_t a_stride_bytes, nk_size_t c_stride_bytes);
349
+
350
+ typedef void (*nk_dots_symmetric_punned_t)(void const *vectors, nk_size_t vectors_count, nk_size_t depth,
351
+ nk_size_t stride_bytes, void *result, nk_size_t result_stride_bytes,
352
+ nk_size_t row_start, nk_size_t row_count);
353
+
354
+ typedef void (*nk_hammings_packed_punned_t)(void const *a, void const *b_packed, void *c, nk_size_t rows,
355
+ nk_size_t columns, nk_size_t depth, nk_size_t a_stride_bytes,
356
+ nk_size_t c_stride_bytes);
357
+
358
+ typedef void (*nk_hammings_symmetric_punned_t)(void const *vectors, nk_size_t vectors_count, nk_size_t depth,
359
+ nk_size_t stride_bytes, void *result, nk_size_t result_stride_bytes,
360
+ nk_size_t row_start, nk_size_t row_count);
361
+
362
+ typedef void (*nk_jaccards_packed_punned_t)(void const *a, void const *b_packed, void *c, nk_size_t rows,
363
+ nk_size_t columns, nk_size_t depth, nk_size_t a_stride_bytes,
364
+ nk_size_t c_stride_bytes);
365
+
366
+ typedef void (*nk_jaccards_symmetric_punned_t)(void const *vectors, nk_size_t vectors_count, nk_size_t depth,
367
+ nk_size_t stride_bytes, void *result, nk_size_t result_stride_bytes,
368
+ nk_size_t row_start, nk_size_t row_count);
369
+
370
+ typedef void (*nk_angulars_packed_punned_t)(void const *a, void const *b_packed, void *c, nk_size_t rows,
371
+ nk_size_t columns, nk_size_t depth, nk_size_t a_stride_bytes,
372
+ nk_size_t c_stride_bytes);
373
+ typedef void (*nk_angulars_symmetric_punned_t)(void const *vectors, nk_size_t vectors_count, nk_size_t depth,
374
+ nk_size_t stride_bytes, void *result, nk_size_t result_stride_bytes,
375
+ nk_size_t row_start, nk_size_t row_count);
376
+ typedef void (*nk_euclideans_packed_punned_t)(void const *a, void const *b_packed, void *c, nk_size_t rows,
377
+ nk_size_t columns, nk_size_t depth, nk_size_t a_stride_bytes,
378
+ nk_size_t c_stride_bytes);
379
+ typedef void (*nk_euclideans_symmetric_punned_t)(void const *vectors, nk_size_t vectors_count, nk_size_t depth,
380
+ nk_size_t stride_bytes, void *result, nk_size_t result_stride_bytes,
381
+ nk_size_t row_start, nk_size_t row_count);
382
+
383
+ typedef void (*nk_maxsim_packed_punned_t)(void const *q_packed, void const *d_packed, nk_size_t query_count,
384
+ nk_size_t document_count, nk_size_t depth, void *result);
385
+
386
+ typedef void (*nk_kernel_cast_punned_t)(void const *from, nk_dtype_t from_type, nk_size_t count, void *to,
387
+ nk_dtype_t to_type);
388
+
389
+ typedef void (*nk_kernel_punned_t)(void *);
390
+
391
+ #if NK_TARGET_X8664_
392
+
393
+ NK_PUBLIC int nk_configure_thread_x86_(nk_capability_t capabilities) {
394
+ #if NK_TARGET_SAPPHIREAMX
395
+ if (capabilities & nk_cap_sapphireamx_k) {
396
+ #if defined(NK_DEFINED_LINUX_)
397
+ // Linux requires explicit permission for AMX tile state via arch_prctl syscall
398
+ int const ARCH_REQ_XCOMP_PERM = 0x1023;
399
+ unsigned long const XFEATURE_XTILEDATA = 18;
400
+ syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_PERM, XFEATURE_XTILEDATA);
401
+ #endif
402
+ // On Windows, AMX tile state is automatically enabled by the OS if hardware supports it.
403
+ // On FreeBSD, no explicit request is needed either.
404
+ nk_unused_(capabilities);
405
+ }
406
+ #else
407
+ nk_unused_(capabilities);
408
+ #endif
409
+ return 1;
410
+ }
411
+
412
+ NK_PUBLIC nk_capability_t nk_capabilities_x8664_(void) {
413
+ union four_registers_t {
414
+ int array[4];
415
+ struct separate_t {
416
+ unsigned eax, ebx, ecx, edx;
417
+ } named;
418
+ } info0, info1, info7, info7sub1;
419
+
420
+ #if defined(_MSC_VER)
421
+ __cpuidex(info0.array, 0, 0);
422
+ __cpuidex(info1.array, 1, 0);
423
+ __cpuidex(info7.array, 7, 0);
424
+ __cpuidex(info7sub1.array, 7, 1);
425
+ #else
426
+ __asm__ __volatile__("cpuid"
427
+ : "=a"(info0.named.eax), "=b"(info0.named.ebx), "=c"(info0.named.ecx), "=d"(info0.named.edx)
428
+ : "a"(0), "c"(0));
429
+ __asm__ __volatile__("cpuid"
430
+ : "=a"(info1.named.eax), "=b"(info1.named.ebx), "=c"(info1.named.ecx), "=d"(info1.named.edx)
431
+ : "a"(1), "c"(0));
432
+ __asm__ __volatile__("cpuid"
433
+ : "=a"(info7.named.eax), "=b"(info7.named.ebx), "=c"(info7.named.ecx), "=d"(info7.named.edx)
434
+ : "a"(7), "c"(0));
435
+ __asm__ __volatile__("cpuid"
436
+ : "=a"(info7sub1.named.eax), "=b"(info7sub1.named.ebx), "=c"(info7sub1.named.ecx),
437
+ "=d"(info7sub1.named.edx)
438
+ : "a"(7), "c"(1));
439
+ #endif
440
+
441
+ unsigned max_leaf = info0.named.eax;
442
+ unsigned supports_avx2 = (info7.named.ebx & 0x00000020) != 0;
443
+ unsigned supports_f16c = (info1.named.ecx & 0x20000000) != 0;
444
+ unsigned supports_fma = (info1.named.ecx & 0x00001000) != 0;
445
+ unsigned supports_avx512f = (info7.named.ebx & 0x00010000) != 0;
446
+ unsigned supports_avx512fp16 = (info7.named.edx & 0x00800000) != 0;
447
+ unsigned supports_avx512vnni = (info7.named.ecx & 0x00000800) != 0;
448
+ unsigned supports_avx512ifma = (info7.named.ebx & 0x00200000) != 0;
449
+ unsigned supports_avx512bitalg = (info7.named.ecx & 0x00001000) != 0;
450
+ unsigned supports_avx512vbmi = (info7.named.ecx & 0x00000002) != 0;
451
+ unsigned supports_avx512vbmi2 = (info7.named.ecx & 0x00000040) != 0;
452
+ unsigned supports_avx512vpopcntdq = (info7.named.ecx & 0x00004000) != 0;
453
+ unsigned supports_avx512bf16 = (info7sub1.named.eax & 0x00000020) != 0;
454
+ unsigned supports_avx512vp2intersect = (info7.named.edx & 0x00000100) != 0;
455
+ unsigned supports_amx_tile = (info7.named.edx & 0x01000000) != 0;
456
+ unsigned supports_amx_bf16 = (info7.named.edx & 0x00400000) != 0;
457
+ unsigned supports_amx_int8 = (info7.named.edx & 0x02000000) != 0;
458
+ unsigned supports_amx_fp16 = (info7sub1.named.eax & 0x00200000) != 0;
459
+ unsigned supports_avxvnni = (info7sub1.named.eax & 0x00000010) != 0;
460
+ unsigned supports_avxvnniint8 = (info7sub1.named.edx & 0x00000010) != 0;
461
+
462
+ // AVX10.2 detection via CPUID leaf 0x24, subleaf 0.
463
+ // EBX[7:0] contains the AVX10 convergent vector ISA version number.
464
+ unsigned supports_avx10v2 = 0;
465
+ if (max_leaf >= 0x24) {
466
+ union four_registers_t info24;
467
+ #if defined(_MSC_VER)
468
+ __cpuidex(info24.array, 0x24, 0);
469
+ #else
470
+ __asm__ __volatile__("cpuid"
471
+ : "=a"(info24.named.eax), "=b"(info24.named.ebx), "=c"(info24.named.ecx),
472
+ "=d"(info24.named.edx)
473
+ : "a"(0x24), "c"(0));
474
+ #endif
475
+ supports_avx10v2 = (info24.named.ebx & 0xFF) >= 2;
476
+ }
477
+
478
+ unsigned supports_haswell = supports_avx2 && supports_f16c && supports_fma;
479
+ unsigned supports_skylake = supports_avx512f;
480
+ unsigned supports_icelake = supports_avx512vnni && supports_avx512ifma && supports_avx512bitalg &&
481
+ supports_avx512vbmi && supports_avx512vbmi2 && supports_avx512vpopcntdq;
482
+ unsigned supports_genoa = supports_avx512bf16;
483
+ unsigned supports_sapphire = supports_avx512fp16;
484
+ unsigned supports_diamond = supports_avx10v2 && supports_sapphire;
485
+ unsigned supports_turin = supports_avx512vp2intersect && supports_avx512bf16;
486
+ unsigned supports_sierra = supports_haswell && supports_avxvnniint8;
487
+ unsigned supports_alder = supports_haswell && supports_avxvnni;
488
+ unsigned supports_sapphireamx = supports_amx_tile && supports_amx_bf16 && supports_amx_int8;
489
+ unsigned supports_graniteamx = supports_sapphireamx && supports_amx_fp16;
490
+
491
+ return (nk_capability_t)((nk_cap_haswell_k * supports_haswell) | (nk_cap_skylake_k * supports_skylake) |
492
+ (nk_cap_icelake_k * supports_icelake) | (nk_cap_genoa_k * supports_genoa) |
493
+ (nk_cap_diamond_k * supports_diamond) | (nk_cap_sapphire_k * supports_sapphire) |
494
+ (nk_cap_turin_k * supports_turin) | (nk_cap_sierra_k * supports_sierra) |
495
+ (nk_cap_alder_k * supports_alder) | (nk_cap_sapphireamx_k * supports_sapphireamx) |
496
+ (nk_cap_graniteamx_k * supports_graniteamx) | (nk_cap_serial_k));
497
+ }
498
+
499
+ #endif // NK_TARGET_X8664_
500
+
501
+ #if NK_TARGET_ARM64_
502
+
503
+ #if NK_HAS_POSIX_EXTENSIONS_
504
+ static sigjmp_buf nk_mrs_arm64_jump_buffer_;
505
+ static void nk_mrs_arm64_sigill_handler_(int sig) {
506
+ nk_unused_(sig);
507
+ siglongjmp(nk_mrs_arm64_jump_buffer_, 1);
508
+ }
509
+ #endif
510
+
511
+ NK_PUBLIC int nk_configure_thread_arm64_(nk_capability_t capabilities) {
512
+ #if defined(_MSC_VER)
513
+ nk_unused_(capabilities);
514
+ return 1;
515
+ #else
516
+ // FPCR.EBF (bit 13) — requires FEAT_EBF16:
517
+ // Enables fused BF16 dot-product semantics for BFDOT/BFMOPA/BFMMLA.
518
+ // Without it, each bf16×bf16 product is individually rounded (Round-to-Odd) before
519
+ // summation (3-way rounding). With EBF=1, intermediates are summed before rounding,
520
+ // matching x86 VDPBF16PS (Genoa/Sapphire Rapids) precision.
521
+ //
522
+ // FPCR.AH (bit 1) — requires FEAT_AFP — is intentionally NOT set:
523
+ // It enables alternate floating-point behavior (FEAT_RPRES: 12-bit FRECPE/FRSQRTE),
524
+ // but also changes sign-bit handling in ways that break CPython's `decimal` module
525
+ // (`Decimal.from_float()` drops the sign of negative values). The FEAT_RPRES benefit
526
+ // (saving one Newton-Raphson iteration) is not worth the process-wide side effects.
527
+ //
528
+ // EBF defaults to 0 on process creation (kernel zeroes FPCR). Setting it is
529
+ // ABI-legal per AAPCS64. Writing this bit on hardware without FEAT_EBF16
530
+ // is unsafe (it is RES0), so we gate on feature detection.
531
+ unsigned long fpcr_desired = 0;
532
+
533
+ #if defined(NK_DEFINED_APPLE_)
534
+ nk_unused_(capabilities);
535
+ size_t sysctl_size = sizeof(unsigned);
536
+ unsigned has_ebf16 = 0;
537
+ if (sysctlbyname("hw.optional.arm.FEAT_EBF16", &has_ebf16, &sysctl_size, NULL, 0) != 0) has_ebf16 = 0;
538
+ if (has_ebf16) fpcr_desired |= (1UL << 13);
539
+
540
+ #elif defined(NK_DEFINED_LINUX_) || defined(NK_DEFINED_FREEBSD_)
541
+ // Read ID registers via MRS. Only safe if MRS is known to work — indicated by
542
+ // capabilities beyond basic NEON (nk_capabilities_arm64_ validated MRS via sigaction probe).
543
+ if (capabilities & ~(nk_cap_neon_k | nk_cap_serial_k)) {
544
+ // FEAT_EBF16: ID_AA64ISAR1_EL1.BF16 bits [47:44] >= 0b0010
545
+ register unsigned long isar1_val __asm__("x0");
546
+ __asm__ __volatile__(".inst 0xD5380620" : "=r"(isar1_val)); // MRS x0, ID_AA64ISAR1_EL1
547
+ if (((isar1_val >> 44) & 0xF) >= 2) fpcr_desired |= (1UL << 13);
548
+ }
549
+ else { nk_unused_(capabilities); }
550
+ #else
551
+ nk_unused_(capabilities);
552
+ #endif
553
+
554
+ if (fpcr_desired) {
555
+ unsigned long fpcr_val;
556
+ __asm__ __volatile__("mrs %0, fpcr" : "=r"(fpcr_val));
557
+ if ((fpcr_val & fpcr_desired) != fpcr_desired) {
558
+ fpcr_val |= fpcr_desired;
559
+ __asm__ __volatile__("msr fpcr, %0" : : "r"(fpcr_val));
560
+ }
561
+ }
562
+ return 1;
563
+ #endif // _MSC_VER
564
+ }
565
+
566
+ NK_PUBLIC nk_capability_t nk_capabilities_arm64_(void) {
567
+ #if defined(NK_DEFINED_APPLE_)
568
+ size_t size = sizeof(unsigned);
569
+ unsigned supports_neon = 0, supports_fp16 = 0, supports_fhm = 0, supports_bf16 = 0, supports_i8mm = 0;
570
+ unsigned supports_sme = 0, supports_sme2 = 0, supports_smef64 = 0, supports_smehalf = 0, supports_sme2p1 = 0,
571
+ supports_smebi32 = 0;
572
+ if (sysctlbyname("hw.optional.neon", &supports_neon, &size, NULL, 0) != 0) supports_neon = 0;
573
+ if (sysctlbyname("hw.optional.arm.FEAT_FP16", &supports_fp16, &size, NULL, 0) != 0) supports_fp16 = 0;
574
+ if (sysctlbyname("hw.optional.arm.FEAT_FHM", &supports_fhm, &size, NULL, 0) != 0) supports_fhm = 0;
575
+ if (sysctlbyname("hw.optional.arm.FEAT_BF16", &supports_bf16, &size, NULL, 0) != 0) supports_bf16 = 0;
576
+ if (sysctlbyname("hw.optional.arm.FEAT_I8MM", &supports_i8mm, &size, NULL, 0) != 0) supports_i8mm = 0;
577
+ if (sysctlbyname("hw.optional.arm.FEAT_SME", &supports_sme, &size, NULL, 0) != 0) supports_sme = 0;
578
+ if (sysctlbyname("hw.optional.arm.FEAT_SME2", &supports_sme2, &size, NULL, 0) != 0) supports_sme2 = 0;
579
+ if (sysctlbyname("hw.optional.arm.FEAT_SME_F64F64", &supports_smef64, &size, NULL, 0) != 0) supports_smef64 = 0;
580
+ if (sysctlbyname("hw.optional.arm.FEAT_SME_F16F16", &supports_smehalf, &size, NULL, 0) != 0) supports_smehalf = 0;
581
+ if (sysctlbyname("hw.optional.arm.FEAT_SME2p1", &supports_sme2p1, &size, NULL, 0) != 0) supports_sme2p1 = 0;
582
+ if (sysctlbyname("hw.optional.arm.SME_BI32I32", &supports_smebi32, &size, NULL, 0) != 0) supports_smebi32 = 0;
583
+
584
+ return (nk_capability_t)((nk_cap_neon_k * (supports_neon)) |
585
+ (nk_cap_neonhalf_k * (supports_neon && supports_fp16)) |
586
+ (nk_cap_neonfhm_k * (supports_neon && supports_fhm)) |
587
+ (nk_cap_neonbfdot_k * (supports_neon && supports_bf16)) |
588
+ (nk_cap_neonsdot_k * (supports_neon && supports_i8mm)) | (nk_cap_sme_k * (supports_sme)) |
589
+ (nk_cap_sme2_k * (supports_sme2)) | (nk_cap_sme2p1_k * (supports_sme2p1)) |
590
+ (nk_cap_smef64_k * (supports_smef64)) | (nk_cap_smehalf_k * (supports_smehalf)) |
591
+ (nk_cap_smebf16_k * (supports_sme)) | (nk_cap_smebi32_k * (supports_smebi32)) |
592
+ (nk_cap_serial_k));
593
+
594
+ #elif defined(NK_DEFINED_LINUX_) || defined(NK_DEFINED_FREEBSD_)
595
+
596
+ #if NK_HAS_POSIX_EXTENSIONS_
597
+ struct sigaction action_new, action_old;
598
+ action_new.sa_handler = nk_mrs_arm64_sigill_handler_;
599
+ sigemptyset(&action_new.sa_mask);
600
+ action_new.sa_flags = 0;
601
+
602
+ int mrs_works = 0;
603
+ if (sigaction(SIGILL, &action_new, &action_old) == 0) {
604
+ if (sigsetjmp(nk_mrs_arm64_jump_buffer_, 1) == 0) {
605
+ register unsigned long midr_value __asm__("x0");
606
+ __asm__ __volatile__(".inst 0xD5380000" : "=r"(midr_value)); // MRS x0, MIDR_EL1
607
+ mrs_works = 1;
608
+ }
609
+ sigaction(SIGILL, &action_old, NULL);
610
+ }
611
+
612
+ if (!mrs_works) return (nk_capability_t)(nk_cap_neon_k | nk_cap_serial_k);
613
+ #else
614
+ return (nk_capability_t)(nk_cap_neon_k | nk_cap_serial_k);
615
+ #endif
616
+
617
+ unsigned long id_aa64isar0_el1 = 0, id_aa64isar1_el1 = 0, id_aa64pfr0_el1 = 0, id_aa64zfr0_el1 = 0,
618
+ id_aa64fpfr0_el1 = 0;
619
+
620
+ register unsigned long __isar0 __asm__("x0");
621
+ __asm__ __volatile__(".inst 0xD5380600" : "=r"(__isar0)); // MRS x0, ID_AA64ISAR0_EL1
622
+ id_aa64isar0_el1 = __isar0;
623
+ unsigned supports_integer_dot_products = ((id_aa64isar0_el1 >> 44) & 0xF) >= 1;
624
+ unsigned supports_fhm = ((id_aa64isar0_el1 >> 48) & 0xF) >= 1;
625
+ register unsigned long __isar1 __asm__("x0");
626
+ __asm__ __volatile__(".inst 0xD5380620" : "=r"(__isar1)); // MRS x0, ID_AA64ISAR1_EL1
627
+ id_aa64isar1_el1 = __isar1;
628
+ unsigned supports_i8mm = ((id_aa64isar1_el1 >> 52) & 0xF) >= 1;
629
+ unsigned supports_bf16 = ((id_aa64isar1_el1 >> 44) & 0xF) >= 1;
630
+
631
+ register unsigned long __pfr0 __asm__("x0");
632
+ __asm__ __volatile__(".inst 0xD5380400" : "=r"(__pfr0)); // MRS x0, ID_AA64PFR0_EL1
633
+ id_aa64pfr0_el1 = __pfr0;
634
+ unsigned supports_sve = ((id_aa64pfr0_el1 >> 32) & 0xF) >= 1;
635
+ unsigned supports_fp16 = ((id_aa64pfr0_el1 >> 20) & 0xF) == 0x1;
636
+ unsigned supports_neon = ((id_aa64pfr0_el1 >> 20) & 0xF) != 0xF;
637
+
638
+ if (supports_sve) {
639
+ register unsigned long __zfr0 __asm__("x0");
640
+ __asm__ __volatile__(".inst 0xD5380480" : "=r"(__zfr0)); // MRS x0, ID_AA64ZFR0_EL1
641
+ id_aa64zfr0_el1 = __zfr0;
642
+ }
643
+ unsigned supports_svesdotmm = ((id_aa64zfr0_el1 >> 44) & 0xF) >= 1;
644
+ unsigned supports_svebfdot = ((id_aa64zfr0_el1 >> 20) & 0xF) >= 1;
645
+ unsigned supports_sve2 = ((id_aa64zfr0_el1) & 0xF) >= 1;
646
+ unsigned supports_sve2p1 = ((id_aa64zfr0_el1) & 0xF) >= 2;
647
+
648
+ register unsigned long __fpfr0 __asm__("x0");
649
+ __asm__ __volatile__(".inst 0xD53804E0" : "=r"(__fpfr0)); // MRS x0, ID_AA64FPFR0_EL1
650
+ id_aa64fpfr0_el1 = __fpfr0;
651
+ unsigned supports_fp8dot4 = ((id_aa64fpfr0_el1 >> 29) & 0x1) >= 1;
652
+
653
+ unsigned long id_aa64pfr1_el1 = 0, id_aa64smfr0_el1 = 0;
654
+ register unsigned long __pfr1 __asm__("x0");
655
+ __asm__ __volatile__(".inst 0xD5380420" : "=r"(__pfr1)); // MRS x0, ID_AA64PFR1_EL1
656
+ id_aa64pfr1_el1 = __pfr1;
657
+ unsigned supports_sme = ((id_aa64pfr1_el1 >> 24) & 0xF) >= 1;
658
+
659
+ unsigned supports_sme2 = 0, supports_sme2p1 = 0;
660
+ unsigned supports_smef64 = 0, supports_smehalf = 0, supports_smebf16 = 0;
661
+ unsigned supports_smebi32 = 0, supports_smelut2 = 0, supports_smefa64 = 0;
662
+ if (supports_sme) {
663
+ // MRS x0, ID_AA64SMFR0_EL1 (S3_0_C0_C4_5) — encoded as raw .inst because some
664
+ // assemblers (Clang 21 in Android NDK r29) reject the symbolic register name.
665
+ // Encoding: 0xD53804A0 = MRS x0, op0=3, op1=0, CRn=0, CRm=4, op2=5, Rt=0.
666
+ register unsigned long __smfr0 __asm__("x0");
667
+ __asm__ __volatile__(".inst 0xD53804A0" : "=r"(__smfr0));
668
+ id_aa64smfr0_el1 = __smfr0;
669
+ unsigned sme_version = (id_aa64smfr0_el1 >> 56) & 0xF;
670
+ supports_sme2 = sme_version >= 1;
671
+ supports_sme2p1 = sme_version >= 2;
672
+ supports_smef64 = (id_aa64smfr0_el1 >> 48) & 0x1;
673
+ supports_smehalf = (id_aa64smfr0_el1 >> 42) & 0x1;
674
+ supports_smebf16 = (id_aa64smfr0_el1 >> 44) & 0x1;
675
+ supports_smebi32 = (id_aa64smfr0_el1 >> 33) & 0x1;
676
+ supports_smefa64 = (id_aa64smfr0_el1 >> 63) & 0x1;
677
+ }
678
+
679
+ return (
680
+ nk_capability_t)((nk_cap_neon_k * (supports_neon)) | (nk_cap_neonhalf_k * (supports_neon && supports_fp16)) |
681
+ (nk_cap_neonfhm_k * (supports_neon && supports_fhm)) |
682
+ (nk_cap_neonbfdot_k * (supports_neon && supports_bf16)) |
683
+ (nk_cap_neonsdot_k * (supports_neon && supports_i8mm && supports_integer_dot_products)) |
684
+ (nk_cap_neonfp8_k * (supports_neon && supports_fp8dot4)) | //
685
+ (nk_cap_sve_k * (supports_sve)) | (nk_cap_svehalf_k * (supports_sve && supports_fp16)) |
686
+ (nk_cap_svebfdot_k * (supports_sve && supports_svebfdot)) |
687
+ (nk_cap_svesdot_k * (supports_sve && supports_svesdotmm)) | (nk_cap_sve2_k * (supports_sve2)) |
688
+ (nk_cap_sve2p1_k * (supports_sve2p1)) | (nk_cap_sme_k * (supports_sme)) |
689
+ (nk_cap_sme2_k * (supports_sme2)) | (nk_cap_sme2p1_k * (supports_sme2p1)) |
690
+ (nk_cap_smef64_k * (supports_smef64)) | (nk_cap_smehalf_k * (supports_smehalf)) |
691
+ (nk_cap_smebf16_k * (supports_smebf16)) | (nk_cap_smebi32_k * (supports_smebi32)) |
692
+ (nk_cap_smefa64_k * (supports_smefa64)) | (nk_cap_serial_k));
693
+ #elif defined(NK_DEFINED_WINDOWS_)
694
+
695
+ unsigned supports_neon = 0, supports_dp = 0;
696
+
697
+ #if defined(PF_ARM_V8_INSTRUCTIONS_AVAILABLE)
698
+ supports_neon = IsProcessorFeaturePresent(PF_ARM_V8_INSTRUCTIONS_AVAILABLE);
699
+ #endif
700
+ #if defined(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE)
701
+ supports_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE);
702
+ #endif
703
+
704
+ return (nk_capability_t)((nk_cap_neon_k * (supports_neon)) | (nk_cap_neonsdot_k * (supports_neon && supports_dp)) |
705
+ (nk_cap_serial_k));
706
+
707
+ #else
708
+ return (nk_capability_t)(nk_cap_neon_k | nk_cap_serial_k);
709
+ #endif
710
+ }
711
+
712
+ #endif // NK_TARGET_ARM64_
713
+
714
+ #if NK_TARGET_RISCV64_
715
+
716
+ NK_PUBLIC nk_capability_t nk_capabilities_riscv64_(void) {
717
+ #if defined(NK_DEFINED_LINUX_)
718
+ unsigned long hwcap = getauxval(AT_HWCAP);
719
+ nk_capability_t caps = nk_cap_serial_k;
720
+ if (hwcap & (1UL << 21)) {
721
+ caps |= nk_cap_rvv_k;
722
+ struct {
723
+ long key;
724
+ unsigned long value;
725
+ } pairs[1] = {{4, 0}};
726
+ if (syscall(258, pairs, 1, 0, (void *)0, 0) == 0) {
727
+ if (pairs[0].value & (1ULL << 30)) caps |= nk_cap_rvvhalf_k;
728
+ if (pairs[0].value & (1ULL << 54)) caps |= nk_cap_rvvbf16_k;
729
+ if (pairs[0].value & (1ULL << 48)) caps |= nk_cap_rvvbb_k; // Zvbb
730
+ }
731
+ }
732
+ return caps;
733
+ #elif defined(NK_DEFINED_FREEBSD_)
734
+ unsigned long hwcap = 0;
735
+ elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap));
736
+ nk_capability_t caps = nk_cap_serial_k;
737
+ if (hwcap & (1UL << 21)) {
738
+ caps |= nk_cap_rvv_k;
739
+ // FreeBSD lacks the Linux hwprobe syscall (258),
740
+ // so zvfh/zvfbfwma/zvbb are compile-time only.
741
+ }
742
+ return caps;
743
+ #else
744
+ return nk_cap_serial_k;
745
+ #endif
746
+ }
747
+
748
+ #endif // NK_TARGET_RISCV64_
749
+
750
+ #if NK_TARGET_LOONGARCH64_
751
+
752
+ NK_PUBLIC nk_capability_t nk_capabilities_loongarch64_(void) {
753
+ #if defined(NK_DEFINED_LINUX_)
754
+ unsigned long hwcap = getauxval(AT_HWCAP);
755
+ nk_capability_t caps = nk_cap_serial_k;
756
+ // LoongArch HWCAP bit 5 = LASX (256-bit SIMD)
757
+ if (hwcap & (1UL << 5)) caps |= nk_cap_loongsonasx_k;
758
+ return caps;
759
+ #else
760
+ return nk_cap_serial_k;
761
+ #endif
762
+ }
763
+
764
+ #endif // NK_TARGET_LOONGARCH64_
765
+
766
+ #if NK_TARGET_POWER64_
767
+
768
+ NK_PUBLIC nk_capability_t nk_capabilities_power64_(void) {
769
+ #if defined(NK_DEFINED_LINUX_)
770
+ unsigned long hwcap = getauxval(AT_HWCAP);
771
+ unsigned long hwcap2 = getauxval(AT_HWCAP2);
772
+ nk_capability_t caps = nk_cap_serial_k;
773
+ nk_unused_(hwcap2);
774
+ // PPC_FEATURE_HAS_VSX = 0x00000080
775
+ if (hwcap & 0x00000080) caps |= nk_cap_powervsx_k;
776
+ return caps;
777
+ #else
778
+ return nk_cap_serial_k;
779
+ #endif
780
+ }
781
+
782
+ #endif // NK_TARGET_POWER64_
783
+
784
+ #if NK_TARGET_WASM_
785
+
786
+ #if defined(__EMSCRIPTEN__) && NK_DYNAMIC_DISPATCH && !defined(NK_PYODIDE_SIDE_MODULE)
787
+ // Standalone Emscripten dynamic dispatch: EM_JS probes defined in c/numkong.c.
788
+ extern int nk_has_v128(void);
789
+ extern int nk_has_relaxed(void);
790
+ #elif defined(__wasi__) && NK_DEFINED_WASI_
791
+ // WASI hosted (NK_WASI_HOSTED=ON): the host provides capability probes via imports.
792
+ __attribute__((__import_module__("env"), __import_name__("nk_has_v128"))) extern int nk_has_v128(void);
793
+ __attribute__((__import_module__("env"), __import_name__("nk_has_relaxed"))) extern int nk_has_relaxed(void);
794
+ #endif
795
+
796
+ NK_PUBLIC nk_capability_t nk_capabilities_v128relaxed_(void) {
797
+ #if ((defined(__EMSCRIPTEN__) && NK_DYNAMIC_DISPATCH) || (defined(__wasi__) && NK_DEFINED_WASI_)) && \
798
+ !defined(NK_PYODIDE_SIDE_MODULE)
799
+ // Hosted environment (Emscripten or WASI with NK_WASI_HOSTED): the host provides
800
+ // runtime probes. Compile-time flags only mean the *compiler* emitted relaxed-SIMD
801
+ // opcodes, not that the current runtime can execute them.
802
+ int has_relaxed = nk_has_relaxed();
803
+ return has_relaxed ? (nk_cap_serial_k | nk_cap_v128relaxed_k) : nk_cap_serial_k;
804
+ #elif defined(__wasm_relaxed_simd__) || defined(__wasm_simd128__)
805
+ // Static WASM or Pyodide side module: if the compiler targeted relaxed SIMD,
806
+ // the runtime must support it (modules with relaxed opcodes fail validation otherwise).
807
+ return nk_cap_serial_k | nk_cap_v128relaxed_k;
808
+ #else
809
+ return nk_cap_serial_k;
810
+ #endif
811
+ }
812
+
813
+ #endif // NK_TARGET_WASM_
814
+
815
+ NK_PUBLIC int nk_configure_thread_(nk_capability_t capabilities) {
816
+ #if NK_TARGET_X8664_
817
+ return nk_configure_thread_x86_(capabilities);
818
+ #endif
819
+ #if NK_TARGET_ARM64_
820
+ return nk_configure_thread_arm64_(capabilities);
821
+ #endif
822
+ nk_unused_(capabilities);
823
+ return 1; // success — no platform-specific thread configuration needed
824
+ }
825
+
826
+ NK_PUBLIC nk_capability_t nk_capabilities_(void) {
827
+ #if NK_TARGET_X8664_
828
+ return nk_capabilities_x8664_();
829
+ #elif NK_TARGET_ARM64_
830
+ return nk_capabilities_arm64_();
831
+ #elif NK_TARGET_RISCV64_
832
+ return nk_capabilities_riscv64_();
833
+ #elif NK_TARGET_LOONGARCH64_
834
+ return nk_capabilities_loongarch64_();
835
+ #elif NK_TARGET_POWER64_
836
+ return nk_capabilities_power64_();
837
+ #elif NK_TARGET_WASM_
838
+ return nk_capabilities_v128relaxed_();
839
+ #else
840
+ return nk_cap_serial_k;
841
+ #endif
842
+ }
843
+
844
+ /**
845
+ * @brief Returns a bitmask of all capabilities the library was compiled with,
846
+ * regardless of whether the current CPU supports them at runtime.
847
+ */
848
+ NK_PUBLIC nk_capability_t nk_capabilities_compiled_(void) {
849
+ nk_capability_t caps = nk_cap_serial_k;
850
+ #if NK_TARGET_X8664_
851
+ caps |= nk_cap_haswell_k * NK_TARGET_HASWELL;
852
+ caps |= nk_cap_skylake_k * NK_TARGET_SKYLAKE;
853
+ caps |= nk_cap_icelake_k * NK_TARGET_ICELAKE;
854
+ caps |= nk_cap_genoa_k * NK_TARGET_GENOA;
855
+ caps |= nk_cap_sapphire_k * NK_TARGET_SAPPHIRE;
856
+ caps |= nk_cap_sapphireamx_k * NK_TARGET_SAPPHIREAMX;
857
+ caps |= nk_cap_graniteamx_k * NK_TARGET_GRANITEAMX;
858
+ caps |= nk_cap_diamond_k * NK_TARGET_DIAMOND;
859
+ caps |= nk_cap_turin_k * NK_TARGET_TURIN;
860
+ caps |= nk_cap_alder_k * NK_TARGET_ALDER;
861
+ caps |= nk_cap_sierra_k * NK_TARGET_SIERRA;
862
+ #endif
863
+ #if NK_TARGET_ARM64_
864
+ caps |= nk_cap_neon_k * NK_TARGET_NEON;
865
+ caps |= nk_cap_neonhalf_k * NK_TARGET_NEONHALF;
866
+ caps |= nk_cap_neonsdot_k * NK_TARGET_NEONSDOT;
867
+ caps |= nk_cap_neonbfdot_k * NK_TARGET_NEONBFDOT;
868
+ caps |= nk_cap_neonfhm_k * NK_TARGET_NEONFHM;
869
+ caps |= nk_cap_neonfp8_k * NK_TARGET_NEONFP8;
870
+ caps |= nk_cap_sve_k * NK_TARGET_SVE;
871
+ caps |= nk_cap_svehalf_k * NK_TARGET_SVEHALF;
872
+ caps |= nk_cap_svesdot_k * NK_TARGET_SVESDOT;
873
+ caps |= nk_cap_svebfdot_k * NK_TARGET_SVEBFDOT;
874
+ caps |= nk_cap_sve2_k * NK_TARGET_SVE2;
875
+ caps |= nk_cap_sve2p1_k * NK_TARGET_SVE2P1;
876
+ caps |= nk_cap_sme_k * NK_TARGET_SME;
877
+ caps |= nk_cap_sme2_k * NK_TARGET_SME2;
878
+ caps |= nk_cap_sme2p1_k * NK_TARGET_SME2P1;
879
+ caps |= nk_cap_smef64_k * NK_TARGET_SMEF64;
880
+ caps |= nk_cap_smehalf_k * NK_TARGET_SMEHALF;
881
+ caps |= nk_cap_smebf16_k * NK_TARGET_SMEBF16;
882
+ caps |= nk_cap_smebi32_k * NK_TARGET_SMEBI32;
883
+ caps |= nk_cap_smelut2_k * NK_TARGET_SMELUT2;
884
+ caps |= nk_cap_smefa64_k * NK_TARGET_SMEFA64;
885
+ #endif
886
+ #if NK_TARGET_RISCV64_
887
+ caps |= nk_cap_rvv_k * NK_TARGET_RVV;
888
+ caps |= nk_cap_rvvhalf_k * NK_TARGET_RVVHALF;
889
+ caps |= nk_cap_rvvbf16_k * NK_TARGET_RVVBF16;
890
+ caps |= nk_cap_rvvbb_k * NK_TARGET_RVVBB;
891
+ #endif
892
+ #if NK_TARGET_LOONGARCH64_
893
+ caps |= nk_cap_loongsonasx_k * NK_TARGET_LOONGSONASX;
894
+ #endif
895
+ #if NK_TARGET_POWER64_
896
+ caps |= nk_cap_powervsx_k * NK_TARGET_POWERVSX;
897
+ #endif
898
+ #if NK_TARGET_WASM_
899
+ caps |= nk_cap_v128relaxed_k * NK_TARGET_V128RELAXED;
900
+ #endif
901
+ return caps;
902
+ }
903
+
904
+ #if NK_DYNAMIC_DISPATCH
905
+
906
+ NK_DYNAMIC nk_capability_t nk_capabilities(void);
907
+ NK_DYNAMIC nk_capability_t nk_capabilities_available(void);
908
+ NK_DYNAMIC nk_capability_t nk_capabilities_compiled(void);
909
+ NK_DYNAMIC int nk_configure_thread(nk_capability_t);
910
+ NK_DYNAMIC int nk_uses_dynamic_dispatch(void);
911
+ NK_DYNAMIC void nk_dispatch_table_update(nk_capability_t);
912
+ NK_DYNAMIC void nk_find_kernel_punned(nk_kernel_kind_t kind, nk_dtype_t dtype, nk_capability_t viable,
913
+ nk_kernel_punned_t *kernel_output, nk_capability_t *capability_output);
914
+
915
+ #else
916
+
917
+ NK_PUBLIC int nk_uses_dynamic_dispatch(void) { return 0; }
918
+ NK_PUBLIC int nk_configure_thread(nk_capability_t c) { return nk_configure_thread_(c); }
919
+ NK_PUBLIC nk_capability_t nk_capabilities(void) { return nk_capabilities_(); }
920
+ NK_PUBLIC nk_capability_t nk_capabilities_available(void) { return nk_capabilities_() & nk_capabilities_compiled_(); }
921
+ NK_PUBLIC nk_capability_t nk_capabilities_compiled(void) { return nk_capabilities_compiled_(); }
922
+ NK_PUBLIC void nk_dispatch_table_update(nk_capability_t caps) { nk_unused_(caps); }
923
+
924
+ #endif
925
+
926
+ #ifdef __cplusplus
927
+ }
928
+
929
+ #endif
930
+ #endif // NK_CAPABILITIES_H