usearch 2.21.4 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) hide show
  1. package/README.md +24 -24
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +7 -7
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +83 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +224 -48
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/dist/cjs/usearch.d.ts +8 -3
  16. package/javascript/dist/cjs/usearch.js +12 -4
  17. package/javascript/dist/esm/usearch.d.ts +8 -3
  18. package/javascript/dist/esm/usearch.js +12 -4
  19. package/javascript/lib.cpp +17 -0
  20. package/javascript/usearch.ts +14 -6
  21. package/numkong/.clang-tidy +30 -0
  22. package/{simsimd → numkong}/.cmake-format.py +18 -0
  23. package/numkong/.editorconfig +12 -0
  24. package/numkong/.git-blame-ignore-revs +123 -0
  25. package/numkong/.mailmap +15 -0
  26. package/numkong/.spi.yml +11 -0
  27. package/numkong/.swift-format +14 -0
  28. package/numkong/CITATION.cff +81 -0
  29. package/numkong/CONTRIBUTING.md +500 -0
  30. package/numkong/Cargo.toml +54 -0
  31. package/numkong/MANIFEST.in +8 -0
  32. package/numkong/Package.swift +84 -0
  33. package/numkong/README.md +569 -0
  34. package/numkong/bench/README.md +217 -0
  35. package/numkong/bench/bench-browser.html +323 -0
  36. package/numkong/bench/bench.cpp +344 -0
  37. package/numkong/bench/bench.hpp +816 -0
  38. package/numkong/bench/bench.js +148 -0
  39. package/numkong/bench/bench.mjs +616 -0
  40. package/numkong/bench/bench_attention.cpp +113 -0
  41. package/numkong/bench/bench_cast.cpp +264 -0
  42. package/numkong/bench/bench_cross_amx.cpp +62 -0
  43. package/numkong/bench/bench_cross_arm.cpp +245 -0
  44. package/numkong/bench/bench_cross_blas.cpp +309 -0
  45. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  46. package/numkong/bench/bench_cross_power.cpp +84 -0
  47. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  48. package/numkong/bench/bench_cross_serial.cpp +151 -0
  49. package/numkong/bench/bench_cross_sme.cpp +163 -0
  50. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  51. package/numkong/bench/bench_cross_x86.cpp +455 -0
  52. package/numkong/bench/bench_curved.cpp +210 -0
  53. package/numkong/bench/bench_dot.cpp +315 -0
  54. package/numkong/bench/bench_each.cpp +503 -0
  55. package/numkong/bench/bench_geospatial.cpp +112 -0
  56. package/numkong/bench/bench_maxsim.cpp +154 -0
  57. package/numkong/bench/bench_mesh.cpp +148 -0
  58. package/numkong/bench/bench_probability.cpp +60 -0
  59. package/numkong/bench/bench_reduce.cpp +371 -0
  60. package/numkong/bench/bench_set.cpp +73 -0
  61. package/numkong/bench/bench_sparse.cpp +198 -0
  62. package/numkong/bench/bench_spatial.cpp +347 -0
  63. package/numkong/bench/bench_trigonometry.cpp +137 -0
  64. package/numkong/bench/swift/Bench.swift +506 -0
  65. package/numkong/binding.gyp +169 -0
  66. package/numkong/build.rs +484 -0
  67. package/numkong/c/dispatch.h +512 -0
  68. package/numkong/c/dispatch_bf16.c +447 -0
  69. package/numkong/c/dispatch_bf16c.c +52 -0
  70. package/numkong/c/dispatch_e2m3.c +296 -0
  71. package/numkong/c/dispatch_e3m2.c +284 -0
  72. package/numkong/c/dispatch_e4m3.c +318 -0
  73. package/numkong/c/dispatch_e5m2.c +316 -0
  74. package/numkong/c/dispatch_f16.c +452 -0
  75. package/numkong/c/dispatch_f16c.c +58 -0
  76. package/numkong/c/dispatch_f32.c +434 -0
  77. package/numkong/c/dispatch_f32c.c +99 -0
  78. package/numkong/c/dispatch_f64.c +348 -0
  79. package/numkong/c/dispatch_f64c.c +98 -0
  80. package/numkong/c/dispatch_i16.c +96 -0
  81. package/numkong/c/dispatch_i32.c +89 -0
  82. package/numkong/c/dispatch_i4.c +153 -0
  83. package/numkong/c/dispatch_i64.c +86 -0
  84. package/numkong/c/dispatch_i8.c +348 -0
  85. package/numkong/c/dispatch_other.c +348 -0
  86. package/numkong/c/dispatch_u1.c +193 -0
  87. package/numkong/c/dispatch_u16.c +124 -0
  88. package/numkong/c/dispatch_u32.c +118 -0
  89. package/numkong/c/dispatch_u4.c +153 -0
  90. package/numkong/c/dispatch_u64.c +102 -0
  91. package/numkong/c/dispatch_u8.c +364 -0
  92. package/numkong/c/numkong.c +940 -0
  93. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  94. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  95. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  96. package/numkong/cmake/nk_math_lib.cmake +46 -0
  97. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  99. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  100. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  101. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  102. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  103. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  104. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  105. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  106. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  107. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  108. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  109. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  110. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  111. package/numkong/include/README.md +643 -0
  112. package/numkong/include/module.modulemap +129 -0
  113. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  114. package/numkong/include/numkong/attention/sme.h +2075 -0
  115. package/numkong/include/numkong/attention.h +49 -0
  116. package/numkong/include/numkong/capabilities.h +930 -0
  117. package/numkong/include/numkong/cast/README.md +262 -0
  118. package/numkong/include/numkong/cast/diamond.h +64 -0
  119. package/numkong/include/numkong/cast/haswell.h +823 -0
  120. package/numkong/include/numkong/cast/icelake.h +475 -0
  121. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  122. package/numkong/include/numkong/cast/neon.h +1174 -0
  123. package/numkong/include/numkong/cast/powervsx.h +449 -0
  124. package/numkong/include/numkong/cast/rvv.h +970 -0
  125. package/numkong/include/numkong/cast/sapphire.h +262 -0
  126. package/numkong/include/numkong/cast/serial.h +2336 -0
  127. package/numkong/include/numkong/cast/skylake.h +915 -0
  128. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  129. package/numkong/include/numkong/cast.h +254 -0
  130. package/numkong/include/numkong/cast.hpp +44 -0
  131. package/numkong/include/numkong/curved/README.md +223 -0
  132. package/numkong/include/numkong/curved/genoa.h +182 -0
  133. package/numkong/include/numkong/curved/haswell.h +276 -0
  134. package/numkong/include/numkong/curved/neon.h +329 -0
  135. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  136. package/numkong/include/numkong/curved/rvv.h +305 -0
  137. package/numkong/include/numkong/curved/serial.h +207 -0
  138. package/numkong/include/numkong/curved/skylake.h +457 -0
  139. package/numkong/include/numkong/curved/smef64.h +530 -0
  140. package/numkong/include/numkong/curved.h +513 -0
  141. package/numkong/include/numkong/curved.hpp +144 -0
  142. package/numkong/include/numkong/dot/README.md +442 -0
  143. package/numkong/include/numkong/dot/alder.h +563 -0
  144. package/numkong/include/numkong/dot/diamond.h +158 -0
  145. package/numkong/include/numkong/dot/genoa.h +289 -0
  146. package/numkong/include/numkong/dot/haswell.h +1723 -0
  147. package/numkong/include/numkong/dot/icelake.h +997 -0
  148. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  149. package/numkong/include/numkong/dot/neon.h +869 -0
  150. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  151. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  152. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  153. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  154. package/numkong/include/numkong/dot/powervsx.h +752 -0
  155. package/numkong/include/numkong/dot/rvv.h +722 -0
  156. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  157. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  158. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  159. package/numkong/include/numkong/dot/sapphire.h +141 -0
  160. package/numkong/include/numkong/dot/serial.h +874 -0
  161. package/numkong/include/numkong/dot/sierra.h +405 -0
  162. package/numkong/include/numkong/dot/skylake.h +1116 -0
  163. package/numkong/include/numkong/dot/sve.h +420 -0
  164. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  165. package/numkong/include/numkong/dot/svehalf.h +168 -0
  166. package/numkong/include/numkong/dot/svesdot.h +90 -0
  167. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  168. package/numkong/include/numkong/dot.h +1136 -0
  169. package/numkong/include/numkong/dot.hpp +94 -0
  170. package/numkong/include/numkong/dots/README.md +496 -0
  171. package/numkong/include/numkong/dots/alder.h +117 -0
  172. package/numkong/include/numkong/dots/diamond.h +86 -0
  173. package/numkong/include/numkong/dots/genoa.h +100 -0
  174. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  175. package/numkong/include/numkong/dots/haswell.h +310 -0
  176. package/numkong/include/numkong/dots/icelake.h +180 -0
  177. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  178. package/numkong/include/numkong/dots/neon.h +123 -0
  179. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  180. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  181. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  182. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  183. package/numkong/include/numkong/dots/powervsx.h +194 -0
  184. package/numkong/include/numkong/dots/rvv.h +2593 -0
  185. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  186. package/numkong/include/numkong/dots/serial.h +2867 -0
  187. package/numkong/include/numkong/dots/sierra.h +100 -0
  188. package/numkong/include/numkong/dots/skylake.h +207 -0
  189. package/numkong/include/numkong/dots/sme.h +5041 -0
  190. package/numkong/include/numkong/dots/smebi32.h +477 -0
  191. package/numkong/include/numkong/dots/smef64.h +1328 -0
  192. package/numkong/include/numkong/dots/smehalf.h +47 -0
  193. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  194. package/numkong/include/numkong/dots.h +3110 -0
  195. package/numkong/include/numkong/dots.hpp +641 -0
  196. package/numkong/include/numkong/each/README.md +465 -0
  197. package/numkong/include/numkong/each/haswell.h +1658 -0
  198. package/numkong/include/numkong/each/icelake.h +272 -0
  199. package/numkong/include/numkong/each/neon.h +1138 -0
  200. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  201. package/numkong/include/numkong/each/neonhalf.h +318 -0
  202. package/numkong/include/numkong/each/rvv.h +1121 -0
  203. package/numkong/include/numkong/each/sapphire.h +343 -0
  204. package/numkong/include/numkong/each/serial.h +282 -0
  205. package/numkong/include/numkong/each/skylake.h +1562 -0
  206. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  207. package/numkong/include/numkong/each.h +2232 -0
  208. package/numkong/include/numkong/each.hpp +434 -0
  209. package/numkong/include/numkong/geospatial/README.md +147 -0
  210. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  211. package/numkong/include/numkong/geospatial/neon.h +615 -0
  212. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  213. package/numkong/include/numkong/geospatial/serial.h +309 -0
  214. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  215. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  216. package/numkong/include/numkong/geospatial.h +453 -0
  217. package/numkong/include/numkong/geospatial.hpp +235 -0
  218. package/numkong/include/numkong/matrix.hpp +336 -0
  219. package/numkong/include/numkong/maxsim/README.md +187 -0
  220. package/numkong/include/numkong/maxsim/alder.h +511 -0
  221. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  222. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  223. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  224. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  225. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  226. package/numkong/include/numkong/maxsim/serial.h +490 -0
  227. package/numkong/include/numkong/maxsim/sme.h +993 -0
  228. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  229. package/numkong/include/numkong/maxsim.h +571 -0
  230. package/numkong/include/numkong/maxsim.hpp +133 -0
  231. package/numkong/include/numkong/mesh/README.md +219 -0
  232. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  233. package/numkong/include/numkong/mesh/neon.h +1821 -0
  234. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  235. package/numkong/include/numkong/mesh/rvv.h +936 -0
  236. package/numkong/include/numkong/mesh/serial.h +721 -0
  237. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  238. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  239. package/numkong/include/numkong/mesh.h +666 -0
  240. package/numkong/include/numkong/mesh.hpp +701 -0
  241. package/numkong/include/numkong/numkong.h +78 -0
  242. package/numkong/include/numkong/numkong.hpp +58 -0
  243. package/numkong/include/numkong/probability/README.md +177 -0
  244. package/numkong/include/numkong/probability/haswell.h +267 -0
  245. package/numkong/include/numkong/probability/neon.h +255 -0
  246. package/numkong/include/numkong/probability/rvv.h +414 -0
  247. package/numkong/include/numkong/probability/serial.h +181 -0
  248. package/numkong/include/numkong/probability/skylake.h +324 -0
  249. package/numkong/include/numkong/probability.h +380 -0
  250. package/numkong/include/numkong/probability.hpp +120 -0
  251. package/numkong/include/numkong/random.h +50 -0
  252. package/numkong/include/numkong/random.hpp +285 -0
  253. package/numkong/include/numkong/reduce/README.md +552 -0
  254. package/numkong/include/numkong/reduce/alder.h +636 -0
  255. package/numkong/include/numkong/reduce/genoa.h +201 -0
  256. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  257. package/numkong/include/numkong/reduce/icelake.h +549 -0
  258. package/numkong/include/numkong/reduce/neon.h +3980 -0
  259. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  260. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  261. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  262. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  263. package/numkong/include/numkong/reduce/serial.h +753 -0
  264. package/numkong/include/numkong/reduce/sierra.h +338 -0
  265. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  266. package/numkong/include/numkong/reduce/sve.h +52 -0
  267. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  268. package/numkong/include/numkong/reduce.h +1582 -0
  269. package/numkong/include/numkong/reduce.hpp +778 -0
  270. package/numkong/include/numkong/scalar/README.md +89 -0
  271. package/numkong/include/numkong/scalar/haswell.h +122 -0
  272. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  273. package/numkong/include/numkong/scalar/neon.h +122 -0
  274. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  275. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  276. package/numkong/include/numkong/scalar/rvv.h +211 -0
  277. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  278. package/numkong/include/numkong/scalar/serial.h +332 -0
  279. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  280. package/numkong/include/numkong/scalar.h +696 -0
  281. package/numkong/include/numkong/set/README.md +179 -0
  282. package/numkong/include/numkong/set/haswell.h +334 -0
  283. package/numkong/include/numkong/set/icelake.h +485 -0
  284. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  285. package/numkong/include/numkong/set/neon.h +363 -0
  286. package/numkong/include/numkong/set/powervsx.h +326 -0
  287. package/numkong/include/numkong/set/rvv.h +226 -0
  288. package/numkong/include/numkong/set/rvvbb.h +117 -0
  289. package/numkong/include/numkong/set/serial.h +174 -0
  290. package/numkong/include/numkong/set/sve.h +187 -0
  291. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  292. package/numkong/include/numkong/set.h +471 -0
  293. package/numkong/include/numkong/set.hpp +114 -0
  294. package/numkong/include/numkong/sets/README.md +149 -0
  295. package/numkong/include/numkong/sets/haswell.h +63 -0
  296. package/numkong/include/numkong/sets/icelake.h +66 -0
  297. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  298. package/numkong/include/numkong/sets/neon.h +61 -0
  299. package/numkong/include/numkong/sets/powervsx.h +65 -0
  300. package/numkong/include/numkong/sets/serial.h +43 -0
  301. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  302. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  303. package/numkong/include/numkong/sets.h +382 -0
  304. package/numkong/include/numkong/sparse/README.md +156 -0
  305. package/numkong/include/numkong/sparse/icelake.h +463 -0
  306. package/numkong/include/numkong/sparse/neon.h +288 -0
  307. package/numkong/include/numkong/sparse/serial.h +117 -0
  308. package/numkong/include/numkong/sparse/sve2.h +504 -0
  309. package/numkong/include/numkong/sparse/turin.h +322 -0
  310. package/numkong/include/numkong/sparse.h +363 -0
  311. package/numkong/include/numkong/sparse.hpp +113 -0
  312. package/numkong/include/numkong/spatial/README.md +439 -0
  313. package/numkong/include/numkong/spatial/alder.h +604 -0
  314. package/numkong/include/numkong/spatial/diamond.h +240 -0
  315. package/numkong/include/numkong/spatial/genoa.h +222 -0
  316. package/numkong/include/numkong/spatial/haswell.h +979 -0
  317. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  318. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  319. package/numkong/include/numkong/spatial/neon.h +846 -0
  320. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  321. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  322. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  323. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  324. package/numkong/include/numkong/spatial/rvv.h +991 -0
  325. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  326. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  327. package/numkong/include/numkong/spatial/serial.h +347 -0
  328. package/numkong/include/numkong/spatial/sierra.h +516 -0
  329. package/numkong/include/numkong/spatial/skylake.h +605 -0
  330. package/numkong/include/numkong/spatial/sve.h +246 -0
  331. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  332. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  333. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  334. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  335. package/numkong/include/numkong/spatial.h +1681 -0
  336. package/numkong/include/numkong/spatial.hpp +183 -0
  337. package/numkong/include/numkong/spatials/README.md +580 -0
  338. package/numkong/include/numkong/spatials/alder.h +94 -0
  339. package/numkong/include/numkong/spatials/diamond.h +82 -0
  340. package/numkong/include/numkong/spatials/genoa.h +94 -0
  341. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  342. package/numkong/include/numkong/spatials/haswell.h +219 -0
  343. package/numkong/include/numkong/spatials/icelake.h +113 -0
  344. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  345. package/numkong/include/numkong/spatials/neon.h +109 -0
  346. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  347. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  348. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  349. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  350. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  351. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  352. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  353. package/numkong/include/numkong/spatials/serial.h +248 -0
  354. package/numkong/include/numkong/spatials/sierra.h +96 -0
  355. package/numkong/include/numkong/spatials/skylake.h +184 -0
  356. package/numkong/include/numkong/spatials/sme.h +1927 -0
  357. package/numkong/include/numkong/spatials/smef64.h +483 -0
  358. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  359. package/numkong/include/numkong/spatials.h +3374 -0
  360. package/numkong/include/numkong/spatials.hpp +509 -0
  361. package/numkong/include/numkong/tensor.hpp +1981 -0
  362. package/numkong/include/numkong/trigonometry/README.md +184 -0
  363. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  364. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  365. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  366. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  367. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  368. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  369. package/numkong/include/numkong/trigonometry.h +467 -0
  370. package/numkong/include/numkong/trigonometry.hpp +166 -0
  371. package/numkong/include/numkong/types.h +1695 -0
  372. package/numkong/include/numkong/types.hpp +6027 -0
  373. package/numkong/include/numkong/vector.hpp +766 -0
  374. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  375. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  376. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  377. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  378. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  380. package/numkong/javascript/README.md +254 -0
  381. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  382. package/numkong/javascript/numkong-browser.ts +40 -0
  383. package/numkong/javascript/numkong-wasm.ts +750 -0
  384. package/numkong/javascript/numkong.c +712 -0
  385. package/numkong/javascript/numkong.ts +613 -0
  386. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  387. package/numkong/javascript/tsconfig-cjs.json +13 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  389. package/numkong/javascript/types.ts +784 -0
  390. package/numkong/numkong.gypi +104 -0
  391. package/numkong/package.json +108 -0
  392. package/numkong/probes/arm_neon.c +8 -0
  393. package/numkong/probes/arm_neon_bfdot.c +9 -0
  394. package/numkong/probes/arm_neon_fhm.c +9 -0
  395. package/numkong/probes/arm_neon_half.c +8 -0
  396. package/numkong/probes/arm_neon_sdot.c +9 -0
  397. package/numkong/probes/arm_neonfp8.c +9 -0
  398. package/numkong/probes/arm_sme.c +16 -0
  399. package/numkong/probes/arm_sme2.c +16 -0
  400. package/numkong/probes/arm_sme2p1.c +16 -0
  401. package/numkong/probes/arm_sme_bf16.c +16 -0
  402. package/numkong/probes/arm_sme_bi32.c +16 -0
  403. package/numkong/probes/arm_sme_f64.c +16 -0
  404. package/numkong/probes/arm_sme_fa64.c +14 -0
  405. package/numkong/probes/arm_sme_half.c +16 -0
  406. package/numkong/probes/arm_sme_lut2.c +15 -0
  407. package/numkong/probes/arm_sve.c +18 -0
  408. package/numkong/probes/arm_sve2.c +20 -0
  409. package/numkong/probes/arm_sve2p1.c +18 -0
  410. package/numkong/probes/arm_sve_bfdot.c +20 -0
  411. package/numkong/probes/arm_sve_half.c +18 -0
  412. package/numkong/probes/arm_sve_sdot.c +21 -0
  413. package/numkong/probes/loongarch_lasx.c +12 -0
  414. package/numkong/probes/power_vsx.c +12 -0
  415. package/numkong/probes/probe.js +127 -0
  416. package/numkong/probes/riscv_rvv.c +14 -0
  417. package/numkong/probes/riscv_rvv_bb.c +15 -0
  418. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  419. package/numkong/probes/riscv_rvv_half.c +14 -0
  420. package/numkong/probes/wasm_v128relaxed.c +11 -0
  421. package/numkong/probes/x86_alder.c +17 -0
  422. package/numkong/probes/x86_diamond.c +17 -0
  423. package/numkong/probes/x86_genoa.c +17 -0
  424. package/numkong/probes/x86_graniteamx.c +19 -0
  425. package/numkong/probes/x86_haswell.c +11 -0
  426. package/numkong/probes/x86_icelake.c +17 -0
  427. package/numkong/probes/x86_sapphire.c +16 -0
  428. package/numkong/probes/x86_sapphireamx.c +18 -0
  429. package/numkong/probes/x86_sierra.c +17 -0
  430. package/numkong/probes/x86_skylake.c +15 -0
  431. package/numkong/probes/x86_turin.c +17 -0
  432. package/numkong/rust/README.md +698 -0
  433. package/numkong/rust/capabilities.rs +96 -0
  434. package/numkong/rust/cast.rs +314 -0
  435. package/numkong/rust/curved.rs +391 -0
  436. package/numkong/rust/each.rs +2721 -0
  437. package/numkong/rust/geospatial.rs +343 -0
  438. package/numkong/rust/matrix.rs +5424 -0
  439. package/numkong/rust/maxsim.rs +540 -0
  440. package/numkong/rust/mesh.rs +837 -0
  441. package/numkong/rust/numkong.rs +409 -0
  442. package/numkong/rust/probability.rs +272 -0
  443. package/numkong/rust/reduce.rs +1249 -0
  444. package/numkong/rust/set.rs +194 -0
  445. package/numkong/rust/sparse.rs +513 -0
  446. package/numkong/rust/spatial.rs +1815 -0
  447. package/numkong/rust/tensor.rs +7565 -0
  448. package/numkong/rust/types.rs +3666 -0
  449. package/numkong/rust/vector.rs +1899 -0
  450. package/numkong/rustfmt.toml +2 -0
  451. package/numkong/swift/Matrix.swift +1388 -0
  452. package/numkong/swift/MaxSim.swift +151 -0
  453. package/numkong/swift/NumKong.swift +283 -0
  454. package/numkong/swift/Numerics.swift +329 -0
  455. package/numkong/swift/README.md +433 -0
  456. package/numkong/swift/Scalar.swift +741 -0
  457. package/numkong/swift/Tensor.swift +209 -0
  458. package/numkong/test/README.md +315 -0
  459. package/numkong/test/playwright.config.ts +16 -0
  460. package/numkong/test/swift/Test.swift +534 -0
  461. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  462. package/numkong/test/test-browser-bundle.html +188 -0
  463. package/numkong/test/test-browser-runner.mjs +43 -0
  464. package/numkong/test/test-browser.html +305 -0
  465. package/numkong/test/test-dtypes.mjs +453 -0
  466. package/numkong/test/test-wasm.mjs +267 -0
  467. package/numkong/test/test.cpp +442 -0
  468. package/numkong/test/test.hpp +580 -0
  469. package/numkong/test/test.mjs +363 -0
  470. package/numkong/test/test_base.py +1041 -0
  471. package/numkong/test/test_cast.cpp +242 -0
  472. package/numkong/test/test_cross.hpp +551 -0
  473. package/numkong/test/test_cross.py +467 -0
  474. package/numkong/test/test_cross_amx.cpp +50 -0
  475. package/numkong/test/test_cross_arm.cpp +225 -0
  476. package/numkong/test/test_cross_blas.cpp +354 -0
  477. package/numkong/test/test_cross_loongarch.cpp +90 -0
  478. package/numkong/test/test_cross_power.cpp +73 -0
  479. package/numkong/test/test_cross_rvv.cpp +109 -0
  480. package/numkong/test/test_cross_serial.cpp +181 -0
  481. package/numkong/test/test_cross_sme.cpp +148 -0
  482. package/numkong/test/test_cross_wasm.cpp +141 -0
  483. package/numkong/test/test_cross_x86.cpp +442 -0
  484. package/numkong/test/test_curved.cpp +182 -0
  485. package/numkong/test/test_curved.py +207 -0
  486. package/numkong/test/test_dot.cpp +353 -0
  487. package/numkong/test/test_dot.py +296 -0
  488. package/numkong/test/test_each.cpp +437 -0
  489. package/numkong/test/test_each.py +756 -0
  490. package/numkong/test/test_geospatial.cpp +155 -0
  491. package/numkong/test/test_geospatial.py +241 -0
  492. package/numkong/test/test_maxsim.cpp +138 -0
  493. package/numkong/test/test_maxsim.py +209 -0
  494. package/numkong/test/test_mesh.cpp +203 -0
  495. package/numkong/test/test_mesh.py +394 -0
  496. package/numkong/test/test_probability.cpp +136 -0
  497. package/numkong/test/test_probability.py +166 -0
  498. package/numkong/test/test_reduce.cpp +563 -0
  499. package/numkong/test/test_reduce.py +781 -0
  500. package/numkong/test/test_set.cpp +151 -0
  501. package/numkong/test/test_set.py +120 -0
  502. package/numkong/test/test_similarities.py +579 -0
  503. package/numkong/test/test_sparse.cpp +121 -0
  504. package/numkong/test/test_sparse.py +118 -0
  505. package/numkong/test/test_spatial.cpp +518 -0
  506. package/numkong/test/test_spatial.py +269 -0
  507. package/numkong/test/test_tensor.cpp +884 -0
  508. package/numkong/test/test_tensor.py +1417 -0
  509. package/numkong/test/test_trigonometry.cpp +156 -0
  510. package/numkong/test/test_trigonometry.py +180 -0
  511. package/package.json +7 -8
  512. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  513. package/prebuilds/linux-arm64/usearch.node +0 -0
  514. package/prebuilds/linux-x64/usearch.node +0 -0
  515. package/fp16/CMakeLists.txt +0 -176
  516. package/fp16/LICENSE +0 -11
  517. package/fp16/README.md +0 -20
  518. package/fp16/bench/alt-element.cc +0 -89
  519. package/fp16/bench/from-alt-array.cc +0 -175
  520. package/fp16/bench/from-ieee-array.cc +0 -399
  521. package/fp16/bench/ieee-element.cc +0 -272
  522. package/fp16/bench/to-alt-array.cc +0 -91
  523. package/fp16/bench/to-ieee-array.cc +0 -303
  524. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  525. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  526. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  527. package/fp16/configure.py +0 -65
  528. package/fp16/confu.yaml +0 -8
  529. package/fp16/include/fp16/__init__.py +0 -0
  530. package/fp16/include/fp16/avx.py +0 -50
  531. package/fp16/include/fp16/avx2.py +0 -53
  532. package/fp16/include/fp16/bitcasts.h +0 -92
  533. package/fp16/include/fp16/fp16.h +0 -451
  534. package/fp16/include/fp16/psimd.h +0 -131
  535. package/fp16/include/fp16.h +0 -11
  536. package/fp16/jni/Android.mk +0 -6
  537. package/fp16/jni/Application.mk +0 -4
  538. package/fp16/test/alt-from-fp32-value.cc +0 -498
  539. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  540. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  541. package/fp16/test/alt-to-fp32-value.cc +0 -348
  542. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  543. package/fp16/test/bitcasts.cc +0 -56
  544. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  545. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  546. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  547. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  548. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  549. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  550. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  551. package/fp16/test/peachpy/stubs.py +0 -38
  552. package/fp16/test/tables.cc +0 -530
  553. package/fp16/test/tables.h +0 -13
  554. package/fp16/third-party/THHalf.h +0 -92
  555. package/fp16/third-party/eigen-half.h +0 -170
  556. package/fp16/third-party/float16-compressor.h +0 -80
  557. package/fp16/third-party/half.hpp +0 -2916
  558. package/fp16/third-party/npy-halffloat.h +0 -328
  559. package/simsimd/.git-blame-ignore-revs +0 -2
  560. package/simsimd/CONTRIBUTING.md +0 -321
  561. package/simsimd/Cargo.toml +0 -49
  562. package/simsimd/MANIFEST.in +0 -4
  563. package/simsimd/Package.swift +0 -28
  564. package/simsimd/README.md +0 -1493
  565. package/simsimd/binding.gyp +0 -35
  566. package/simsimd/build.rs +0 -70
  567. package/simsimd/c/lib.c +0 -374
  568. package/simsimd/include/module.modulemap +0 -4
  569. package/simsimd/include/simsimd/binary.h +0 -486
  570. package/simsimd/include/simsimd/curved.h +0 -1541
  571. package/simsimd/include/simsimd/dot.h +0 -1853
  572. package/simsimd/include/simsimd/elementwise.h +0 -2465
  573. package/simsimd/include/simsimd/geospatial.h +0 -43
  574. package/simsimd/include/simsimd/mesh.h +0 -69
  575. package/simsimd/include/simsimd/probability.h +0 -606
  576. package/simsimd/include/simsimd/simsimd.h +0 -2567
  577. package/simsimd/include/simsimd/sparse.h +0 -1384
  578. package/simsimd/include/simsimd/spatial.h +0 -2335
  579. package/simsimd/include/simsimd/types.h +0 -666
  580. package/simsimd/javascript/fallback.ts +0 -233
  581. package/simsimd/javascript/lib.c +0 -125
  582. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  583. package/simsimd/javascript/simsimd.ts +0 -179
  584. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  585. package/simsimd/package-lock.json +0 -1761
  586. package/simsimd/package.json +0 -61
  587. package/simsimd/rust/lib.rs +0 -1821
  588. package/simsimd/scripts/bench.cxx +0 -1170
  589. package/simsimd/scripts/bench.ipynb +0 -187
  590. package/simsimd/scripts/bench.js +0 -127
  591. package/simsimd/scripts/bench.rs +0 -876
  592. package/simsimd/scripts/bench_vectors.py +0 -734
  593. package/simsimd/scripts/bench_vectors_live.py +0 -213
  594. package/simsimd/scripts/test.c +0 -187
  595. package/simsimd/scripts/test.mjs +0 -220
  596. package/simsimd/scripts/test.py +0 -1505
  597. package/simsimd/swift/SimSIMD.swift +0 -149
  598. package/simsimd/swift/Test.swift +0 -128
  599. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  600. /package/{simsimd → numkong}/LICENSE +0 -0
  601. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  602. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,211 @@
1
+ /**
2
+ * @brief SIMD-accelerated Elementwise Arithmetic for NEON BF16.
3
+ * @file include/numkong/each/neonbfdot.h
4
+ * @author Ash Vardanian
5
+ * @date December 27, 2025
6
+ *
7
+ * @sa include/numkong/each.h
8
+ *
9
+ * @section elementwise_neonbfdot_instructions ARM NEON BF16 Instructions (ARMv8.6-BF16)
10
+ *
11
+ * Intrinsic Instruction A76 M5
12
+ * vld1_bf16 LD1 (V.4H) 4cy @ 2p 4cy @ 3p
13
+ * vst1_bf16 ST1 (V.4H) 2cy @ 2p 2cy @ 3p
14
+ * vcvt_f32_bf16 BFCVTN (V.4H, V.4S) 3cy @ 2p 3cy @ 4p
15
+ * vcvt_bf16_f32 BFCVT (V.4H, V.4S) 3cy @ 2p 3cy @ 4p
16
+ * vaddq_f32 FADD (V.4S, V.4S, V.4S) 2cy @ 2p 2cy @ 4p
17
+ * vmulq_f32 FMUL (V.4S, V.4S, V.4S) 3cy @ 2p 3cy @ 4p
18
+ * vmulq_n_f32 FMUL (V.4S, V.4S, scalar) 3cy @ 2p 3cy @ 4p
19
+ * vfmaq_f32 FMLA (V.4S, V.4S, V.4S) 4cy @ 2p 3cy @ 4p
20
+ * vfmaq_n_f32 FMLA (V.4S, V.4S, scalar) 4cy @ 2p 3cy @ 4p
21
+ * vdupq_n_f32 DUP (V.4S, scalar) 2cy @ 2p 2cy @ 4p
22
+ *
23
+ * The ARMv8.6-BF16 extension provides element-wise operations on BF16 data by converting to F32
24
+ * for arithmetic, then back to BF16 for storage. This preserves the dynamic range benefits of BF16
25
+ * (matching F32 exponent) while using F32 precision for intermediate calculations.
26
+ *
27
+ * Operations process 4 BF16 elements at a time, widening to F32 for computation. While this gives
28
+ * lower throughput than native F16 operations, it prevents overflow issues common with FP16's
29
+ * limited exponent range in ML training workloads.
30
+ */
31
+ #ifndef NK_EACH_NEONBFDOT_H
32
+ #define NK_EACH_NEONBFDOT_H
33
+
34
+ #if NK_TARGET_ARM64_
35
+ #if NK_TARGET_NEONBFDOT
36
+
37
+ #include "numkong/types.h"
38
+ #include "numkong/cast/serial.h"
39
+
40
+ #if defined(__cplusplus)
41
+ extern "C" {
42
+ #endif
43
+
44
+ #if defined(__clang__)
45
+ #pragma clang attribute push(__attribute__((target("arch=armv8.6-a+simd+bf16"))), apply_to = function)
46
+ #elif defined(__GNUC__)
47
+ #pragma GCC push_options
48
+ #pragma GCC target("arch=armv8.6-a+simd+bf16")
49
+ #endif
50
+
51
+ NK_PUBLIC void nk_each_sum_bf16_neonbfdot(nk_bf16_t const *a, nk_bf16_t const *b, nk_size_t n, nk_bf16_t *result) {
52
+ nk_size_t i = 0;
53
+ for (; i + 4 <= n; i += 4) {
54
+ bfloat16x4_t a_bf16x4 = vld1_bf16((bfloat16_t const *)a + i);
55
+ bfloat16x4_t b_bf16x4 = vld1_bf16((bfloat16_t const *)b + i);
56
+ float32x4_t a_f32x4 = vcvt_f32_bf16(a_bf16x4);
57
+ float32x4_t b_f32x4 = vcvt_f32_bf16(b_bf16x4);
58
+ float32x4_t result_f32x4 = vaddq_f32(a_f32x4, b_f32x4);
59
+ bfloat16x4_t result_bf16x4 = vcvt_bf16_f32(result_f32x4);
60
+ vst1_bf16((bfloat16_t *)result + i, result_bf16x4);
61
+ }
62
+ if (i < n) {
63
+ nk_b64_vec_t a_tail, b_tail;
64
+ nk_partial_load_b16x4_serial_(a + i, &a_tail, n - i);
65
+ nk_partial_load_b16x4_serial_(b + i, &b_tail, n - i);
66
+ bfloat16x4_t a_bf16x4 = vreinterpret_bf16_u16(a_tail.u16x4);
67
+ bfloat16x4_t b_bf16x4 = vreinterpret_bf16_u16(b_tail.u16x4);
68
+ float32x4_t a_f32x4 = vcvt_f32_bf16(a_bf16x4);
69
+ float32x4_t b_f32x4 = vcvt_f32_bf16(b_bf16x4);
70
+ float32x4_t result_f32x4 = vaddq_f32(a_f32x4, b_f32x4);
71
+ bfloat16x4_t result_bf16x4 = vcvt_bf16_f32(result_f32x4);
72
+ nk_b64_vec_t result_vec;
73
+ result_vec.u16x4 = vreinterpret_u16_bf16(result_bf16x4);
74
+ nk_partial_store_b16x4_serial_(result + i, &result_vec, n - i);
75
+ }
76
+ }
77
+
78
+ NK_PUBLIC void nk_each_scale_bf16_neonbfdot(nk_bf16_t const *a, nk_size_t n, nk_f32_t const *alpha,
79
+ nk_f32_t const *beta, nk_bf16_t *result) {
80
+ nk_f32_t alpha_val = *alpha;
81
+ nk_f32_t beta_val = *beta;
82
+ float32x4_t alpha_f32x4 = vdupq_n_f32(alpha_val);
83
+ float32x4_t beta_f32x4 = vdupq_n_f32(beta_val);
84
+ nk_size_t i = 0;
85
+ for (; i + 4 <= n; i += 4) {
86
+ bfloat16x4_t a_bf16x4 = vld1_bf16((bfloat16_t const *)a + i);
87
+ float32x4_t a_f32x4 = vcvt_f32_bf16(a_bf16x4);
88
+ float32x4_t result_f32x4 = vfmaq_f32(beta_f32x4, a_f32x4, alpha_f32x4);
89
+ bfloat16x4_t result_bf16x4 = vcvt_bf16_f32(result_f32x4);
90
+ vst1_bf16((bfloat16_t *)result + i, result_bf16x4);
91
+ }
92
+ if (i < n) {
93
+ nk_b64_vec_t a_tail;
94
+ nk_partial_load_b16x4_serial_(a + i, &a_tail, n - i);
95
+ bfloat16x4_t a_bf16x4 = vreinterpret_bf16_u16(a_tail.u16x4);
96
+ float32x4_t a_f32x4 = vcvt_f32_bf16(a_bf16x4);
97
+ float32x4_t result_f32x4 = vfmaq_f32(beta_f32x4, a_f32x4, alpha_f32x4);
98
+ bfloat16x4_t result_bf16x4 = vcvt_bf16_f32(result_f32x4);
99
+ nk_b64_vec_t result_vec;
100
+ result_vec.u16x4 = vreinterpret_u16_bf16(result_bf16x4);
101
+ nk_partial_store_b16x4_serial_(result + i, &result_vec, n - i);
102
+ }
103
+ }
104
+
105
+ NK_PUBLIC void nk_each_blend_bf16_neonbfdot( //
106
+ nk_bf16_t const *a, nk_bf16_t const *b, nk_size_t n, //
107
+ nk_f32_t const *alpha, nk_f32_t const *beta, nk_bf16_t *result) {
108
+
109
+ nk_f32_t alpha_val = *alpha;
110
+ nk_f32_t beta_val = *beta;
111
+
112
+ // There are several special cases we may want to implement:
113
+ // 1. Simple addition, when both weights are equal to 1.0.
114
+ if (alpha_val == 1 && beta_val == 1) {
115
+ // In this case we can avoid expensive multiplications.
116
+ nk_each_sum_bf16_neonbfdot(a, b, n, result);
117
+ return;
118
+ }
119
+ // 2. Just scaling, when one of the weights is equal to zero.
120
+ else if (alpha_val == 0 || beta_val == 0) {
121
+ // In this case we can avoid half of the load instructions.
122
+ nk_f32_t zero = 0;
123
+ if (beta_val == 0) { nk_each_scale_bf16_neonbfdot(a, n, alpha, &zero, result); }
124
+ else { nk_each_scale_bf16_neonbfdot(b, n, beta, &zero, result); }
125
+ return;
126
+ }
127
+
128
+ // The general case.
129
+ nk_size_t i = 0;
130
+ for (; i + 4 <= n; i += 4) {
131
+ bfloat16x4_t a_bf16x4 = vld1_bf16((bfloat16_t const *)a + i);
132
+ bfloat16x4_t b_bf16x4 = vld1_bf16((bfloat16_t const *)b + i);
133
+ float32x4_t a_f32x4 = vcvt_f32_bf16(a_bf16x4);
134
+ float32x4_t b_f32x4 = vcvt_f32_bf16(b_bf16x4);
135
+ float32x4_t a_scaled_f32x4 = vmulq_n_f32(a_f32x4, alpha_val);
136
+ float32x4_t b_scaled_f32x4 = vmulq_n_f32(b_f32x4, beta_val);
137
+ float32x4_t result_f32x4 = vaddq_f32(a_scaled_f32x4, b_scaled_f32x4);
138
+ bfloat16x4_t result_bf16x4 = vcvt_bf16_f32(result_f32x4);
139
+ vst1_bf16((bfloat16_t *)result + i, result_bf16x4);
140
+ }
141
+ if (i < n) {
142
+ nk_b64_vec_t a_tail, b_tail;
143
+ nk_partial_load_b16x4_serial_(a + i, &a_tail, n - i);
144
+ nk_partial_load_b16x4_serial_(b + i, &b_tail, n - i);
145
+ bfloat16x4_t a_bf16x4 = vreinterpret_bf16_u16(a_tail.u16x4);
146
+ bfloat16x4_t b_bf16x4 = vreinterpret_bf16_u16(b_tail.u16x4);
147
+ float32x4_t a_f32x4 = vcvt_f32_bf16(a_bf16x4);
148
+ float32x4_t b_f32x4 = vcvt_f32_bf16(b_bf16x4);
149
+ float32x4_t a_scaled_f32x4 = vmulq_n_f32(a_f32x4, alpha_val);
150
+ float32x4_t b_scaled_f32x4 = vmulq_n_f32(b_f32x4, beta_val);
151
+ float32x4_t result_f32x4 = vaddq_f32(a_scaled_f32x4, b_scaled_f32x4);
152
+ bfloat16x4_t result_bf16x4 = vcvt_bf16_f32(result_f32x4);
153
+ nk_b64_vec_t result_vec;
154
+ result_vec.u16x4 = vreinterpret_u16_bf16(result_bf16x4);
155
+ nk_partial_store_b16x4_serial_(result + i, &result_vec, n - i);
156
+ }
157
+ }
158
+
159
+ NK_PUBLIC void nk_each_fma_bf16_neonbfdot( //
160
+ nk_bf16_t const *a, nk_bf16_t const *b, nk_bf16_t const *c, //
161
+ nk_size_t n, nk_f32_t const *alpha, nk_f32_t const *beta, nk_bf16_t *result) {
162
+ nk_f32_t alpha_val = *alpha;
163
+ nk_f32_t beta_val = *beta;
164
+ nk_size_t i = 0;
165
+ for (; i + 4 <= n; i += 4) {
166
+ bfloat16x4_t a_bf16x4 = vld1_bf16((bfloat16_t const *)a + i);
167
+ bfloat16x4_t b_bf16x4 = vld1_bf16((bfloat16_t const *)b + i);
168
+ bfloat16x4_t c_bf16x4 = vld1_bf16((bfloat16_t const *)c + i);
169
+ float32x4_t a_f32x4 = vcvt_f32_bf16(a_bf16x4);
170
+ float32x4_t b_f32x4 = vcvt_f32_bf16(b_bf16x4);
171
+ float32x4_t c_f32x4 = vcvt_f32_bf16(c_bf16x4);
172
+ float32x4_t ab_f32x4 = vmulq_f32(a_f32x4, b_f32x4);
173
+ float32x4_t ab_scaled_f32x4 = vmulq_n_f32(ab_f32x4, alpha_val);
174
+ float32x4_t result_f32x4 = vfmaq_n_f32(ab_scaled_f32x4, c_f32x4, beta_val);
175
+ bfloat16x4_t result_bf16x4 = vcvt_bf16_f32(result_f32x4);
176
+ vst1_bf16((bfloat16_t *)result + i, result_bf16x4);
177
+ }
178
+ if (i < n) {
179
+ nk_b64_vec_t a_tail, b_tail, c_tail;
180
+ nk_partial_load_b16x4_serial_(a + i, &a_tail, n - i);
181
+ nk_partial_load_b16x4_serial_(b + i, &b_tail, n - i);
182
+ nk_partial_load_b16x4_serial_(c + i, &c_tail, n - i);
183
+ bfloat16x4_t a_bf16x4 = vreinterpret_bf16_u16(a_tail.u16x4);
184
+ bfloat16x4_t b_bf16x4 = vreinterpret_bf16_u16(b_tail.u16x4);
185
+ bfloat16x4_t c_bf16x4 = vreinterpret_bf16_u16(c_tail.u16x4);
186
+ float32x4_t a_f32x4 = vcvt_f32_bf16(a_bf16x4);
187
+ float32x4_t b_f32x4 = vcvt_f32_bf16(b_bf16x4);
188
+ float32x4_t c_f32x4 = vcvt_f32_bf16(c_bf16x4);
189
+ float32x4_t ab_f32x4 = vmulq_f32(a_f32x4, b_f32x4);
190
+ float32x4_t ab_scaled_f32x4 = vmulq_n_f32(ab_f32x4, alpha_val);
191
+ float32x4_t result_f32x4 = vfmaq_n_f32(ab_scaled_f32x4, c_f32x4, beta_val);
192
+ bfloat16x4_t result_bf16x4 = vcvt_bf16_f32(result_f32x4);
193
+ nk_b64_vec_t result_vec;
194
+ result_vec.u16x4 = vreinterpret_u16_bf16(result_bf16x4);
195
+ nk_partial_store_b16x4_serial_(result + i, &result_vec, n - i);
196
+ }
197
+ }
198
+
199
+ #if defined(__clang__)
200
+ #pragma clang attribute pop
201
+ #elif defined(__GNUC__)
202
+ #pragma GCC pop_options
203
+ #endif
204
+
205
+ #if defined(__cplusplus)
206
+ } // extern "C"
207
+ #endif
208
+
209
+ #endif // NK_TARGET_NEONBFDOT
210
+ #endif // NK_TARGET_ARM64_
211
+ #endif // NK_EACH_NEONBFDOT_H
@@ -0,0 +1,318 @@
1
+ /**
2
+ * @brief SIMD-accelerated Elementwise Arithmetic for NEON FP16.
3
+ * @file include/numkong/each/neonhalf.h
4
+ * @author Ash Vardanian
5
+ * @date December 27, 2025
6
+ *
7
+ * @sa include/numkong/each.h
8
+ *
9
+ * @section elementwise_neonhalf_instructions ARM NEON FP16 Instructions (ARMv8.2-FP16)
10
+ *
11
+ * Intrinsic Instruction A76 M5
12
+ * vld1q_f16 LD1 (V.8H) 4cy @ 2p 4cy @ 3p
13
+ * vst1q_f16 ST1 (V.8H) 2cy @ 2p 2cy @ 3p
14
+ * vaddq_f16 FADD (V.8H, V.8H, V.8H) 2cy @ 2p 2cy @ 4p
15
+ * vmulq_f16 FMUL (V.8H, V.8H, V.8H) 3cy @ 2p 3cy @ 4p
16
+ * vmulq_n_f16 FMUL (V.8H, V.8H, scalar) 3cy @ 2p 3cy @ 4p
17
+ * vfmaq_f16 FMLA (V.8H, V.8H, V.8H) 4cy @ 2p 4cy @ 4p
18
+ * vfmaq_n_f16 FMLA (V.8H, V.8H, scalar) 4cy @ 2p 4cy @ 4p
19
+ * vdupq_n_f16 DUP (V.8H, scalar) 2cy @ 2p 2cy @ 4p
20
+ * vld1_u8 LD1 (V.8B) 4cy @ 2p 4cy @ 3p
21
+ * vld1_s8 LD1 (V.8B) 4cy @ 2p 4cy @ 3p
22
+ * vmovl_u8 UXTL (V.8H, V.8B) 2cy @ 2p 2cy @ 4p
23
+ * vmovl_s8 SXTL (V.8H, V.8B) 2cy @ 2p 2cy @ 4p
24
+ * vcvtq_f16_u16 UCVTF (V.8H, V.8H) 3cy @ 2p 3cy @ 4p
25
+ * vcvtq_f16_s16 SCVTF (V.8H, V.8H) 3cy @ 2p 3cy @ 4p
26
+ * vcvtnq_u16_f16 FCVTNU (V.8H, V.8H) 3cy @ 2p 3cy @ 4p
27
+ * vcvtnq_s16_f16 FCVTNS (V.8H, V.8H) 3cy @ 2p 3cy @ 4p
28
+ * vqmovn_u16 UQXTN (V.8B, V.8H) 3cy @ 2p 3cy @ 4p
29
+ * vqmovn_s16 SQXTN (V.8B, V.8H) 3cy @ 2p 3cy @ 4p
30
+ * vqaddq_u8 UQADD (V.16B, V.16B, V.16B) 2cy @ 2p 3cy @ 2p
31
+ * vqaddq_s8 SQADD (V.16B, V.16B, V.16B) 2cy @ 2p 3cy @ 2p
32
+ *
33
+ * The ARMv8.2-FP16 extension enables native half-precision element-wise operations, processing 8
34
+ * F16 elements per instruction. Operations like sum, scale, blend, and fma work directly in F16,
35
+ * avoiding conversion overhead while halving memory bandwidth vs F32.
36
+ *
37
+ * For int8 element-wise operations, values are widened to F16 for arithmetic via UCVTF/SCVTF,
38
+ * then narrowed back with saturating conversion (FCVTA + UQXTN/SQXTN) to handle overflow gracefully.
39
+ */
40
+ #ifndef NK_EACH_NEONHALF_H
41
+ #define NK_EACH_NEONHALF_H
42
+
43
+ #if NK_TARGET_ARM64_
44
+ #if NK_TARGET_NEONHALF
45
+
46
+ #include "numkong/types.h"
47
+ #include "numkong/cast/serial.h" // `nk_f32_to_i8_serial`
48
+ #include "numkong/each/neon.h" // `nk_each_sum_u8_neon`, `nk_each_sum_i8_neon`
49
+
50
+ #if defined(__cplusplus)
51
+ extern "C" {
52
+ #endif
53
+
54
+ #if defined(__clang__)
55
+ #pragma clang attribute push(__attribute__((target("arch=armv8.2-a+simd+fp16"))), apply_to = function)
56
+ #elif defined(__GNUC__)
57
+ #pragma GCC push_options
58
+ #pragma GCC target("arch=armv8.2-a+simd+fp16")
59
+ #endif
60
+
61
+ NK_PUBLIC void nk_each_sum_f16_neonhalf(nk_f16_t const *a, nk_f16_t const *b, nk_size_t n, nk_f16_t *result) {
62
+ // The main loop:
63
+ nk_size_t i = 0;
64
+ for (; i + 8 <= n; i += 8) {
65
+ float16x8_t a_vec = vld1q_f16((float16_t const *)a + i);
66
+ float16x8_t b_vec = vld1q_f16((float16_t const *)b + i);
67
+ float16x8_t sum_vec = vaddq_f16(a_vec, b_vec);
68
+ vst1q_f16((float16_t *)result + i, sum_vec);
69
+ }
70
+
71
+ // The tail:
72
+ for (; i < n; ++i) ((float16_t *)result)[i] = ((float16_t const *)a)[i] + ((float16_t const *)b)[i];
73
+ }
74
+
75
+ NK_PUBLIC void nk_each_scale_f16_neonhalf(nk_f16_t const *a, nk_size_t n, nk_f32_t const *alpha, nk_f32_t const *beta,
76
+ nk_f16_t *result) {
77
+ nk_f32_t alpha_val = *alpha;
78
+ nk_f32_t beta_val = *beta;
79
+ float16_t alpha_f16 = (float16_t)alpha_val;
80
+ float16_t beta_f16 = (float16_t)beta_val;
81
+ float16x8_t alpha_f16x8 = vdupq_n_f16(alpha_f16);
82
+ float16x8_t beta_f16x8 = vdupq_n_f16(beta_f16);
83
+
84
+ // The main loop:
85
+ nk_size_t i = 0;
86
+ for (; i + 8 <= n; i += 8) {
87
+ float16x8_t a_f16x8 = vld1q_f16((float16_t const *)a + i);
88
+ float16x8_t result_f16x8 = vfmaq_f16(beta_f16x8, a_f16x8, alpha_f16x8);
89
+ vst1q_f16((float16_t *)result + i, result_f16x8);
90
+ }
91
+
92
+ // The tail:
93
+ for (; i < n; ++i) ((float16_t *)result)[i] = alpha_f16 * ((float16_t const *)a)[i] + beta_f16;
94
+ }
95
+
96
+ NK_PUBLIC void nk_each_blend_f16_neonhalf( //
97
+ nk_f16_t const *a, nk_f16_t const *b, nk_size_t n, //
98
+ nk_f32_t const *alpha, nk_f32_t const *beta, nk_f16_t *result) {
99
+
100
+ nk_f32_t alpha_val = *alpha;
101
+ nk_f32_t beta_val = *beta;
102
+
103
+ // There are several special cases we may want to implement:
104
+ // 1. Simple addition, when both weights are equal to 1.0.
105
+ if (alpha_val == 1 && beta_val == 1) {
106
+ // In this case we can avoid expensive multiplications.
107
+ nk_each_sum_f16_neonhalf(a, b, n, result);
108
+ return;
109
+ }
110
+ // 2. Just scaling, when one of the weights is equal to zero.
111
+ else if (alpha_val == 0 || beta_val == 0) {
112
+ // In this case we can avoid half of the load instructions.
113
+ nk_f32_t zero = 0;
114
+ if (beta_val == 0) { nk_each_scale_f16_neonhalf(a, n, alpha, &zero, result); }
115
+ else { nk_each_scale_f16_neonhalf(b, n, beta, &zero, result); }
116
+ return;
117
+ }
118
+
119
+ // The general case.
120
+ float16_t alpha_f16 = (float16_t)alpha_val;
121
+ float16_t beta_f16 = (float16_t)beta_val;
122
+
123
+ // The main loop:
124
+ nk_size_t i = 0;
125
+ for (; i + 8 <= n; i += 8) {
126
+ float16x8_t a_f16x8 = vld1q_f16((float16_t const *)a + i);
127
+ float16x8_t b_f16x8 = vld1q_f16((float16_t const *)b + i);
128
+ float16x8_t a_scaled_f16x8 = vmulq_n_f16(a_f16x8, alpha_f16);
129
+ float16x8_t result_f16x8 = vfmaq_n_f16(a_scaled_f16x8, b_f16x8, beta_f16);
130
+ vst1q_f16((float16_t *)result + i, result_f16x8);
131
+ }
132
+
133
+ // The tail:
134
+ for (; i < n; ++i)
135
+ ((float16_t *)result)[i] = alpha_f16 * ((float16_t const *)a)[i] + beta_f16 * ((float16_t const *)b)[i];
136
+ }
137
+
138
+ NK_PUBLIC void nk_each_fma_f16_neonhalf( //
139
+ nk_f16_t const *a, nk_f16_t const *b, nk_f16_t const *c, //
140
+ nk_size_t n, nk_f32_t const *alpha, nk_f32_t const *beta, nk_f16_t *result) {
141
+ nk_f32_t alpha_val = *alpha;
142
+ nk_f32_t beta_val = *beta;
143
+ float16_t alpha_f16 = (float16_t)alpha_val;
144
+ float16_t beta_f16 = (float16_t)beta_val;
145
+
146
+ // The main loop:
147
+ nk_size_t i = 0;
148
+ for (; i + 8 <= n; i += 8) {
149
+ float16x8_t a_f16x8 = vld1q_f16((float16_t const *)a + i);
150
+ float16x8_t b_f16x8 = vld1q_f16((float16_t const *)b + i);
151
+ float16x8_t c_f16x8 = vld1q_f16((float16_t const *)c + i);
152
+ float16x8_t ab_f16x8 = vmulq_f16(a_f16x8, b_f16x8);
153
+ float16x8_t ab_scaled_f16x8 = vmulq_n_f16(ab_f16x8, alpha_f16);
154
+ float16x8_t result_f16x8 = vfmaq_n_f16(ab_scaled_f16x8, c_f16x8, beta_f16);
155
+ vst1q_f16((float16_t *)result + i, result_f16x8);
156
+ }
157
+
158
+ // The tail:
159
+ for (; i < n; ++i)
160
+ ((float16_t *)result)[i] = alpha_f16 * ((float16_t const *)a)[i] * ((float16_t const *)b)[i] +
161
+ beta_f16 * ((float16_t const *)c)[i];
162
+ }
163
+
164
+ NK_PUBLIC void nk_each_scale_u8_neonhalf(nk_u8_t const *a, nk_size_t n, nk_f32_t const *alpha, nk_f32_t const *beta,
165
+ nk_u8_t *result) {
166
+ float16_t alpha_f16 = (float16_t)*alpha;
167
+ float16_t beta_f16 = (float16_t)*beta;
168
+ float16x8_t alpha_f16x8 = vdupq_n_f16(alpha_f16);
169
+ float16x8_t beta_f16x8 = vdupq_n_f16(beta_f16);
170
+
171
+ // The main loop:
172
+ nk_size_t i = 0;
173
+ for (; i + 8 <= n; i += 8) {
174
+ uint8x8_t a_u8x8 = vld1_u8(a + i);
175
+ float16x8_t a_f16x8 = vcvtq_f16_u16(vmovl_u8(a_u8x8));
176
+ float16x8_t result_f16x8 = vfmaq_f16(beta_f16x8, a_f16x8, alpha_f16x8);
177
+ uint8x8_t result_u8x8 = vqmovn_u16(vcvtnq_u16_f16(result_f16x8));
178
+ vst1_u8(result + i, result_u8x8);
179
+ }
180
+
181
+ // The tail:
182
+ for (; i < n; ++i) {
183
+ nk_f32_t sum = alpha_f16 * a[i] + beta_f16;
184
+ nk_f32_to_u8_serial(&sum, result + i);
185
+ }
186
+ }
187
+
188
+ NK_PUBLIC void nk_each_blend_u8_neonhalf( //
189
+ nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, //
190
+ nk_f32_t const *alpha, nk_f32_t const *beta, nk_u8_t *result) {
191
+
192
+ nk_f32_t alpha_val = *alpha;
193
+ nk_f32_t beta_val = *beta;
194
+
195
+ // There are several special cases we may want to implement:
196
+ // 1. Simple addition, when both weights are equal to 1.0.
197
+ if (alpha_val == 1 && beta_val == 1) {
198
+ // In this case we can avoid expensive multiplications.
199
+ nk_each_sum_u8_neon(a, b, n, result);
200
+ return;
201
+ }
202
+ // 2. Just scaling, when one of the weights is equal to zero.
203
+ else if (alpha_val == 0 || beta_val == 0) {
204
+ // In this case we can avoid half of the load instructions.
205
+ nk_f32_t zero = 0;
206
+ if (beta_val == 0) { nk_each_scale_u8_neonhalf(a, n, alpha, &zero, result); }
207
+ else { nk_each_scale_u8_neonhalf(b, n, beta, &zero, result); }
208
+ return;
209
+ }
210
+
211
+ // The general case.
212
+ float16_t alpha_f16 = (float16_t)alpha_val;
213
+ float16_t beta_f16 = (float16_t)beta_val;
214
+
215
+ // The main loop:
216
+ nk_size_t i = 0;
217
+ for (; i + 8 <= n; i += 8) {
218
+ uint8x8_t a_u8x8 = vld1_u8(a + i);
219
+ uint8x8_t b_u8x8 = vld1_u8(b + i);
220
+ float16x8_t a_f16x8 = vcvtq_f16_u16(vmovl_u8(a_u8x8));
221
+ float16x8_t b_f16x8 = vcvtq_f16_u16(vmovl_u8(b_u8x8));
222
+ float16x8_t a_scaled_f16x8 = vmulq_n_f16(a_f16x8, alpha_f16);
223
+ float16x8_t result_f16x8 = vfmaq_n_f16(a_scaled_f16x8, b_f16x8, beta_f16);
224
+ uint8x8_t result_u8x8 = vqmovn_u16(vcvtnq_u16_f16(result_f16x8));
225
+ vst1_u8(result + i, result_u8x8);
226
+ }
227
+
228
+ // The tail:
229
+ for (; i < n; ++i) {
230
+ nk_f32_t sum = alpha_f16 * a[i] + beta_f16 * b[i];
231
+ nk_f32_to_u8_serial(&sum, result + i);
232
+ }
233
+ }
234
+
235
+ NK_PUBLIC void nk_each_scale_i8_neonhalf(nk_i8_t const *a, nk_size_t n, nk_f32_t const *alpha, nk_f32_t const *beta,
236
+ nk_i8_t *result) {
237
+ float16_t alpha_f16 = (float16_t)*alpha;
238
+ float16_t beta_f16 = (float16_t)*beta;
239
+ float16x8_t alpha_f16x8 = vdupq_n_f16(alpha_f16);
240
+ float16x8_t beta_f16x8 = vdupq_n_f16(beta_f16);
241
+
242
+ // The main loop:
243
+ nk_size_t i = 0;
244
+ for (; i + 8 <= n; i += 8) {
245
+ int8x8_t a_i8x8 = vld1_s8(a + i);
246
+ float16x8_t a_f16x8 = vcvtq_f16_s16(vmovl_s8(a_i8x8));
247
+ float16x8_t result_f16x8 = vfmaq_f16(beta_f16x8, a_f16x8, alpha_f16x8);
248
+ int8x8_t result_i8x8 = vqmovn_s16(vcvtnq_s16_f16(result_f16x8));
249
+ vst1_s8(result + i, result_i8x8);
250
+ }
251
+
252
+ // The tail:
253
+ for (; i < n; ++i) {
254
+ nk_f32_t sum = alpha_f16 * a[i] + beta_f16;
255
+ nk_f32_to_i8_serial(&sum, result + i);
256
+ }
257
+ }
258
+
259
+ NK_PUBLIC void nk_each_blend_i8_neonhalf( //
260
+ nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, //
261
+ nk_f32_t const *alpha, nk_f32_t const *beta, nk_i8_t *result) {
262
+
263
+ nk_f32_t alpha_val = *alpha;
264
+ nk_f32_t beta_val = *beta;
265
+
266
+ // There are several special cases we may want to implement:
267
+ // 1. Simple addition, when both weights are equal to 1.0.
268
+ if (alpha_val == 1 && beta_val == 1) {
269
+ // In this case we can avoid expensive multiplications.
270
+ nk_each_sum_i8_neon(a, b, n, result);
271
+ return;
272
+ }
273
+ // 2. Just scaling, when one of the weights is equal to zero.
274
+ else if (alpha_val == 0 || beta_val == 0) {
275
+ // In this case we can avoid half of the load instructions.
276
+ nk_f32_t zero = 0;
277
+ if (beta_val == 0) { nk_each_scale_i8_neonhalf(a, n, alpha, &zero, result); }
278
+ else { nk_each_scale_i8_neonhalf(b, n, beta, &zero, result); }
279
+ return;
280
+ }
281
+
282
+ // The general case.
283
+ float16_t alpha_f16 = (float16_t)alpha_val;
284
+ float16_t beta_f16 = (float16_t)beta_val;
285
+
286
+ // The main loop:
287
+ nk_size_t i = 0;
288
+ for (; i + 8 <= n; i += 8) {
289
+ int8x8_t a_i8x8 = vld1_s8(a + i);
290
+ int8x8_t b_i8x8 = vld1_s8(b + i);
291
+ float16x8_t a_f16x8 = vcvtq_f16_s16(vmovl_s8(a_i8x8));
292
+ float16x8_t b_f16x8 = vcvtq_f16_s16(vmovl_s8(b_i8x8));
293
+ float16x8_t a_scaled_f16x8 = vmulq_n_f16(a_f16x8, alpha_f16);
294
+ float16x8_t result_f16x8 = vfmaq_n_f16(a_scaled_f16x8, b_f16x8, beta_f16);
295
+ int8x8_t result_i8x8 = vqmovn_s16(vcvtnq_s16_f16(result_f16x8));
296
+ vst1_s8(result + i, result_i8x8);
297
+ }
298
+
299
+ // The tail:
300
+ for (; i < n; ++i) {
301
+ nk_f32_t sum = alpha_f16 * a[i] + beta_f16 * b[i];
302
+ nk_f32_to_i8_serial(&sum, result + i);
303
+ }
304
+ }
305
+
306
+ #if defined(__clang__)
307
+ #pragma clang attribute pop
308
+ #elif defined(__GNUC__)
309
+ #pragma GCC pop_options
310
+ #endif
311
+
312
+ #if defined(__cplusplus)
313
+ } // extern "C"
314
+ #endif
315
+
316
+ #endif // NK_TARGET_NEONHALF
317
+ #endif // NK_TARGET_ARM64_
318
+ #endif // NK_EACH_NEONHALF_H