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,504 @@
1
+ /**
2
+ * @brief SVE2-accelerated Sparse Vector Operations.
3
+ * @file include/numkong/sparse/sve2.h
4
+ * @author Ash Vardanian
5
+ * @date February 6, 2026
6
+ *
7
+ * @sa include/numkong/sparse.h
8
+ */
9
+ #ifndef NK_SPARSE_SVE2_H
10
+ #define NK_SPARSE_SVE2_H
11
+
12
+ #if NK_TARGET_ARM64_
13
+
14
+ #include "numkong/types.h"
15
+ #include "numkong/reduce/sve.h" // `nk_svaddv_f64_`
16
+
17
+ #if defined(__cplusplus)
18
+ extern "C" {
19
+ #endif
20
+
21
+ /* SVE2 introduces many new integer-oriented instructions, extending some of the NEON functionality
22
+ * to variable-length SVE registers. Those include "compare multiple" intrinsics:
23
+ *
24
+ * - `svmatch[_u16]` that matches each scalar in first vector against all members of a 128-bit lane in the second.
25
+ * - `svhistcnt[_s32]_z` does something similar, performing an inclusive prefix scan.
26
+ * - `svtbx[_u16]` does extended table lookup
27
+ *
28
+ * Other notable instructions:
29
+ *
30
+ * - `DUP`: Broadcast indexed predicate element
31
+ * https://developer.arm.com/documentation/ddi0602/2021-06/SVE-Instructions/DUP--predicate---Broadcast-indexed-predicate-element-?lang=en
32
+ * - `SCLAMP` and `UCLAMP`: clamp values, i.e. combined min+max
33
+ * https://developer.arm.com/documentation/ddi0602/2021-06/SVE-Instructions/SCLAMP--Signed-clamp-to-minimum-maximum-vector-?lang=en
34
+ * https://developer.arm.com/documentation/ddi0602/2021-06/SVE-Instructions/UCLAMP--Unsigned-clamp-to-minimum-maximum-vector-?lang=en
35
+ * - `TBLQ`: Table lookup quadword
36
+ * https://developer.arm.com/documentation/ddi0602/2022-12/SVE-Instructions/TBLQ--Programmable-table-lookup-within-each-quadword-vector-segment--zeroing--?lang=en
37
+ *
38
+ * Great resources for SVE2 intrinsics:
39
+ *
40
+ * > ARM's Scalable Vector Extensions: A Critical Look at SVE2 For Integer Workloads
41
+ * https://gist.github.com/zingaburga/805669eb891c820bd220418ee3f0d6bd
42
+ */
43
+ #if NK_TARGET_SVE2
44
+ #if defined(__clang__)
45
+ #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+sve+sve2"))), apply_to = function)
46
+ #elif defined(__GNUC__)
47
+ #pragma GCC push_options
48
+ #pragma GCC target("arch=armv8.2-a+sve+sve2")
49
+ #endif
50
+
51
+ NK_PUBLIC void nk_sparse_intersect_u16_sve2( //
52
+ nk_u16_t const *a, nk_u16_t const *b, //
53
+ nk_size_t a_length, nk_size_t b_length, //
54
+ nk_u16_t *result, nk_size_t *count) {
55
+
56
+ // A single SVE lane is 128 bits wide, so one lane fits 8 values.
57
+ nk_size_t const register_size = svcnth();
58
+ nk_size_t const lanes_count = register_size / 8;
59
+ nk_size_t a_idx = 0, b_idx = 0;
60
+ nk_size_t c = 0;
61
+
62
+ while (a_idx < a_length && b_idx < b_length) {
63
+ // Load `a_member` and broadcast it, load `b_members_vec` from memory
64
+ svbool_t a_progress_b16x = svwhilelt_b16_u64(a_idx, a_length);
65
+ svbool_t b_progress_b16x = svwhilelt_b16_u64(b_idx, b_length);
66
+ svuint16_t a_u16x = svld1_u16(a_progress_b16x, a + a_idx);
67
+ svuint16_t b_u16x = svld1_u16(b_progress_b16x, b + b_idx);
68
+
69
+ // Intersecting registers with `svmatch_u16` involves a lot of shuffling
70
+ // and comparisons, so we want to avoid it if the slices don't overlap at all..
71
+ nk_u16_t a_min;
72
+ nk_u16_t a_max = svlastb(a_progress_b16x, a_u16x);
73
+ nk_u16_t b_min = svlasta(svpfalse_b(), b_u16x);
74
+ nk_u16_t b_max = svlastb(b_progress_b16x, b_u16x);
75
+
76
+ // If the slices don't overlap, advance the appropriate pointer
77
+ while (a_max < b_min && (a_idx + register_size) <= a_length) {
78
+ a_idx += register_size;
79
+ a_progress_b16x = svwhilelt_b16_u64(a_idx, a_length);
80
+ a_u16x = svld1_u16(a_progress_b16x, a + a_idx);
81
+ a_max = svlastb(a_progress_b16x, a_u16x);
82
+ }
83
+ a_min = svlasta(svpfalse_b(), a_u16x);
84
+ while (b_max < a_min && (b_idx + register_size) <= b_length) {
85
+ b_idx += register_size;
86
+ b_progress_b16x = svwhilelt_b16_u64(b_idx, b_length);
87
+ b_u16x = svld1_u16(b_progress_b16x, b + b_idx);
88
+ b_max = svlastb(b_progress_b16x, b_u16x);
89
+ }
90
+ b_min = svlasta(svpfalse_b(), b_u16x);
91
+
92
+ // Before we evaluate the intersection size, obfurscating the order in `b_u16x`,
93
+ // let's estimate how much we will need to advance the pointers afterwards.
94
+ // For that, we don't even need to broadcast the values in SVE, as the whole
95
+ // register can be compared against a scalar:
96
+ //
97
+ // svuint16_t a_last_broadcasted = svdup_n_u16(a_max);
98
+ // svuint16_t b_last_broadcasted = svdup_n_u16(b_max);
99
+ svbool_t a_mask_b16x = svcmple_n_u16(a_progress_b16x, a_u16x, b_max);
100
+ svbool_t b_mask_b16x = svcmple_n_u16(b_progress_b16x, b_u16x, a_max);
101
+ nk_u64_t a_step = svcntp_b16(a_progress_b16x, a_mask_b16x);
102
+ nk_u64_t b_step = svcntp_b16(b_progress_b16x, b_mask_b16x);
103
+
104
+ // Compare `a_u16x` with each lane of `b_u16x`
105
+ svbool_t equal_mask_b16x = svmatch_u16(a_progress_b16x, a_u16x, b_u16x);
106
+ for (nk_size_t i = 1; i < lanes_count; i++) {
107
+ b_u16x = svext_u16(b_u16x, b_u16x, 8);
108
+ equal_mask_b16x = svorr_z(svptrue_b16(), equal_mask_b16x, svmatch_u16(a_progress_b16x, a_u16x, b_u16x));
109
+ }
110
+ nk_size_t equal_count = svcntp_b16(svptrue_b16(), equal_mask_b16x);
111
+
112
+ // Manually compact and store matching elements (svcompact_u16 is not defined)
113
+ if (result) {
114
+ nk_u16_t a_data[16];
115
+ nk_u16_t mask_data[16];
116
+
117
+ svst1_u16(svptrue_b16(), a_data, a_u16x);
118
+ svst1_u16(svptrue_b16(), mask_data, svdup_n_u16_z(equal_mask_b16x, 1));
119
+
120
+ for (nk_size_t i = 0; i < svcnth(); i++)
121
+ if (mask_data[i]) result[c++] = a_data[i];
122
+ c -= equal_count;
123
+ }
124
+
125
+ // Advance
126
+ a_idx += a_step;
127
+ b_idx += b_step;
128
+ c += equal_count;
129
+ }
130
+ *count = c;
131
+ }
132
+
133
+ NK_PUBLIC void nk_sparse_intersect_u32_sve2( //
134
+ nk_u32_t const *a, nk_u32_t const *b, //
135
+ nk_size_t a_length, nk_size_t b_length, //
136
+ nk_u32_t *result, nk_size_t *count) {
137
+
138
+ // A single SVE lane is 128 bits wide, so one lane fits 4 values.
139
+ nk_size_t const register_size = svcntw();
140
+ nk_size_t const lanes_count = register_size / 4;
141
+ nk_size_t a_idx = 0, b_idx = 0;
142
+ nk_size_t c = 0;
143
+
144
+ while (a_idx < a_length && b_idx < b_length) {
145
+ // Load `a_member` and broadcast it, load `b_members_vec` from memory
146
+ svbool_t a_progress_b32x = svwhilelt_b32_u64(a_idx, a_length);
147
+ svbool_t b_progress_b32x = svwhilelt_b32_u64(b_idx, b_length);
148
+ svuint32_t a_u32x = svld1_u32(a_progress_b32x, a + a_idx);
149
+ svuint32_t b_u32x = svld1_u32(b_progress_b32x, b + b_idx);
150
+
151
+ // Intersecting registers with `svmatch_u16` involves a lot of shuffling
152
+ // and comparisons, so we want to avoid it if the slices don't overlap at all..
153
+ nk_u32_t a_min;
154
+ nk_u32_t a_max = svlastb(a_progress_b32x, a_u32x);
155
+ nk_u32_t b_min = svlasta(svpfalse_b(), b_u32x);
156
+ nk_u32_t b_max = svlastb(b_progress_b32x, b_u32x);
157
+
158
+ // If the slices don't overlap, advance the appropriate pointer
159
+ while (a_max < b_min && (a_idx + register_size) <= a_length) {
160
+ a_idx += register_size;
161
+ a_progress_b32x = svwhilelt_b32_u64(a_idx, a_length);
162
+ a_u32x = svld1_u32(a_progress_b32x, a + a_idx);
163
+ a_max = svlastb(a_progress_b32x, a_u32x);
164
+ }
165
+ a_min = svlasta(svpfalse_b(), a_u32x);
166
+ while (b_max < a_min && (b_idx + register_size) <= b_length) {
167
+ b_idx += register_size;
168
+ b_progress_b32x = svwhilelt_b32_u64(b_idx, b_length);
169
+ b_u32x = svld1_u32(b_progress_b32x, b + b_idx);
170
+ b_max = svlastb(b_progress_b32x, b_u32x);
171
+ }
172
+ b_min = svlasta(svpfalse_b(), b_u32x);
173
+
174
+ // Before we evaluate the intersection size, obfurscating the order in `b_u32x`,
175
+ // let's estimate how much we will need to advance the pointers afterwards.
176
+ // For that, we don't even need to broadcast the values in SVE, as the whole
177
+ // register can be compared against a scalar:
178
+ //
179
+ // svuint32_t a_last_broadcasted = svdup_n_u32(a_max);
180
+ // svuint32_t b_last_broadcasted = svdup_n_u32(b_max);
181
+ svbool_t a_mask_b32x = svcmple_n_u32(a_progress_b32x, a_u32x, b_max);
182
+ svbool_t b_mask_b32x = svcmple_n_u32(b_progress_b32x, b_u32x, a_max);
183
+ nk_u64_t a_step = svcntp_b32(a_progress_b32x, a_mask_b32x);
184
+ nk_u64_t b_step = svcntp_b32(b_progress_b32x, b_mask_b32x);
185
+
186
+ // Comparing `a_u32x` with each lane of `b_u32x` can't be done with `svmatch`,
187
+ // the same way as in `nk_sparse_intersect_u16_sve2`, as that instruction is only
188
+ // available for 8-bit and 16-bit integers.
189
+ //
190
+ // svbool_t equal_mask_b32x = svpfalse_b();
191
+ // for (nk_size_t i = 0; i < register_size; i++) {
192
+ // equal_mask_b32x = svorr_z(svptrue_b32(), equal_mask_b32x, svcmpeq_u32(a_progress, a_u32x, b_u32x));
193
+ // b_u32x = svext_u32(b_u32x, b_u32x, 1);
194
+ // }
195
+ // nk_size_t equal_count = svcntp_b32(a_progress, equal_mask_b32x);
196
+ //
197
+ // Alternatively, one can use histogram instructions, like `svhistcnt_u32_z`.
198
+ // They practically compute the prefix-matching count, which is equivalent to
199
+ // the lower triangle of the row-major intersection matrix.
200
+ // To compute the upper triangle, we can reverse (with `svrev_b32`) the order of
201
+ // elements and repeat the operation, accumulating the results for top and bottom.
202
+ // Let's look at 4x element registers as an example:
203
+ //
204
+ // ⊐ α = {A, B, C, D}, β = {X, Y, Z, W}:
205
+ //
206
+ // hist(α, β): hist(α_rev, β_rev):
207
+ //
208
+ // X Y Z W W Z Y X
209
+ // A 1 0 0 0 D 1 0 0 0
210
+ // B 1 1 0 0 C 1 1 0 0
211
+ // C 1 1 1 0 B 1 1 1 0
212
+ // D 1 1 1 1 A 1 1 1 1
213
+ //
214
+ svuint32_t hist_low_u32x = svhistcnt_u32_z(a_progress_b32x, a_u32x, b_u32x);
215
+ svuint32_t a_rev_u32x = svrev_u32(a_u32x);
216
+ svuint32_t b_rev_u32x = svrev_u32(b_u32x);
217
+ svuint32_t hist_high_u32x = svrev_u32(svhistcnt_u32_z(svptrue_b32(), a_rev_u32x, b_rev_u32x));
218
+ svuint32_t hist_u32x = svorr_u32_x(a_progress_b32x, hist_low_u32x, hist_high_u32x);
219
+ svbool_t equal_mask_b32x = svcmpne_n_u32(a_progress_b32x, hist_u32x, 0);
220
+ nk_size_t equal_count = svcntp_b32(a_progress_b32x, equal_mask_b32x);
221
+
222
+ // Use SVE2 svcompact to compress matching elements and store to result buffer
223
+ if (result) {
224
+ svuint32_t compacted_u32x = svcompact_u32(equal_mask_b32x, a_u32x);
225
+ svbool_t store_predicate_b32x = svwhilelt_b32_u64(0u, equal_count);
226
+ svst1_u32(store_predicate_b32x, result + c, compacted_u32x);
227
+ }
228
+
229
+ // Advance
230
+ a_idx += a_step;
231
+ b_idx += b_step;
232
+ c += equal_count;
233
+ }
234
+ *count = c;
235
+ }
236
+
237
+ NK_PUBLIC void nk_sparse_intersect_u64_sve2( //
238
+ nk_u64_t const *a, nk_u64_t const *b, //
239
+ nk_size_t a_length, nk_size_t b_length, //
240
+ nk_u64_t *result, nk_size_t *count) {
241
+
242
+ // A single SVE lane is 128 bits wide, so one lane fits 2 values.
243
+ nk_size_t const register_size = svcntd();
244
+ nk_size_t const lanes_count = register_size / 2;
245
+ nk_size_t a_idx = 0, b_idx = 0;
246
+ nk_size_t c = 0;
247
+
248
+ while (a_idx < a_length && b_idx < b_length) {
249
+ // Load `a_member` and broadcast it, load `b_members_vec` from memory
250
+ svbool_t a_progress_b64x = svwhilelt_b64_u64(a_idx, a_length);
251
+ svbool_t b_progress_b64x = svwhilelt_b64_u64(b_idx, b_length);
252
+ svuint64_t a_u64x = svld1_u64(a_progress_b64x, a + a_idx);
253
+ svuint64_t b_u64x = svld1_u64(b_progress_b64x, b + b_idx);
254
+
255
+ // Intersecting registers involves comparisons,
256
+ // so we want to avoid it if the slices don't overlap at all.
257
+ nk_u64_t a_min;
258
+ nk_u64_t a_max = svlastb(a_progress_b64x, a_u64x);
259
+ nk_u64_t b_min = svlasta(svpfalse_b(), b_u64x);
260
+ nk_u64_t b_max = svlastb(b_progress_b64x, b_u64x);
261
+
262
+ // If the slices don't overlap, advance the appropriate pointer
263
+ while (a_max < b_min && (a_idx + register_size) <= a_length) {
264
+ a_idx += register_size;
265
+ a_progress_b64x = svwhilelt_b64_u64(a_idx, a_length);
266
+ a_u64x = svld1_u64(a_progress_b64x, a + a_idx);
267
+ a_max = svlastb(a_progress_b64x, a_u64x);
268
+ }
269
+ a_min = svlasta(svpfalse_b(), a_u64x);
270
+ while (b_max < a_min && (b_idx + register_size) <= b_length) {
271
+ b_idx += register_size;
272
+ b_progress_b64x = svwhilelt_b64_u64(b_idx, b_length);
273
+ b_u64x = svld1_u64(b_progress_b64x, b + b_idx);
274
+ b_max = svlastb(b_progress_b64x, b_u64x);
275
+ }
276
+ b_min = svlasta(svpfalse_b(), b_u64x);
277
+
278
+ // Estimate how much we will need to advance the pointers afterwards.
279
+ svbool_t a_mask_b64x = svcmple_n_u64(a_progress_b64x, a_u64x, b_max);
280
+ svbool_t b_mask_b64x = svcmple_n_u64(b_progress_b64x, b_u64x, a_max);
281
+ nk_u64_t a_step = svcntp_b64(a_progress_b64x, a_mask_b64x);
282
+ nk_u64_t b_step = svcntp_b64(b_progress_b64x, b_mask_b64x);
283
+
284
+ // Use histogram instructions like `svhistcnt_u64_z` to compute intersection.
285
+ // They compute the prefix-matching count, equivalent to the lower triangle
286
+ // of the row-major intersection matrix.
287
+ svuint64_t hist_low_u64x = svhistcnt_u64_z(a_progress_b64x, a_u64x, b_u64x);
288
+ svuint64_t a_rev_u64x = svrev_u64(a_u64x);
289
+ svuint64_t b_rev_u64x = svrev_u64(b_u64x);
290
+ svuint64_t hist_high_u64x = svrev_u64(svhistcnt_u64_z(svptrue_b64(), a_rev_u64x, b_rev_u64x));
291
+ svuint64_t hist_u64x = svorr_u64_x(a_progress_b64x, hist_low_u64x, hist_high_u64x);
292
+ svbool_t equal_mask_b64x = svcmpne_n_u64(a_progress_b64x, hist_u64x, 0);
293
+ nk_size_t equal_count = svcntp_b64(a_progress_b64x, equal_mask_b64x);
294
+
295
+ // Use SVE2 svcompact to compress matching elements and store to result buffer
296
+ if (result) {
297
+ svuint64_t compacted_u64x = svcompact_u64(equal_mask_b64x, a_u64x);
298
+ svbool_t store_predicate_b64x = svwhilelt_b64_u64(0u, equal_count);
299
+ svst1_u64(store_predicate_b64x, result + c, compacted_u64x);
300
+ }
301
+
302
+ // Advance
303
+ a_idx += a_step;
304
+ b_idx += b_step;
305
+ c += equal_count;
306
+ }
307
+ *count = c;
308
+ }
309
+
310
+ NK_PUBLIC void nk_sparse_dot_u32f32_sve2( //
311
+ nk_u32_t const *a, nk_u32_t const *b, //
312
+ nk_f32_t const *a_weights, nk_f32_t const *b_weights, //
313
+ nk_size_t a_length, nk_size_t b_length, //
314
+ nk_f64_t *product) {
315
+
316
+ nk_size_t const register_size = svcntw();
317
+ nk_size_t const vector_length_f64 = svcntd();
318
+ nk_size_t a_idx = 0, b_idx = 0;
319
+ svbool_t const predicate_all_b32x = svptrue_b32();
320
+ svbool_t const predicate_all_b64x = svptrue_b64();
321
+ svfloat64_t product_f64x = svdup_f64(0.0);
322
+
323
+ while (a_idx < a_length && b_idx < b_length) {
324
+ // Load indices with progress predicates
325
+ svbool_t a_progress_b32x = svwhilelt_b32_u64(a_idx, a_length);
326
+ svbool_t b_progress_b32x = svwhilelt_b32_u64(b_idx, b_length);
327
+ svuint32_t a_u32x = svld1_u32(a_progress_b32x, a + a_idx);
328
+ svuint32_t b_u32x = svld1_u32(b_progress_b32x, b + b_idx);
329
+
330
+ // Avoid expensive intersection if slices don't overlap at all
331
+ nk_u32_t a_min;
332
+ nk_u32_t a_max = svlastb(a_progress_b32x, a_u32x);
333
+ nk_u32_t b_min = svlasta(svpfalse_b(), b_u32x);
334
+ nk_u32_t b_max = svlastb(b_progress_b32x, b_u32x);
335
+
336
+ // If the slices don't overlap, advance the appropriate pointer
337
+ while (a_max < b_min && (a_idx + register_size) <= a_length) {
338
+ a_idx += register_size;
339
+ a_progress_b32x = svwhilelt_b32_u64(a_idx, a_length);
340
+ a_u32x = svld1_u32(a_progress_b32x, a + a_idx);
341
+ a_max = svlastb(a_progress_b32x, a_u32x);
342
+ }
343
+ a_min = svlasta(svpfalse_b(), a_u32x);
344
+ while (b_max < a_min && (b_idx + register_size) <= b_length) {
345
+ b_idx += register_size;
346
+ b_progress_b32x = svwhilelt_b32_u64(b_idx, b_length);
347
+ b_u32x = svld1_u32(b_progress_b32x, b + b_idx);
348
+ b_max = svlastb(b_progress_b32x, b_u32x);
349
+ }
350
+ b_min = svlasta(svpfalse_b(), b_u32x);
351
+
352
+ // Calculate step sizes before modifying vectors
353
+ svbool_t a_mask_b32x = svcmple_n_u32(a_progress_b32x, a_u32x, b_max);
354
+ svbool_t b_mask_b32x = svcmple_n_u32(b_progress_b32x, b_u32x, a_max);
355
+ nk_u64_t a_step = svcntp_b32(a_progress_b32x, a_mask_b32x);
356
+ nk_u64_t b_step = svcntp_b32(b_progress_b32x, b_mask_b32x);
357
+
358
+ // Use histogram-based intersection (svmatch_u32 doesn't exist)
359
+ svuint32_t hist_low_u32x = svhistcnt_u32_z(a_progress_b32x, a_u32x, b_u32x);
360
+ svuint32_t a_rev_u32x = svrev_u32(a_u32x);
361
+ svuint32_t b_rev_u32x = svrev_u32(b_u32x);
362
+ svuint32_t hist_high_u32x = svrev_u32(svhistcnt_u32_z(predicate_all_b32x, a_rev_u32x, b_rev_u32x));
363
+ svuint32_t hist_u32x = svorr_u32_x(a_progress_b32x, hist_low_u32x, hist_high_u32x);
364
+ svbool_t a_equal_mask_b32x = svcmpne_n_u32(a_progress_b32x, hist_u32x, 0);
365
+ svbool_t a_overlap_mask_b32x = svand_b_z(predicate_all_b32x, a_progress_b32x, a_equal_mask_b32x);
366
+
367
+ if (!svptest_any(a_progress_b32x, a_overlap_mask_b32x)) {
368
+ a_idx += a_step;
369
+ b_idx += b_step;
370
+ continue;
371
+ }
372
+
373
+ // Compute b overlap mask (symmetric histogram: which b elements match something in a)
374
+ svuint32_t b_hist_low_u32x = svhistcnt_u32_z(b_progress_b32x, b_u32x, a_u32x);
375
+ svuint32_t b_hist_high_u32x = svrev_u32(svhistcnt_u32_z(predicate_all_b32x, b_rev_u32x, a_rev_u32x));
376
+ svuint32_t b_hist_u32x = svorr_u32_x(b_progress_b32x, b_hist_low_u32x, b_hist_high_u32x);
377
+ svbool_t b_overlap_mask_b32x = svand_b_z(predicate_all_b32x, b_progress_b32x,
378
+ svcmpne_n_u32(b_progress_b32x, b_hist_u32x, 0));
379
+
380
+ // Compact matching weights — both arrays are sorted, so svcompact
381
+ // preserves relative order and aligns corresponding intersection pairs.
382
+ svfloat32_t a_matched_f32x = svcompact_f32(a_overlap_mask_b32x, svld1_f32(a_progress_b32x, a_weights + a_idx));
383
+ svfloat32_t b_matched_f32x = svcompact_f32(b_overlap_mask_b32x, svld1_f32(b_progress_b32x, b_weights + b_idx));
384
+
385
+ // Widen to f64 and accumulate. svcvt_f64_f32 converts even-indexed f32
386
+ // elements; svcvtlt_f64_f32 converts odd-indexed f32 elements.
387
+ nk_size_t match_count = svcntp_b32(a_progress_b32x, a_overlap_mask_b32x);
388
+ svbool_t pred_even_b64x = svwhilelt_b64_u64(0u, (match_count + 1) / 2);
389
+ svbool_t pred_odd_b64x = svwhilelt_b64_u64(0u, match_count / 2);
390
+ product_f64x = svmla_f64_x(pred_even_b64x, product_f64x, svcvt_f64_f32_x(pred_even_b64x, a_matched_f32x),
391
+ svcvt_f64_f32_x(pred_even_b64x, b_matched_f32x));
392
+ product_f64x = svmla_f64_x(pred_odd_b64x, product_f64x, svcvtlt_f64_f32_x(pred_odd_b64x, a_matched_f32x),
393
+ svcvtlt_f64_f32_x(pred_odd_b64x, b_matched_f32x));
394
+
395
+ // Advance
396
+ a_idx += a_step;
397
+ b_idx += b_step;
398
+ }
399
+ *product = nk_svaddv_f64_(predicate_all_b64x, product_f64x);
400
+ }
401
+
402
+ #if defined(__clang__)
403
+ #pragma clang attribute pop
404
+ #elif defined(__GNUC__)
405
+ #pragma GCC pop_options
406
+ #endif
407
+ #endif // NK_TARGET_SVE2
408
+
409
+ #if NK_TARGET_SVE2 && NK_TARGET_SVEBFDOT
410
+ #if defined(__clang__)
411
+ #pragma clang attribute push(__attribute__((target("arch=armv8.6-a+sve+sve2+bf16"))), apply_to = function)
412
+ #elif defined(__GNUC__)
413
+ #pragma GCC push_options
414
+ #pragma GCC target("arch=armv8.6-a+sve+sve2+bf16")
415
+ #endif
416
+
417
+ NK_PUBLIC void nk_sparse_dot_u16bf16_sve2( //
418
+ nk_u16_t const *a, nk_u16_t const *b, //
419
+ nk_bf16_t const *a_weights, nk_bf16_t const *b_weights, //
420
+ nk_size_t a_length, nk_size_t b_length, //
421
+ nk_f32_t *product) {
422
+
423
+ // A single SVE lane is 128 bits wide, so one lane fits 8 values.
424
+ nk_size_t const register_size = svcnth();
425
+ nk_size_t const lanes_count = register_size / 8;
426
+ nk_size_t a_idx = 0, b_idx = 0;
427
+ svfloat32_t product_f32x = svdupq_n_f32(0.f, 0.f, 0.f, 0.f);
428
+
429
+ while (a_idx < a_length && b_idx < b_length) {
430
+ // Load `a_member` and broadcast it, load `b_members_vec` from memory
431
+ svbool_t a_progress_b16x = svwhilelt_b16_u64(a_idx, a_length);
432
+ svbool_t b_progress_b16x = svwhilelt_b16_u64(b_idx, b_length);
433
+ svuint16_t a_u16x = svld1_u16(a_progress_b16x, a + a_idx);
434
+ svuint16_t b_u16x = svld1_u16(b_progress_b16x, b + b_idx);
435
+
436
+ // Intersecting registers with `svmatch_u16` involves a lot of shuffling
437
+ // and comparisons, so we want to avoid it if the slices don't overlap at all..
438
+ nk_u16_t a_min;
439
+ nk_u16_t a_max = svlastb(a_progress_b16x, a_u16x);
440
+ nk_u16_t b_min = svlasta(svpfalse_b(), b_u16x);
441
+ nk_u16_t b_max = svlastb(b_progress_b16x, b_u16x);
442
+
443
+ // If the slices don't overlap, advance the appropriate pointer
444
+ while (a_max < b_min && (a_idx + register_size) <= a_length) {
445
+ a_idx += register_size;
446
+ a_progress_b16x = svwhilelt_b16_u64(a_idx, a_length);
447
+ a_u16x = svld1_u16(a_progress_b16x, a + a_idx);
448
+ a_max = svlastb(a_progress_b16x, a_u16x);
449
+ }
450
+ a_min = svlasta(svpfalse_b(), a_u16x);
451
+ while (b_max < a_min && (b_idx + register_size) <= b_length) {
452
+ b_idx += register_size;
453
+ b_progress_b16x = svwhilelt_b16_u64(b_idx, b_length);
454
+ b_u16x = svld1_u16(b_progress_b16x, b + b_idx);
455
+ b_max = svlastb(b_progress_b16x, b_u16x);
456
+ }
457
+ b_min = svlasta(svpfalse_b(), b_u16x);
458
+
459
+ // Before we evaluate the intersection size, obfurscating the order in `b_u16x`,
460
+ // let's estimate how much we will need to advance the pointers afterwards.
461
+ // For that, we don't even need to broadcast the values in SVE, as the whole
462
+ // register can be compared against a scalar:
463
+ //
464
+ // svuint16_t a_last_broadcasted = svdup_n_u16(a_max);
465
+ // svuint16_t b_last_broadcasted = svdup_n_u16(b_max);
466
+ svbool_t a_mask_b16x = svcmple_n_u16(a_progress_b16x, a_u16x, b_max);
467
+ svbool_t b_mask_b16x = svcmple_n_u16(b_progress_b16x, b_u16x, a_max);
468
+ nk_u64_t a_step = svcntp_b16(a_progress_b16x, a_mask_b16x);
469
+ nk_u64_t b_step = svcntp_b16(b_progress_b16x, b_mask_b16x);
470
+
471
+ // Compare `a_u16x` with each lane of `b_u16x`
472
+ svbfloat16_t a_weights_bf16x = svld1_bf16(a_progress_b16x, (__bf16 const *)a_weights + a_idx);
473
+ svbfloat16_t b_weights_bf16x = svld1_bf16(b_progress_b16x, (__bf16 const *)b_weights + b_idx);
474
+ for (nk_size_t i = 0; i < lanes_count; i++) {
475
+ svbool_t equal_mask_b16x = svmatch_u16(a_progress_b16x, a_u16x, b_u16x);
476
+ //! The `svsel_bf16` intrinsic is broken in many compilers, not returning the correct type.
477
+ //! So we reinterprete floats as integers and apply `svsel_s16`, but the `svreinterpret_s16_bs16`
478
+ //! and `svreinterpret_bf16_s16` are not always properly defined!
479
+ svint16_t b_equal_weights_s16x = svsel_s16(equal_mask_b16x, svreinterpret_s16_bf16(b_weights_bf16x),
480
+ svdup_n_s16(0));
481
+ product_f32x = svbfdot_f32(product_f32x, a_weights_bf16x, svreinterpret_bf16_s16(b_equal_weights_s16x));
482
+ b_u16x = svext_u16(b_u16x, b_u16x, 8);
483
+ }
484
+
485
+ // Advance
486
+ a_idx += a_step;
487
+ b_idx += b_step;
488
+ }
489
+ *product = nk_svaddv_f32_(svptrue_b32(), product_f32x);
490
+ }
491
+
492
+ #if defined(__clang__)
493
+ #pragma clang attribute pop
494
+ #elif defined(__GNUC__)
495
+ #pragma GCC pop_options
496
+ #endif
497
+ #endif // NK_TARGET_SVE2 && NK_TARGET_SVEBFDOT
498
+
499
+ #if defined(__cplusplus)
500
+ } // extern "C"
501
+ #endif
502
+
503
+ #endif // NK_TARGET_ARM64_
504
+ #endif // NK_SPARSE_SVE2_H