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,254 @@
1
+ /**
2
+ * @brief SIMD-accelerated Type Conversions.
3
+ * @file include/numkong/cast.h
4
+ * @author Ash Vardanian
5
+ * @date January 2, 2026
6
+ *
7
+ * This file focuses on numeric types not uniformly supported across platforms, prioritizing:
8
+ *
9
+ * - `e5m2` & `e4m3` ↔ `f16` & `bf16` - used for low-precision dot-products on modern CPUs,
10
+ * - `e5m2` & `e4m3` ↔ `f32` - used for low-precision dot-products on older CPUs,
11
+ * - `f16` & `bf16` ↔ `f32` - often used for half-precision dot-products on older CPUs,
12
+ *
13
+ * Unlike most operation classes in NumKong, these are dependent on two input types: "from" & "to".
14
+ * It contains scalar helpers named like `nk_f16_to_f32_serial_` as well as buffer-to-buffer
15
+ * `memcpy`-like vectorized operations, such as `nk_cast_f16_to_f32` with `nk_cast_f16_to_f32_serial`,
16
+ * `nk_cast_f16_to_f32_neon`, `nk_cast_f16_to_f32_skylake`, and other platform-specific variants.
17
+ *
18
+ * It also includes "partial load" and "partial store" type-punned helper functions for handling
19
+ * IO between memory and registers, that are extensively reused in reductions, elementwise ops, and
20
+ * dot-products.
21
+ *
22
+ * Float-format narrowing uses round-to-nearest, ties-to-even. Float-to-integer narrowing follows
23
+ * the same tie rule, saturates infinities, and maps NaNs to zero.
24
+ *
25
+ * Assuming the overall breadth and sparsity of our type system, its clear, that not all type conversions
26
+ * have equivalent relevance. With ~16 numeric types we'd be looking at 21x21=441 conversions for:
27
+ *
28
+ * e4m3 e5m2 bf16 f16 f32 f64
29
+ * bf16c f16c f32c f64c
30
+ * i4 i8 i16 i32 i64
31
+ * u1 u4 u8 u16 u32 u64
32
+ *
33
+ * To simplify the design and make it more broadly applicable in AI workloads, we implement a slower
34
+ * @b "hub-and-spoke" design to guiding most conversions through an intermediate type, like `f64` or `i64`.
35
+ *
36
+ */
37
+ #ifndef NK_CAST_H
38
+ #define NK_CAST_H
39
+
40
+ #include "numkong/types.h"
41
+
42
+ #if defined(__cplusplus)
43
+ extern "C" {
44
+ #endif
45
+
46
+ /**
47
+ * @brief Elementwise type-casting for arrays of entries.
48
+ *
49
+ * @param[in] from The immutable input source array containing `n` elements of `from_type` type.
50
+ * @param[in] from_type The type of elements in the immutable source array.
51
+ * @param[in] n The number of elements in both input and output arrays.
52
+ * @param[in] to The mutable output array containing `n` elements of `to_type` type.
53
+ * @param[in] to_type The type of elements in the mutable target array.
54
+ */
55
+ NK_DYNAMIC void nk_cast(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
56
+
57
+ /** @copydoc nk_cast */
58
+ NK_PUBLIC void nk_cast_serial(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
59
+
60
+ /** @brief Scalar conversion from f16 to f32. */
61
+ NK_DYNAMIC void nk_f16_to_f32(nk_f16_t const *src, nk_f32_t *dest);
62
+ /** @brief Scalar conversion from bf16 to f32. */
63
+ NK_DYNAMIC void nk_bf16_to_f32(nk_bf16_t const *src, nk_f32_t *dest);
64
+ /** @brief Scalar conversion from e4m3 to f32. */
65
+ NK_DYNAMIC void nk_e4m3_to_f32(nk_e4m3_t const *src, nk_f32_t *dest);
66
+ /** @brief Scalar conversion from e5m2 to f32. */
67
+ NK_DYNAMIC void nk_e5m2_to_f32(nk_e5m2_t const *src, nk_f32_t *dest);
68
+ /** @brief Scalar conversion from e2m3 to f32. */
69
+ NK_DYNAMIC void nk_e2m3_to_f32(nk_e2m3_t const *src, nk_f32_t *dest);
70
+ /** @brief Scalar conversion from e3m2 to f32. */
71
+ NK_DYNAMIC void nk_e3m2_to_f32(nk_e3m2_t const *src, nk_f32_t *dest);
72
+
73
+ /** @brief Scalar conversion from f32 to f16. */
74
+ NK_DYNAMIC void nk_f32_to_f16(nk_f32_t const *src, nk_f16_t *dest);
75
+ /** @brief Scalar conversion from f32 to bf16. */
76
+ NK_DYNAMIC void nk_f32_to_bf16(nk_f32_t const *src, nk_bf16_t *dest);
77
+ /** @brief Scalar conversion from f32 to e4m3. */
78
+ NK_DYNAMIC void nk_f32_to_e4m3(nk_f32_t const *src, nk_e4m3_t *dest);
79
+ /** @brief Scalar conversion from f32 to e5m2. */
80
+ NK_DYNAMIC void nk_f32_to_e5m2(nk_f32_t const *src, nk_e5m2_t *dest);
81
+ /** @brief Scalar conversion from f32 to e2m3. */
82
+ NK_DYNAMIC void nk_f32_to_e2m3(nk_f32_t const *src, nk_e2m3_t *dest);
83
+ /** @brief Scalar conversion from f32 to e3m2. */
84
+ NK_DYNAMIC void nk_f32_to_e3m2(nk_f32_t const *src, nk_e3m2_t *dest);
85
+
86
+ /** @copydoc nk_f16_to_f32 */
87
+ NK_PUBLIC void nk_f16_to_f32_serial(nk_f16_t const *src, nk_f32_t *dest);
88
+ /** @copydoc nk_f32_to_f16 */
89
+ NK_PUBLIC void nk_f32_to_f16_serial(nk_f32_t const *src, nk_f16_t *dest);
90
+ /** @copydoc nk_bf16_to_f32 */
91
+ NK_PUBLIC void nk_bf16_to_f32_serial(nk_bf16_t const *src, nk_f32_t *dest);
92
+ /** @copydoc nk_f32_to_bf16 */
93
+ NK_PUBLIC void nk_f32_to_bf16_serial(nk_f32_t const *src, nk_bf16_t *dest);
94
+ /** @copydoc nk_e4m3_to_f32 */
95
+ NK_PUBLIC void nk_e4m3_to_f32_serial(nk_e4m3_t const *src, nk_f32_t *dest);
96
+ /** @copydoc nk_f32_to_e4m3 */
97
+ NK_PUBLIC void nk_f32_to_e4m3_serial(nk_f32_t const *src, nk_e4m3_t *dest);
98
+ /** @copydoc nk_e5m2_to_f32 */
99
+ NK_PUBLIC void nk_e5m2_to_f32_serial(nk_e5m2_t const *src, nk_f32_t *dest);
100
+ /** @copydoc nk_f32_to_e5m2 */
101
+ NK_PUBLIC void nk_f32_to_e5m2_serial(nk_f32_t const *src, nk_e5m2_t *dest);
102
+ /** @copydoc nk_e2m3_to_f32 */
103
+ NK_PUBLIC void nk_e2m3_to_f32_serial(nk_e2m3_t const *src, nk_f32_t *dest);
104
+ /** @copydoc nk_f32_to_e2m3 */
105
+ NK_PUBLIC void nk_f32_to_e2m3_serial(nk_f32_t const *src, nk_e2m3_t *dest);
106
+ /** @copydoc nk_e3m2_to_f32 */
107
+ NK_PUBLIC void nk_e3m2_to_f32_serial(nk_e3m2_t const *src, nk_f32_t *dest);
108
+ /** @copydoc nk_f32_to_e3m2 */
109
+ NK_PUBLIC void nk_f32_to_e3m2_serial(nk_f32_t const *src, nk_e3m2_t *dest);
110
+
111
+ #if NK_TARGET_NEON
112
+ /** @copydoc nk_cast */
113
+ NK_PUBLIC void nk_cast_neon(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
114
+ /** @copydoc nk_f16_to_f32 */
115
+ NK_PUBLIC void nk_f16_to_f32_neon(nk_f16_t const *src, nk_f32_t *dest);
116
+ /** @copydoc nk_f32_to_f16 */
117
+ NK_PUBLIC void nk_f32_to_f16_neon(nk_f32_t const *src, nk_f16_t *dest);
118
+ #endif // NK_TARGET_NEON
119
+
120
+ #if NK_TARGET_HASWELL
121
+ /** @copydoc nk_cast */
122
+ NK_PUBLIC void nk_cast_haswell(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
123
+ /** @copydoc nk_f16_to_f32 */
124
+ NK_PUBLIC void nk_f16_to_f32_haswell(nk_f16_t const *src, nk_f32_t *dest);
125
+ /** @copydoc nk_f32_to_f16 */
126
+ NK_PUBLIC void nk_f32_to_f16_haswell(nk_f32_t const *src, nk_f16_t *dest);
127
+ #endif // NK_TARGET_HASWELL
128
+
129
+ #if NK_TARGET_SKYLAKE
130
+ /** @copydoc nk_cast */
131
+ NK_PUBLIC void nk_cast_skylake(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
132
+ #endif // NK_TARGET_SKYLAKE
133
+
134
+ #if NK_TARGET_ICELAKE
135
+ /** @copydoc nk_cast */
136
+ NK_PUBLIC void nk_cast_icelake(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
137
+ #endif // NK_TARGET_ICELAKE
138
+
139
+ #if NK_TARGET_SAPPHIRE
140
+ /** @copydoc nk_cast */
141
+ NK_PUBLIC void nk_cast_sapphire(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
142
+ /** @copydoc nk_f16_to_f32 */
143
+ NK_PUBLIC void nk_f16_to_f32_sapphire(nk_f16_t const *src, nk_f32_t *dest);
144
+ /** @copydoc nk_f32_to_f16 */
145
+ NK_PUBLIC void nk_f32_to_f16_sapphire(nk_f32_t const *src, nk_f16_t *dest);
146
+ #endif // NK_TARGET_SAPPHIRE
147
+
148
+ #if NK_TARGET_RVV
149
+ /** @copydoc nk_cast */
150
+ NK_PUBLIC void nk_cast_rvv(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
151
+ #endif // NK_TARGET_RVV
152
+
153
+ #if NK_TARGET_POWERVSX
154
+ /** @copydoc nk_cast */
155
+ NK_PUBLIC void nk_cast_powervsx(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
156
+ /** @copydoc nk_f16_to_f32 */
157
+ NK_PUBLIC void nk_f16_to_f32_powervsx(nk_f16_t const *src, nk_f32_t *dest);
158
+ /** @copydoc nk_f32_to_f16 */
159
+ NK_PUBLIC void nk_f32_to_f16_powervsx(nk_f32_t const *src, nk_f16_t *dest);
160
+ #endif // NK_TARGET_POWERVSX
161
+
162
+ #if NK_TARGET_V128RELAXED
163
+ /** @copydoc nk_cast */
164
+ NK_PUBLIC void nk_cast_v128relaxed(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type);
165
+ #endif // NK_TARGET_V128RELAXED
166
+
167
+ #if defined(__cplusplus)
168
+ } // extern "C"
169
+ #endif
170
+
171
+ #include "numkong/cast/serial.h"
172
+ #include "numkong/cast/neon.h"
173
+ #include "numkong/cast/haswell.h"
174
+ #include "numkong/cast/skylake.h"
175
+ #include "numkong/cast/icelake.h"
176
+ #include "numkong/cast/sapphire.h"
177
+ #include "numkong/cast/rvv.h"
178
+ #include "numkong/cast/powervsx.h"
179
+ #include "numkong/cast/loongsonasx.h"
180
+
181
+ #if defined(__cplusplus)
182
+ extern "C" {
183
+ #endif
184
+
185
+ #if !NK_DYNAMIC_DISPATCH
186
+
187
+ NK_PUBLIC void nk_cast(void const *from, nk_dtype_t from_type, nk_size_t n, void *to, nk_dtype_t to_type) {
188
+ #if NK_TARGET_SAPPHIRE
189
+ nk_cast_sapphire(from, from_type, n, to, to_type);
190
+ #elif NK_TARGET_ICELAKE
191
+ nk_cast_icelake(from, from_type, n, to, to_type);
192
+ #elif NK_TARGET_SKYLAKE
193
+ nk_cast_skylake(from, from_type, n, to, to_type);
194
+ #elif NK_TARGET_HASWELL
195
+ nk_cast_haswell(from, from_type, n, to, to_type);
196
+ #elif NK_TARGET_POWERVSX
197
+ nk_cast_powervsx(from, from_type, n, to, to_type);
198
+ #elif NK_TARGET_RVV
199
+ nk_cast_rvv(from, from_type, n, to, to_type);
200
+ #elif NK_TARGET_NEON
201
+ nk_cast_neon(from, from_type, n, to, to_type);
202
+ #elif NK_TARGET_V128RELAXED
203
+ nk_cast_v128relaxed(from, from_type, n, to, to_type);
204
+ #else
205
+ nk_cast_serial(from, from_type, n, to, to_type);
206
+ #endif
207
+ }
208
+
209
+ NK_PUBLIC void nk_f16_to_f32(nk_f16_t const *src, nk_f32_t *dest) {
210
+ #if NK_TARGET_SAPPHIRE
211
+ nk_f16_to_f32_sapphire(src, dest);
212
+ #elif NK_TARGET_HASWELL
213
+ nk_f16_to_f32_haswell(src, dest);
214
+ #elif NK_TARGET_POWERVSX
215
+ nk_f16_to_f32_powervsx(src, dest);
216
+ #elif NK_TARGET_NEON
217
+ nk_f16_to_f32_neon(src, dest);
218
+ #else
219
+ nk_f16_to_f32_serial(src, dest);
220
+ #endif
221
+ }
222
+
223
+ NK_PUBLIC void nk_f32_to_f16(nk_f32_t const *src, nk_f16_t *dest) {
224
+ #if NK_TARGET_SAPPHIRE
225
+ nk_f32_to_f16_sapphire(src, dest);
226
+ #elif NK_TARGET_HASWELL
227
+ nk_f32_to_f16_haswell(src, dest);
228
+ #elif NK_TARGET_POWERVSX
229
+ nk_f32_to_f16_powervsx(src, dest);
230
+ #elif NK_TARGET_NEON
231
+ nk_f32_to_f16_neon(src, dest);
232
+ #else
233
+ nk_f32_to_f16_serial(src, dest);
234
+ #endif
235
+ }
236
+
237
+ NK_PUBLIC void nk_bf16_to_f32(nk_bf16_t const *src, nk_f32_t *dest) { nk_bf16_to_f32_serial(src, dest); }
238
+ NK_PUBLIC void nk_f32_to_bf16(nk_f32_t const *src, nk_bf16_t *dest) { nk_f32_to_bf16_serial(src, dest); }
239
+ NK_PUBLIC void nk_e4m3_to_f32(nk_e4m3_t const *src, nk_f32_t *dest) { nk_e4m3_to_f32_serial(src, dest); }
240
+ NK_PUBLIC void nk_f32_to_e4m3(nk_f32_t const *src, nk_e4m3_t *dest) { nk_f32_to_e4m3_serial(src, dest); }
241
+ NK_PUBLIC void nk_e5m2_to_f32(nk_e5m2_t const *src, nk_f32_t *dest) { nk_e5m2_to_f32_serial(src, dest); }
242
+ NK_PUBLIC void nk_f32_to_e5m2(nk_f32_t const *src, nk_e5m2_t *dest) { nk_f32_to_e5m2_serial(src, dest); }
243
+ NK_PUBLIC void nk_e2m3_to_f32(nk_e2m3_t const *src, nk_f32_t *dest) { nk_e2m3_to_f32_serial(src, dest); }
244
+ NK_PUBLIC void nk_f32_to_e2m3(nk_f32_t const *src, nk_e2m3_t *dest) { nk_f32_to_e2m3_serial(src, dest); }
245
+ NK_PUBLIC void nk_e3m2_to_f32(nk_e3m2_t const *src, nk_f32_t *dest) { nk_e3m2_to_f32_serial(src, dest); }
246
+ NK_PUBLIC void nk_f32_to_e3m2(nk_f32_t const *src, nk_e3m2_t *dest) { nk_f32_to_e3m2_serial(src, dest); }
247
+
248
+ #endif // !NK_DYNAMIC_DISPATCH
249
+
250
+ #if defined(__cplusplus)
251
+ } // extern "C"
252
+ #endif
253
+
254
+ #endif // NK_CAST_H
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @brief C++ wrappers for SIMD-accelerated type casting.
3
+ * @file include/numkong/cast.hpp
4
+ * @author Ash Vardanian
5
+ * @date March 20, 2026
6
+ */
7
+ #ifndef NK_CAST_HPP
8
+ #define NK_CAST_HPP
9
+
10
+ #include <cstddef> // `std::size_t`
11
+
12
+ #include "numkong/cast.h"
13
+
14
+ #include "numkong/types.hpp"
15
+ #include "numkong/vector.hpp"
16
+
17
+ namespace ashvardanian::numkong {
18
+
19
+ /**
20
+ * @brief Elementwise type-cast from one numeric type to another.
21
+ * @param[in] from Input array of `n` elements.
22
+ * @param[in] n Number of elements.
23
+ * @param[out] to Output array of `n` elements.
24
+ *
25
+ * @tparam from_type_ Source element type.
26
+ * @tparam to_type_ Destination element type.
27
+ * @tparam allow_simd_ Enable SIMD kernel dispatch when `prefer_simd_k`.
28
+ */
29
+ template <numeric_dtype from_type_, numeric_dtype to_type_, allow_simd_t allow_simd_ = prefer_simd_k>
30
+ void cast(from_type_ const *from, std::size_t n, to_type_ *to) noexcept {
31
+ if constexpr (allow_simd_ == prefer_simd_k) nk_cast(from, from_type_::dtype(), n, to, to_type_::dtype());
32
+ else nk_cast_serial(from, from_type_::dtype(), n, to, to_type_::dtype());
33
+ }
34
+
35
+ /** @brief Elementwise type-cast between vector views. Sizes must match. */
36
+ template <numeric_dtype from_type_, numeric_dtype to_type_, allow_simd_t allow_simd_ = prefer_simd_k>
37
+ void cast(vector_view<from_type_> from, vector_span<to_type_> to) noexcept {
38
+ std::size_t n = from.size() < to.size() ? from.size() : to.size();
39
+ cast<from_type_, to_type_, allow_simd_>(from.data(), n, to.data());
40
+ }
41
+
42
+ } // namespace ashvardanian::numkong
43
+
44
+ #endif // NK_CAST_HPP
@@ -0,0 +1,223 @@
1
+ # Curved Space Distances in NumKong
2
+
3
+ NumKong implements distance functions for curved metric spaces: bilinear forms compute $a^T C b$ for an arbitrary metric tensor $C$, while Mahalanobis distance generalizes Euclidean distance to account for correlations between dimensions.
4
+ Complex bilinear forms extend this to Hermitian inner products.
5
+ These operations are central to Gaussian process inference, metric learning, and statistical distance measures.
6
+
7
+ The bilinear form for real vectors is:
8
+
9
+ $$
10
+ \text{bilinear}(a, b, C) = a^T C b = \sum_{i=0}^{n-1} \sum_{j=0}^{n-1} a_i \cdot c_{ij} \cdot b_j
11
+ $$
12
+
13
+ The Mahalanobis distance is:
14
+
15
+ $$
16
+ \text{mahalanobis}(a, b, C) = \sqrt{(a - b)^T C (a - b)}
17
+ $$
18
+
19
+ For complex vectors, the bilinear form uses the conjugate transpose:
20
+
21
+ $$
22
+ \text{bilinear}(a, b, C) = a^H C b = \sum_{i=0}^{n-1} \sum_{j=0}^{n-1} \bar{a_i} \cdot c_{ij} \cdot b_j
23
+ $$
24
+
25
+ Reformulating as Python pseudocode:
26
+
27
+ ```python
28
+ import numpy as np
29
+
30
+ def bilinear(a: np.ndarray, b: np.ndarray, C: np.ndarray) -> float:
31
+ return a @ C @ b
32
+
33
+ def mahalanobis(a: np.ndarray, b: np.ndarray, C: np.ndarray) -> float:
34
+ diff = a - b
35
+ return np.sqrt(diff @ C @ diff)
36
+
37
+ def bilinear_complex(a: np.ndarray, b: np.ndarray, C: np.ndarray) -> complex:
38
+ return np.conj(a) @ C @ b
39
+ ```
40
+
41
+ ## Input & Output Types
42
+
43
+ Real bilinear and Mahalanobis:
44
+
45
+ | Input Type | Output Type | Description |
46
+ | ---------- | ----------- | ---------------------------------------------- |
47
+ | `f64` | `f64` | 64-bit IEEE 754 double precision |
48
+ | `f32` | `f32` | 32-bit IEEE 754 single precision |
49
+ | `f16` | `f32` | 16-bit IEEE 754 half precision, widened output |
50
+ | `bf16` | `f32` | 16-bit brain float, widened output |
51
+
52
+ Complex bilinear:
53
+
54
+ | Input Type | Output Type | Description |
55
+ | ---------- | ----------- | ------------------------------------------ |
56
+ | `f64c` | `f64c` | 64-bit complex pairs |
57
+ | `f32c` | `f32c` | 32-bit complex pairs |
58
+ | `f16c` | `f32c` | 16-bit complex pairs, widened output |
59
+ | `bf16c` | `f32c` | 16-bit brain complex pairs, widened output |
60
+
61
+ ## Optimizations
62
+
63
+ ### Row-Major Streaming with Nested Dot2
64
+
65
+ `nk_bilinear_f64_skylake`, `nk_mahalanobis_f64_skylake` decompose the bilinear form $a^T C b$ as $\sum_i a_i \cdot \text{dot}(C_i, b)$ where $C_i$ is the $i$-th row of the metric tensor.
66
+ Each inner dot product uses Dot2 compensation — TwoProd via FMA captures the rounding error of each $c_{ij} \cdot b_j$ product exactly, and a TwoSum chain propagates it through the accumulator.
67
+ The outer sum over rows uses a second level of compensation, tracking the rounding error of each $a_i \cdot r_i$ accumulation.
68
+ This nested structure gives $O(n)$ cache-friendly sequential access to the $n \times n$ matrix $C$, since each row is read once and discarded.
69
+ `nk_bilinear_f32_neon`, `nk_bilinear_f32_skylake`, `nk_mahalanobis_f32_neon`, `nk_mahalanobis_f32_skylake` use the same row-major streaming pattern but accumulate in `f64` instead of Dot2, which provides sufficient precision for `f32` inputs.
70
+
71
+ ### SME Outer-Product Accumulation
72
+
73
+ `nk_bilinear_f32_smef64`, `nk_bilinear_f64_smef64`, `nk_bilinear_f32c_smef64`, `nk_bilinear_f64c_smef64`, `nk_mahalanobis_f32_smef64`, `nk_mahalanobis_f64_smef64` use the Scalable Matrix Extension to compute the bilinear form as an outer-product accumulation.
74
+ Each `FMOPA` instruction performs a rank-1 update $a_i \cdot b^T$ into the SME ZA tile array, and the matrix $C$ is streamed row-by-row and multiplied into the accumulator.
75
+ This differs from the row-major dot approach — it reformulates $a^T C b$ as a matrix-multiply problem where SME's 2D tile registers use the matrix engine's throughput.
76
+ For dimensions that align to the tile size, this approach has high throughput; dimensions that do not align fall back to NEON for cleanup of the residual elements.
77
+
78
+ ### Complex Bilinear Decomposition
79
+
80
+ `nk_bilinear_f32c_neon`, `nk_bilinear_f32c_skylake`, `nk_bilinear_f64c_skylake` compute $a^H C b$ where each element involves 4 real multiplications from the complex product $\bar{a_i} \cdot c_{ij} \cdot b_j$.
81
+ The kernel decomposes this into real and imaginary dot products over rows of $C$: for each row $i$, it computes the real part as $a_{i,re} \cdot \text{dot}(C_i, b)_{re} + a_{i,im} \cdot \text{dot}(C_i, b)_{im}$ and the imaginary part with the conjugation baked in as sign flips.
82
+ This fuses the conjugation of $a$ into the sign of the cross terms rather than explicitly negating the imaginary components, saving one negate operation per element.
83
+
84
+ ## Performance
85
+
86
+ The following performance tables are produced by manually re-running `nk_test` and `nk_bench` included internal tools to measure both accuracy and throughput at different input shapes.
87
+ The input size is controlled by the `NK_CURVED_DIMENSIONS` environment variable.
88
+ The metric tensor is a square matrix of side $N$, so each bilinear form $\mathbf{x}^\top M \mathbf{x}$ has $O(N^2)$ arithmetic complexity.
89
+ Columns show matrix side length: 256², 1024², 4096².
90
+ The throughput is measured in GSO/s as Giga Scalar Operations per Second.
91
+ Accuracy is reported as mean ULP (units in last place) averaged over all test pairs — the average number of representable floating-point values between the computed result and the exact answer.
92
+ Each kernel runs for at least 20 seconds per configuration.
93
+ Benchmark threads are pinned to specific cores; on machines with heterogeneous core types (e.g., Apple P/E cores), only the fastest cores are used.
94
+ Workloads that significantly degrade CPU frequencies (Intel AMX, Apple SME) run in separate passes to avoid affecting throughput measurements of other kernels.
95
+ Rows marked `🧩` use external BLAS baselines rather than NumKong kernels.
96
+
97
+ ### Intel Sapphire Rapids
98
+
99
+ #### Native
100
+
101
+ | Kernel | 256² | 1024² | 4096² |
102
+ | :---------------------------- | -----------------------: | -----------------------: | -----------------------: |
103
+ | __f64c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
104
+ | `bilinear_f64c_with_blas` 🧩 | 1.25 gso/s | 1.36 gso/s | 1.38 gso/s |
105
+ | `nk_bilinear_f64c_serial` | 0.0862 gso/s, 0.5 ulp | 0.161 gso/s, 0.2 ulp | 0.171 gso/s, 0.5 ulp |
106
+ | `nk_bilinear_f64c_skylake` | 0.583 gso/s, 3.5 ulp | 0.718 gso/s, 3.5 ulp | 0.765 gso/s, 3.5 ulp |
107
+ | __f32c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
108
+ | `bilinear_f32c_with_blas` 🧩 | 2.14 gso/s | 2.61 gso/s | 2.57 gso/s |
109
+ | `nk_bilinear_f32c_serial` | 0.756 gso/s, 0 ulp | 1.37 gso/s, 0 ulp | 1.37 gso/s, 0 ulp |
110
+ | `nk_bilinear_f32c_skylake` | 1.72 gso/s, 0 ulp | 1.75 gso/s, 0 ulp | 1.46 gso/s, 0 ulp |
111
+ | __bf16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
112
+ | `nk_bilinear_bf16c_serial` | 0.154 gso/s, 5 ulp | 0.158 gso/s, 5.8 ulp | 0.155 gso/s, 5 ulp |
113
+ | `nk_bilinear_bf16c_genoa` | 2.81 gso/s, 5 ulp | 4.57 gso/s, 5 ulp | 4.47 gso/s, 5 ulp |
114
+ | __f16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
115
+ | `nk_bilinear_f16c_serial` | 0.585 gso/s, 7.2 ulp | 0.592 gso/s, 7.2 ulp | 0.600 gso/s, 7.2 ulp |
116
+ | __f64__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
117
+ | `bilinear_f64_with_blas` 🧩 | 2.84 gso/s | 3.23 gso/s | 3.14 gso/s |
118
+ | `nk_bilinear_f64_serial` | 0.291 gso/s, 0.7 ulp | 0.565 gso/s, 0.4 ulp | 0.577 gso/s, 0.7 ulp |
119
+ | `nk_mahalanobis_f64_serial` | 0.267 gso/s, 0 ulp | 0.537 gso/s, 0 ulp | 0.539 gso/s, 0 ulp |
120
+ | `nk_bilinear_f64_skylake` | 1.79 gso/s, 1.6 ulp | 1.71 gso/s, 1.3 ulp | 1.59 gso/s, 1 ulp |
121
+ | `nk_mahalanobis_f64_skylake` | 1.77 gso/s, 0 ulp | 1.82 gso/s, 0 ulp | 2.12 gso/s, 0.2 ulp |
122
+ | __f32__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
123
+ | `bilinear_f32_with_blas` 🧩 | 4.09 gso/s | 5.61 gso/s | 6.59 gso/s |
124
+ | `nk_bilinear_f32_serial` | 1.19 gso/s, 0 ulp | 2.71 gso/s, 0 ulp | 2.68 gso/s, 0 ulp |
125
+ | `nk_mahalanobis_f32_serial` | 2.36 gso/s, 0 ulp | 2.53 gso/s, 0 ulp | 2.40 gso/s, 0 ulp |
126
+ | `nk_bilinear_f32_haswell` | 3.45 gso/s, 0 ulp | 3.66 gso/s, 0 ulp | 3.24 gso/s, 0 ulp |
127
+ | `nk_mahalanobis_f32_haswell` | 3.37 gso/s, 0 ulp | 3.28 gso/s, 0 ulp | 3.30 gso/s, 0 ulp |
128
+ | `nk_bilinear_f32_skylake` | 3.68 gso/s, 0 ulp | 3.08 gso/s, 0 ulp | 2.71 gso/s, 0 ulp |
129
+ | `nk_mahalanobis_f32_skylake` | 3.45 gso/s, 0 ulp | 2.94 gso/s, 0 ulp | 3.32 gso/s, 0 ulp |
130
+ | __bf16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
131
+ | `nk_bilinear_bf16_serial` | 0.321 gso/s, 16 ulp | 0.331 gso/s, 13 ulp | 0.314 gso/s, 12 ulp |
132
+ | `nk_mahalanobis_bf16_serial` | 0.216 gso/s, 2.2 ulp | 0.215 gso/s, 2.1 ulp | 0.211 gso/s, 2.3 ulp |
133
+ | `nk_bilinear_bf16_haswell` | 6.75 gso/s, 11 ulp | 7.04 gso/s, 13 ulp | 6.80 gso/s, 13 ulp |
134
+ | `nk_mahalanobis_bf16_haswell` | 5.93 gso/s, 1 ulp | 5.77 gso/s, 1 ulp | 5.86 gso/s, 1 ulp |
135
+ | `nk_bilinear_bf16_genoa` | 6.22 gso/s, 18 ulp | 10.9 gso/s, 18 ulp | 10.3 gso/s, 18 ulp |
136
+ | `nk_mahalanobis_bf16_genoa` | 7.04 gso/s, 8.55K ulp | 8.76 gso/s, 8.41K ulp | 8.57 gso/s, 8.41K ulp |
137
+ | __f16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
138
+ | `nk_bilinear_f16_serial` | 0.654 gso/s, 23 ulp | 0.652 gso/s, 23 ulp | 0.657 gso/s, 23 ulp |
139
+ | `nk_mahalanobis_f16_serial` | 0.510 gso/s, 2.7 ulp | 0.520 gso/s, 3.2 ulp | 0.500 gso/s, 2.7 ulp |
140
+ | `nk_bilinear_f16_haswell` | 7.36 gso/s, 37 ulp | 7.30 gso/s, 37 ulp | 7.29 gso/s, 37 ulp |
141
+ | `nk_mahalanobis_f16_haswell` | 6.75 gso/s, 1 ulp | 6.24 gso/s, 1 ulp | 6.83 gso/s, 1 ulp |
142
+
143
+ #### WASM
144
+
145
+ Measured with Wasmtime v42 (Cranelift backend).
146
+
147
+ | Kernel | 256² | 1024² | 4096² |
148
+ | :------------------------- | -----------------------: | -----------------------: | -----------------------: |
149
+ | __f64c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
150
+ | `nk_bilinear_f64c_serial` | 0.21 gso/s, 1.2 ulp | 0.21 gso/s, 1.2 ulp | 0.21 gso/s, 1.2 ulp |
151
+ | __f32c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
152
+ | `nk_bilinear_f32c_serial` | 1.10 gso/s, 0 ulp | 1.07 gso/s, 0 ulp | 1.10 gso/s, 0 ulp |
153
+ | __bf16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
154
+ | `nk_bilinear_bf16c_serial` | 1.26 gso/s, 9.8 ulp | 1.31 gso/s, 9.8 ulp | 1.27 gso/s, 9.5 ulp |
155
+ | __f16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
156
+ | `nk_bilinear_f16c_serial` | 0.40 gso/s, 39 ulp | 0.38 gso/s, 39 ulp | 0.40 gso/s, 39 ulp |
157
+ | __f64__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
158
+ | `nk_bilinear_f64_serial` | 0.49 gso/s, 0.6 ulp | 0.49 gso/s, 0.6 ulp | 0.48 gso/s, 0.6 ulp |
159
+ | __f32__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
160
+ | `nk_bilinear_f32_serial` | 2.54 gso/s, 0 ulp | 2.62 gso/s, 0 ulp | 2.53 gso/s, 0 ulp |
161
+ | __bf16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
162
+ | `nk_bilinear_bf16_serial` | 2.91 gso/s, 27 ulp | 2.90 gso/s, 22 ulp | 2.98 gso/s, 22 ulp |
163
+ | __f16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
164
+ | `nk_bilinear_f16_serial` | 0.76 gso/s, 74 ulp | 0.76 gso/s, 74 ulp | 0.78 gso/s, 74 ulp |
165
+
166
+ ### Apple M4
167
+
168
+ #### Native
169
+
170
+ | Kernel | 256² | 1024² | 4096² |
171
+ | :------------------------------ | -----------------------: | -----------------------: | -----------------------: |
172
+ | __f64c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
173
+ | `nk_bilinear_f64c_serial` | 0.368 gso/s, 2.2 ulp | 0.371 gso/s, 2.2 ulp | 0.367 gso/s, 2.2 ulp |
174
+ | __f32c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
175
+ | `nk_bilinear_f32c_serial` | 2.33 gso/s, 0 ulp | 2.27 gso/s, 0 ulp | 2.28 gso/s, 0 ulp |
176
+ | `nk_bilinear_f32c_neon` | 2.11 gso/s, 0 ulp | 1.89 gso/s, 0 ulp | 1.85 gso/s, 0 ulp |
177
+ | __bf16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
178
+ | `nk_bilinear_bf16c_serial` | 2.83 gso/s, 33.0 ulp | 2.54 gso/s, 34.5 ulp | 2.49 gso/s, 34.5 ulp |
179
+ | `nk_bilinear_bf16c_neonbfdot` | 5.05 gso/s, 17.0 ulp | 4.20 gso/s, 17.0 ulp | 4.04 gso/s, 17.0 ulp |
180
+ | __f16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
181
+ | `nk_bilinear_f16c_serial` | 2.81 gso/s, 51.8 ulp | 2.54 gso/s, 51.8 ulp | 2.48 gso/s, 51.8 ulp |
182
+ | `nk_bilinear_f16c_neonhalf` | 5.00 gso/s, 17.3 ulp | 4.16 gso/s, 17.3 ulp | 4.00 gso/s, 16.4 ulp |
183
+ | __f64__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
184
+ | `nk_bilinear_f64_serial` | 0.717 gso/s, 0.4 ulp | 0.711 gso/s, 0.4 ulp | 0.721 gso/s, 0.4 ulp |
185
+ | `nk_mahalanobis_f64_serial` | 0.664 gso/s, 0.5 ulp | 0.667 gso/s, 0.5 ulp | 0.672 gso/s, 0.5 ulp |
186
+ | __f32__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
187
+ | `nk_bilinear_f32_serial` | 3.92 gso/s, 0 ulp | 3.05 gso/s, 0 ulp | 2.87 gso/s, 0 ulp |
188
+ | `nk_mahalanobis_f32_serial` | 3.42 gso/s, 0 ulp | 2.88 gso/s, 0 ulp | 2.74 gso/s, 0 ulp |
189
+ | `nk_bilinear_f32_neon` | 4.90 gso/s, 0 ulp | 3.82 gso/s, 0 ulp | 3.49 gso/s, 0 ulp |
190
+ | `nk_mahalanobis_f32_neon` | 4.68 gso/s, 0 ulp | 3.71 gso/s, 0 ulp | 3.48 gso/s, 0 ulp |
191
+ | __bf16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
192
+ | `nk_bilinear_bf16_serial` | 4.17 gso/s, 20.7 ulp | 3.19 gso/s, 21.2 ulp | 2.94 gso/s, 20.7 ulp |
193
+ | `nk_mahalanobis_bf16_serial` | 3.86 gso/s, 2.1 ulp | 2.98 gso/s, 2.2 ulp | 2.79 gso/s, 2.1 ulp |
194
+ | `nk_bilinear_bf16_neonbfdot` | 28.0 gso/s, 28.0 ulp | 23.5 gso/s, 41.2 ulp | 20.4 gso/s, 41.1 ulp |
195
+ | `nk_mahalanobis_bf16_neonbfdot` | 9.14 gso/s, 2.2 ulp | 7.93 gso/s, 2.2 ulp | 7.43 gso/s, 2.2 ulp |
196
+ | __f16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
197
+ | `nk_bilinear_f16_serial` | ? gso/s, ? ulp | ? gso/s, ? ulp | ? gso/s, ? ulp |
198
+ | `nk_mahalanobis_f16_serial` | ? gso/s, ? ulp | ? gso/s, ? ulp | ? gso/s, ? ulp |
199
+ | `nk_bilinear_f16_neonhalf` | ? gso/s, ? ulp | ? gso/s, ? ulp | ? gso/s, ? ulp |
200
+ | `nk_mahalanobis_f16_neonhalf` | ? gso/s, ? ulp | ? gso/s, ? ulp | ? gso/s, ? ulp |
201
+
202
+ #### WASM
203
+
204
+ Measured with Wasmtime v43 (Cranelift backend).
205
+
206
+ | Kernel | 256² | 1024² | 4096² |
207
+ | :------------------------- | -----------------------: | -----------------------: | -----------------------: |
208
+ | __f64c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
209
+ | `nk_bilinear_f64c_serial` | 0.445 gso/s, ? ulp | 0.445 gso/s, ? ulp | 0.445 gso/s, ? ulp |
210
+ | __f32c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
211
+ | `nk_bilinear_f32c_serial` | 2.83 gso/s, ? ulp | 2.83 gso/s, ? ulp | 2.84 gso/s, ? ulp |
212
+ | __bf16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
213
+ | `nk_bilinear_bf16c_serial` | 3.05 gso/s, ? ulp | 3.02 gso/s, ? ulp | 3.03 gso/s, ? ulp |
214
+ | __f16c__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
215
+ | `nk_bilinear_f16c_serial` | 0.984 gso/s, ? ulp | 0.992 gso/s, ? ulp | 0.995 gso/s, ? ulp |
216
+ | __f64__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
217
+ | `nk_bilinear_f64_serial` | 0.998 gso/s, ? ulp | 0.999 gso/s, ? ulp | 0.999 gso/s, ? ulp |
218
+ | __f32__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
219
+ | `nk_bilinear_f32_serial` | 5.00 gso/s, ? ulp | 3.73 gso/s, ? ulp | 3.49 gso/s, ? ulp |
220
+ | __bf16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
221
+ | `nk_bilinear_bf16_serial` | 4.84 gso/s, ? ulp | 3.83 gso/s, ? ulp | 3.60 gso/s, ? ulp |
222
+ | __f16__ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ | ░░░░░░░░░░░░░░░░░░░░░░░░ |
223
+ | `nk_bilinear_f16_serial` | 1.90 gso/s, ? ulp | 1.75 gso/s, ? ulp | 1.93 gso/s, ? ulp |