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,540 @@
1
+ //! MaxSim (ColBERT-style late-interaction) scoring with pre-packed matrices.
2
+ //!
3
+ //! MaxSim is the late-interaction similarity introduced by ColBERT: given a
4
+ //! query matrix `Q` (one row per query token) and a document matrix `D` (one
5
+ //! row per document token), the score is the sum over query rows of the max
6
+ //! inner product with any document row. It retains token-level granularity —
7
+ //! unlike single-vector retrieval — while remaining cheap enough to run over
8
+ //! large candidate sets.
9
+ //!
10
+ //! [`MaxSimPackedMatrix`] stores those matrices in a quantized format
11
+ //! optimized for fast coarse screening followed by full-precision refinement:
12
+ //! an i8 pre-pass filters obvious non-matches before the original
13
+ //! `f32` / `f16` / `bf16` values resolve the top candidates.
14
+ //!
15
+ //! # Typical flow
16
+ //!
17
+ //! 1. Pack both the query set and the document set with
18
+ //! [`MaxSimPackedMatrix::try_pack`] (or [`TensorView::try_maxsim_pack`]).
19
+ //! 2. Call [`MaxSimPackedMatrix::try_score`] on the pair; the score type is
20
+ //! `f64` for `f32` inputs and `f32` for `f16` / `bf16` inputs.
21
+ //!
22
+ //! # Example
23
+ //!
24
+ //! The doctest below is marked `ignore` because doctests compile as separate
25
+ //! crates and would need to re-link the `libnumkong` C library that provides
26
+ //! the `nk_maxsim_*` FFI symbols used here. The in-crate tests at the bottom
27
+ //! of this file exercise the same code path.
28
+ //!
29
+ //! ```rust,ignore
30
+ //! use numkong::{MaxSimPackedMatrix, Tensor};
31
+ //!
32
+ //! let queries = Tensor::<f32>::try_full(&[32, 128], 1.0).unwrap();
33
+ //! let documents = Tensor::<f32>::try_full(&[1024, 128], 1.0).unwrap();
34
+ //!
35
+ //! let queries_packed = MaxSimPackedMatrix::try_pack(&queries.view()).unwrap();
36
+ //! let docs_packed = MaxSimPackedMatrix::try_pack(&documents.view()).unwrap();
37
+ //! let score = queries_packed.score(&docs_packed);
38
+ //! ```
39
+
40
+ extern crate alloc;
41
+
42
+ use core::marker::PhantomData;
43
+ use core::ptr::NonNull;
44
+
45
+ use crate::tensor::{Allocator, Global, TensorError, TensorView, SIMD_ALIGNMENT};
46
+ use crate::types::{bf16, f16, StorageElement};
47
+
48
+ // region: FFI
49
+
50
+ #[link(name = "numkong")]
51
+ extern "C" {
52
+ fn nk_maxsim_packed_size_f32(vector_count: usize, depth: usize) -> usize;
53
+ fn nk_maxsim_pack_f32(
54
+ v: *const f32,
55
+ vector_count: usize,
56
+ depth: usize,
57
+ stride: usize,
58
+ packed: *mut u8,
59
+ );
60
+ fn nk_maxsim_packed_f32(
61
+ q: *const u8,
62
+ d: *const u8,
63
+ query_count: usize,
64
+ document_count: usize,
65
+ depth: usize,
66
+ result: *mut f64,
67
+ );
68
+
69
+ fn nk_maxsim_packed_size_f16(vector_count: usize, depth: usize) -> usize;
70
+ fn nk_maxsim_pack_f16(
71
+ v: *const f16,
72
+ vector_count: usize,
73
+ depth: usize,
74
+ stride: usize,
75
+ packed: *mut u8,
76
+ );
77
+ fn nk_maxsim_packed_f16(
78
+ q: *const u8,
79
+ d: *const u8,
80
+ query_count: usize,
81
+ document_count: usize,
82
+ depth: usize,
83
+ result: *mut f32,
84
+ );
85
+
86
+ fn nk_maxsim_packed_size_bf16(vector_count: usize, depth: usize) -> usize;
87
+ fn nk_maxsim_pack_bf16(
88
+ v: *const bf16,
89
+ vector_count: usize,
90
+ depth: usize,
91
+ stride: usize,
92
+ packed: *mut u8,
93
+ );
94
+ fn nk_maxsim_packed_bf16(
95
+ q: *const u8,
96
+ d: *const u8,
97
+ query_count: usize,
98
+ document_count: usize,
99
+ depth: usize,
100
+ result: *mut f32,
101
+ );
102
+ }
103
+
104
+ // endregion: FFI
105
+
106
+ // region: MaxSim trait
107
+
108
+ /// Trait abstracting MaxSim pack/score operations per scalar type.
109
+ pub trait MaxSim: StorageElement + Clone {
110
+ /// Score type returned by MaxSim scoring.
111
+ type Score: Clone + Default;
112
+
113
+ /// Returns the packed buffer size in bytes for `vector_count` vectors of given `depth`.
114
+ fn maxsim_packed_size(vector_count: usize, depth: usize) -> usize;
115
+
116
+ /// Pack vectors into backend-specific quantized format.
117
+ ///
118
+ /// # Safety
119
+ /// - `vectors` must point to `vector_count` rows of `depth` elements, byte stride `stride`
120
+ /// - `packed` must have at least `maxsim_packed_size(vector_count, depth)` bytes
121
+ unsafe fn maxsim_pack(
122
+ vectors: *const Self,
123
+ vector_count: usize,
124
+ depth: usize,
125
+ stride: usize,
126
+ packed: *mut u8,
127
+ );
128
+
129
+ /// Compute MaxSim score on pre-packed buffers.
130
+ ///
131
+ /// # Safety
132
+ /// - Both buffers must have been produced by `maxsim_pack` with matching depth
133
+ /// - `result` must point to valid, writable memory for `Self::Score`
134
+ unsafe fn maxsim_packed(
135
+ q: *const u8,
136
+ d: *const u8,
137
+ query_count: usize,
138
+ document_count: usize,
139
+ depth: usize,
140
+ result: *mut Self::Score,
141
+ );
142
+ }
143
+
144
+ // endregion: MaxSim trait
145
+
146
+ // region: MaxSim impls
147
+
148
+ impl MaxSim for f32 {
149
+ type Score = f64;
150
+
151
+ fn maxsim_packed_size(vector_count: usize, depth: usize) -> usize {
152
+ unsafe { nk_maxsim_packed_size_f32(vector_count, depth) }
153
+ }
154
+
155
+ unsafe fn maxsim_pack(
156
+ vectors: *const Self,
157
+ vector_count: usize,
158
+ depth: usize,
159
+ stride: usize,
160
+ packed: *mut u8,
161
+ ) {
162
+ nk_maxsim_pack_f32(vectors, vector_count, depth, stride, packed)
163
+ }
164
+
165
+ unsafe fn maxsim_packed(
166
+ q: *const u8,
167
+ d: *const u8,
168
+ query_count: usize,
169
+ document_count: usize,
170
+ depth: usize,
171
+ result: *mut Self::Score,
172
+ ) {
173
+ nk_maxsim_packed_f32(q, d, query_count, document_count, depth, result)
174
+ }
175
+ }
176
+
177
+ impl MaxSim for f16 {
178
+ type Score = f32;
179
+
180
+ fn maxsim_packed_size(vector_count: usize, depth: usize) -> usize {
181
+ unsafe { nk_maxsim_packed_size_f16(vector_count, depth) }
182
+ }
183
+
184
+ unsafe fn maxsim_pack(
185
+ vectors: *const Self,
186
+ vector_count: usize,
187
+ depth: usize,
188
+ stride: usize,
189
+ packed: *mut u8,
190
+ ) {
191
+ nk_maxsim_pack_f16(vectors, vector_count, depth, stride, packed)
192
+ }
193
+
194
+ unsafe fn maxsim_packed(
195
+ q: *const u8,
196
+ d: *const u8,
197
+ query_count: usize,
198
+ document_count: usize,
199
+ depth: usize,
200
+ result: *mut Self::Score,
201
+ ) {
202
+ nk_maxsim_packed_f16(q, d, query_count, document_count, depth, result)
203
+ }
204
+ }
205
+
206
+ impl MaxSim for bf16 {
207
+ type Score = f32;
208
+
209
+ fn maxsim_packed_size(vector_count: usize, depth: usize) -> usize {
210
+ unsafe { nk_maxsim_packed_size_bf16(vector_count, depth) }
211
+ }
212
+
213
+ unsafe fn maxsim_pack(
214
+ vectors: *const Self,
215
+ vector_count: usize,
216
+ depth: usize,
217
+ stride: usize,
218
+ packed: *mut u8,
219
+ ) {
220
+ nk_maxsim_pack_bf16(vectors, vector_count, depth, stride, packed)
221
+ }
222
+
223
+ unsafe fn maxsim_packed(
224
+ q: *const u8,
225
+ d: *const u8,
226
+ query_count: usize,
227
+ document_count: usize,
228
+ depth: usize,
229
+ result: *mut Self::Score,
230
+ ) {
231
+ nk_maxsim_packed_bf16(q, d, query_count, document_count, depth, result)
232
+ }
233
+ }
234
+
235
+ // endregion: MaxSim impls
236
+
237
+ // region: MaxSimPackedMatrix
238
+
239
+ /// Pre-packed vector set for MaxSim scoring.
240
+ ///
241
+ /// Both query and document vectors must be packed before scoring.
242
+ /// The buffer uses i8 quantization for fast coarse screening,
243
+ /// with full-precision originals retained for refinement.
244
+ pub struct MaxSimPackedMatrix<Scalar: MaxSim, Alloc: Allocator = Global> {
245
+ data: NonNull<u8>,
246
+ size: usize,
247
+ vector_count: usize,
248
+ depth: usize,
249
+ alloc: Alloc,
250
+ _marker: PhantomData<Scalar>,
251
+ }
252
+
253
+ // Safety: MaxSimPackedMatrix owns its data and is just bytes
254
+ unsafe impl<Scalar: MaxSim + Send, Alloc: Allocator + Send> Send
255
+ for MaxSimPackedMatrix<Scalar, Alloc>
256
+ {
257
+ }
258
+ unsafe impl<Scalar: MaxSim + Sync, Alloc: Allocator + Sync> Sync
259
+ for MaxSimPackedMatrix<Scalar, Alloc>
260
+ {
261
+ }
262
+
263
+ impl<Scalar: MaxSim, Alloc: Allocator> Drop for MaxSimPackedMatrix<Scalar, Alloc> {
264
+ fn drop(&mut self) {
265
+ if self.size > 0 {
266
+ unsafe {
267
+ let layout =
268
+ alloc::alloc::Layout::from_size_align_unchecked(self.size, SIMD_ALIGNMENT);
269
+ self.alloc.deallocate(self.data, layout);
270
+ }
271
+ }
272
+ }
273
+ }
274
+
275
+ impl<Scalar: MaxSim, Alloc: Allocator + Clone> MaxSimPackedMatrix<Scalar, Alloc> {
276
+ /// Try to clone this packed matrix, returning an error on allocation failure.
277
+ pub fn try_clone(&self) -> Result<Self, TensorError> {
278
+ if self.size == 0 {
279
+ return Ok(Self {
280
+ data: NonNull::dangling(),
281
+ size: 0,
282
+ vector_count: self.vector_count,
283
+ depth: self.depth,
284
+ alloc: self.alloc.clone(),
285
+ _marker: PhantomData,
286
+ });
287
+ }
288
+
289
+ let layout = alloc::alloc::Layout::from_size_align(self.size, SIMD_ALIGNMENT)
290
+ .map_err(|_| TensorError::AllocationFailed)?;
291
+ let ptr = self
292
+ .alloc
293
+ .allocate(layout)
294
+ .ok_or(TensorError::AllocationFailed)?;
295
+ unsafe {
296
+ core::ptr::copy_nonoverlapping(self.data.as_ptr(), ptr.as_ptr(), self.size);
297
+ }
298
+ Ok(Self {
299
+ data: ptr,
300
+ size: self.size,
301
+ vector_count: self.vector_count,
302
+ depth: self.depth,
303
+ alloc: self.alloc.clone(),
304
+ _marker: PhantomData,
305
+ })
306
+ }
307
+ }
308
+
309
+ impl<Scalar: MaxSim, Alloc: Allocator + Clone> Clone for MaxSimPackedMatrix<Scalar, Alloc> {
310
+ fn clone(&self) -> Self {
311
+ self.try_clone()
312
+ .expect("MaxSimPackedMatrix clone allocation failed")
313
+ }
314
+ }
315
+
316
+ impl<Scalar: MaxSim, Alloc: Allocator> MaxSimPackedMatrix<Scalar, Alloc> {
317
+ /// Pack vectors from a 2D tensor view using a custom allocator.
318
+ ///
319
+ /// Returns `Err` if the view is not 2D, the depth axis is not contiguous,
320
+ /// the row stride is negative, or allocation fails.
321
+ pub fn try_pack_in<const MAX_RANK: usize>(
322
+ vectors: &TensorView<'_, Scalar, MAX_RANK>,
323
+ alloc: Alloc,
324
+ ) -> Result<Self, TensorError> {
325
+ let (vector_count, depth, row_stride_bytes) = validate_maxsim_view(vectors)?;
326
+ let size = Scalar::maxsim_packed_size(vector_count, depth);
327
+
328
+ let data = if size == 0 {
329
+ NonNull::dangling()
330
+ } else {
331
+ let layout = alloc::alloc::Layout::from_size_align(size, SIMD_ALIGNMENT)
332
+ .map_err(|_| TensorError::AllocationFailed)?;
333
+ let ptr = alloc
334
+ .allocate(layout)
335
+ .ok_or(TensorError::AllocationFailed)?;
336
+ unsafe {
337
+ core::ptr::write_bytes(ptr.as_ptr(), 0, size);
338
+ }
339
+ ptr
340
+ };
341
+
342
+ if size > 0 {
343
+ unsafe {
344
+ Scalar::maxsim_pack(
345
+ vectors.as_ptr(),
346
+ vector_count,
347
+ depth,
348
+ row_stride_bytes,
349
+ data.as_ptr(),
350
+ );
351
+ }
352
+ }
353
+
354
+ Ok(Self {
355
+ data,
356
+ size,
357
+ vector_count,
358
+ depth,
359
+ alloc,
360
+ _marker: PhantomData,
361
+ })
362
+ }
363
+
364
+ /// Compute MaxSim score against another packed matrix.
365
+ ///
366
+ /// Returns `Err` if depths don't match.
367
+ pub fn try_score<OtherAlloc: Allocator>(
368
+ &self,
369
+ other: &MaxSimPackedMatrix<Scalar, OtherAlloc>,
370
+ ) -> Result<Scalar::Score, TensorError> {
371
+ if self.depth != other.depth {
372
+ return Err(TensorError::DimensionMismatch {
373
+ expected: self.depth,
374
+ got: other.depth,
375
+ });
376
+ }
377
+ let mut score = Scalar::Score::default();
378
+ unsafe {
379
+ Scalar::maxsim_packed(
380
+ self.as_ptr(),
381
+ other.as_ptr(),
382
+ self.vector_count,
383
+ other.vector_count,
384
+ self.depth,
385
+ &mut score,
386
+ )
387
+ };
388
+ Ok(score)
389
+ }
390
+
391
+ /// Convenience that panics on error.
392
+ pub fn score<OtherAlloc: Allocator>(
393
+ &self,
394
+ other: &MaxSimPackedMatrix<Scalar, OtherAlloc>,
395
+ ) -> Scalar::Score {
396
+ self.try_score(other)
397
+ .expect("MaxSimPackedMatrix::score failed")
398
+ }
399
+
400
+ /// Returns a reference to the allocator.
401
+ pub fn allocator(&self) -> &Alloc {
402
+ &self.alloc
403
+ }
404
+
405
+ /// Returns dimensions (vector_count, depth) of the original vector set.
406
+ pub fn dims(&self) -> (usize, usize) {
407
+ (self.vector_count, self.depth)
408
+ }
409
+
410
+ /// Returns the packed data buffer.
411
+ pub fn as_bytes(&self) -> &[u8] {
412
+ unsafe { core::slice::from_raw_parts(self.data.as_ptr(), self.size) }
413
+ }
414
+
415
+ /// Returns a pointer to the packed data.
416
+ pub fn as_ptr(&self) -> *const u8 {
417
+ self.data.as_ptr()
418
+ }
419
+ }
420
+
421
+ // Convenience methods using Global allocator
422
+ impl<Scalar: MaxSim> MaxSimPackedMatrix<Scalar, Global> {
423
+ /// Pack vectors from a 2D tensor view using the global allocator.
424
+ pub fn try_pack<const MAX_RANK: usize>(
425
+ vectors: &TensorView<'_, Scalar, MAX_RANK>,
426
+ ) -> Result<Self, TensorError> {
427
+ Self::try_pack_in(vectors, Global)
428
+ }
429
+
430
+ /// Convenience constructor that panics on error.
431
+ pub fn pack<const MAX_RANK: usize>(vectors: &TensorView<'_, Scalar, MAX_RANK>) -> Self {
432
+ Self::try_pack(vectors).expect("MaxSimPackedMatrix::pack failed")
433
+ }
434
+ }
435
+
436
+ // endregion: MaxSimPackedMatrix
437
+
438
+ fn validate_maxsim_view<Scalar, const MAX_RANK: usize>(
439
+ vectors: &TensorView<'_, Scalar, MAX_RANK>,
440
+ ) -> Result<(usize, usize, usize), TensorError> {
441
+ if vectors.ndim() != 2 {
442
+ return Err(TensorError::DimensionMismatch {
443
+ expected: 2,
444
+ got: vectors.ndim(),
445
+ });
446
+ }
447
+
448
+ if !vectors.has_contiguous_rows() {
449
+ return Err(TensorError::NonContiguousRows);
450
+ }
451
+
452
+ let row_stride_bytes = vectors.stride_bytes(0);
453
+ if row_stride_bytes < 0 {
454
+ return Err(TensorError::InvalidShape {
455
+ axis: 0,
456
+ size: row_stride_bytes as usize,
457
+ reason: "MaxSim requires non-negative row strides",
458
+ });
459
+ }
460
+
461
+ Ok((
462
+ vectors.shape()[0],
463
+ vectors.shape()[1],
464
+ row_stride_bytes as usize,
465
+ ))
466
+ }
467
+
468
+ // region: TensorView convenience
469
+
470
+ impl<'a, Scalar: MaxSim, const MAX_RANK: usize> TensorView<'a, Scalar, MAX_RANK> {
471
+ /// Pack this 2D tensor view for MaxSim scoring using the provided allocator.
472
+ pub fn try_maxsim_pack_in<Alloc: Allocator>(
473
+ &self,
474
+ alloc: Alloc,
475
+ ) -> Result<MaxSimPackedMatrix<Scalar, Alloc>, TensorError> {
476
+ MaxSimPackedMatrix::try_pack_in(self, alloc)
477
+ }
478
+
479
+ /// Pack this 2D tensor view for MaxSim scoring using the global allocator.
480
+ pub fn try_maxsim_pack(&self) -> Result<MaxSimPackedMatrix<Scalar, Global>, TensorError> {
481
+ self.try_maxsim_pack_in(Global)
482
+ }
483
+ }
484
+
485
+ // endregion: TensorView convenience
486
+
487
+ #[cfg(test)]
488
+ mod tests {
489
+ use super::*;
490
+ use crate::tensor::{SliceRange, Tensor};
491
+
492
+ #[test]
493
+ fn maxsim_packs_from_tensor_view() {
494
+ let queries = Tensor::<f32>::try_full(&[4, 16], 1.0).unwrap();
495
+ let docs = Tensor::<f32>::try_full(&[8, 16], 1.0).unwrap();
496
+
497
+ let queries_packed = queries.view().try_maxsim_pack().unwrap();
498
+ let docs_packed = docs.view().try_maxsim_pack().unwrap();
499
+
500
+ assert_eq!(queries_packed.dims(), (4, 16));
501
+ assert_eq!(docs_packed.dims(), (8, 16));
502
+ assert!(queries_packed.score(&docs_packed).is_finite());
503
+ }
504
+
505
+ #[test]
506
+ fn maxsim_rejects_non_contiguous_depth_axis() {
507
+ let queries = Tensor::<f32>::try_full(&[4, 16], 1.0).unwrap();
508
+ let transposed = queries.transpose().unwrap();
509
+ let result = transposed.try_maxsim_pack();
510
+ assert!(matches!(result, Err(TensorError::NonContiguousRows)));
511
+ }
512
+
513
+ #[test]
514
+ fn maxsim_accepts_outer_strided_views() {
515
+ let queries = Tensor::<f32>::try_full(&[8, 16], 1.0).unwrap();
516
+ let odd_rows = queries
517
+ .slice(&[
518
+ SliceRange::range_step(1, 7, 2),
519
+ SliceRange::range_step(0, 16, 1),
520
+ ])
521
+ .unwrap();
522
+
523
+ let queries_packed = odd_rows.try_maxsim_pack().unwrap();
524
+ assert_eq!(queries_packed.dims(), (3, 16));
525
+ }
526
+
527
+ #[test]
528
+ fn maxsim_rejects_negative_row_stride() {
529
+ let queries = Tensor::<f32>::try_full(&[8, 16], 1.0).unwrap();
530
+ let reversed_rows = queries
531
+ .slice(&[
532
+ SliceRange::range_step(7, 0, -1),
533
+ SliceRange::range_step(0, 16, 1),
534
+ ])
535
+ .unwrap();
536
+
537
+ let result = reversed_rows.try_maxsim_pack();
538
+ assert!(matches!(result, Err(TensorError::InvalidShape { .. })));
539
+ }
540
+ }