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,509 @@
1
+ /**
2
+ * @brief C++ wrappers for SIMD-accelerated Batched Spatial Distance Matrices.
3
+ * @file include/numkong/spatials.hpp
4
+ * @author Ash Vardanian
5
+ * @date March 2026
6
+ */
7
+ #ifndef NK_SPATIALS_HPP
8
+ #define NK_SPATIALS_HPP
9
+
10
+ #include <cstdint>
11
+ #include <cstring>
12
+ #include <type_traits>
13
+
14
+ #include "numkong/spatials.h"
15
+
16
+ #include "numkong/types.hpp"
17
+
18
+ namespace ashvardanian::numkong {
19
+
20
+ /**
21
+ * @brief Symmetric angular distance matrix: C[i,j] = angular(A[i], A[j])
22
+ * @param[in] a Matrix A [vectors_count x depth]
23
+ * @param[in] vectors_count Number of vectors (n)
24
+ * @param[in] depth Dimension of each vector (k)
25
+ * @param[in] a_stride_in_bytes Stride between vectors in A
26
+ * @param[out] c Output matrix C [n x n]
27
+ * @param[in] c_stride_in_bytes Stride between rows of C in bytes
28
+ * @param[in] row_start Starting row index (default 0)
29
+ * @param[in] row_count Number of rows to compute (default all)
30
+ *
31
+ * @tparam in_type_ Input element type
32
+ * @tparam result_type_ Output type, defaults to `in_type_::angular_result_t`
33
+ * @tparam allow_simd_ Enable SIMD kernel dispatch when `prefer_simd_k`
34
+ */
35
+ template <numeric_dtype in_type_, numeric_dtype result_type_ = typename in_type_::angular_result_t,
36
+ allow_simd_t allow_simd_ = prefer_simd_k>
37
+ void angulars_symmetric(in_type_ const *a, std::size_t vectors_count, std::size_t depth, std::size_t a_stride_in_bytes,
38
+ result_type_ *c, std::size_t c_stride_in_bytes, std::size_t row_start = 0,
39
+ std::size_t row_count = std::numeric_limits<std::size_t>::max()) noexcept {
40
+ if (row_count == std::numeric_limits<std::size_t>::max()) row_count = vectors_count;
41
+ constexpr bool dispatch = allow_simd_ == prefer_simd_k &&
42
+ std::is_same_v<result_type_, typename in_type_::angular_result_t>;
43
+
44
+ if constexpr (std::is_same_v<in_type_, f64_t> && dispatch)
45
+ nk_angulars_symmetric_f64(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
46
+ row_start, row_count);
47
+ else if constexpr (std::is_same_v<in_type_, f32_t> && dispatch)
48
+ nk_angulars_symmetric_f32(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
49
+ row_start, row_count);
50
+ else if constexpr (std::is_same_v<in_type_, f16_t> && dispatch)
51
+ nk_angulars_symmetric_f16(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
52
+ row_start, row_count);
53
+ else if constexpr (std::is_same_v<in_type_, bf16_t> && dispatch)
54
+ nk_angulars_symmetric_bf16(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
55
+ row_start, row_count);
56
+ else if constexpr (std::is_same_v<in_type_, e4m3_t> && dispatch)
57
+ nk_angulars_symmetric_e4m3(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
58
+ row_start, row_count);
59
+ else if constexpr (std::is_same_v<in_type_, e5m2_t> && dispatch)
60
+ nk_angulars_symmetric_e5m2(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
61
+ row_start, row_count);
62
+ else if constexpr (std::is_same_v<in_type_, e2m3_t> && dispatch)
63
+ nk_angulars_symmetric_e2m3(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
64
+ row_start, row_count);
65
+ else if constexpr (std::is_same_v<in_type_, e3m2_t> && dispatch)
66
+ nk_angulars_symmetric_e3m2(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
67
+ row_start, row_count);
68
+ else if constexpr (std::is_same_v<in_type_, i8_t> && dispatch)
69
+ nk_angulars_symmetric_i8(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
70
+ row_start, row_count);
71
+ else if constexpr (std::is_same_v<in_type_, u8_t> && dispatch)
72
+ nk_angulars_symmetric_u8(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
73
+ row_start, row_count);
74
+ else if constexpr (std::is_same_v<in_type_, i4x2_t> && dispatch)
75
+ nk_angulars_symmetric_i4(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
76
+ row_start, row_count);
77
+ else if constexpr (std::is_same_v<in_type_, u4x2_t> && dispatch)
78
+ nk_angulars_symmetric_u4(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
79
+ row_start, row_count);
80
+ else {
81
+ std::size_t depth_values = divide_round_up(depth, dimensions_per_value<in_type_>());
82
+ char const *a_bytes = reinterpret_cast<char const *>(a);
83
+ char *c_bytes = reinterpret_cast<char *>(c);
84
+ std::size_t row_end = row_start + row_count < vectors_count ? row_start + row_count : vectors_count;
85
+
86
+ for (std::size_t i = row_start; i < row_end; i++) {
87
+ in_type_ const *a_i = reinterpret_cast<in_type_ const *>(a_bytes + i * a_stride_in_bytes);
88
+ result_type_ *c_row = reinterpret_cast<result_type_ *>(c_bytes + i * c_stride_in_bytes);
89
+ for (std::size_t j = 0; j < vectors_count; j++) {
90
+ in_type_ const *a_j = reinterpret_cast<in_type_ const *>(a_bytes + j * a_stride_in_bytes);
91
+ result_type_ ab {}, aa {}, bb {};
92
+ for (std::size_t l = 0; l < depth_values; l++) {
93
+ ab = fma(a_i[l], a_j[l], ab);
94
+ aa = fma(a_i[l], a_i[l], aa);
95
+ bb = fma(a_j[l], a_j[l], bb);
96
+ }
97
+ result_type_ cos_sim = ab / (aa.sqrt() * bb.sqrt());
98
+ result_type_ distance = result_type_(1) - cos_sim;
99
+ c_row[j] = distance > result_type_(0) ? distance : result_type_(0);
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ /**
106
+ * @brief Symmetric Euclidean distance matrix: C[i,j] = euclidean(A[i], A[j])
107
+ * @param[in] a Matrix A [vectors_count x depth]
108
+ * @param[in] vectors_count Number of vectors (n)
109
+ * @param[in] depth Dimension of each vector (k)
110
+ * @param[in] a_stride_in_bytes Stride between vectors in A
111
+ * @param[out] c Output matrix C [n x n]
112
+ * @param[in] c_stride_in_bytes Stride between rows of C in bytes
113
+ * @param[in] row_start Starting row index (default 0)
114
+ * @param[in] row_count Number of rows to compute (default all)
115
+ *
116
+ * @tparam in_type_ Input element type
117
+ * @tparam result_type_ Output type, defaults to `in_type_::euclidean_result_t`
118
+ * @tparam allow_simd_ Enable SIMD kernel dispatch when `prefer_simd_k`
119
+ */
120
+ template <numeric_dtype in_type_, numeric_dtype result_type_ = typename in_type_::euclidean_result_t,
121
+ allow_simd_t allow_simd_ = prefer_simd_k>
122
+ void euclideans_symmetric(in_type_ const *a, std::size_t vectors_count, std::size_t depth,
123
+ std::size_t a_stride_in_bytes, result_type_ *c, std::size_t c_stride_in_bytes,
124
+ std::size_t row_start = 0,
125
+ std::size_t row_count = std::numeric_limits<std::size_t>::max()) noexcept {
126
+ if (row_count == std::numeric_limits<std::size_t>::max()) row_count = vectors_count;
127
+ constexpr bool dispatch = allow_simd_ == prefer_simd_k &&
128
+ std::is_same_v<result_type_, typename in_type_::euclidean_result_t>;
129
+
130
+ if constexpr (std::is_same_v<in_type_, f64_t> && dispatch)
131
+ nk_euclideans_symmetric_f64(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
132
+ row_start, row_count);
133
+ else if constexpr (std::is_same_v<in_type_, f32_t> && dispatch)
134
+ nk_euclideans_symmetric_f32(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
135
+ row_start, row_count);
136
+ else if constexpr (std::is_same_v<in_type_, f16_t> && dispatch)
137
+ nk_euclideans_symmetric_f16(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
138
+ row_start, row_count);
139
+ else if constexpr (std::is_same_v<in_type_, bf16_t> && dispatch)
140
+ nk_euclideans_symmetric_bf16(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
141
+ row_start, row_count);
142
+ else if constexpr (std::is_same_v<in_type_, e4m3_t> && dispatch)
143
+ nk_euclideans_symmetric_e4m3(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
144
+ row_start, row_count);
145
+ else if constexpr (std::is_same_v<in_type_, e5m2_t> && dispatch)
146
+ nk_euclideans_symmetric_e5m2(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
147
+ row_start, row_count);
148
+ else if constexpr (std::is_same_v<in_type_, e2m3_t> && dispatch)
149
+ nk_euclideans_symmetric_e2m3(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
150
+ row_start, row_count);
151
+ else if constexpr (std::is_same_v<in_type_, e3m2_t> && dispatch)
152
+ nk_euclideans_symmetric_e3m2(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
153
+ row_start, row_count);
154
+ else if constexpr (std::is_same_v<in_type_, i8_t> && dispatch)
155
+ nk_euclideans_symmetric_i8(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
156
+ row_start, row_count);
157
+ else if constexpr (std::is_same_v<in_type_, u8_t> && dispatch)
158
+ nk_euclideans_symmetric_u8(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
159
+ row_start, row_count);
160
+ else if constexpr (std::is_same_v<in_type_, i4x2_t> && dispatch)
161
+ nk_euclideans_symmetric_i4(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
162
+ row_start, row_count);
163
+ else if constexpr (std::is_same_v<in_type_, u4x2_t> && dispatch)
164
+ nk_euclideans_symmetric_u4(&a->raw_, vectors_count, depth, a_stride_in_bytes, &c->raw_, c_stride_in_bytes,
165
+ row_start, row_count);
166
+ else {
167
+ std::size_t depth_values = divide_round_up(depth, dimensions_per_value<in_type_>());
168
+ char const *a_bytes = reinterpret_cast<char const *>(a);
169
+ char *c_bytes = reinterpret_cast<char *>(c);
170
+ std::size_t row_end = row_start + row_count < vectors_count ? row_start + row_count : vectors_count;
171
+
172
+ for (std::size_t i = row_start; i < row_end; i++) {
173
+ in_type_ const *a_i = reinterpret_cast<in_type_ const *>(a_bytes + i * a_stride_in_bytes);
174
+ result_type_ *c_row = reinterpret_cast<result_type_ *>(c_bytes + i * c_stride_in_bytes);
175
+ for (std::size_t j = 0; j < vectors_count; j++) {
176
+ in_type_ const *a_j = reinterpret_cast<in_type_ const *>(a_bytes + j * a_stride_in_bytes);
177
+ result_type_ sum {};
178
+ for (std::size_t l = 0; l < depth_values; l++) sum = fdsa(a_i[l], a_j[l], sum);
179
+ c_row[j] = sum.sqrt();
180
+ }
181
+ }
182
+ }
183
+ }
184
+
185
+ /**
186
+ * @brief Packed angular distances: C = angular(A, B_packed)
187
+ * @param[in] a Matrix A [row_count x depth]
188
+ * @param[in] b_packed Packed B matrix (produced by nk_dots_pack_*)
189
+ * @param[out] c Output matrix C [row_count x column_count]
190
+ * @param[in] row_count Rows of A and C (m)
191
+ * @param[in] column_count Columns of B and C (n)
192
+ * @param[in] depth Shared inner dimension (k)
193
+ * @param[in] a_stride_in_bytes Stride between rows of A in bytes
194
+ * @param[in] c_stride_in_bytes Stride between rows of C in bytes
195
+ *
196
+ * @tparam in_type_ Input element type
197
+ * @tparam result_type_ Output type, defaults to `in_type_::angular_result_t`
198
+ * @tparam allow_simd_ Enable SIMD kernel dispatch when `prefer_simd_k`
199
+ */
200
+ template <numeric_dtype in_type_, numeric_dtype result_type_ = typename in_type_::angular_result_t,
201
+ allow_simd_t allow_simd_ = prefer_simd_k>
202
+ void angulars_packed(in_type_ const *a, void const *b_packed, result_type_ *c, size_t row_count, size_t column_count,
203
+ size_t depth, size_t a_stride_in_bytes, size_t c_stride_in_bytes) noexcept {
204
+ constexpr bool dispatch = allow_simd_ == prefer_simd_k &&
205
+ std::is_same_v<result_type_, typename in_type_::angular_result_t>;
206
+
207
+ if constexpr (std::is_same_v<in_type_, f64_t> && dispatch)
208
+ nk_angulars_packed_f64(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
209
+ c_stride_in_bytes);
210
+ else if constexpr (std::is_same_v<in_type_, f32_t> && dispatch)
211
+ nk_angulars_packed_f32(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
212
+ c_stride_in_bytes);
213
+ else if constexpr (std::is_same_v<in_type_, f16_t> && dispatch)
214
+ nk_angulars_packed_f16(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
215
+ c_stride_in_bytes);
216
+ else if constexpr (std::is_same_v<in_type_, bf16_t> && dispatch)
217
+ nk_angulars_packed_bf16(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
218
+ c_stride_in_bytes);
219
+ else if constexpr (std::is_same_v<in_type_, e4m3_t> && dispatch)
220
+ nk_angulars_packed_e4m3(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
221
+ c_stride_in_bytes);
222
+ else if constexpr (std::is_same_v<in_type_, e5m2_t> && dispatch)
223
+ nk_angulars_packed_e5m2(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
224
+ c_stride_in_bytes);
225
+ else if constexpr (std::is_same_v<in_type_, e2m3_t> && dispatch)
226
+ nk_angulars_packed_e2m3(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
227
+ c_stride_in_bytes);
228
+ else if constexpr (std::is_same_v<in_type_, e3m2_t> && dispatch)
229
+ nk_angulars_packed_e3m2(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
230
+ c_stride_in_bytes);
231
+ else if constexpr (std::is_same_v<in_type_, i8_t> && dispatch)
232
+ nk_angulars_packed_i8(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
233
+ c_stride_in_bytes);
234
+ else if constexpr (std::is_same_v<in_type_, u8_t> && dispatch)
235
+ nk_angulars_packed_u8(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
236
+ c_stride_in_bytes);
237
+ else if constexpr (std::is_same_v<in_type_, i4x2_t> && dispatch)
238
+ nk_angulars_packed_i4(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
239
+ c_stride_in_bytes);
240
+ else if constexpr (std::is_same_v<in_type_, u4x2_t> && dispatch)
241
+ nk_angulars_packed_u4(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
242
+ c_stride_in_bytes);
243
+ else {
244
+ // Scalar fallback: extract pointer and stride, compute pairwise angular distances
245
+ in_type_ const *b;
246
+ size_t b_stride_in_bytes;
247
+ char const *b_packed_bytes = reinterpret_cast<char const *>(b_packed);
248
+ std::memcpy(&b, b_packed_bytes, sizeof(void *));
249
+ std::memcpy(&b_stride_in_bytes, b_packed_bytes + sizeof(void *), sizeof(size_t));
250
+
251
+ char const *a_bytes = reinterpret_cast<char const *>(a);
252
+ char const *b_bytes = reinterpret_cast<char const *>(b);
253
+ char *c_bytes = reinterpret_cast<char *>(c);
254
+ std::size_t depth_values = divide_round_up(depth, dimensions_per_value<in_type_>());
255
+
256
+ for (size_t i = 0; i < row_count; i++) {
257
+ in_type_ const *a_row = reinterpret_cast<in_type_ const *>(a_bytes + i * a_stride_in_bytes);
258
+ result_type_ *c_row = reinterpret_cast<result_type_ *>(c_bytes + i * c_stride_in_bytes);
259
+ for (size_t j = 0; j < column_count; j++) {
260
+ in_type_ const *b_row = reinterpret_cast<in_type_ const *>(b_bytes + j * b_stride_in_bytes);
261
+ result_type_ ab {}, aa {}, bb {};
262
+ for (std::size_t l = 0; l < depth_values; l++) {
263
+ ab = fma(a_row[l], b_row[l], ab);
264
+ aa = fma(a_row[l], a_row[l], aa);
265
+ bb = fma(b_row[l], b_row[l], bb);
266
+ }
267
+ result_type_ cos_sim = ab / (aa.sqrt() * bb.sqrt());
268
+ result_type_ distance = result_type_(1) - cos_sim;
269
+ c_row[j] = distance > result_type_(0) ? distance : result_type_(0);
270
+ }
271
+ }
272
+ }
273
+ }
274
+
275
+ /**
276
+ * @brief Packed Euclidean distances: C = euclidean(A, B_packed)
277
+ * @param[in] a Matrix A [row_count x depth]
278
+ * @param[in] b_packed Packed B matrix (produced by nk_dots_pack_*)
279
+ * @param[out] c Output matrix C [row_count x column_count]
280
+ * @param[in] row_count Rows of A and C (m)
281
+ * @param[in] column_count Columns of B and C (n)
282
+ * @param[in] depth Shared inner dimension (k)
283
+ * @param[in] a_stride_in_bytes Stride between rows of A in bytes
284
+ * @param[in] c_stride_in_bytes Stride between rows of C in bytes
285
+ *
286
+ * @tparam in_type_ Input element type
287
+ * @tparam result_type_ Output type, defaults to `in_type_::euclidean_result_t`
288
+ * @tparam allow_simd_ Enable SIMD kernel dispatch when `prefer_simd_k`
289
+ */
290
+ template <numeric_dtype in_type_, numeric_dtype result_type_ = typename in_type_::euclidean_result_t,
291
+ allow_simd_t allow_simd_ = prefer_simd_k>
292
+ void euclideans_packed(in_type_ const *a, void const *b_packed, result_type_ *c, size_t row_count, size_t column_count,
293
+ size_t depth, size_t a_stride_in_bytes, size_t c_stride_in_bytes) noexcept {
294
+ constexpr bool dispatch = allow_simd_ == prefer_simd_k &&
295
+ std::is_same_v<result_type_, typename in_type_::euclidean_result_t>;
296
+
297
+ if constexpr (std::is_same_v<in_type_, f64_t> && dispatch)
298
+ nk_euclideans_packed_f64(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
299
+ c_stride_in_bytes);
300
+ else if constexpr (std::is_same_v<in_type_, f32_t> && dispatch)
301
+ nk_euclideans_packed_f32(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
302
+ c_stride_in_bytes);
303
+ else if constexpr (std::is_same_v<in_type_, f16_t> && dispatch)
304
+ nk_euclideans_packed_f16(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
305
+ c_stride_in_bytes);
306
+ else if constexpr (std::is_same_v<in_type_, bf16_t> && dispatch)
307
+ nk_euclideans_packed_bf16(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
308
+ c_stride_in_bytes);
309
+ else if constexpr (std::is_same_v<in_type_, e4m3_t> && dispatch)
310
+ nk_euclideans_packed_e4m3(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
311
+ c_stride_in_bytes);
312
+ else if constexpr (std::is_same_v<in_type_, e5m2_t> && dispatch)
313
+ nk_euclideans_packed_e5m2(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
314
+ c_stride_in_bytes);
315
+ else if constexpr (std::is_same_v<in_type_, e2m3_t> && dispatch)
316
+ nk_euclideans_packed_e2m3(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
317
+ c_stride_in_bytes);
318
+ else if constexpr (std::is_same_v<in_type_, e3m2_t> && dispatch)
319
+ nk_euclideans_packed_e3m2(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
320
+ c_stride_in_bytes);
321
+ else if constexpr (std::is_same_v<in_type_, i8_t> && dispatch)
322
+ nk_euclideans_packed_i8(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
323
+ c_stride_in_bytes);
324
+ else if constexpr (std::is_same_v<in_type_, u8_t> && dispatch)
325
+ nk_euclideans_packed_u8(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
326
+ c_stride_in_bytes);
327
+ else if constexpr (std::is_same_v<in_type_, i4x2_t> && dispatch)
328
+ nk_euclideans_packed_i4(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
329
+ c_stride_in_bytes);
330
+ else if constexpr (std::is_same_v<in_type_, u4x2_t> && dispatch)
331
+ nk_euclideans_packed_u4(&a->raw_, b_packed, &c->raw_, row_count, column_count, depth, a_stride_in_bytes,
332
+ c_stride_in_bytes);
333
+ else {
334
+ // Scalar fallback: extract pointer and stride, compute pairwise euclidean distances
335
+ in_type_ const *b;
336
+ size_t b_stride_in_bytes;
337
+ char const *b_packed_bytes = reinterpret_cast<char const *>(b_packed);
338
+ std::memcpy(&b, b_packed_bytes, sizeof(void *));
339
+ std::memcpy(&b_stride_in_bytes, b_packed_bytes + sizeof(void *), sizeof(size_t));
340
+
341
+ char const *a_bytes = reinterpret_cast<char const *>(a);
342
+ char const *b_bytes = reinterpret_cast<char const *>(b);
343
+ char *c_bytes = reinterpret_cast<char *>(c);
344
+ std::size_t depth_values = divide_round_up(depth, dimensions_per_value<in_type_>());
345
+
346
+ for (size_t i = 0; i < row_count; i++) {
347
+ in_type_ const *a_row = reinterpret_cast<in_type_ const *>(a_bytes + i * a_stride_in_bytes);
348
+ result_type_ *c_row = reinterpret_cast<result_type_ *>(c_bytes + i * c_stride_in_bytes);
349
+ for (size_t j = 0; j < column_count; j++) {
350
+ in_type_ const *b_row = reinterpret_cast<in_type_ const *>(b_bytes + j * b_stride_in_bytes);
351
+ result_type_ sum {};
352
+ for (std::size_t l = 0; l < depth_values; l++) sum = fdsa(a_row[l], b_row[l], sum);
353
+ c_row[j] = sum.sqrt();
354
+ }
355
+ }
356
+ }
357
+ }
358
+
359
+ } // namespace ashvardanian::numkong
360
+
361
+ #include "numkong/tensor.hpp"
362
+
363
+ namespace ashvardanian::numkong {
364
+
365
+ #pragma region Concept Constrained Symmetric Spatial Distances
366
+
367
+ /** @brief Symmetric angular distances: C[i,j] = angular(A[i], A[j]). */
368
+ template <numeric_dtype value_type_, const_matrix_of<value_type_> input_matrix_,
369
+ mutable_matrix_of<typename value_type_::angular_result_t> output_matrix_>
370
+ bool angulars_symmetric(input_matrix_ const &input, output_matrix_ &&output) noexcept {
371
+ std::size_t num_vectors = input.extent(0);
372
+ if (output.extent(0) != num_vectors || output.extent(1) != num_vectors) return false;
373
+ numkong::angulars_symmetric<value_type_>(input.data(), num_vectors, input.extent(1),
374
+ static_cast<std::size_t>(input.stride_bytes(0)), output.data(),
375
+ static_cast<std::size_t>(output.stride_bytes(0)));
376
+ return true;
377
+ }
378
+
379
+ /** @brief Allocating symmetric angular distances. */
380
+ template <numeric_dtype value_type_, const_matrix_of<value_type_> input_matrix_,
381
+ typename allocator_type_ = aligned_allocator<typename value_type_::angular_result_t>>
382
+ matrix<typename value_type_::angular_result_t, allocator_type_> try_angulars_symmetric(
383
+ input_matrix_ const &input) noexcept {
384
+ using result_t = typename value_type_::angular_result_t;
385
+ using out_tensor_t = matrix<result_t, allocator_type_>;
386
+ if (input.empty()) return out_tensor_t {};
387
+ std::size_t num_vectors = input.extent(0);
388
+ auto result = out_tensor_t::try_zeros({num_vectors, num_vectors});
389
+ if (result.empty()) return result;
390
+ if (!angulars_symmetric<value_type_>(input, result.span())) return out_tensor_t {};
391
+ return result;
392
+ }
393
+
394
+ /** @brief Symmetric Euclidean distances: C[i,j] = euclidean(A[i], A[j]). */
395
+ template <numeric_dtype value_type_, const_matrix_of<value_type_> input_matrix_,
396
+ mutable_matrix_of<typename value_type_::euclidean_result_t> output_matrix_>
397
+ bool euclideans_symmetric(input_matrix_ const &input, output_matrix_ &&output) noexcept {
398
+ std::size_t num_vectors = input.extent(0);
399
+ if (output.extent(0) != num_vectors || output.extent(1) != num_vectors) return false;
400
+ numkong::euclideans_symmetric<value_type_>(input.data(), num_vectors, input.extent(1),
401
+ static_cast<std::size_t>(input.stride_bytes(0)), output.data(),
402
+ static_cast<std::size_t>(output.stride_bytes(0)));
403
+ return true;
404
+ }
405
+
406
+ /** @brief Allocating symmetric Euclidean distances. */
407
+ template <numeric_dtype value_type_, const_matrix_of<value_type_> input_matrix_,
408
+ typename allocator_type_ = aligned_allocator<typename value_type_::euclidean_result_t>>
409
+ matrix<typename value_type_::euclidean_result_t, allocator_type_> try_euclideans_symmetric(
410
+ input_matrix_ const &input) noexcept {
411
+ using result_t = typename value_type_::euclidean_result_t;
412
+ using out_tensor_t = matrix<result_t, allocator_type_>;
413
+ if (input.empty()) return out_tensor_t {};
414
+ std::size_t num_vectors = input.extent(0);
415
+ auto result = out_tensor_t::try_zeros({num_vectors, num_vectors});
416
+ if (result.empty()) return result;
417
+ if (!euclideans_symmetric<value_type_>(input, result.span())) return out_tensor_t {};
418
+ return result;
419
+ }
420
+
421
+ /** @brief Partitioned symmetric angular distances for parallel row-range work. */
422
+ template <numeric_dtype value_type_, const_matrix_of<value_type_> input_matrix_,
423
+ mutable_matrix_of<typename value_type_::angular_result_t> output_matrix_>
424
+ bool angulars_symmetric(input_matrix_ const &input, output_matrix_ &&output, std::size_t row_start,
425
+ std::size_t row_count) noexcept {
426
+ std::size_t num_vectors = input.extent(0);
427
+ if (output.extent(0) != num_vectors || output.extent(1) != num_vectors) return false;
428
+ numkong::angulars_symmetric<value_type_>(input.data(), num_vectors, input.extent(1),
429
+ static_cast<std::size_t>(input.stride_bytes(0)), output.data(),
430
+ static_cast<std::size_t>(output.stride_bytes(0)), row_start, row_count);
431
+ return true;
432
+ }
433
+
434
+ /** @brief Partitioned symmetric Euclidean distances for parallel row-range work. */
435
+ template <numeric_dtype value_type_, const_matrix_of<value_type_> input_matrix_,
436
+ mutable_matrix_of<typename value_type_::euclidean_result_t> output_matrix_>
437
+ bool euclideans_symmetric(input_matrix_ const &input, output_matrix_ &&output, std::size_t row_start,
438
+ std::size_t row_count) noexcept {
439
+ std::size_t num_vectors = input.extent(0);
440
+ if (output.extent(0) != num_vectors || output.extent(1) != num_vectors) return false;
441
+ numkong::euclideans_symmetric<value_type_>(input.data(), num_vectors, input.extent(1),
442
+ static_cast<std::size_t>(input.stride_bytes(0)), output.data(),
443
+ static_cast<std::size_t>(output.stride_bytes(0)), row_start, row_count);
444
+ return true;
445
+ }
446
+
447
+ #pragma endregion Concept Constrained Symmetric Spatial Distances
448
+
449
+ #pragma region Concept Constrained Packed Spatial Distances
450
+
451
+ /** @brief Packed angular distances: C = angular(A, B_packed). */
452
+ template <numeric_dtype value_type_, packed_matrix_like packed_type_, const_matrix_of<value_type_> input_matrix_,
453
+ mutable_matrix_of<typename value_type_::angular_result_t> output_matrix_>
454
+ bool angulars_packed(input_matrix_ const &a, packed_type_ const &packed_b, output_matrix_ &&c) noexcept {
455
+ if (packed_b.empty() || a.rank() < 2 || c.rank() < 2) return false;
456
+ if (a.extent(1) != packed_b.depth()) return false;
457
+ if (c.extent(0) != a.extent(0) || c.extent(1) != packed_b.rows()) return false;
458
+ numkong::angulars_packed<value_type_>(a.data(), packed_b.data(), c.data(), a.extent(0), packed_b.rows(),
459
+ packed_b.depth(), static_cast<std::size_t>(a.stride_bytes(0)),
460
+ static_cast<std::size_t>(c.stride_bytes(0)));
461
+ return true;
462
+ }
463
+
464
+ /** @brief Allocating packed angular distances. */
465
+ template <numeric_dtype value_type_, packed_matrix_like packed_type_, const_matrix_of<value_type_> input_matrix_,
466
+ typename allocator_type_ = aligned_allocator<typename value_type_::angular_result_t>>
467
+ matrix<typename value_type_::angular_result_t, allocator_type_> try_angulars_packed(
468
+ input_matrix_ const &a, packed_type_ const &packed_b) noexcept {
469
+ using result_t = typename value_type_::angular_result_t;
470
+ using out_t = matrix<result_t, allocator_type_>;
471
+ if (packed_b.empty() || a.rank() < 2) return out_t {};
472
+ auto c = out_t::try_empty({a.extent(0), packed_b.rows()});
473
+ if (c.empty()) return c;
474
+ if (!angulars_packed<value_type_>(a, packed_b, c.as_matrix_span())) return out_t {};
475
+ return c;
476
+ }
477
+
478
+ /** @brief Packed Euclidean distances: C = euclidean(A, B_packed). */
479
+ template <numeric_dtype value_type_, packed_matrix_like packed_type_, const_matrix_of<value_type_> input_matrix_,
480
+ mutable_matrix_of<typename value_type_::euclidean_result_t> output_matrix_>
481
+ bool euclideans_packed(input_matrix_ const &a, packed_type_ const &packed_b, output_matrix_ &&c) noexcept {
482
+ if (packed_b.empty() || a.rank() < 2 || c.rank() < 2) return false;
483
+ if (a.extent(1) != packed_b.depth()) return false;
484
+ if (c.extent(0) != a.extent(0) || c.extent(1) != packed_b.rows()) return false;
485
+ numkong::euclideans_packed<value_type_>(a.data(), packed_b.data(), c.data(), a.extent(0), packed_b.rows(),
486
+ packed_b.depth(), static_cast<std::size_t>(a.stride_bytes(0)),
487
+ static_cast<std::size_t>(c.stride_bytes(0)));
488
+ return true;
489
+ }
490
+
491
+ /** @brief Allocating packed Euclidean distances. */
492
+ template <numeric_dtype value_type_, packed_matrix_like packed_type_, const_matrix_of<value_type_> input_matrix_,
493
+ typename allocator_type_ = aligned_allocator<typename value_type_::euclidean_result_t>>
494
+ matrix<typename value_type_::euclidean_result_t, allocator_type_> try_euclideans_packed(
495
+ input_matrix_ const &a, packed_type_ const &packed_b) noexcept {
496
+ using result_t = typename value_type_::euclidean_result_t;
497
+ using out_t = matrix<result_t, allocator_type_>;
498
+ if (packed_b.empty() || a.rank() < 2) return out_t {};
499
+ auto c = out_t::try_empty({a.extent(0), packed_b.rows()});
500
+ if (c.empty()) return c;
501
+ if (!euclideans_packed<value_type_>(a, packed_b, c.as_matrix_span())) return out_t {};
502
+ return c;
503
+ }
504
+
505
+ #pragma endregion Concept Constrained Packed Spatial Distances
506
+
507
+ } // namespace ashvardanian::numkong
508
+
509
+ #endif // NK_SPATIALS_HPP