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,246 @@
1
+ /**
2
+ * @brief SIMD-accelerated Spatial Similarity Measures for SVE.
3
+ * @file include/numkong/spatial/sve.h
4
+ * @author Ash Vardanian
5
+ * @date December 27, 2025
6
+ *
7
+ * @sa include/numkong/spatial.h
8
+ *
9
+ * @section spatial_sve_instructions ARM SVE Instructions
10
+ *
11
+ * Intrinsic Instruction V1
12
+ * svld1_f32 LD1W (Z.S, P/Z, [Xn]) 4-6cy @ 2p
13
+ * svsub_f32_x FSUB (Z.S, P/M, Z.S, Z.S) 3cy @ 2p
14
+ * svmla_f32_x FMLA (Z.S, P/M, Z.S, Z.S) 4cy @ 2p
15
+ * svaddv_f32 FADDV (S, P, Z.S) 6cy @ 1p
16
+ * svdupq_n_f32 DUP (Z.S, #imm) 1cy @ 2p
17
+ * svwhilelt_b32 WHILELT (P.S, Xn, Xm) 2cy @ 1p
18
+ * svptrue_b32 PTRUE (P.S, pattern) 1cy @ 2p
19
+ * svcntw CNTW (Xd) 1cy @ 2p
20
+ * svld1_f64 LD1D (Z.D, P/Z, [Xn]) 4-6cy @ 2p
21
+ * svsub_f64_x FSUB (Z.D, P/M, Z.D, Z.D) 3cy @ 2p
22
+ * svmla_f64_x FMLA (Z.D, P/M, Z.D, Z.D) 4cy @ 2p
23
+ * svaddv_f64 FADDV (D, P, Z.D) 6cy @ 1p
24
+ *
25
+ * SVE vector widths vary across implementations: Graviton3 uses 256-bit, while Graviton4/5
26
+ * and Apple M4+ use 128-bit. Code using svcntb() adapts automatically, but wider vectors
27
+ * process more elements per iteration with identical latencies.
28
+ *
29
+ * Spatial operations like L2 distance and angular similarity benefit from SVE's fused
30
+ * multiply-add instructions. The FADDV reduction dominates the critical path for short vectors.
31
+ */
32
+ #ifndef NK_SPATIAL_SVE_H
33
+ #define NK_SPATIAL_SVE_H
34
+
35
+ #if NK_TARGET_ARM64_
36
+ #if NK_TARGET_SVE
37
+
38
+ #include "numkong/types.h"
39
+ #include "numkong/reduce/sve.h" // `nk_svaddv_f64_`
40
+ #include "numkong/spatial/neon.h" // `nk_f64_sqrt_neon`
41
+ #include "numkong/dot/sve.h" // `nk_dot_stable_sum_f64_sve_`
42
+
43
+ #if defined(__cplusplus)
44
+ extern "C" {
45
+ #endif
46
+
47
+ #if defined(__clang__)
48
+ #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+sve"))), apply_to = function)
49
+ #elif defined(__GNUC__)
50
+ #pragma GCC push_options
51
+ #pragma GCC target("arch=armv8.2-a+sve")
52
+ #endif
53
+
54
+ /** @brief Reciprocal square root of an f32 SVE vector via estimate + 2 Newton-Raphson steps.
55
+ *
56
+ * Computes 1/sqrt(x) for each active lane. The initial estimate from `svrsqrte_f32`
57
+ * has ~8 bits of precision; each Newton-Raphson iteration via `svrsqrts_f32` roughly
58
+ * doubles the mantissa bits, giving ~23 bits (~full f32 precision) after 2 steps.
59
+ *
60
+ * Marked `__arm_streaming_compatible` so the helper is callable from both streaming
61
+ * (SME) and non-streaming (SVE) contexts without mode transitions.
62
+ *
63
+ * @param predicate Active-lane mask
64
+ * @param x Input vector (must be positive for meaningful results)
65
+ * @return Approximate 1/sqrt(x) with ~23-bit mantissa accuracy
66
+ */
67
+ NK_INTERNAL svfloat32_t nk_rsqrt_f32x_sve_(svbool_t predicate_b32x, svfloat32_t x) NK_STREAMING_COMPATIBLE_ {
68
+ svfloat32_t r = svrsqrte_f32(x);
69
+ r = svmul_f32_x(predicate_b32x, r, svrsqrts_f32(svmul_f32_x(predicate_b32x, x, r), r));
70
+ r = svmul_f32_x(predicate_b32x, r, svrsqrts_f32(svmul_f32_x(predicate_b32x, x, r), r));
71
+ return r;
72
+ }
73
+
74
+ /** @brief Reciprocal square root of an f64 SVE vector via estimate + 3 Newton-Raphson steps.
75
+ *
76
+ * Computes 1/sqrt(x) for each active lane. The initial estimate from `svrsqrte_f64`
77
+ * has ~8 bits of precision; three Newton-Raphson iterations via `svrsqrts_f64` yield
78
+ * ~52-bit mantissa accuracy (full f64 precision).
79
+ *
80
+ * Marked `__arm_streaming_compatible` so the helper is callable from both streaming
81
+ * (SME) and non-streaming (SVE) contexts without mode transitions.
82
+ *
83
+ * @param predicate_b32x Active-lane mask
84
+ * @param x Input vector (must be positive for meaningful results)
85
+ * @return Approximate 1/sqrt(x) with ~52-bit mantissa accuracy
86
+ */
87
+ NK_INTERNAL svfloat64_t nk_rsqrt_f64x_sve_(svbool_t predicate_b64x, svfloat64_t x) NK_STREAMING_COMPATIBLE_ {
88
+ svfloat64_t r = svrsqrte_f64(x);
89
+ r = svmul_f64_x(predicate_b64x, r, svrsqrts_f64(svmul_f64_x(predicate_b64x, x, r), r));
90
+ r = svmul_f64_x(predicate_b64x, r, svrsqrts_f64(svmul_f64_x(predicate_b64x, x, r), r));
91
+ r = svmul_f64_x(predicate_b64x, r, svrsqrts_f64(svmul_f64_x(predicate_b64x, x, r), r));
92
+ return r;
93
+ }
94
+
95
+ NK_PUBLIC void nk_sqeuclidean_f32_sve(nk_f32_t const *a, nk_f32_t const *b, nk_size_t n, nk_f64_t *result) {
96
+ nk_size_t i = 0;
97
+ svfloat64_t dist_sq_f64x = svdupq_n_f64(0.0, 0.0);
98
+ for (; i < n; i += svcntw()) {
99
+ svbool_t predicate_b32x = svwhilelt_b32_u64(i, n);
100
+ svfloat32_t a_f32x = svld1_f32(predicate_b32x, a + i);
101
+ svfloat32_t b_f32x = svld1_f32(predicate_b32x, b + i);
102
+ nk_size_t remaining = n - i < svcntw() ? n - i : svcntw();
103
+
104
+ // svcvt_f64_f32_x widens only even-indexed f32 elements; svext by 1 shifts odd into even.
105
+ svbool_t pred_even_b64x = svwhilelt_b64_u64(0u, (remaining + 1) / 2);
106
+ svfloat64_t a_even_f64x = svcvt_f64_f32_x(pred_even_b64x, a_f32x);
107
+ svfloat64_t b_even_f64x = svcvt_f64_f32_x(pred_even_b64x, b_f32x);
108
+ svfloat64_t diff_even_f64x = svsub_f64_x(pred_even_b64x, a_even_f64x, b_even_f64x);
109
+ dist_sq_f64x = svmla_f64_m(pred_even_b64x, dist_sq_f64x, diff_even_f64x, diff_even_f64x);
110
+
111
+ svbool_t pred_odd_b64x = svwhilelt_b64_u64(0u, remaining / 2);
112
+ svfloat64_t a_odd_f64x = svcvt_f64_f32_x(pred_odd_b64x, svext_f32(a_f32x, a_f32x, 1));
113
+ svfloat64_t b_odd_f64x = svcvt_f64_f32_x(pred_odd_b64x, svext_f32(b_f32x, b_f32x, 1));
114
+ svfloat64_t diff_odd_f64x = svsub_f64_x(pred_odd_b64x, a_odd_f64x, b_odd_f64x);
115
+ dist_sq_f64x = svmla_f64_m(pred_odd_b64x, dist_sq_f64x, diff_odd_f64x, diff_odd_f64x);
116
+ }
117
+ nk_f64_t dist_sq_f64 = nk_svaddv_f64_(svptrue_b64(), dist_sq_f64x);
118
+ *result = dist_sq_f64;
119
+ }
120
+
121
+ NK_PUBLIC void nk_euclidean_f32_sve(nk_f32_t const *a, nk_f32_t const *b, nk_size_t n, nk_f64_t *result) {
122
+ nk_sqeuclidean_f32_sve(a, b, n, result);
123
+ *result = nk_f64_sqrt_neon(*result);
124
+ }
125
+
126
+ NK_PUBLIC void nk_angular_f32_sve(nk_f32_t const *a, nk_f32_t const *b, nk_size_t n, nk_f64_t *result) {
127
+ nk_size_t i = 0;
128
+ svfloat64_t ab_f64x = svdupq_n_f64(0.0, 0.0);
129
+ svfloat64_t a2_f64x = svdupq_n_f64(0.0, 0.0);
130
+ svfloat64_t b2_f64x = svdupq_n_f64(0.0, 0.0);
131
+ for (; i < n; i += svcntw()) {
132
+ svbool_t predicate_b32x = svwhilelt_b32_u64(i, n);
133
+ svfloat32_t a_f32x = svld1_f32(predicate_b32x, a + i);
134
+ svfloat32_t b_f32x = svld1_f32(predicate_b32x, b + i);
135
+ nk_size_t remaining = n - i < svcntw() ? n - i : svcntw();
136
+
137
+ // svcvt_f64_f32_x widens only even-indexed f32 elements; svext by 1 shifts odd into even.
138
+ svbool_t pred_even_b64x = svwhilelt_b64_u64(0u, (remaining + 1) / 2);
139
+ svfloat64_t a_even_f64x = svcvt_f64_f32_x(pred_even_b64x, a_f32x);
140
+ svfloat64_t b_even_f64x = svcvt_f64_f32_x(pred_even_b64x, b_f32x);
141
+ ab_f64x = svmla_f64_m(pred_even_b64x, ab_f64x, a_even_f64x, b_even_f64x);
142
+ a2_f64x = svmla_f64_m(pred_even_b64x, a2_f64x, a_even_f64x, a_even_f64x);
143
+ b2_f64x = svmla_f64_m(pred_even_b64x, b2_f64x, b_even_f64x, b_even_f64x);
144
+
145
+ svbool_t pred_odd_b64x = svwhilelt_b64_u64(0u, remaining / 2);
146
+ svfloat64_t a_odd_f64x = svcvt_f64_f32_x(pred_odd_b64x, svext_f32(a_f32x, a_f32x, 1));
147
+ svfloat64_t b_odd_f64x = svcvt_f64_f32_x(pred_odd_b64x, svext_f32(b_f32x, b_f32x, 1));
148
+ ab_f64x = svmla_f64_m(pred_odd_b64x, ab_f64x, a_odd_f64x, b_odd_f64x);
149
+ a2_f64x = svmla_f64_m(pred_odd_b64x, a2_f64x, a_odd_f64x, a_odd_f64x);
150
+ b2_f64x = svmla_f64_m(pred_odd_b64x, b2_f64x, b_odd_f64x, b_odd_f64x);
151
+ }
152
+
153
+ nk_f64_t ab_f64 = nk_svaddv_f64_(svptrue_b64(), ab_f64x);
154
+ nk_f64_t a2_f64 = nk_svaddv_f64_(svptrue_b64(), a2_f64x);
155
+ nk_f64_t b2_f64 = nk_svaddv_f64_(svptrue_b64(), b2_f64x);
156
+ *result = nk_angular_normalize_f64_neon_(ab_f64, a2_f64, b2_f64);
157
+ }
158
+
159
+ NK_PUBLIC void nk_sqeuclidean_f64_sve(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
160
+ // Neumaier compensated summation for numerical stability
161
+ nk_size_t i = 0;
162
+ svfloat64_t sum_f64x = svdupq_n_f64(0.0, 0.0);
163
+ svfloat64_t compensation_f64x = svdupq_n_f64(0.0, 0.0);
164
+ svbool_t predicate_all_b64x = svptrue_b64();
165
+ do {
166
+ svbool_t predicate_b64x = svwhilelt_b64_u64(i, n);
167
+ svfloat64_t a_f64x = svld1_f64(predicate_b64x, a + i);
168
+ svfloat64_t b_f64x = svld1_f64(predicate_b64x, b + i);
169
+ svfloat64_t diff_f64x = svsub_f64_x(predicate_b64x, a_f64x, b_f64x);
170
+ svfloat64_t diff_sq_f64x = svmul_f64_x(predicate_b64x, diff_f64x, diff_f64x);
171
+ // Neumaier: t = sum + x
172
+ svfloat64_t t_f64x = svadd_f64_m(predicate_b64x, sum_f64x, diff_sq_f64x);
173
+ svfloat64_t abs_sum_f64x = svabs_f64_x(predicate_b64x, sum_f64x);
174
+ // diff_sq is already non-negative (it's a square), so svabs is unnecessary
175
+ svbool_t sum_ge_x_b64x = svcmpge_f64(predicate_b64x, abs_sum_f64x, diff_sq_f64x);
176
+ // When |sum| >= |x|: comp += (sum - t) + x; when |x| > |sum|: comp += (x - t) + sum
177
+ svfloat64_t comp_sum_large_f64x = svadd_f64_x(predicate_b64x, svsub_f64_x(predicate_b64x, sum_f64x, t_f64x),
178
+ diff_sq_f64x);
179
+ svfloat64_t comp_x_large_f64x = svadd_f64_x(predicate_b64x, svsub_f64_x(predicate_b64x, diff_sq_f64x, t_f64x),
180
+ sum_f64x);
181
+ svfloat64_t comp_update_f64x = svsel_f64(sum_ge_x_b64x, comp_sum_large_f64x, comp_x_large_f64x);
182
+ compensation_f64x = svadd_f64_m(predicate_b64x, compensation_f64x, comp_update_f64x);
183
+ sum_f64x = t_f64x;
184
+ i += svcntd();
185
+ } while (i < n);
186
+ *result = nk_dot_stable_sum_f64_sve_(predicate_all_b64x, sum_f64x, compensation_f64x);
187
+ }
188
+
189
+ NK_PUBLIC void nk_euclidean_f64_sve(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
190
+ nk_sqeuclidean_f64_sve(a, b, n, result);
191
+ *result = nk_f64_sqrt_neon(*result);
192
+ }
193
+
194
+ NK_PUBLIC void nk_angular_f64_sve(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
195
+ // Dot2 (Ogita-Rump-Oishi) for cross-product ab (may have cancellation),
196
+ // simple FMA for self-products a2/b2 (all positive, no cancellation)
197
+ nk_size_t i = 0;
198
+ svfloat64_t ab_sum_f64x = svdupq_n_f64(0.0, 0.0);
199
+ svfloat64_t ab_compensation_f64x = svdupq_n_f64(0.0, 0.0);
200
+ svfloat64_t a2_f64x = svdupq_n_f64(0.0, 0.0);
201
+ svfloat64_t b2_f64x = svdupq_n_f64(0.0, 0.0);
202
+ svbool_t predicate_all_b64x = svptrue_b64();
203
+ do {
204
+ svbool_t predicate_b64x = svwhilelt_b64_u64(i, n);
205
+ svfloat64_t a_f64x = svld1_f64(predicate_b64x, a + i);
206
+ svfloat64_t b_f64x = svld1_f64(predicate_b64x, b + i);
207
+ // TwoProd for ab: product = a*b, error = fma(a,b,-product) = -(product - a*b)
208
+ svfloat64_t product_f64x = svmul_f64_x(predicate_b64x, a_f64x, b_f64x);
209
+ svfloat64_t product_error_f64x = svneg_f64_x(predicate_b64x,
210
+ svnmls_f64_x(predicate_b64x, product_f64x, a_f64x, b_f64x));
211
+ // TwoSum: (tentative_sum, sum_error) = TwoSum(sum, product)
212
+ svfloat64_t tentative_sum_f64x = svadd_f64_m(predicate_b64x, ab_sum_f64x, product_f64x);
213
+ svfloat64_t virtual_addend_f64x = svsub_f64_x(predicate_b64x, tentative_sum_f64x, ab_sum_f64x);
214
+ svfloat64_t sum_error_f64x = svadd_f64_x(
215
+ predicate_b64x,
216
+ svsub_f64_x(predicate_b64x, ab_sum_f64x,
217
+ svsub_f64_x(predicate_b64x, tentative_sum_f64x, virtual_addend_f64x)),
218
+ svsub_f64_x(predicate_b64x, product_f64x, virtual_addend_f64x));
219
+ ab_sum_f64x = tentative_sum_f64x;
220
+ ab_compensation_f64x = svadd_f64_m(predicate_b64x, ab_compensation_f64x,
221
+ svadd_f64_x(predicate_b64x, sum_error_f64x, product_error_f64x));
222
+ // Simple FMA for self-products (no cancellation)
223
+ a2_f64x = svmla_f64_m(predicate_b64x, a2_f64x, a_f64x, a_f64x);
224
+ b2_f64x = svmla_f64_m(predicate_b64x, b2_f64x, b_f64x, b_f64x);
225
+ i += svcntd();
226
+ } while (i < n);
227
+
228
+ nk_f64_t ab_f64 = nk_dot_stable_sum_f64_sve_(predicate_all_b64x, ab_sum_f64x, ab_compensation_f64x);
229
+ nk_f64_t a2_f64 = nk_svaddv_f64_(predicate_all_b64x, a2_f64x);
230
+ nk_f64_t b2_f64 = nk_svaddv_f64_(predicate_all_b64x, b2_f64x);
231
+ *result = nk_angular_normalize_f64_neon_(ab_f64, a2_f64, b2_f64);
232
+ }
233
+
234
+ #if defined(__clang__)
235
+ #pragma clang attribute pop
236
+ #elif defined(__GNUC__)
237
+ #pragma GCC pop_options
238
+ #endif
239
+
240
+ #if defined(__cplusplus)
241
+ } // extern "C"
242
+ #endif
243
+
244
+ #endif // NK_TARGET_SVE
245
+ #endif // NK_TARGET_ARM64_
246
+ #endif // NK_SPATIAL_SVE_H
@@ -0,0 +1,125 @@
1
+ /**
2
+ * @brief SIMD-accelerated Spatial Similarity Measures for SVE BF16.
3
+ * @file include/numkong/spatial/sve.h
4
+ * @author Ash Vardanian
5
+ * @date December 27, 2025
6
+ *
7
+ * @sa include/numkong/spatial.h
8
+ *
9
+ * @section spatial_svebfdot_instructions ARM SVE+BF16 Instructions
10
+ *
11
+ * Intrinsic Instruction V1
12
+ * svld1_bf16 LD1H (Z.H, P/Z, [Xn]) 4-6cy @ 2p
13
+ * svld1_u16 LD1H (Z.H, P/Z, [Xn]) 4-6cy @ 2p
14
+ * svbfdot_f32 BFDOT (Z.S, Z.H, Z.H) 4cy @ 2p
15
+ * svmla_f32_x FMLA (Z.S, P/M, Z.S, Z.S) 4cy @ 2p
16
+ * svsub_f32_x FSUB (Z.S, P/M, Z.S, Z.S) 3cy @ 2p
17
+ * svaddv_f32 FADDV (S, P, Z.S) 6cy @ 1p
18
+ * svunpklo_u32 UUNPKLO (Z.S, Z.H) 2cy @ 2p
19
+ * svunpkhi_u32 UUNPKHI (Z.S, Z.H) 2cy @ 2p
20
+ * svlsl_n_u32_x LSL (Z.S, P/M, Z.S, #imm) 2cy @ 2p
21
+ * svwhilelt_b16 WHILELT (P.H, Xn, Xm) 2cy @ 1p
22
+ * svwhilelt_b32 WHILELT (P.S, Xn, Xm) 2cy @ 1p
23
+ * svcnth CNTH (Xd) 1cy @ 2p
24
+ *
25
+ * SVE vector widths vary across implementations: Graviton3 uses 256-bit, while Graviton4/5
26
+ * and Apple M4+ use 128-bit. Code using svcntb() adapts automatically, but wider vectors
27
+ * process more elements per iteration with identical latencies.
28
+ *
29
+ * The BFDOT instruction fuses two BF16 multiplications with FP32 accumulation, providing
30
+ * efficient BF16 dot products without explicit conversion overhead.
31
+ */
32
+ #ifndef NK_SPATIAL_SVEBFDOT_H
33
+ #define NK_SPATIAL_SVEBFDOT_H
34
+
35
+ #if NK_TARGET_ARM64_
36
+ #if NK_TARGET_SVEBFDOT
37
+
38
+ #include "numkong/types.h"
39
+ #include "numkong/reduce/sve.h" // `nk_svaddv_f64_`
40
+ #include "numkong/spatial/neon.h" // `nk_f32_sqrt_neon`
41
+
42
+ #if defined(__cplusplus)
43
+ extern "C" {
44
+ #endif
45
+
46
+ #if defined(__clang__)
47
+ #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+sve+bf16"))), apply_to = function)
48
+ #elif defined(__GNUC__)
49
+ #pragma GCC push_options
50
+ #pragma GCC target("arch=armv8.2-a+sve+bf16")
51
+ #endif
52
+
53
+ NK_PUBLIC void nk_sqeuclidean_bf16_svebfdot(nk_bf16_t const *a_enum, nk_bf16_t const *b_enum, nk_size_t n,
54
+ nk_f32_t *result) {
55
+ nk_size_t i = 0;
56
+ svfloat32_t d2_low_f32x = svdupq_n_f32(0.f, 0.f, 0.f, 0.f);
57
+ svfloat32_t d2_high_f32x = svdupq_n_f32(0.f, 0.f, 0.f, 0.f);
58
+ nk_u16_t const *a = (nk_u16_t const *)(a_enum);
59
+ nk_u16_t const *b = (nk_u16_t const *)(b_enum);
60
+ do {
61
+ svbool_t predicate_b16x = svwhilelt_b16_u64(i, n);
62
+ svuint16_t a_u16x = svld1_u16(predicate_b16x, a + i);
63
+ svuint16_t b_u16x = svld1_u16(predicate_b16x, b + i);
64
+
65
+ // There is no `bf16` subtraction in SVE, so we need to convert to `u32` and shift.
66
+ svbool_t predicate_low_b32x = svwhilelt_b32_u64(i, n);
67
+ svbool_t predicate_high_b32x = svwhilelt_b32_u64(i + svcnth() / 2, n);
68
+ svfloat32_t a_low_f32x = svreinterpret_f32_u32(svlsl_n_u32_x(predicate_low_b32x, svunpklo_u32(a_u16x), 16));
69
+ svfloat32_t a_high_f32x = svreinterpret_f32_u32(svlsl_n_u32_x(predicate_high_b32x, svunpkhi_u32(a_u16x), 16));
70
+ svfloat32_t b_low_f32x = svreinterpret_f32_u32(svlsl_n_u32_x(predicate_low_b32x, svunpklo_u32(b_u16x), 16));
71
+ svfloat32_t b_high_f32x = svreinterpret_f32_u32(svlsl_n_u32_x(predicate_high_b32x, svunpkhi_u32(b_u16x), 16));
72
+
73
+ svfloat32_t a_minus_b_low_f32x = svsub_f32_x(predicate_low_b32x, a_low_f32x, b_low_f32x);
74
+ svfloat32_t a_minus_b_high_f32x = svsub_f32_x(predicate_high_b32x, a_high_f32x, b_high_f32x);
75
+ d2_low_f32x = svmla_f32_m(predicate_low_b32x, d2_low_f32x, a_minus_b_low_f32x, a_minus_b_low_f32x);
76
+ d2_high_f32x = svmla_f32_m(predicate_high_b32x, d2_high_f32x, a_minus_b_high_f32x, a_minus_b_high_f32x);
77
+ i += svcnth();
78
+ } while (i < n);
79
+ nk_f32_t d2_low = nk_svaddv_f32_(svptrue_b32(), d2_low_f32x);
80
+ nk_f32_t d2_high = nk_svaddv_f32_(svptrue_b32(), d2_high_f32x);
81
+ nk_f32_t d2 = d2_low + d2_high;
82
+ *result = d2;
83
+ }
84
+ NK_PUBLIC void nk_euclidean_bf16_svebfdot(nk_bf16_t const *a, nk_bf16_t const *b, nk_size_t n, nk_f32_t *result) {
85
+ nk_sqeuclidean_bf16_svebfdot(a, b, n, result);
86
+ *result = nk_f32_sqrt_neon(*result);
87
+ }
88
+
89
+ NK_PUBLIC void nk_angular_bf16_svebfdot(nk_bf16_t const *a_enum, nk_bf16_t const *b_enum, nk_size_t n,
90
+ nk_f32_t *result) {
91
+ nk_size_t i = 0;
92
+ svfloat32_t ab_f32x = svdupq_n_f32(0.f, 0.f, 0.f, 0.f);
93
+ svfloat32_t a2_f32x = svdupq_n_f32(0.f, 0.f, 0.f, 0.f);
94
+ svfloat32_t b2_f32x = svdupq_n_f32(0.f, 0.f, 0.f, 0.f);
95
+ nk_bf16_for_arm_simd_t const *a = (nk_bf16_for_arm_simd_t const *)(a_enum);
96
+ nk_bf16_for_arm_simd_t const *b = (nk_bf16_for_arm_simd_t const *)(b_enum);
97
+ do {
98
+ svbool_t predicate_b16x = svwhilelt_b16_u64(i, n);
99
+ svbfloat16_t a_bf16x = svld1_bf16(predicate_b16x, a + i);
100
+ svbfloat16_t b_bf16x = svld1_bf16(predicate_b16x, b + i);
101
+ ab_f32x = svbfdot_f32(ab_f32x, a_bf16x, b_bf16x);
102
+ a2_f32x = svbfdot_f32(a2_f32x, a_bf16x, a_bf16x);
103
+ b2_f32x = svbfdot_f32(b2_f32x, b_bf16x, b_bf16x);
104
+ i += svcnth();
105
+ } while (i < n);
106
+
107
+ nk_f32_t ab = nk_svaddv_f32_(svptrue_b32(), ab_f32x);
108
+ nk_f32_t a2 = nk_svaddv_f32_(svptrue_b32(), a2_f32x);
109
+ nk_f32_t b2 = nk_svaddv_f32_(svptrue_b32(), b2_f32x);
110
+ *result = nk_angular_normalize_f32_neon_(ab, a2, b2);
111
+ }
112
+
113
+ #if defined(__clang__)
114
+ #pragma clang attribute pop
115
+ #elif defined(__GNUC__)
116
+ #pragma GCC pop_options
117
+ #endif
118
+
119
+ #if defined(__cplusplus)
120
+ } // extern "C"
121
+ #endif
122
+
123
+ #endif // NK_TARGET_SVEBFDOT
124
+ #endif // NK_TARGET_ARM64_
125
+ #endif // NK_SPATIAL_SVEBFDOT_H
@@ -0,0 +1,136 @@
1
+ /**
2
+ * @brief SIMD-accelerated Spatial Similarity Measures for SVE FP16.
3
+ * @file include/numkong/spatial/sve.h
4
+ * @author Ash Vardanian
5
+ * @date December 27, 2025
6
+ *
7
+ * @sa include/numkong/spatial.h
8
+ *
9
+ * @section spatial_svehalf_instructions ARM SVE+FP16 Instructions
10
+ *
11
+ * Intrinsic Instruction V1
12
+ * svld1_f16 LD1H (Z.H, P/Z, [Xn]) 4-6cy @ 2p
13
+ * svsub_f16_x FSUB (Z.H, P/M, Z.H, Z.H) 3cy @ 2p
14
+ * svmla_f16_x FMLA (Z.H, P/M, Z.H, Z.H) 4cy @ 2p
15
+ * svaddv_f16 FADDV (H, P, Z.H) 6cy @ 1p
16
+ * svdupq_n_f16 DUP (Z.H, #imm) 1cy @ 2p
17
+ * svwhilelt_b16 WHILELT (P.H, Xn, Xm) 2cy @ 1p
18
+ * svptrue_b16 PTRUE (P.H, pattern) 1cy @ 2p
19
+ * svcnth CNTH (Xd) 1cy @ 2p
20
+ *
21
+ * SVE vector widths vary across implementations: Graviton3 uses 256-bit, while Graviton4/5
22
+ * and Apple M4+ use 128-bit. Code using svcntb() adapts automatically, but wider vectors
23
+ * process more elements per iteration with identical latencies.
24
+ *
25
+ * FP16 spatial operations trade precision for throughput, processing twice as many elements
26
+ * per cycle. This is particularly effective for embedding similarity in ML applications.
27
+ */
28
+ #ifndef NK_SPATIAL_SVEHALF_H
29
+ #define NK_SPATIAL_SVEHALF_H
30
+
31
+ #if NK_TARGET_ARM64_
32
+ #if NK_TARGET_SVEHALF
33
+
34
+ #include "numkong/types.h"
35
+ #include "numkong/reduce/sve.h" // `nk_svaddv_f64_`
36
+ #include "numkong/spatial/neon.h" // `nk_f32_sqrt_neon`
37
+
38
+ #if defined(__cplusplus)
39
+ extern "C" {
40
+ #endif
41
+
42
+ #if defined(__clang__)
43
+ #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+sve+fp16"))), apply_to = function)
44
+ #elif defined(__GNUC__)
45
+ #pragma GCC push_options
46
+ #pragma GCC target("arch=armv8.2-a+sve+fp16")
47
+ #endif
48
+
49
+ NK_PUBLIC void nk_sqeuclidean_f16_svehalf(nk_f16_t const *a_enum, nk_f16_t const *b_enum, nk_size_t n,
50
+ nk_f32_t *result) {
51
+ nk_size_t i = 0;
52
+ svfloat32_t d2_f32x = svdup_n_f32(0.0f);
53
+ nk_f16_for_arm_simd_t const *a = (nk_f16_for_arm_simd_t const *)(a_enum);
54
+ nk_f16_for_arm_simd_t const *b = (nk_f16_for_arm_simd_t const *)(b_enum);
55
+ do {
56
+ svbool_t predicate_b16x = svwhilelt_b16_u64(i, n);
57
+ svfloat16_t a_f16x = svld1_f16(predicate_b16x, a + i);
58
+ svfloat16_t b_f16x = svld1_f16(predicate_b16x, b + i);
59
+ nk_size_t remaining = n - i < svcnth() ? n - i : svcnth();
60
+
61
+ // SVE `svcvt_f32_f16_x` widens only even-indexed f16 elements (0, 2, 4, ...),
62
+ // so we need two passes: one on the original vector (even elements) and one on
63
+ // a vector shifted by one position via `svext` (odd elements become even).
64
+ svbool_t pred_even_b32x = svwhilelt_b32_u64(0u, (remaining + 1) / 2);
65
+ svfloat32_t a_even_f32x = svcvt_f32_f16_x(pred_even_b32x, a_f16x);
66
+ svfloat32_t b_even_f32x = svcvt_f32_f16_x(pred_even_b32x, b_f16x);
67
+ svfloat32_t diff_even_f32x = svsub_f32_x(pred_even_b32x, a_even_f32x, b_even_f32x);
68
+ d2_f32x = svmla_f32_m(pred_even_b32x, d2_f32x, diff_even_f32x, diff_even_f32x);
69
+
70
+ svbool_t pred_odd_b32x = svwhilelt_b32_u64(0u, remaining / 2);
71
+ svfloat32_t a_odd_f32x = svcvt_f32_f16_x(pred_odd_b32x, svext_f16(a_f16x, a_f16x, 1));
72
+ svfloat32_t b_odd_f32x = svcvt_f32_f16_x(pred_odd_b32x, svext_f16(b_f16x, b_f16x, 1));
73
+ svfloat32_t diff_odd_f32x = svsub_f32_x(pred_odd_b32x, a_odd_f32x, b_odd_f32x);
74
+ d2_f32x = svmla_f32_m(pred_odd_b32x, d2_f32x, diff_odd_f32x, diff_odd_f32x);
75
+
76
+ i += svcnth();
77
+ } while (i < n);
78
+ *result = nk_svaddv_f32_(svptrue_b32(), d2_f32x);
79
+ }
80
+
81
+ NK_PUBLIC void nk_euclidean_f16_svehalf(nk_f16_t const *a, nk_f16_t const *b, nk_size_t n, nk_f32_t *result) {
82
+ nk_sqeuclidean_f16_svehalf(a, b, n, result);
83
+ *result = nk_f32_sqrt_neon(*result);
84
+ }
85
+
86
+ NK_PUBLIC void nk_angular_f16_svehalf(nk_f16_t const *a_enum, nk_f16_t const *b_enum, nk_size_t n, nk_f32_t *result) {
87
+ nk_size_t i = 0;
88
+ svfloat32_t ab_f32x = svdup_n_f32(0.0f);
89
+ svfloat32_t a2_f32x = svdup_n_f32(0.0f);
90
+ svfloat32_t b2_f32x = svdup_n_f32(0.0f);
91
+ nk_f16_for_arm_simd_t const *a = (nk_f16_for_arm_simd_t const *)(a_enum);
92
+ nk_f16_for_arm_simd_t const *b = (nk_f16_for_arm_simd_t const *)(b_enum);
93
+ do {
94
+ svbool_t predicate_b16x = svwhilelt_b16_u64(i, n);
95
+ svfloat16_t a_f16x = svld1_f16(predicate_b16x, a + i);
96
+ svfloat16_t b_f16x = svld1_f16(predicate_b16x, b + i);
97
+ nk_size_t remaining = n - i < svcnth() ? n - i : svcnth();
98
+
99
+ // Even-indexed f16 elements (0, 2, 4, ...)
100
+ svbool_t pred_even_b32x = svwhilelt_b32_u64(0u, (remaining + 1) / 2);
101
+ svfloat32_t a_even_f32x = svcvt_f32_f16_x(pred_even_b32x, a_f16x);
102
+ svfloat32_t b_even_f32x = svcvt_f32_f16_x(pred_even_b32x, b_f16x);
103
+ ab_f32x = svmla_f32_m(pred_even_b32x, ab_f32x, a_even_f32x, b_even_f32x);
104
+ a2_f32x = svmla_f32_m(pred_even_b32x, a2_f32x, a_even_f32x, a_even_f32x);
105
+ b2_f32x = svmla_f32_m(pred_even_b32x, b2_f32x, b_even_f32x, b_even_f32x);
106
+
107
+ // Odd-indexed f16 elements (1, 3, 5, ...) via svext shift-by-1
108
+ svbool_t pred_odd_b32x = svwhilelt_b32_u64(0u, remaining / 2);
109
+ svfloat32_t a_odd_f32x = svcvt_f32_f16_x(pred_odd_b32x, svext_f16(a_f16x, a_f16x, 1));
110
+ svfloat32_t b_odd_f32x = svcvt_f32_f16_x(pred_odd_b32x, svext_f16(b_f16x, b_f16x, 1));
111
+ ab_f32x = svmla_f32_m(pred_odd_b32x, ab_f32x, a_odd_f32x, b_odd_f32x);
112
+ a2_f32x = svmla_f32_m(pred_odd_b32x, a2_f32x, a_odd_f32x, a_odd_f32x);
113
+ b2_f32x = svmla_f32_m(pred_odd_b32x, b2_f32x, b_odd_f32x, b_odd_f32x);
114
+
115
+ i += svcnth();
116
+ } while (i < n);
117
+
118
+ nk_f32_t ab_f32 = nk_svaddv_f32_(svptrue_b32(), ab_f32x);
119
+ nk_f32_t a2_f32 = nk_svaddv_f32_(svptrue_b32(), a2_f32x);
120
+ nk_f32_t b2_f32 = nk_svaddv_f32_(svptrue_b32(), b2_f32x);
121
+ *result = nk_angular_normalize_f32_neon_(ab_f32, a2_f32, b2_f32);
122
+ }
123
+
124
+ #if defined(__clang__)
125
+ #pragma clang attribute pop
126
+ #elif defined(__GNUC__)
127
+ #pragma GCC pop_options
128
+ #endif
129
+
130
+ #if defined(__cplusplus)
131
+ } // extern "C"
132
+ #endif
133
+
134
+ #endif // NK_TARGET_SVEHALF
135
+ #endif // NK_TARGET_ARM64_
136
+ #endif // NK_SPATIAL_SVEHALF_H
@@ -0,0 +1,143 @@
1
+ /**
2
+ * @brief SIMD-accelerated Spatial Similarity Measures for SVE SDOT.
3
+ * @file include/numkong/spatial/svesdot.h
4
+ * @author Ash Vardanian
5
+ * @date April 3, 2026
6
+ *
7
+ * @sa include/numkong/spatial.h
8
+ *
9
+ * @section spatial_svesdot_instructions ARM SVE+DotProd Instructions
10
+ *
11
+ * Intrinsic Instruction V1
12
+ * svld1_s8 LD1B (Z.B, P/Z, [Xn]) 4-6cy @ 2p
13
+ * svld1_u8 LD1B (Z.B, P/Z, [Xn]) 4-6cy @ 2p
14
+ * svdot_s32 SDOT (Z.S, Z.B, Z.B) 3cy @ 2p
15
+ * svdot_u32 UDOT (Z.S, Z.B, Z.B) 3cy @ 2p
16
+ * svabd_s8_x SABD (Z.B, P/M, Z.B) 3cy @ 2p
17
+ * svabd_u8_x UABD (Z.B, P/M, Z.B) 3cy @ 2p
18
+ * svaddv_s32 SADDV (D, P, Z.S) 6cy @ 1p
19
+ * svaddv_u32 UADDV (D, P, Z.S) 6cy @ 1p
20
+ * svwhilelt_b8 WHILELT (P.B, Xn, Xm) 2cy @ 1p
21
+ * svcntb CNTB (Xd) 1cy @ 2p
22
+ *
23
+ * SVE vector widths vary across implementations: Graviton3 uses 256-bit, while Graviton4/5
24
+ * and Apple M4+ use 128-bit. Code using svcntb() adapts automatically, but wider vectors
25
+ * process more elements per iteration with identical latencies.
26
+ *
27
+ * For L2 distance, SABD/UABD computes |a-b| per byte, then UDOT squares and accumulates.
28
+ * Angular distance uses SDOT/UDOT directly for dot product and norm computations.
29
+ */
30
+ #ifndef NK_SPATIAL_SVESDOT_H
31
+ #define NK_SPATIAL_SVESDOT_H
32
+
33
+ #if NK_TARGET_ARM64_
34
+ #if NK_TARGET_SVESDOT
35
+
36
+ #include "numkong/types.h"
37
+ #include "numkong/reduce/sve.h" // `nk_svaddv_f64_`
38
+ #include "numkong/spatial/neon.h" // `nk_angular_normalize_f32_neon_`, `nk_f32_sqrt_neon`
39
+
40
+ #if defined(__cplusplus)
41
+ extern "C" {
42
+ #endif
43
+
44
+ #if defined(__clang__)
45
+ #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+sve+dotprod"))), apply_to = function)
46
+ #elif defined(__GNUC__)
47
+ #pragma GCC push_options
48
+ #pragma GCC target("arch=armv8.2-a+sve+dotprod")
49
+ #endif
50
+
51
+ NK_PUBLIC void nk_sqeuclidean_i8_svesdot(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_u32_t *result) {
52
+ nk_size_t i = 0;
53
+ svuint32_t distance_sq_u32x = svdup_u32(0);
54
+ do {
55
+ svbool_t predicate_b8x = svwhilelt_b8_u64(i, n);
56
+ svint8_t a_i8x = svld1_s8(predicate_b8x, a + i);
57
+ svint8_t b_i8x = svld1_s8(predicate_b8x, b + i);
58
+ svuint8_t diff_u8x = svreinterpret_u8_s8(svabd_s8_x(predicate_b8x, a_i8x, b_i8x));
59
+ distance_sq_u32x = svdot_u32(distance_sq_u32x, diff_u8x, diff_u8x);
60
+ i += svcntb();
61
+ } while (i < n);
62
+ *result = (nk_u32_t)nk_svaddv_u32_(svptrue_b32(), distance_sq_u32x);
63
+ }
64
+ NK_PUBLIC void nk_euclidean_i8_svesdot(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_f32_t *result) {
65
+ nk_u32_t distance_sq_u32;
66
+ nk_sqeuclidean_i8_svesdot(a, b, n, &distance_sq_u32);
67
+ *result = nk_f32_sqrt_neon((nk_f32_t)distance_sq_u32);
68
+ }
69
+
70
+ NK_PUBLIC void nk_angular_i8_svesdot(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_f32_t *result) {
71
+ nk_size_t i = 0;
72
+ svint32_t ab_i32x = svdup_s32(0);
73
+ svint32_t a2_i32x = svdup_s32(0);
74
+ svint32_t b2_i32x = svdup_s32(0);
75
+ do {
76
+ svbool_t predicate_b8x = svwhilelt_b8_u64(i, n);
77
+ svint8_t a_i8x = svld1_s8(predicate_b8x, a + i);
78
+ svint8_t b_i8x = svld1_s8(predicate_b8x, b + i);
79
+ ab_i32x = svdot_s32(ab_i32x, a_i8x, b_i8x);
80
+ a2_i32x = svdot_s32(a2_i32x, a_i8x, a_i8x);
81
+ b2_i32x = svdot_s32(b2_i32x, b_i8x, b_i8x);
82
+ i += svcntb();
83
+ } while (i < n);
84
+
85
+ nk_i32_t ab = (nk_i32_t)nk_svaddv_s32_(svptrue_b32(), ab_i32x);
86
+ nk_i32_t a2 = (nk_i32_t)nk_svaddv_s32_(svptrue_b32(), a2_i32x);
87
+ nk_i32_t b2 = (nk_i32_t)nk_svaddv_s32_(svptrue_b32(), b2_i32x);
88
+ *result = nk_angular_normalize_f32_neon_((nk_f32_t)ab, (nk_f32_t)a2, (nk_f32_t)b2);
89
+ }
90
+
91
+ NK_PUBLIC void nk_sqeuclidean_u8_svesdot(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_u32_t *result) {
92
+ nk_size_t i = 0;
93
+ svuint32_t distance_sq_u32x = svdup_u32(0);
94
+ do {
95
+ svbool_t predicate_b8x = svwhilelt_b8_u64(i, n);
96
+ svuint8_t a_u8x = svld1_u8(predicate_b8x, a + i);
97
+ svuint8_t b_u8x = svld1_u8(predicate_b8x, b + i);
98
+ svuint8_t diff_u8x = svabd_u8_x(predicate_b8x, a_u8x, b_u8x);
99
+ distance_sq_u32x = svdot_u32(distance_sq_u32x, diff_u8x, diff_u8x);
100
+ i += svcntb();
101
+ } while (i < n);
102
+ *result = (nk_u32_t)nk_svaddv_u32_(svptrue_b32(), distance_sq_u32x);
103
+ }
104
+ NK_PUBLIC void nk_euclidean_u8_svesdot(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_f32_t *result) {
105
+ nk_u32_t distance_sq_u32;
106
+ nk_sqeuclidean_u8_svesdot(a, b, n, &distance_sq_u32);
107
+ *result = nk_f32_sqrt_neon((nk_f32_t)distance_sq_u32);
108
+ }
109
+
110
+ NK_PUBLIC void nk_angular_u8_svesdot(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_f32_t *result) {
111
+ nk_size_t i = 0;
112
+ svuint32_t ab_u32x = svdup_u32(0);
113
+ svuint32_t a2_u32x = svdup_u32(0);
114
+ svuint32_t b2_u32x = svdup_u32(0);
115
+ do {
116
+ svbool_t predicate_b8x = svwhilelt_b8_u64(i, n);
117
+ svuint8_t a_u8x = svld1_u8(predicate_b8x, a + i);
118
+ svuint8_t b_u8x = svld1_u8(predicate_b8x, b + i);
119
+ ab_u32x = svdot_u32(ab_u32x, a_u8x, b_u8x);
120
+ a2_u32x = svdot_u32(a2_u32x, a_u8x, a_u8x);
121
+ b2_u32x = svdot_u32(b2_u32x, b_u8x, b_u8x);
122
+ i += svcntb();
123
+ } while (i < n);
124
+
125
+ nk_u32_t ab = (nk_u32_t)nk_svaddv_u32_(svptrue_b32(), ab_u32x);
126
+ nk_u32_t a2 = (nk_u32_t)nk_svaddv_u32_(svptrue_b32(), a2_u32x);
127
+ nk_u32_t b2 = (nk_u32_t)nk_svaddv_u32_(svptrue_b32(), b2_u32x);
128
+ *result = nk_angular_normalize_f32_neon_((nk_f32_t)ab, (nk_f32_t)a2, (nk_f32_t)b2);
129
+ }
130
+
131
+ #if defined(__clang__)
132
+ #pragma clang attribute pop
133
+ #elif defined(__GNUC__)
134
+ #pragma GCC pop_options
135
+ #endif
136
+
137
+ #if defined(__cplusplus)
138
+ } // extern "C"
139
+ #endif
140
+
141
+ #endif // NK_TARGET_SVESDOT
142
+ #endif // NK_TARGET_ARM64_
143
+ #endif // NK_SPATIAL_SVESDOT_H