usearch 2.21.3 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) hide show
  1. package/README.md +24 -24
  2. package/binding.gyp +15 -37
  3. package/c/CMakeLists.txt +4 -5
  4. package/c/README.md +7 -7
  5. package/c/lib.cpp +32 -14
  6. package/c/test.c +83 -1
  7. package/c/usearch.h +24 -3
  8. package/cpp/CMakeLists.txt +4 -0
  9. package/cpp/README.md +5 -5
  10. package/cpp/bench.cpp +97 -116
  11. package/cpp/test.cpp +117 -20
  12. package/include/usearch/index.hpp +235 -52
  13. package/include/usearch/index_dense.hpp +105 -40
  14. package/include/usearch/index_plugins.hpp +1387 -204
  15. package/javascript/dist/cjs/usearch.d.ts +8 -3
  16. package/javascript/dist/cjs/usearch.js +12 -4
  17. package/javascript/dist/esm/usearch.d.ts +8 -3
  18. package/javascript/dist/esm/usearch.js +12 -4
  19. package/javascript/lib.cpp +17 -0
  20. package/javascript/usearch.ts +14 -6
  21. package/numkong/.clang-tidy +30 -0
  22. package/{simsimd → numkong}/.cmake-format.py +18 -0
  23. package/numkong/.editorconfig +12 -0
  24. package/numkong/.git-blame-ignore-revs +123 -0
  25. package/numkong/.mailmap +15 -0
  26. package/numkong/.spi.yml +11 -0
  27. package/numkong/.swift-format +14 -0
  28. package/numkong/CITATION.cff +81 -0
  29. package/numkong/CONTRIBUTING.md +500 -0
  30. package/numkong/Cargo.toml +54 -0
  31. package/numkong/MANIFEST.in +8 -0
  32. package/numkong/Package.swift +84 -0
  33. package/numkong/README.md +569 -0
  34. package/numkong/bench/README.md +217 -0
  35. package/numkong/bench/bench-browser.html +323 -0
  36. package/numkong/bench/bench.cpp +344 -0
  37. package/numkong/bench/bench.hpp +816 -0
  38. package/numkong/bench/bench.js +148 -0
  39. package/numkong/bench/bench.mjs +616 -0
  40. package/numkong/bench/bench_attention.cpp +113 -0
  41. package/numkong/bench/bench_cast.cpp +264 -0
  42. package/numkong/bench/bench_cross_amx.cpp +62 -0
  43. package/numkong/bench/bench_cross_arm.cpp +245 -0
  44. package/numkong/bench/bench_cross_blas.cpp +309 -0
  45. package/numkong/bench/bench_cross_loongarch.cpp +106 -0
  46. package/numkong/bench/bench_cross_power.cpp +84 -0
  47. package/numkong/bench/bench_cross_rvv.cpp +121 -0
  48. package/numkong/bench/bench_cross_serial.cpp +151 -0
  49. package/numkong/bench/bench_cross_sme.cpp +163 -0
  50. package/numkong/bench/bench_cross_wasm.cpp +142 -0
  51. package/numkong/bench/bench_cross_x86.cpp +455 -0
  52. package/numkong/bench/bench_curved.cpp +210 -0
  53. package/numkong/bench/bench_dot.cpp +315 -0
  54. package/numkong/bench/bench_each.cpp +503 -0
  55. package/numkong/bench/bench_geospatial.cpp +112 -0
  56. package/numkong/bench/bench_maxsim.cpp +154 -0
  57. package/numkong/bench/bench_mesh.cpp +148 -0
  58. package/numkong/bench/bench_probability.cpp +60 -0
  59. package/numkong/bench/bench_reduce.cpp +371 -0
  60. package/numkong/bench/bench_set.cpp +73 -0
  61. package/numkong/bench/bench_sparse.cpp +198 -0
  62. package/numkong/bench/bench_spatial.cpp +347 -0
  63. package/numkong/bench/bench_trigonometry.cpp +137 -0
  64. package/numkong/bench/swift/Bench.swift +506 -0
  65. package/numkong/binding.gyp +169 -0
  66. package/numkong/build.rs +484 -0
  67. package/numkong/c/dispatch.h +512 -0
  68. package/numkong/c/dispatch_bf16.c +447 -0
  69. package/numkong/c/dispatch_bf16c.c +52 -0
  70. package/numkong/c/dispatch_e2m3.c +296 -0
  71. package/numkong/c/dispatch_e3m2.c +284 -0
  72. package/numkong/c/dispatch_e4m3.c +318 -0
  73. package/numkong/c/dispatch_e5m2.c +316 -0
  74. package/numkong/c/dispatch_f16.c +452 -0
  75. package/numkong/c/dispatch_f16c.c +58 -0
  76. package/numkong/c/dispatch_f32.c +434 -0
  77. package/numkong/c/dispatch_f32c.c +99 -0
  78. package/numkong/c/dispatch_f64.c +348 -0
  79. package/numkong/c/dispatch_f64c.c +98 -0
  80. package/numkong/c/dispatch_i16.c +96 -0
  81. package/numkong/c/dispatch_i32.c +89 -0
  82. package/numkong/c/dispatch_i4.c +153 -0
  83. package/numkong/c/dispatch_i64.c +86 -0
  84. package/numkong/c/dispatch_i8.c +348 -0
  85. package/numkong/c/dispatch_other.c +348 -0
  86. package/numkong/c/dispatch_u1.c +193 -0
  87. package/numkong/c/dispatch_u16.c +124 -0
  88. package/numkong/c/dispatch_u32.c +118 -0
  89. package/numkong/c/dispatch_u4.c +153 -0
  90. package/numkong/c/dispatch_u64.c +102 -0
  91. package/numkong/c/dispatch_u8.c +364 -0
  92. package/numkong/c/numkong.c +940 -0
  93. package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
  94. package/numkong/cmake/nk_isa_probe.cmake +90 -0
  95. package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
  96. package/numkong/cmake/nk_math_lib.cmake +46 -0
  97. package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
  98. package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
  99. package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
  100. package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
  101. package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
  102. package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
  103. package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
  104. package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
  105. package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
  106. package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
  107. package/numkong/cmake/toolchain-wasi.cmake +77 -0
  108. package/numkong/cmake/toolchain-wasm.cmake +70 -0
  109. package/numkong/cmake/toolchain-wasm64.cmake +62 -0
  110. package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
  111. package/numkong/include/README.md +643 -0
  112. package/numkong/include/module.modulemap +129 -0
  113. package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
  114. package/numkong/include/numkong/attention/sme.h +2075 -0
  115. package/numkong/include/numkong/attention.h +49 -0
  116. package/numkong/include/numkong/capabilities.h +930 -0
  117. package/numkong/include/numkong/cast/README.md +262 -0
  118. package/numkong/include/numkong/cast/diamond.h +64 -0
  119. package/numkong/include/numkong/cast/haswell.h +823 -0
  120. package/numkong/include/numkong/cast/icelake.h +475 -0
  121. package/numkong/include/numkong/cast/loongsonasx.h +252 -0
  122. package/numkong/include/numkong/cast/neon.h +1174 -0
  123. package/numkong/include/numkong/cast/powervsx.h +449 -0
  124. package/numkong/include/numkong/cast/rvv.h +970 -0
  125. package/numkong/include/numkong/cast/sapphire.h +262 -0
  126. package/numkong/include/numkong/cast/serial.h +2336 -0
  127. package/numkong/include/numkong/cast/skylake.h +915 -0
  128. package/numkong/include/numkong/cast/v128relaxed.h +537 -0
  129. package/numkong/include/numkong/cast.h +254 -0
  130. package/numkong/include/numkong/cast.hpp +44 -0
  131. package/numkong/include/numkong/curved/README.md +223 -0
  132. package/numkong/include/numkong/curved/genoa.h +182 -0
  133. package/numkong/include/numkong/curved/haswell.h +276 -0
  134. package/numkong/include/numkong/curved/neon.h +329 -0
  135. package/numkong/include/numkong/curved/neonbfdot.h +211 -0
  136. package/numkong/include/numkong/curved/rvv.h +305 -0
  137. package/numkong/include/numkong/curved/serial.h +207 -0
  138. package/numkong/include/numkong/curved/skylake.h +457 -0
  139. package/numkong/include/numkong/curved/smef64.h +530 -0
  140. package/numkong/include/numkong/curved.h +513 -0
  141. package/numkong/include/numkong/curved.hpp +144 -0
  142. package/numkong/include/numkong/dot/README.md +442 -0
  143. package/numkong/include/numkong/dot/alder.h +563 -0
  144. package/numkong/include/numkong/dot/diamond.h +158 -0
  145. package/numkong/include/numkong/dot/genoa.h +289 -0
  146. package/numkong/include/numkong/dot/haswell.h +1723 -0
  147. package/numkong/include/numkong/dot/icelake.h +997 -0
  148. package/numkong/include/numkong/dot/loongsonasx.h +671 -0
  149. package/numkong/include/numkong/dot/neon.h +869 -0
  150. package/numkong/include/numkong/dot/neonbfdot.h +243 -0
  151. package/numkong/include/numkong/dot/neonfhm.h +358 -0
  152. package/numkong/include/numkong/dot/neonfp8.h +323 -0
  153. package/numkong/include/numkong/dot/neonsdot.h +622 -0
  154. package/numkong/include/numkong/dot/powervsx.h +752 -0
  155. package/numkong/include/numkong/dot/rvv.h +722 -0
  156. package/numkong/include/numkong/dot/rvvbb.h +72 -0
  157. package/numkong/include/numkong/dot/rvvbf16.h +123 -0
  158. package/numkong/include/numkong/dot/rvvhalf.h +129 -0
  159. package/numkong/include/numkong/dot/sapphire.h +141 -0
  160. package/numkong/include/numkong/dot/serial.h +874 -0
  161. package/numkong/include/numkong/dot/sierra.h +405 -0
  162. package/numkong/include/numkong/dot/skylake.h +1116 -0
  163. package/numkong/include/numkong/dot/sve.h +420 -0
  164. package/numkong/include/numkong/dot/svebfdot.h +75 -0
  165. package/numkong/include/numkong/dot/svehalf.h +168 -0
  166. package/numkong/include/numkong/dot/svesdot.h +90 -0
  167. package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
  168. package/numkong/include/numkong/dot.h +1136 -0
  169. package/numkong/include/numkong/dot.hpp +94 -0
  170. package/numkong/include/numkong/dots/README.md +496 -0
  171. package/numkong/include/numkong/dots/alder.h +117 -0
  172. package/numkong/include/numkong/dots/diamond.h +86 -0
  173. package/numkong/include/numkong/dots/genoa.h +100 -0
  174. package/numkong/include/numkong/dots/graniteamx.h +733 -0
  175. package/numkong/include/numkong/dots/haswell.h +310 -0
  176. package/numkong/include/numkong/dots/icelake.h +180 -0
  177. package/numkong/include/numkong/dots/loongsonasx.h +176 -0
  178. package/numkong/include/numkong/dots/neon.h +123 -0
  179. package/numkong/include/numkong/dots/neonbfdot.h +59 -0
  180. package/numkong/include/numkong/dots/neonfhm.h +96 -0
  181. package/numkong/include/numkong/dots/neonfp8.h +99 -0
  182. package/numkong/include/numkong/dots/neonsdot.h +144 -0
  183. package/numkong/include/numkong/dots/powervsx.h +194 -0
  184. package/numkong/include/numkong/dots/rvv.h +2593 -0
  185. package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
  186. package/numkong/include/numkong/dots/serial.h +2867 -0
  187. package/numkong/include/numkong/dots/sierra.h +100 -0
  188. package/numkong/include/numkong/dots/skylake.h +207 -0
  189. package/numkong/include/numkong/dots/sme.h +5041 -0
  190. package/numkong/include/numkong/dots/smebi32.h +477 -0
  191. package/numkong/include/numkong/dots/smef64.h +1328 -0
  192. package/numkong/include/numkong/dots/smehalf.h +47 -0
  193. package/numkong/include/numkong/dots/v128relaxed.h +317 -0
  194. package/numkong/include/numkong/dots.h +3110 -0
  195. package/numkong/include/numkong/dots.hpp +641 -0
  196. package/numkong/include/numkong/each/README.md +465 -0
  197. package/numkong/include/numkong/each/haswell.h +1658 -0
  198. package/numkong/include/numkong/each/icelake.h +272 -0
  199. package/numkong/include/numkong/each/neon.h +1138 -0
  200. package/numkong/include/numkong/each/neonbfdot.h +211 -0
  201. package/numkong/include/numkong/each/neonhalf.h +318 -0
  202. package/numkong/include/numkong/each/rvv.h +1121 -0
  203. package/numkong/include/numkong/each/sapphire.h +343 -0
  204. package/numkong/include/numkong/each/serial.h +282 -0
  205. package/numkong/include/numkong/each/skylake.h +1562 -0
  206. package/numkong/include/numkong/each/v128relaxed.h +562 -0
  207. package/numkong/include/numkong/each.h +2232 -0
  208. package/numkong/include/numkong/each.hpp +434 -0
  209. package/numkong/include/numkong/geospatial/README.md +147 -0
  210. package/numkong/include/numkong/geospatial/haswell.h +633 -0
  211. package/numkong/include/numkong/geospatial/neon.h +615 -0
  212. package/numkong/include/numkong/geospatial/rvv.h +701 -0
  213. package/numkong/include/numkong/geospatial/serial.h +309 -0
  214. package/numkong/include/numkong/geospatial/skylake.h +613 -0
  215. package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
  216. package/numkong/include/numkong/geospatial.h +453 -0
  217. package/numkong/include/numkong/geospatial.hpp +235 -0
  218. package/numkong/include/numkong/matrix.hpp +336 -0
  219. package/numkong/include/numkong/maxsim/README.md +187 -0
  220. package/numkong/include/numkong/maxsim/alder.h +511 -0
  221. package/numkong/include/numkong/maxsim/genoa.h +115 -0
  222. package/numkong/include/numkong/maxsim/haswell.h +553 -0
  223. package/numkong/include/numkong/maxsim/icelake.h +480 -0
  224. package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
  225. package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
  226. package/numkong/include/numkong/maxsim/serial.h +490 -0
  227. package/numkong/include/numkong/maxsim/sme.h +993 -0
  228. package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
  229. package/numkong/include/numkong/maxsim.h +571 -0
  230. package/numkong/include/numkong/maxsim.hpp +133 -0
  231. package/numkong/include/numkong/mesh/README.md +219 -0
  232. package/numkong/include/numkong/mesh/haswell.h +2013 -0
  233. package/numkong/include/numkong/mesh/neon.h +1821 -0
  234. package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
  235. package/numkong/include/numkong/mesh/rvv.h +936 -0
  236. package/numkong/include/numkong/mesh/serial.h +721 -0
  237. package/numkong/include/numkong/mesh/skylake.h +2344 -0
  238. package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
  239. package/numkong/include/numkong/mesh.h +666 -0
  240. package/numkong/include/numkong/mesh.hpp +701 -0
  241. package/numkong/include/numkong/numkong.h +78 -0
  242. package/numkong/include/numkong/numkong.hpp +58 -0
  243. package/numkong/include/numkong/probability/README.md +177 -0
  244. package/numkong/include/numkong/probability/haswell.h +267 -0
  245. package/numkong/include/numkong/probability/neon.h +255 -0
  246. package/numkong/include/numkong/probability/rvv.h +414 -0
  247. package/numkong/include/numkong/probability/serial.h +181 -0
  248. package/numkong/include/numkong/probability/skylake.h +324 -0
  249. package/numkong/include/numkong/probability.h +380 -0
  250. package/numkong/include/numkong/probability.hpp +120 -0
  251. package/numkong/include/numkong/random.h +50 -0
  252. package/numkong/include/numkong/random.hpp +285 -0
  253. package/numkong/include/numkong/reduce/README.md +552 -0
  254. package/numkong/include/numkong/reduce/alder.h +636 -0
  255. package/numkong/include/numkong/reduce/genoa.h +201 -0
  256. package/numkong/include/numkong/reduce/haswell.h +3785 -0
  257. package/numkong/include/numkong/reduce/icelake.h +549 -0
  258. package/numkong/include/numkong/reduce/neon.h +3980 -0
  259. package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
  260. package/numkong/include/numkong/reduce/neonfhm.h +293 -0
  261. package/numkong/include/numkong/reduce/neonsdot.h +357 -0
  262. package/numkong/include/numkong/reduce/rvv.h +3533 -0
  263. package/numkong/include/numkong/reduce/serial.h +753 -0
  264. package/numkong/include/numkong/reduce/sierra.h +338 -0
  265. package/numkong/include/numkong/reduce/skylake.h +3794 -0
  266. package/numkong/include/numkong/reduce/sve.h +52 -0
  267. package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
  268. package/numkong/include/numkong/reduce.h +1582 -0
  269. package/numkong/include/numkong/reduce.hpp +778 -0
  270. package/numkong/include/numkong/scalar/README.md +89 -0
  271. package/numkong/include/numkong/scalar/haswell.h +122 -0
  272. package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
  273. package/numkong/include/numkong/scalar/neon.h +122 -0
  274. package/numkong/include/numkong/scalar/neonhalf.h +70 -0
  275. package/numkong/include/numkong/scalar/powervsx.h +96 -0
  276. package/numkong/include/numkong/scalar/rvv.h +211 -0
  277. package/numkong/include/numkong/scalar/sapphire.h +74 -0
  278. package/numkong/include/numkong/scalar/serial.h +332 -0
  279. package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
  280. package/numkong/include/numkong/scalar.h +696 -0
  281. package/numkong/include/numkong/set/README.md +179 -0
  282. package/numkong/include/numkong/set/haswell.h +334 -0
  283. package/numkong/include/numkong/set/icelake.h +485 -0
  284. package/numkong/include/numkong/set/loongsonasx.h +181 -0
  285. package/numkong/include/numkong/set/neon.h +363 -0
  286. package/numkong/include/numkong/set/powervsx.h +326 -0
  287. package/numkong/include/numkong/set/rvv.h +226 -0
  288. package/numkong/include/numkong/set/rvvbb.h +117 -0
  289. package/numkong/include/numkong/set/serial.h +174 -0
  290. package/numkong/include/numkong/set/sve.h +187 -0
  291. package/numkong/include/numkong/set/v128relaxed.h +240 -0
  292. package/numkong/include/numkong/set.h +471 -0
  293. package/numkong/include/numkong/set.hpp +114 -0
  294. package/numkong/include/numkong/sets/README.md +149 -0
  295. package/numkong/include/numkong/sets/haswell.h +63 -0
  296. package/numkong/include/numkong/sets/icelake.h +66 -0
  297. package/numkong/include/numkong/sets/loongsonasx.h +52 -0
  298. package/numkong/include/numkong/sets/neon.h +61 -0
  299. package/numkong/include/numkong/sets/powervsx.h +65 -0
  300. package/numkong/include/numkong/sets/serial.h +43 -0
  301. package/numkong/include/numkong/sets/smebi32.h +1135 -0
  302. package/numkong/include/numkong/sets/v128relaxed.h +58 -0
  303. package/numkong/include/numkong/sets.h +382 -0
  304. package/numkong/include/numkong/sparse/README.md +156 -0
  305. package/numkong/include/numkong/sparse/icelake.h +463 -0
  306. package/numkong/include/numkong/sparse/neon.h +288 -0
  307. package/numkong/include/numkong/sparse/serial.h +117 -0
  308. package/numkong/include/numkong/sparse/sve2.h +504 -0
  309. package/numkong/include/numkong/sparse/turin.h +322 -0
  310. package/numkong/include/numkong/sparse.h +363 -0
  311. package/numkong/include/numkong/sparse.hpp +113 -0
  312. package/numkong/include/numkong/spatial/README.md +439 -0
  313. package/numkong/include/numkong/spatial/alder.h +604 -0
  314. package/numkong/include/numkong/spatial/diamond.h +240 -0
  315. package/numkong/include/numkong/spatial/genoa.h +222 -0
  316. package/numkong/include/numkong/spatial/haswell.h +979 -0
  317. package/numkong/include/numkong/spatial/icelake.h +1067 -0
  318. package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
  319. package/numkong/include/numkong/spatial/neon.h +846 -0
  320. package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
  321. package/numkong/include/numkong/spatial/neonfp8.h +258 -0
  322. package/numkong/include/numkong/spatial/neonsdot.h +429 -0
  323. package/numkong/include/numkong/spatial/powervsx.h +738 -0
  324. package/numkong/include/numkong/spatial/rvv.h +991 -0
  325. package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
  326. package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
  327. package/numkong/include/numkong/spatial/serial.h +347 -0
  328. package/numkong/include/numkong/spatial/sierra.h +516 -0
  329. package/numkong/include/numkong/spatial/skylake.h +605 -0
  330. package/numkong/include/numkong/spatial/sve.h +246 -0
  331. package/numkong/include/numkong/spatial/svebfdot.h +125 -0
  332. package/numkong/include/numkong/spatial/svehalf.h +136 -0
  333. package/numkong/include/numkong/spatial/svesdot.h +143 -0
  334. package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
  335. package/numkong/include/numkong/spatial.h +1681 -0
  336. package/numkong/include/numkong/spatial.hpp +183 -0
  337. package/numkong/include/numkong/spatials/README.md +580 -0
  338. package/numkong/include/numkong/spatials/alder.h +94 -0
  339. package/numkong/include/numkong/spatials/diamond.h +82 -0
  340. package/numkong/include/numkong/spatials/genoa.h +94 -0
  341. package/numkong/include/numkong/spatials/graniteamx.h +173 -0
  342. package/numkong/include/numkong/spatials/haswell.h +219 -0
  343. package/numkong/include/numkong/spatials/icelake.h +113 -0
  344. package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
  345. package/numkong/include/numkong/spatials/neon.h +109 -0
  346. package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
  347. package/numkong/include/numkong/spatials/neonfhm.h +92 -0
  348. package/numkong/include/numkong/spatials/neonfp8.h +111 -0
  349. package/numkong/include/numkong/spatials/neonsdot.h +143 -0
  350. package/numkong/include/numkong/spatials/powervsx.h +153 -0
  351. package/numkong/include/numkong/spatials/rvv.h +1976 -0
  352. package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
  353. package/numkong/include/numkong/spatials/serial.h +248 -0
  354. package/numkong/include/numkong/spatials/sierra.h +96 -0
  355. package/numkong/include/numkong/spatials/skylake.h +184 -0
  356. package/numkong/include/numkong/spatials/sme.h +1927 -0
  357. package/numkong/include/numkong/spatials/smef64.h +483 -0
  358. package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
  359. package/numkong/include/numkong/spatials.h +3374 -0
  360. package/numkong/include/numkong/spatials.hpp +509 -0
  361. package/numkong/include/numkong/tensor.hpp +1981 -0
  362. package/numkong/include/numkong/trigonometry/README.md +184 -0
  363. package/numkong/include/numkong/trigonometry/haswell.h +653 -0
  364. package/numkong/include/numkong/trigonometry/neon.h +638 -0
  365. package/numkong/include/numkong/trigonometry/rvv.h +700 -0
  366. package/numkong/include/numkong/trigonometry/serial.h +703 -0
  367. package/numkong/include/numkong/trigonometry/skylake.h +725 -0
  368. package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
  369. package/numkong/include/numkong/trigonometry.h +467 -0
  370. package/numkong/include/numkong/trigonometry.hpp +166 -0
  371. package/numkong/include/numkong/types.h +1695 -0
  372. package/numkong/include/numkong/types.hpp +6027 -0
  373. package/numkong/include/numkong/vector.hpp +766 -0
  374. package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
  375. package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
  376. package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
  377. package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
  378. package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
  379. package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
  380. package/numkong/javascript/README.md +254 -0
  381. package/numkong/javascript/node-gyp-build.d.ts +4 -0
  382. package/numkong/javascript/numkong-browser.ts +40 -0
  383. package/numkong/javascript/numkong-wasm.ts +750 -0
  384. package/numkong/javascript/numkong.c +712 -0
  385. package/numkong/javascript/numkong.ts +613 -0
  386. package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
  387. package/numkong/javascript/tsconfig-cjs.json +13 -0
  388. package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
  389. package/numkong/javascript/types.ts +784 -0
  390. package/numkong/numkong.gypi +104 -0
  391. package/numkong/package.json +108 -0
  392. package/numkong/probes/arm_neon.c +8 -0
  393. package/numkong/probes/arm_neon_bfdot.c +9 -0
  394. package/numkong/probes/arm_neon_fhm.c +9 -0
  395. package/numkong/probes/arm_neon_half.c +8 -0
  396. package/numkong/probes/arm_neon_sdot.c +9 -0
  397. package/numkong/probes/arm_neonfp8.c +9 -0
  398. package/numkong/probes/arm_sme.c +16 -0
  399. package/numkong/probes/arm_sme2.c +16 -0
  400. package/numkong/probes/arm_sme2p1.c +16 -0
  401. package/numkong/probes/arm_sme_bf16.c +16 -0
  402. package/numkong/probes/arm_sme_bi32.c +16 -0
  403. package/numkong/probes/arm_sme_f64.c +16 -0
  404. package/numkong/probes/arm_sme_fa64.c +14 -0
  405. package/numkong/probes/arm_sme_half.c +16 -0
  406. package/numkong/probes/arm_sme_lut2.c +15 -0
  407. package/numkong/probes/arm_sve.c +18 -0
  408. package/numkong/probes/arm_sve2.c +20 -0
  409. package/numkong/probes/arm_sve2p1.c +18 -0
  410. package/numkong/probes/arm_sve_bfdot.c +20 -0
  411. package/numkong/probes/arm_sve_half.c +18 -0
  412. package/numkong/probes/arm_sve_sdot.c +21 -0
  413. package/numkong/probes/loongarch_lasx.c +12 -0
  414. package/numkong/probes/power_vsx.c +12 -0
  415. package/numkong/probes/probe.js +127 -0
  416. package/numkong/probes/riscv_rvv.c +14 -0
  417. package/numkong/probes/riscv_rvv_bb.c +15 -0
  418. package/numkong/probes/riscv_rvv_bf16.c +17 -0
  419. package/numkong/probes/riscv_rvv_half.c +14 -0
  420. package/numkong/probes/wasm_v128relaxed.c +11 -0
  421. package/numkong/probes/x86_alder.c +17 -0
  422. package/numkong/probes/x86_diamond.c +17 -0
  423. package/numkong/probes/x86_genoa.c +17 -0
  424. package/numkong/probes/x86_graniteamx.c +19 -0
  425. package/numkong/probes/x86_haswell.c +11 -0
  426. package/numkong/probes/x86_icelake.c +17 -0
  427. package/numkong/probes/x86_sapphire.c +16 -0
  428. package/numkong/probes/x86_sapphireamx.c +18 -0
  429. package/numkong/probes/x86_sierra.c +17 -0
  430. package/numkong/probes/x86_skylake.c +15 -0
  431. package/numkong/probes/x86_turin.c +17 -0
  432. package/numkong/rust/README.md +698 -0
  433. package/numkong/rust/capabilities.rs +96 -0
  434. package/numkong/rust/cast.rs +314 -0
  435. package/numkong/rust/curved.rs +391 -0
  436. package/numkong/rust/each.rs +2721 -0
  437. package/numkong/rust/geospatial.rs +343 -0
  438. package/numkong/rust/matrix.rs +5424 -0
  439. package/numkong/rust/maxsim.rs +540 -0
  440. package/numkong/rust/mesh.rs +837 -0
  441. package/numkong/rust/numkong.rs +409 -0
  442. package/numkong/rust/probability.rs +272 -0
  443. package/numkong/rust/reduce.rs +1249 -0
  444. package/numkong/rust/set.rs +194 -0
  445. package/numkong/rust/sparse.rs +513 -0
  446. package/numkong/rust/spatial.rs +1815 -0
  447. package/numkong/rust/tensor.rs +7565 -0
  448. package/numkong/rust/types.rs +3666 -0
  449. package/numkong/rust/vector.rs +1899 -0
  450. package/numkong/rustfmt.toml +2 -0
  451. package/numkong/swift/Matrix.swift +1388 -0
  452. package/numkong/swift/MaxSim.swift +151 -0
  453. package/numkong/swift/NumKong.swift +283 -0
  454. package/numkong/swift/Numerics.swift +329 -0
  455. package/numkong/swift/README.md +433 -0
  456. package/numkong/swift/Scalar.swift +741 -0
  457. package/numkong/swift/Tensor.swift +209 -0
  458. package/numkong/test/README.md +315 -0
  459. package/numkong/test/playwright.config.ts +16 -0
  460. package/numkong/test/swift/Test.swift +534 -0
  461. package/numkong/test/test-browser-bundle-runner.mjs +36 -0
  462. package/numkong/test/test-browser-bundle.html +188 -0
  463. package/numkong/test/test-browser-runner.mjs +43 -0
  464. package/numkong/test/test-browser.html +305 -0
  465. package/numkong/test/test-dtypes.mjs +453 -0
  466. package/numkong/test/test-wasm.mjs +267 -0
  467. package/numkong/test/test.cpp +442 -0
  468. package/numkong/test/test.hpp +580 -0
  469. package/numkong/test/test.mjs +363 -0
  470. package/numkong/test/test_base.py +1041 -0
  471. package/numkong/test/test_cast.cpp +242 -0
  472. package/numkong/test/test_cross.hpp +551 -0
  473. package/numkong/test/test_cross.py +467 -0
  474. package/numkong/test/test_cross_amx.cpp +50 -0
  475. package/numkong/test/test_cross_arm.cpp +225 -0
  476. package/numkong/test/test_cross_blas.cpp +354 -0
  477. package/numkong/test/test_cross_loongarch.cpp +90 -0
  478. package/numkong/test/test_cross_power.cpp +73 -0
  479. package/numkong/test/test_cross_rvv.cpp +109 -0
  480. package/numkong/test/test_cross_serial.cpp +181 -0
  481. package/numkong/test/test_cross_sme.cpp +148 -0
  482. package/numkong/test/test_cross_wasm.cpp +141 -0
  483. package/numkong/test/test_cross_x86.cpp +442 -0
  484. package/numkong/test/test_curved.cpp +182 -0
  485. package/numkong/test/test_curved.py +207 -0
  486. package/numkong/test/test_dot.cpp +353 -0
  487. package/numkong/test/test_dot.py +296 -0
  488. package/numkong/test/test_each.cpp +437 -0
  489. package/numkong/test/test_each.py +756 -0
  490. package/numkong/test/test_geospatial.cpp +155 -0
  491. package/numkong/test/test_geospatial.py +241 -0
  492. package/numkong/test/test_maxsim.cpp +138 -0
  493. package/numkong/test/test_maxsim.py +209 -0
  494. package/numkong/test/test_mesh.cpp +203 -0
  495. package/numkong/test/test_mesh.py +394 -0
  496. package/numkong/test/test_probability.cpp +136 -0
  497. package/numkong/test/test_probability.py +166 -0
  498. package/numkong/test/test_reduce.cpp +563 -0
  499. package/numkong/test/test_reduce.py +781 -0
  500. package/numkong/test/test_set.cpp +151 -0
  501. package/numkong/test/test_set.py +120 -0
  502. package/numkong/test/test_similarities.py +579 -0
  503. package/numkong/test/test_sparse.cpp +121 -0
  504. package/numkong/test/test_sparse.py +118 -0
  505. package/numkong/test/test_spatial.cpp +518 -0
  506. package/numkong/test/test_spatial.py +269 -0
  507. package/numkong/test/test_tensor.cpp +884 -0
  508. package/numkong/test/test_tensor.py +1417 -0
  509. package/numkong/test/test_trigonometry.cpp +156 -0
  510. package/numkong/test/test_trigonometry.py +180 -0
  511. package/package.json +7 -8
  512. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  513. package/prebuilds/linux-arm64/usearch.node +0 -0
  514. package/prebuilds/linux-x64/usearch.node +0 -0
  515. package/fp16/CMakeLists.txt +0 -176
  516. package/fp16/LICENSE +0 -11
  517. package/fp16/README.md +0 -20
  518. package/fp16/bench/alt-element.cc +0 -89
  519. package/fp16/bench/from-alt-array.cc +0 -175
  520. package/fp16/bench/from-ieee-array.cc +0 -399
  521. package/fp16/bench/ieee-element.cc +0 -272
  522. package/fp16/bench/to-alt-array.cc +0 -91
  523. package/fp16/bench/to-ieee-array.cc +0 -303
  524. package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
  525. package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
  526. package/fp16/cmake/DownloadPSimd.cmake +0 -15
  527. package/fp16/configure.py +0 -65
  528. package/fp16/confu.yaml +0 -8
  529. package/fp16/include/fp16/__init__.py +0 -0
  530. package/fp16/include/fp16/avx.py +0 -50
  531. package/fp16/include/fp16/avx2.py +0 -53
  532. package/fp16/include/fp16/bitcasts.h +0 -92
  533. package/fp16/include/fp16/fp16.h +0 -451
  534. package/fp16/include/fp16/psimd.h +0 -131
  535. package/fp16/include/fp16.h +0 -11
  536. package/fp16/jni/Android.mk +0 -6
  537. package/fp16/jni/Application.mk +0 -4
  538. package/fp16/test/alt-from-fp32-value.cc +0 -498
  539. package/fp16/test/alt-to-fp32-bits.cc +0 -263
  540. package/fp16/test/alt-to-fp32-psimd.cc +0 -145
  541. package/fp16/test/alt-to-fp32-value.cc +0 -348
  542. package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
  543. package/fp16/test/bitcasts.cc +0 -56
  544. package/fp16/test/ieee-from-fp32-value.cc +0 -523
  545. package/fp16/test/ieee-to-fp32-bits.cc +0 -333
  546. package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
  547. package/fp16/test/ieee-to-fp32-value.cc +0 -420
  548. package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
  549. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
  550. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
  551. package/fp16/test/peachpy/stubs.py +0 -38
  552. package/fp16/test/tables.cc +0 -530
  553. package/fp16/test/tables.h +0 -13
  554. package/fp16/third-party/THHalf.h +0 -92
  555. package/fp16/third-party/eigen-half.h +0 -170
  556. package/fp16/third-party/float16-compressor.h +0 -80
  557. package/fp16/third-party/half.hpp +0 -2916
  558. package/fp16/third-party/npy-halffloat.h +0 -328
  559. package/simsimd/.git-blame-ignore-revs +0 -2
  560. package/simsimd/CONTRIBUTING.md +0 -321
  561. package/simsimd/Cargo.toml +0 -49
  562. package/simsimd/MANIFEST.in +0 -4
  563. package/simsimd/Package.swift +0 -28
  564. package/simsimd/README.md +0 -1493
  565. package/simsimd/binding.gyp +0 -35
  566. package/simsimd/build.rs +0 -70
  567. package/simsimd/c/lib.c +0 -374
  568. package/simsimd/include/module.modulemap +0 -4
  569. package/simsimd/include/simsimd/binary.h +0 -486
  570. package/simsimd/include/simsimd/curved.h +0 -1541
  571. package/simsimd/include/simsimd/dot.h +0 -1853
  572. package/simsimd/include/simsimd/elementwise.h +0 -2465
  573. package/simsimd/include/simsimd/geospatial.h +0 -43
  574. package/simsimd/include/simsimd/mesh.h +0 -69
  575. package/simsimd/include/simsimd/probability.h +0 -606
  576. package/simsimd/include/simsimd/simsimd.h +0 -2567
  577. package/simsimd/include/simsimd/sparse.h +0 -1384
  578. package/simsimd/include/simsimd/spatial.h +0 -2335
  579. package/simsimd/include/simsimd/types.h +0 -666
  580. package/simsimd/javascript/fallback.ts +0 -233
  581. package/simsimd/javascript/lib.c +0 -125
  582. package/simsimd/javascript/node-gyp-build.d.ts +0 -1
  583. package/simsimd/javascript/simsimd.ts +0 -179
  584. package/simsimd/javascript/tsconfig-cjs.json +0 -8
  585. package/simsimd/package-lock.json +0 -1761
  586. package/simsimd/package.json +0 -61
  587. package/simsimd/rust/lib.rs +0 -1821
  588. package/simsimd/scripts/bench.cxx +0 -1170
  589. package/simsimd/scripts/bench.ipynb +0 -187
  590. package/simsimd/scripts/bench.js +0 -127
  591. package/simsimd/scripts/bench.rs +0 -876
  592. package/simsimd/scripts/bench_vectors.py +0 -734
  593. package/simsimd/scripts/bench_vectors_live.py +0 -213
  594. package/simsimd/scripts/test.c +0 -187
  595. package/simsimd/scripts/test.mjs +0 -220
  596. package/simsimd/scripts/test.py +0 -1505
  597. package/simsimd/swift/SimSIMD.swift +0 -149
  598. package/simsimd/swift/Test.swift +0 -128
  599. /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
  600. /package/{simsimd → numkong}/LICENSE +0 -0
  601. /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
  602. /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
@@ -0,0 +1,638 @@
1
+ /**
2
+ * @brief SIMD-accelerated Trigonometric Functions for NEON.
3
+ * @file include/numkong/trigonometry/neon.h
4
+ * @author Ash Vardanian
5
+ * @date December 28, 2025
6
+ *
7
+ * @sa include/numkong/trigonometry.h
8
+ * @see https://sleef.org
9
+ *
10
+ * @section trigonometry_neon_instructions ARM NEON Instructions
11
+ *
12
+ * Intrinsic Instruction A76 M5
13
+ * vfmaq_f32 FMLA (V.4S, V.4S, V.4S) 4cy @ 2p 3cy @ 4p
14
+ * vfmsq_f32 FMLS (V.4S, V.4S, V.4S) 4cy @ 2p 3cy @ 4p
15
+ * vmulq_f32 FMUL (V.4S, V.4S, V.4S) 3cy @ 2p 3cy @ 4p
16
+ * vaddq_f32 FADD (V.4S, V.4S, V.4S) 2cy @ 2p 2cy @ 4p
17
+ * vsubq_f32 FSUB (V.4S, V.4S, V.4S) 2cy @ 2p 2cy @ 4p
18
+ * vcvtnq_s32_f32 FCVTNS (V.4S, V.4S) 3cy @ 2p 3cy @ 4p
19
+ * vcvtq_f32_s32 SCVTF (V.4S, V.4S) 3cy @ 2p 3cy @ 4p
20
+ * vbslq_f32 BSL (V.16B, V.16B, V.16B) 1cy @ 2p 2cy @ 4p
21
+ * vrecpeq_f32 FRECPE (V.4S, V.4S) 2cy @ 2p 3cy @ 1p
22
+ * vrecpsq_f32 FRECPS (V.4S, V.4S, V.4S) 4cy @ 2p 3cy @ 2p
23
+ * vfmaq_f64 FMLA (V.2D, V.2D, V.2D) 4cy @ 2p 3cy @ 4p
24
+ * vdivq_f64 FDIV (V.2D, V.2D, V.2D) 12cy @ 1p 7cy @ 1p
25
+ *
26
+ * Polynomial approximations for sin/cos/atan are FMA-dominated. On 4-pipe cores (Apple M4+,
27
+ * Graviton3+, Oryon), FMA throughput is 4/cy with 4cy latency.
28
+ *
29
+ * Division (vdivq_f64) remains slow at 0.5/cy on all cores. For f32, use fast reciprocal
30
+ * (vrecpeq_f32 + Newton-Raphson) instead when precision allows.
31
+ */
32
+ #ifndef NK_TRIGONOMETRY_NEON_H
33
+ #define NK_TRIGONOMETRY_NEON_H
34
+
35
+ #if NK_TARGET_ARM64_
36
+ #if NK_TARGET_NEON
37
+
38
+ #include "numkong/types.h"
39
+ #include "numkong/reduce/neon.h"
40
+
41
+ #if defined(__cplusplus)
42
+ extern "C" {
43
+ #endif
44
+
45
+ #if defined(__clang__)
46
+ #pragma clang attribute push(__attribute__((target("arch=armv8-a+simd"))), apply_to = function)
47
+ #elif defined(__GNUC__)
48
+ #pragma GCC push_options
49
+ #pragma GCC target("arch=armv8-a+simd")
50
+ #endif
51
+
52
+ /* NEON trigonometry kernels (4-way f32, 2-way f64)
53
+ * These implement polynomial approximations using 128-bit NEON vectors.
54
+ */
55
+
56
+ NK_INTERNAL float32x4_t nk_sin_f32x4_neon_(float32x4_t const angles_radians) {
57
+ // Cody-Waite constants for argument reduction
58
+ float32x4_t const pi_high_f32x4 = vdupq_n_f32(3.1415927f);
59
+ float32x4_t const pi_low_f32x4 = vdupq_n_f32(-8.742278e-8f);
60
+ float32x4_t const pi_reciprocal_f32x4 = vdupq_n_f32(0.31830988618379067154f);
61
+ // Degree-9 minimax coefficients
62
+ float32x4_t const coeff_9_f32x4 = vdupq_n_f32(+2.7557319224e-6f);
63
+ float32x4_t const coeff_7_f32x4 = vdupq_n_f32(-1.9841269841e-4f);
64
+ float32x4_t const coeff_5_f32x4 = vdupq_n_f32(+8.3333293855e-3f);
65
+ float32x4_t const coeff_3_f32x4 = vdupq_n_f32(-1.6666666641e-1f);
66
+
67
+ // Compute (multiples_of_pi_i32x4) = round(angle / π) using vcvtnq which rounds to nearest
68
+ float32x4_t quotients_f32x4 = vmulq_f32(angles_radians, pi_reciprocal_f32x4);
69
+ int32x4_t multiples_of_pi_i32x4 = vcvtnq_s32_f32(quotients_f32x4);
70
+ float32x4_t rounded_quotients_f32x4 = vcvtq_f32_s32(multiples_of_pi_i32x4);
71
+
72
+ // Cody-Waite range reduction
73
+ float32x4_t angles_f32x4 = vfmsq_f32(angles_radians, rounded_quotients_f32x4, pi_high_f32x4);
74
+ angles_f32x4 = vfmsq_f32(angles_f32x4, rounded_quotients_f32x4, pi_low_f32x4);
75
+ float32x4_t const angles_squared_f32x4 = vmulq_f32(angles_f32x4, angles_f32x4);
76
+ float32x4_t const angles_cubed_f32x4 = vmulq_f32(angles_f32x4, angles_squared_f32x4);
77
+
78
+ // Degree-9 polynomial via Horner's method
79
+ float32x4_t polynomials_f32x4 = coeff_9_f32x4;
80
+ polynomials_f32x4 = vfmaq_f32(coeff_7_f32x4, polynomials_f32x4, angles_squared_f32x4);
81
+ polynomials_f32x4 = vfmaq_f32(coeff_5_f32x4, polynomials_f32x4, angles_squared_f32x4);
82
+ polynomials_f32x4 = vfmaq_f32(coeff_3_f32x4, polynomials_f32x4, angles_squared_f32x4);
83
+ float32x4_t results_f32x4 = vfmaq_f32(angles_f32x4, angles_cubed_f32x4, polynomials_f32x4);
84
+
85
+ // If multiples_of_pi_i32x4 is odd, flip the sign
86
+ int32x4_t parity_i32x4 = vandq_s32(multiples_of_pi_i32x4, vdupq_n_s32(1));
87
+ uint32x4_t odd_mask_u32x4 = vceqq_s32(parity_i32x4, vdupq_n_s32(1));
88
+ float32x4_t negated_f32x4 = vnegq_f32(results_f32x4);
89
+ results_f32x4 = vbslq_f32(odd_mask_u32x4, negated_f32x4, results_f32x4);
90
+ return results_f32x4;
91
+ }
92
+
93
+ NK_INTERNAL float32x4_t nk_cos_f32x4_neon_(float32x4_t const angles_radians) {
94
+ // Cody-Waite constants for argument reduction
95
+ float32x4_t const pi_high_f32x4 = vdupq_n_f32(3.1415927f);
96
+ float32x4_t const pi_low_f32x4 = vdupq_n_f32(-8.742278e-8f);
97
+ float32x4_t const pi_half_f32x4 = vdupq_n_f32(1.57079632679489661923f);
98
+ float32x4_t const pi_reciprocal_f32x4 = vdupq_n_f32(0.31830988618379067154f);
99
+ // Degree-9 minimax coefficients
100
+ float32x4_t const coeff_9_f32x4 = vdupq_n_f32(+2.7557319224e-6f);
101
+ float32x4_t const coeff_7_f32x4 = vdupq_n_f32(-1.9841269841e-4f);
102
+ float32x4_t const coeff_5_f32x4 = vdupq_n_f32(+8.3333293855e-3f);
103
+ float32x4_t const coeff_3_f32x4 = vdupq_n_f32(-1.6666666641e-1f);
104
+
105
+ // Compute round((angle / π) - 0.5)
106
+ float32x4_t quotients_f32x4 = vsubq_f32(vmulq_f32(angles_radians, pi_reciprocal_f32x4), vdupq_n_f32(0.5f));
107
+ int32x4_t multiples_of_pi_i32x4 = vcvtnq_s32_f32(quotients_f32x4);
108
+ float32x4_t rounded_quotients_f32x4 = vcvtq_f32_s32(multiples_of_pi_i32x4);
109
+
110
+ // Cody-Waite range reduction: angle = (angle - pi/2) - rounded * (pi_high + pi_low)
111
+ float32x4_t shifted_f32x4 = vsubq_f32(angles_radians, pi_half_f32x4);
112
+ float32x4_t angles_f32x4 = vfmsq_f32(shifted_f32x4, rounded_quotients_f32x4, pi_high_f32x4);
113
+ angles_f32x4 = vfmsq_f32(angles_f32x4, rounded_quotients_f32x4, pi_low_f32x4);
114
+ float32x4_t const angles_squared_f32x4 = vmulq_f32(angles_f32x4, angles_f32x4);
115
+ float32x4_t const angles_cubed_f32x4 = vmulq_f32(angles_f32x4, angles_squared_f32x4);
116
+
117
+ // Degree-9 polynomial via Horner's method
118
+ float32x4_t polynomials_f32x4 = coeff_9_f32x4;
119
+ polynomials_f32x4 = vfmaq_f32(coeff_7_f32x4, polynomials_f32x4, angles_squared_f32x4);
120
+ polynomials_f32x4 = vfmaq_f32(coeff_5_f32x4, polynomials_f32x4, angles_squared_f32x4);
121
+ polynomials_f32x4 = vfmaq_f32(coeff_3_f32x4, polynomials_f32x4, angles_squared_f32x4);
122
+ float32x4_t results_f32x4 = vfmaq_f32(angles_f32x4, angles_cubed_f32x4, polynomials_f32x4);
123
+
124
+ // If multiples_of_pi_i32x4 is even, flip the sign
125
+ int32x4_t parity_i32x4 = vandq_s32(multiples_of_pi_i32x4, vdupq_n_s32(1));
126
+ uint32x4_t even_mask_u32x4 = vceqq_s32(parity_i32x4, vdupq_n_s32(0));
127
+ float32x4_t negated_f32x4 = vnegq_f32(results_f32x4);
128
+ results_f32x4 = vbslq_f32(even_mask_u32x4, negated_f32x4, results_f32x4);
129
+ return results_f32x4;
130
+ }
131
+
132
+ NK_INTERNAL float32x4_t nk_atan_f32x4_neon_(float32x4_t const inputs) {
133
+ // Polynomial coefficients for atan approximation (8 terms)
134
+ float32x4_t const coeff_8_f32x4 = vdupq_n_f32(-0.333331018686294555664062f);
135
+ float32x4_t const coeff_7_f32x4 = vdupq_n_f32(+0.199926957488059997558594f);
136
+ float32x4_t const coeff_6_f32x4 = vdupq_n_f32(-0.142027363181114196777344f);
137
+ float32x4_t const coeff_5_f32x4 = vdupq_n_f32(+0.106347933411598205566406f);
138
+ float32x4_t const coeff_4_f32x4 = vdupq_n_f32(-0.0748900920152664184570312f);
139
+ float32x4_t const coeff_3_f32x4 = vdupq_n_f32(+0.0425049886107444763183594f);
140
+ float32x4_t const coeff_2_f32x4 = vdupq_n_f32(-0.0159569028764963150024414f);
141
+ float32x4_t const coeff_1_f32x4 = vdupq_n_f32(+0.00282363896258175373077393f);
142
+ float32x4_t const half_pi_f32x4 = vdupq_n_f32(1.5707963267948966f);
143
+
144
+ // Detect negative values_f32x4 and take absolute value
145
+ float32x4_t const zeros_f32x4 = vdupq_n_f32(0);
146
+ uint32x4_t negative_mask_u32x4 = vcltq_f32(inputs, zeros_f32x4);
147
+ float32x4_t values_f32x4 = vabsq_f32(inputs);
148
+
149
+ // Check if values_f32x4 > 1 (need reciprocal)
150
+ uint32x4_t reciprocal_mask_u32x4 = vcgtq_f32(values_f32x4, vdupq_n_f32(1.0f));
151
+
152
+ // Fast reciprocal using vrecpeq + Newton-Raphson (faster than vdivq on many Arm cores)
153
+ float32x4_t recip_f32x4 = vrecpeq_f32(values_f32x4);
154
+ recip_f32x4 = vmulq_f32(recip_f32x4, vrecpsq_f32(values_f32x4, recip_f32x4));
155
+ recip_f32x4 = vmulq_f32(recip_f32x4, vrecpsq_f32(values_f32x4, recip_f32x4));
156
+ values_f32x4 = vbslq_f32(reciprocal_mask_u32x4, recip_f32x4, values_f32x4);
157
+
158
+ // Compute powers
159
+ float32x4_t const values_squared_f32x4 = vmulq_f32(values_f32x4, values_f32x4);
160
+ float32x4_t const values_cubed_f32x4 = vmulq_f32(values_f32x4, values_squared_f32x4);
161
+
162
+ // Polynomial evaluation using Horner's method
163
+ float32x4_t polynomials_f32x4 = coeff_1_f32x4;
164
+ polynomials_f32x4 = vfmaq_f32(coeff_2_f32x4, polynomials_f32x4, values_squared_f32x4);
165
+ polynomials_f32x4 = vfmaq_f32(coeff_3_f32x4, polynomials_f32x4, values_squared_f32x4);
166
+ polynomials_f32x4 = vfmaq_f32(coeff_4_f32x4, polynomials_f32x4, values_squared_f32x4);
167
+ polynomials_f32x4 = vfmaq_f32(coeff_5_f32x4, polynomials_f32x4, values_squared_f32x4);
168
+ polynomials_f32x4 = vfmaq_f32(coeff_6_f32x4, polynomials_f32x4, values_squared_f32x4);
169
+ polynomials_f32x4 = vfmaq_f32(coeff_7_f32x4, polynomials_f32x4, values_squared_f32x4);
170
+ polynomials_f32x4 = vfmaq_f32(coeff_8_f32x4, polynomials_f32x4, values_squared_f32x4);
171
+
172
+ // Compute result_f32x4: atan(x) ≈ x + x³ * P(x²)
173
+ float32x4_t result_f32x4 = vfmaq_f32(values_f32x4, values_cubed_f32x4, polynomials_f32x4);
174
+
175
+ // Adjust for reciprocal: result_f32x4 = π/2 - result_f32x4
176
+ float32x4_t adjusted_f32x4 = vsubq_f32(half_pi_f32x4, result_f32x4);
177
+ result_f32x4 = vbslq_f32(reciprocal_mask_u32x4, adjusted_f32x4, result_f32x4);
178
+
179
+ // Adjust for negative: result_f32x4 = -result_f32x4
180
+ float32x4_t negated_f32x4 = vnegq_f32(result_f32x4);
181
+ result_f32x4 = vbslq_f32(negative_mask_u32x4, negated_f32x4, result_f32x4);
182
+ return result_f32x4;
183
+ }
184
+
185
+ NK_INTERNAL float32x4_t nk_atan2_f32x4_neon_(float32x4_t const ys_inputs, float32x4_t const xs_inputs) {
186
+ // Polynomial coefficients (same as atan)
187
+ float32x4_t const coeff_8_f32x4 = vdupq_n_f32(-0.333331018686294555664062f);
188
+ float32x4_t const coeff_7_f32x4 = vdupq_n_f32(+0.199926957488059997558594f);
189
+ float32x4_t const coeff_6_f32x4 = vdupq_n_f32(-0.142027363181114196777344f);
190
+ float32x4_t const coeff_5_f32x4 = vdupq_n_f32(+0.106347933411598205566406f);
191
+ float32x4_t const coeff_4_f32x4 = vdupq_n_f32(-0.0748900920152664184570312f);
192
+ float32x4_t const coeff_3_f32x4 = vdupq_n_f32(+0.0425049886107444763183594f);
193
+ float32x4_t const coeff_2_f32x4 = vdupq_n_f32(-0.0159569028764963150024414f);
194
+ float32x4_t const coeff_1_f32x4 = vdupq_n_f32(+0.00282363896258175373077393f);
195
+ float32x4_t const half_pi_f32x4 = vdupq_n_f32(1.5707963267948966f);
196
+ float32x4_t const zeros_f32x4 = vdupq_n_f32(0);
197
+
198
+ // Quadrant adjustments - take absolute values
199
+ uint32x4_t xs_negative_mask_u32x4 = vcltq_f32(xs_inputs, zeros_f32x4);
200
+ float32x4_t xs_f32x4 = vabsq_f32(xs_inputs);
201
+ float32x4_t ys_f32x4 = vabsq_f32(ys_inputs);
202
+
203
+ // Ensure proper fraction where numerator < denominator
204
+ uint32x4_t swap_mask_u32x4 = vcgtq_f32(ys_f32x4, xs_f32x4);
205
+ float32x4_t temps_f32x4 = xs_f32x4;
206
+ xs_f32x4 = vbslq_f32(swap_mask_u32x4, ys_f32x4, xs_f32x4);
207
+ ys_f32x4 = vbslq_f32(swap_mask_u32x4, vnegq_f32(temps_f32x4), ys_f32x4);
208
+
209
+ // Fast reciprocal for division: ratio_f32x4 = ys_f32x4 / xs_f32x4 ≈ ys_f32x4 * recip_f32x4(xs_f32x4)
210
+ float32x4_t recip_f32x4 = vrecpeq_f32(xs_f32x4);
211
+ recip_f32x4 = vmulq_f32(recip_f32x4, vrecpsq_f32(xs_f32x4, recip_f32x4));
212
+ recip_f32x4 = vmulq_f32(recip_f32x4, vrecpsq_f32(xs_f32x4, recip_f32x4));
213
+ float32x4_t const ratio_f32x4 = vmulq_f32(ys_f32x4, recip_f32x4);
214
+ float32x4_t const ratio_squared_f32x4 = vmulq_f32(ratio_f32x4, ratio_f32x4);
215
+ float32x4_t const ratio_cubed_f32x4 = vmulq_f32(ratio_f32x4, ratio_squared_f32x4);
216
+
217
+ // Polynomial evaluation using Horner's method
218
+ float32x4_t polynomials_f32x4 = coeff_1_f32x4;
219
+ polynomials_f32x4 = vfmaq_f32(coeff_2_f32x4, polynomials_f32x4, ratio_squared_f32x4);
220
+ polynomials_f32x4 = vfmaq_f32(coeff_3_f32x4, polynomials_f32x4, ratio_squared_f32x4);
221
+ polynomials_f32x4 = vfmaq_f32(coeff_4_f32x4, polynomials_f32x4, ratio_squared_f32x4);
222
+ polynomials_f32x4 = vfmaq_f32(coeff_5_f32x4, polynomials_f32x4, ratio_squared_f32x4);
223
+ polynomials_f32x4 = vfmaq_f32(coeff_6_f32x4, polynomials_f32x4, ratio_squared_f32x4);
224
+ polynomials_f32x4 = vfmaq_f32(coeff_7_f32x4, polynomials_f32x4, ratio_squared_f32x4);
225
+ polynomials_f32x4 = vfmaq_f32(coeff_8_f32x4, polynomials_f32x4, ratio_squared_f32x4);
226
+
227
+ // Compute the result
228
+ float32x4_t results_f32x4 = vfmaq_f32(ratio_f32x4, ratio_cubed_f32x4, polynomials_f32x4);
229
+
230
+ // Compute quadrant_f32x4 value: 0 for x>=0 && !swap, 1 for x>=0 && swap,
231
+ // -2 for x<0 && !swap, -1 for x<0 && swap
232
+ float32x4_t quadrant_f32x4 = vdupq_n_f32(0.0f);
233
+ float32x4_t neg_two_f32x4 = vdupq_n_f32(-2.0f);
234
+ quadrant_f32x4 = vbslq_f32(xs_negative_mask_u32x4, neg_two_f32x4, quadrant_f32x4);
235
+ float32x4_t quadrant_incremented_f32x4 = vaddq_f32(quadrant_f32x4, vdupq_n_f32(1.0f));
236
+ quadrant_f32x4 = vbslq_f32(swap_mask_u32x4, quadrant_incremented_f32x4, quadrant_f32x4);
237
+
238
+ // Adjust for quadrant_f32x4: result += quadrant_f32x4 * π/2
239
+ results_f32x4 = vfmaq_f32(results_f32x4, quadrant_f32x4, half_pi_f32x4);
240
+
241
+ // Transfer sign from x and y by XOR with sign bits
242
+ uint32x4_t sign_mask_u32x4 = vreinterpretq_u32_f32(vdupq_n_f32(-0.0f));
243
+ uint32x4_t xs_sign_u32x4 = vandq_u32(vreinterpretq_u32_f32(xs_inputs), sign_mask_u32x4);
244
+ uint32x4_t ys_sign_u32x4 = vandq_u32(vreinterpretq_u32_f32(ys_inputs), sign_mask_u32x4);
245
+ uint32x4_t result_bits_u32x4 = vreinterpretq_u32_f32(results_f32x4);
246
+ result_bits_u32x4 = veorq_u32(result_bits_u32x4, xs_sign_u32x4);
247
+ result_bits_u32x4 = veorq_u32(result_bits_u32x4, ys_sign_u32x4);
248
+ results_f32x4 = vreinterpretq_f32_u32(result_bits_u32x4);
249
+
250
+ return results_f32x4;
251
+ }
252
+
253
+ NK_INTERNAL float64x2_t nk_sin_f64x2_neon_(float64x2_t const angles_radians) {
254
+ // Constants for argument reduction
255
+ float64x2_t const pi_high_f64x2 = vdupq_n_f64(3.141592653589793116);
256
+ float64x2_t const pi_low_f64x2 = vdupq_n_f64(1.2246467991473532072e-16);
257
+ float64x2_t const pi_reciprocal_f64x2 = vdupq_n_f64(0.31830988618379067154);
258
+
259
+ // Polynomial coefficients for sine approximation
260
+ float64x2_t const coeff_0_f64x2 = vdupq_n_f64(+0.00833333333333332974823815);
261
+ float64x2_t const coeff_1_f64x2 = vdupq_n_f64(-0.000198412698412696162806809);
262
+ float64x2_t const coeff_2_f64x2 = vdupq_n_f64(+2.75573192239198747630416e-06);
263
+ float64x2_t const coeff_3_f64x2 = vdupq_n_f64(-2.50521083763502045810755e-08);
264
+ float64x2_t const coeff_4_f64x2 = vdupq_n_f64(+1.60590430605664501629054e-10);
265
+ float64x2_t const coeff_5_f64x2 = vdupq_n_f64(-7.64712219118158833288484e-13);
266
+ float64x2_t const coeff_6_f64x2 = vdupq_n_f64(+2.81009972710863200091251e-15);
267
+ float64x2_t const coeff_7_f64x2 = vdupq_n_f64(-7.97255955009037868891952e-18);
268
+ float64x2_t const coeff_8_f64x2 = vdupq_n_f64(-0.166666666666666657414808);
269
+
270
+ // Compute round(angle / π)
271
+ float64x2_t const quotients_f64x2 = vmulq_f64(angles_radians, pi_reciprocal_f64x2);
272
+ int64x2_t multiples_of_pi_i64x2 = vcvtnq_s64_f64(quotients_f64x2);
273
+ float64x2_t rounded_quotients_f64x2 = vcvtq_f64_s64(multiples_of_pi_i64x2);
274
+
275
+ // Two-step Cody-Waite reduction: angle - rounded * π_high - rounded * π_low
276
+ float64x2_t angles_f64x2 = angles_radians;
277
+ angles_f64x2 = vfmsq_f64(angles_f64x2, rounded_quotients_f64x2, pi_high_f64x2);
278
+ angles_f64x2 = vfmsq_f64(angles_f64x2, rounded_quotients_f64x2, pi_low_f64x2);
279
+
280
+ // If multiples_of_pi_i64x2 is odd, negate the angle
281
+ int64x2_t parity_i64x2 = vandq_s64(multiples_of_pi_i64x2, vdupq_n_s64(1));
282
+ uint64x2_t odd_mask_u64x2 = vceqq_s64(parity_i64x2, vdupq_n_s64(1));
283
+ float64x2_t negated_angles_f64x2 = vnegq_f64(angles_f64x2);
284
+ angles_f64x2 = vbslq_f64(odd_mask_u64x2, negated_angles_f64x2, angles_f64x2);
285
+
286
+ float64x2_t const angles_squared_f64x2 = vmulq_f64(angles_f64x2, angles_f64x2);
287
+ float64x2_t const angles_cubed_f64x2 = vmulq_f64(angles_f64x2, angles_squared_f64x2);
288
+ float64x2_t const angles_quadratic_f64x2 = vmulq_f64(angles_squared_f64x2, angles_squared_f64x2);
289
+ float64x2_t const angles_octic_f64x2 = vmulq_f64(angles_quadratic_f64x2, angles_quadratic_f64x2);
290
+
291
+ // Compute polynomial terms using Estrin's scheme for better ILP
292
+ float64x2_t const poly_67_f64x2 = vfmaq_f64(coeff_6_f64x2, angles_squared_f64x2, coeff_7_f64x2);
293
+ float64x2_t const poly_45_f64x2 = vfmaq_f64(coeff_4_f64x2, angles_squared_f64x2, coeff_5_f64x2);
294
+ float64x2_t const poly_4567_f64x2 = vfmaq_f64(poly_45_f64x2, angles_quadratic_f64x2, poly_67_f64x2);
295
+
296
+ float64x2_t const poly_23_f64x2 = vfmaq_f64(coeff_2_f64x2, angles_squared_f64x2, coeff_3_f64x2);
297
+ float64x2_t const poly_01_f64x2 = vfmaq_f64(coeff_0_f64x2, angles_squared_f64x2, coeff_1_f64x2);
298
+ float64x2_t const poly_0123_f64x2 = vfmaq_f64(poly_01_f64x2, angles_quadratic_f64x2, poly_23_f64x2);
299
+
300
+ // Combine polynomial terms
301
+ float64x2_t results_f64x2 = vfmaq_f64(poly_0123_f64x2, angles_octic_f64x2, poly_4567_f64x2);
302
+ results_f64x2 = vfmaq_f64(coeff_8_f64x2, results_f64x2, angles_squared_f64x2);
303
+ results_f64x2 = vfmaq_f64(angles_f64x2, results_f64x2, angles_cubed_f64x2);
304
+
305
+ // Handle zero input (preserve sign of zero)
306
+ uint64x2_t const non_zero_mask_u64x2 = vceqq_f64(angles_radians, vdupq_n_f64(0));
307
+ results_f64x2 = vbslq_f64(non_zero_mask_u64x2, angles_radians, results_f64x2);
308
+ return results_f64x2;
309
+ }
310
+
311
+ NK_INTERNAL float64x2_t nk_cos_f64x2_neon_(float64x2_t const angles_radians) {
312
+ // Constants for argument reduction
313
+ float64x2_t const pi_high_half_f64x2 = vdupq_n_f64(3.141592653589793116 * 0.5);
314
+ float64x2_t const pi_low_half_f64x2 = vdupq_n_f64(1.2246467991473532072e-16 * 0.5);
315
+ float64x2_t const pi_reciprocal_f64x2 = vdupq_n_f64(0.31830988618379067154);
316
+
317
+ // Polynomial coefficients for cosine approximation
318
+ float64x2_t const coeff_0_f64x2 = vdupq_n_f64(+0.00833333333333332974823815);
319
+ float64x2_t const coeff_1_f64x2 = vdupq_n_f64(-0.000198412698412696162806809);
320
+ float64x2_t const coeff_2_f64x2 = vdupq_n_f64(+2.75573192239198747630416e-06);
321
+ float64x2_t const coeff_3_f64x2 = vdupq_n_f64(-2.50521083763502045810755e-08);
322
+ float64x2_t const coeff_4_f64x2 = vdupq_n_f64(+1.60590430605664501629054e-10);
323
+ float64x2_t const coeff_5_f64x2 = vdupq_n_f64(-7.64712219118158833288484e-13);
324
+ float64x2_t const coeff_6_f64x2 = vdupq_n_f64(+2.81009972710863200091251e-15);
325
+ float64x2_t const coeff_7_f64x2 = vdupq_n_f64(-7.97255955009037868891952e-18);
326
+ float64x2_t const coeff_8_f64x2 = vdupq_n_f64(-0.166666666666666657414808);
327
+
328
+ // Compute 2 * round(angle / π - 0.5) + 1
329
+ float64x2_t const quotients_f64x2 = vsubq_f64(vmulq_f64(angles_radians, pi_reciprocal_f64x2), vdupq_n_f64(0.5));
330
+ float64x2_t const rounded_f64x2 = vcvtq_f64_s64(vcvtnq_s64_f64(quotients_f64x2));
331
+ float64x2_t const rounded_quotients_f64x2 = vfmaq_f64(vdupq_n_f64(1.0), vdupq_n_f64(2.0), rounded_f64x2);
332
+ int64x2_t quotients_i64_i64x2 = vcvtnq_s64_f64(rounded_quotients_f64x2);
333
+
334
+ // Two-step Cody-Waite reduction
335
+ float64x2_t angles_f64x2 = angles_radians;
336
+ angles_f64x2 = vfmsq_f64(angles_f64x2, rounded_quotients_f64x2, pi_high_half_f64x2);
337
+ angles_f64x2 = vfmsq_f64(angles_f64x2, rounded_quotients_f64x2, pi_low_half_f64x2);
338
+
339
+ // If (rounded_quotients_f64x2 & 2) == 0, negate the angle
340
+ int64x2_t bit2_i64x2 = vandq_s64(quotients_i64_i64x2, vdupq_n_s64(2));
341
+ uint64x2_t flip_mask_u64x2 = vceqq_s64(bit2_i64x2, vdupq_n_s64(0));
342
+ float64x2_t negated_angles_f64x2 = vnegq_f64(angles_f64x2);
343
+ angles_f64x2 = vbslq_f64(flip_mask_u64x2, negated_angles_f64x2, angles_f64x2);
344
+
345
+ float64x2_t const angles_squared_f64x2 = vmulq_f64(angles_f64x2, angles_f64x2);
346
+ float64x2_t const angles_cubed_f64x2 = vmulq_f64(angles_f64x2, angles_squared_f64x2);
347
+ float64x2_t const angles_quadratic_f64x2 = vmulq_f64(angles_squared_f64x2, angles_squared_f64x2);
348
+ float64x2_t const angles_octic_f64x2 = vmulq_f64(angles_quadratic_f64x2, angles_quadratic_f64x2);
349
+
350
+ // Compute polynomial terms using Estrin's scheme
351
+ float64x2_t const poly_67_f64x2 = vfmaq_f64(coeff_6_f64x2, angles_squared_f64x2, coeff_7_f64x2);
352
+ float64x2_t const poly_45_f64x2 = vfmaq_f64(coeff_4_f64x2, angles_squared_f64x2, coeff_5_f64x2);
353
+ float64x2_t const poly_4567_f64x2 = vfmaq_f64(poly_45_f64x2, angles_quadratic_f64x2, poly_67_f64x2);
354
+
355
+ float64x2_t const poly_23_f64x2 = vfmaq_f64(coeff_2_f64x2, angles_squared_f64x2, coeff_3_f64x2);
356
+ float64x2_t const poly_01_f64x2 = vfmaq_f64(coeff_0_f64x2, angles_squared_f64x2, coeff_1_f64x2);
357
+ float64x2_t const poly_0123_f64x2 = vfmaq_f64(poly_01_f64x2, angles_quadratic_f64x2, poly_23_f64x2);
358
+
359
+ // Combine polynomial terms
360
+ float64x2_t results_f64x2 = vfmaq_f64(poly_0123_f64x2, angles_octic_f64x2, poly_4567_f64x2);
361
+ results_f64x2 = vfmaq_f64(coeff_8_f64x2, results_f64x2, angles_squared_f64x2);
362
+ results_f64x2 = vfmaq_f64(angles_f64x2, results_f64x2, angles_cubed_f64x2);
363
+ return results_f64x2;
364
+ }
365
+
366
+ NK_INTERNAL float64x2_t nk_atan_f64x2_neon_(float64x2_t const inputs) {
367
+ // Polynomial coefficients for atan approximation (19 terms)
368
+ float64x2_t const coeff_19_f64x2 = vdupq_n_f64(-1.88796008463073496563746e-05);
369
+ float64x2_t const coeff_18_f64x2 = vdupq_n_f64(+0.000209850076645816976906797);
370
+ float64x2_t const coeff_17_f64x2 = vdupq_n_f64(-0.00110611831486672482563471);
371
+ float64x2_t const coeff_16_f64x2 = vdupq_n_f64(+0.00370026744188713119232403);
372
+ float64x2_t const coeff_15_f64x2 = vdupq_n_f64(-0.00889896195887655491740809);
373
+ float64x2_t const coeff_14_f64x2 = vdupq_n_f64(+0.016599329773529201970117);
374
+ float64x2_t const coeff_13_f64x2 = vdupq_n_f64(-0.0254517624932312641616861);
375
+ float64x2_t const coeff_12_f64x2 = vdupq_n_f64(+0.0337852580001353069993897);
376
+ float64x2_t const coeff_11_f64x2 = vdupq_n_f64(-0.0407629191276836500001934);
377
+ float64x2_t const coeff_10_f64x2 = vdupq_n_f64(+0.0466667150077840625632675);
378
+ float64x2_t const coeff_9_f64x2 = vdupq_n_f64(-0.0523674852303482457616113);
379
+ float64x2_t const coeff_8_f64x2 = vdupq_n_f64(+0.0587666392926673580854313);
380
+ float64x2_t const coeff_7_f64x2 = vdupq_n_f64(-0.0666573579361080525984562);
381
+ float64x2_t const coeff_6_f64x2 = vdupq_n_f64(+0.0769219538311769618355029);
382
+ float64x2_t const coeff_5_f64x2 = vdupq_n_f64(-0.090908995008245008229153);
383
+ float64x2_t const coeff_4_f64x2 = vdupq_n_f64(+0.111111105648261418443745);
384
+ float64x2_t const coeff_3_f64x2 = vdupq_n_f64(-0.14285714266771329383765);
385
+ float64x2_t const coeff_2_f64x2 = vdupq_n_f64(+0.199999999996591265594148);
386
+ float64x2_t const coeff_1_f64x2 = vdupq_n_f64(-0.333333333333311110369124);
387
+ float64x2_t const half_pi_f64x2 = vdupq_n_f64(1.5707963267948966);
388
+ float64x2_t const zeros_f64x2 = vdupq_n_f64(0);
389
+
390
+ // Detect negative and take absolute value
391
+ uint64x2_t negative_mask_u64x2 = vcltq_f64(inputs, zeros_f64x2);
392
+ float64x2_t values_f64x2 = vabsq_f64(inputs);
393
+
394
+ // Check if values_f64x2 > 1 (need reciprocal) - use division for f64 precision
395
+ uint64x2_t reciprocal_mask_u64x2 = vcgtq_f64(values_f64x2, vdupq_n_f64(1.0));
396
+ float64x2_t reciprocal_values_f64x2 = vdivq_f64(vdupq_n_f64(1.0), values_f64x2);
397
+ values_f64x2 = vbslq_f64(reciprocal_mask_u64x2, reciprocal_values_f64x2, values_f64x2);
398
+
399
+ // Compute powers
400
+ float64x2_t const values_squared_f64x2 = vmulq_f64(values_f64x2, values_f64x2);
401
+ float64x2_t const values_cubed_f64x2 = vmulq_f64(values_f64x2, values_squared_f64x2);
402
+
403
+ // Polynomial evaluation using Horner's method
404
+ float64x2_t polynomials_f64x2 = coeff_19_f64x2;
405
+ polynomials_f64x2 = vfmaq_f64(coeff_18_f64x2, polynomials_f64x2, values_squared_f64x2);
406
+ polynomials_f64x2 = vfmaq_f64(coeff_17_f64x2, polynomials_f64x2, values_squared_f64x2);
407
+ polynomials_f64x2 = vfmaq_f64(coeff_16_f64x2, polynomials_f64x2, values_squared_f64x2);
408
+ polynomials_f64x2 = vfmaq_f64(coeff_15_f64x2, polynomials_f64x2, values_squared_f64x2);
409
+ polynomials_f64x2 = vfmaq_f64(coeff_14_f64x2, polynomials_f64x2, values_squared_f64x2);
410
+ polynomials_f64x2 = vfmaq_f64(coeff_13_f64x2, polynomials_f64x2, values_squared_f64x2);
411
+ polynomials_f64x2 = vfmaq_f64(coeff_12_f64x2, polynomials_f64x2, values_squared_f64x2);
412
+ polynomials_f64x2 = vfmaq_f64(coeff_11_f64x2, polynomials_f64x2, values_squared_f64x2);
413
+ polynomials_f64x2 = vfmaq_f64(coeff_10_f64x2, polynomials_f64x2, values_squared_f64x2);
414
+ polynomials_f64x2 = vfmaq_f64(coeff_9_f64x2, polynomials_f64x2, values_squared_f64x2);
415
+ polynomials_f64x2 = vfmaq_f64(coeff_8_f64x2, polynomials_f64x2, values_squared_f64x2);
416
+ polynomials_f64x2 = vfmaq_f64(coeff_7_f64x2, polynomials_f64x2, values_squared_f64x2);
417
+ polynomials_f64x2 = vfmaq_f64(coeff_6_f64x2, polynomials_f64x2, values_squared_f64x2);
418
+ polynomials_f64x2 = vfmaq_f64(coeff_5_f64x2, polynomials_f64x2, values_squared_f64x2);
419
+ polynomials_f64x2 = vfmaq_f64(coeff_4_f64x2, polynomials_f64x2, values_squared_f64x2);
420
+ polynomials_f64x2 = vfmaq_f64(coeff_3_f64x2, polynomials_f64x2, values_squared_f64x2);
421
+ polynomials_f64x2 = vfmaq_f64(coeff_2_f64x2, polynomials_f64x2, values_squared_f64x2);
422
+ polynomials_f64x2 = vfmaq_f64(coeff_1_f64x2, polynomials_f64x2, values_squared_f64x2);
423
+
424
+ // Compute result_f64x2
425
+ float64x2_t result_f64x2 = vfmaq_f64(values_f64x2, values_cubed_f64x2, polynomials_f64x2);
426
+
427
+ // Adjust for reciprocal: result_f64x2 = π/2 - result_f64x2
428
+ float64x2_t adjusted_f64x2 = vsubq_f64(half_pi_f64x2, result_f64x2);
429
+ result_f64x2 = vbslq_f64(reciprocal_mask_u64x2, adjusted_f64x2, result_f64x2);
430
+
431
+ // Adjust for negative: result_f64x2 = -result_f64x2
432
+ float64x2_t negated_f64x2 = vnegq_f64(result_f64x2);
433
+ result_f64x2 = vbslq_f64(negative_mask_u64x2, negated_f64x2, result_f64x2);
434
+ return result_f64x2;
435
+ }
436
+
437
+ NK_INTERNAL float64x2_t nk_atan2_f64x2_neon_(float64x2_t const ys_inputs, float64x2_t const xs_inputs) {
438
+ // Polynomial coefficients (same as atan)
439
+ float64x2_t const coeff_19_f64x2 = vdupq_n_f64(-1.88796008463073496563746e-05);
440
+ float64x2_t const coeff_18_f64x2 = vdupq_n_f64(+0.000209850076645816976906797);
441
+ float64x2_t const coeff_17_f64x2 = vdupq_n_f64(-0.00110611831486672482563471);
442
+ float64x2_t const coeff_16_f64x2 = vdupq_n_f64(+0.00370026744188713119232403);
443
+ float64x2_t const coeff_15_f64x2 = vdupq_n_f64(-0.00889896195887655491740809);
444
+ float64x2_t const coeff_14_f64x2 = vdupq_n_f64(+0.016599329773529201970117);
445
+ float64x2_t const coeff_13_f64x2 = vdupq_n_f64(-0.0254517624932312641616861);
446
+ float64x2_t const coeff_12_f64x2 = vdupq_n_f64(+0.0337852580001353069993897);
447
+ float64x2_t const coeff_11_f64x2 = vdupq_n_f64(-0.0407629191276836500001934);
448
+ float64x2_t const coeff_10_f64x2 = vdupq_n_f64(+0.0466667150077840625632675);
449
+ float64x2_t const coeff_9_f64x2 = vdupq_n_f64(-0.0523674852303482457616113);
450
+ float64x2_t const coeff_8_f64x2 = vdupq_n_f64(+0.0587666392926673580854313);
451
+ float64x2_t const coeff_7_f64x2 = vdupq_n_f64(-0.0666573579361080525984562);
452
+ float64x2_t const coeff_6_f64x2 = vdupq_n_f64(+0.0769219538311769618355029);
453
+ float64x2_t const coeff_5_f64x2 = vdupq_n_f64(-0.090908995008245008229153);
454
+ float64x2_t const coeff_4_f64x2 = vdupq_n_f64(+0.111111105648261418443745);
455
+ float64x2_t const coeff_3_f64x2 = vdupq_n_f64(-0.14285714266771329383765);
456
+ float64x2_t const coeff_2_f64x2 = vdupq_n_f64(+0.199999999996591265594148);
457
+ float64x2_t const coeff_1_f64x2 = vdupq_n_f64(-0.333333333333311110369124);
458
+ float64x2_t const half_pi_f64x2 = vdupq_n_f64(1.5707963267948966);
459
+ float64x2_t const zeros_f64x2 = vdupq_n_f64(0);
460
+
461
+ // Quadrant adjustments - take absolute values
462
+ uint64x2_t xs_negative_mask_u64x2 = vcltq_f64(xs_inputs, zeros_f64x2);
463
+ float64x2_t xs_f64x2 = vabsq_f64(xs_inputs);
464
+ float64x2_t ys_f64x2 = vabsq_f64(ys_inputs);
465
+
466
+ // Ensure proper fraction where numerator < denominator
467
+ uint64x2_t swap_mask_u64x2 = vcgtq_f64(ys_f64x2, xs_f64x2);
468
+ float64x2_t temps_f64x2 = xs_f64x2;
469
+ xs_f64x2 = vbslq_f64(swap_mask_u64x2, ys_f64x2, xs_f64x2);
470
+ ys_f64x2 = vbslq_f64(swap_mask_u64x2, vnegq_f64(temps_f64x2), ys_f64x2);
471
+
472
+ // Division for f64 precision
473
+ float64x2_t const ratio_f64x2 = vdivq_f64(ys_f64x2, xs_f64x2);
474
+ float64x2_t const ratio_squared_f64x2 = vmulq_f64(ratio_f64x2, ratio_f64x2);
475
+ float64x2_t const ratio_cubed_f64x2 = vmulq_f64(ratio_f64x2, ratio_squared_f64x2);
476
+
477
+ // Polynomial evaluation using Horner's method
478
+ float64x2_t polynomials_f64x2 = coeff_19_f64x2;
479
+ polynomials_f64x2 = vfmaq_f64(coeff_18_f64x2, polynomials_f64x2, ratio_squared_f64x2);
480
+ polynomials_f64x2 = vfmaq_f64(coeff_17_f64x2, polynomials_f64x2, ratio_squared_f64x2);
481
+ polynomials_f64x2 = vfmaq_f64(coeff_16_f64x2, polynomials_f64x2, ratio_squared_f64x2);
482
+ polynomials_f64x2 = vfmaq_f64(coeff_15_f64x2, polynomials_f64x2, ratio_squared_f64x2);
483
+ polynomials_f64x2 = vfmaq_f64(coeff_14_f64x2, polynomials_f64x2, ratio_squared_f64x2);
484
+ polynomials_f64x2 = vfmaq_f64(coeff_13_f64x2, polynomials_f64x2, ratio_squared_f64x2);
485
+ polynomials_f64x2 = vfmaq_f64(coeff_12_f64x2, polynomials_f64x2, ratio_squared_f64x2);
486
+ polynomials_f64x2 = vfmaq_f64(coeff_11_f64x2, polynomials_f64x2, ratio_squared_f64x2);
487
+ polynomials_f64x2 = vfmaq_f64(coeff_10_f64x2, polynomials_f64x2, ratio_squared_f64x2);
488
+ polynomials_f64x2 = vfmaq_f64(coeff_9_f64x2, polynomials_f64x2, ratio_squared_f64x2);
489
+ polynomials_f64x2 = vfmaq_f64(coeff_8_f64x2, polynomials_f64x2, ratio_squared_f64x2);
490
+ polynomials_f64x2 = vfmaq_f64(coeff_7_f64x2, polynomials_f64x2, ratio_squared_f64x2);
491
+ polynomials_f64x2 = vfmaq_f64(coeff_6_f64x2, polynomials_f64x2, ratio_squared_f64x2);
492
+ polynomials_f64x2 = vfmaq_f64(coeff_5_f64x2, polynomials_f64x2, ratio_squared_f64x2);
493
+ polynomials_f64x2 = vfmaq_f64(coeff_4_f64x2, polynomials_f64x2, ratio_squared_f64x2);
494
+ polynomials_f64x2 = vfmaq_f64(coeff_3_f64x2, polynomials_f64x2, ratio_squared_f64x2);
495
+ polynomials_f64x2 = vfmaq_f64(coeff_2_f64x2, polynomials_f64x2, ratio_squared_f64x2);
496
+ polynomials_f64x2 = vfmaq_f64(coeff_1_f64x2, polynomials_f64x2, ratio_squared_f64x2);
497
+
498
+ // Compute the result
499
+ float64x2_t results_f64x2 = vfmaq_f64(ratio_f64x2, ratio_cubed_f64x2, polynomials_f64x2);
500
+
501
+ // Compute quadrant_f64x2 value: 0 for x>=0 && !swap, 1 for x>=0 && swap,
502
+ // -2 for x<0 && !swap, -1 for x<0 && swap
503
+ float64x2_t quadrant_f64x2 = vdupq_n_f64(0.0);
504
+ float64x2_t neg_two_f64x2 = vdupq_n_f64(-2.0);
505
+ quadrant_f64x2 = vbslq_f64(xs_negative_mask_u64x2, neg_two_f64x2, quadrant_f64x2);
506
+ float64x2_t quadrant_incremented_f64x2 = vaddq_f64(quadrant_f64x2, vdupq_n_f64(1.0));
507
+ quadrant_f64x2 = vbslq_f64(swap_mask_u64x2, quadrant_incremented_f64x2, quadrant_f64x2);
508
+
509
+ // Adjust for quadrant_f64x2: result += quadrant_f64x2 * π/2
510
+ results_f64x2 = vfmaq_f64(results_f64x2, quadrant_f64x2, half_pi_f64x2);
511
+
512
+ // Transfer sign from x and y by XOR with sign bits
513
+ uint64x2_t sign_mask_u64x2 = vreinterpretq_u64_f64(vdupq_n_f64(-0.0));
514
+ uint64x2_t xs_sign_u64x2 = vandq_u64(vreinterpretq_u64_f64(xs_inputs), sign_mask_u64x2);
515
+ uint64x2_t ys_sign_u64x2 = vandq_u64(vreinterpretq_u64_f64(ys_inputs), sign_mask_u64x2);
516
+ uint64x2_t result_bits_u64x2 = vreinterpretq_u64_f64(results_f64x2);
517
+ result_bits_u64x2 = veorq_u64(result_bits_u64x2, xs_sign_u64x2);
518
+ result_bits_u64x2 = veorq_u64(result_bits_u64x2, ys_sign_u64x2);
519
+ results_f64x2 = vreinterpretq_f64_u64(result_bits_u64x2);
520
+
521
+ return results_f64x2;
522
+ }
523
+
524
+ NK_PUBLIC void nk_each_sin_f32_neon(nk_f32_t const *ins, nk_size_t n, nk_f32_t *outs) {
525
+ nk_size_t i = 0;
526
+ for (; i + 4 <= n; i += 4) {
527
+ float32x4_t angles_f32x4 = vld1q_f32(ins + i);
528
+ float32x4_t results_f32x4 = nk_sin_f32x4_neon_(angles_f32x4);
529
+ vst1q_f32(outs + i, results_f32x4);
530
+ }
531
+ if (i < n) {
532
+ nk_size_t remaining = n - i;
533
+ nk_b128_vec_t angles_vec;
534
+ nk_partial_load_b32x4_serial_(ins + i, &angles_vec, remaining);
535
+ nk_b128_vec_t results_vec;
536
+ results_vec.f32x4 = nk_sin_f32x4_neon_(angles_vec.f32x4);
537
+ nk_partial_store_b32x4_serial_(&results_vec, outs + i, remaining);
538
+ }
539
+ }
540
+
541
+ NK_PUBLIC void nk_each_cos_f32_neon(nk_f32_t const *ins, nk_size_t n, nk_f32_t *outs) {
542
+ nk_size_t i = 0;
543
+ for (; i + 4 <= n; i += 4) {
544
+ float32x4_t angles_f32x4 = vld1q_f32(ins + i);
545
+ float32x4_t results_f32x4 = nk_cos_f32x4_neon_(angles_f32x4);
546
+ vst1q_f32(outs + i, results_f32x4);
547
+ }
548
+ if (i < n) {
549
+ nk_size_t remaining = n - i;
550
+ nk_b128_vec_t angles_vec;
551
+ nk_partial_load_b32x4_serial_(ins + i, &angles_vec, remaining);
552
+ nk_b128_vec_t results_vec;
553
+ results_vec.f32x4 = nk_cos_f32x4_neon_(angles_vec.f32x4);
554
+ nk_partial_store_b32x4_serial_(&results_vec, outs + i, remaining);
555
+ }
556
+ }
557
+
558
+ NK_PUBLIC void nk_each_atan_f32_neon(nk_f32_t const *ins, nk_size_t n, nk_f32_t *outs) {
559
+ nk_size_t i = 0;
560
+ for (; i + 4 <= n; i += 4) {
561
+ float32x4_t values_f32x4 = vld1q_f32(ins + i);
562
+ float32x4_t results_f32x4 = nk_atan_f32x4_neon_(values_f32x4);
563
+ vst1q_f32(outs + i, results_f32x4);
564
+ }
565
+ if (i < n) {
566
+ nk_size_t remaining = n - i;
567
+ nk_b128_vec_t values_vec;
568
+ nk_partial_load_b32x4_serial_(ins + i, &values_vec, remaining);
569
+ nk_b128_vec_t results_vec;
570
+ results_vec.f32x4 = nk_atan_f32x4_neon_(values_vec.f32x4);
571
+ nk_partial_store_b32x4_serial_(&results_vec, outs + i, remaining);
572
+ }
573
+ }
574
+
575
+ NK_PUBLIC void nk_each_sin_f64_neon(nk_f64_t const *ins, nk_size_t n, nk_f64_t *outs) {
576
+ nk_size_t i = 0;
577
+ for (; i + 2 <= n; i += 2) {
578
+ float64x2_t angles_f64x2 = vld1q_f64(ins + i);
579
+ float64x2_t results_f64x2 = nk_sin_f64x2_neon_(angles_f64x2);
580
+ vst1q_f64(outs + i, results_f64x2);
581
+ }
582
+ if (i < n) {
583
+ nk_size_t remaining = n - i;
584
+ nk_b128_vec_t angles_vec;
585
+ nk_partial_load_b64x2_serial_(ins + i, &angles_vec, remaining);
586
+ nk_b128_vec_t results_vec;
587
+ results_vec.f64x2 = nk_sin_f64x2_neon_(angles_vec.f64x2);
588
+ nk_partial_store_b64x2_serial_(&results_vec, outs + i, remaining);
589
+ }
590
+ }
591
+
592
+ NK_PUBLIC void nk_each_cos_f64_neon(nk_f64_t const *ins, nk_size_t n, nk_f64_t *outs) {
593
+ nk_size_t i = 0;
594
+ for (; i + 2 <= n; i += 2) {
595
+ float64x2_t angles_f64x2 = vld1q_f64(ins + i);
596
+ float64x2_t results_f64x2 = nk_cos_f64x2_neon_(angles_f64x2);
597
+ vst1q_f64(outs + i, results_f64x2);
598
+ }
599
+ if (i < n) {
600
+ nk_size_t remaining = n - i;
601
+ nk_b128_vec_t angles_vec;
602
+ nk_partial_load_b64x2_serial_(ins + i, &angles_vec, remaining);
603
+ nk_b128_vec_t results_vec;
604
+ results_vec.f64x2 = nk_cos_f64x2_neon_(angles_vec.f64x2);
605
+ nk_partial_store_b64x2_serial_(&results_vec, outs + i, remaining);
606
+ }
607
+ }
608
+
609
+ NK_PUBLIC void nk_each_atan_f64_neon(nk_f64_t const *ins, nk_size_t n, nk_f64_t *outs) {
610
+ nk_size_t i = 0;
611
+ for (; i + 2 <= n; i += 2) {
612
+ float64x2_t values_f64x2 = vld1q_f64(ins + i);
613
+ float64x2_t results_f64x2 = nk_atan_f64x2_neon_(values_f64x2);
614
+ vst1q_f64(outs + i, results_f64x2);
615
+ }
616
+ if (i < n) {
617
+ nk_size_t remaining = n - i;
618
+ nk_b128_vec_t values_vec;
619
+ nk_partial_load_b64x2_serial_(ins + i, &values_vec, remaining);
620
+ nk_b128_vec_t results_vec;
621
+ results_vec.f64x2 = nk_atan_f64x2_neon_(values_vec.f64x2);
622
+ nk_partial_store_b64x2_serial_(&results_vec, outs + i, remaining);
623
+ }
624
+ }
625
+
626
+ #if defined(__clang__)
627
+ #pragma clang attribute pop
628
+ #elif defined(__GNUC__)
629
+ #pragma GCC pop_options
630
+ #endif
631
+
632
+ #if defined(__cplusplus)
633
+ } // extern "C"
634
+ #endif
635
+
636
+ #endif // NK_TARGET_NEON
637
+ #endif // NK_TARGET_ARM64_
638
+ #endif // NK_TRIGONOMETRY_NEON_H