usearch 2.21.4 → 2.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (604) hide show
  1. package/README.md +65 -69
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +8 -8
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +124 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +224 -48
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/README.md +1 -1
  16. package/javascript/dist/cjs/usearch.d.ts +8 -3
  17. package/javascript/dist/cjs/usearch.js +12 -4
  18. package/javascript/dist/esm/usearch.d.ts +8 -3
  19. package/javascript/dist/esm/usearch.js +12 -4
  20. package/javascript/lib.cpp +17 -0
  21. package/javascript/usearch.test.js +117 -94
  22. package/javascript/usearch.ts +14 -6
  23. package/numkong/.clang-tidy +30 -0
  24. package/{simsimd → numkong}/.cmake-format.py +18 -0
  25. package/numkong/.editorconfig +12 -0
  26. package/numkong/.git-blame-ignore-revs +123 -0
  27. package/numkong/.mailmap +15 -0
  28. package/numkong/.spi.yml +11 -0
  29. package/numkong/.swift-format +14 -0
  30. package/numkong/CITATION.cff +81 -0
  31. package/numkong/CONTRIBUTING.md +500 -0
  32. package/numkong/Cargo.toml +54 -0
  33. package/numkong/MANIFEST.in +8 -0
  34. package/numkong/Package.swift +84 -0
  35. package/numkong/README.md +569 -0
  36. package/numkong/bench/README.md +217 -0
  37. package/numkong/bench/bench-browser.html +323 -0
  38. package/numkong/bench/bench.cpp +344 -0
  39. package/numkong/bench/bench.hpp +816 -0
  40. package/numkong/bench/bench.js +148 -0
  41. package/numkong/bench/bench.mjs +616 -0
  42. package/numkong/bench/bench_attention.cpp +113 -0
  43. package/numkong/bench/bench_cast.cpp +264 -0
  44. package/numkong/bench/bench_cross_amx.cpp +62 -0
  45. package/numkong/bench/bench_cross_arm.cpp +245 -0
  46. package/numkong/bench/bench_cross_blas.cpp +309 -0
  47. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  48. package/numkong/bench/bench_cross_power.cpp +84 -0
  49. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  50. package/numkong/bench/bench_cross_serial.cpp +151 -0
  51. package/numkong/bench/bench_cross_sme.cpp +163 -0
  52. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  53. package/numkong/bench/bench_cross_x86.cpp +455 -0
  54. package/numkong/bench/bench_curved.cpp +210 -0
  55. package/numkong/bench/bench_dot.cpp +315 -0
  56. package/numkong/bench/bench_each.cpp +503 -0
  57. package/numkong/bench/bench_geospatial.cpp +112 -0
  58. package/numkong/bench/bench_maxsim.cpp +154 -0
  59. package/numkong/bench/bench_mesh.cpp +148 -0
  60. package/numkong/bench/bench_probability.cpp +60 -0
  61. package/numkong/bench/bench_reduce.cpp +371 -0
  62. package/numkong/bench/bench_set.cpp +73 -0
  63. package/numkong/bench/bench_sparse.cpp +198 -0
  64. package/numkong/bench/bench_spatial.cpp +347 -0
  65. package/numkong/bench/bench_trigonometry.cpp +137 -0
  66. package/numkong/bench/swift/Bench.swift +506 -0
  67. package/numkong/binding.gyp +169 -0
  68. package/numkong/build.rs +484 -0
  69. package/numkong/c/dispatch.h +512 -0
  70. package/numkong/c/dispatch_bf16.c +447 -0
  71. package/numkong/c/dispatch_bf16c.c +52 -0
  72. package/numkong/c/dispatch_e2m3.c +296 -0
  73. package/numkong/c/dispatch_e3m2.c +284 -0
  74. package/numkong/c/dispatch_e4m3.c +318 -0
  75. package/numkong/c/dispatch_e5m2.c +316 -0
  76. package/numkong/c/dispatch_f16.c +452 -0
  77. package/numkong/c/dispatch_f16c.c +58 -0
  78. package/numkong/c/dispatch_f32.c +434 -0
  79. package/numkong/c/dispatch_f32c.c +99 -0
  80. package/numkong/c/dispatch_f64.c +348 -0
  81. package/numkong/c/dispatch_f64c.c +98 -0
  82. package/numkong/c/dispatch_i16.c +96 -0
  83. package/numkong/c/dispatch_i32.c +89 -0
  84. package/numkong/c/dispatch_i4.c +153 -0
  85. package/numkong/c/dispatch_i64.c +86 -0
  86. package/numkong/c/dispatch_i8.c +348 -0
  87. package/numkong/c/dispatch_other.c +348 -0
  88. package/numkong/c/dispatch_u1.c +193 -0
  89. package/numkong/c/dispatch_u16.c +124 -0
  90. package/numkong/c/dispatch_u32.c +118 -0
  91. package/numkong/c/dispatch_u4.c +153 -0
  92. package/numkong/c/dispatch_u64.c +102 -0
  93. package/numkong/c/dispatch_u8.c +364 -0
  94. package/numkong/c/numkong.c +940 -0
  95. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  96. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  97. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_math_lib.cmake +46 -0
  99. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  100. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  101. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  102. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  103. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  104. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  105. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  106. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  107. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  108. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  109. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  110. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  111. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  112. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  113. package/numkong/include/README.md +643 -0
  114. package/numkong/include/module.modulemap +129 -0
  115. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  116. package/numkong/include/numkong/attention/sme.h +2075 -0
  117. package/numkong/include/numkong/attention.h +49 -0
  118. package/numkong/include/numkong/capabilities.h +930 -0
  119. package/numkong/include/numkong/cast/README.md +262 -0
  120. package/numkong/include/numkong/cast/diamond.h +64 -0
  121. package/numkong/include/numkong/cast/haswell.h +823 -0
  122. package/numkong/include/numkong/cast/icelake.h +475 -0
  123. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  124. package/numkong/include/numkong/cast/neon.h +1174 -0
  125. package/numkong/include/numkong/cast/powervsx.h +449 -0
  126. package/numkong/include/numkong/cast/rvv.h +970 -0
  127. package/numkong/include/numkong/cast/sapphire.h +262 -0
  128. package/numkong/include/numkong/cast/serial.h +2336 -0
  129. package/numkong/include/numkong/cast/skylake.h +915 -0
  130. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  131. package/numkong/include/numkong/cast.h +254 -0
  132. package/numkong/include/numkong/cast.hpp +44 -0
  133. package/numkong/include/numkong/curved/README.md +223 -0
  134. package/numkong/include/numkong/curved/genoa.h +182 -0
  135. package/numkong/include/numkong/curved/haswell.h +276 -0
  136. package/numkong/include/numkong/curved/neon.h +329 -0
  137. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  138. package/numkong/include/numkong/curved/rvv.h +305 -0
  139. package/numkong/include/numkong/curved/serial.h +207 -0
  140. package/numkong/include/numkong/curved/skylake.h +457 -0
  141. package/numkong/include/numkong/curved/smef64.h +530 -0
  142. package/numkong/include/numkong/curved.h +513 -0
  143. package/numkong/include/numkong/curved.hpp +144 -0
  144. package/numkong/include/numkong/dot/README.md +442 -0
  145. package/numkong/include/numkong/dot/alder.h +563 -0
  146. package/numkong/include/numkong/dot/diamond.h +158 -0
  147. package/numkong/include/numkong/dot/genoa.h +289 -0
  148. package/numkong/include/numkong/dot/haswell.h +1723 -0
  149. package/numkong/include/numkong/dot/icelake.h +997 -0
  150. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  151. package/numkong/include/numkong/dot/neon.h +869 -0
  152. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  153. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  154. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  155. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  156. package/numkong/include/numkong/dot/powervsx.h +752 -0
  157. package/numkong/include/numkong/dot/rvv.h +722 -0
  158. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  159. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  160. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  161. package/numkong/include/numkong/dot/sapphire.h +141 -0
  162. package/numkong/include/numkong/dot/serial.h +874 -0
  163. package/numkong/include/numkong/dot/sierra.h +405 -0
  164. package/numkong/include/numkong/dot/skylake.h +1116 -0
  165. package/numkong/include/numkong/dot/sve.h +420 -0
  166. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  167. package/numkong/include/numkong/dot/svehalf.h +168 -0
  168. package/numkong/include/numkong/dot/svesdot.h +90 -0
  169. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  170. package/numkong/include/numkong/dot.h +1136 -0
  171. package/numkong/include/numkong/dot.hpp +94 -0
  172. package/numkong/include/numkong/dots/README.md +496 -0
  173. package/numkong/include/numkong/dots/alder.h +117 -0
  174. package/numkong/include/numkong/dots/diamond.h +86 -0
  175. package/numkong/include/numkong/dots/genoa.h +100 -0
  176. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  177. package/numkong/include/numkong/dots/haswell.h +310 -0
  178. package/numkong/include/numkong/dots/icelake.h +180 -0
  179. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  180. package/numkong/include/numkong/dots/neon.h +123 -0
  181. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  182. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  183. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  184. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  185. package/numkong/include/numkong/dots/powervsx.h +194 -0
  186. package/numkong/include/numkong/dots/rvv.h +2593 -0
  187. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  188. package/numkong/include/numkong/dots/serial.h +2867 -0
  189. package/numkong/include/numkong/dots/sierra.h +100 -0
  190. package/numkong/include/numkong/dots/skylake.h +207 -0
  191. package/numkong/include/numkong/dots/sme.h +5041 -0
  192. package/numkong/include/numkong/dots/smebi32.h +477 -0
  193. package/numkong/include/numkong/dots/smef64.h +1328 -0
  194. package/numkong/include/numkong/dots/smehalf.h +47 -0
  195. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  196. package/numkong/include/numkong/dots.h +3110 -0
  197. package/numkong/include/numkong/dots.hpp +641 -0
  198. package/numkong/include/numkong/each/README.md +465 -0
  199. package/numkong/include/numkong/each/haswell.h +1658 -0
  200. package/numkong/include/numkong/each/icelake.h +272 -0
  201. package/numkong/include/numkong/each/neon.h +1138 -0
  202. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  203. package/numkong/include/numkong/each/neonhalf.h +318 -0
  204. package/numkong/include/numkong/each/rvv.h +1121 -0
  205. package/numkong/include/numkong/each/sapphire.h +343 -0
  206. package/numkong/include/numkong/each/serial.h +282 -0
  207. package/numkong/include/numkong/each/skylake.h +1562 -0
  208. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  209. package/numkong/include/numkong/each.h +2232 -0
  210. package/numkong/include/numkong/each.hpp +434 -0
  211. package/numkong/include/numkong/geospatial/README.md +147 -0
  212. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  213. package/numkong/include/numkong/geospatial/neon.h +615 -0
  214. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  215. package/numkong/include/numkong/geospatial/serial.h +309 -0
  216. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  217. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  218. package/numkong/include/numkong/geospatial.h +453 -0
  219. package/numkong/include/numkong/geospatial.hpp +235 -0
  220. package/numkong/include/numkong/matrix.hpp +336 -0
  221. package/numkong/include/numkong/maxsim/README.md +187 -0
  222. package/numkong/include/numkong/maxsim/alder.h +511 -0
  223. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  224. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  225. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  226. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  227. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  228. package/numkong/include/numkong/maxsim/serial.h +490 -0
  229. package/numkong/include/numkong/maxsim/sme.h +993 -0
  230. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  231. package/numkong/include/numkong/maxsim.h +571 -0
  232. package/numkong/include/numkong/maxsim.hpp +133 -0
  233. package/numkong/include/numkong/mesh/README.md +219 -0
  234. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  235. package/numkong/include/numkong/mesh/neon.h +1821 -0
  236. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  237. package/numkong/include/numkong/mesh/rvv.h +936 -0
  238. package/numkong/include/numkong/mesh/serial.h +721 -0
  239. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  240. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  241. package/numkong/include/numkong/mesh.h +666 -0
  242. package/numkong/include/numkong/mesh.hpp +701 -0
  243. package/numkong/include/numkong/numkong.h +78 -0
  244. package/numkong/include/numkong/numkong.hpp +58 -0
  245. package/numkong/include/numkong/probability/README.md +177 -0
  246. package/numkong/include/numkong/probability/haswell.h +267 -0
  247. package/numkong/include/numkong/probability/neon.h +255 -0
  248. package/numkong/include/numkong/probability/rvv.h +414 -0
  249. package/numkong/include/numkong/probability/serial.h +181 -0
  250. package/numkong/include/numkong/probability/skylake.h +324 -0
  251. package/numkong/include/numkong/probability.h +380 -0
  252. package/numkong/include/numkong/probability.hpp +120 -0
  253. package/numkong/include/numkong/random.h +50 -0
  254. package/numkong/include/numkong/random.hpp +285 -0
  255. package/numkong/include/numkong/reduce/README.md +552 -0
  256. package/numkong/include/numkong/reduce/alder.h +636 -0
  257. package/numkong/include/numkong/reduce/genoa.h +201 -0
  258. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  259. package/numkong/include/numkong/reduce/icelake.h +549 -0
  260. package/numkong/include/numkong/reduce/neon.h +3980 -0
  261. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  262. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  263. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  264. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  265. package/numkong/include/numkong/reduce/serial.h +753 -0
  266. package/numkong/include/numkong/reduce/sierra.h +338 -0
  267. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  268. package/numkong/include/numkong/reduce/sve.h +52 -0
  269. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  270. package/numkong/include/numkong/reduce.h +1582 -0
  271. package/numkong/include/numkong/reduce.hpp +778 -0
  272. package/numkong/include/numkong/scalar/README.md +89 -0
  273. package/numkong/include/numkong/scalar/haswell.h +122 -0
  274. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  275. package/numkong/include/numkong/scalar/neon.h +122 -0
  276. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  277. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  278. package/numkong/include/numkong/scalar/rvv.h +211 -0
  279. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  280. package/numkong/include/numkong/scalar/serial.h +332 -0
  281. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  282. package/numkong/include/numkong/scalar.h +696 -0
  283. package/numkong/include/numkong/set/README.md +179 -0
  284. package/numkong/include/numkong/set/haswell.h +334 -0
  285. package/numkong/include/numkong/set/icelake.h +485 -0
  286. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  287. package/numkong/include/numkong/set/neon.h +363 -0
  288. package/numkong/include/numkong/set/powervsx.h +326 -0
  289. package/numkong/include/numkong/set/rvv.h +226 -0
  290. package/numkong/include/numkong/set/rvvbb.h +117 -0
  291. package/numkong/include/numkong/set/serial.h +174 -0
  292. package/numkong/include/numkong/set/sve.h +187 -0
  293. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  294. package/numkong/include/numkong/set.h +471 -0
  295. package/numkong/include/numkong/set.hpp +114 -0
  296. package/numkong/include/numkong/sets/README.md +149 -0
  297. package/numkong/include/numkong/sets/haswell.h +63 -0
  298. package/numkong/include/numkong/sets/icelake.h +66 -0
  299. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  300. package/numkong/include/numkong/sets/neon.h +61 -0
  301. package/numkong/include/numkong/sets/powervsx.h +65 -0
  302. package/numkong/include/numkong/sets/serial.h +43 -0
  303. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  304. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  305. package/numkong/include/numkong/sets.h +382 -0
  306. package/numkong/include/numkong/sparse/README.md +156 -0
  307. package/numkong/include/numkong/sparse/icelake.h +463 -0
  308. package/numkong/include/numkong/sparse/neon.h +288 -0
  309. package/numkong/include/numkong/sparse/serial.h +117 -0
  310. package/numkong/include/numkong/sparse/sve2.h +504 -0
  311. package/numkong/include/numkong/sparse/turin.h +322 -0
  312. package/numkong/include/numkong/sparse.h +363 -0
  313. package/numkong/include/numkong/sparse.hpp +113 -0
  314. package/numkong/include/numkong/spatial/README.md +439 -0
  315. package/numkong/include/numkong/spatial/alder.h +604 -0
  316. package/numkong/include/numkong/spatial/diamond.h +240 -0
  317. package/numkong/include/numkong/spatial/genoa.h +222 -0
  318. package/numkong/include/numkong/spatial/haswell.h +979 -0
  319. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  320. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  321. package/numkong/include/numkong/spatial/neon.h +846 -0
  322. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  323. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  324. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  325. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  326. package/numkong/include/numkong/spatial/rvv.h +991 -0
  327. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  328. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  329. package/numkong/include/numkong/spatial/serial.h +347 -0
  330. package/numkong/include/numkong/spatial/sierra.h +516 -0
  331. package/numkong/include/numkong/spatial/skylake.h +605 -0
  332. package/numkong/include/numkong/spatial/sve.h +246 -0
  333. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  334. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  335. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  336. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  337. package/numkong/include/numkong/spatial.h +1681 -0
  338. package/numkong/include/numkong/spatial.hpp +183 -0
  339. package/numkong/include/numkong/spatials/README.md +580 -0
  340. package/numkong/include/numkong/spatials/alder.h +94 -0
  341. package/numkong/include/numkong/spatials/diamond.h +82 -0
  342. package/numkong/include/numkong/spatials/genoa.h +94 -0
  343. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  344. package/numkong/include/numkong/spatials/haswell.h +219 -0
  345. package/numkong/include/numkong/spatials/icelake.h +113 -0
  346. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  347. package/numkong/include/numkong/spatials/neon.h +109 -0
  348. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  349. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  350. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  351. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  352. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  353. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  354. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  355. package/numkong/include/numkong/spatials/serial.h +248 -0
  356. package/numkong/include/numkong/spatials/sierra.h +96 -0
  357. package/numkong/include/numkong/spatials/skylake.h +184 -0
  358. package/numkong/include/numkong/spatials/sme.h +1927 -0
  359. package/numkong/include/numkong/spatials/smef64.h +483 -0
  360. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  361. package/numkong/include/numkong/spatials.h +3374 -0
  362. package/numkong/include/numkong/spatials.hpp +509 -0
  363. package/numkong/include/numkong/tensor.hpp +1981 -0
  364. package/numkong/include/numkong/trigonometry/README.md +184 -0
  365. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  366. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  367. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  368. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  369. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  370. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  371. package/numkong/include/numkong/trigonometry.h +467 -0
  372. package/numkong/include/numkong/trigonometry.hpp +166 -0
  373. package/numkong/include/numkong/types.h +1695 -0
  374. package/numkong/include/numkong/types.hpp +6027 -0
  375. package/numkong/include/numkong/vector.hpp +766 -0
  376. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  377. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  378. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  380. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  381. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  382. package/numkong/javascript/README.md +254 -0
  383. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  384. package/numkong/javascript/numkong-browser.ts +40 -0
  385. package/numkong/javascript/numkong-wasm.ts +750 -0
  386. package/numkong/javascript/numkong.c +712 -0
  387. package/numkong/javascript/numkong.ts +613 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  389. package/numkong/javascript/tsconfig-cjs.json +13 -0
  390. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  391. package/numkong/javascript/types.ts +784 -0
  392. package/numkong/numkong.gypi +104 -0
  393. package/numkong/package.json +108 -0
  394. package/numkong/probes/arm_neon.c +8 -0
  395. package/numkong/probes/arm_neon_bfdot.c +9 -0
  396. package/numkong/probes/arm_neon_fhm.c +9 -0
  397. package/numkong/probes/arm_neon_half.c +8 -0
  398. package/numkong/probes/arm_neon_sdot.c +9 -0
  399. package/numkong/probes/arm_neonfp8.c +9 -0
  400. package/numkong/probes/arm_sme.c +16 -0
  401. package/numkong/probes/arm_sme2.c +16 -0
  402. package/numkong/probes/arm_sme2p1.c +16 -0
  403. package/numkong/probes/arm_sme_bf16.c +16 -0
  404. package/numkong/probes/arm_sme_bi32.c +16 -0
  405. package/numkong/probes/arm_sme_f64.c +16 -0
  406. package/numkong/probes/arm_sme_fa64.c +14 -0
  407. package/numkong/probes/arm_sme_half.c +16 -0
  408. package/numkong/probes/arm_sme_lut2.c +15 -0
  409. package/numkong/probes/arm_sve.c +18 -0
  410. package/numkong/probes/arm_sve2.c +20 -0
  411. package/numkong/probes/arm_sve2p1.c +18 -0
  412. package/numkong/probes/arm_sve_bfdot.c +20 -0
  413. package/numkong/probes/arm_sve_half.c +18 -0
  414. package/numkong/probes/arm_sve_sdot.c +21 -0
  415. package/numkong/probes/loongarch_lasx.c +12 -0
  416. package/numkong/probes/power_vsx.c +12 -0
  417. package/numkong/probes/probe.js +127 -0
  418. package/numkong/probes/riscv_rvv.c +14 -0
  419. package/numkong/probes/riscv_rvv_bb.c +15 -0
  420. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  421. package/numkong/probes/riscv_rvv_half.c +14 -0
  422. package/numkong/probes/wasm_v128relaxed.c +11 -0
  423. package/numkong/probes/x86_alder.c +17 -0
  424. package/numkong/probes/x86_diamond.c +17 -0
  425. package/numkong/probes/x86_genoa.c +17 -0
  426. package/numkong/probes/x86_graniteamx.c +19 -0
  427. package/numkong/probes/x86_haswell.c +11 -0
  428. package/numkong/probes/x86_icelake.c +17 -0
  429. package/numkong/probes/x86_sapphire.c +16 -0
  430. package/numkong/probes/x86_sapphireamx.c +18 -0
  431. package/numkong/probes/x86_sierra.c +17 -0
  432. package/numkong/probes/x86_skylake.c +15 -0
  433. package/numkong/probes/x86_turin.c +17 -0
  434. package/numkong/rust/README.md +698 -0
  435. package/numkong/rust/capabilities.rs +96 -0
  436. package/numkong/rust/cast.rs +314 -0
  437. package/numkong/rust/curved.rs +391 -0
  438. package/numkong/rust/each.rs +2721 -0
  439. package/numkong/rust/geospatial.rs +343 -0
  440. package/numkong/rust/matrix.rs +5424 -0
  441. package/numkong/rust/maxsim.rs +540 -0
  442. package/numkong/rust/mesh.rs +837 -0
  443. package/numkong/rust/numkong.rs +409 -0
  444. package/numkong/rust/probability.rs +272 -0
  445. package/numkong/rust/reduce.rs +1249 -0
  446. package/numkong/rust/set.rs +194 -0
  447. package/numkong/rust/sparse.rs +513 -0
  448. package/numkong/rust/spatial.rs +1815 -0
  449. package/numkong/rust/tensor.rs +7565 -0
  450. package/numkong/rust/types.rs +3666 -0
  451. package/numkong/rust/vector.rs +1899 -0
  452. package/numkong/rustfmt.toml +2 -0
  453. package/numkong/swift/Matrix.swift +1388 -0
  454. package/numkong/swift/MaxSim.swift +151 -0
  455. package/numkong/swift/NumKong.swift +283 -0
  456. package/numkong/swift/Numerics.swift +329 -0
  457. package/numkong/swift/README.md +433 -0
  458. package/numkong/swift/Scalar.swift +741 -0
  459. package/numkong/swift/Tensor.swift +209 -0
  460. package/numkong/test/README.md +315 -0
  461. package/numkong/test/playwright.config.ts +16 -0
  462. package/numkong/test/swift/Test.swift +534 -0
  463. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  464. package/numkong/test/test-browser-bundle.html +188 -0
  465. package/numkong/test/test-browser-runner.mjs +43 -0
  466. package/numkong/test/test-browser.html +305 -0
  467. package/numkong/test/test-dtypes.mjs +453 -0
  468. package/numkong/test/test-wasm.mjs +267 -0
  469. package/numkong/test/test.cpp +442 -0
  470. package/numkong/test/test.hpp +580 -0
  471. package/numkong/test/test.mjs +363 -0
  472. package/numkong/test/test_base.py +1041 -0
  473. package/numkong/test/test_cast.cpp +242 -0
  474. package/numkong/test/test_cross.hpp +551 -0
  475. package/numkong/test/test_cross.py +467 -0
  476. package/numkong/test/test_cross_amx.cpp +50 -0
  477. package/numkong/test/test_cross_arm.cpp +225 -0
  478. package/numkong/test/test_cross_blas.cpp +354 -0
  479. package/numkong/test/test_cross_loongarch.cpp +90 -0
  480. package/numkong/test/test_cross_power.cpp +73 -0
  481. package/numkong/test/test_cross_rvv.cpp +109 -0
  482. package/numkong/test/test_cross_serial.cpp +181 -0
  483. package/numkong/test/test_cross_sme.cpp +148 -0
  484. package/numkong/test/test_cross_wasm.cpp +141 -0
  485. package/numkong/test/test_cross_x86.cpp +442 -0
  486. package/numkong/test/test_curved.cpp +182 -0
  487. package/numkong/test/test_curved.py +207 -0
  488. package/numkong/test/test_dot.cpp +353 -0
  489. package/numkong/test/test_dot.py +296 -0
  490. package/numkong/test/test_each.cpp +437 -0
  491. package/numkong/test/test_each.py +756 -0
  492. package/numkong/test/test_geospatial.cpp +155 -0
  493. package/numkong/test/test_geospatial.py +241 -0
  494. package/numkong/test/test_maxsim.cpp +138 -0
  495. package/numkong/test/test_maxsim.py +209 -0
  496. package/numkong/test/test_mesh.cpp +203 -0
  497. package/numkong/test/test_mesh.py +394 -0
  498. package/numkong/test/test_probability.cpp +136 -0
  499. package/numkong/test/test_probability.py +166 -0
  500. package/numkong/test/test_reduce.cpp +563 -0
  501. package/numkong/test/test_reduce.py +781 -0
  502. package/numkong/test/test_set.cpp +151 -0
  503. package/numkong/test/test_set.py +120 -0
  504. package/numkong/test/test_similarities.py +579 -0
  505. package/numkong/test/test_sparse.cpp +121 -0
  506. package/numkong/test/test_sparse.py +118 -0
  507. package/numkong/test/test_spatial.cpp +518 -0
  508. package/numkong/test/test_spatial.py +269 -0
  509. package/numkong/test/test_tensor.cpp +884 -0
  510. package/numkong/test/test_tensor.py +1417 -0
  511. package/numkong/test/test_trigonometry.cpp +156 -0
  512. package/numkong/test/test_trigonometry.py +180 -0
  513. package/package.json +7 -8
  514. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  515. package/prebuilds/linux-arm64/usearch.node +0 -0
  516. package/prebuilds/linux-x64/usearch.node +0 -0
  517. package/fp16/CMakeLists.txt +0 -176
  518. package/fp16/LICENSE +0 -11
  519. package/fp16/README.md +0 -20
  520. package/fp16/bench/alt-element.cc +0 -89
  521. package/fp16/bench/from-alt-array.cc +0 -175
  522. package/fp16/bench/from-ieee-array.cc +0 -399
  523. package/fp16/bench/ieee-element.cc +0 -272
  524. package/fp16/bench/to-alt-array.cc +0 -91
  525. package/fp16/bench/to-ieee-array.cc +0 -303
  526. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  527. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  528. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  529. package/fp16/configure.py +0 -65
  530. package/fp16/confu.yaml +0 -8
  531. package/fp16/include/fp16/__init__.py +0 -0
  532. package/fp16/include/fp16/avx.py +0 -50
  533. package/fp16/include/fp16/avx2.py +0 -53
  534. package/fp16/include/fp16/bitcasts.h +0 -92
  535. package/fp16/include/fp16/fp16.h +0 -451
  536. package/fp16/include/fp16/psimd.h +0 -131
  537. package/fp16/include/fp16.h +0 -11
  538. package/fp16/jni/Android.mk +0 -6
  539. package/fp16/jni/Application.mk +0 -4
  540. package/fp16/test/alt-from-fp32-value.cc +0 -498
  541. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  542. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  543. package/fp16/test/alt-to-fp32-value.cc +0 -348
  544. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  545. package/fp16/test/bitcasts.cc +0 -56
  546. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  547. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  548. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  549. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  550. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  551. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  552. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  553. package/fp16/test/peachpy/stubs.py +0 -38
  554. package/fp16/test/tables.cc +0 -530
  555. package/fp16/test/tables.h +0 -13
  556. package/fp16/third-party/THHalf.h +0 -92
  557. package/fp16/third-party/eigen-half.h +0 -170
  558. package/fp16/third-party/float16-compressor.h +0 -80
  559. package/fp16/third-party/half.hpp +0 -2916
  560. package/fp16/third-party/npy-halffloat.h +0 -328
  561. package/simsimd/.git-blame-ignore-revs +0 -2
  562. package/simsimd/CONTRIBUTING.md +0 -321
  563. package/simsimd/Cargo.toml +0 -49
  564. package/simsimd/MANIFEST.in +0 -4
  565. package/simsimd/Package.swift +0 -28
  566. package/simsimd/README.md +0 -1493
  567. package/simsimd/binding.gyp +0 -35
  568. package/simsimd/build.rs +0 -70
  569. package/simsimd/c/lib.c +0 -374
  570. package/simsimd/include/module.modulemap +0 -4
  571. package/simsimd/include/simsimd/binary.h +0 -486
  572. package/simsimd/include/simsimd/curved.h +0 -1541
  573. package/simsimd/include/simsimd/dot.h +0 -1853
  574. package/simsimd/include/simsimd/elementwise.h +0 -2465
  575. package/simsimd/include/simsimd/geospatial.h +0 -43
  576. package/simsimd/include/simsimd/mesh.h +0 -69
  577. package/simsimd/include/simsimd/probability.h +0 -606
  578. package/simsimd/include/simsimd/simsimd.h +0 -2567
  579. package/simsimd/include/simsimd/sparse.h +0 -1384
  580. package/simsimd/include/simsimd/spatial.h +0 -2335
  581. package/simsimd/include/simsimd/types.h +0 -666
  582. package/simsimd/javascript/fallback.ts +0 -233
  583. package/simsimd/javascript/lib.c +0 -125
  584. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  585. package/simsimd/javascript/simsimd.ts +0 -179
  586. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  587. package/simsimd/package-lock.json +0 -1761
  588. package/simsimd/package.json +0 -61
  589. package/simsimd/rust/lib.rs +0 -1821
  590. package/simsimd/scripts/bench.cxx +0 -1170
  591. package/simsimd/scripts/bench.ipynb +0 -187
  592. package/simsimd/scripts/bench.js +0 -127
  593. package/simsimd/scripts/bench.rs +0 -876
  594. package/simsimd/scripts/bench_vectors.py +0 -734
  595. package/simsimd/scripts/bench_vectors_live.py +0 -213
  596. package/simsimd/scripts/test.c +0 -187
  597. package/simsimd/scripts/test.mjs +0 -220
  598. package/simsimd/scripts/test.py +0 -1505
  599. package/simsimd/swift/SimSIMD.swift +0 -149
  600. package/simsimd/swift/Test.swift +0 -128
  601. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  602. /package/{simsimd → numkong}/LICENSE +0 -0
  603. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  604. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,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