usearch 2.21.3 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) hide show
  1. package/README.md +24 -24
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +7 -7
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +83 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +235 -52
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/dist/cjs/usearch.d.ts +8 -3
  16. package/javascript/dist/cjs/usearch.js +12 -4
  17. package/javascript/dist/esm/usearch.d.ts +8 -3
  18. package/javascript/dist/esm/usearch.js +12 -4
  19. package/javascript/lib.cpp +17 -0
  20. package/javascript/usearch.ts +14 -6
  21. package/numkong/.clang-tidy +30 -0
  22. package/{simsimd → numkong}/.cmake-format.py +18 -0
  23. package/numkong/.editorconfig +12 -0
  24. package/numkong/.git-blame-ignore-revs +123 -0
  25. package/numkong/.mailmap +15 -0
  26. package/numkong/.spi.yml +11 -0
  27. package/numkong/.swift-format +14 -0
  28. package/numkong/CITATION.cff +81 -0
  29. package/numkong/CONTRIBUTING.md +500 -0
  30. package/numkong/Cargo.toml +54 -0
  31. package/numkong/MANIFEST.in +8 -0
  32. package/numkong/Package.swift +84 -0
  33. package/numkong/README.md +569 -0
  34. package/numkong/bench/README.md +217 -0
  35. package/numkong/bench/bench-browser.html +323 -0
  36. package/numkong/bench/bench.cpp +344 -0
  37. package/numkong/bench/bench.hpp +816 -0
  38. package/numkong/bench/bench.js +148 -0
  39. package/numkong/bench/bench.mjs +616 -0
  40. package/numkong/bench/bench_attention.cpp +113 -0
  41. package/numkong/bench/bench_cast.cpp +264 -0
  42. package/numkong/bench/bench_cross_amx.cpp +62 -0
  43. package/numkong/bench/bench_cross_arm.cpp +245 -0
  44. package/numkong/bench/bench_cross_blas.cpp +309 -0
  45. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  46. package/numkong/bench/bench_cross_power.cpp +84 -0
  47. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  48. package/numkong/bench/bench_cross_serial.cpp +151 -0
  49. package/numkong/bench/bench_cross_sme.cpp +163 -0
  50. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  51. package/numkong/bench/bench_cross_x86.cpp +455 -0
  52. package/numkong/bench/bench_curved.cpp +210 -0
  53. package/numkong/bench/bench_dot.cpp +315 -0
  54. package/numkong/bench/bench_each.cpp +503 -0
  55. package/numkong/bench/bench_geospatial.cpp +112 -0
  56. package/numkong/bench/bench_maxsim.cpp +154 -0
  57. package/numkong/bench/bench_mesh.cpp +148 -0
  58. package/numkong/bench/bench_probability.cpp +60 -0
  59. package/numkong/bench/bench_reduce.cpp +371 -0
  60. package/numkong/bench/bench_set.cpp +73 -0
  61. package/numkong/bench/bench_sparse.cpp +198 -0
  62. package/numkong/bench/bench_spatial.cpp +347 -0
  63. package/numkong/bench/bench_trigonometry.cpp +137 -0
  64. package/numkong/bench/swift/Bench.swift +506 -0
  65. package/numkong/binding.gyp +169 -0
  66. package/numkong/build.rs +484 -0
  67. package/numkong/c/dispatch.h +512 -0
  68. package/numkong/c/dispatch_bf16.c +447 -0
  69. package/numkong/c/dispatch_bf16c.c +52 -0
  70. package/numkong/c/dispatch_e2m3.c +296 -0
  71. package/numkong/c/dispatch_e3m2.c +284 -0
  72. package/numkong/c/dispatch_e4m3.c +318 -0
  73. package/numkong/c/dispatch_e5m2.c +316 -0
  74. package/numkong/c/dispatch_f16.c +452 -0
  75. package/numkong/c/dispatch_f16c.c +58 -0
  76. package/numkong/c/dispatch_f32.c +434 -0
  77. package/numkong/c/dispatch_f32c.c +99 -0
  78. package/numkong/c/dispatch_f64.c +348 -0
  79. package/numkong/c/dispatch_f64c.c +98 -0
  80. package/numkong/c/dispatch_i16.c +96 -0
  81. package/numkong/c/dispatch_i32.c +89 -0
  82. package/numkong/c/dispatch_i4.c +153 -0
  83. package/numkong/c/dispatch_i64.c +86 -0
  84. package/numkong/c/dispatch_i8.c +348 -0
  85. package/numkong/c/dispatch_other.c +348 -0
  86. package/numkong/c/dispatch_u1.c +193 -0
  87. package/numkong/c/dispatch_u16.c +124 -0
  88. package/numkong/c/dispatch_u32.c +118 -0
  89. package/numkong/c/dispatch_u4.c +153 -0
  90. package/numkong/c/dispatch_u64.c +102 -0
  91. package/numkong/c/dispatch_u8.c +364 -0
  92. package/numkong/c/numkong.c +940 -0
  93. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  94. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  95. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  96. package/numkong/cmake/nk_math_lib.cmake +46 -0
  97. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  99. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  100. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  101. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  102. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  103. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  104. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  105. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  106. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  107. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  108. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  109. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  110. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  111. package/numkong/include/README.md +643 -0
  112. package/numkong/include/module.modulemap +129 -0
  113. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  114. package/numkong/include/numkong/attention/sme.h +2075 -0
  115. package/numkong/include/numkong/attention.h +49 -0
  116. package/numkong/include/numkong/capabilities.h +930 -0
  117. package/numkong/include/numkong/cast/README.md +262 -0
  118. package/numkong/include/numkong/cast/diamond.h +64 -0
  119. package/numkong/include/numkong/cast/haswell.h +823 -0
  120. package/numkong/include/numkong/cast/icelake.h +475 -0
  121. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  122. package/numkong/include/numkong/cast/neon.h +1174 -0
  123. package/numkong/include/numkong/cast/powervsx.h +449 -0
  124. package/numkong/include/numkong/cast/rvv.h +970 -0
  125. package/numkong/include/numkong/cast/sapphire.h +262 -0
  126. package/numkong/include/numkong/cast/serial.h +2336 -0
  127. package/numkong/include/numkong/cast/skylake.h +915 -0
  128. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  129. package/numkong/include/numkong/cast.h +254 -0
  130. package/numkong/include/numkong/cast.hpp +44 -0
  131. package/numkong/include/numkong/curved/README.md +223 -0
  132. package/numkong/include/numkong/curved/genoa.h +182 -0
  133. package/numkong/include/numkong/curved/haswell.h +276 -0
  134. package/numkong/include/numkong/curved/neon.h +329 -0
  135. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  136. package/numkong/include/numkong/curved/rvv.h +305 -0
  137. package/numkong/include/numkong/curved/serial.h +207 -0
  138. package/numkong/include/numkong/curved/skylake.h +457 -0
  139. package/numkong/include/numkong/curved/smef64.h +530 -0
  140. package/numkong/include/numkong/curved.h +513 -0
  141. package/numkong/include/numkong/curved.hpp +144 -0
  142. package/numkong/include/numkong/dot/README.md +442 -0
  143. package/numkong/include/numkong/dot/alder.h +563 -0
  144. package/numkong/include/numkong/dot/diamond.h +158 -0
  145. package/numkong/include/numkong/dot/genoa.h +289 -0
  146. package/numkong/include/numkong/dot/haswell.h +1723 -0
  147. package/numkong/include/numkong/dot/icelake.h +997 -0
  148. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  149. package/numkong/include/numkong/dot/neon.h +869 -0
  150. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  151. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  152. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  153. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  154. package/numkong/include/numkong/dot/powervsx.h +752 -0
  155. package/numkong/include/numkong/dot/rvv.h +722 -0
  156. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  157. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  158. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  159. package/numkong/include/numkong/dot/sapphire.h +141 -0
  160. package/numkong/include/numkong/dot/serial.h +874 -0
  161. package/numkong/include/numkong/dot/sierra.h +405 -0
  162. package/numkong/include/numkong/dot/skylake.h +1116 -0
  163. package/numkong/include/numkong/dot/sve.h +420 -0
  164. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  165. package/numkong/include/numkong/dot/svehalf.h +168 -0
  166. package/numkong/include/numkong/dot/svesdot.h +90 -0
  167. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  168. package/numkong/include/numkong/dot.h +1136 -0
  169. package/numkong/include/numkong/dot.hpp +94 -0
  170. package/numkong/include/numkong/dots/README.md +496 -0
  171. package/numkong/include/numkong/dots/alder.h +117 -0
  172. package/numkong/include/numkong/dots/diamond.h +86 -0
  173. package/numkong/include/numkong/dots/genoa.h +100 -0
  174. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  175. package/numkong/include/numkong/dots/haswell.h +310 -0
  176. package/numkong/include/numkong/dots/icelake.h +180 -0
  177. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  178. package/numkong/include/numkong/dots/neon.h +123 -0
  179. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  180. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  181. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  182. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  183. package/numkong/include/numkong/dots/powervsx.h +194 -0
  184. package/numkong/include/numkong/dots/rvv.h +2593 -0
  185. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  186. package/numkong/include/numkong/dots/serial.h +2867 -0
  187. package/numkong/include/numkong/dots/sierra.h +100 -0
  188. package/numkong/include/numkong/dots/skylake.h +207 -0
  189. package/numkong/include/numkong/dots/sme.h +5041 -0
  190. package/numkong/include/numkong/dots/smebi32.h +477 -0
  191. package/numkong/include/numkong/dots/smef64.h +1328 -0
  192. package/numkong/include/numkong/dots/smehalf.h +47 -0
  193. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  194. package/numkong/include/numkong/dots.h +3110 -0
  195. package/numkong/include/numkong/dots.hpp +641 -0
  196. package/numkong/include/numkong/each/README.md +465 -0
  197. package/numkong/include/numkong/each/haswell.h +1658 -0
  198. package/numkong/include/numkong/each/icelake.h +272 -0
  199. package/numkong/include/numkong/each/neon.h +1138 -0
  200. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  201. package/numkong/include/numkong/each/neonhalf.h +318 -0
  202. package/numkong/include/numkong/each/rvv.h +1121 -0
  203. package/numkong/include/numkong/each/sapphire.h +343 -0
  204. package/numkong/include/numkong/each/serial.h +282 -0
  205. package/numkong/include/numkong/each/skylake.h +1562 -0
  206. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  207. package/numkong/include/numkong/each.h +2232 -0
  208. package/numkong/include/numkong/each.hpp +434 -0
  209. package/numkong/include/numkong/geospatial/README.md +147 -0
  210. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  211. package/numkong/include/numkong/geospatial/neon.h +615 -0
  212. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  213. package/numkong/include/numkong/geospatial/serial.h +309 -0
  214. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  215. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  216. package/numkong/include/numkong/geospatial.h +453 -0
  217. package/numkong/include/numkong/geospatial.hpp +235 -0
  218. package/numkong/include/numkong/matrix.hpp +336 -0
  219. package/numkong/include/numkong/maxsim/README.md +187 -0
  220. package/numkong/include/numkong/maxsim/alder.h +511 -0
  221. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  222. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  223. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  224. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  225. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  226. package/numkong/include/numkong/maxsim/serial.h +490 -0
  227. package/numkong/include/numkong/maxsim/sme.h +993 -0
  228. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  229. package/numkong/include/numkong/maxsim.h +571 -0
  230. package/numkong/include/numkong/maxsim.hpp +133 -0
  231. package/numkong/include/numkong/mesh/README.md +219 -0
  232. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  233. package/numkong/include/numkong/mesh/neon.h +1821 -0
  234. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  235. package/numkong/include/numkong/mesh/rvv.h +936 -0
  236. package/numkong/include/numkong/mesh/serial.h +721 -0
  237. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  238. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  239. package/numkong/include/numkong/mesh.h +666 -0
  240. package/numkong/include/numkong/mesh.hpp +701 -0
  241. package/numkong/include/numkong/numkong.h +78 -0
  242. package/numkong/include/numkong/numkong.hpp +58 -0
  243. package/numkong/include/numkong/probability/README.md +177 -0
  244. package/numkong/include/numkong/probability/haswell.h +267 -0
  245. package/numkong/include/numkong/probability/neon.h +255 -0
  246. package/numkong/include/numkong/probability/rvv.h +414 -0
  247. package/numkong/include/numkong/probability/serial.h +181 -0
  248. package/numkong/include/numkong/probability/skylake.h +324 -0
  249. package/numkong/include/numkong/probability.h +380 -0
  250. package/numkong/include/numkong/probability.hpp +120 -0
  251. package/numkong/include/numkong/random.h +50 -0
  252. package/numkong/include/numkong/random.hpp +285 -0
  253. package/numkong/include/numkong/reduce/README.md +552 -0
  254. package/numkong/include/numkong/reduce/alder.h +636 -0
  255. package/numkong/include/numkong/reduce/genoa.h +201 -0
  256. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  257. package/numkong/include/numkong/reduce/icelake.h +549 -0
  258. package/numkong/include/numkong/reduce/neon.h +3980 -0
  259. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  260. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  261. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  262. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  263. package/numkong/include/numkong/reduce/serial.h +753 -0
  264. package/numkong/include/numkong/reduce/sierra.h +338 -0
  265. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  266. package/numkong/include/numkong/reduce/sve.h +52 -0
  267. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  268. package/numkong/include/numkong/reduce.h +1582 -0
  269. package/numkong/include/numkong/reduce.hpp +778 -0
  270. package/numkong/include/numkong/scalar/README.md +89 -0
  271. package/numkong/include/numkong/scalar/haswell.h +122 -0
  272. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  273. package/numkong/include/numkong/scalar/neon.h +122 -0
  274. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  275. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  276. package/numkong/include/numkong/scalar/rvv.h +211 -0
  277. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  278. package/numkong/include/numkong/scalar/serial.h +332 -0
  279. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  280. package/numkong/include/numkong/scalar.h +696 -0
  281. package/numkong/include/numkong/set/README.md +179 -0
  282. package/numkong/include/numkong/set/haswell.h +334 -0
  283. package/numkong/include/numkong/set/icelake.h +485 -0
  284. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  285. package/numkong/include/numkong/set/neon.h +363 -0
  286. package/numkong/include/numkong/set/powervsx.h +326 -0
  287. package/numkong/include/numkong/set/rvv.h +226 -0
  288. package/numkong/include/numkong/set/rvvbb.h +117 -0
  289. package/numkong/include/numkong/set/serial.h +174 -0
  290. package/numkong/include/numkong/set/sve.h +187 -0
  291. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  292. package/numkong/include/numkong/set.h +471 -0
  293. package/numkong/include/numkong/set.hpp +114 -0
  294. package/numkong/include/numkong/sets/README.md +149 -0
  295. package/numkong/include/numkong/sets/haswell.h +63 -0
  296. package/numkong/include/numkong/sets/icelake.h +66 -0
  297. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  298. package/numkong/include/numkong/sets/neon.h +61 -0
  299. package/numkong/include/numkong/sets/powervsx.h +65 -0
  300. package/numkong/include/numkong/sets/serial.h +43 -0
  301. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  302. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  303. package/numkong/include/numkong/sets.h +382 -0
  304. package/numkong/include/numkong/sparse/README.md +156 -0
  305. package/numkong/include/numkong/sparse/icelake.h +463 -0
  306. package/numkong/include/numkong/sparse/neon.h +288 -0
  307. package/numkong/include/numkong/sparse/serial.h +117 -0
  308. package/numkong/include/numkong/sparse/sve2.h +504 -0
  309. package/numkong/include/numkong/sparse/turin.h +322 -0
  310. package/numkong/include/numkong/sparse.h +363 -0
  311. package/numkong/include/numkong/sparse.hpp +113 -0
  312. package/numkong/include/numkong/spatial/README.md +439 -0
  313. package/numkong/include/numkong/spatial/alder.h +604 -0
  314. package/numkong/include/numkong/spatial/diamond.h +240 -0
  315. package/numkong/include/numkong/spatial/genoa.h +222 -0
  316. package/numkong/include/numkong/spatial/haswell.h +979 -0
  317. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  318. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  319. package/numkong/include/numkong/spatial/neon.h +846 -0
  320. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  321. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  322. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  323. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  324. package/numkong/include/numkong/spatial/rvv.h +991 -0
  325. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  326. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  327. package/numkong/include/numkong/spatial/serial.h +347 -0
  328. package/numkong/include/numkong/spatial/sierra.h +516 -0
  329. package/numkong/include/numkong/spatial/skylake.h +605 -0
  330. package/numkong/include/numkong/spatial/sve.h +246 -0
  331. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  332. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  333. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  334. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  335. package/numkong/include/numkong/spatial.h +1681 -0
  336. package/numkong/include/numkong/spatial.hpp +183 -0
  337. package/numkong/include/numkong/spatials/README.md +580 -0
  338. package/numkong/include/numkong/spatials/alder.h +94 -0
  339. package/numkong/include/numkong/spatials/diamond.h +82 -0
  340. package/numkong/include/numkong/spatials/genoa.h +94 -0
  341. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  342. package/numkong/include/numkong/spatials/haswell.h +219 -0
  343. package/numkong/include/numkong/spatials/icelake.h +113 -0
  344. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  345. package/numkong/include/numkong/spatials/neon.h +109 -0
  346. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  347. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  348. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  349. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  350. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  351. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  352. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  353. package/numkong/include/numkong/spatials/serial.h +248 -0
  354. package/numkong/include/numkong/spatials/sierra.h +96 -0
  355. package/numkong/include/numkong/spatials/skylake.h +184 -0
  356. package/numkong/include/numkong/spatials/sme.h +1927 -0
  357. package/numkong/include/numkong/spatials/smef64.h +483 -0
  358. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  359. package/numkong/include/numkong/spatials.h +3374 -0
  360. package/numkong/include/numkong/spatials.hpp +509 -0
  361. package/numkong/include/numkong/tensor.hpp +1981 -0
  362. package/numkong/include/numkong/trigonometry/README.md +184 -0
  363. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  364. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  365. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  366. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  367. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  368. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  369. package/numkong/include/numkong/trigonometry.h +467 -0
  370. package/numkong/include/numkong/trigonometry.hpp +166 -0
  371. package/numkong/include/numkong/types.h +1695 -0
  372. package/numkong/include/numkong/types.hpp +6027 -0
  373. package/numkong/include/numkong/vector.hpp +766 -0
  374. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  375. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  376. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  377. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  378. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  380. package/numkong/javascript/README.md +254 -0
  381. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  382. package/numkong/javascript/numkong-browser.ts +40 -0
  383. package/numkong/javascript/numkong-wasm.ts +750 -0
  384. package/numkong/javascript/numkong.c +712 -0
  385. package/numkong/javascript/numkong.ts +613 -0
  386. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  387. package/numkong/javascript/tsconfig-cjs.json +13 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  389. package/numkong/javascript/types.ts +784 -0
  390. package/numkong/numkong.gypi +104 -0
  391. package/numkong/package.json +108 -0
  392. package/numkong/probes/arm_neon.c +8 -0
  393. package/numkong/probes/arm_neon_bfdot.c +9 -0
  394. package/numkong/probes/arm_neon_fhm.c +9 -0
  395. package/numkong/probes/arm_neon_half.c +8 -0
  396. package/numkong/probes/arm_neon_sdot.c +9 -0
  397. package/numkong/probes/arm_neonfp8.c +9 -0
  398. package/numkong/probes/arm_sme.c +16 -0
  399. package/numkong/probes/arm_sme2.c +16 -0
  400. package/numkong/probes/arm_sme2p1.c +16 -0
  401. package/numkong/probes/arm_sme_bf16.c +16 -0
  402. package/numkong/probes/arm_sme_bi32.c +16 -0
  403. package/numkong/probes/arm_sme_f64.c +16 -0
  404. package/numkong/probes/arm_sme_fa64.c +14 -0
  405. package/numkong/probes/arm_sme_half.c +16 -0
  406. package/numkong/probes/arm_sme_lut2.c +15 -0
  407. package/numkong/probes/arm_sve.c +18 -0
  408. package/numkong/probes/arm_sve2.c +20 -0
  409. package/numkong/probes/arm_sve2p1.c +18 -0
  410. package/numkong/probes/arm_sve_bfdot.c +20 -0
  411. package/numkong/probes/arm_sve_half.c +18 -0
  412. package/numkong/probes/arm_sve_sdot.c +21 -0
  413. package/numkong/probes/loongarch_lasx.c +12 -0
  414. package/numkong/probes/power_vsx.c +12 -0
  415. package/numkong/probes/probe.js +127 -0
  416. package/numkong/probes/riscv_rvv.c +14 -0
  417. package/numkong/probes/riscv_rvv_bb.c +15 -0
  418. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  419. package/numkong/probes/riscv_rvv_half.c +14 -0
  420. package/numkong/probes/wasm_v128relaxed.c +11 -0
  421. package/numkong/probes/x86_alder.c +17 -0
  422. package/numkong/probes/x86_diamond.c +17 -0
  423. package/numkong/probes/x86_genoa.c +17 -0
  424. package/numkong/probes/x86_graniteamx.c +19 -0
  425. package/numkong/probes/x86_haswell.c +11 -0
  426. package/numkong/probes/x86_icelake.c +17 -0
  427. package/numkong/probes/x86_sapphire.c +16 -0
  428. package/numkong/probes/x86_sapphireamx.c +18 -0
  429. package/numkong/probes/x86_sierra.c +17 -0
  430. package/numkong/probes/x86_skylake.c +15 -0
  431. package/numkong/probes/x86_turin.c +17 -0
  432. package/numkong/rust/README.md +698 -0
  433. package/numkong/rust/capabilities.rs +96 -0
  434. package/numkong/rust/cast.rs +314 -0
  435. package/numkong/rust/curved.rs +391 -0
  436. package/numkong/rust/each.rs +2721 -0
  437. package/numkong/rust/geospatial.rs +343 -0
  438. package/numkong/rust/matrix.rs +5424 -0
  439. package/numkong/rust/maxsim.rs +540 -0
  440. package/numkong/rust/mesh.rs +837 -0
  441. package/numkong/rust/numkong.rs +409 -0
  442. package/numkong/rust/probability.rs +272 -0
  443. package/numkong/rust/reduce.rs +1249 -0
  444. package/numkong/rust/set.rs +194 -0
  445. package/numkong/rust/sparse.rs +513 -0
  446. package/numkong/rust/spatial.rs +1815 -0
  447. package/numkong/rust/tensor.rs +7565 -0
  448. package/numkong/rust/types.rs +3666 -0
  449. package/numkong/rust/vector.rs +1899 -0
  450. package/numkong/rustfmt.toml +2 -0
  451. package/numkong/swift/Matrix.swift +1388 -0
  452. package/numkong/swift/MaxSim.swift +151 -0
  453. package/numkong/swift/NumKong.swift +283 -0
  454. package/numkong/swift/Numerics.swift +329 -0
  455. package/numkong/swift/README.md +433 -0
  456. package/numkong/swift/Scalar.swift +741 -0
  457. package/numkong/swift/Tensor.swift +209 -0
  458. package/numkong/test/README.md +315 -0
  459. package/numkong/test/playwright.config.ts +16 -0
  460. package/numkong/test/swift/Test.swift +534 -0
  461. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  462. package/numkong/test/test-browser-bundle.html +188 -0
  463. package/numkong/test/test-browser-runner.mjs +43 -0
  464. package/numkong/test/test-browser.html +305 -0
  465. package/numkong/test/test-dtypes.mjs +453 -0
  466. package/numkong/test/test-wasm.mjs +267 -0
  467. package/numkong/test/test.cpp +442 -0
  468. package/numkong/test/test.hpp +580 -0
  469. package/numkong/test/test.mjs +363 -0
  470. package/numkong/test/test_base.py +1041 -0
  471. package/numkong/test/test_cast.cpp +242 -0
  472. package/numkong/test/test_cross.hpp +551 -0
  473. package/numkong/test/test_cross.py +467 -0
  474. package/numkong/test/test_cross_amx.cpp +50 -0
  475. package/numkong/test/test_cross_arm.cpp +225 -0
  476. package/numkong/test/test_cross_blas.cpp +354 -0
  477. package/numkong/test/test_cross_loongarch.cpp +90 -0
  478. package/numkong/test/test_cross_power.cpp +73 -0
  479. package/numkong/test/test_cross_rvv.cpp +109 -0
  480. package/numkong/test/test_cross_serial.cpp +181 -0
  481. package/numkong/test/test_cross_sme.cpp +148 -0
  482. package/numkong/test/test_cross_wasm.cpp +141 -0
  483. package/numkong/test/test_cross_x86.cpp +442 -0
  484. package/numkong/test/test_curved.cpp +182 -0
  485. package/numkong/test/test_curved.py +207 -0
  486. package/numkong/test/test_dot.cpp +353 -0
  487. package/numkong/test/test_dot.py +296 -0
  488. package/numkong/test/test_each.cpp +437 -0
  489. package/numkong/test/test_each.py +756 -0
  490. package/numkong/test/test_geospatial.cpp +155 -0
  491. package/numkong/test/test_geospatial.py +241 -0
  492. package/numkong/test/test_maxsim.cpp +138 -0
  493. package/numkong/test/test_maxsim.py +209 -0
  494. package/numkong/test/test_mesh.cpp +203 -0
  495. package/numkong/test/test_mesh.py +394 -0
  496. package/numkong/test/test_probability.cpp +136 -0
  497. package/numkong/test/test_probability.py +166 -0
  498. package/numkong/test/test_reduce.cpp +563 -0
  499. package/numkong/test/test_reduce.py +781 -0
  500. package/numkong/test/test_set.cpp +151 -0
  501. package/numkong/test/test_set.py +120 -0
  502. package/numkong/test/test_similarities.py +579 -0
  503. package/numkong/test/test_sparse.cpp +121 -0
  504. package/numkong/test/test_sparse.py +118 -0
  505. package/numkong/test/test_spatial.cpp +518 -0
  506. package/numkong/test/test_spatial.py +269 -0
  507. package/numkong/test/test_tensor.cpp +884 -0
  508. package/numkong/test/test_tensor.py +1417 -0
  509. package/numkong/test/test_trigonometry.cpp +156 -0
  510. package/numkong/test/test_trigonometry.py +180 -0
  511. package/package.json +7 -8
  512. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  513. package/prebuilds/linux-arm64/usearch.node +0 -0
  514. package/prebuilds/linux-x64/usearch.node +0 -0
  515. package/fp16/CMakeLists.txt +0 -176
  516. package/fp16/LICENSE +0 -11
  517. package/fp16/README.md +0 -20
  518. package/fp16/bench/alt-element.cc +0 -89
  519. package/fp16/bench/from-alt-array.cc +0 -175
  520. package/fp16/bench/from-ieee-array.cc +0 -399
  521. package/fp16/bench/ieee-element.cc +0 -272
  522. package/fp16/bench/to-alt-array.cc +0 -91
  523. package/fp16/bench/to-ieee-array.cc +0 -303
  524. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  525. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  526. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  527. package/fp16/configure.py +0 -65
  528. package/fp16/confu.yaml +0 -8
  529. package/fp16/include/fp16/__init__.py +0 -0
  530. package/fp16/include/fp16/avx.py +0 -50
  531. package/fp16/include/fp16/avx2.py +0 -53
  532. package/fp16/include/fp16/bitcasts.h +0 -92
  533. package/fp16/include/fp16/fp16.h +0 -451
  534. package/fp16/include/fp16/psimd.h +0 -131
  535. package/fp16/include/fp16.h +0 -11
  536. package/fp16/jni/Android.mk +0 -6
  537. package/fp16/jni/Application.mk +0 -4
  538. package/fp16/test/alt-from-fp32-value.cc +0 -498
  539. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  540. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  541. package/fp16/test/alt-to-fp32-value.cc +0 -348
  542. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  543. package/fp16/test/bitcasts.cc +0 -56
  544. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  545. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  546. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  547. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  548. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  549. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  550. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  551. package/fp16/test/peachpy/stubs.py +0 -38
  552. package/fp16/test/tables.cc +0 -530
  553. package/fp16/test/tables.h +0 -13
  554. package/fp16/third-party/THHalf.h +0 -92
  555. package/fp16/third-party/eigen-half.h +0 -170
  556. package/fp16/third-party/float16-compressor.h +0 -80
  557. package/fp16/third-party/half.hpp +0 -2916
  558. package/fp16/third-party/npy-halffloat.h +0 -328
  559. package/simsimd/.git-blame-ignore-revs +0 -2
  560. package/simsimd/CONTRIBUTING.md +0 -321
  561. package/simsimd/Cargo.toml +0 -49
  562. package/simsimd/MANIFEST.in +0 -4
  563. package/simsimd/Package.swift +0 -28
  564. package/simsimd/README.md +0 -1493
  565. package/simsimd/binding.gyp +0 -35
  566. package/simsimd/build.rs +0 -70
  567. package/simsimd/c/lib.c +0 -374
  568. package/simsimd/include/module.modulemap +0 -4
  569. package/simsimd/include/simsimd/binary.h +0 -486
  570. package/simsimd/include/simsimd/curved.h +0 -1541
  571. package/simsimd/include/simsimd/dot.h +0 -1853
  572. package/simsimd/include/simsimd/elementwise.h +0 -2465
  573. package/simsimd/include/simsimd/geospatial.h +0 -43
  574. package/simsimd/include/simsimd/mesh.h +0 -69
  575. package/simsimd/include/simsimd/probability.h +0 -606
  576. package/simsimd/include/simsimd/simsimd.h +0 -2567
  577. package/simsimd/include/simsimd/sparse.h +0 -1384
  578. package/simsimd/include/simsimd/spatial.h +0 -2335
  579. package/simsimd/include/simsimd/types.h +0 -666
  580. package/simsimd/javascript/fallback.ts +0 -233
  581. package/simsimd/javascript/lib.c +0 -125
  582. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  583. package/simsimd/javascript/simsimd.ts +0 -179
  584. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  585. package/simsimd/package-lock.json +0 -1761
  586. package/simsimd/package.json +0 -61
  587. package/simsimd/rust/lib.rs +0 -1821
  588. package/simsimd/scripts/bench.cxx +0 -1170
  589. package/simsimd/scripts/bench.ipynb +0 -187
  590. package/simsimd/scripts/bench.js +0 -127
  591. package/simsimd/scripts/bench.rs +0 -876
  592. package/simsimd/scripts/bench_vectors.py +0 -734
  593. package/simsimd/scripts/bench_vectors_live.py +0 -213
  594. package/simsimd/scripts/test.c +0 -187
  595. package/simsimd/scripts/test.mjs +0 -220
  596. package/simsimd/scripts/test.py +0 -1505
  597. package/simsimd/swift/SimSIMD.swift +0 -149
  598. package/simsimd/swift/Test.swift +0 -128
  599. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  600. /package/{simsimd → numkong}/LICENSE +0 -0
  601. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  602. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,738 @@
1
+ /**
2
+ * @brief SIMD-accelerated Spatial Similarity Measures for Power VSX.
3
+ * @file include/numkong/spatial/powervsx.h
4
+ * @author Ash Vardanian
5
+ * @date March 23, 2026
6
+ *
7
+ * @sa include/numkong/spatial.h
8
+ *
9
+ * @section spatial_powervsx_instructions Key Power VSX Spatial Instructions
10
+ *
11
+ * Power ISA 3.0 (POWER9+) VSX instructions for distance computations:
12
+ *
13
+ * Intrinsic Instruction POWER9
14
+ * vec_madd(f32) XVMADDASP 5cy
15
+ * vec_mul(f32) XVMULSP 5cy
16
+ * vec_add(f32) XVADDSP 5cy
17
+ * vec_sub(f32) XVSUBSP 5cy
18
+ * vec_rsqrte(f32) XVRSQRTESP 5cy
19
+ * vec_sqrt(f32) XVSQRTSP 26cy
20
+ * vec_doublee XVCVSPDP 3cy (f32 → f64 even elts)
21
+ * vec_xl_len LXVL 5cy (partial vector load)
22
+ * vec_extract_fp32_from_shorth XVCVHPSP 5cy (f16 → f32 high half)
23
+ * vec_extract_fp32_from_shortl XVCVHPSP 5cy (f16 → f32 low half)
24
+ * vec_msum(i8, u8, i32) VMSUMMBM 5cy (i8×u8 widening multiply-sum)
25
+ * vec_msum(u8, u8, u32) VMSUMUBM 5cy (u8×u8 widening multiply-sum)
26
+ * vec_unpackh(i8) VUPKHSB 2cy (sign-extend high 8 i8 → i16x8)
27
+ * vec_unpackl(i8) VUPKLSB 2cy (sign-extend low 8 i8 → i16x8)
28
+ *
29
+ * For angular distance, `vec_rsqrte` provides ~12-bit precision. Two Newton-Raphson
30
+ * iterations achieve ~23-bit precision for f32, three iterations for f64.
31
+ */
32
+ #ifndef NK_SPATIAL_POWERVSX_H
33
+ #define NK_SPATIAL_POWERVSX_H
34
+
35
+ #if NK_TARGET_POWER64_
36
+ #if NK_TARGET_POWERVSX
37
+
38
+ #include "numkong/types.h"
39
+ #include "numkong/dot/powervsx.h" // `nk_hsum_*_powervsx_`, includes cast/powervsx.h
40
+ #include "numkong/scalar/powervsx.h" // `nk_f32_sqrt_powervsx`, `nk_f64_sqrt_powervsx`
41
+
42
+ #if defined(__cplusplus)
43
+ extern "C" {
44
+ #endif
45
+
46
+ #if defined(__clang__)
47
+ #pragma clang attribute push(__attribute__((target("power9-vector"))), apply_to = function)
48
+ #elif defined(__GNUC__)
49
+ #pragma GCC push_options
50
+ #pragma GCC target("power9-vector")
51
+ #endif
52
+
53
+ /**
54
+ * @brief Reciprocal square root of 4 floats with Newton-Raphson refinement.
55
+ *
56
+ * Uses `vec_rsqrte` (~12-bit initial estimate) followed by two Newton-Raphson
57
+ * iterations, achieving ~23-bit precision sufficient for f32.
58
+ * NR step: rsqrt = rsqrt × (1.5 − 0.5 × x × rsqrt × rsqrt)
59
+ */
60
+ NK_INTERNAL nk_vf32x4_t nk_rsqrt_f32x4_powervsx_(nk_vf32x4_t x) {
61
+ nk_vf32x4_t half_f32x4 = vec_splats(0.5f);
62
+ nk_vf32x4_t three_halves_f32x4 = vec_splats(1.5f);
63
+ nk_vf32x4_t rsqrt_f32x4 = vec_rsqrte(x);
64
+ // Iteration 1
65
+ nk_vf32x4_t nr_f32x4 = vec_sub(three_halves_f32x4,
66
+ vec_mul(half_f32x4, vec_mul(x, vec_mul(rsqrt_f32x4, rsqrt_f32x4))));
67
+ rsqrt_f32x4 = vec_mul(rsqrt_f32x4, nr_f32x4);
68
+ // Iteration 2
69
+ nr_f32x4 = vec_sub(three_halves_f32x4, vec_mul(half_f32x4, vec_mul(x, vec_mul(rsqrt_f32x4, rsqrt_f32x4))));
70
+ rsqrt_f32x4 = vec_mul(rsqrt_f32x4, nr_f32x4);
71
+ return rsqrt_f32x4;
72
+ }
73
+
74
+ /**
75
+ * @brief Reciprocal square root of 2 doubles with Newton-Raphson refinement.
76
+ *
77
+ * Uses `vec_rsqrte` (~12-bit estimate) followed by three Newton-Raphson
78
+ * iterations, achieving ~48-bit precision for f64.
79
+ */
80
+ NK_INTERNAL nk_vf64x2_t nk_rsqrt_f64x2_powervsx_(nk_vf64x2_t x) {
81
+ nk_vf64x2_t half_f64x2 = vec_splats(0.5);
82
+ nk_vf64x2_t three_halves_f64x2 = vec_splats(1.5);
83
+ nk_vf64x2_t rsqrt_f64x2 = vec_rsqrte(x);
84
+ // Iteration 1
85
+ nk_vf64x2_t nr_f64x2 = vec_sub(three_halves_f64x2,
86
+ vec_mul(half_f64x2, vec_mul(x, vec_mul(rsqrt_f64x2, rsqrt_f64x2))));
87
+ rsqrt_f64x2 = vec_mul(rsqrt_f64x2, nr_f64x2);
88
+ // Iteration 2
89
+ nr_f64x2 = vec_sub(three_halves_f64x2, vec_mul(half_f64x2, vec_mul(x, vec_mul(rsqrt_f64x2, rsqrt_f64x2))));
90
+ rsqrt_f64x2 = vec_mul(rsqrt_f64x2, nr_f64x2);
91
+ // Iteration 3
92
+ nr_f64x2 = vec_sub(three_halves_f64x2, vec_mul(half_f64x2, vec_mul(x, vec_mul(rsqrt_f64x2, rsqrt_f64x2))));
93
+ rsqrt_f64x2 = vec_mul(rsqrt_f64x2, nr_f64x2);
94
+ return rsqrt_f64x2;
95
+ }
96
+
97
+ NK_INTERNAL nk_f32_t nk_angular_normalize_f32_powervsx_(nk_f32_t ab, nk_f32_t a2, nk_f32_t b2) {
98
+ if (a2 == 0 && b2 == 0) return 0;
99
+ if (ab == 0) return 1;
100
+ nk_vf32x4_t squares_f32x4 = vec_splats(0.0f);
101
+ squares_f32x4 = vec_insert(a2, squares_f32x4, 0);
102
+ squares_f32x4 = vec_insert(b2, squares_f32x4, 1);
103
+ nk_vf32x4_t rsqrts_f32x4 = nk_rsqrt_f32x4_powervsx_(squares_f32x4);
104
+ nk_f32_t a2_rsqrt = vec_extract(rsqrts_f32x4, 0);
105
+ nk_f32_t b2_rsqrt = vec_extract(rsqrts_f32x4, 1);
106
+ nk_f32_t result = 1 - ab * a2_rsqrt * b2_rsqrt;
107
+ return result > 0 ? result : 0;
108
+ }
109
+
110
+ NK_INTERNAL nk_f64_t nk_angular_normalize_f64_powervsx_(nk_f64_t ab, nk_f64_t a2, nk_f64_t b2) {
111
+ if (a2 == 0 && b2 == 0) return 0;
112
+ if (ab == 0) return 1;
113
+ nk_vf64x2_t squares_f64x2 = vec_splats(0.0);
114
+ squares_f64x2 = vec_insert(a2, squares_f64x2, 0);
115
+ squares_f64x2 = vec_insert(b2, squares_f64x2, 1);
116
+ nk_vf64x2_t rsqrts_f64x2 = nk_rsqrt_f64x2_powervsx_(squares_f64x2);
117
+ nk_f64_t a2_rsqrt = vec_extract(rsqrts_f64x2, 0);
118
+ nk_f64_t b2_rsqrt = vec_extract(rsqrts_f64x2, 1);
119
+ nk_f64_t result = 1 - ab * a2_rsqrt * b2_rsqrt;
120
+ return result > 0 ? result : 0;
121
+ }
122
+
123
+ #pragma region F32 and F64 Floats
124
+
125
+ NK_PUBLIC void nk_sqeuclidean_f32_powervsx(nk_f32_t const *a, nk_f32_t const *b, nk_size_t n, nk_f64_t *result) {
126
+ // Accumulate in f64 for numerical stability using vec_doublee/vec_doubleo (f32 → f64)
127
+ nk_vf64x2_t sum_even_f64x2 = vec_splats((nk_f64_t)0);
128
+ nk_vf64x2_t sum_odd_f64x2 = vec_splats((nk_f64_t)0);
129
+ nk_vf32x4_t a_f32x4, b_f32x4;
130
+ nk_size_t tail_bytes;
131
+
132
+ nk_sqeuclidean_f32_powervsx_cycle:
133
+ if (n < 4) {
134
+ tail_bytes = n * sizeof(nk_f32_t);
135
+ a_f32x4 = vec_xl_len((nk_f32_t *)a, tail_bytes);
136
+ b_f32x4 = vec_xl_len((nk_f32_t *)b, tail_bytes);
137
+ n = 0;
138
+ }
139
+ else {
140
+ a_f32x4 = vec_xl(0, a);
141
+ b_f32x4 = vec_xl(0, b);
142
+ a += 4, b += 4, n -= 4;
143
+ }
144
+ // Widen a and b to f64 before subtraction to avoid f32 precision loss in (a−b)
145
+ nk_vf64x2_t a_even_f64x2 = vec_doublee(a_f32x4);
146
+ nk_vf64x2_t b_even_f64x2 = vec_doublee(b_f32x4);
147
+ nk_vf64x2_t diff_even_f64x2 = vec_sub(a_even_f64x2, b_even_f64x2);
148
+ sum_even_f64x2 = vec_madd(diff_even_f64x2, diff_even_f64x2, sum_even_f64x2);
149
+ nk_vf64x2_t a_odd_f64x2 = vec_doubleo(a_f32x4);
150
+ nk_vf64x2_t b_odd_f64x2 = vec_doubleo(b_f32x4);
151
+ nk_vf64x2_t diff_odd_f64x2 = vec_sub(a_odd_f64x2, b_odd_f64x2);
152
+ sum_odd_f64x2 = vec_madd(diff_odd_f64x2, diff_odd_f64x2, sum_odd_f64x2);
153
+ if (n) goto nk_sqeuclidean_f32_powervsx_cycle;
154
+
155
+ nk_vf64x2_t total_f64x2 = vec_add(sum_even_f64x2, sum_odd_f64x2);
156
+ *result = nk_hsum_f64x2_powervsx_(total_f64x2);
157
+ }
158
+
159
+ NK_PUBLIC void nk_euclidean_f32_powervsx(nk_f32_t const *a, nk_f32_t const *b, nk_size_t n, nk_f64_t *result) {
160
+ nk_sqeuclidean_f32_powervsx(a, b, n, result);
161
+ *result = nk_f64_sqrt_powervsx(*result);
162
+ }
163
+
164
+ NK_PUBLIC void nk_angular_f32_powervsx(nk_f32_t const *a, nk_f32_t const *b, nk_size_t n, nk_f64_t *result) {
165
+ // Accumulate in f64 for numerical stability using vec_doublee/vec_doubleo
166
+ nk_vf64x2_t ab_even_f64x2 = vec_splats((nk_f64_t)0);
167
+ nk_vf64x2_t ab_odd_f64x2 = vec_splats((nk_f64_t)0);
168
+ nk_vf64x2_t a2_even_f64x2 = vec_splats((nk_f64_t)0);
169
+ nk_vf64x2_t a2_odd_f64x2 = vec_splats((nk_f64_t)0);
170
+ nk_vf64x2_t b2_even_f64x2 = vec_splats((nk_f64_t)0);
171
+ nk_vf64x2_t b2_odd_f64x2 = vec_splats((nk_f64_t)0);
172
+ nk_vf32x4_t a_f32x4, b_f32x4;
173
+ nk_size_t tail_bytes;
174
+
175
+ nk_angular_f32_powervsx_cycle:
176
+ if (n < 4) {
177
+ tail_bytes = n * sizeof(nk_f32_t);
178
+ a_f32x4 = vec_xl_len((nk_f32_t *)a, tail_bytes);
179
+ b_f32x4 = vec_xl_len((nk_f32_t *)b, tail_bytes);
180
+ n = 0;
181
+ }
182
+ else {
183
+ a_f32x4 = vec_xl(0, a);
184
+ b_f32x4 = vec_xl(0, b);
185
+ a += 4, b += 4, n -= 4;
186
+ }
187
+ // Even elements (0, 2) → f64
188
+ nk_vf64x2_t a_even_f64x2 = vec_doublee(a_f32x4);
189
+ nk_vf64x2_t b_even_f64x2 = vec_doublee(b_f32x4);
190
+ ab_even_f64x2 = vec_madd(a_even_f64x2, b_even_f64x2, ab_even_f64x2);
191
+ a2_even_f64x2 = vec_madd(a_even_f64x2, a_even_f64x2, a2_even_f64x2);
192
+ b2_even_f64x2 = vec_madd(b_even_f64x2, b_even_f64x2, b2_even_f64x2);
193
+ // Odd elements (1, 3) → f64: rotate by 4 bytes
194
+ nk_vf32x4_t a_rotated_f32x4 = vec_sld(a_f32x4, a_f32x4, 4);
195
+ nk_vf32x4_t b_rotated_f32x4 = vec_sld(b_f32x4, b_f32x4, 4);
196
+ nk_vf64x2_t a_odd_f64x2 = vec_doublee(a_rotated_f32x4);
197
+ nk_vf64x2_t b_odd_f64x2 = vec_doublee(b_rotated_f32x4);
198
+ ab_odd_f64x2 = vec_madd(a_odd_f64x2, b_odd_f64x2, ab_odd_f64x2);
199
+ a2_odd_f64x2 = vec_madd(a_odd_f64x2, a_odd_f64x2, a2_odd_f64x2);
200
+ b2_odd_f64x2 = vec_madd(b_odd_f64x2, b_odd_f64x2, b2_odd_f64x2);
201
+ if (n) goto nk_angular_f32_powervsx_cycle;
202
+
203
+ nk_f64_t ab = nk_hsum_f64x2_powervsx_(vec_add(ab_even_f64x2, ab_odd_f64x2));
204
+ nk_f64_t a2 = nk_hsum_f64x2_powervsx_(vec_add(a2_even_f64x2, a2_odd_f64x2));
205
+ nk_f64_t b2 = nk_hsum_f64x2_powervsx_(vec_add(b2_even_f64x2, b2_odd_f64x2));
206
+ *result = nk_angular_normalize_f64_powervsx_(ab, a2, b2);
207
+ }
208
+
209
+ NK_PUBLIC void nk_sqeuclidean_f64_powervsx(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
210
+ nk_vf64x2_t sum_f64x2 = vec_splats((nk_f64_t)0);
211
+ nk_vf64x2_t a_f64x2, b_f64x2;
212
+ nk_size_t tail_bytes;
213
+
214
+ nk_sqeuclidean_f64_powervsx_cycle:
215
+ if (n < 2) {
216
+ tail_bytes = n * sizeof(nk_f64_t);
217
+ a_f64x2 = vec_xl_len((nk_f64_t *)a, tail_bytes);
218
+ b_f64x2 = vec_xl_len((nk_f64_t *)b, tail_bytes);
219
+ n = 0;
220
+ }
221
+ else {
222
+ a_f64x2 = vec_xl(0, a);
223
+ b_f64x2 = vec_xl(0, b);
224
+ a += 2, b += 2, n -= 2;
225
+ }
226
+ nk_vf64x2_t diff_f64x2 = vec_sub(a_f64x2, b_f64x2);
227
+ sum_f64x2 = vec_madd(diff_f64x2, diff_f64x2, sum_f64x2);
228
+ if (n) goto nk_sqeuclidean_f64_powervsx_cycle;
229
+
230
+ *result = nk_hsum_f64x2_powervsx_(sum_f64x2);
231
+ }
232
+
233
+ NK_PUBLIC void nk_euclidean_f64_powervsx(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
234
+ nk_sqeuclidean_f64_powervsx(a, b, n, result);
235
+ *result = nk_f64_sqrt_powervsx(*result);
236
+ }
237
+
238
+ NK_PUBLIC void nk_angular_f64_powervsx(nk_f64_t const *a, nk_f64_t const *b, nk_size_t n, nk_f64_t *result) {
239
+ // Dot2 (Ogita-Rump-Oishi) for cross-product ab (may have cancellation),
240
+ // simple FMA for self-products a2/b2 (all positive, no cancellation)
241
+ nk_vf64x2_t ab_sum_f64x2 = vec_splats((nk_f64_t)0);
242
+ nk_vf64x2_t ab_compensation_f64x2 = vec_splats((nk_f64_t)0);
243
+ nk_vf64x2_t a2_f64x2 = vec_splats((nk_f64_t)0);
244
+ nk_vf64x2_t b2_f64x2 = vec_splats((nk_f64_t)0);
245
+ nk_vf64x2_t a_f64x2, b_f64x2;
246
+ nk_size_t tail_bytes;
247
+
248
+ nk_angular_f64_powervsx_cycle:
249
+ if (n < 2) {
250
+ tail_bytes = n * sizeof(nk_f64_t);
251
+ a_f64x2 = vec_xl_len((nk_f64_t *)a, tail_bytes);
252
+ b_f64x2 = vec_xl_len((nk_f64_t *)b, tail_bytes);
253
+ n = 0;
254
+ }
255
+ else {
256
+ a_f64x2 = vec_xl(0, a);
257
+ b_f64x2 = vec_xl(0, b);
258
+ a += 2, b += 2, n -= 2;
259
+ }
260
+ // TwoProd for ab: product = a×b, error = msub(a, b, product) captures rounding error
261
+ nk_vf64x2_t product_f64x2 = vec_mul(a_f64x2, b_f64x2);
262
+ nk_vf64x2_t product_error_f64x2 = vec_msub(a_f64x2, b_f64x2, product_f64x2);
263
+ // TwoSum: (t, q) = TwoSum(sum, product) where t = sum + product rounded, q = error
264
+ nk_vf64x2_t tentative_sum_f64x2 = vec_add(ab_sum_f64x2, product_f64x2);
265
+ nk_vf64x2_t virtual_addend_f64x2 = vec_sub(tentative_sum_f64x2, ab_sum_f64x2);
266
+ nk_vf64x2_t sum_error_f64x2 = vec_add(vec_sub(ab_sum_f64x2, vec_sub(tentative_sum_f64x2, virtual_addend_f64x2)),
267
+ vec_sub(product_f64x2, virtual_addend_f64x2));
268
+ ab_sum_f64x2 = tentative_sum_f64x2;
269
+ ab_compensation_f64x2 = vec_add(ab_compensation_f64x2, vec_add(sum_error_f64x2, product_error_f64x2));
270
+ // Simple FMA for self-products (no cancellation)
271
+ a2_f64x2 = vec_madd(a_f64x2, a_f64x2, a2_f64x2);
272
+ b2_f64x2 = vec_madd(b_f64x2, b_f64x2, b2_f64x2);
273
+ if (n) goto nk_angular_f64_powervsx_cycle;
274
+
275
+ *result = nk_angular_normalize_f64_powervsx_(nk_dot_stable_sum_f64x2_powervsx_(ab_sum_f64x2, ab_compensation_f64x2),
276
+ nk_hsum_f64x2_powervsx_(a2_f64x2), nk_hsum_f64x2_powervsx_(b2_f64x2));
277
+ }
278
+
279
+ #pragma endregion F32 and F64 Floats
280
+ #pragma region F16 and BF16 Floats
281
+
282
+ NK_PUBLIC void nk_sqeuclidean_bf16_powervsx(nk_bf16_t const *a, nk_bf16_t const *b, nk_size_t n, nk_f32_t *result) {
283
+ // bf16 → f32 via merge with zero: places bf16 bits in upper 16 of each f32
284
+ nk_vu16x8_t zero_u16x8 = vec_splats((nk_u16_t)0);
285
+ nk_vf32x4_t sum_f32x4 = vec_splats(0.0f);
286
+ nk_vu16x8_t a_u16x8, b_u16x8;
287
+ nk_size_t tail_bytes;
288
+
289
+ nk_sqeuclidean_bf16_powervsx_cycle:
290
+ if (n < 8) {
291
+ tail_bytes = n * sizeof(nk_bf16_t);
292
+ a_u16x8 = vec_xl_len((nk_u16_t *)a, tail_bytes);
293
+ b_u16x8 = vec_xl_len((nk_u16_t *)b, tail_bytes);
294
+ n = 0;
295
+ }
296
+ else {
297
+ a_u16x8 = vec_xl(0, (nk_u16_t const *)a);
298
+ b_u16x8 = vec_xl(0, (nk_u16_t const *)b);
299
+ a += 8, b += 8, n -= 8;
300
+ }
301
+ nk_vf32x4_t a_high_f32x4 = (nk_vf32x4_t)vec_mergeh(zero_u16x8, a_u16x8);
302
+ nk_vf32x4_t a_low_f32x4 = (nk_vf32x4_t)vec_mergel(zero_u16x8, a_u16x8);
303
+ nk_vf32x4_t b_high_f32x4 = (nk_vf32x4_t)vec_mergeh(zero_u16x8, b_u16x8);
304
+ nk_vf32x4_t b_low_f32x4 = (nk_vf32x4_t)vec_mergel(zero_u16x8, b_u16x8);
305
+ nk_vf32x4_t diff_high_f32x4 = vec_sub(a_high_f32x4, b_high_f32x4);
306
+ nk_vf32x4_t diff_low_f32x4 = vec_sub(a_low_f32x4, b_low_f32x4);
307
+ sum_f32x4 = vec_madd(diff_high_f32x4, diff_high_f32x4, sum_f32x4);
308
+ sum_f32x4 = vec_madd(diff_low_f32x4, diff_low_f32x4, sum_f32x4);
309
+ if (n) goto nk_sqeuclidean_bf16_powervsx_cycle;
310
+ *result = nk_hsum_f32x4_powervsx_(sum_f32x4);
311
+ }
312
+
313
+ NK_PUBLIC void nk_euclidean_bf16_powervsx(nk_bf16_t const *a, nk_bf16_t const *b, nk_size_t n, nk_f32_t *result) {
314
+ nk_sqeuclidean_bf16_powervsx(a, b, n, result);
315
+ *result = nk_f32_sqrt_powervsx(*result);
316
+ }
317
+
318
+ NK_PUBLIC void nk_angular_bf16_powervsx(nk_bf16_t const *a, nk_bf16_t const *b, nk_size_t n, nk_f32_t *result) {
319
+ nk_vu16x8_t zero_u16x8 = vec_splats((nk_u16_t)0);
320
+ nk_vf32x4_t ab_f32x4 = vec_splats(0.0f);
321
+ nk_vf32x4_t a2_f32x4 = vec_splats(0.0f);
322
+ nk_vf32x4_t b2_f32x4 = vec_splats(0.0f);
323
+ nk_vu16x8_t a_u16x8, b_u16x8;
324
+ nk_size_t tail_bytes;
325
+
326
+ nk_angular_bf16_powervsx_cycle:
327
+ if (n < 8) {
328
+ tail_bytes = n * sizeof(nk_bf16_t);
329
+ a_u16x8 = vec_xl_len((nk_u16_t *)a, tail_bytes);
330
+ b_u16x8 = vec_xl_len((nk_u16_t *)b, tail_bytes);
331
+ n = 0;
332
+ }
333
+ else {
334
+ a_u16x8 = vec_xl(0, (nk_u16_t const *)a);
335
+ b_u16x8 = vec_xl(0, (nk_u16_t const *)b);
336
+ a += 8, b += 8, n -= 8;
337
+ }
338
+ nk_vf32x4_t a_high_f32x4 = (nk_vf32x4_t)vec_mergeh(zero_u16x8, a_u16x8);
339
+ nk_vf32x4_t a_low_f32x4 = (nk_vf32x4_t)vec_mergel(zero_u16x8, a_u16x8);
340
+ nk_vf32x4_t b_high_f32x4 = (nk_vf32x4_t)vec_mergeh(zero_u16x8, b_u16x8);
341
+ nk_vf32x4_t b_low_f32x4 = (nk_vf32x4_t)vec_mergel(zero_u16x8, b_u16x8);
342
+ ab_f32x4 = vec_madd(a_high_f32x4, b_high_f32x4, ab_f32x4);
343
+ ab_f32x4 = vec_madd(a_low_f32x4, b_low_f32x4, ab_f32x4);
344
+ a2_f32x4 = vec_madd(a_high_f32x4, a_high_f32x4, a2_f32x4);
345
+ a2_f32x4 = vec_madd(a_low_f32x4, a_low_f32x4, a2_f32x4);
346
+ b2_f32x4 = vec_madd(b_high_f32x4, b_high_f32x4, b2_f32x4);
347
+ b2_f32x4 = vec_madd(b_low_f32x4, b_low_f32x4, b2_f32x4);
348
+ if (n) goto nk_angular_bf16_powervsx_cycle;
349
+ nk_f32_t ab = nk_hsum_f32x4_powervsx_(ab_f32x4);
350
+ nk_f32_t a2 = nk_hsum_f32x4_powervsx_(a2_f32x4);
351
+ nk_f32_t b2 = nk_hsum_f32x4_powervsx_(b2_f32x4);
352
+ *result = nk_angular_normalize_f32_powervsx_(ab, a2, b2);
353
+ }
354
+
355
+ NK_PUBLIC void nk_sqeuclidean_f16_powervsx(nk_f16_t const *a, nk_f16_t const *b, nk_size_t n, nk_f32_t *result) {
356
+ // f16 → f32 via POWER9 hardware XVCVHPSP (vec_extract_fp32_from_shorth/shortl)
357
+ nk_vf32x4_t sum_f32x4 = vec_splats(0.0f);
358
+ nk_vu16x8_t a_u16x8, b_u16x8;
359
+ nk_size_t tail_bytes;
360
+
361
+ nk_sqeuclidean_f16_powervsx_cycle:
362
+ if (n < 8) {
363
+ tail_bytes = n * sizeof(nk_f16_t);
364
+ a_u16x8 = vec_xl_len((nk_u16_t *)a, tail_bytes);
365
+ b_u16x8 = vec_xl_len((nk_u16_t *)b, tail_bytes);
366
+ n = 0;
367
+ }
368
+ else {
369
+ a_u16x8 = vec_xl(0, (nk_u16_t const *)a);
370
+ b_u16x8 = vec_xl(0, (nk_u16_t const *)b);
371
+ a += 8, b += 8, n -= 8;
372
+ }
373
+ nk_vf32x4_t a_high_f32x4 = vec_extract_fp32_from_shorth(a_u16x8);
374
+ nk_vf32x4_t a_low_f32x4 = vec_extract_fp32_from_shortl(a_u16x8);
375
+ nk_vf32x4_t b_high_f32x4 = vec_extract_fp32_from_shorth(b_u16x8);
376
+ nk_vf32x4_t b_low_f32x4 = vec_extract_fp32_from_shortl(b_u16x8);
377
+ nk_vf32x4_t diff_high_f32x4 = vec_sub(a_high_f32x4, b_high_f32x4);
378
+ nk_vf32x4_t diff_low_f32x4 = vec_sub(a_low_f32x4, b_low_f32x4);
379
+ sum_f32x4 = vec_madd(diff_high_f32x4, diff_high_f32x4, sum_f32x4);
380
+ sum_f32x4 = vec_madd(diff_low_f32x4, diff_low_f32x4, sum_f32x4);
381
+ if (n) goto nk_sqeuclidean_f16_powervsx_cycle;
382
+ *result = nk_hsum_f32x4_powervsx_(sum_f32x4);
383
+ }
384
+
385
+ NK_PUBLIC void nk_euclidean_f16_powervsx(nk_f16_t const *a, nk_f16_t const *b, nk_size_t n, nk_f32_t *result) {
386
+ nk_sqeuclidean_f16_powervsx(a, b, n, result);
387
+ *result = nk_f32_sqrt_powervsx(*result);
388
+ }
389
+
390
+ NK_PUBLIC void nk_angular_f16_powervsx(nk_f16_t const *a, nk_f16_t const *b, nk_size_t n, nk_f32_t *result) {
391
+ // f16 → f32 via POWER9 hardware XVCVHPSP
392
+ nk_vf32x4_t ab_f32x4 = vec_splats(0.0f);
393
+ nk_vf32x4_t a2_f32x4 = vec_splats(0.0f);
394
+ nk_vf32x4_t b2_f32x4 = vec_splats(0.0f);
395
+ nk_vu16x8_t a_u16x8, b_u16x8;
396
+ nk_size_t tail_bytes;
397
+
398
+ nk_angular_f16_powervsx_cycle:
399
+ if (n < 8) {
400
+ tail_bytes = n * sizeof(nk_f16_t);
401
+ a_u16x8 = vec_xl_len((nk_u16_t *)a, tail_bytes);
402
+ b_u16x8 = vec_xl_len((nk_u16_t *)b, tail_bytes);
403
+ n = 0;
404
+ }
405
+ else {
406
+ a_u16x8 = vec_xl(0, (nk_u16_t const *)a);
407
+ b_u16x8 = vec_xl(0, (nk_u16_t const *)b);
408
+ a += 8, b += 8, n -= 8;
409
+ }
410
+ nk_vf32x4_t a_high_f32x4 = vec_extract_fp32_from_shorth(a_u16x8);
411
+ nk_vf32x4_t a_low_f32x4 = vec_extract_fp32_from_shortl(a_u16x8);
412
+ nk_vf32x4_t b_high_f32x4 = vec_extract_fp32_from_shorth(b_u16x8);
413
+ nk_vf32x4_t b_low_f32x4 = vec_extract_fp32_from_shortl(b_u16x8);
414
+ ab_f32x4 = vec_madd(a_high_f32x4, b_high_f32x4, ab_f32x4);
415
+ ab_f32x4 = vec_madd(a_low_f32x4, b_low_f32x4, ab_f32x4);
416
+ a2_f32x4 = vec_madd(a_high_f32x4, a_high_f32x4, a2_f32x4);
417
+ a2_f32x4 = vec_madd(a_low_f32x4, a_low_f32x4, a2_f32x4);
418
+ b2_f32x4 = vec_madd(b_high_f32x4, b_high_f32x4, b2_f32x4);
419
+ b2_f32x4 = vec_madd(b_low_f32x4, b_low_f32x4, b2_f32x4);
420
+ if (n) goto nk_angular_f16_powervsx_cycle;
421
+ nk_f32_t ab = nk_hsum_f32x4_powervsx_(ab_f32x4);
422
+ nk_f32_t a2 = nk_hsum_f32x4_powervsx_(a2_f32x4);
423
+ nk_f32_t b2 = nk_hsum_f32x4_powervsx_(b2_f32x4);
424
+ *result = nk_angular_normalize_f32_powervsx_(ab, a2, b2);
425
+ }
426
+
427
+ #pragma endregion F16 and BF16 Floats
428
+ #pragma region I8 and U8 Integers
429
+
430
+ NK_PUBLIC void nk_sqeuclidean_i8_powervsx(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_u32_t *result) {
431
+ // Power has no vabdq_s8. Widen i8 → i16 via vec_unpackh/vec_unpackl,
432
+ // subtract in i16, then vec_msum(diff_i16, diff_i16, accumulator_i32) to square-accumulate.
433
+ nk_vi32x4_t accumulator_i32x4 = vec_splats((nk_i32_t)0);
434
+ nk_vi8x16_t a_i8x16, b_i8x16;
435
+ nk_size_t tail_bytes;
436
+
437
+ nk_sqeuclidean_i8_powervsx_cycle:
438
+ if (n < 16) {
439
+ tail_bytes = n * sizeof(nk_i8_t);
440
+ a_i8x16 = vec_xl_len((nk_i8_t *)a, tail_bytes);
441
+ b_i8x16 = vec_xl_len((nk_i8_t *)b, tail_bytes);
442
+ n = 0;
443
+ }
444
+ else {
445
+ a_i8x16 = vec_xl(0, a);
446
+ b_i8x16 = vec_xl(0, b);
447
+ a += 16, b += 16, n -= 16;
448
+ }
449
+ // Widen high 8 bytes: i8 → i16
450
+ nk_vi16x8_t a_high_i16x8 = vec_unpackh(a_i8x16);
451
+ nk_vi16x8_t b_high_i16x8 = vec_unpackh(b_i8x16);
452
+ nk_vi16x8_t diff_high_i16x8 = vec_sub(a_high_i16x8, b_high_i16x8);
453
+ // vec_msum: multiply 8 i16 pairs and accumulate into 4 i32 lanes
454
+ accumulator_i32x4 = vec_msum(diff_high_i16x8, diff_high_i16x8, accumulator_i32x4);
455
+ // Widen low 8 bytes: i8 → i16
456
+ nk_vi16x8_t a_low_i16x8 = vec_unpackl(a_i8x16);
457
+ nk_vi16x8_t b_low_i16x8 = vec_unpackl(b_i8x16);
458
+ nk_vi16x8_t diff_low_i16x8 = vec_sub(a_low_i16x8, b_low_i16x8);
459
+ accumulator_i32x4 = vec_msum(diff_low_i16x8, diff_low_i16x8, accumulator_i32x4);
460
+ if (n) goto nk_sqeuclidean_i8_powervsx_cycle;
461
+
462
+ *result = (nk_u32_t)nk_hsum_i32x4_powervsx_(accumulator_i32x4);
463
+ }
464
+
465
+ NK_PUBLIC void nk_euclidean_i8_powervsx(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_f32_t *result) {
466
+ nk_u32_t distance_sq_u32;
467
+ nk_sqeuclidean_i8_powervsx(a, b, n, &distance_sq_u32);
468
+ *result = nk_f32_sqrt_powervsx((nk_f32_t)distance_sq_u32);
469
+ }
470
+
471
+ NK_PUBLIC void nk_angular_i8_powervsx(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_f32_t *result) {
472
+ // Hybrid approach for 3-accumulator i8 angular distance:
473
+ // a·b: algebraic transform — VMSUMMBM(a, b⊕0x80) with correction −128·Σa
474
+ // a·a: abs-based unsigned — VMSUMUBM(|a|, |a|), no correction needed
475
+ // b·b: abs-based unsigned — VMSUMUBM(|b|, |b|), no correction needed
476
+ // abs(-128)→-128 in i8 → 128 as u8 → 128²=16384=(-128)². Safe for all values.
477
+ // 3 independent MSUM chains → excellent ILP on POWER9's dual-issue p01.
478
+ nk_vu8x16_t const bias_u8x16 = vec_splats((nk_u8_t)0x80);
479
+ nk_vi8x16_t const zeros_i8x16 = vec_splats((nk_i8_t)0);
480
+ nk_vi32x4_t dot_product_i32x4 = vec_splats((nk_i32_t)0);
481
+ nk_vu32x4_t a_norm_sq_u32x4 = vec_splats((nk_u32_t)0);
482
+ nk_vu32x4_t b_norm_sq_u32x4 = vec_splats((nk_u32_t)0);
483
+ nk_vu32x4_t sum_a_biased_u32x4 = vec_splats((nk_u32_t)0);
484
+ nk_size_t count_padded = ((n + 15) / 16) * 16;
485
+ nk_vi8x16_t a_i8x16, b_i8x16;
486
+ nk_size_t tail_bytes;
487
+
488
+ nk_angular_i8_powervsx_cycle:
489
+ if (n < 16) {
490
+ tail_bytes = n * sizeof(nk_i8_t);
491
+ a_i8x16 = vec_xl_len((nk_i8_t *)a, tail_bytes);
492
+ b_i8x16 = vec_xl_len((nk_i8_t *)b, tail_bytes);
493
+ n = 0;
494
+ }
495
+ else {
496
+ a_i8x16 = vec_xl(0, a);
497
+ b_i8x16 = vec_xl(0, b);
498
+ a += 16, b += 16, n -= 16;
499
+ }
500
+
501
+ // Dot product: algebraic via VMSUMMBM(i8 × u8 → i32)
502
+ nk_vu8x16_t b_biased_u8x16 = vec_xor((nk_vu8x16_t)b_i8x16, bias_u8x16);
503
+ dot_product_i32x4 = vec_msum(a_i8x16, b_biased_u8x16, dot_product_i32x4);
504
+ // Correction sum: Σ(a+128) via VSUM4UBS
505
+ sum_a_biased_u32x4 = vec_sum4s(vec_xor((nk_vu8x16_t)a_i8x16, bias_u8x16), sum_a_biased_u32x4);
506
+ // Norms: |a|² and |b|² via VMSUMUBM(u8 × u8 → u32) on absolute values
507
+ nk_vu8x16_t a_abs_u8x16 = (nk_vu8x16_t)vec_max(a_i8x16, vec_sub(zeros_i8x16, a_i8x16));
508
+ nk_vu8x16_t b_abs_u8x16 = (nk_vu8x16_t)vec_max(b_i8x16, vec_sub(zeros_i8x16, b_i8x16));
509
+ a_norm_sq_u32x4 = vec_msum(a_abs_u8x16, a_abs_u8x16, a_norm_sq_u32x4);
510
+ b_norm_sq_u32x4 = vec_msum(b_abs_u8x16, b_abs_u8x16, b_norm_sq_u32x4);
511
+
512
+ if (n) goto nk_angular_i8_powervsx_cycle;
513
+
514
+ // Correct the biased dot product: a·b = biased − 128·Σa = biased − 128·(Σ(a+128) − 128·count_padded)
515
+ nk_i64_t correction = 128LL * (nk_i64_t)nk_hsum_u32x4_powervsx_(sum_a_biased_u32x4) -
516
+ 16384LL * (nk_i64_t)count_padded;
517
+ nk_i32_t dot_product_i32 = (nk_i32_t)((nk_i64_t)nk_hsum_i32x4_powervsx_(dot_product_i32x4) - correction);
518
+ nk_u32_t a_norm_sq_u32 = nk_hsum_u32x4_powervsx_(a_norm_sq_u32x4);
519
+ nk_u32_t b_norm_sq_u32 = nk_hsum_u32x4_powervsx_(b_norm_sq_u32x4);
520
+ *result = nk_angular_normalize_f32_powervsx_((nk_f32_t)dot_product_i32, (nk_f32_t)a_norm_sq_u32,
521
+ (nk_f32_t)b_norm_sq_u32);
522
+ }
523
+
524
+ NK_PUBLIC void nk_sqeuclidean_u8_powervsx(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_u32_t *result) {
525
+ // Compute |a-b| without underflow: vec_sub(vec_max(a, b), vec_min(a, b))
526
+ // Then square-accumulate via vec_msum(u8, u8, u32) → VMSUMUBM
527
+ nk_vu32x4_t accumulator_u32x4 = vec_splats((nk_u32_t)0);
528
+ nk_vu8x16_t a_u8x16, b_u8x16;
529
+ nk_size_t tail_bytes;
530
+
531
+ nk_sqeuclidean_u8_powervsx_cycle:
532
+ if (n < 16) {
533
+ tail_bytes = n * sizeof(nk_u8_t);
534
+ a_u8x16 = vec_xl_len((nk_u8_t *)a, tail_bytes);
535
+ b_u8x16 = vec_xl_len((nk_u8_t *)b, tail_bytes);
536
+ n = 0;
537
+ }
538
+ else {
539
+ a_u8x16 = vec_xl(0, a);
540
+ b_u8x16 = vec_xl(0, b);
541
+ a += 16, b += 16, n -= 16;
542
+ }
543
+ nk_vu8x16_t diff_u8x16 = vec_sub(vec_max(a_u8x16, b_u8x16), vec_min(a_u8x16, b_u8x16));
544
+ // VMSUMUBM: u8 × u8 → u32 accumulate
545
+ accumulator_u32x4 = vec_msum(diff_u8x16, diff_u8x16, accumulator_u32x4);
546
+ if (n) goto nk_sqeuclidean_u8_powervsx_cycle;
547
+
548
+ *result = nk_hsum_u32x4_powervsx_(accumulator_u32x4);
549
+ }
550
+
551
+ NK_PUBLIC void nk_euclidean_u8_powervsx(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_f32_t *result) {
552
+ nk_u32_t distance_sq_u32;
553
+ nk_sqeuclidean_u8_powervsx(a, b, n, &distance_sq_u32);
554
+ *result = nk_f32_sqrt_powervsx((nk_f32_t)distance_sq_u32);
555
+ }
556
+
557
+ NK_PUBLIC void nk_angular_u8_powervsx(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_f32_t *result) {
558
+ // Triple accumulator in u32 using vec_msum(u8, u8, u32) → VMSUMUBM
559
+ nk_vu32x4_t ab_u32x4 = vec_splats((nk_u32_t)0);
560
+ nk_vu32x4_t aa_u32x4 = vec_splats((nk_u32_t)0);
561
+ nk_vu32x4_t bb_u32x4 = vec_splats((nk_u32_t)0);
562
+ nk_vu8x16_t a_u8x16, b_u8x16;
563
+ nk_size_t tail_bytes;
564
+
565
+ nk_angular_u8_powervsx_cycle:
566
+ if (n < 16) {
567
+ tail_bytes = n * sizeof(nk_u8_t);
568
+ a_u8x16 = vec_xl_len((nk_u8_t *)a, tail_bytes);
569
+ b_u8x16 = vec_xl_len((nk_u8_t *)b, tail_bytes);
570
+ n = 0;
571
+ }
572
+ else {
573
+ a_u8x16 = vec_xl(0, a);
574
+ b_u8x16 = vec_xl(0, b);
575
+ a += 16, b += 16, n -= 16;
576
+ }
577
+ // VMSUMUBM: u8 × u8 → u32 accumulate
578
+ ab_u32x4 = vec_msum(a_u8x16, b_u8x16, ab_u32x4);
579
+ aa_u32x4 = vec_msum(a_u8x16, a_u8x16, aa_u32x4);
580
+ bb_u32x4 = vec_msum(b_u8x16, b_u8x16, bb_u32x4);
581
+ if (n) goto nk_angular_u8_powervsx_cycle;
582
+
583
+ nk_u32_t ab = nk_hsum_u32x4_powervsx_(ab_u32x4);
584
+ nk_u32_t aa = nk_hsum_u32x4_powervsx_(aa_u32x4);
585
+ nk_u32_t bb = nk_hsum_u32x4_powervsx_(bb_u32x4);
586
+ *result = nk_angular_normalize_f32_powervsx_((nk_f32_t)ab, (nk_f32_t)aa, (nk_f32_t)bb);
587
+ }
588
+
589
+ /** @brief Angular from_dot: computes 1 − dot × rsqrt(query_sumsq × target_sumsq) for 4 pairs in f64. */
590
+ NK_INTERNAL void nk_angular_through_f64_from_dot_powervsx_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
591
+ nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
592
+ nk_vf64x2_t dots_ab_f64x2 = dots.vf64x2s[0];
593
+ nk_vf64x2_t dots_cd_f64x2 = dots.vf64x2s[1];
594
+ nk_vf64x2_t query_f64x2 = vec_splats(query_sumsq);
595
+ nk_vf64x2_t targets_ab_f64x2 = target_sumsqs.vf64x2s[0];
596
+ nk_vf64x2_t targets_cd_f64x2 = target_sumsqs.vf64x2s[1];
597
+
598
+ nk_vf64x2_t products_ab_f64x2 = vec_mul(query_f64x2, targets_ab_f64x2);
599
+ nk_vf64x2_t products_cd_f64x2 = vec_mul(query_f64x2, targets_cd_f64x2);
600
+
601
+ nk_vf64x2_t rsqrt_ab_f64x2 = nk_rsqrt_f64x2_powervsx_(products_ab_f64x2);
602
+ nk_vf64x2_t rsqrt_cd_f64x2 = nk_rsqrt_f64x2_powervsx_(products_cd_f64x2);
603
+
604
+ nk_vf64x2_t ones_f64x2 = vec_splats(1.0);
605
+ nk_vf64x2_t zeros_f64x2 = vec_splats(0.0);
606
+ nk_vf64x2_t result_ab_f64x2 = vec_max(vec_sub(ones_f64x2, vec_mul(dots_ab_f64x2, rsqrt_ab_f64x2)), zeros_f64x2);
607
+ nk_vf64x2_t result_cd_f64x2 = vec_max(vec_sub(ones_f64x2, vec_mul(dots_cd_f64x2, rsqrt_cd_f64x2)), zeros_f64x2);
608
+
609
+ nk_vu64x2_t prodzero_ab_u64x2 = (nk_vu64x2_t)vec_cmpeq(products_ab_f64x2, zeros_f64x2);
610
+ nk_vu64x2_t dotzero_ab_u64x2 = (nk_vu64x2_t)vec_cmpeq(dots_ab_f64x2, zeros_f64x2);
611
+ result_ab_f64x2 = vec_sel(result_ab_f64x2, zeros_f64x2, vec_and(prodzero_ab_u64x2, dotzero_ab_u64x2));
612
+ result_ab_f64x2 = vec_sel(result_ab_f64x2, ones_f64x2, vec_andc(prodzero_ab_u64x2, dotzero_ab_u64x2));
613
+
614
+ nk_vu64x2_t prodzero_cd_u64x2 = (nk_vu64x2_t)vec_cmpeq(products_cd_f64x2, zeros_f64x2);
615
+ nk_vu64x2_t dotzero_cd_u64x2 = (nk_vu64x2_t)vec_cmpeq(dots_cd_f64x2, zeros_f64x2);
616
+ result_cd_f64x2 = vec_sel(result_cd_f64x2, zeros_f64x2, vec_and(prodzero_cd_u64x2, dotzero_cd_u64x2));
617
+ result_cd_f64x2 = vec_sel(result_cd_f64x2, ones_f64x2, vec_andc(prodzero_cd_u64x2, dotzero_cd_u64x2));
618
+
619
+ results->vf64x2s[0] = result_ab_f64x2;
620
+ results->vf64x2s[1] = result_cd_f64x2;
621
+ }
622
+
623
+ /** @brief Euclidean from_dot: computes √(query_sumsq + target_sumsq − 2×dot) for 4 pairs in f64. */
624
+ NK_INTERNAL void nk_euclidean_through_f64_from_dot_powervsx_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
625
+ nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
626
+ nk_vf64x2_t query_f64x2 = vec_splats(query_sumsq);
627
+ nk_vf64x2_t neg_two_f64x2 = vec_splats(-2.0);
628
+ nk_vf64x2_t zeros_f64x2 = vec_splats(0.0);
629
+
630
+ nk_vf64x2_t sum_sq_ab_f64x2 = vec_add(query_f64x2, target_sumsqs.vf64x2s[0]);
631
+ nk_vf64x2_t sum_sq_cd_f64x2 = vec_add(query_f64x2, target_sumsqs.vf64x2s[1]);
632
+ nk_vf64x2_t dist_sq_ab_f64x2 = vec_max(vec_madd(neg_two_f64x2, dots.vf64x2s[0], sum_sq_ab_f64x2), zeros_f64x2);
633
+ nk_vf64x2_t dist_sq_cd_f64x2 = vec_max(vec_madd(neg_two_f64x2, dots.vf64x2s[1], sum_sq_cd_f64x2), zeros_f64x2);
634
+
635
+ results->vf64x2s[0] = vec_sqrt(dist_sq_ab_f64x2);
636
+ results->vf64x2s[1] = vec_sqrt(dist_sq_cd_f64x2);
637
+ }
638
+
639
+ /** @brief Angular from_dot: computes 1 − dot × rsqrt(query_sumsq × target_sumsq) for 4 pairs in f32. */
640
+ NK_INTERNAL void nk_angular_through_f32_from_dot_powervsx_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
641
+ nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
642
+ nk_vf32x4_t dots_f32x4 = dots.vf32x4;
643
+ nk_vf32x4_t query_f32x4 = vec_splats(query_sumsq);
644
+ nk_vf32x4_t products_f32x4 = vec_mul(query_f32x4, target_sumsqs.vf32x4);
645
+ nk_vf32x4_t rsqrt_f32x4 = nk_rsqrt_f32x4_powervsx_(products_f32x4);
646
+ nk_vf32x4_t normalized_f32x4 = vec_mul(dots_f32x4, rsqrt_f32x4);
647
+ nk_vf32x4_t angular_f32x4 = vec_sub(vec_splats(1.0f), normalized_f32x4);
648
+ nk_vf32x4_t result_f32x4 = vec_max(angular_f32x4, vec_splats(0.0f));
649
+ results->vf32x4 = result_f32x4;
650
+ }
651
+
652
+ /** @brief Euclidean from_dot: computes √(query_sumsq + target_sumsq − 2×dot) for 4 pairs in f32. */
653
+ NK_INTERNAL void nk_euclidean_through_f32_from_dot_powervsx_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
654
+ nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
655
+ nk_vf32x4_t dots_f32x4 = dots.vf32x4;
656
+ nk_vf32x4_t query_f32x4 = vec_splats(query_sumsq);
657
+ nk_vf32x4_t sum_sq_f32x4 = vec_add(query_f32x4, target_sumsqs.vf32x4);
658
+ // dist_sq = sum_sq − 2 × dot
659
+ nk_vf32x4_t dist_sq_f32x4 = vec_madd(vec_splats(-2.0f), dots_f32x4, sum_sq_f32x4);
660
+ // Clamp and sqrt
661
+ dist_sq_f32x4 = vec_max(dist_sq_f32x4, vec_splats(0.0f));
662
+ nk_vf32x4_t dist_f32x4 = vec_sqrt(dist_sq_f32x4);
663
+ results->vf32x4 = dist_f32x4;
664
+ }
665
+
666
+ /** @brief Angular from_dot for i32 accumulators: cast to f32, rsqrt+NR, clamp. 4 pairs. */
667
+ NK_INTERNAL void nk_angular_through_i32_from_dot_powervsx_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
668
+ nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
669
+ nk_vi32x4_t dots_i32x4 = dots.vi32x4;
670
+ nk_vf32x4_t dots_f32x4 = vec_ctf(dots_i32x4, 0);
671
+ nk_vf32x4_t query_f32x4 = vec_splats((nk_f32_t)query_sumsq);
672
+ nk_vi32x4_t targets_i32x4 = target_sumsqs.vi32x4;
673
+ nk_vf32x4_t products_f32x4 = vec_mul(query_f32x4, vec_ctf(targets_i32x4, 0));
674
+ nk_vf32x4_t rsqrt_f32x4 = nk_rsqrt_f32x4_powervsx_(products_f32x4);
675
+ nk_vf32x4_t normalized_f32x4 = vec_mul(dots_f32x4, rsqrt_f32x4);
676
+ nk_vf32x4_t angular_f32x4 = vec_sub(vec_splats(1.0f), normalized_f32x4);
677
+ nk_vf32x4_t result_f32x4 = vec_max(angular_f32x4, vec_splats(0.0f));
678
+ results->vf32x4 = result_f32x4;
679
+ }
680
+
681
+ /** @brief Euclidean from_dot for i32 accumulators: cast to f32, then √(a² + b² − 2ab). 4 pairs. */
682
+ NK_INTERNAL void nk_euclidean_through_i32_from_dot_powervsx_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
683
+ nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
684
+ nk_vi32x4_t dots_i32x4 = dots.vi32x4;
685
+ nk_vf32x4_t dots_f32x4 = vec_ctf(dots_i32x4, 0);
686
+ nk_vf32x4_t query_f32x4 = vec_splats((nk_f32_t)query_sumsq);
687
+ nk_vi32x4_t targets_i32x4 = target_sumsqs.vi32x4;
688
+ nk_vf32x4_t sum_sq_f32x4 = vec_add(query_f32x4, vec_ctf(targets_i32x4, 0));
689
+ nk_vf32x4_t dist_sq_f32x4 = vec_madd(vec_splats(-2.0f), dots_f32x4, sum_sq_f32x4);
690
+ dist_sq_f32x4 = vec_max(dist_sq_f32x4, vec_splats(0.0f));
691
+ nk_vf32x4_t dist_f32x4 = vec_sqrt(dist_sq_f32x4);
692
+ results->vf32x4 = dist_f32x4;
693
+ }
694
+
695
+ /** @brief Angular from_dot for u32 accumulators: cast to f32, rsqrt+NR, clamp. 4 pairs. */
696
+ NK_INTERNAL void nk_angular_through_u32_from_dot_powervsx_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
697
+ nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
698
+ nk_vu32x4_t dots_u32x4 = dots.vu32x4;
699
+ nk_vf32x4_t dots_f32x4 = vec_ctf(dots_u32x4, 0);
700
+ nk_vf32x4_t query_f32x4 = vec_splats((nk_f32_t)query_sumsq);
701
+ nk_vu32x4_t targets_u32x4 = target_sumsqs.vu32x4;
702
+ nk_vf32x4_t products_f32x4 = vec_mul(query_f32x4, vec_ctf(targets_u32x4, 0));
703
+ nk_vf32x4_t rsqrt_f32x4 = nk_rsqrt_f32x4_powervsx_(products_f32x4);
704
+ nk_vf32x4_t normalized_f32x4 = vec_mul(dots_f32x4, rsqrt_f32x4);
705
+ nk_vf32x4_t angular_f32x4 = vec_sub(vec_splats(1.0f), normalized_f32x4);
706
+ nk_vf32x4_t result_f32x4 = vec_max(angular_f32x4, vec_splats(0.0f));
707
+ results->vf32x4 = result_f32x4;
708
+ }
709
+
710
+ /** @brief Euclidean from_dot for u32 accumulators: cast to f32, then √(a² + b² − 2ab). 4 pairs. */
711
+ NK_INTERNAL void nk_euclidean_through_u32_from_dot_powervsx_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
712
+ nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
713
+ nk_vu32x4_t dots_u32x4 = dots.vu32x4;
714
+ nk_vf32x4_t dots_f32x4 = vec_ctf(dots_u32x4, 0);
715
+ nk_vf32x4_t query_f32x4 = vec_splats((nk_f32_t)query_sumsq);
716
+ nk_vu32x4_t targets_u32x4 = target_sumsqs.vu32x4;
717
+ nk_vf32x4_t sum_sq_f32x4 = vec_add(query_f32x4, vec_ctf(targets_u32x4, 0));
718
+ nk_vf32x4_t dist_sq_f32x4 = vec_madd(vec_splats(-2.0f), dots_f32x4, sum_sq_f32x4);
719
+ dist_sq_f32x4 = vec_max(dist_sq_f32x4, vec_splats(0.0f));
720
+ nk_vf32x4_t dist_f32x4 = vec_sqrt(dist_sq_f32x4);
721
+ results->vf32x4 = dist_f32x4;
722
+ }
723
+
724
+ #pragma endregion I8 and U8 Integers
725
+
726
+ #if defined(__clang__)
727
+ #pragma clang attribute pop
728
+ #elif defined(__GNUC__)
729
+ #pragma GCC pop_options
730
+ #endif
731
+
732
+ #if defined(__cplusplus)
733
+ } // extern "C"
734
+ #endif
735
+
736
+ #endif // NK_TARGET_POWERVSX
737
+ #endif // NK_TARGET_POWER64_
738
+ #endif // NK_SPATIAL_POWERVSX_H