usearch 2.21.4 → 2.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (604) hide show
  1. package/README.md +65 -69
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +8 -8
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +124 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +224 -48
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/README.md +1 -1
  16. package/javascript/dist/cjs/usearch.d.ts +8 -3
  17. package/javascript/dist/cjs/usearch.js +12 -4
  18. package/javascript/dist/esm/usearch.d.ts +8 -3
  19. package/javascript/dist/esm/usearch.js +12 -4
  20. package/javascript/lib.cpp +17 -0
  21. package/javascript/usearch.test.js +117 -94
  22. package/javascript/usearch.ts +14 -6
  23. package/numkong/.clang-tidy +30 -0
  24. package/{simsimd → numkong}/.cmake-format.py +18 -0
  25. package/numkong/.editorconfig +12 -0
  26. package/numkong/.git-blame-ignore-revs +123 -0
  27. package/numkong/.mailmap +15 -0
  28. package/numkong/.spi.yml +11 -0
  29. package/numkong/.swift-format +14 -0
  30. package/numkong/CITATION.cff +81 -0
  31. package/numkong/CONTRIBUTING.md +500 -0
  32. package/numkong/Cargo.toml +54 -0
  33. package/numkong/MANIFEST.in +8 -0
  34. package/numkong/Package.swift +84 -0
  35. package/numkong/README.md +569 -0
  36. package/numkong/bench/README.md +217 -0
  37. package/numkong/bench/bench-browser.html +323 -0
  38. package/numkong/bench/bench.cpp +344 -0
  39. package/numkong/bench/bench.hpp +816 -0
  40. package/numkong/bench/bench.js +148 -0
  41. package/numkong/bench/bench.mjs +616 -0
  42. package/numkong/bench/bench_attention.cpp +113 -0
  43. package/numkong/bench/bench_cast.cpp +264 -0
  44. package/numkong/bench/bench_cross_amx.cpp +62 -0
  45. package/numkong/bench/bench_cross_arm.cpp +245 -0
  46. package/numkong/bench/bench_cross_blas.cpp +309 -0
  47. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  48. package/numkong/bench/bench_cross_power.cpp +84 -0
  49. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  50. package/numkong/bench/bench_cross_serial.cpp +151 -0
  51. package/numkong/bench/bench_cross_sme.cpp +163 -0
  52. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  53. package/numkong/bench/bench_cross_x86.cpp +455 -0
  54. package/numkong/bench/bench_curved.cpp +210 -0
  55. package/numkong/bench/bench_dot.cpp +315 -0
  56. package/numkong/bench/bench_each.cpp +503 -0
  57. package/numkong/bench/bench_geospatial.cpp +112 -0
  58. package/numkong/bench/bench_maxsim.cpp +154 -0
  59. package/numkong/bench/bench_mesh.cpp +148 -0
  60. package/numkong/bench/bench_probability.cpp +60 -0
  61. package/numkong/bench/bench_reduce.cpp +371 -0
  62. package/numkong/bench/bench_set.cpp +73 -0
  63. package/numkong/bench/bench_sparse.cpp +198 -0
  64. package/numkong/bench/bench_spatial.cpp +347 -0
  65. package/numkong/bench/bench_trigonometry.cpp +137 -0
  66. package/numkong/bench/swift/Bench.swift +506 -0
  67. package/numkong/binding.gyp +169 -0
  68. package/numkong/build.rs +484 -0
  69. package/numkong/c/dispatch.h +512 -0
  70. package/numkong/c/dispatch_bf16.c +447 -0
  71. package/numkong/c/dispatch_bf16c.c +52 -0
  72. package/numkong/c/dispatch_e2m3.c +296 -0
  73. package/numkong/c/dispatch_e3m2.c +284 -0
  74. package/numkong/c/dispatch_e4m3.c +318 -0
  75. package/numkong/c/dispatch_e5m2.c +316 -0
  76. package/numkong/c/dispatch_f16.c +452 -0
  77. package/numkong/c/dispatch_f16c.c +58 -0
  78. package/numkong/c/dispatch_f32.c +434 -0
  79. package/numkong/c/dispatch_f32c.c +99 -0
  80. package/numkong/c/dispatch_f64.c +348 -0
  81. package/numkong/c/dispatch_f64c.c +98 -0
  82. package/numkong/c/dispatch_i16.c +96 -0
  83. package/numkong/c/dispatch_i32.c +89 -0
  84. package/numkong/c/dispatch_i4.c +153 -0
  85. package/numkong/c/dispatch_i64.c +86 -0
  86. package/numkong/c/dispatch_i8.c +348 -0
  87. package/numkong/c/dispatch_other.c +348 -0
  88. package/numkong/c/dispatch_u1.c +193 -0
  89. package/numkong/c/dispatch_u16.c +124 -0
  90. package/numkong/c/dispatch_u32.c +118 -0
  91. package/numkong/c/dispatch_u4.c +153 -0
  92. package/numkong/c/dispatch_u64.c +102 -0
  93. package/numkong/c/dispatch_u8.c +364 -0
  94. package/numkong/c/numkong.c +940 -0
  95. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  96. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  97. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_math_lib.cmake +46 -0
  99. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  100. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  101. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  102. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  103. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  104. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  105. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  106. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  107. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  108. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  109. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  110. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  111. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  112. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  113. package/numkong/include/README.md +643 -0
  114. package/numkong/include/module.modulemap +129 -0
  115. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  116. package/numkong/include/numkong/attention/sme.h +2075 -0
  117. package/numkong/include/numkong/attention.h +49 -0
  118. package/numkong/include/numkong/capabilities.h +930 -0
  119. package/numkong/include/numkong/cast/README.md +262 -0
  120. package/numkong/include/numkong/cast/diamond.h +64 -0
  121. package/numkong/include/numkong/cast/haswell.h +823 -0
  122. package/numkong/include/numkong/cast/icelake.h +475 -0
  123. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  124. package/numkong/include/numkong/cast/neon.h +1174 -0
  125. package/numkong/include/numkong/cast/powervsx.h +449 -0
  126. package/numkong/include/numkong/cast/rvv.h +970 -0
  127. package/numkong/include/numkong/cast/sapphire.h +262 -0
  128. package/numkong/include/numkong/cast/serial.h +2336 -0
  129. package/numkong/include/numkong/cast/skylake.h +915 -0
  130. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  131. package/numkong/include/numkong/cast.h +254 -0
  132. package/numkong/include/numkong/cast.hpp +44 -0
  133. package/numkong/include/numkong/curved/README.md +223 -0
  134. package/numkong/include/numkong/curved/genoa.h +182 -0
  135. package/numkong/include/numkong/curved/haswell.h +276 -0
  136. package/numkong/include/numkong/curved/neon.h +329 -0
  137. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  138. package/numkong/include/numkong/curved/rvv.h +305 -0
  139. package/numkong/include/numkong/curved/serial.h +207 -0
  140. package/numkong/include/numkong/curved/skylake.h +457 -0
  141. package/numkong/include/numkong/curved/smef64.h +530 -0
  142. package/numkong/include/numkong/curved.h +513 -0
  143. package/numkong/include/numkong/curved.hpp +144 -0
  144. package/numkong/include/numkong/dot/README.md +442 -0
  145. package/numkong/include/numkong/dot/alder.h +563 -0
  146. package/numkong/include/numkong/dot/diamond.h +158 -0
  147. package/numkong/include/numkong/dot/genoa.h +289 -0
  148. package/numkong/include/numkong/dot/haswell.h +1723 -0
  149. package/numkong/include/numkong/dot/icelake.h +997 -0
  150. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  151. package/numkong/include/numkong/dot/neon.h +869 -0
  152. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  153. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  154. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  155. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  156. package/numkong/include/numkong/dot/powervsx.h +752 -0
  157. package/numkong/include/numkong/dot/rvv.h +722 -0
  158. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  159. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  160. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  161. package/numkong/include/numkong/dot/sapphire.h +141 -0
  162. package/numkong/include/numkong/dot/serial.h +874 -0
  163. package/numkong/include/numkong/dot/sierra.h +405 -0
  164. package/numkong/include/numkong/dot/skylake.h +1116 -0
  165. package/numkong/include/numkong/dot/sve.h +420 -0
  166. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  167. package/numkong/include/numkong/dot/svehalf.h +168 -0
  168. package/numkong/include/numkong/dot/svesdot.h +90 -0
  169. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  170. package/numkong/include/numkong/dot.h +1136 -0
  171. package/numkong/include/numkong/dot.hpp +94 -0
  172. package/numkong/include/numkong/dots/README.md +496 -0
  173. package/numkong/include/numkong/dots/alder.h +117 -0
  174. package/numkong/include/numkong/dots/diamond.h +86 -0
  175. package/numkong/include/numkong/dots/genoa.h +100 -0
  176. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  177. package/numkong/include/numkong/dots/haswell.h +310 -0
  178. package/numkong/include/numkong/dots/icelake.h +180 -0
  179. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  180. package/numkong/include/numkong/dots/neon.h +123 -0
  181. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  182. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  183. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  184. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  185. package/numkong/include/numkong/dots/powervsx.h +194 -0
  186. package/numkong/include/numkong/dots/rvv.h +2593 -0
  187. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  188. package/numkong/include/numkong/dots/serial.h +2867 -0
  189. package/numkong/include/numkong/dots/sierra.h +100 -0
  190. package/numkong/include/numkong/dots/skylake.h +207 -0
  191. package/numkong/include/numkong/dots/sme.h +5041 -0
  192. package/numkong/include/numkong/dots/smebi32.h +477 -0
  193. package/numkong/include/numkong/dots/smef64.h +1328 -0
  194. package/numkong/include/numkong/dots/smehalf.h +47 -0
  195. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  196. package/numkong/include/numkong/dots.h +3110 -0
  197. package/numkong/include/numkong/dots.hpp +641 -0
  198. package/numkong/include/numkong/each/README.md +465 -0
  199. package/numkong/include/numkong/each/haswell.h +1658 -0
  200. package/numkong/include/numkong/each/icelake.h +272 -0
  201. package/numkong/include/numkong/each/neon.h +1138 -0
  202. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  203. package/numkong/include/numkong/each/neonhalf.h +318 -0
  204. package/numkong/include/numkong/each/rvv.h +1121 -0
  205. package/numkong/include/numkong/each/sapphire.h +343 -0
  206. package/numkong/include/numkong/each/serial.h +282 -0
  207. package/numkong/include/numkong/each/skylake.h +1562 -0
  208. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  209. package/numkong/include/numkong/each.h +2232 -0
  210. package/numkong/include/numkong/each.hpp +434 -0
  211. package/numkong/include/numkong/geospatial/README.md +147 -0
  212. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  213. package/numkong/include/numkong/geospatial/neon.h +615 -0
  214. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  215. package/numkong/include/numkong/geospatial/serial.h +309 -0
  216. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  217. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  218. package/numkong/include/numkong/geospatial.h +453 -0
  219. package/numkong/include/numkong/geospatial.hpp +235 -0
  220. package/numkong/include/numkong/matrix.hpp +336 -0
  221. package/numkong/include/numkong/maxsim/README.md +187 -0
  222. package/numkong/include/numkong/maxsim/alder.h +511 -0
  223. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  224. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  225. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  226. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  227. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  228. package/numkong/include/numkong/maxsim/serial.h +490 -0
  229. package/numkong/include/numkong/maxsim/sme.h +993 -0
  230. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  231. package/numkong/include/numkong/maxsim.h +571 -0
  232. package/numkong/include/numkong/maxsim.hpp +133 -0
  233. package/numkong/include/numkong/mesh/README.md +219 -0
  234. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  235. package/numkong/include/numkong/mesh/neon.h +1821 -0
  236. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  237. package/numkong/include/numkong/mesh/rvv.h +936 -0
  238. package/numkong/include/numkong/mesh/serial.h +721 -0
  239. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  240. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  241. package/numkong/include/numkong/mesh.h +666 -0
  242. package/numkong/include/numkong/mesh.hpp +701 -0
  243. package/numkong/include/numkong/numkong.h +78 -0
  244. package/numkong/include/numkong/numkong.hpp +58 -0
  245. package/numkong/include/numkong/probability/README.md +177 -0
  246. package/numkong/include/numkong/probability/haswell.h +267 -0
  247. package/numkong/include/numkong/probability/neon.h +255 -0
  248. package/numkong/include/numkong/probability/rvv.h +414 -0
  249. package/numkong/include/numkong/probability/serial.h +181 -0
  250. package/numkong/include/numkong/probability/skylake.h +324 -0
  251. package/numkong/include/numkong/probability.h +380 -0
  252. package/numkong/include/numkong/probability.hpp +120 -0
  253. package/numkong/include/numkong/random.h +50 -0
  254. package/numkong/include/numkong/random.hpp +285 -0
  255. package/numkong/include/numkong/reduce/README.md +552 -0
  256. package/numkong/include/numkong/reduce/alder.h +636 -0
  257. package/numkong/include/numkong/reduce/genoa.h +201 -0
  258. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  259. package/numkong/include/numkong/reduce/icelake.h +549 -0
  260. package/numkong/include/numkong/reduce/neon.h +3980 -0
  261. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  262. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  263. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  264. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  265. package/numkong/include/numkong/reduce/serial.h +753 -0
  266. package/numkong/include/numkong/reduce/sierra.h +338 -0
  267. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  268. package/numkong/include/numkong/reduce/sve.h +52 -0
  269. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  270. package/numkong/include/numkong/reduce.h +1582 -0
  271. package/numkong/include/numkong/reduce.hpp +778 -0
  272. package/numkong/include/numkong/scalar/README.md +89 -0
  273. package/numkong/include/numkong/scalar/haswell.h +122 -0
  274. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  275. package/numkong/include/numkong/scalar/neon.h +122 -0
  276. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  277. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  278. package/numkong/include/numkong/scalar/rvv.h +211 -0
  279. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  280. package/numkong/include/numkong/scalar/serial.h +332 -0
  281. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  282. package/numkong/include/numkong/scalar.h +696 -0
  283. package/numkong/include/numkong/set/README.md +179 -0
  284. package/numkong/include/numkong/set/haswell.h +334 -0
  285. package/numkong/include/numkong/set/icelake.h +485 -0
  286. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  287. package/numkong/include/numkong/set/neon.h +363 -0
  288. package/numkong/include/numkong/set/powervsx.h +326 -0
  289. package/numkong/include/numkong/set/rvv.h +226 -0
  290. package/numkong/include/numkong/set/rvvbb.h +117 -0
  291. package/numkong/include/numkong/set/serial.h +174 -0
  292. package/numkong/include/numkong/set/sve.h +187 -0
  293. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  294. package/numkong/include/numkong/set.h +471 -0
  295. package/numkong/include/numkong/set.hpp +114 -0
  296. package/numkong/include/numkong/sets/README.md +149 -0
  297. package/numkong/include/numkong/sets/haswell.h +63 -0
  298. package/numkong/include/numkong/sets/icelake.h +66 -0
  299. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  300. package/numkong/include/numkong/sets/neon.h +61 -0
  301. package/numkong/include/numkong/sets/powervsx.h +65 -0
  302. package/numkong/include/numkong/sets/serial.h +43 -0
  303. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  304. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  305. package/numkong/include/numkong/sets.h +382 -0
  306. package/numkong/include/numkong/sparse/README.md +156 -0
  307. package/numkong/include/numkong/sparse/icelake.h +463 -0
  308. package/numkong/include/numkong/sparse/neon.h +288 -0
  309. package/numkong/include/numkong/sparse/serial.h +117 -0
  310. package/numkong/include/numkong/sparse/sve2.h +504 -0
  311. package/numkong/include/numkong/sparse/turin.h +322 -0
  312. package/numkong/include/numkong/sparse.h +363 -0
  313. package/numkong/include/numkong/sparse.hpp +113 -0
  314. package/numkong/include/numkong/spatial/README.md +439 -0
  315. package/numkong/include/numkong/spatial/alder.h +604 -0
  316. package/numkong/include/numkong/spatial/diamond.h +240 -0
  317. package/numkong/include/numkong/spatial/genoa.h +222 -0
  318. package/numkong/include/numkong/spatial/haswell.h +979 -0
  319. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  320. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  321. package/numkong/include/numkong/spatial/neon.h +846 -0
  322. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  323. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  324. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  325. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  326. package/numkong/include/numkong/spatial/rvv.h +991 -0
  327. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  328. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  329. package/numkong/include/numkong/spatial/serial.h +347 -0
  330. package/numkong/include/numkong/spatial/sierra.h +516 -0
  331. package/numkong/include/numkong/spatial/skylake.h +605 -0
  332. package/numkong/include/numkong/spatial/sve.h +246 -0
  333. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  334. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  335. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  336. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  337. package/numkong/include/numkong/spatial.h +1681 -0
  338. package/numkong/include/numkong/spatial.hpp +183 -0
  339. package/numkong/include/numkong/spatials/README.md +580 -0
  340. package/numkong/include/numkong/spatials/alder.h +94 -0
  341. package/numkong/include/numkong/spatials/diamond.h +82 -0
  342. package/numkong/include/numkong/spatials/genoa.h +94 -0
  343. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  344. package/numkong/include/numkong/spatials/haswell.h +219 -0
  345. package/numkong/include/numkong/spatials/icelake.h +113 -0
  346. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  347. package/numkong/include/numkong/spatials/neon.h +109 -0
  348. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  349. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  350. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  351. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  352. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  353. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  354. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  355. package/numkong/include/numkong/spatials/serial.h +248 -0
  356. package/numkong/include/numkong/spatials/sierra.h +96 -0
  357. package/numkong/include/numkong/spatials/skylake.h +184 -0
  358. package/numkong/include/numkong/spatials/sme.h +1927 -0
  359. package/numkong/include/numkong/spatials/smef64.h +483 -0
  360. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  361. package/numkong/include/numkong/spatials.h +3374 -0
  362. package/numkong/include/numkong/spatials.hpp +509 -0
  363. package/numkong/include/numkong/tensor.hpp +1981 -0
  364. package/numkong/include/numkong/trigonometry/README.md +184 -0
  365. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  366. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  367. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  368. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  369. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  370. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  371. package/numkong/include/numkong/trigonometry.h +467 -0
  372. package/numkong/include/numkong/trigonometry.hpp +166 -0
  373. package/numkong/include/numkong/types.h +1695 -0
  374. package/numkong/include/numkong/types.hpp +6027 -0
  375. package/numkong/include/numkong/vector.hpp +766 -0
  376. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  377. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  378. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  380. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  381. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  382. package/numkong/javascript/README.md +254 -0
  383. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  384. package/numkong/javascript/numkong-browser.ts +40 -0
  385. package/numkong/javascript/numkong-wasm.ts +750 -0
  386. package/numkong/javascript/numkong.c +712 -0
  387. package/numkong/javascript/numkong.ts +613 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  389. package/numkong/javascript/tsconfig-cjs.json +13 -0
  390. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  391. package/numkong/javascript/types.ts +784 -0
  392. package/numkong/numkong.gypi +104 -0
  393. package/numkong/package.json +108 -0
  394. package/numkong/probes/arm_neon.c +8 -0
  395. package/numkong/probes/arm_neon_bfdot.c +9 -0
  396. package/numkong/probes/arm_neon_fhm.c +9 -0
  397. package/numkong/probes/arm_neon_half.c +8 -0
  398. package/numkong/probes/arm_neon_sdot.c +9 -0
  399. package/numkong/probes/arm_neonfp8.c +9 -0
  400. package/numkong/probes/arm_sme.c +16 -0
  401. package/numkong/probes/arm_sme2.c +16 -0
  402. package/numkong/probes/arm_sme2p1.c +16 -0
  403. package/numkong/probes/arm_sme_bf16.c +16 -0
  404. package/numkong/probes/arm_sme_bi32.c +16 -0
  405. package/numkong/probes/arm_sme_f64.c +16 -0
  406. package/numkong/probes/arm_sme_fa64.c +14 -0
  407. package/numkong/probes/arm_sme_half.c +16 -0
  408. package/numkong/probes/arm_sme_lut2.c +15 -0
  409. package/numkong/probes/arm_sve.c +18 -0
  410. package/numkong/probes/arm_sve2.c +20 -0
  411. package/numkong/probes/arm_sve2p1.c +18 -0
  412. package/numkong/probes/arm_sve_bfdot.c +20 -0
  413. package/numkong/probes/arm_sve_half.c +18 -0
  414. package/numkong/probes/arm_sve_sdot.c +21 -0
  415. package/numkong/probes/loongarch_lasx.c +12 -0
  416. package/numkong/probes/power_vsx.c +12 -0
  417. package/numkong/probes/probe.js +127 -0
  418. package/numkong/probes/riscv_rvv.c +14 -0
  419. package/numkong/probes/riscv_rvv_bb.c +15 -0
  420. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  421. package/numkong/probes/riscv_rvv_half.c +14 -0
  422. package/numkong/probes/wasm_v128relaxed.c +11 -0
  423. package/numkong/probes/x86_alder.c +17 -0
  424. package/numkong/probes/x86_diamond.c +17 -0
  425. package/numkong/probes/x86_genoa.c +17 -0
  426. package/numkong/probes/x86_graniteamx.c +19 -0
  427. package/numkong/probes/x86_haswell.c +11 -0
  428. package/numkong/probes/x86_icelake.c +17 -0
  429. package/numkong/probes/x86_sapphire.c +16 -0
  430. package/numkong/probes/x86_sapphireamx.c +18 -0
  431. package/numkong/probes/x86_sierra.c +17 -0
  432. package/numkong/probes/x86_skylake.c +15 -0
  433. package/numkong/probes/x86_turin.c +17 -0
  434. package/numkong/rust/README.md +698 -0
  435. package/numkong/rust/capabilities.rs +96 -0
  436. package/numkong/rust/cast.rs +314 -0
  437. package/numkong/rust/curved.rs +391 -0
  438. package/numkong/rust/each.rs +2721 -0
  439. package/numkong/rust/geospatial.rs +343 -0
  440. package/numkong/rust/matrix.rs +5424 -0
  441. package/numkong/rust/maxsim.rs +540 -0
  442. package/numkong/rust/mesh.rs +837 -0
  443. package/numkong/rust/numkong.rs +409 -0
  444. package/numkong/rust/probability.rs +272 -0
  445. package/numkong/rust/reduce.rs +1249 -0
  446. package/numkong/rust/set.rs +194 -0
  447. package/numkong/rust/sparse.rs +513 -0
  448. package/numkong/rust/spatial.rs +1815 -0
  449. package/numkong/rust/tensor.rs +7565 -0
  450. package/numkong/rust/types.rs +3666 -0
  451. package/numkong/rust/vector.rs +1899 -0
  452. package/numkong/rustfmt.toml +2 -0
  453. package/numkong/swift/Matrix.swift +1388 -0
  454. package/numkong/swift/MaxSim.swift +151 -0
  455. package/numkong/swift/NumKong.swift +283 -0
  456. package/numkong/swift/Numerics.swift +329 -0
  457. package/numkong/swift/README.md +433 -0
  458. package/numkong/swift/Scalar.swift +741 -0
  459. package/numkong/swift/Tensor.swift +209 -0
  460. package/numkong/test/README.md +315 -0
  461. package/numkong/test/playwright.config.ts +16 -0
  462. package/numkong/test/swift/Test.swift +534 -0
  463. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  464. package/numkong/test/test-browser-bundle.html +188 -0
  465. package/numkong/test/test-browser-runner.mjs +43 -0
  466. package/numkong/test/test-browser.html +305 -0
  467. package/numkong/test/test-dtypes.mjs +453 -0
  468. package/numkong/test/test-wasm.mjs +267 -0
  469. package/numkong/test/test.cpp +442 -0
  470. package/numkong/test/test.hpp +580 -0
  471. package/numkong/test/test.mjs +363 -0
  472. package/numkong/test/test_base.py +1041 -0
  473. package/numkong/test/test_cast.cpp +242 -0
  474. package/numkong/test/test_cross.hpp +551 -0
  475. package/numkong/test/test_cross.py +467 -0
  476. package/numkong/test/test_cross_amx.cpp +50 -0
  477. package/numkong/test/test_cross_arm.cpp +225 -0
  478. package/numkong/test/test_cross_blas.cpp +354 -0
  479. package/numkong/test/test_cross_loongarch.cpp +90 -0
  480. package/numkong/test/test_cross_power.cpp +73 -0
  481. package/numkong/test/test_cross_rvv.cpp +109 -0
  482. package/numkong/test/test_cross_serial.cpp +181 -0
  483. package/numkong/test/test_cross_sme.cpp +148 -0
  484. package/numkong/test/test_cross_wasm.cpp +141 -0
  485. package/numkong/test/test_cross_x86.cpp +442 -0
  486. package/numkong/test/test_curved.cpp +182 -0
  487. package/numkong/test/test_curved.py +207 -0
  488. package/numkong/test/test_dot.cpp +353 -0
  489. package/numkong/test/test_dot.py +296 -0
  490. package/numkong/test/test_each.cpp +437 -0
  491. package/numkong/test/test_each.py +756 -0
  492. package/numkong/test/test_geospatial.cpp +155 -0
  493. package/numkong/test/test_geospatial.py +241 -0
  494. package/numkong/test/test_maxsim.cpp +138 -0
  495. package/numkong/test/test_maxsim.py +209 -0
  496. package/numkong/test/test_mesh.cpp +203 -0
  497. package/numkong/test/test_mesh.py +394 -0
  498. package/numkong/test/test_probability.cpp +136 -0
  499. package/numkong/test/test_probability.py +166 -0
  500. package/numkong/test/test_reduce.cpp +563 -0
  501. package/numkong/test/test_reduce.py +781 -0
  502. package/numkong/test/test_set.cpp +151 -0
  503. package/numkong/test/test_set.py +120 -0
  504. package/numkong/test/test_similarities.py +579 -0
  505. package/numkong/test/test_sparse.cpp +121 -0
  506. package/numkong/test/test_sparse.py +118 -0
  507. package/numkong/test/test_spatial.cpp +518 -0
  508. package/numkong/test/test_spatial.py +269 -0
  509. package/numkong/test/test_tensor.cpp +884 -0
  510. package/numkong/test/test_tensor.py +1417 -0
  511. package/numkong/test/test_trigonometry.cpp +156 -0
  512. package/numkong/test/test_trigonometry.py +180 -0
  513. package/package.json +7 -8
  514. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  515. package/prebuilds/linux-arm64/usearch.node +0 -0
  516. package/prebuilds/linux-x64/usearch.node +0 -0
  517. package/fp16/CMakeLists.txt +0 -176
  518. package/fp16/LICENSE +0 -11
  519. package/fp16/README.md +0 -20
  520. package/fp16/bench/alt-element.cc +0 -89
  521. package/fp16/bench/from-alt-array.cc +0 -175
  522. package/fp16/bench/from-ieee-array.cc +0 -399
  523. package/fp16/bench/ieee-element.cc +0 -272
  524. package/fp16/bench/to-alt-array.cc +0 -91
  525. package/fp16/bench/to-ieee-array.cc +0 -303
  526. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  527. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  528. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  529. package/fp16/configure.py +0 -65
  530. package/fp16/confu.yaml +0 -8
  531. package/fp16/include/fp16/__init__.py +0 -0
  532. package/fp16/include/fp16/avx.py +0 -50
  533. package/fp16/include/fp16/avx2.py +0 -53
  534. package/fp16/include/fp16/bitcasts.h +0 -92
  535. package/fp16/include/fp16/fp16.h +0 -451
  536. package/fp16/include/fp16/psimd.h +0 -131
  537. package/fp16/include/fp16.h +0 -11
  538. package/fp16/jni/Android.mk +0 -6
  539. package/fp16/jni/Application.mk +0 -4
  540. package/fp16/test/alt-from-fp32-value.cc +0 -498
  541. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  542. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  543. package/fp16/test/alt-to-fp32-value.cc +0 -348
  544. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  545. package/fp16/test/bitcasts.cc +0 -56
  546. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  547. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  548. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  549. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  550. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  551. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  552. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  553. package/fp16/test/peachpy/stubs.py +0 -38
  554. package/fp16/test/tables.cc +0 -530
  555. package/fp16/test/tables.h +0 -13
  556. package/fp16/third-party/THHalf.h +0 -92
  557. package/fp16/third-party/eigen-half.h +0 -170
  558. package/fp16/third-party/float16-compressor.h +0 -80
  559. package/fp16/third-party/half.hpp +0 -2916
  560. package/fp16/third-party/npy-halffloat.h +0 -328
  561. package/simsimd/.git-blame-ignore-revs +0 -2
  562. package/simsimd/CONTRIBUTING.md +0 -321
  563. package/simsimd/Cargo.toml +0 -49
  564. package/simsimd/MANIFEST.in +0 -4
  565. package/simsimd/Package.swift +0 -28
  566. package/simsimd/README.md +0 -1493
  567. package/simsimd/binding.gyp +0 -35
  568. package/simsimd/build.rs +0 -70
  569. package/simsimd/c/lib.c +0 -374
  570. package/simsimd/include/module.modulemap +0 -4
  571. package/simsimd/include/simsimd/binary.h +0 -486
  572. package/simsimd/include/simsimd/curved.h +0 -1541
  573. package/simsimd/include/simsimd/dot.h +0 -1853
  574. package/simsimd/include/simsimd/elementwise.h +0 -2465
  575. package/simsimd/include/simsimd/geospatial.h +0 -43
  576. package/simsimd/include/simsimd/mesh.h +0 -69
  577. package/simsimd/include/simsimd/probability.h +0 -606
  578. package/simsimd/include/simsimd/simsimd.h +0 -2567
  579. package/simsimd/include/simsimd/sparse.h +0 -1384
  580. package/simsimd/include/simsimd/spatial.h +0 -2335
  581. package/simsimd/include/simsimd/types.h +0 -666
  582. package/simsimd/javascript/fallback.ts +0 -233
  583. package/simsimd/javascript/lib.c +0 -125
  584. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  585. package/simsimd/javascript/simsimd.ts +0 -179
  586. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  587. package/simsimd/package-lock.json +0 -1761
  588. package/simsimd/package.json +0 -61
  589. package/simsimd/rust/lib.rs +0 -1821
  590. package/simsimd/scripts/bench.cxx +0 -1170
  591. package/simsimd/scripts/bench.ipynb +0 -187
  592. package/simsimd/scripts/bench.js +0 -127
  593. package/simsimd/scripts/bench.rs +0 -876
  594. package/simsimd/scripts/bench_vectors.py +0 -734
  595. package/simsimd/scripts/bench_vectors_live.py +0 -213
  596. package/simsimd/scripts/test.c +0 -187
  597. package/simsimd/scripts/test.mjs +0 -220
  598. package/simsimd/scripts/test.py +0 -1505
  599. package/simsimd/swift/SimSIMD.swift +0 -149
  600. package/simsimd/swift/Test.swift +0 -128
  601. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  602. /package/{simsimd → numkong}/LICENSE +0 -0
  603. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  604. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,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