usearch 2.21.4 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) hide show
  1. package/README.md +24 -24
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +7 -7
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +83 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +224 -48
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/dist/cjs/usearch.d.ts +8 -3
  16. package/javascript/dist/cjs/usearch.js +12 -4
  17. package/javascript/dist/esm/usearch.d.ts +8 -3
  18. package/javascript/dist/esm/usearch.js +12 -4
  19. package/javascript/lib.cpp +17 -0
  20. package/javascript/usearch.ts +14 -6
  21. package/numkong/.clang-tidy +30 -0
  22. package/{simsimd → numkong}/.cmake-format.py +18 -0
  23. package/numkong/.editorconfig +12 -0
  24. package/numkong/.git-blame-ignore-revs +123 -0
  25. package/numkong/.mailmap +15 -0
  26. package/numkong/.spi.yml +11 -0
  27. package/numkong/.swift-format +14 -0
  28. package/numkong/CITATION.cff +81 -0
  29. package/numkong/CONTRIBUTING.md +500 -0
  30. package/numkong/Cargo.toml +54 -0
  31. package/numkong/MANIFEST.in +8 -0
  32. package/numkong/Package.swift +84 -0
  33. package/numkong/README.md +569 -0
  34. package/numkong/bench/README.md +217 -0
  35. package/numkong/bench/bench-browser.html +323 -0
  36. package/numkong/bench/bench.cpp +344 -0
  37. package/numkong/bench/bench.hpp +816 -0
  38. package/numkong/bench/bench.js +148 -0
  39. package/numkong/bench/bench.mjs +616 -0
  40. package/numkong/bench/bench_attention.cpp +113 -0
  41. package/numkong/bench/bench_cast.cpp +264 -0
  42. package/numkong/bench/bench_cross_amx.cpp +62 -0
  43. package/numkong/bench/bench_cross_arm.cpp +245 -0
  44. package/numkong/bench/bench_cross_blas.cpp +309 -0
  45. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  46. package/numkong/bench/bench_cross_power.cpp +84 -0
  47. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  48. package/numkong/bench/bench_cross_serial.cpp +151 -0
  49. package/numkong/bench/bench_cross_sme.cpp +163 -0
  50. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  51. package/numkong/bench/bench_cross_x86.cpp +455 -0
  52. package/numkong/bench/bench_curved.cpp +210 -0
  53. package/numkong/bench/bench_dot.cpp +315 -0
  54. package/numkong/bench/bench_each.cpp +503 -0
  55. package/numkong/bench/bench_geospatial.cpp +112 -0
  56. package/numkong/bench/bench_maxsim.cpp +154 -0
  57. package/numkong/bench/bench_mesh.cpp +148 -0
  58. package/numkong/bench/bench_probability.cpp +60 -0
  59. package/numkong/bench/bench_reduce.cpp +371 -0
  60. package/numkong/bench/bench_set.cpp +73 -0
  61. package/numkong/bench/bench_sparse.cpp +198 -0
  62. package/numkong/bench/bench_spatial.cpp +347 -0
  63. package/numkong/bench/bench_trigonometry.cpp +137 -0
  64. package/numkong/bench/swift/Bench.swift +506 -0
  65. package/numkong/binding.gyp +169 -0
  66. package/numkong/build.rs +484 -0
  67. package/numkong/c/dispatch.h +512 -0
  68. package/numkong/c/dispatch_bf16.c +447 -0
  69. package/numkong/c/dispatch_bf16c.c +52 -0
  70. package/numkong/c/dispatch_e2m3.c +296 -0
  71. package/numkong/c/dispatch_e3m2.c +284 -0
  72. package/numkong/c/dispatch_e4m3.c +318 -0
  73. package/numkong/c/dispatch_e5m2.c +316 -0
  74. package/numkong/c/dispatch_f16.c +452 -0
  75. package/numkong/c/dispatch_f16c.c +58 -0
  76. package/numkong/c/dispatch_f32.c +434 -0
  77. package/numkong/c/dispatch_f32c.c +99 -0
  78. package/numkong/c/dispatch_f64.c +348 -0
  79. package/numkong/c/dispatch_f64c.c +98 -0
  80. package/numkong/c/dispatch_i16.c +96 -0
  81. package/numkong/c/dispatch_i32.c +89 -0
  82. package/numkong/c/dispatch_i4.c +153 -0
  83. package/numkong/c/dispatch_i64.c +86 -0
  84. package/numkong/c/dispatch_i8.c +348 -0
  85. package/numkong/c/dispatch_other.c +348 -0
  86. package/numkong/c/dispatch_u1.c +193 -0
  87. package/numkong/c/dispatch_u16.c +124 -0
  88. package/numkong/c/dispatch_u32.c +118 -0
  89. package/numkong/c/dispatch_u4.c +153 -0
  90. package/numkong/c/dispatch_u64.c +102 -0
  91. package/numkong/c/dispatch_u8.c +364 -0
  92. package/numkong/c/numkong.c +940 -0
  93. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  94. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  95. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  96. package/numkong/cmake/nk_math_lib.cmake +46 -0
  97. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  99. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  100. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  101. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  102. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  103. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  104. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  105. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  106. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  107. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  108. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  109. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  110. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  111. package/numkong/include/README.md +643 -0
  112. package/numkong/include/module.modulemap +129 -0
  113. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  114. package/numkong/include/numkong/attention/sme.h +2075 -0
  115. package/numkong/include/numkong/attention.h +49 -0
  116. package/numkong/include/numkong/capabilities.h +930 -0
  117. package/numkong/include/numkong/cast/README.md +262 -0
  118. package/numkong/include/numkong/cast/diamond.h +64 -0
  119. package/numkong/include/numkong/cast/haswell.h +823 -0
  120. package/numkong/include/numkong/cast/icelake.h +475 -0
  121. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  122. package/numkong/include/numkong/cast/neon.h +1174 -0
  123. package/numkong/include/numkong/cast/powervsx.h +449 -0
  124. package/numkong/include/numkong/cast/rvv.h +970 -0
  125. package/numkong/include/numkong/cast/sapphire.h +262 -0
  126. package/numkong/include/numkong/cast/serial.h +2336 -0
  127. package/numkong/include/numkong/cast/skylake.h +915 -0
  128. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  129. package/numkong/include/numkong/cast.h +254 -0
  130. package/numkong/include/numkong/cast.hpp +44 -0
  131. package/numkong/include/numkong/curved/README.md +223 -0
  132. package/numkong/include/numkong/curved/genoa.h +182 -0
  133. package/numkong/include/numkong/curved/haswell.h +276 -0
  134. package/numkong/include/numkong/curved/neon.h +329 -0
  135. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  136. package/numkong/include/numkong/curved/rvv.h +305 -0
  137. package/numkong/include/numkong/curved/serial.h +207 -0
  138. package/numkong/include/numkong/curved/skylake.h +457 -0
  139. package/numkong/include/numkong/curved/smef64.h +530 -0
  140. package/numkong/include/numkong/curved.h +513 -0
  141. package/numkong/include/numkong/curved.hpp +144 -0
  142. package/numkong/include/numkong/dot/README.md +442 -0
  143. package/numkong/include/numkong/dot/alder.h +563 -0
  144. package/numkong/include/numkong/dot/diamond.h +158 -0
  145. package/numkong/include/numkong/dot/genoa.h +289 -0
  146. package/numkong/include/numkong/dot/haswell.h +1723 -0
  147. package/numkong/include/numkong/dot/icelake.h +997 -0
  148. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  149. package/numkong/include/numkong/dot/neon.h +869 -0
  150. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  151. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  152. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  153. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  154. package/numkong/include/numkong/dot/powervsx.h +752 -0
  155. package/numkong/include/numkong/dot/rvv.h +722 -0
  156. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  157. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  158. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  159. package/numkong/include/numkong/dot/sapphire.h +141 -0
  160. package/numkong/include/numkong/dot/serial.h +874 -0
  161. package/numkong/include/numkong/dot/sierra.h +405 -0
  162. package/numkong/include/numkong/dot/skylake.h +1116 -0
  163. package/numkong/include/numkong/dot/sve.h +420 -0
  164. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  165. package/numkong/include/numkong/dot/svehalf.h +168 -0
  166. package/numkong/include/numkong/dot/svesdot.h +90 -0
  167. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  168. package/numkong/include/numkong/dot.h +1136 -0
  169. package/numkong/include/numkong/dot.hpp +94 -0
  170. package/numkong/include/numkong/dots/README.md +496 -0
  171. package/numkong/include/numkong/dots/alder.h +117 -0
  172. package/numkong/include/numkong/dots/diamond.h +86 -0
  173. package/numkong/include/numkong/dots/genoa.h +100 -0
  174. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  175. package/numkong/include/numkong/dots/haswell.h +310 -0
  176. package/numkong/include/numkong/dots/icelake.h +180 -0
  177. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  178. package/numkong/include/numkong/dots/neon.h +123 -0
  179. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  180. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  181. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  182. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  183. package/numkong/include/numkong/dots/powervsx.h +194 -0
  184. package/numkong/include/numkong/dots/rvv.h +2593 -0
  185. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  186. package/numkong/include/numkong/dots/serial.h +2867 -0
  187. package/numkong/include/numkong/dots/sierra.h +100 -0
  188. package/numkong/include/numkong/dots/skylake.h +207 -0
  189. package/numkong/include/numkong/dots/sme.h +5041 -0
  190. package/numkong/include/numkong/dots/smebi32.h +477 -0
  191. package/numkong/include/numkong/dots/smef64.h +1328 -0
  192. package/numkong/include/numkong/dots/smehalf.h +47 -0
  193. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  194. package/numkong/include/numkong/dots.h +3110 -0
  195. package/numkong/include/numkong/dots.hpp +641 -0
  196. package/numkong/include/numkong/each/README.md +465 -0
  197. package/numkong/include/numkong/each/haswell.h +1658 -0
  198. package/numkong/include/numkong/each/icelake.h +272 -0
  199. package/numkong/include/numkong/each/neon.h +1138 -0
  200. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  201. package/numkong/include/numkong/each/neonhalf.h +318 -0
  202. package/numkong/include/numkong/each/rvv.h +1121 -0
  203. package/numkong/include/numkong/each/sapphire.h +343 -0
  204. package/numkong/include/numkong/each/serial.h +282 -0
  205. package/numkong/include/numkong/each/skylake.h +1562 -0
  206. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  207. package/numkong/include/numkong/each.h +2232 -0
  208. package/numkong/include/numkong/each.hpp +434 -0
  209. package/numkong/include/numkong/geospatial/README.md +147 -0
  210. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  211. package/numkong/include/numkong/geospatial/neon.h +615 -0
  212. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  213. package/numkong/include/numkong/geospatial/serial.h +309 -0
  214. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  215. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  216. package/numkong/include/numkong/geospatial.h +453 -0
  217. package/numkong/include/numkong/geospatial.hpp +235 -0
  218. package/numkong/include/numkong/matrix.hpp +336 -0
  219. package/numkong/include/numkong/maxsim/README.md +187 -0
  220. package/numkong/include/numkong/maxsim/alder.h +511 -0
  221. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  222. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  223. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  224. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  225. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  226. package/numkong/include/numkong/maxsim/serial.h +490 -0
  227. package/numkong/include/numkong/maxsim/sme.h +993 -0
  228. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  229. package/numkong/include/numkong/maxsim.h +571 -0
  230. package/numkong/include/numkong/maxsim.hpp +133 -0
  231. package/numkong/include/numkong/mesh/README.md +219 -0
  232. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  233. package/numkong/include/numkong/mesh/neon.h +1821 -0
  234. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  235. package/numkong/include/numkong/mesh/rvv.h +936 -0
  236. package/numkong/include/numkong/mesh/serial.h +721 -0
  237. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  238. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  239. package/numkong/include/numkong/mesh.h +666 -0
  240. package/numkong/include/numkong/mesh.hpp +701 -0
  241. package/numkong/include/numkong/numkong.h +78 -0
  242. package/numkong/include/numkong/numkong.hpp +58 -0
  243. package/numkong/include/numkong/probability/README.md +177 -0
  244. package/numkong/include/numkong/probability/haswell.h +267 -0
  245. package/numkong/include/numkong/probability/neon.h +255 -0
  246. package/numkong/include/numkong/probability/rvv.h +414 -0
  247. package/numkong/include/numkong/probability/serial.h +181 -0
  248. package/numkong/include/numkong/probability/skylake.h +324 -0
  249. package/numkong/include/numkong/probability.h +380 -0
  250. package/numkong/include/numkong/probability.hpp +120 -0
  251. package/numkong/include/numkong/random.h +50 -0
  252. package/numkong/include/numkong/random.hpp +285 -0
  253. package/numkong/include/numkong/reduce/README.md +552 -0
  254. package/numkong/include/numkong/reduce/alder.h +636 -0
  255. package/numkong/include/numkong/reduce/genoa.h +201 -0
  256. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  257. package/numkong/include/numkong/reduce/icelake.h +549 -0
  258. package/numkong/include/numkong/reduce/neon.h +3980 -0
  259. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  260. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  261. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  262. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  263. package/numkong/include/numkong/reduce/serial.h +753 -0
  264. package/numkong/include/numkong/reduce/sierra.h +338 -0
  265. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  266. package/numkong/include/numkong/reduce/sve.h +52 -0
  267. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  268. package/numkong/include/numkong/reduce.h +1582 -0
  269. package/numkong/include/numkong/reduce.hpp +778 -0
  270. package/numkong/include/numkong/scalar/README.md +89 -0
  271. package/numkong/include/numkong/scalar/haswell.h +122 -0
  272. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  273. package/numkong/include/numkong/scalar/neon.h +122 -0
  274. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  275. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  276. package/numkong/include/numkong/scalar/rvv.h +211 -0
  277. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  278. package/numkong/include/numkong/scalar/serial.h +332 -0
  279. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  280. package/numkong/include/numkong/scalar.h +696 -0
  281. package/numkong/include/numkong/set/README.md +179 -0
  282. package/numkong/include/numkong/set/haswell.h +334 -0
  283. package/numkong/include/numkong/set/icelake.h +485 -0
  284. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  285. package/numkong/include/numkong/set/neon.h +363 -0
  286. package/numkong/include/numkong/set/powervsx.h +326 -0
  287. package/numkong/include/numkong/set/rvv.h +226 -0
  288. package/numkong/include/numkong/set/rvvbb.h +117 -0
  289. package/numkong/include/numkong/set/serial.h +174 -0
  290. package/numkong/include/numkong/set/sve.h +187 -0
  291. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  292. package/numkong/include/numkong/set.h +471 -0
  293. package/numkong/include/numkong/set.hpp +114 -0
  294. package/numkong/include/numkong/sets/README.md +149 -0
  295. package/numkong/include/numkong/sets/haswell.h +63 -0
  296. package/numkong/include/numkong/sets/icelake.h +66 -0
  297. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  298. package/numkong/include/numkong/sets/neon.h +61 -0
  299. package/numkong/include/numkong/sets/powervsx.h +65 -0
  300. package/numkong/include/numkong/sets/serial.h +43 -0
  301. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  302. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  303. package/numkong/include/numkong/sets.h +382 -0
  304. package/numkong/include/numkong/sparse/README.md +156 -0
  305. package/numkong/include/numkong/sparse/icelake.h +463 -0
  306. package/numkong/include/numkong/sparse/neon.h +288 -0
  307. package/numkong/include/numkong/sparse/serial.h +117 -0
  308. package/numkong/include/numkong/sparse/sve2.h +504 -0
  309. package/numkong/include/numkong/sparse/turin.h +322 -0
  310. package/numkong/include/numkong/sparse.h +363 -0
  311. package/numkong/include/numkong/sparse.hpp +113 -0
  312. package/numkong/include/numkong/spatial/README.md +439 -0
  313. package/numkong/include/numkong/spatial/alder.h +604 -0
  314. package/numkong/include/numkong/spatial/diamond.h +240 -0
  315. package/numkong/include/numkong/spatial/genoa.h +222 -0
  316. package/numkong/include/numkong/spatial/haswell.h +979 -0
  317. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  318. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  319. package/numkong/include/numkong/spatial/neon.h +846 -0
  320. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  321. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  322. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  323. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  324. package/numkong/include/numkong/spatial/rvv.h +991 -0
  325. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  326. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  327. package/numkong/include/numkong/spatial/serial.h +347 -0
  328. package/numkong/include/numkong/spatial/sierra.h +516 -0
  329. package/numkong/include/numkong/spatial/skylake.h +605 -0
  330. package/numkong/include/numkong/spatial/sve.h +246 -0
  331. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  332. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  333. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  334. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  335. package/numkong/include/numkong/spatial.h +1681 -0
  336. package/numkong/include/numkong/spatial.hpp +183 -0
  337. package/numkong/include/numkong/spatials/README.md +580 -0
  338. package/numkong/include/numkong/spatials/alder.h +94 -0
  339. package/numkong/include/numkong/spatials/diamond.h +82 -0
  340. package/numkong/include/numkong/spatials/genoa.h +94 -0
  341. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  342. package/numkong/include/numkong/spatials/haswell.h +219 -0
  343. package/numkong/include/numkong/spatials/icelake.h +113 -0
  344. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  345. package/numkong/include/numkong/spatials/neon.h +109 -0
  346. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  347. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  348. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  349. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  350. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  351. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  352. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  353. package/numkong/include/numkong/spatials/serial.h +248 -0
  354. package/numkong/include/numkong/spatials/sierra.h +96 -0
  355. package/numkong/include/numkong/spatials/skylake.h +184 -0
  356. package/numkong/include/numkong/spatials/sme.h +1927 -0
  357. package/numkong/include/numkong/spatials/smef64.h +483 -0
  358. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  359. package/numkong/include/numkong/spatials.h +3374 -0
  360. package/numkong/include/numkong/spatials.hpp +509 -0
  361. package/numkong/include/numkong/tensor.hpp +1981 -0
  362. package/numkong/include/numkong/trigonometry/README.md +184 -0
  363. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  364. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  365. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  366. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  367. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  368. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  369. package/numkong/include/numkong/trigonometry.h +467 -0
  370. package/numkong/include/numkong/trigonometry.hpp +166 -0
  371. package/numkong/include/numkong/types.h +1695 -0
  372. package/numkong/include/numkong/types.hpp +6027 -0
  373. package/numkong/include/numkong/vector.hpp +766 -0
  374. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  375. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  376. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  377. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  378. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  380. package/numkong/javascript/README.md +254 -0
  381. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  382. package/numkong/javascript/numkong-browser.ts +40 -0
  383. package/numkong/javascript/numkong-wasm.ts +750 -0
  384. package/numkong/javascript/numkong.c +712 -0
  385. package/numkong/javascript/numkong.ts +613 -0
  386. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  387. package/numkong/javascript/tsconfig-cjs.json +13 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  389. package/numkong/javascript/types.ts +784 -0
  390. package/numkong/numkong.gypi +104 -0
  391. package/numkong/package.json +108 -0
  392. package/numkong/probes/arm_neon.c +8 -0
  393. package/numkong/probes/arm_neon_bfdot.c +9 -0
  394. package/numkong/probes/arm_neon_fhm.c +9 -0
  395. package/numkong/probes/arm_neon_half.c +8 -0
  396. package/numkong/probes/arm_neon_sdot.c +9 -0
  397. package/numkong/probes/arm_neonfp8.c +9 -0
  398. package/numkong/probes/arm_sme.c +16 -0
  399. package/numkong/probes/arm_sme2.c +16 -0
  400. package/numkong/probes/arm_sme2p1.c +16 -0
  401. package/numkong/probes/arm_sme_bf16.c +16 -0
  402. package/numkong/probes/arm_sme_bi32.c +16 -0
  403. package/numkong/probes/arm_sme_f64.c +16 -0
  404. package/numkong/probes/arm_sme_fa64.c +14 -0
  405. package/numkong/probes/arm_sme_half.c +16 -0
  406. package/numkong/probes/arm_sme_lut2.c +15 -0
  407. package/numkong/probes/arm_sve.c +18 -0
  408. package/numkong/probes/arm_sve2.c +20 -0
  409. package/numkong/probes/arm_sve2p1.c +18 -0
  410. package/numkong/probes/arm_sve_bfdot.c +20 -0
  411. package/numkong/probes/arm_sve_half.c +18 -0
  412. package/numkong/probes/arm_sve_sdot.c +21 -0
  413. package/numkong/probes/loongarch_lasx.c +12 -0
  414. package/numkong/probes/power_vsx.c +12 -0
  415. package/numkong/probes/probe.js +127 -0
  416. package/numkong/probes/riscv_rvv.c +14 -0
  417. package/numkong/probes/riscv_rvv_bb.c +15 -0
  418. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  419. package/numkong/probes/riscv_rvv_half.c +14 -0
  420. package/numkong/probes/wasm_v128relaxed.c +11 -0
  421. package/numkong/probes/x86_alder.c +17 -0
  422. package/numkong/probes/x86_diamond.c +17 -0
  423. package/numkong/probes/x86_genoa.c +17 -0
  424. package/numkong/probes/x86_graniteamx.c +19 -0
  425. package/numkong/probes/x86_haswell.c +11 -0
  426. package/numkong/probes/x86_icelake.c +17 -0
  427. package/numkong/probes/x86_sapphire.c +16 -0
  428. package/numkong/probes/x86_sapphireamx.c +18 -0
  429. package/numkong/probes/x86_sierra.c +17 -0
  430. package/numkong/probes/x86_skylake.c +15 -0
  431. package/numkong/probes/x86_turin.c +17 -0
  432. package/numkong/rust/README.md +698 -0
  433. package/numkong/rust/capabilities.rs +96 -0
  434. package/numkong/rust/cast.rs +314 -0
  435. package/numkong/rust/curved.rs +391 -0
  436. package/numkong/rust/each.rs +2721 -0
  437. package/numkong/rust/geospatial.rs +343 -0
  438. package/numkong/rust/matrix.rs +5424 -0
  439. package/numkong/rust/maxsim.rs +540 -0
  440. package/numkong/rust/mesh.rs +837 -0
  441. package/numkong/rust/numkong.rs +409 -0
  442. package/numkong/rust/probability.rs +272 -0
  443. package/numkong/rust/reduce.rs +1249 -0
  444. package/numkong/rust/set.rs +194 -0
  445. package/numkong/rust/sparse.rs +513 -0
  446. package/numkong/rust/spatial.rs +1815 -0
  447. package/numkong/rust/tensor.rs +7565 -0
  448. package/numkong/rust/types.rs +3666 -0
  449. package/numkong/rust/vector.rs +1899 -0
  450. package/numkong/rustfmt.toml +2 -0
  451. package/numkong/swift/Matrix.swift +1388 -0
  452. package/numkong/swift/MaxSim.swift +151 -0
  453. package/numkong/swift/NumKong.swift +283 -0
  454. package/numkong/swift/Numerics.swift +329 -0
  455. package/numkong/swift/README.md +433 -0
  456. package/numkong/swift/Scalar.swift +741 -0
  457. package/numkong/swift/Tensor.swift +209 -0
  458. package/numkong/test/README.md +315 -0
  459. package/numkong/test/playwright.config.ts +16 -0
  460. package/numkong/test/swift/Test.swift +534 -0
  461. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  462. package/numkong/test/test-browser-bundle.html +188 -0
  463. package/numkong/test/test-browser-runner.mjs +43 -0
  464. package/numkong/test/test-browser.html +305 -0
  465. package/numkong/test/test-dtypes.mjs +453 -0
  466. package/numkong/test/test-wasm.mjs +267 -0
  467. package/numkong/test/test.cpp +442 -0
  468. package/numkong/test/test.hpp +580 -0
  469. package/numkong/test/test.mjs +363 -0
  470. package/numkong/test/test_base.py +1041 -0
  471. package/numkong/test/test_cast.cpp +242 -0
  472. package/numkong/test/test_cross.hpp +551 -0
  473. package/numkong/test/test_cross.py +467 -0
  474. package/numkong/test/test_cross_amx.cpp +50 -0
  475. package/numkong/test/test_cross_arm.cpp +225 -0
  476. package/numkong/test/test_cross_blas.cpp +354 -0
  477. package/numkong/test/test_cross_loongarch.cpp +90 -0
  478. package/numkong/test/test_cross_power.cpp +73 -0
  479. package/numkong/test/test_cross_rvv.cpp +109 -0
  480. package/numkong/test/test_cross_serial.cpp +181 -0
  481. package/numkong/test/test_cross_sme.cpp +148 -0
  482. package/numkong/test/test_cross_wasm.cpp +141 -0
  483. package/numkong/test/test_cross_x86.cpp +442 -0
  484. package/numkong/test/test_curved.cpp +182 -0
  485. package/numkong/test/test_curved.py +207 -0
  486. package/numkong/test/test_dot.cpp +353 -0
  487. package/numkong/test/test_dot.py +296 -0
  488. package/numkong/test/test_each.cpp +437 -0
  489. package/numkong/test/test_each.py +756 -0
  490. package/numkong/test/test_geospatial.cpp +155 -0
  491. package/numkong/test/test_geospatial.py +241 -0
  492. package/numkong/test/test_maxsim.cpp +138 -0
  493. package/numkong/test/test_maxsim.py +209 -0
  494. package/numkong/test/test_mesh.cpp +203 -0
  495. package/numkong/test/test_mesh.py +394 -0
  496. package/numkong/test/test_probability.cpp +136 -0
  497. package/numkong/test/test_probability.py +166 -0
  498. package/numkong/test/test_reduce.cpp +563 -0
  499. package/numkong/test/test_reduce.py +781 -0
  500. package/numkong/test/test_set.cpp +151 -0
  501. package/numkong/test/test_set.py +120 -0
  502. package/numkong/test/test_similarities.py +579 -0
  503. package/numkong/test/test_sparse.cpp +121 -0
  504. package/numkong/test/test_sparse.py +118 -0
  505. package/numkong/test/test_spatial.cpp +518 -0
  506. package/numkong/test/test_spatial.py +269 -0
  507. package/numkong/test/test_tensor.cpp +884 -0
  508. package/numkong/test/test_tensor.py +1417 -0
  509. package/numkong/test/test_trigonometry.cpp +156 -0
  510. package/numkong/test/test_trigonometry.py +180 -0
  511. package/package.json +7 -8
  512. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  513. package/prebuilds/linux-arm64/usearch.node +0 -0
  514. package/prebuilds/linux-x64/usearch.node +0 -0
  515. package/fp16/CMakeLists.txt +0 -176
  516. package/fp16/LICENSE +0 -11
  517. package/fp16/README.md +0 -20
  518. package/fp16/bench/alt-element.cc +0 -89
  519. package/fp16/bench/from-alt-array.cc +0 -175
  520. package/fp16/bench/from-ieee-array.cc +0 -399
  521. package/fp16/bench/ieee-element.cc +0 -272
  522. package/fp16/bench/to-alt-array.cc +0 -91
  523. package/fp16/bench/to-ieee-array.cc +0 -303
  524. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  525. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  526. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  527. package/fp16/configure.py +0 -65
  528. package/fp16/confu.yaml +0 -8
  529. package/fp16/include/fp16/__init__.py +0 -0
  530. package/fp16/include/fp16/avx.py +0 -50
  531. package/fp16/include/fp16/avx2.py +0 -53
  532. package/fp16/include/fp16/bitcasts.h +0 -92
  533. package/fp16/include/fp16/fp16.h +0 -451
  534. package/fp16/include/fp16/psimd.h +0 -131
  535. package/fp16/include/fp16.h +0 -11
  536. package/fp16/jni/Android.mk +0 -6
  537. package/fp16/jni/Application.mk +0 -4
  538. package/fp16/test/alt-from-fp32-value.cc +0 -498
  539. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  540. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  541. package/fp16/test/alt-to-fp32-value.cc +0 -348
  542. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  543. package/fp16/test/bitcasts.cc +0 -56
  544. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  545. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  546. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  547. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  548. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  549. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  550. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  551. package/fp16/test/peachpy/stubs.py +0 -38
  552. package/fp16/test/tables.cc +0 -530
  553. package/fp16/test/tables.h +0 -13
  554. package/fp16/third-party/THHalf.h +0 -92
  555. package/fp16/third-party/eigen-half.h +0 -170
  556. package/fp16/third-party/float16-compressor.h +0 -80
  557. package/fp16/third-party/half.hpp +0 -2916
  558. package/fp16/third-party/npy-halffloat.h +0 -328
  559. package/simsimd/.git-blame-ignore-revs +0 -2
  560. package/simsimd/CONTRIBUTING.md +0 -321
  561. package/simsimd/Cargo.toml +0 -49
  562. package/simsimd/MANIFEST.in +0 -4
  563. package/simsimd/Package.swift +0 -28
  564. package/simsimd/README.md +0 -1493
  565. package/simsimd/binding.gyp +0 -35
  566. package/simsimd/build.rs +0 -70
  567. package/simsimd/c/lib.c +0 -374
  568. package/simsimd/include/module.modulemap +0 -4
  569. package/simsimd/include/simsimd/binary.h +0 -486
  570. package/simsimd/include/simsimd/curved.h +0 -1541
  571. package/simsimd/include/simsimd/dot.h +0 -1853
  572. package/simsimd/include/simsimd/elementwise.h +0 -2465
  573. package/simsimd/include/simsimd/geospatial.h +0 -43
  574. package/simsimd/include/simsimd/mesh.h +0 -69
  575. package/simsimd/include/simsimd/probability.h +0 -606
  576. package/simsimd/include/simsimd/simsimd.h +0 -2567
  577. package/simsimd/include/simsimd/sparse.h +0 -1384
  578. package/simsimd/include/simsimd/spatial.h +0 -2335
  579. package/simsimd/include/simsimd/types.h +0 -666
  580. package/simsimd/javascript/fallback.ts +0 -233
  581. package/simsimd/javascript/lib.c +0 -125
  582. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  583. package/simsimd/javascript/simsimd.ts +0 -179
  584. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  585. package/simsimd/package-lock.json +0 -1761
  586. package/simsimd/package.json +0 -61
  587. package/simsimd/rust/lib.rs +0 -1821
  588. package/simsimd/scripts/bench.cxx +0 -1170
  589. package/simsimd/scripts/bench.ipynb +0 -187
  590. package/simsimd/scripts/bench.js +0 -127
  591. package/simsimd/scripts/bench.rs +0 -876
  592. package/simsimd/scripts/bench_vectors.py +0 -734
  593. package/simsimd/scripts/bench_vectors_live.py +0 -213
  594. package/simsimd/scripts/test.c +0 -187
  595. package/simsimd/scripts/test.mjs +0 -220
  596. package/simsimd/scripts/test.py +0 -1505
  597. package/simsimd/swift/SimSIMD.swift +0 -149
  598. package/simsimd/swift/Test.swift +0 -128
  599. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  600. /package/{simsimd → numkong}/LICENSE +0 -0
  601. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  602. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,1249 @@
1
+ //! Statistical reductions: moments (sum/sum-of-squares) and min/max.
2
+ //!
3
+ //! This module provides:
4
+ //!
5
+ //! - [`ReduceMoments`]: Sum and sum-of-squares over a strided slice
6
+ //! - [`ReduceMinMax`]: Minimum and maximum over a strided slice
7
+ //! - [`Reductions`]: Blanket trait combining `ReduceMoments + ReduceMinMax`
8
+
9
+ use crate::types::{bf16, e2m3, e3m2, e4m3, e5m2, f16, i4x2, u1x8, u4x2, StorageElement};
10
+
11
+ #[link(name = "numkong")]
12
+ extern "C" {
13
+ // Reductions: moments (sum + sum-of-squares)
14
+ fn nk_reduce_moments_f64(
15
+ data: *const f64,
16
+ count: usize,
17
+ stride_bytes: usize,
18
+ sum: *mut f64,
19
+ sumsq: *mut f64,
20
+ );
21
+ fn nk_reduce_moments_f32(
22
+ data: *const f32,
23
+ count: usize,
24
+ stride_bytes: usize,
25
+ sum: *mut f64,
26
+ sumsq: *mut f64,
27
+ );
28
+ fn nk_reduce_moments_i8(
29
+ data: *const i8,
30
+ count: usize,
31
+ stride_bytes: usize,
32
+ sum: *mut i64,
33
+ sumsq: *mut u64,
34
+ );
35
+ fn nk_reduce_moments_u8(
36
+ data: *const u8,
37
+ count: usize,
38
+ stride_bytes: usize,
39
+ sum: *mut u64,
40
+ sumsq: *mut u64,
41
+ );
42
+ fn nk_reduce_moments_i16(
43
+ data: *const i16,
44
+ count: usize,
45
+ stride_bytes: usize,
46
+ sum: *mut i64,
47
+ sumsq: *mut u64,
48
+ );
49
+ fn nk_reduce_moments_u16(
50
+ data: *const u16,
51
+ count: usize,
52
+ stride_bytes: usize,
53
+ sum: *mut u64,
54
+ sumsq: *mut u64,
55
+ );
56
+ fn nk_reduce_moments_i32(
57
+ data: *const i32,
58
+ count: usize,
59
+ stride_bytes: usize,
60
+ sum: *mut i64,
61
+ sumsq: *mut u64,
62
+ );
63
+ fn nk_reduce_moments_u32(
64
+ data: *const u32,
65
+ count: usize,
66
+ stride_bytes: usize,
67
+ sum: *mut u64,
68
+ sumsq: *mut u64,
69
+ );
70
+ fn nk_reduce_moments_i64(
71
+ data: *const i64,
72
+ count: usize,
73
+ stride_bytes: usize,
74
+ sum: *mut i64,
75
+ sumsq: *mut u64,
76
+ );
77
+ fn nk_reduce_moments_u64(
78
+ data: *const u64,
79
+ count: usize,
80
+ stride_bytes: usize,
81
+ sum: *mut u64,
82
+ sumsq: *mut u64,
83
+ );
84
+ fn nk_reduce_moments_f16(
85
+ data: *const f16,
86
+ count: usize,
87
+ stride_bytes: usize,
88
+ sum: *mut f32,
89
+ sumsq: *mut f32,
90
+ );
91
+ fn nk_reduce_moments_bf16(
92
+ data: *const bf16,
93
+ count: usize,
94
+ stride_bytes: usize,
95
+ sum: *mut f32,
96
+ sumsq: *mut f32,
97
+ );
98
+ fn nk_reduce_moments_e4m3(
99
+ data: *const e4m3,
100
+ count: usize,
101
+ stride_bytes: usize,
102
+ sum: *mut f32,
103
+ sumsq: *mut f32,
104
+ );
105
+ fn nk_reduce_moments_e5m2(
106
+ data: *const e5m2,
107
+ count: usize,
108
+ stride_bytes: usize,
109
+ sum: *mut f32,
110
+ sumsq: *mut f32,
111
+ );
112
+ fn nk_reduce_moments_e2m3(
113
+ data: *const e2m3,
114
+ count: usize,
115
+ stride_bytes: usize,
116
+ sum: *mut f32,
117
+ sumsq: *mut f32,
118
+ );
119
+ fn nk_reduce_moments_e3m2(
120
+ data: *const e3m2,
121
+ count: usize,
122
+ stride_bytes: usize,
123
+ sum: *mut f32,
124
+ sumsq: *mut f32,
125
+ );
126
+ fn nk_reduce_moments_i4(
127
+ data: *const i4x2,
128
+ count: usize,
129
+ stride_bytes: usize,
130
+ sum: *mut i64,
131
+ sumsq: *mut u64,
132
+ );
133
+ fn nk_reduce_moments_u4(
134
+ data: *const u4x2,
135
+ count: usize,
136
+ stride_bytes: usize,
137
+ sum: *mut u64,
138
+ sumsq: *mut u64,
139
+ );
140
+ fn nk_reduce_moments_u1(
141
+ data: *const u1x8,
142
+ count: usize,
143
+ stride_bytes: usize,
144
+ sum: *mut u64,
145
+ sumsq: *mut u64,
146
+ );
147
+
148
+ // Reductions: minmax (min + max + argmin + argmax)
149
+ fn nk_reduce_minmax_f64(
150
+ data: *const f64,
151
+ count: usize,
152
+ stride_bytes: usize,
153
+ min_val: *mut f64,
154
+ min_idx: *mut usize,
155
+ max_val: *mut f64,
156
+ max_idx: *mut usize,
157
+ );
158
+ fn nk_reduce_minmax_f32(
159
+ data: *const f32,
160
+ count: usize,
161
+ stride_bytes: usize,
162
+ min_val: *mut f32,
163
+ min_idx: *mut usize,
164
+ max_val: *mut f32,
165
+ max_idx: *mut usize,
166
+ );
167
+ fn nk_reduce_minmax_i8(
168
+ data: *const i8,
169
+ count: usize,
170
+ stride_bytes: usize,
171
+ min_val: *mut i8,
172
+ min_idx: *mut usize,
173
+ max_val: *mut i8,
174
+ max_idx: *mut usize,
175
+ );
176
+ fn nk_reduce_minmax_u8(
177
+ data: *const u8,
178
+ count: usize,
179
+ stride_bytes: usize,
180
+ min_val: *mut u8,
181
+ min_idx: *mut usize,
182
+ max_val: *mut u8,
183
+ max_idx: *mut usize,
184
+ );
185
+ fn nk_reduce_minmax_i16(
186
+ data: *const i16,
187
+ count: usize,
188
+ stride_bytes: usize,
189
+ min_val: *mut i16,
190
+ min_idx: *mut usize,
191
+ max_val: *mut i16,
192
+ max_idx: *mut usize,
193
+ );
194
+ fn nk_reduce_minmax_u16(
195
+ data: *const u16,
196
+ count: usize,
197
+ stride_bytes: usize,
198
+ min_val: *mut u16,
199
+ min_idx: *mut usize,
200
+ max_val: *mut u16,
201
+ max_idx: *mut usize,
202
+ );
203
+ fn nk_reduce_minmax_i32(
204
+ data: *const i32,
205
+ count: usize,
206
+ stride_bytes: usize,
207
+ min_val: *mut i32,
208
+ min_idx: *mut usize,
209
+ max_val: *mut i32,
210
+ max_idx: *mut usize,
211
+ );
212
+ fn nk_reduce_minmax_u32(
213
+ data: *const u32,
214
+ count: usize,
215
+ stride_bytes: usize,
216
+ min_val: *mut u32,
217
+ min_idx: *mut usize,
218
+ max_val: *mut u32,
219
+ max_idx: *mut usize,
220
+ );
221
+ fn nk_reduce_minmax_i64(
222
+ data: *const i64,
223
+ count: usize,
224
+ stride_bytes: usize,
225
+ min_val: *mut i64,
226
+ min_idx: *mut usize,
227
+ max_val: *mut i64,
228
+ max_idx: *mut usize,
229
+ );
230
+ fn nk_reduce_minmax_u64(
231
+ data: *const u64,
232
+ count: usize,
233
+ stride_bytes: usize,
234
+ min_val: *mut u64,
235
+ min_idx: *mut usize,
236
+ max_val: *mut u64,
237
+ max_idx: *mut usize,
238
+ );
239
+ fn nk_reduce_minmax_f16(
240
+ data: *const f16,
241
+ count: usize,
242
+ stride_bytes: usize,
243
+ min_val: *mut f16,
244
+ min_idx: *mut usize,
245
+ max_val: *mut f16,
246
+ max_idx: *mut usize,
247
+ );
248
+ fn nk_reduce_minmax_bf16(
249
+ data: *const bf16,
250
+ count: usize,
251
+ stride_bytes: usize,
252
+ min_val: *mut bf16,
253
+ min_idx: *mut usize,
254
+ max_val: *mut bf16,
255
+ max_idx: *mut usize,
256
+ );
257
+ fn nk_reduce_minmax_e4m3(
258
+ data: *const e4m3,
259
+ count: usize,
260
+ stride_bytes: usize,
261
+ min_val: *mut e4m3,
262
+ min_idx: *mut usize,
263
+ max_val: *mut e4m3,
264
+ max_idx: *mut usize,
265
+ );
266
+ fn nk_reduce_minmax_e5m2(
267
+ data: *const e5m2,
268
+ count: usize,
269
+ stride_bytes: usize,
270
+ min_val: *mut e5m2,
271
+ min_idx: *mut usize,
272
+ max_val: *mut e5m2,
273
+ max_idx: *mut usize,
274
+ );
275
+ fn nk_reduce_minmax_e2m3(
276
+ data: *const e2m3,
277
+ count: usize,
278
+ stride_bytes: usize,
279
+ min_val: *mut e2m3,
280
+ min_idx: *mut usize,
281
+ max_val: *mut e2m3,
282
+ max_idx: *mut usize,
283
+ );
284
+ fn nk_reduce_minmax_e3m2(
285
+ data: *const e3m2,
286
+ count: usize,
287
+ stride_bytes: usize,
288
+ min_val: *mut e3m2,
289
+ min_idx: *mut usize,
290
+ max_val: *mut e3m2,
291
+ max_idx: *mut usize,
292
+ );
293
+ fn nk_reduce_minmax_i4(
294
+ data: *const i4x2,
295
+ count: usize,
296
+ stride_bytes: usize,
297
+ min_val: *mut i8,
298
+ min_idx: *mut usize,
299
+ max_val: *mut i8,
300
+ max_idx: *mut usize,
301
+ );
302
+ fn nk_reduce_minmax_u4(
303
+ data: *const u4x2,
304
+ count: usize,
305
+ stride_bytes: usize,
306
+ min_val: *mut u8,
307
+ min_idx: *mut usize,
308
+ max_val: *mut u8,
309
+ max_idx: *mut usize,
310
+ );
311
+ fn nk_reduce_minmax_u1(
312
+ data: *const u1x8,
313
+ count: usize,
314
+ stride_bytes: usize,
315
+ min_val: *mut u8,
316
+ min_idx: *mut usize,
317
+ max_val: *mut u8,
318
+ max_idx: *mut usize,
319
+ );
320
+ }
321
+
322
+ /// Compute first and second moments (sum and sum-of-squares) with stride support.
323
+ ///
324
+ /// Returns `(sum, sum_of_squares)` for all elements in a slice, with optional striding.
325
+ /// The output types may be wider than the input to avoid overflow.
326
+ pub trait ReduceMoments: StorageElement {
327
+ /// Type for the sum output.
328
+ type SumOutput: StorageElement;
329
+ /// Type for the sum-of-squares output.
330
+ type SumSqOutput: StorageElement;
331
+ /// Compute `(sum, sum_of_squares)` for raw pointer input with the given stride in bytes.
332
+ ///
333
+ /// # Safety
334
+ /// `data` must point to at least one reachable element when `count > 0`, and every logical
335
+ /// element addressed by `count` and `stride_bytes` must be valid to read.
336
+ unsafe fn reduce_moments_raw(
337
+ data: *const Self,
338
+ count: usize,
339
+ stride_bytes: usize,
340
+ ) -> (Self::SumOutput, Self::SumSqOutput);
341
+ /// Compute `(sum, sum_of_squares)` for `data` with the given stride (in bytes).
342
+ /// Use `stride_bytes = size_of::<Self>()` for contiguous data.
343
+ fn reduce_moments(data: &[Self], stride_bytes: usize) -> (Self::SumOutput, Self::SumSqOutput) {
344
+ unsafe { Self::reduce_moments_raw(data.as_ptr(), data.len(), stride_bytes) }
345
+ }
346
+ }
347
+
348
+ unsafe fn reduce_moments_via_ffi<Scalar, Sum: Default, SumSq: Default>(
349
+ data: *const Scalar,
350
+ count: usize,
351
+ stride_bytes: usize,
352
+ ffi: unsafe extern "C" fn(*const Scalar, usize, usize, *mut Sum, *mut SumSq),
353
+ ) -> (Sum, SumSq)
354
+ where
355
+ Scalar: StorageElement,
356
+ {
357
+ let mut sum: Sum = Default::default();
358
+ let mut sumsq: SumSq = Default::default();
359
+ ffi(
360
+ data,
361
+ count * Scalar::dimensions_per_value(),
362
+ stride_bytes,
363
+ &mut sum,
364
+ &mut sumsq,
365
+ );
366
+ (sum, sumsq)
367
+ }
368
+
369
+ impl ReduceMoments for f64 {
370
+ type SumOutput = f64;
371
+ type SumSqOutput = f64;
372
+
373
+ unsafe fn reduce_moments_raw(
374
+ data: *const Self,
375
+ count: usize,
376
+ stride_bytes: usize,
377
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
378
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_f64)
379
+ }
380
+ }
381
+
382
+ impl ReduceMoments for f32 {
383
+ type SumOutput = f64;
384
+ type SumSqOutput = f64;
385
+
386
+ unsafe fn reduce_moments_raw(
387
+ data: *const Self,
388
+ count: usize,
389
+ stride_bytes: usize,
390
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
391
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_f32)
392
+ }
393
+ }
394
+
395
+ impl ReduceMoments for i8 {
396
+ type SumOutput = i64;
397
+ type SumSqOutput = u64;
398
+
399
+ unsafe fn reduce_moments_raw(
400
+ data: *const Self,
401
+ count: usize,
402
+ stride_bytes: usize,
403
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
404
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_i8)
405
+ }
406
+ }
407
+
408
+ impl ReduceMoments for u8 {
409
+ type SumOutput = u64;
410
+ type SumSqOutput = u64;
411
+
412
+ unsafe fn reduce_moments_raw(
413
+ data: *const Self,
414
+ count: usize,
415
+ stride_bytes: usize,
416
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
417
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_u8)
418
+ }
419
+ }
420
+
421
+ impl ReduceMoments for i16 {
422
+ type SumOutput = i64;
423
+ type SumSqOutput = u64;
424
+
425
+ unsafe fn reduce_moments_raw(
426
+ data: *const Self,
427
+ count: usize,
428
+ stride_bytes: usize,
429
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
430
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_i16)
431
+ }
432
+ }
433
+
434
+ impl ReduceMoments for u16 {
435
+ type SumOutput = u64;
436
+ type SumSqOutput = u64;
437
+
438
+ unsafe fn reduce_moments_raw(
439
+ data: *const Self,
440
+ count: usize,
441
+ stride_bytes: usize,
442
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
443
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_u16)
444
+ }
445
+ }
446
+
447
+ impl ReduceMoments for i32 {
448
+ type SumOutput = i64;
449
+ type SumSqOutput = u64;
450
+
451
+ unsafe fn reduce_moments_raw(
452
+ data: *const Self,
453
+ count: usize,
454
+ stride_bytes: usize,
455
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
456
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_i32)
457
+ }
458
+ }
459
+
460
+ impl ReduceMoments for u32 {
461
+ type SumOutput = u64;
462
+ type SumSqOutput = u64;
463
+
464
+ unsafe fn reduce_moments_raw(
465
+ data: *const Self,
466
+ count: usize,
467
+ stride_bytes: usize,
468
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
469
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_u32)
470
+ }
471
+ }
472
+
473
+ impl ReduceMoments for i64 {
474
+ type SumOutput = i64;
475
+ type SumSqOutput = u64;
476
+
477
+ unsafe fn reduce_moments_raw(
478
+ data: *const Self,
479
+ count: usize,
480
+ stride_bytes: usize,
481
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
482
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_i64)
483
+ }
484
+ }
485
+
486
+ impl ReduceMoments for u64 {
487
+ type SumOutput = u64;
488
+ type SumSqOutput = u64;
489
+
490
+ unsafe fn reduce_moments_raw(
491
+ data: *const Self,
492
+ count: usize,
493
+ stride_bytes: usize,
494
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
495
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_u64)
496
+ }
497
+ }
498
+
499
+ impl ReduceMoments for f16 {
500
+ type SumOutput = f32;
501
+ type SumSqOutput = f32;
502
+
503
+ unsafe fn reduce_moments_raw(
504
+ data: *const Self,
505
+ count: usize,
506
+ stride_bytes: usize,
507
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
508
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_f16)
509
+ }
510
+ }
511
+
512
+ impl ReduceMoments for bf16 {
513
+ type SumOutput = f32;
514
+ type SumSqOutput = f32;
515
+
516
+ unsafe fn reduce_moments_raw(
517
+ data: *const Self,
518
+ count: usize,
519
+ stride_bytes: usize,
520
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
521
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_bf16)
522
+ }
523
+ }
524
+
525
+ impl ReduceMoments for e4m3 {
526
+ type SumOutput = f32;
527
+ type SumSqOutput = f32;
528
+
529
+ unsafe fn reduce_moments_raw(
530
+ data: *const Self,
531
+ count: usize,
532
+ stride_bytes: usize,
533
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
534
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_e4m3)
535
+ }
536
+ }
537
+
538
+ impl ReduceMoments for e5m2 {
539
+ type SumOutput = f32;
540
+ type SumSqOutput = f32;
541
+
542
+ unsafe fn reduce_moments_raw(
543
+ data: *const Self,
544
+ count: usize,
545
+ stride_bytes: usize,
546
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
547
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_e5m2)
548
+ }
549
+ }
550
+
551
+ impl ReduceMoments for e2m3 {
552
+ type SumOutput = f32;
553
+ type SumSqOutput = f32;
554
+
555
+ unsafe fn reduce_moments_raw(
556
+ data: *const Self,
557
+ count: usize,
558
+ stride_bytes: usize,
559
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
560
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_e2m3)
561
+ }
562
+ }
563
+
564
+ impl ReduceMoments for e3m2 {
565
+ type SumOutput = f32;
566
+ type SumSqOutput = f32;
567
+
568
+ unsafe fn reduce_moments_raw(
569
+ data: *const Self,
570
+ count: usize,
571
+ stride_bytes: usize,
572
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
573
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_e3m2)
574
+ }
575
+ }
576
+
577
+ impl ReduceMoments for i4x2 {
578
+ type SumOutput = i64;
579
+ type SumSqOutput = u64;
580
+
581
+ unsafe fn reduce_moments_raw(
582
+ data: *const Self,
583
+ count: usize,
584
+ stride_bytes: usize,
585
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
586
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_i4)
587
+ }
588
+ }
589
+
590
+ impl ReduceMoments for u4x2 {
591
+ type SumOutput = u64;
592
+ type SumSqOutput = u64;
593
+
594
+ unsafe fn reduce_moments_raw(
595
+ data: *const Self,
596
+ count: usize,
597
+ stride_bytes: usize,
598
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
599
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_u4)
600
+ }
601
+ }
602
+
603
+ impl ReduceMoments for u1x8 {
604
+ type SumOutput = u64;
605
+ type SumSqOutput = u64;
606
+
607
+ unsafe fn reduce_moments_raw(
608
+ data: *const Self,
609
+ count: usize,
610
+ stride_bytes: usize,
611
+ ) -> (Self::SumOutput, Self::SumSqOutput) {
612
+ reduce_moments_via_ffi(data, count, stride_bytes, nk_reduce_moments_u1)
613
+ }
614
+ }
615
+
616
+ /// Find minimum and maximum values with their indices, with stride support.
617
+ ///
618
+ /// Returns `Some((min_value, min_index, max_value, max_index))` for all elements in a slice,
619
+ /// or `None` if all elements are NaN (for NaN-masking formats).
620
+ /// The output value type matches the logical reduced scalar type.
621
+ pub trait ReduceMinMax: StorageElement {
622
+ /// Output type for the min/max values — matches the C layer's native type.
623
+ type Output: StorageElement;
624
+ /// Whether `NK_SIZE_MAX` indicates that the reduction produced no value.
625
+ const NONE_ON_SENTINEL: bool;
626
+ /// Returns `Some((min_value, min_index, max_value, max_index))` for raw pointer input with the
627
+ /// specified stride, or `None` if all elements are NaN.
628
+ ///
629
+ /// # Safety
630
+ /// `data` must point to at least one reachable element when `count > 0`, and every logical
631
+ /// element addressed by `count` and `stride_bytes` must be valid to read.
632
+ unsafe fn reduce_minmax_raw(
633
+ data: *const Self,
634
+ count: usize,
635
+ stride_bytes: usize,
636
+ ) -> Option<(Self::Output, usize, Self::Output, usize)>;
637
+ /// Returns `Some((min_value, min_index, max_value, max_index))` for the given data with the
638
+ /// specified stride, or `None` if all elements are NaN.
639
+ fn reduce_minmax(
640
+ data: &[Self],
641
+ stride_bytes: usize,
642
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
643
+ unsafe { Self::reduce_minmax_raw(data.as_ptr(), data.len(), stride_bytes) }
644
+ }
645
+ }
646
+
647
+ unsafe fn reduce_minmax_via_ffi<Scalar, Out: Default>(
648
+ data: *const Scalar,
649
+ count: usize,
650
+ stride_bytes: usize,
651
+ none_on_sentinel: bool,
652
+ ffi: unsafe extern "C" fn(
653
+ *const Scalar,
654
+ usize,
655
+ usize,
656
+ *mut Out,
657
+ *mut usize,
658
+ *mut Out,
659
+ *mut usize,
660
+ ),
661
+ ) -> Option<(Out, usize, Out, usize)>
662
+ where
663
+ Scalar: StorageElement,
664
+ {
665
+ let mut min_value: Out = Default::default();
666
+ let mut min_index: usize = 0;
667
+ let mut max_value: Out = Default::default();
668
+ let mut max_index: usize = 0;
669
+ ffi(
670
+ data,
671
+ count * Scalar::dimensions_per_value(),
672
+ stride_bytes,
673
+ &mut min_value,
674
+ &mut min_index,
675
+ &mut max_value,
676
+ &mut max_index,
677
+ );
678
+ if none_on_sentinel && min_index == usize::MAX {
679
+ return None;
680
+ }
681
+ Some((min_value, min_index, max_value, max_index))
682
+ }
683
+
684
+ impl ReduceMinMax for f64 {
685
+ type Output = f64;
686
+ const NONE_ON_SENTINEL: bool = true;
687
+
688
+ unsafe fn reduce_minmax_raw(
689
+ data: *const Self,
690
+ count: usize,
691
+ stride_bytes: usize,
692
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
693
+ reduce_minmax_via_ffi(
694
+ data,
695
+ count,
696
+ stride_bytes,
697
+ Self::NONE_ON_SENTINEL,
698
+ nk_reduce_minmax_f64,
699
+ )
700
+ }
701
+ }
702
+
703
+ impl ReduceMinMax for f32 {
704
+ type Output = f32;
705
+ const NONE_ON_SENTINEL: bool = true;
706
+
707
+ unsafe fn reduce_minmax_raw(
708
+ data: *const Self,
709
+ count: usize,
710
+ stride_bytes: usize,
711
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
712
+ reduce_minmax_via_ffi(
713
+ data,
714
+ count,
715
+ stride_bytes,
716
+ Self::NONE_ON_SENTINEL,
717
+ nk_reduce_minmax_f32,
718
+ )
719
+ }
720
+ }
721
+
722
+ impl ReduceMinMax for i8 {
723
+ type Output = i8;
724
+ const NONE_ON_SENTINEL: bool = false;
725
+
726
+ unsafe fn reduce_minmax_raw(
727
+ data: *const Self,
728
+ count: usize,
729
+ stride_bytes: usize,
730
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
731
+ reduce_minmax_via_ffi(
732
+ data,
733
+ count,
734
+ stride_bytes,
735
+ Self::NONE_ON_SENTINEL,
736
+ nk_reduce_minmax_i8,
737
+ )
738
+ }
739
+ }
740
+
741
+ impl ReduceMinMax for u8 {
742
+ type Output = u8;
743
+ const NONE_ON_SENTINEL: bool = false;
744
+
745
+ unsafe fn reduce_minmax_raw(
746
+ data: *const Self,
747
+ count: usize,
748
+ stride_bytes: usize,
749
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
750
+ reduce_minmax_via_ffi(
751
+ data,
752
+ count,
753
+ stride_bytes,
754
+ Self::NONE_ON_SENTINEL,
755
+ nk_reduce_minmax_u8,
756
+ )
757
+ }
758
+ }
759
+
760
+ impl ReduceMinMax for i16 {
761
+ type Output = i16;
762
+ const NONE_ON_SENTINEL: bool = false;
763
+
764
+ unsafe fn reduce_minmax_raw(
765
+ data: *const Self,
766
+ count: usize,
767
+ stride_bytes: usize,
768
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
769
+ reduce_minmax_via_ffi(
770
+ data,
771
+ count,
772
+ stride_bytes,
773
+ Self::NONE_ON_SENTINEL,
774
+ nk_reduce_minmax_i16,
775
+ )
776
+ }
777
+ }
778
+
779
+ impl ReduceMinMax for u16 {
780
+ type Output = u16;
781
+ const NONE_ON_SENTINEL: bool = false;
782
+
783
+ unsafe fn reduce_minmax_raw(
784
+ data: *const Self,
785
+ count: usize,
786
+ stride_bytes: usize,
787
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
788
+ reduce_minmax_via_ffi(
789
+ data,
790
+ count,
791
+ stride_bytes,
792
+ Self::NONE_ON_SENTINEL,
793
+ nk_reduce_minmax_u16,
794
+ )
795
+ }
796
+ }
797
+
798
+ impl ReduceMinMax for i32 {
799
+ type Output = i32;
800
+ const NONE_ON_SENTINEL: bool = false;
801
+
802
+ unsafe fn reduce_minmax_raw(
803
+ data: *const Self,
804
+ count: usize,
805
+ stride_bytes: usize,
806
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
807
+ reduce_minmax_via_ffi(
808
+ data,
809
+ count,
810
+ stride_bytes,
811
+ Self::NONE_ON_SENTINEL,
812
+ nk_reduce_minmax_i32,
813
+ )
814
+ }
815
+ }
816
+
817
+ impl ReduceMinMax for u32 {
818
+ type Output = u32;
819
+ const NONE_ON_SENTINEL: bool = false;
820
+
821
+ unsafe fn reduce_minmax_raw(
822
+ data: *const Self,
823
+ count: usize,
824
+ stride_bytes: usize,
825
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
826
+ reduce_minmax_via_ffi(
827
+ data,
828
+ count,
829
+ stride_bytes,
830
+ Self::NONE_ON_SENTINEL,
831
+ nk_reduce_minmax_u32,
832
+ )
833
+ }
834
+ }
835
+
836
+ impl ReduceMinMax for i64 {
837
+ type Output = i64;
838
+ const NONE_ON_SENTINEL: bool = false;
839
+
840
+ unsafe fn reduce_minmax_raw(
841
+ data: *const Self,
842
+ count: usize,
843
+ stride_bytes: usize,
844
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
845
+ reduce_minmax_via_ffi(
846
+ data,
847
+ count,
848
+ stride_bytes,
849
+ Self::NONE_ON_SENTINEL,
850
+ nk_reduce_minmax_i64,
851
+ )
852
+ }
853
+ }
854
+
855
+ impl ReduceMinMax for u64 {
856
+ type Output = u64;
857
+ const NONE_ON_SENTINEL: bool = false;
858
+
859
+ unsafe fn reduce_minmax_raw(
860
+ data: *const Self,
861
+ count: usize,
862
+ stride_bytes: usize,
863
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
864
+ reduce_minmax_via_ffi(
865
+ data,
866
+ count,
867
+ stride_bytes,
868
+ Self::NONE_ON_SENTINEL,
869
+ nk_reduce_minmax_u64,
870
+ )
871
+ }
872
+ }
873
+
874
+ impl ReduceMinMax for f16 {
875
+ type Output = f16;
876
+ const NONE_ON_SENTINEL: bool = true;
877
+
878
+ unsafe fn reduce_minmax_raw(
879
+ data: *const Self,
880
+ count: usize,
881
+ stride_bytes: usize,
882
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
883
+ reduce_minmax_via_ffi(
884
+ data,
885
+ count,
886
+ stride_bytes,
887
+ Self::NONE_ON_SENTINEL,
888
+ nk_reduce_minmax_f16,
889
+ )
890
+ }
891
+ }
892
+
893
+ impl ReduceMinMax for bf16 {
894
+ type Output = bf16;
895
+ const NONE_ON_SENTINEL: bool = true;
896
+
897
+ unsafe fn reduce_minmax_raw(
898
+ data: *const Self,
899
+ count: usize,
900
+ stride_bytes: usize,
901
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
902
+ reduce_minmax_via_ffi(
903
+ data,
904
+ count,
905
+ stride_bytes,
906
+ Self::NONE_ON_SENTINEL,
907
+ nk_reduce_minmax_bf16,
908
+ )
909
+ }
910
+ }
911
+
912
+ impl ReduceMinMax for e4m3 {
913
+ type Output = e4m3;
914
+ const NONE_ON_SENTINEL: bool = true;
915
+
916
+ unsafe fn reduce_minmax_raw(
917
+ data: *const Self,
918
+ count: usize,
919
+ stride_bytes: usize,
920
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
921
+ reduce_minmax_via_ffi(
922
+ data,
923
+ count,
924
+ stride_bytes,
925
+ Self::NONE_ON_SENTINEL,
926
+ nk_reduce_minmax_e4m3,
927
+ )
928
+ }
929
+ }
930
+
931
+ impl ReduceMinMax for e5m2 {
932
+ type Output = e5m2;
933
+ const NONE_ON_SENTINEL: bool = true;
934
+
935
+ unsafe fn reduce_minmax_raw(
936
+ data: *const Self,
937
+ count: usize,
938
+ stride_bytes: usize,
939
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
940
+ reduce_minmax_via_ffi(
941
+ data,
942
+ count,
943
+ stride_bytes,
944
+ Self::NONE_ON_SENTINEL,
945
+ nk_reduce_minmax_e5m2,
946
+ )
947
+ }
948
+ }
949
+
950
+ impl ReduceMinMax for e2m3 {
951
+ type Output = e2m3;
952
+ const NONE_ON_SENTINEL: bool = false;
953
+
954
+ unsafe fn reduce_minmax_raw(
955
+ data: *const Self,
956
+ count: usize,
957
+ stride_bytes: usize,
958
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
959
+ reduce_minmax_via_ffi(
960
+ data,
961
+ count,
962
+ stride_bytes,
963
+ Self::NONE_ON_SENTINEL,
964
+ nk_reduce_minmax_e2m3,
965
+ )
966
+ }
967
+ }
968
+
969
+ impl ReduceMinMax for e3m2 {
970
+ type Output = e3m2;
971
+ const NONE_ON_SENTINEL: bool = false;
972
+
973
+ unsafe fn reduce_minmax_raw(
974
+ data: *const Self,
975
+ count: usize,
976
+ stride_bytes: usize,
977
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
978
+ reduce_minmax_via_ffi(
979
+ data,
980
+ count,
981
+ stride_bytes,
982
+ Self::NONE_ON_SENTINEL,
983
+ nk_reduce_minmax_e3m2,
984
+ )
985
+ }
986
+ }
987
+
988
+ impl ReduceMinMax for i4x2 {
989
+ type Output = i8;
990
+ const NONE_ON_SENTINEL: bool = false;
991
+
992
+ unsafe fn reduce_minmax_raw(
993
+ data: *const Self,
994
+ count: usize,
995
+ stride_bytes: usize,
996
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
997
+ reduce_minmax_via_ffi(
998
+ data,
999
+ count,
1000
+ stride_bytes,
1001
+ Self::NONE_ON_SENTINEL,
1002
+ nk_reduce_minmax_i4,
1003
+ )
1004
+ }
1005
+ }
1006
+
1007
+ impl ReduceMinMax for u4x2 {
1008
+ type Output = u8;
1009
+ const NONE_ON_SENTINEL: bool = false;
1010
+
1011
+ unsafe fn reduce_minmax_raw(
1012
+ data: *const Self,
1013
+ count: usize,
1014
+ stride_bytes: usize,
1015
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
1016
+ reduce_minmax_via_ffi(
1017
+ data,
1018
+ count,
1019
+ stride_bytes,
1020
+ Self::NONE_ON_SENTINEL,
1021
+ nk_reduce_minmax_u4,
1022
+ )
1023
+ }
1024
+ }
1025
+
1026
+ impl ReduceMinMax for u1x8 {
1027
+ type Output = u8;
1028
+ const NONE_ON_SENTINEL: bool = false;
1029
+
1030
+ unsafe fn reduce_minmax_raw(
1031
+ data: *const Self,
1032
+ count: usize,
1033
+ stride_bytes: usize,
1034
+ ) -> Option<(Self::Output, usize, Self::Output, usize)> {
1035
+ reduce_minmax_via_ffi(
1036
+ data,
1037
+ count,
1038
+ stride_bytes,
1039
+ Self::NONE_ON_SENTINEL,
1040
+ nk_reduce_minmax_u1,
1041
+ )
1042
+ }
1043
+ }
1044
+
1045
+ /// `Reductions` bundles reduction operations: ReduceMoments and ReduceMinMax.
1046
+ pub trait Reductions: ReduceMoments + ReduceMinMax {}
1047
+ impl<Scalar: ReduceMoments + ReduceMinMax> Reductions for Scalar {}
1048
+
1049
+ #[cfg(test)]
1050
+ mod tests {
1051
+ use super::*;
1052
+ use crate::types::{
1053
+ assert_close, bf16, e2m3, e3m2, e4m3, e5m2, f16, FloatLike, NumberLike, TestableType,
1054
+ };
1055
+
1056
+ // region: ReduceMoments
1057
+
1058
+ fn check_reduce_moments<Scalar>(input_values: &[f32])
1059
+ where
1060
+ Scalar: FloatLike + TestableType + ReduceMoments,
1061
+ Scalar::SumOutput: FloatLike,
1062
+ Scalar::SumSqOutput: FloatLike,
1063
+ {
1064
+ let data: Vec<Scalar> = input_values.iter().map(|&v| Scalar::from_f32(v)).collect();
1065
+ let stride_bytes = core::mem::size_of::<Scalar>();
1066
+ let (actual_sum, actual_sumsq) = Scalar::reduce_moments(&data, stride_bytes);
1067
+ let expected_sum: f64 = input_values.iter().map(|&v| v as f64).sum();
1068
+ let expected_sumsq: f64 = input_values.iter().map(|&v| (v as f64) * (v as f64)).sum();
1069
+ let sample_count = input_values.len() as f64;
1070
+ assert_close(
1071
+ actual_sum.to_f64(),
1072
+ expected_sum,
1073
+ Scalar::atol() * sample_count,
1074
+ Scalar::rtol(),
1075
+ &format!("reduce_moments<{}> sum", core::any::type_name::<Scalar>()),
1076
+ );
1077
+ assert_close(
1078
+ actual_sumsq.to_f64(),
1079
+ expected_sumsq,
1080
+ Scalar::atol() * sample_count,
1081
+ Scalar::rtol(),
1082
+ &format!("reduce_moments<{}> sumsq", core::any::type_name::<Scalar>()),
1083
+ );
1084
+ }
1085
+
1086
+ #[test]
1087
+ fn moments_reduction() {
1088
+ // Float types — SumOutput/SumSqOutput are FloatLike (f32 or f64)
1089
+ let input_values = &[1.0, 2.0, 3.0, 4.0, 5.0];
1090
+ check_reduce_moments::<f64>(input_values);
1091
+ check_reduce_moments::<f32>(input_values);
1092
+ check_reduce_moments::<f16>(input_values);
1093
+ check_reduce_moments::<bf16>(input_values);
1094
+ check_reduce_moments::<e4m3>(input_values);
1095
+ check_reduce_moments::<e5m2>(&[1.0, 2.0, 3.0]);
1096
+ check_reduce_moments::<e2m3>(&[1.0, 2.0, 3.0]);
1097
+ check_reduce_moments::<e3m2>(&[1.0, 2.0, 3.0]);
1098
+
1099
+ // Integer types — now also go through generics with FloatLike for i64/u64
1100
+ let signed = &[1.0_f32, -2.0, 3.0, -4.0, 5.0];
1101
+ let unsigned = &[1.0_f32, 2.0, 3.0, 4.0, 5.0];
1102
+ check_reduce_moments::<i8>(signed);
1103
+ check_reduce_moments::<u8>(unsigned);
1104
+ check_reduce_moments::<i16>(signed);
1105
+ check_reduce_moments::<u16>(unsigned);
1106
+ check_reduce_moments::<i32>(signed);
1107
+ check_reduce_moments::<u32>(unsigned);
1108
+ check_reduce_moments::<i64>(signed);
1109
+ check_reduce_moments::<u64>(unsigned);
1110
+ }
1111
+
1112
+ // endregion
1113
+
1114
+ // region: ReduceMinMax
1115
+
1116
+ fn check_reduce_minmax<Scalar>(input_values: &[f32])
1117
+ where
1118
+ Scalar: FloatLike + TestableType + ReduceMinMax,
1119
+ Scalar::Output: FloatLike,
1120
+ {
1121
+ let data: Vec<Scalar> = input_values.iter().map(|&v| Scalar::from_f32(v)).collect();
1122
+ let stride_bytes = core::mem::size_of::<Scalar>();
1123
+ let result = Scalar::reduce_minmax(&data, stride_bytes);
1124
+ assert!(result.is_some(), "Expected Some for non-NaN input");
1125
+ let (actual_min, actual_min_index, actual_max, actual_max_index) = result.unwrap();
1126
+ let (expected_min_index, expected_min) = input_values
1127
+ .iter()
1128
+ .enumerate()
1129
+ .min_by(|left, right| left.1.partial_cmp(right.1).unwrap())
1130
+ .unwrap();
1131
+ let (expected_max_index, expected_max) = input_values
1132
+ .iter()
1133
+ .enumerate()
1134
+ .max_by(|left, right| left.1.partial_cmp(right.1).unwrap())
1135
+ .unwrap();
1136
+ assert_close(
1137
+ actual_min.to_f64(),
1138
+ *expected_min as f64,
1139
+ Scalar::atol(),
1140
+ 0.0,
1141
+ &format!("reduce_minmax<{}> min", core::any::type_name::<Scalar>()),
1142
+ );
1143
+ assert_eq!(
1144
+ actual_min_index,
1145
+ expected_min_index,
1146
+ "reduce_minmax<{}> min_index",
1147
+ core::any::type_name::<Scalar>()
1148
+ );
1149
+ assert_close(
1150
+ actual_max.to_f64(),
1151
+ *expected_max as f64,
1152
+ Scalar::atol(),
1153
+ 0.0,
1154
+ &format!("reduce_minmax<{}> max", core::any::type_name::<Scalar>()),
1155
+ );
1156
+ assert_eq!(
1157
+ actual_max_index,
1158
+ expected_max_index,
1159
+ "reduce_minmax<{}> max_index",
1160
+ core::any::type_name::<Scalar>()
1161
+ );
1162
+ }
1163
+
1164
+ #[test]
1165
+ fn minmax_reduction() {
1166
+ // All FloatLike types — Output is also FloatLike
1167
+ let input_values = &[3.0, 1.0, 4.0, 1.5, 5.0, 2.0];
1168
+ check_reduce_minmax::<f64>(input_values);
1169
+ check_reduce_minmax::<f32>(input_values);
1170
+ check_reduce_minmax::<f16>(input_values);
1171
+ check_reduce_minmax::<bf16>(input_values);
1172
+ check_reduce_minmax::<e4m3>(input_values);
1173
+ check_reduce_minmax::<e5m2>(input_values);
1174
+ check_reduce_minmax::<e2m3>(&[3.0, 1.0, 4.0, 1.5, 5.0, 2.0]);
1175
+ check_reduce_minmax::<e3m2>(input_values);
1176
+ check_reduce_minmax::<i8>(input_values);
1177
+ check_reduce_minmax::<u8>(input_values);
1178
+ check_reduce_minmax::<i32>(input_values);
1179
+ check_reduce_minmax::<u32>(input_values);
1180
+
1181
+ // i16, u16, i64, u64 — now also go through generics with FloatLike
1182
+ check_reduce_minmax::<i16>(&[3.0, -1.0, 4.0, -5.0, 2.0]);
1183
+ check_reduce_minmax::<u16>(&[3.0, 1.0, 4.0, 5.0, 2.0]);
1184
+ check_reduce_minmax::<i64>(&[3.0, -1.0, 4.0, -5.0, 2.0]);
1185
+ check_reduce_minmax::<u64>(&[3.0, 1.0, 4.0, 5.0, 2.0]);
1186
+ }
1187
+
1188
+ #[test]
1189
+ fn minmax_reduction_all_nan() {
1190
+ let nan_f64: Vec<f64> = vec![f64::NAN; 16];
1191
+ assert_eq!(
1192
+ f64::reduce_minmax(&nan_f64, core::mem::size_of::<f64>()),
1193
+ None
1194
+ );
1195
+
1196
+ let nan_f32: Vec<f32> = vec![f32::NAN; 16];
1197
+ assert_eq!(
1198
+ f32::reduce_minmax(&nan_f32, core::mem::size_of::<f32>()),
1199
+ None
1200
+ );
1201
+
1202
+ let nan_f16: Vec<f16> = vec![f16::NAN; 16];
1203
+ assert_eq!(
1204
+ f16::reduce_minmax(&nan_f16, core::mem::size_of::<f16>()),
1205
+ None
1206
+ );
1207
+
1208
+ let nan_bf16: Vec<bf16> = vec![bf16::NAN; 16];
1209
+ assert_eq!(
1210
+ bf16::reduce_minmax(&nan_bf16, core::mem::size_of::<bf16>()),
1211
+ None
1212
+ );
1213
+
1214
+ let nan_e4m3: Vec<e4m3> = vec![e4m3::NAN; 16];
1215
+ assert_eq!(
1216
+ e4m3::reduce_minmax(&nan_e4m3, core::mem::size_of::<e4m3>()),
1217
+ None
1218
+ );
1219
+
1220
+ let nan_e5m2: Vec<e5m2> = vec![e5m2::NAN; 16];
1221
+ assert_eq!(
1222
+ e5m2::reduce_minmax(&nan_e5m2, core::mem::size_of::<e5m2>()),
1223
+ None
1224
+ );
1225
+ }
1226
+
1227
+ #[test]
1228
+ fn minmax_reduction_mixed_nan() {
1229
+ let data = vec![f64::NAN, 3.0, f64::NAN, 1.0, f64::NAN, 5.0];
1230
+ let result = f64::reduce_minmax(&data, core::mem::size_of::<f64>());
1231
+ assert!(result.is_some());
1232
+ let (min_value, min_index, max_value, max_index) = result.unwrap();
1233
+ assert_close(min_value, 1.0, 1e-10, 0.0, "mixed min");
1234
+ assert_eq!(min_index, 3);
1235
+ assert_close(max_value, 5.0, 1e-10, 0.0, "mixed max");
1236
+ assert_eq!(max_index, 5);
1237
+
1238
+ let data_f32: Vec<f32> = vec![f32::NAN, 3.0, f32::NAN, 1.0, f32::NAN, 5.0];
1239
+ let result_f32 = f32::reduce_minmax(&data_f32, core::mem::size_of::<f32>());
1240
+ assert!(result_f32.is_some());
1241
+ let (min_value, min_index, max_value, max_index) = result_f32.unwrap();
1242
+ assert_close(min_value as f64, 1.0, 1e-5, 0.0, "mixed f32 min");
1243
+ assert_eq!(min_index, 3);
1244
+ assert_close(max_value as f64, 5.0, 1e-5, 0.0, "mixed f32 max");
1245
+ assert_eq!(max_index, 5);
1246
+ }
1247
+
1248
+ // endregion
1249
+ }