usearch 2.21.3 → 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 +235 -52
  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,580 @@
1
+ /**
2
+ * @brief C++ test suite with precision analysis using double-double arithmetic.
3
+ * @file test/test.hpp
4
+ * @author Ash Vardanian
5
+ * @date December 28, 2025
6
+ *
7
+ * This test suite compares NumKong operations against high-precision references,
8
+ * like our `f118_t` double-double type, and reports ULP, absolute, and relative error statistics.
9
+ *
10
+ * Environment Variables:
11
+ * NK_FILTER=<pattern> - Filter tests by name RegEx (default: run all)
12
+ * NK_SEED=N - RNG seed (default: 42)
13
+ *
14
+ * NK_DENSE_DIMENSIONS=N - Vector dimension for dot/spatial tests (default: 1536)
15
+ * NK_CURVED_DIMENSIONS=N - Vector dimension for curved tests (default: 64)
16
+ * NK_SPARSE_DIMENSIONS=N - Vector dimension for sparse tests (default: 256)
17
+ * NK_MESH_POINTS=N - Point count for mesh tests (default: 1000)
18
+ * NK_MATRIX_HEIGHT=N - GEMM M dimension (default: 1024)
19
+ * NK_MATRIX_WIDTH=N - GEMM N dimension (default: 128)
20
+ * NK_MATRIX_DEPTH=N - GEMM K dimension (default: 1536)
21
+ *
22
+ * NK_IN_QEMU - Set when running under QEMU (relaxes accuracy thresholds)
23
+ * NK_TEST_ASSERT=1 - Assert on failed accuracy checks (default: 0)
24
+ * NK_TEST_VERBOSE=1 - Show per-dimension ULP breakdown (default: 0)
25
+ * NK_ULP_THRESHOLD_F32=N - Max allowed ULP for f32 (default: 4)
26
+ * NK_ULP_THRESHOLD_F16=N - Max allowed ULP for f16 (default: 32)
27
+ * NK_ULP_THRESHOLD_BF16=N - Max allowed ULP for bf16 (default: 256)
28
+ * NK_BUDGET_SECS=<seconds> - Time budget per kernel in seconds (default: 1)
29
+ * NK_RANDOM_DISTRIBUTION=<type> - Random distribution: uniform_k|lognormal_k|cauchy_k (default: lognormal_k)
30
+ */
31
+
32
+ #pragma once
33
+ #ifndef NK_TEST_HPP
34
+ #define NK_TEST_HPP
35
+
36
+ #include <cmath> // `std::fabs`, `std::isnan`, `std::isinf`
37
+ #include <cstdint> // `std::uint64_t`, `std::int32_t`, `std::int64_t`
38
+ #include <cstdio> // `std::printf`, `std::fflush`
39
+ #include <cstdlib> // `std::abort`
40
+ #include <cstring> // `std::memcpy`, `std::strstr`
41
+
42
+ #include <algorithm> // `std::min`, `std::max`
43
+ #include <array> // `std::array`
44
+ #include <cassert> // `assert`
45
+ #include <chrono> // `std::chrono::steady_clock`, `std::chrono::duration_cast`
46
+ #include <complex> // `std::complex`
47
+ #include <limits> // `std::numeric_limits`
48
+ #include <new> // `std::bad_alloc`
49
+ #include <optional> // `std::optional`
50
+
51
+ #if NK_TEST_USE_OPENMP
52
+ #include <omp.h>
53
+ #endif
54
+
55
+ #ifndef NK_ALLOW_ISA_REDIRECT
56
+ #define NK_ALLOW_ISA_REDIRECT 0
57
+ #endif
58
+
59
+ // Optional BLAS/MKL integration for precision comparison
60
+ #ifndef NK_COMPARE_TO_BLAS
61
+ #define NK_COMPARE_TO_BLAS 0
62
+ #endif
63
+ #ifndef NK_COMPARE_TO_MKL
64
+ #define NK_COMPARE_TO_MKL 0
65
+ #endif
66
+ #ifndef NK_COMPARE_TO_ACCELERATE
67
+ #define NK_COMPARE_TO_ACCELERATE 0
68
+ #endif
69
+
70
+ // Include reference library headers - MKL, Accelerate, or generic CBLAS
71
+ #if NK_COMPARE_TO_MKL
72
+ #include <mkl.h> // MKL includes its own CBLAS interface
73
+ #elif NK_COMPARE_TO_ACCELERATE
74
+ #include <Accelerate/Accelerate.h> // Apple Accelerate framework
75
+ #elif NK_COMPARE_TO_BLAS
76
+ #include <cblas.h> // Generic CBLAS (OpenBLAS, etc.)
77
+ #endif
78
+
79
+ // Intests we want to make sure our custom floating-point routines are used instead of
80
+ // compiler-provided native types.
81
+ #undef NK_NATIVE_F16
82
+ #define NK_NATIVE_F16 0
83
+ #undef NK_NATIVE_BF16
84
+ #define NK_NATIVE_BF16 0
85
+
86
+ #include "numkong/types.hpp"
87
+ #include "numkong/tensor.hpp"
88
+ #include "numkong/dots.hpp"
89
+ #include "numkong/maxsim.hpp"
90
+ #include "numkong/matrix.hpp"
91
+ #include "numkong/reduce.hpp"
92
+ #include "numkong/each.hpp"
93
+ #include "numkong/trigonometry.hpp"
94
+ #include "numkong/spatials.hpp"
95
+ #include "numkong/random.hpp" // `nk::fill_uniform`
96
+
97
+ namespace nk = ashvardanian::numkong;
98
+
99
+ using nk::bf16_t;
100
+ using nk::bf16c_t;
101
+ using nk::e2m3_t;
102
+ using nk::e3m2_t;
103
+ using nk::e4m3_t;
104
+ using nk::e5m2_t;
105
+ using nk::f118_t;
106
+ using nk::f118c_t;
107
+ using nk::f16_t;
108
+ using nk::f16c_t;
109
+ using nk::f32_t;
110
+ using nk::f32c_t;
111
+ using nk::f64_t;
112
+ using nk::f64c_t;
113
+ using nk::i16_t;
114
+ using nk::i32_t;
115
+ using nk::i4x2_t;
116
+ using nk::i64_t;
117
+ using nk::i8_t;
118
+ using nk::u16_t;
119
+ using nk::u1x8_t;
120
+ using nk::u32_t;
121
+ using nk::u4x2_t;
122
+ using nk::u64_t;
123
+ using nk::u8_t;
124
+
125
+ using steady_clock = std::chrono::steady_clock;
126
+ using time_point = steady_clock::time_point;
127
+
128
+ /**
129
+ * @brief Maps scalar types to appropriate reference types for ULP testing.
130
+ *
131
+ * Two template parameters: input type and result type (defaulting to input).
132
+ * - f32/f64 input → f118_t (need full double-double precision)
133
+ * - Complex f32c/f64c input → f118c_t
134
+ * - Smaller complex (f16c, bf16c) → f64c_t (52-bit mantissa >> 7-10 bit mantissa)
135
+ * - Everything else (integers, bf16, f16, etc.) → f64_t
136
+ */
137
+ template <typename input_type_, typename result_type_ = input_type_>
138
+ using reference_for = std::conditional_t<
139
+ std::is_same_v<input_type_, f32_t> || std::is_same_v<input_type_, f64_t>, f118_t,
140
+ std::conditional_t<
141
+ nk::is_complex_dtype<input_type_>(),
142
+ std::conditional_t<std::is_same_v<input_type_, f32c_t> || std::is_same_v<input_type_, f64c_t>, f118c_t, f64c_t>,
143
+ f64_t>>;
144
+
145
+ template class nk::vector<int>;
146
+ template class nk::vector<nk::i32_t>;
147
+ template class nk::vector<nk::u1x8_t>;
148
+ template class nk::vector<nk::i4x2_t>;
149
+ template class nk::vector<nk::f64c_t>;
150
+ template class nk::vector<std::complex<float>>;
151
+
152
+ enum class random_distribution_kind_t { uniform_k, lognormal_k, cauchy_k };
153
+ enum class comparison_family_t {
154
+ exact_k,
155
+ narrow_arithmetic_k,
156
+ mixed_precision_reduction_k,
157
+ probability_k,
158
+ geospatial_k,
159
+ external_baseline_k,
160
+ };
161
+ enum class comparison_failure_mode_t { exact_distance_k, ulp_threshold_k };
162
+
163
+ struct comparison_family_spec_t {
164
+ comparison_failure_mode_t failure_mode;
165
+ std::array<char const *, 5> column_labels;
166
+ };
167
+
168
+ inline constexpr comparison_family_spec_t comparison_family_spec(comparison_family_t family) noexcept {
169
+ switch (family) {
170
+ case comparison_family_t::exact_k:
171
+ return {comparison_failure_mode_t::exact_distance_k, {"max_dist", "mean_dist", "max_abs", "mismatch", "exact"}};
172
+ case comparison_family_t::probability_k:
173
+ return {comparison_failure_mode_t::ulp_threshold_k, {"max_abs", "mean_abs", "max_rel", "mean_rel", "mean_ulp"}};
174
+ case comparison_family_t::geospatial_k:
175
+ return {comparison_failure_mode_t::ulp_threshold_k, {"max_abs", "mean_abs", "max_rel", "mean_ulp", "max_ulp"}};
176
+ case comparison_family_t::narrow_arithmetic_k:
177
+ case comparison_family_t::mixed_precision_reduction_k:
178
+ case comparison_family_t::external_baseline_k:
179
+ return {comparison_failure_mode_t::ulp_threshold_k, {"max_abs", "max_rel", "mean_ulp", "max_ulp", "exact"}};
180
+ }
181
+ return {comparison_failure_mode_t::ulp_threshold_k, {"max_abs", "max_rel", "mean_ulp", "max_ulp", "exact"}};
182
+ }
183
+
184
+ struct test_config_t {
185
+ /** Assert on failed accuracy checks. Override: `NK_TEST_ASSERT=1`. */
186
+ bool assert_on_failure = false;
187
+ /** Show per-dimension ULP breakdown. Override: `NK_TEST_VERBOSE=1`. */
188
+ bool verbose = false;
189
+ /** Relaxed accuracy for emulated SIMD. Override: `NK_IN_QEMU`. */
190
+ bool running_in_qemu = false;
191
+ /** Max allowed ULP for f32. Override: `NK_ULP_THRESHOLD_F32`. */
192
+ std::uint64_t ulp_threshold_f32 = 4;
193
+ /** Max allowed ULP for f16. Override: `NK_ULP_THRESHOLD_F16`. */
194
+ std::uint64_t ulp_threshold_f16 = 32;
195
+ /** Max allowed ULP for bf16. Override: `NK_ULP_THRESHOLD_BF16`. */
196
+ std::uint64_t ulp_threshold_bf16 = 256;
197
+ /** Time budget per kernel in milliseconds. Override: `NK_BUDGET_SECS`. */
198
+ std::size_t time_budget_ms = 1000;
199
+ /** Random seed for reproducible tests. Override: `NK_SEED`. */
200
+ std::uint32_t seed = 42;
201
+ /** Filter tests by name (regex or substring). Override: `NK_FILTER`. */
202
+ char const *filter = nullptr;
203
+ /** Random distribution for test inputs. Override: `NK_RANDOM_DISTRIBUTION`. */
204
+ random_distribution_kind_t distribution = random_distribution_kind_t::lognormal_k;
205
+
206
+ /** For dot products, spatial metrics. Override: `NK_DENSE_DIMENSIONS`. */
207
+ std::size_t dense_dimensions = 1536;
208
+ /** For curved metrics (quadratic in dims). Override: `NK_CURVED_DIMENSIONS`. */
209
+ std::size_t curved_dimensions = 64;
210
+ /** For sparse set intersection and sparse dot. Override: `NK_SPARSE_DIMENSIONS`. */
211
+ std::size_t sparse_dimensions = 256;
212
+ /** Number of 3D points for RMSD, Kabsch. Override: `NK_MESH_POINTS`. */
213
+ std::size_t mesh_points = 1000;
214
+ /** GEMM M dimension. Override: `NK_MATRIX_HEIGHT`. */
215
+ std::size_t matrix_height = 1024;
216
+ /** GEMM N dimension. Override: `NK_MATRIX_WIDTH`. */
217
+ std::size_t matrix_width = 128;
218
+ /** GEMM K dimension. Override: `NK_MATRIX_DEPTH`. */
219
+ std::size_t matrix_depth = 1536;
220
+ /** Max angular separation in degrees for geospatial tests. Override: `NK_MAX_COORD_ANGLE`. */
221
+ float max_coord_angle = 180.0f;
222
+ /** Count of kernels that failed the configured accuracy checks. */
223
+ std::size_t failure_count = 0;
224
+
225
+ bool should_run(char const *test_name) const;
226
+
227
+ std::uint64_t ulp_threshold_for(char const *kernel_name) const noexcept {
228
+ if (std::strstr(kernel_name, "_bf16")) return ulp_threshold_bf16;
229
+ if (std::strstr(kernel_name, "_f16")) return ulp_threshold_f16;
230
+ return ulp_threshold_f32;
231
+ }
232
+
233
+ char const *distribution_name() const noexcept {
234
+ switch (distribution) {
235
+ case random_distribution_kind_t::uniform_k: return "uniform";
236
+ case random_distribution_kind_t::lognormal_k: return "lognormal";
237
+ case random_distribution_kind_t::cauchy_k: return "cauchy";
238
+ default: return "unknown";
239
+ }
240
+ }
241
+ };
242
+
243
+ extern test_config_t global_config;
244
+ void print_stats_header(comparison_family_t family) noexcept;
245
+ struct error_stats_t;
246
+ bool should_fail(char const *kernel_name, error_stats_t const &stats) noexcept;
247
+ void print_stats_row(char const *kernel_name, error_stats_t const &stats) noexcept;
248
+
249
+ /**
250
+ * @brief Tracks the currently-running kernel name for SIGILL diagnostics.
251
+ * Set before each kernel call, cleared after. A signal handler installed in
252
+ * main() reads this to log the culprit before the process exits.
253
+ */
254
+ inline char const *volatile nk_test_current_kernel_ = nullptr;
255
+
256
+ struct error_stats_section_t {
257
+ char const *title = nullptr;
258
+ bool emitted_any = false;
259
+ std::optional<comparison_family_t> last_family;
260
+
261
+ explicit error_stats_section_t(char const *title = nullptr) noexcept : title(title) {}
262
+ ~error_stats_section_t() = default;
263
+
264
+ template <typename test_function_type_, typename... args_types_>
265
+ void operator()(char const *kernel_name, test_function_type_ test_fn, args_types_ &&...args) {
266
+ if (!global_config.should_run(kernel_name)) return;
267
+
268
+ nk_test_current_kernel_ = kernel_name;
269
+ auto stats = test_fn(std::forward<args_types_>(args)...);
270
+ nk_test_current_kernel_ = nullptr;
271
+
272
+ if (!emitted_any) {
273
+ if (title) {
274
+ std::puts("");
275
+ std::printf("%s:\n", title);
276
+ }
277
+ emitted_any = true;
278
+ }
279
+ if (last_family != stats.family) {
280
+ print_stats_header(stats.family);
281
+ last_family = stats.family;
282
+ }
283
+ print_stats_row(kernel_name, stats);
284
+ if (global_config.assert_on_failure && should_fail(kernel_name, stats)) ++global_config.failure_count;
285
+ }
286
+ };
287
+
288
+ inline time_point test_start_time() { return steady_clock::now(); }
289
+
290
+ inline bool within_time_budget(time_point start) {
291
+ auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(steady_clock::now() - start).count();
292
+ return elapsed < static_cast<long long>(global_config.time_budget_ms);
293
+ }
294
+
295
+ /**
296
+ * @brief Compute ULP (Units in Last Place) distance between two floating-point values.
297
+ *
298
+ * ULP distance is the number of representable floating-point numbers between a and b.
299
+ * This is the gold standard for comparing floating-point implementations.
300
+ *
301
+ * Uses the XOR transformation from Bruce Dawson's algorithm to handle all sign combinations:
302
+ * @see https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
303
+ * @see https://en.wikipedia.org/wiki/Unit_in_the_last_place
304
+ */
305
+ template <typename scalar_type_>
306
+ std::uint64_t ulp_distance(scalar_type_ a, scalar_type_ b) noexcept {
307
+ // Handle special cases - skip float checks for integer types
308
+ if constexpr (!nk::is_integral_dtype<scalar_type_>()) {
309
+ if (std::isnan(static_cast<double>(a)) || std::isnan(static_cast<double>(b)))
310
+ return std::numeric_limits<std::uint64_t>::max();
311
+ }
312
+ if (a == b) return 0; // Also handles +0 == -0
313
+
314
+ // Use the XOR transformation from Bruce Dawson's "Comparing Floating Point Numbers"
315
+ // This transforms float bit patterns to an ordered integer representation where
316
+ // the integer difference equals the ULP distance.
317
+ if constexpr (sizeof(scalar_type_) == 4) {
318
+ std::int32_t ia, ib;
319
+ std::memcpy(&ia, &a, sizeof(ia));
320
+ std::memcpy(&ib, &b, sizeof(ib));
321
+
322
+ // Transform negative floats: flip all bits except sign to reverse their ordering
323
+ // This makes the integer representation monotonically ordered with float value
324
+ if (ia < 0) ia ^= 0x7FFFFFFF;
325
+ if (ib < 0) ib ^= 0x7FFFFFFF;
326
+
327
+ // Compute absolute difference using 64-bit arithmetic to avoid overflow
328
+ std::int64_t diff = static_cast<std::int64_t>(ia) - static_cast<std::int64_t>(ib);
329
+ return static_cast<std::uint64_t>(diff < 0 ? -diff : diff);
330
+ }
331
+ else if constexpr (sizeof(scalar_type_) == 8) {
332
+ std::int64_t ia, ib;
333
+ std::memcpy(&ia, &a, sizeof(ia));
334
+ std::memcpy(&ib, &b, sizeof(ib));
335
+
336
+ if (ia < 0) ia ^= 0x7FFFFFFFFFFFFFFFLL;
337
+ if (ib < 0) ib ^= 0x7FFFFFFFFFFFFFFFLL;
338
+
339
+ // For 64-bit, handle potential overflow in subtraction when signs differ
340
+ if ((ia >= 0) != (ib >= 0)) {
341
+ // Different signs after transformation: distance = |ia| + |ib|
342
+ // Safe negation that handles INT64_MIN
343
+ auto safe_abs = [](std::int64_t x) -> std::uint64_t {
344
+ return x < 0 ? static_cast<std::uint64_t>(~x) + 1 : static_cast<std::uint64_t>(x);
345
+ };
346
+ return safe_abs(ia) + safe_abs(ib);
347
+ }
348
+ // Same sign: simple subtraction (no overflow possible)
349
+ return ia >= ib ? static_cast<std::uint64_t>(ia - ib) : static_cast<std::uint64_t>(ib - ia);
350
+ }
351
+ else {
352
+ // For f16/bf16, convert to f32 and compute there
353
+ return ulp_distance(static_cast<float>(a), static_cast<float>(b));
354
+ }
355
+ }
356
+
357
+ template <typename scalar_type_>
358
+ std::uint64_t integer_distance(scalar_type_ a, scalar_type_ b) noexcept {
359
+ auto ordered = [](scalar_type_ value) noexcept -> std::uint64_t {
360
+ if constexpr (nk::is_signed_dtype<scalar_type_>())
361
+ return static_cast<std::uint64_t>(static_cast<std::int64_t>(value)) ^ (1ull << 63);
362
+ else return static_cast<std::uint64_t>(value);
363
+ };
364
+ std::uint64_t a_ordered = ordered(a), b_ordered = ordered(b);
365
+ return a_ordered >= b_ordered ? a_ordered - b_ordered : b_ordered - a_ordered;
366
+ }
367
+
368
+ /**
369
+ * @brief Accumulator for error statistics across multiple test trials.
370
+ */
371
+ struct error_stats_t {
372
+ comparison_family_t family = comparison_family_t::narrow_arithmetic_k;
373
+
374
+ nk_f64_t min_abs_err = std::numeric_limits<nk_f64_t>::max();
375
+ nk_f64_t max_abs_err = 0;
376
+ nk_f64_t sum_abs_err = 0;
377
+
378
+ nk_f64_t min_rel_err = std::numeric_limits<nk_f64_t>::max();
379
+ nk_f64_t max_rel_err = 0;
380
+ nk_f64_t sum_rel_err = 0;
381
+
382
+ std::uint64_t min_ulp = std::numeric_limits<std::uint64_t>::max();
383
+ std::uint64_t max_ulp = 0;
384
+ f118_t sum_ulp = f118_t();
385
+
386
+ std::size_t count = 0;
387
+ std::size_t exact_matches = 0;
388
+ bool saw_floating_distance = false;
389
+
390
+ explicit error_stats_t(comparison_family_t family = comparison_family_t::narrow_arithmetic_k) noexcept
391
+ : family(family) {}
392
+
393
+ template <typename actual_type_, typename expected_type_>
394
+ void accumulate(actual_type_ actual, expected_type_ expected) noexcept {
395
+ if constexpr (nk::is_complex_dtype<actual_type_>())
396
+ accumulate_scalar(actual.real(), expected.real()), accumulate_scalar(actual.imag(), expected.imag());
397
+ else accumulate_scalar(actual, expected);
398
+ }
399
+
400
+ template <typename actual_type_, typename expected_type_>
401
+ void accumulate_scalar(actual_type_ actual, expected_type_ expected) noexcept {
402
+ actual_type_ expected_as_actual;
403
+ if constexpr (std::is_same_v<expected_type_, f118_t> || std::is_same_v<expected_type_, f118c_t>)
404
+ expected_as_actual = expected.template to<actual_type_>();
405
+ else if constexpr (nk::is_integral_dtype<expected_type_>() && nk::is_integral_dtype<actual_type_>())
406
+ expected_as_actual = actual_type_(expected);
407
+ else expected_as_actual = actual_type_(static_cast<double>(expected));
408
+
409
+ bool const use_integer_distance = family == comparison_family_t::exact_k &&
410
+ nk::is_integral_dtype<actual_type_>();
411
+ std::uint64_t ulps = use_integer_distance ? integer_distance(actual, expected_as_actual)
412
+ : ulp_distance(actual, expected_as_actual);
413
+
414
+ // Skip NaN/Inf pairs — sentinel value means the comparison is meaningless
415
+ if (ulps == std::numeric_limits<std::uint64_t>::max()) return;
416
+
417
+ if constexpr (!nk::is_integral_dtype<actual_type_>()) saw_floating_distance = true;
418
+
419
+ if constexpr (!nk::is_integral_dtype<actual_type_>() || std::is_integral_v<actual_type_>) {
420
+ nk_f64_t exp_f64 = static_cast<nk_f64_t>(expected_as_actual);
421
+ nk_f64_t act_f64 = static_cast<nk_f64_t>(actual);
422
+
423
+ nk_f64_t abs_err = std::fabs(exp_f64 - act_f64);
424
+ nk_f64_t rel_err = exp_f64 != 0 ? abs_err / std::fabs(exp_f64) : abs_err;
425
+
426
+ min_abs_err = std::min(min_abs_err, abs_err);
427
+ max_abs_err = std::max(max_abs_err, abs_err);
428
+ sum_abs_err += abs_err;
429
+ min_rel_err = std::min(min_rel_err, rel_err);
430
+ max_rel_err = std::max(max_rel_err, rel_err);
431
+ sum_rel_err += rel_err;
432
+ }
433
+
434
+ // Always update ULP metrics (works for both integer and float)
435
+ min_ulp = std::min(min_ulp, ulps);
436
+ max_ulp = std::max(max_ulp, ulps);
437
+ sum_ulp += f118_t(ulps);
438
+
439
+ count++;
440
+ if (ulps == 0) exact_matches++;
441
+ }
442
+
443
+ nk_f64_t mean_abs_err() const noexcept { return count > 0 ? sum_abs_err / count : 0; }
444
+ nk_f64_t mean_rel_err() const noexcept { return count > 0 ? sum_rel_err / count : 0; }
445
+ nk_f64_t mean_ulp() const noexcept {
446
+ // On 32-bit WASM we need this ugly casting sequence to avoid adding more `f118_t` constructors
447
+ return count > 0 ? static_cast<double>(sum_ulp / f118_t(static_cast<double>(count))) : 0;
448
+ }
449
+ std::size_t mismatches() const noexcept { return count - exact_matches; }
450
+
451
+ void reset() noexcept {
452
+ comparison_family_t const current_family = family;
453
+ *this = error_stats_t {current_family};
454
+ }
455
+
456
+ void merge(error_stats_t const &other) noexcept {
457
+ if (other.count == 0) return;
458
+ if (count == 0) family = other.family;
459
+ else assert(family == other.family && "Can't merge stats from different comparison families");
460
+ min_abs_err = std::min(min_abs_err, other.min_abs_err);
461
+ max_abs_err = std::max(max_abs_err, other.max_abs_err);
462
+ sum_abs_err += other.sum_abs_err;
463
+ min_rel_err = std::min(min_rel_err, other.min_rel_err);
464
+ max_rel_err = std::max(max_rel_err, other.max_rel_err);
465
+ sum_rel_err += other.sum_rel_err;
466
+ min_ulp = std::min(min_ulp, other.min_ulp);
467
+ max_ulp = std::max(max_ulp, other.max_ulp);
468
+ sum_ulp += other.sum_ulp;
469
+ count += other.count;
470
+ exact_matches += other.exact_matches;
471
+ saw_floating_distance = saw_floating_distance || other.saw_floating_distance;
472
+ }
473
+ };
474
+
475
+ inline bool should_fail(char const *kernel_name, error_stats_t const &stats) noexcept {
476
+ // GCC 14 LoongArch tree-FRE miscompiles the serial f16→f32 conversion used by
477
+ // the test reference path. The LASX f16 kernels are verified correct independently.
478
+ if (global_config.running_in_qemu && std::strstr(kernel_name, "_f16")) return false;
479
+
480
+ comparison_family_spec_t const spec = comparison_family_spec(stats.family);
481
+ switch (spec.failure_mode) {
482
+ case comparison_failure_mode_t::exact_distance_k:
483
+ if (!stats.saw_floating_distance) return stats.max_ulp > 0;
484
+ return stats.max_ulp > global_config.ulp_threshold_for(kernel_name);
485
+ case comparison_failure_mode_t::ulp_threshold_k:
486
+ return stats.max_ulp > global_config.ulp_threshold_for(kernel_name);
487
+ }
488
+ return false;
489
+ }
490
+
491
+ inline void print_stats_row(char const *kernel_name, error_stats_t const &stats) noexcept {
492
+ switch (stats.family) {
493
+ case comparison_family_t::exact_k:
494
+ std::printf("%-40s %12llu %10.1f %12.2e %12zu %10zu\n", kernel_name,
495
+ static_cast<unsigned long long>(stats.max_ulp), stats.mean_ulp(), stats.max_abs_err,
496
+ stats.mismatches(), stats.exact_matches);
497
+ break;
498
+ case comparison_family_t::probability_k:
499
+ std::printf("%-40s %12.2e %10.2e %12.2e %12.2e %10.2e\n", kernel_name, stats.max_abs_err, stats.mean_abs_err(),
500
+ stats.max_rel_err, stats.mean_rel_err(), stats.mean_ulp());
501
+ break;
502
+ case comparison_family_t::geospatial_k:
503
+ std::printf("%-40s %12.2e %10.2e %12.2e %12.1f %10llu\n", kernel_name, stats.max_abs_err, stats.mean_abs_err(),
504
+ stats.max_rel_err, stats.mean_ulp(), static_cast<unsigned long long>(stats.max_ulp));
505
+ break;
506
+ case comparison_family_t::narrow_arithmetic_k:
507
+ case comparison_family_t::mixed_precision_reduction_k:
508
+ case comparison_family_t::external_baseline_k:
509
+ std::printf("%-40s %12.2e %10.2e %12.2e %12llu %10zu\n", kernel_name, stats.max_abs_err, stats.max_rel_err,
510
+ stats.mean_ulp(), static_cast<unsigned long long>(stats.max_ulp), stats.exact_matches);
511
+ break;
512
+ }
513
+ std::fflush(stdout);
514
+ }
515
+
516
+ /**
517
+ * @brief Factory function to allocate vectors, potentially raising bad-allocs.
518
+ */
519
+ template <typename type_>
520
+ [[nodiscard]] nk::vector<type_> make_vector(std::size_t n) {
521
+ auto result = nk::vector<type_>::try_zeros(n);
522
+ #if defined(__cpp_exceptions) || defined(__EXCEPTIONS)
523
+ if (result.empty() && n > 0) throw std::bad_alloc();
524
+ #else
525
+ if (result.empty() && n > 0) std::abort();
526
+ #endif
527
+ return result;
528
+ }
529
+
530
+ /**
531
+ * @brief Fill buffer with random values, respecting global distribution setting.
532
+ *
533
+ * Dispatches to appropriate nk::fill_* library function based on `global_config.distribution`.
534
+ * Infers sensible bounds from type's representable range.
535
+ */
536
+ template <typename scalar_type_, typename generator_type_>
537
+ void fill_random(generator_type_ &generator, nk::vector<scalar_type_> &vector) {
538
+ switch (global_config.distribution) {
539
+ case random_distribution_kind_t::uniform_k:
540
+ nk::fill_uniform(generator, vector.values_data(), vector.size_values());
541
+ break;
542
+ case random_distribution_kind_t::lognormal_k:
543
+ nk::fill_lognormal(generator, vector.values_data(), vector.size_values());
544
+ break;
545
+ case random_distribution_kind_t::cauchy_k:
546
+ nk::fill_cauchy(generator, vector.values_data(), vector.size_values());
547
+ break;
548
+ }
549
+ }
550
+
551
+ // Forward declarations for test modules
552
+ void test_casts();
553
+ void test_reduce();
554
+ void test_dot();
555
+ void test_spatial();
556
+ void test_set();
557
+ void test_curved();
558
+ void test_probability();
559
+ void test_each();
560
+ void test_trigonometry();
561
+ void test_geospatial();
562
+ void test_mesh();
563
+ void test_sparse();
564
+ void test_vector_types();
565
+ void test_tensor_ops();
566
+ void test_maxsim();
567
+
568
+ // Forward declarations for cross/batch tests (ISA-family files)
569
+ void test_cross_serial();
570
+ void test_cross_x86();
571
+ void test_cross_amx();
572
+ void test_cross_arm();
573
+ void test_cross_sme();
574
+ void test_cross_blas();
575
+ void test_cross_rvv();
576
+ void test_cross_power();
577
+ void test_cross_loongarch();
578
+ void test_cross_wasm();
579
+
580
+ #endif // NK_TEST_HPP