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,698 @@
1
+ # NumKong for Rust
2
+
3
+ NumKong's Rust crate keeps most of the native kernel surface while expressing it in Rust-native terms.
4
+ Rust is a natural fit for NumKong when you want static typing, explicit ownership, and strong container APIs without giving up mixed precision.
5
+ Traits cover scalar metric families.
6
+ `Tensor`, `Vector`, and packed matrix types cover the higher-level workflows.
7
+ Custom allocators, low-precision storage wrappers, and explicit row-contiguity checks stay visible instead of being hidden behind a dynamic runtime.
8
+ The crate makes the storage policy and result promotion visible.
9
+ That matters for fp16, bf16, fp8, packed bits, and strided reductions.
10
+
11
+ ## Quickstart
12
+
13
+ ```rust
14
+ use numkong::{configure_thread, Dot};
15
+
16
+ fn main() {
17
+ configure_thread();
18
+ let a = [1.0_f32, 2.0, 3.0];
19
+ let b = [4.0_f32, 5.0, 6.0];
20
+ let dot = f32::dot(&a, &b).unwrap();
21
+ println!("dot={dot}");
22
+ }
23
+ ```
24
+
25
+ ## Highlights
26
+
27
+ This is the most fully featured high-level SDK after Python.
28
+ It is a good fit if you want most of the native breadth without dropping into a manual FFI layer.
29
+
30
+ __Trait-first scalar API.__
31
+ `Type::operation(&a, &b)` stays compact and predictable.
32
+ __Allocator-aware tensors.__
33
+ `Tensor`, `PackedMatrix`, and `MaxSimPackedMatrix` can use custom allocators.
34
+ __Storage-first low precision.__
35
+ `f16`, `bf16`, fp8, fp6, and packed integer wrappers are first-class types.
36
+ __Matrix kernels with explicit contracts.__
37
+ Packed and symmetric kernels validate shapes and row contiguity.
38
+ __No hidden thread pool.__
39
+ Parallel helpers remain host-controlled.
40
+ __Fork Union support.__
41
+ The `parallel` feature is the intended native orchestration layer.
42
+
43
+ ## Ecosystem Comparison
44
+
45
+ | Feature | NumKong | [nalgebra](https://github.com/dimforge/nalgebra) | [ndarray](https://github.com/rust-ndarray/ndarray) |
46
+ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------- |
47
+ | Operation families | dots, distances, binary, probability, geospatial, curved, mesh, sparse, MaxSim, elementwise, reductions, cast, trig | linear algebra, decompositions | general n-dimensional arithmetic |
48
+ | Precision | BFloat16 through sub-byte; automatic widening; Kahan summation; 0 ULP in Float32/Float64 | Float32/Float64 only; no widening; standard accuracy | Float32/Float64 only; no widening; standard accuracy |
49
+ | Runtime SIMD dispatch | auto-selects best ISA per-thread at runtime across x86, ARM, RISC-V | none | none |
50
+ | Packed matrix, GEMM-like | pack once, reuse across query batches | standard matmul; no persistent packing | `dot` for matmul; no persistent packing |
51
+ | Symmetric kernels, SYRK-like | skip duplicate pairs, up to 2x speedup for self-distance | no duplicate-pair skipping | no duplicate-pair skipping |
52
+ | Memory model | Caller-owned; `Tensor`/`PackedMatrix` support custom allocators | Heap-allocated matrices; custom storage trait | Heap-allocated; no custom allocator support |
53
+ | Host-side parallelism | row-range partitioning via reusable `ThreadPool`; no hidden threads | Rayon-based parallelism possible | Rayon-based parallelism possible |
54
+
55
+ NumKong validates `f16` and `bf16` interop against the `half` crate in its own test suite.
56
+ That lets you move between ecosystem-standard half types and NumKong's kernel-facing wrappers without ambiguity.
57
+
58
+ ## Installation
59
+
60
+ Minimal:
61
+
62
+ ```toml
63
+ [dependencies]
64
+ numkong = "7"
65
+ ```
66
+
67
+ With host-side parallel helpers:
68
+
69
+ ```toml
70
+ [dependencies]
71
+ numkong = { version = "7", features = ["parallel", "std"] }
72
+ ```
73
+
74
+ ## Compilation and Backend Selection
75
+
76
+ The crate uses the `cc` build system to compile the C backend with `NK_DYNAMIC_DISPATCH=1` automatically.
77
+ All supported backends for the target architecture are compiled into a single binary and selected at runtime.
78
+
79
+ The two Cargo features are `std`, which enables standard library support, and `parallel`, which adds host-side orchestration via ForkUnion and implies `std`.
80
+
81
+ Backend selection follows the target architecture.
82
+ ARM gets NEON, SVE, and SME, with SME available on Linux, FreeBSD, and macOS.
83
+ x86-64 gets Haswell (AVX2), Skylake/Icelake/Sapphire Rapids AVX-512 variants, and AMX on Linux and Windows only.
84
+ RISC-V gets RVV backends on Linux and FreeBSD.
85
+ WASM gets relaxed v128.
86
+
87
+ Individual backends can be disabled through environment variables.
88
+ Any `NK_TARGET_*` variable set to `0` or `false` disables that backend.
89
+ Backends not explicitly disabled are enabled by default for the target platform.
90
+
91
+ ```sh
92
+ NK_TARGET_NEON=0 cargo build
93
+ NK_TARGET_SVE=0 NK_TARGET_SME=0 cargo build
94
+ ```
95
+
96
+ If a backend fails to compile, the build system automatically disables it and retries with the remaining backends.
97
+ A warning is emitted for each disabled backend.
98
+
99
+ ## Dynamic Dispatch and Capabilities
100
+
101
+ `configure_thread` enables CPU-specific acceleration features such as Intel AMX.
102
+ It must be called once per thread before using AMX operations.
103
+
104
+ ```rust
105
+ use numkong::{available, configure_thread, cap};
106
+
107
+ let caps = available();
108
+ configure_thread();
109
+
110
+ if caps & cap::SAPPHIREAMX != 0 {
111
+ println!("AMX available");
112
+ }
113
+ ```
114
+
115
+ Call `configure_thread` at the start of every thread that will use AMX operations.
116
+ In a thread-pool setting, each worker thread needs its own call.
117
+ The function is idempotent and cheap to call more than once on the same thread.
118
+
119
+ ## Core Traits
120
+
121
+ The crate root re-exports the main metric families:
122
+
123
+ - `Dot`, `VDot`, `Angular`, `Euclidean`
124
+ - `Hamming`, `Jaccard`
125
+ - `KullbackLeibler`, `JensenShannon`
126
+ - `Haversine`, `Vincenty`
127
+ - `Bilinear`, `Mahalanobis`
128
+ - `ReduceMoments`, `ReduceMinMax`
129
+ - `EachScale`, `EachSum`, `EachBlend`, `EachFMA`
130
+
131
+ The standard call shape is:
132
+
133
+ ```rust
134
+ use numkong::{Dot, JensenShannon, Jaccard, u1x8};
135
+
136
+ let a = [1.0_f32, 2.0, 3.0];
137
+ let b = [4.0_f32, 5.0, 6.0];
138
+ let dot = f32::dot(&a, &b).unwrap();
139
+
140
+ let bits_a = [u1x8(0b11110000), u1x8(0b00001111)];
141
+ let bits_b = [u1x8(0b11110000), u1x8(0b11110000)];
142
+ let jaccard = u1x8::jaccard(&bits_a, &bits_b).unwrap();
143
+
144
+ let p = [0.2_f32, 0.3, 0.5];
145
+ let q = [0.1_f32, 0.3, 0.6];
146
+ let jsd = f32::jensenshannon(&p, &q).unwrap();
147
+
148
+ println!("{dot} {jaccard} {jsd}");
149
+ ```
150
+
151
+ ## Dot Products
152
+
153
+ Dot products span real, complex, quantized, and packed storage types.
154
+
155
+ ```rust
156
+ use numkong::{Dot, VDot, f32c};
157
+
158
+ let a = [f32c { re: 1.0, im: 2.0 }, f32c { re: 3.0, im: 4.0 }];
159
+ let b = [f32c { re: 5.0, im: 6.0 }, f32c { re: 7.0, im: 8.0 }];
160
+
161
+ let dot = f32c::dot(&a, &b).unwrap();
162
+ let vdot = f32c::vdot(&a, &b).unwrap(); // like numpy.vdot, conjugated
163
+
164
+ println!("{dot:?} {vdot:?}");
165
+ ```
166
+
167
+ ## Dense Distances
168
+
169
+ The dense spatial family covers `sqeuclidean`, `euclidean`, and `angular`.
170
+ The main value over naive loops is the combination of SIMD and safer accumulation policy.
171
+
172
+ ```rust
173
+ use numkong::Euclidean;
174
+
175
+ let a = [1_i8, 2, 3, 4];
176
+ let b = [4_i8, 3, 2, 1];
177
+
178
+ let distance = i8::euclidean(&a, &b).unwrap(); // widened output, not int8
179
+ println!("{distance}");
180
+ ```
181
+
182
+ ## Scalar Types and Promotions
183
+
184
+ The scalar wrappers are storage-first types.
185
+ They are not decorative aliases over `f32`.
186
+
187
+ | Type | Layout | Bytes | Range | Inf | NaN |
188
+ | ------ | ------------- | ----- | ------------ | --- | --- |
189
+ | `f16` | 1+5+10 | 2 | ±65504 | yes | yes |
190
+ | `bf16` | 1+8+7 | 2 | ±3.4×10³⁸ | yes | yes |
191
+ | `e4m3` | 1+4+3 | 1 | ±448 | no | yes |
192
+ | `e5m2` | 1+5+2 | 1 | ±57344 | yes | yes |
193
+ | `e2m3` | 1+2+3 (6 bit) | 1 | ±7.5 | no | no |
194
+ | `e3m2` | 1+3+2 (6 bit) | 1 | ±28 | no | no |
195
+ | `u1x8` | 8 packed bits | 1 | 0–1 per bit | — | — |
196
+ | `u4x2` | 2×4-bit uint | 1 | 0–15 per nib | — | — |
197
+ | `i4x2` | 2×4-bit int | 1 | −8–7 per nib | — | — |
198
+
199
+ The trait hierarchy documents intent:
200
+
201
+ - `StorageElement` — raw storable element type.
202
+ - `NumberLike` — adds numeric conversion and ordering.
203
+ - `FloatConvertible` — adds unpacking and float-domain conversion.
204
+
205
+ The output type is intentionally wider than the storage type for many operations.
206
+ For example, `i8::dot` returns `i32`.
207
+ `f32::dot` returns a wider accumulator type.
208
+ Moments reductions widen even more aggressively.
209
+
210
+ ## Set Similarity
211
+
212
+ Packed-binary metrics work on packed words instead of boolean slices.
213
+ That is the right model once the workload is "semantic hash" rather than "array of booleans".
214
+
215
+ ```rust
216
+ use numkong::{Hamming, Jaccard, u1x8};
217
+
218
+ let a = [u1x8(0b10101010), u1x8(0b11110000)];
219
+ let b = [u1x8(0b10101110), u1x8(0b11000000)];
220
+ let hamming = u1x8::hamming(&a, &b).unwrap();
221
+ let jaccard = u1x8::jaccard(&a, &b).unwrap();
222
+ ```
223
+
224
+ Integer set Jaccard works on sorted arrays of integer identifiers.
225
+
226
+ ```rust
227
+ let set_a = [1_u32, 3, 5, 7, 9];
228
+ let set_b = [3_u32, 5, 8, 9, 10];
229
+ let jaccard_sets = u32::jaccard(&set_a, &set_b).unwrap();
230
+ assert!(jaccard_sets > 0.0 && jaccard_sets < 1.0); // |A ∩ B| / |A ∪ B|
231
+ ```
232
+
233
+ ## Probability Metrics
234
+
235
+ ```rust
236
+ use numkong::{JensenShannon, KullbackLeibler};
237
+
238
+ let p = [0.2_f32, 0.3, 0.5], q = [0.1_f32, 0.3, 0.6];
239
+ let kl_forward = f32::kullbackleibler(&p, &q).unwrap();
240
+ let kl_reverse = f32::kullbackleibler(&q, &p).unwrap();
241
+ assert!(kl_forward != kl_reverse); // KLD is asymmetric
242
+
243
+ let js_forward = f32::jensenshannon(&p, &q).unwrap();
244
+ let js_reverse = f32::jensenshannon(&q, &p).unwrap();
245
+ assert!((js_forward - js_reverse).abs() < 1e-6, "JSD is symmetric");
246
+ ```
247
+
248
+ ## Geospatial Metrics
249
+
250
+ Inputs are latitudes and longitudes in radians.
251
+ Outputs are meters.
252
+
253
+ ```rust
254
+ use numkong::{Haversine, Vincenty};
255
+
256
+ // Statue of Liberty (40.6892°N, 74.0445°W) → Big Ben (51.5007°N, 0.1246°W)
257
+ let liberty_lat = [0.7101605100_f64], liberty_lon = [-1.2923203180_f64];
258
+ let big_ben_lat = [0.8988567821_f64], big_ben_lon = [-0.0021746802_f64];
259
+ let mut distance = [0.0_f64; 1];
260
+ f64::vincenty(&liberty_lat, &liberty_lon, &big_ben_lat, &big_ben_lon, &mut distance).unwrap(); // ≈ 5,589,857 m (ellipsoidal, baseline)
261
+ f64::haversine(&liberty_lat, &liberty_lon, &big_ben_lat, &big_ben_lon, &mut distance).unwrap(); // ≈ 5,543,723 m (spherical, ~46 km less)
262
+
263
+ // Vincenty in f32 — drifts ~2 m from f64
264
+ let liberty_lat32 = [0.7101605100_f32], liberty_lon32 = [-1.2923203180_f32];
265
+ let big_ben_lat32 = [0.8988567821_f32], big_ben_lon32 = [-0.0021746802_f32];
266
+ let mut distance_f32 = [0.0_f32; 1];
267
+ f32::vincenty(&liberty_lat32, &liberty_lon32, &big_ben_lat32, &big_ben_lon32, &mut distance_f32).unwrap(); // ≈ 5,589,859 m (+2 m drift)
268
+ ```
269
+
270
+ ## Curved Metrics
271
+
272
+ Curved-space kernels combine vectors with an extra metric tensor or covariance inverse.
273
+
274
+ ```rust
275
+ use numkong::{Bilinear, Mahalanobis, f32c};
276
+
277
+ // Complex bilinear form: aᴴ M b
278
+ let a = [f32c { re: 1.0, im: 0.0 }; 16];
279
+ let b = [f32c { re: 0.0, im: 1.0 }; 16];
280
+ let metric = [f32c { re: 1.0, im: 0.0 }; 16 * 16];
281
+ let bilinear = f32c::bilinear(&a, &b, &metric).unwrap();
282
+
283
+ // Real Mahalanobis distance: √((a−b)ᵀ M⁻¹ (a−b))
284
+ let x = [1.0_f32; 32];
285
+ let y = [2.0_f32; 32];
286
+ let mut inv_cov = vec![0.0_f32; 32 * 32];
287
+ for i in 0..32 { inv_cov[i * 32 + i] = 1.0; } // identity matrix
288
+ let distance = f32::mahalanobis(&x, &y, &inv_cov).unwrap();
289
+ ```
290
+
291
+ ## Vectors, Tensors, Views, and Spans
292
+
293
+ The container model is unusual enough that it needs direct documentation.
294
+
295
+ - `Vector<T>` owns one-dimensional storage.
296
+ - `VectorView<'a, T>` is an immutable borrowed view.
297
+ - `VectorSpan<'a, T>` is a mutable borrowed view.
298
+ - `Tensor<T, A, MAX_RANK>` owns N-dimensional storage and can use a custom allocator.
299
+ - `TensorView` and `TensorSpan` are the borrowed forms.
300
+ - `Matrix<T>` is a rank-2 alias over `Tensor<T, _, 2>`.
301
+
302
+ The allocator story is explicit.
303
+ `Tensor` and `PackedMatrix` default to `Global`.
304
+ The underlying layout uses `SIMD_ALIGNMENT == 64` for owned allocations.
305
+ That does _not_ mean callers must align their source buffers manually.
306
+ It means owned outputs and packed payloads are allocated in a SIMD-friendly way when the crate owns them.
307
+
308
+ ```rust
309
+ use numkong::{RangeStep, SliceRange, Tensor};
310
+
311
+ let t = Tensor::<f32>::try_from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], &[3, 3]).unwrap();
312
+
313
+ let col = t.slice((.., 1_usize)).unwrap(); // t[:, 1] — column 1
314
+ let rows = t.slice((0..2_usize, ..)).unwrap(); // t[0:2, :] — first two rows
315
+ let tail = t.slice((-2_isize.., ..)).unwrap(); // t[-2:, :] — last two rows
316
+ let neg = t.slice((.., -2..-1_isize)).unwrap(); // t[:, -2:-1]
317
+ let step = t.slice((.., RangeStep::new(0, 3, 2))).unwrap(); // t[:, ::2]
318
+
319
+ // Explicit &[SliceRange] syntax also works
320
+ let col = t.slice(&[SliceRange::full(), SliceRange::index(1)]).unwrap();
321
+ ```
322
+
323
+ Tuple elements implement `SliceArg` — each monomorphized with zero runtime dispatch:
324
+
325
+ | Rust syntax | Meaning |
326
+ | ------------------------------- | -------------------------------------- |
327
+ | `..` | all |
328
+ | `0_usize` / `-1_isize` | single index (negative wraps from end) |
329
+ | `1..4_usize` / `-3..-1_isize` | half-open range |
330
+ | `..3_usize` / `..-1_isize` | from start |
331
+ | `1_usize..` / `-2_isize..` | to end |
332
+ | `0..=2_usize` / `-3..=-1_isize` | inclusive range |
333
+ | `RangeStep::new(0, 6, 2)` | stepped (no Rust literal) |
334
+
335
+ Integer literals default to `i32` — use `_usize` / `_isize` suffixes.
336
+ Negative `isize` values wrap from the dimension end, like Python.
337
+
338
+ Iteration works at the logical-dimension level.
339
+ For sub-byte types like `i4x2` (2 nibbles per byte), iterating a 3-element vector yields 6 dimensions.
340
+ Immutable iterators (`iter()`) yield `DimRef<T>`, which dereferences to `T::DimScalar`.
341
+ Mutable iterators (`iter_mut()`) yield `DimMut<T>`, which writes back on drop — the only way to mutate individual nibbles or bits.
342
+
343
+ ```rust
344
+ use numkong::{Vector, i4x2};
345
+
346
+ let mut nibbles = Vector::<i4x2>::try_zeros(4).unwrap();
347
+ for (i, mut dim) in nibbles.iter_mut().enumerate() {
348
+ *dim = i as i8;
349
+ }
350
+ assert_eq!(nibbles.try_get(0_usize).unwrap(), 0);
351
+ assert_eq!(nibbles.try_get(3_usize).unwrap(), 3);
352
+ ```
353
+
354
+ Vectors and tensors can be converted between each other without copying:
355
+
356
+ ```rust
357
+ use numkong::{Vector, Tensor};
358
+
359
+ let v = Vector::<f32>::try_from_scalars(&[1.0, 2.0, 3.0]).unwrap();
360
+ let t: Tensor<f32, _, 8> = v.try_into_tensor().unwrap();
361
+ assert_eq!(t.shape(), &[3]);
362
+ let v2 = t.try_into_vector().unwrap();
363
+ assert_eq!(v2.dims(), 3);
364
+ ```
365
+
366
+ The main layout rules are:
367
+
368
+ - General slicing and transposition are supported by views.
369
+ - Elementwise and many reduction kernels accept strided views.
370
+ - Matrix-style kernels require rank-2 inputs with contiguous rows.
371
+ - A tensor can be non-contiguous overall and still have contiguous rows.
372
+ - Some reductions have SIMD kernels for strided lanes.
373
+ - Some backends still fall back depending on alignment and dtype.
374
+
375
+ Sub-byte types (`i4x2`, `u4x2`, `u1x8`) use logical shapes.
376
+ A shape of `[8]` for `i4x2` means 8 nibbles (stored in 4 bytes), not 8 bytes.
377
+ The innermost dimension must be divisible by `dimensions_per_value()` (2 for nibble types, 8 for bit types).
378
+ Transpose and reshape are not supported for sub-byte types — they return `SubByteUnsupported`.
379
+
380
+ ## Elementwise Operations
381
+
382
+ Elementwise kernels live on tensors and views.
383
+ They are not a promise that every arbitrary strided view gets the same SIMD path on every backend.
384
+
385
+ ```rust
386
+ use numkong::Tensor;
387
+
388
+ let a = Tensor::<f32>::try_from_slice(&[1.0, 2.0, 3.0, 4.0], &[2, 2]).unwrap();
389
+ let b = Tensor::<f32>::try_full(&[2, 2], 2.0).unwrap();
390
+
391
+ let blended = a.view().try_blend_tensor(&b.view(), 0.25, 0.75).unwrap();
392
+ let sines = blended.sin().unwrap();
393
+
394
+ assert_eq!(sines.shape(), &[2, 2]);
395
+ ```
396
+
397
+ Compound assignment operators work in-place:
398
+
399
+ ```rust
400
+ use numkong::Tensor;
401
+
402
+ let mut t = Tensor::<f32>::try_full(&[4], 1.0).unwrap();
403
+ t += 10.0;
404
+ t -= 0.5;
405
+ t *= 2.0;
406
+ ```
407
+
408
+ ## Trigonometry
409
+
410
+ The trigonometric kernels share the tensor and view surface.
411
+ They are useful both directly and as a sanity check that the container path is not just about matrix kernels.
412
+
413
+ ```rust
414
+ use numkong::Tensor;
415
+
416
+ let a = Tensor::<f32>::try_from_slice(&[0.0, 1.0, 2.0, 3.0], &[2, 2]).unwrap();
417
+ let c = a.cos().unwrap();
418
+ let s = a.sin().unwrap();
419
+
420
+ assert_eq!(c.shape(), &[2, 2]);
421
+ assert_eq!(s.shape(), &[2, 2]);
422
+ ```
423
+
424
+ ## Moments Reductions
425
+
426
+ Moments reductions return both sum and sum-of-squares.
427
+ That is the right building block for norms and variance-like workflows.
428
+
429
+ ```rust
430
+ use numkong::{ReduceMoments, Tensor};
431
+
432
+ let narrow = Tensor::<u8>::try_full(&[1024], 255).unwrap();
433
+ let (sum, sumsq) = narrow.try_moments_all().unwrap();
434
+
435
+ assert!(sum > 255); // a naive u8 accumulation would overflow immediately
436
+ assert!(sumsq > 255u64); // same for sum-of-squares
437
+ ```
438
+
439
+ The important documentation point is not just "wider outputs exist".
440
+ It is that the API makes the widened outputs part of the type story.
441
+
442
+ ## Min/Max Reductions
443
+
444
+ Min/max reductions return a `MinMaxResult` with both the value and its flat index:
445
+
446
+ ```rust
447
+ use numkong::Tensor;
448
+
449
+ let t = Tensor::<f32>::try_from_slice(&[
450
+ 3.0, 0.0, 7.0,
451
+ 1.0, 2.0, 5.0,
452
+ 4.0, -1.0, 6.0,
453
+ ], &[3, 3]).unwrap();
454
+
455
+ let second_column = t.slice((.., 1_usize)).unwrap(); // t[:, 1]
456
+ let idx = second_column.try_argmin_all().unwrap();
457
+
458
+ assert_eq!(idx, 2);
459
+ ```
460
+
461
+
462
+ ## Sparse Operations and Intersections
463
+
464
+ Sparse helpers cover both sorted-index intersection and weighted sparse dot products.
465
+
466
+ ```rust
467
+ use numkong::{SparseIntersect, SparseDot};
468
+
469
+ let a_idx = [1_u32, 3, 5, 7], b_idx = [3_u32, 4, 5, 8];
470
+ let count = u32::sparse_intersection_size(&a_idx, &b_idx);
471
+ assert_eq!(count, 2); // indices 3 and 5
472
+
473
+ let a_weights = [1.0_f32, 2.0, 3.0, 4.0], b_weights = [5.0_f32, 6.0, 7.0, 8.0];
474
+ let dot = u32::sparse_dot(&a_idx, &b_idx, &a_weights, &b_weights).unwrap();
475
+ assert!(dot > 0.0); // weighted dot over shared indices
476
+ ```
477
+
478
+ ## Packed Matrix Kernels for GEMM-Like Workloads
479
+
480
+ Packed kernels are the main "matrix throughput" path in the crate.
481
+ They are `GEMM`-like in workload shape.
482
+ They are not a thin BLAS clone.
483
+
484
+ ```rust
485
+ use numkong::{PackedMatrix, Tensor};
486
+
487
+ let a = Tensor::<f32>::try_full(&[1024, 512], 1.0).unwrap();
488
+ let b = Tensor::<f32>::try_full(&[256, 512], 1.0).unwrap();
489
+
490
+ let b_packed = PackedMatrix::try_pack(&b).unwrap();
491
+ let c = a.dots_packed(&b_packed);
492
+
493
+ assert_eq!(c.shape(), &[1024, 256]);
494
+ ```
495
+
496
+ The useful economics are:
497
+
498
+ - pack `B` once
499
+ - reuse it across many `A` batches
500
+ - convert or pad once during packing instead of on every multiply
501
+ - reuse precomputed norms for `angulars_packed` and `euclideans_packed`
502
+
503
+ The crate checks row contiguity because these kernels assume contiguous rows.
504
+ Caller-side source alignment is not required.
505
+ The owned packed buffer handles its own aligned allocation internally.
506
+
507
+ ## Symmetric Kernels for SYRK-Like Workloads
508
+
509
+ Symmetric kernels are for self-similarity and self-distance.
510
+ They are `SYRK`-like in shape.
511
+ They avoid duplicate `(i, j)` and `(j, i)` work.
512
+
513
+ ```rust
514
+ use numkong::Tensor;
515
+
516
+ let vectors = Tensor::<f32>::try_full(&[100, 768], 1.0).unwrap();
517
+ let gram = vectors.view().try_dots_symmetric().unwrap();
518
+
519
+ assert_eq!(gram.shape(), &[100, 100]);
520
+ ```
521
+
522
+ This family is also where row-window partitioning becomes the natural parallel model.
523
+ That is structurally different from packed `GEMM`-style work against a shared packed RHS.
524
+
525
+ ## MaxSim and ColBERT-Style Late Interaction
526
+
527
+ MaxSim is the late-interaction primitive used by systems such as [ColBERT](https://arxiv.org/abs/2004.12832).
528
+ It is not "just another matrix multiply".
529
+
530
+ ```rust
531
+ use numkong::{MaxSimPackedMatrix, Tensor};
532
+
533
+ let queries = Tensor::<f32>::try_full(&[4, 16], 1.0).unwrap();
534
+ let docs = Tensor::<f32>::try_full(&[8, 16], 1.0).unwrap();
535
+
536
+ let queries_packed = queries.view().try_maxsim_pack().unwrap();
537
+ let docs_packed = docs.view().try_maxsim_pack().unwrap();
538
+ let score = queries_packed.score(&docs_packed);
539
+
540
+ assert!(score.is_finite());
541
+ ```
542
+
543
+ ## Geometric Mesh Alignment
544
+
545
+ Mesh alignment returns transforms, scales, and RMSD values.
546
+ That is a different API shape from the scalar metric families.
547
+
548
+ ```rust
549
+ use numkong::MeshAlignment;
550
+
551
+ let source = [[0.0_f32, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
552
+ let target = [[0.0_f32, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
553
+
554
+ let result = f32::kabsch(&source, &target).unwrap();
555
+ assert!(result.rmsd < 1e-6);
556
+ assert!((result.scale - 1.0).abs() < 1e-6);
557
+
558
+ // Umeyama with known 2x scaling
559
+ let scaled = [[0.0_f32, 0.0, 0.0], [2.0, 0.0, 0.0], [0.0, 2.0, 0.0]];
560
+ let result = f32::umeyama(&source, &scaled).unwrap();
561
+ assert!(result.rmsd < 1e-6);
562
+ assert!((result.scale - 2.0).abs() < 0.01);
563
+ ```
564
+
565
+ ## Tolerance Comparison
566
+
567
+ Exact floating-point equality is rarely what you want after arithmetic.
568
+ `allclose()` checks every element pair with the formula:
569
+
570
+ $$
571
+ |a - b| \leq \text{atol} + \text{rtol} \cdot |b|
572
+ $$
573
+
574
+ Available on `Vector`, `VectorView`, `VectorSpan`, `Tensor`, `TensorView`, and `TensorSpan`.
575
+ For tensors, `allclose` is provided by the `AllCloseOps` trait — import it if calling on a `TensorRef` implementor.
576
+ Shape mismatch returns `false`.
577
+ The scalar helper `is_close` is re-exported at crate root.
578
+
579
+ ```rust
580
+ use numkong::{is_close, Vector, Tensor};
581
+
582
+ // Scalar check
583
+ assert!(is_close(1.0, 1.0 + 1e-8, 1e-6, 0.0));
584
+
585
+ // Vector tolerance check
586
+ let a = Vector::<f32>::try_full(3, 1.0).unwrap();
587
+ let b = Vector::<f32>::try_full(3, 1.0 + 1e-7).unwrap();
588
+ assert!(a.allclose(&b, 1e-6, 0.0));
589
+
590
+ // Tensor tolerance check
591
+ let ta = Tensor::<f32>::try_full(&[2, 3], 1.0).unwrap();
592
+ let tb = Tensor::<f32>::try_full(&[2, 3], 1.0 + 1e-7).unwrap();
593
+ assert!(ta.allclose(&tb, 1e-6, 0.0));
594
+ ```
595
+
596
+ ## Type Casting
597
+
598
+ The `cast` function performs bulk conversion between contiguous slices.
599
+ Any pair of types that implement `CastDtype` (all `NumberLike` scalars) can be converted.
600
+
601
+ ```rust
602
+ use numkong::{cast, f16, bf16};
603
+
604
+ let src: Vec<f32> = vec![1.0, 2.0, 3.0];
605
+ let mut dst: Vec<f16> = vec![f16::from(0.0_f32); 3];
606
+ cast(&src, &mut dst);
607
+ assert!((dst[0].to_f32() - 1.0).abs() < 0.01);
608
+ ```
609
+
610
+ `Tensor`, `TensorView`, and `TensorSpan` expose casting via the `CastOps` trait.
611
+ `try_cast_dtype()` allocates a new tensor; `try_cast_dtype_into()` writes into a pre-allocated `TensorSpan`.
612
+ Strided and non-contiguous views are supported: the implementation scans strides from the innermost dimension outward to find the longest contiguous tail, then walks the outer dimensions and casts each contiguous block in a single kernel call.
613
+
614
+ ```rust
615
+ use numkong::{Tensor, f16};
616
+
617
+ let src = Tensor::<f32>::try_full(&[4, 4], 1.0).unwrap();
618
+ let mut dst = Tensor::<f16>::try_zeros(&[4, 4]).unwrap();
619
+ src.view().try_cast_dtype_into(&mut dst.span()).unwrap();
620
+ ```
621
+
622
+ ## Parallelism and ForkUnion
623
+
624
+ NumKong does not own a thread pool.
625
+ The `parallel` feature adds host-side orchestration helpers via [ForkUnion](https://github.com/ashvardanian/ForkUnion), not a hidden scheduler.
626
+
627
+ ```rust
628
+ use numkong::{PackedMatrix, Tensor};
629
+ use fork_union::ThreadPool;
630
+
631
+ let a = Tensor::<f32>::try_full(&[4096, 768], 1.0).unwrap();
632
+ let b = Tensor::<f32>::try_full(&[8192, 768], 1.0).unwrap();
633
+ let mut pool = ThreadPool::try_spawn(4).unwrap();
634
+
635
+ // GEMM-like: rows of A partitioned across threads, one shared packed B
636
+ let b_packed = PackedMatrix::try_pack(&b).unwrap();
637
+ let c = a.dots_packed_parallel(&b_packed, &mut pool);
638
+ assert_eq!(c.shape(), &[4096, 8192]);
639
+
640
+ // SYRK-like: row windows of one square output partitioned across threads
641
+ let gram = a.dots_symmetric_parallel(&mut pool);
642
+ assert_eq!(gram.shape(), &[4096, 4096]);
643
+ ```
644
+
645
+ Rayon or a manual thread pool can still work if the rest of your application already depends on them.
646
+
647
+ ## Addressing External Memory
648
+
649
+ Views wrap raw pointers without ownership, owned containers accept custom allocators, and the scalar trait API works on any `&[T]` regardless of how the memory was allocated.
650
+
651
+ `VectorView::from_raw_parts` and `TensorView::from_raw_parts` wrap device-accessible or externally allocated memory.
652
+ The mutable counterparts `VectorSpan::from_raw_parts` and `TensorSpan::from_raw_parts` work the same way with `*mut T`.
653
+
654
+ ```rust
655
+ use numkong::{VectorView, TensorView};
656
+
657
+ let embeddings_ptr: *const f32 = /* from CUDA, mmap, or FFI */;
658
+ let embeddings = unsafe {
659
+ VectorView::from_raw_parts(embeddings_ptr, 1024, std::mem::size_of::<f32>() as isize)
660
+ };
661
+
662
+ let shape = [32, 64];
663
+ let strides = [64 * 4, 4]; // row-major f32
664
+ let matrix = unsafe { TensorView::<f32>::from_raw_parts(embeddings_ptr, &shape, &strides) };
665
+ ```
666
+
667
+ Owned containers accept any allocator.
668
+ A CUDA unified memory allocator looks like this:
669
+
670
+ ```rust
671
+ use std::alloc::{Allocator, AllocError, Layout};
672
+ use std::ptr::NonNull;
673
+ use numkong::Vector;
674
+
675
+ struct CudaAllocator;
676
+
677
+ unsafe impl Allocator for CudaAllocator {
678
+ fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
679
+ let raw = unsafe { cuda_malloc_managed(layout.size()) };
680
+ let base = NonNull::new(raw).ok_or(AllocError)?;
681
+ Ok(NonNull::slice_from_raw_parts(base, layout.size()))
682
+ }
683
+ unsafe fn deallocate(&self, block: NonNull<u8>, _layout: Layout) {
684
+ cuda_free(block.as_ptr());
685
+ }
686
+ }
687
+
688
+ let queries = Vector::<f32, CudaAllocator>::try_zeros_in(1024, CudaAllocator).unwrap();
689
+ ```
690
+
691
+ The trait-based scalar API works on any `&[T]` — `Vec`, mmap, arena, or pinned buffer:
692
+
693
+ ```rust
694
+ use numkong::Dot;
695
+
696
+ let weights: &[f32] = /* any contiguous slice */;
697
+ let similarity = f32::dot(weights, weights).unwrap();
698
+ ```