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.
- package/README.md +24 -24
- package/binding.gyp +15 -37
- package/c/CMakeLists.txt +4 -5
- package/c/README.md +7 -7
- package/c/lib.cpp +32 -14
- package/c/test.c +83 -1
- package/c/usearch.h +24 -3
- package/cpp/CMakeLists.txt +4 -0
- package/cpp/README.md +5 -5
- package/cpp/bench.cpp +97 -116
- package/cpp/test.cpp +117 -20
- package/include/usearch/index.hpp +235 -52
- package/include/usearch/index_dense.hpp +105 -40
- package/include/usearch/index_plugins.hpp +1387 -204
- package/javascript/dist/cjs/usearch.d.ts +8 -3
- package/javascript/dist/cjs/usearch.js +12 -4
- package/javascript/dist/esm/usearch.d.ts +8 -3
- package/javascript/dist/esm/usearch.js +12 -4
- package/javascript/lib.cpp +17 -0
- package/javascript/usearch.ts +14 -6
- package/numkong/.clang-tidy +30 -0
- package/{simsimd → numkong}/.cmake-format.py +18 -0
- package/numkong/.editorconfig +12 -0
- package/numkong/.git-blame-ignore-revs +123 -0
- package/numkong/.mailmap +15 -0
- package/numkong/.spi.yml +11 -0
- package/numkong/.swift-format +14 -0
- package/numkong/CITATION.cff +81 -0
- package/numkong/CONTRIBUTING.md +500 -0
- package/numkong/Cargo.toml +54 -0
- package/numkong/MANIFEST.in +8 -0
- package/numkong/Package.swift +84 -0
- package/numkong/README.md +569 -0
- package/numkong/bench/README.md +217 -0
- package/numkong/bench/bench-browser.html +323 -0
- package/numkong/bench/bench.cpp +344 -0
- package/numkong/bench/bench.hpp +816 -0
- package/numkong/bench/bench.js +148 -0
- package/numkong/bench/bench.mjs +616 -0
- package/numkong/bench/bench_attention.cpp +113 -0
- package/numkong/bench/bench_cast.cpp +264 -0
- package/numkong/bench/bench_cross_amx.cpp +62 -0
- package/numkong/bench/bench_cross_arm.cpp +245 -0
- package/numkong/bench/bench_cross_blas.cpp +309 -0
- package/numkong/bench/bench_cross_loongarch.cpp +106 -0
- package/numkong/bench/bench_cross_power.cpp +84 -0
- package/numkong/bench/bench_cross_rvv.cpp +121 -0
- package/numkong/bench/bench_cross_serial.cpp +151 -0
- package/numkong/bench/bench_cross_sme.cpp +163 -0
- package/numkong/bench/bench_cross_wasm.cpp +142 -0
- package/numkong/bench/bench_cross_x86.cpp +455 -0
- package/numkong/bench/bench_curved.cpp +210 -0
- package/numkong/bench/bench_dot.cpp +315 -0
- package/numkong/bench/bench_each.cpp +503 -0
- package/numkong/bench/bench_geospatial.cpp +112 -0
- package/numkong/bench/bench_maxsim.cpp +154 -0
- package/numkong/bench/bench_mesh.cpp +148 -0
- package/numkong/bench/bench_probability.cpp +60 -0
- package/numkong/bench/bench_reduce.cpp +371 -0
- package/numkong/bench/bench_set.cpp +73 -0
- package/numkong/bench/bench_sparse.cpp +198 -0
- package/numkong/bench/bench_spatial.cpp +347 -0
- package/numkong/bench/bench_trigonometry.cpp +137 -0
- package/numkong/bench/swift/Bench.swift +506 -0
- package/numkong/binding.gyp +169 -0
- package/numkong/build.rs +484 -0
- package/numkong/c/dispatch.h +512 -0
- package/numkong/c/dispatch_bf16.c +447 -0
- package/numkong/c/dispatch_bf16c.c +52 -0
- package/numkong/c/dispatch_e2m3.c +296 -0
- package/numkong/c/dispatch_e3m2.c +284 -0
- package/numkong/c/dispatch_e4m3.c +318 -0
- package/numkong/c/dispatch_e5m2.c +316 -0
- package/numkong/c/dispatch_f16.c +452 -0
- package/numkong/c/dispatch_f16c.c +58 -0
- package/numkong/c/dispatch_f32.c +434 -0
- package/numkong/c/dispatch_f32c.c +99 -0
- package/numkong/c/dispatch_f64.c +348 -0
- package/numkong/c/dispatch_f64c.c +98 -0
- package/numkong/c/dispatch_i16.c +96 -0
- package/numkong/c/dispatch_i32.c +89 -0
- package/numkong/c/dispatch_i4.c +153 -0
- package/numkong/c/dispatch_i64.c +86 -0
- package/numkong/c/dispatch_i8.c +348 -0
- package/numkong/c/dispatch_other.c +348 -0
- package/numkong/c/dispatch_u1.c +193 -0
- package/numkong/c/dispatch_u16.c +124 -0
- package/numkong/c/dispatch_u32.c +118 -0
- package/numkong/c/dispatch_u4.c +153 -0
- package/numkong/c/dispatch_u64.c +102 -0
- package/numkong/c/dispatch_u8.c +364 -0
- package/numkong/c/numkong.c +940 -0
- package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
- package/numkong/cmake/nk_isa_probe.cmake +90 -0
- package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
- package/numkong/cmake/nk_math_lib.cmake +46 -0
- package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
- package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
- package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
- package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
- package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
- package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
- package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
- package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
- package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
- package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
- package/numkong/cmake/toolchain-wasi.cmake +77 -0
- package/numkong/cmake/toolchain-wasm.cmake +70 -0
- package/numkong/cmake/toolchain-wasm64.cmake +62 -0
- package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
- package/numkong/include/README.md +643 -0
- package/numkong/include/module.modulemap +129 -0
- package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
- package/numkong/include/numkong/attention/sme.h +2075 -0
- package/numkong/include/numkong/attention.h +49 -0
- package/numkong/include/numkong/capabilities.h +930 -0
- package/numkong/include/numkong/cast/README.md +262 -0
- package/numkong/include/numkong/cast/diamond.h +64 -0
- package/numkong/include/numkong/cast/haswell.h +823 -0
- package/numkong/include/numkong/cast/icelake.h +475 -0
- package/numkong/include/numkong/cast/loongsonasx.h +252 -0
- package/numkong/include/numkong/cast/neon.h +1174 -0
- package/numkong/include/numkong/cast/powervsx.h +449 -0
- package/numkong/include/numkong/cast/rvv.h +970 -0
- package/numkong/include/numkong/cast/sapphire.h +262 -0
- package/numkong/include/numkong/cast/serial.h +2336 -0
- package/numkong/include/numkong/cast/skylake.h +915 -0
- package/numkong/include/numkong/cast/v128relaxed.h +537 -0
- package/numkong/include/numkong/cast.h +254 -0
- package/numkong/include/numkong/cast.hpp +44 -0
- package/numkong/include/numkong/curved/README.md +223 -0
- package/numkong/include/numkong/curved/genoa.h +182 -0
- package/numkong/include/numkong/curved/haswell.h +276 -0
- package/numkong/include/numkong/curved/neon.h +329 -0
- package/numkong/include/numkong/curved/neonbfdot.h +211 -0
- package/numkong/include/numkong/curved/rvv.h +305 -0
- package/numkong/include/numkong/curved/serial.h +207 -0
- package/numkong/include/numkong/curved/skylake.h +457 -0
- package/numkong/include/numkong/curved/smef64.h +530 -0
- package/numkong/include/numkong/curved.h +513 -0
- package/numkong/include/numkong/curved.hpp +144 -0
- package/numkong/include/numkong/dot/README.md +442 -0
- package/numkong/include/numkong/dot/alder.h +563 -0
- package/numkong/include/numkong/dot/diamond.h +158 -0
- package/numkong/include/numkong/dot/genoa.h +289 -0
- package/numkong/include/numkong/dot/haswell.h +1723 -0
- package/numkong/include/numkong/dot/icelake.h +997 -0
- package/numkong/include/numkong/dot/loongsonasx.h +671 -0
- package/numkong/include/numkong/dot/neon.h +869 -0
- package/numkong/include/numkong/dot/neonbfdot.h +243 -0
- package/numkong/include/numkong/dot/neonfhm.h +358 -0
- package/numkong/include/numkong/dot/neonfp8.h +323 -0
- package/numkong/include/numkong/dot/neonsdot.h +622 -0
- package/numkong/include/numkong/dot/powervsx.h +752 -0
- package/numkong/include/numkong/dot/rvv.h +722 -0
- package/numkong/include/numkong/dot/rvvbb.h +72 -0
- package/numkong/include/numkong/dot/rvvbf16.h +123 -0
- package/numkong/include/numkong/dot/rvvhalf.h +129 -0
- package/numkong/include/numkong/dot/sapphire.h +141 -0
- package/numkong/include/numkong/dot/serial.h +874 -0
- package/numkong/include/numkong/dot/sierra.h +405 -0
- package/numkong/include/numkong/dot/skylake.h +1116 -0
- package/numkong/include/numkong/dot/sve.h +420 -0
- package/numkong/include/numkong/dot/svebfdot.h +75 -0
- package/numkong/include/numkong/dot/svehalf.h +168 -0
- package/numkong/include/numkong/dot/svesdot.h +90 -0
- package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
- package/numkong/include/numkong/dot.h +1136 -0
- package/numkong/include/numkong/dot.hpp +94 -0
- package/numkong/include/numkong/dots/README.md +496 -0
- package/numkong/include/numkong/dots/alder.h +117 -0
- package/numkong/include/numkong/dots/diamond.h +86 -0
- package/numkong/include/numkong/dots/genoa.h +100 -0
- package/numkong/include/numkong/dots/graniteamx.h +733 -0
- package/numkong/include/numkong/dots/haswell.h +310 -0
- package/numkong/include/numkong/dots/icelake.h +180 -0
- package/numkong/include/numkong/dots/loongsonasx.h +176 -0
- package/numkong/include/numkong/dots/neon.h +123 -0
- package/numkong/include/numkong/dots/neonbfdot.h +59 -0
- package/numkong/include/numkong/dots/neonfhm.h +96 -0
- package/numkong/include/numkong/dots/neonfp8.h +99 -0
- package/numkong/include/numkong/dots/neonsdot.h +144 -0
- package/numkong/include/numkong/dots/powervsx.h +194 -0
- package/numkong/include/numkong/dots/rvv.h +2593 -0
- package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
- package/numkong/include/numkong/dots/serial.h +2867 -0
- package/numkong/include/numkong/dots/sierra.h +100 -0
- package/numkong/include/numkong/dots/skylake.h +207 -0
- package/numkong/include/numkong/dots/sme.h +5041 -0
- package/numkong/include/numkong/dots/smebi32.h +477 -0
- package/numkong/include/numkong/dots/smef64.h +1328 -0
- package/numkong/include/numkong/dots/smehalf.h +47 -0
- package/numkong/include/numkong/dots/v128relaxed.h +317 -0
- package/numkong/include/numkong/dots.h +3110 -0
- package/numkong/include/numkong/dots.hpp +641 -0
- package/numkong/include/numkong/each/README.md +465 -0
- package/numkong/include/numkong/each/haswell.h +1658 -0
- package/numkong/include/numkong/each/icelake.h +272 -0
- package/numkong/include/numkong/each/neon.h +1138 -0
- package/numkong/include/numkong/each/neonbfdot.h +211 -0
- package/numkong/include/numkong/each/neonhalf.h +318 -0
- package/numkong/include/numkong/each/rvv.h +1121 -0
- package/numkong/include/numkong/each/sapphire.h +343 -0
- package/numkong/include/numkong/each/serial.h +282 -0
- package/numkong/include/numkong/each/skylake.h +1562 -0
- package/numkong/include/numkong/each/v128relaxed.h +562 -0
- package/numkong/include/numkong/each.h +2232 -0
- package/numkong/include/numkong/each.hpp +434 -0
- package/numkong/include/numkong/geospatial/README.md +147 -0
- package/numkong/include/numkong/geospatial/haswell.h +633 -0
- package/numkong/include/numkong/geospatial/neon.h +615 -0
- package/numkong/include/numkong/geospatial/rvv.h +701 -0
- package/numkong/include/numkong/geospatial/serial.h +309 -0
- package/numkong/include/numkong/geospatial/skylake.h +613 -0
- package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
- package/numkong/include/numkong/geospatial.h +453 -0
- package/numkong/include/numkong/geospatial.hpp +235 -0
- package/numkong/include/numkong/matrix.hpp +336 -0
- package/numkong/include/numkong/maxsim/README.md +187 -0
- package/numkong/include/numkong/maxsim/alder.h +511 -0
- package/numkong/include/numkong/maxsim/genoa.h +115 -0
- package/numkong/include/numkong/maxsim/haswell.h +553 -0
- package/numkong/include/numkong/maxsim/icelake.h +480 -0
- package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
- package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
- package/numkong/include/numkong/maxsim/serial.h +490 -0
- package/numkong/include/numkong/maxsim/sme.h +993 -0
- package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
- package/numkong/include/numkong/maxsim.h +571 -0
- package/numkong/include/numkong/maxsim.hpp +133 -0
- package/numkong/include/numkong/mesh/README.md +219 -0
- package/numkong/include/numkong/mesh/haswell.h +2013 -0
- package/numkong/include/numkong/mesh/neon.h +1821 -0
- package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
- package/numkong/include/numkong/mesh/rvv.h +936 -0
- package/numkong/include/numkong/mesh/serial.h +721 -0
- package/numkong/include/numkong/mesh/skylake.h +2344 -0
- package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
- package/numkong/include/numkong/mesh.h +666 -0
- package/numkong/include/numkong/mesh.hpp +701 -0
- package/numkong/include/numkong/numkong.h +78 -0
- package/numkong/include/numkong/numkong.hpp +58 -0
- package/numkong/include/numkong/probability/README.md +177 -0
- package/numkong/include/numkong/probability/haswell.h +267 -0
- package/numkong/include/numkong/probability/neon.h +255 -0
- package/numkong/include/numkong/probability/rvv.h +414 -0
- package/numkong/include/numkong/probability/serial.h +181 -0
- package/numkong/include/numkong/probability/skylake.h +324 -0
- package/numkong/include/numkong/probability.h +380 -0
- package/numkong/include/numkong/probability.hpp +120 -0
- package/numkong/include/numkong/random.h +50 -0
- package/numkong/include/numkong/random.hpp +285 -0
- package/numkong/include/numkong/reduce/README.md +552 -0
- package/numkong/include/numkong/reduce/alder.h +636 -0
- package/numkong/include/numkong/reduce/genoa.h +201 -0
- package/numkong/include/numkong/reduce/haswell.h +3785 -0
- package/numkong/include/numkong/reduce/icelake.h +549 -0
- package/numkong/include/numkong/reduce/neon.h +3980 -0
- package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
- package/numkong/include/numkong/reduce/neonfhm.h +293 -0
- package/numkong/include/numkong/reduce/neonsdot.h +357 -0
- package/numkong/include/numkong/reduce/rvv.h +3533 -0
- package/numkong/include/numkong/reduce/serial.h +753 -0
- package/numkong/include/numkong/reduce/sierra.h +338 -0
- package/numkong/include/numkong/reduce/skylake.h +3794 -0
- package/numkong/include/numkong/reduce/sve.h +52 -0
- package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
- package/numkong/include/numkong/reduce.h +1582 -0
- package/numkong/include/numkong/reduce.hpp +778 -0
- package/numkong/include/numkong/scalar/README.md +89 -0
- package/numkong/include/numkong/scalar/haswell.h +122 -0
- package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
- package/numkong/include/numkong/scalar/neon.h +122 -0
- package/numkong/include/numkong/scalar/neonhalf.h +70 -0
- package/numkong/include/numkong/scalar/powervsx.h +96 -0
- package/numkong/include/numkong/scalar/rvv.h +211 -0
- package/numkong/include/numkong/scalar/sapphire.h +74 -0
- package/numkong/include/numkong/scalar/serial.h +332 -0
- package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
- package/numkong/include/numkong/scalar.h +696 -0
- package/numkong/include/numkong/set/README.md +179 -0
- package/numkong/include/numkong/set/haswell.h +334 -0
- package/numkong/include/numkong/set/icelake.h +485 -0
- package/numkong/include/numkong/set/loongsonasx.h +181 -0
- package/numkong/include/numkong/set/neon.h +363 -0
- package/numkong/include/numkong/set/powervsx.h +326 -0
- package/numkong/include/numkong/set/rvv.h +226 -0
- package/numkong/include/numkong/set/rvvbb.h +117 -0
- package/numkong/include/numkong/set/serial.h +174 -0
- package/numkong/include/numkong/set/sve.h +187 -0
- package/numkong/include/numkong/set/v128relaxed.h +240 -0
- package/numkong/include/numkong/set.h +471 -0
- package/numkong/include/numkong/set.hpp +114 -0
- package/numkong/include/numkong/sets/README.md +149 -0
- package/numkong/include/numkong/sets/haswell.h +63 -0
- package/numkong/include/numkong/sets/icelake.h +66 -0
- package/numkong/include/numkong/sets/loongsonasx.h +52 -0
- package/numkong/include/numkong/sets/neon.h +61 -0
- package/numkong/include/numkong/sets/powervsx.h +65 -0
- package/numkong/include/numkong/sets/serial.h +43 -0
- package/numkong/include/numkong/sets/smebi32.h +1135 -0
- package/numkong/include/numkong/sets/v128relaxed.h +58 -0
- package/numkong/include/numkong/sets.h +382 -0
- package/numkong/include/numkong/sparse/README.md +156 -0
- package/numkong/include/numkong/sparse/icelake.h +463 -0
- package/numkong/include/numkong/sparse/neon.h +288 -0
- package/numkong/include/numkong/sparse/serial.h +117 -0
- package/numkong/include/numkong/sparse/sve2.h +504 -0
- package/numkong/include/numkong/sparse/turin.h +322 -0
- package/numkong/include/numkong/sparse.h +363 -0
- package/numkong/include/numkong/sparse.hpp +113 -0
- package/numkong/include/numkong/spatial/README.md +439 -0
- package/numkong/include/numkong/spatial/alder.h +604 -0
- package/numkong/include/numkong/spatial/diamond.h +240 -0
- package/numkong/include/numkong/spatial/genoa.h +222 -0
- package/numkong/include/numkong/spatial/haswell.h +979 -0
- package/numkong/include/numkong/spatial/icelake.h +1067 -0
- package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
- package/numkong/include/numkong/spatial/neon.h +846 -0
- package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
- package/numkong/include/numkong/spatial/neonfp8.h +258 -0
- package/numkong/include/numkong/spatial/neonsdot.h +429 -0
- package/numkong/include/numkong/spatial/powervsx.h +738 -0
- package/numkong/include/numkong/spatial/rvv.h +991 -0
- package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
- package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
- package/numkong/include/numkong/spatial/serial.h +347 -0
- package/numkong/include/numkong/spatial/sierra.h +516 -0
- package/numkong/include/numkong/spatial/skylake.h +605 -0
- package/numkong/include/numkong/spatial/sve.h +246 -0
- package/numkong/include/numkong/spatial/svebfdot.h +125 -0
- package/numkong/include/numkong/spatial/svehalf.h +136 -0
- package/numkong/include/numkong/spatial/svesdot.h +143 -0
- package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
- package/numkong/include/numkong/spatial.h +1681 -0
- package/numkong/include/numkong/spatial.hpp +183 -0
- package/numkong/include/numkong/spatials/README.md +580 -0
- package/numkong/include/numkong/spatials/alder.h +94 -0
- package/numkong/include/numkong/spatials/diamond.h +82 -0
- package/numkong/include/numkong/spatials/genoa.h +94 -0
- package/numkong/include/numkong/spatials/graniteamx.h +173 -0
- package/numkong/include/numkong/spatials/haswell.h +219 -0
- package/numkong/include/numkong/spatials/icelake.h +113 -0
- package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
- package/numkong/include/numkong/spatials/neon.h +109 -0
- package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
- package/numkong/include/numkong/spatials/neonfhm.h +92 -0
- package/numkong/include/numkong/spatials/neonfp8.h +111 -0
- package/numkong/include/numkong/spatials/neonsdot.h +143 -0
- package/numkong/include/numkong/spatials/powervsx.h +153 -0
- package/numkong/include/numkong/spatials/rvv.h +1976 -0
- package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
- package/numkong/include/numkong/spatials/serial.h +248 -0
- package/numkong/include/numkong/spatials/sierra.h +96 -0
- package/numkong/include/numkong/spatials/skylake.h +184 -0
- package/numkong/include/numkong/spatials/sme.h +1927 -0
- package/numkong/include/numkong/spatials/smef64.h +483 -0
- package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
- package/numkong/include/numkong/spatials.h +3374 -0
- package/numkong/include/numkong/spatials.hpp +509 -0
- package/numkong/include/numkong/tensor.hpp +1981 -0
- package/numkong/include/numkong/trigonometry/README.md +184 -0
- package/numkong/include/numkong/trigonometry/haswell.h +653 -0
- package/numkong/include/numkong/trigonometry/neon.h +638 -0
- package/numkong/include/numkong/trigonometry/rvv.h +700 -0
- package/numkong/include/numkong/trigonometry/serial.h +703 -0
- package/numkong/include/numkong/trigonometry/skylake.h +725 -0
- package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
- package/numkong/include/numkong/trigonometry.h +467 -0
- package/numkong/include/numkong/trigonometry.hpp +166 -0
- package/numkong/include/numkong/types.h +1695 -0
- package/numkong/include/numkong/types.hpp +6027 -0
- package/numkong/include/numkong/vector.hpp +766 -0
- package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
- package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
- package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
- package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
- package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
- package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
- package/numkong/javascript/README.md +254 -0
- package/numkong/javascript/node-gyp-build.d.ts +4 -0
- package/numkong/javascript/numkong-browser.ts +40 -0
- package/numkong/javascript/numkong-wasm.ts +750 -0
- package/numkong/javascript/numkong.c +712 -0
- package/numkong/javascript/numkong.ts +613 -0
- package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
- package/numkong/javascript/tsconfig-cjs.json +13 -0
- package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
- package/numkong/javascript/types.ts +784 -0
- package/numkong/numkong.gypi +104 -0
- package/numkong/package.json +108 -0
- package/numkong/probes/arm_neon.c +8 -0
- package/numkong/probes/arm_neon_bfdot.c +9 -0
- package/numkong/probes/arm_neon_fhm.c +9 -0
- package/numkong/probes/arm_neon_half.c +8 -0
- package/numkong/probes/arm_neon_sdot.c +9 -0
- package/numkong/probes/arm_neonfp8.c +9 -0
- package/numkong/probes/arm_sme.c +16 -0
- package/numkong/probes/arm_sme2.c +16 -0
- package/numkong/probes/arm_sme2p1.c +16 -0
- package/numkong/probes/arm_sme_bf16.c +16 -0
- package/numkong/probes/arm_sme_bi32.c +16 -0
- package/numkong/probes/arm_sme_f64.c +16 -0
- package/numkong/probes/arm_sme_fa64.c +14 -0
- package/numkong/probes/arm_sme_half.c +16 -0
- package/numkong/probes/arm_sme_lut2.c +15 -0
- package/numkong/probes/arm_sve.c +18 -0
- package/numkong/probes/arm_sve2.c +20 -0
- package/numkong/probes/arm_sve2p1.c +18 -0
- package/numkong/probes/arm_sve_bfdot.c +20 -0
- package/numkong/probes/arm_sve_half.c +18 -0
- package/numkong/probes/arm_sve_sdot.c +21 -0
- package/numkong/probes/loongarch_lasx.c +12 -0
- package/numkong/probes/power_vsx.c +12 -0
- package/numkong/probes/probe.js +127 -0
- package/numkong/probes/riscv_rvv.c +14 -0
- package/numkong/probes/riscv_rvv_bb.c +15 -0
- package/numkong/probes/riscv_rvv_bf16.c +17 -0
- package/numkong/probes/riscv_rvv_half.c +14 -0
- package/numkong/probes/wasm_v128relaxed.c +11 -0
- package/numkong/probes/x86_alder.c +17 -0
- package/numkong/probes/x86_diamond.c +17 -0
- package/numkong/probes/x86_genoa.c +17 -0
- package/numkong/probes/x86_graniteamx.c +19 -0
- package/numkong/probes/x86_haswell.c +11 -0
- package/numkong/probes/x86_icelake.c +17 -0
- package/numkong/probes/x86_sapphire.c +16 -0
- package/numkong/probes/x86_sapphireamx.c +18 -0
- package/numkong/probes/x86_sierra.c +17 -0
- package/numkong/probes/x86_skylake.c +15 -0
- package/numkong/probes/x86_turin.c +17 -0
- package/numkong/rust/README.md +698 -0
- package/numkong/rust/capabilities.rs +96 -0
- package/numkong/rust/cast.rs +314 -0
- package/numkong/rust/curved.rs +391 -0
- package/numkong/rust/each.rs +2721 -0
- package/numkong/rust/geospatial.rs +343 -0
- package/numkong/rust/matrix.rs +5424 -0
- package/numkong/rust/maxsim.rs +540 -0
- package/numkong/rust/mesh.rs +837 -0
- package/numkong/rust/numkong.rs +409 -0
- package/numkong/rust/probability.rs +272 -0
- package/numkong/rust/reduce.rs +1249 -0
- package/numkong/rust/set.rs +194 -0
- package/numkong/rust/sparse.rs +513 -0
- package/numkong/rust/spatial.rs +1815 -0
- package/numkong/rust/tensor.rs +7565 -0
- package/numkong/rust/types.rs +3666 -0
- package/numkong/rust/vector.rs +1899 -0
- package/numkong/rustfmt.toml +2 -0
- package/numkong/swift/Matrix.swift +1388 -0
- package/numkong/swift/MaxSim.swift +151 -0
- package/numkong/swift/NumKong.swift +283 -0
- package/numkong/swift/Numerics.swift +329 -0
- package/numkong/swift/README.md +433 -0
- package/numkong/swift/Scalar.swift +741 -0
- package/numkong/swift/Tensor.swift +209 -0
- package/numkong/test/README.md +315 -0
- package/numkong/test/playwright.config.ts +16 -0
- package/numkong/test/swift/Test.swift +534 -0
- package/numkong/test/test-browser-bundle-runner.mjs +36 -0
- package/numkong/test/test-browser-bundle.html +188 -0
- package/numkong/test/test-browser-runner.mjs +43 -0
- package/numkong/test/test-browser.html +305 -0
- package/numkong/test/test-dtypes.mjs +453 -0
- package/numkong/test/test-wasm.mjs +267 -0
- package/numkong/test/test.cpp +442 -0
- package/numkong/test/test.hpp +580 -0
- package/numkong/test/test.mjs +363 -0
- package/numkong/test/test_base.py +1041 -0
- package/numkong/test/test_cast.cpp +242 -0
- package/numkong/test/test_cross.hpp +551 -0
- package/numkong/test/test_cross.py +467 -0
- package/numkong/test/test_cross_amx.cpp +50 -0
- package/numkong/test/test_cross_arm.cpp +225 -0
- package/numkong/test/test_cross_blas.cpp +354 -0
- package/numkong/test/test_cross_loongarch.cpp +90 -0
- package/numkong/test/test_cross_power.cpp +73 -0
- package/numkong/test/test_cross_rvv.cpp +109 -0
- package/numkong/test/test_cross_serial.cpp +181 -0
- package/numkong/test/test_cross_sme.cpp +148 -0
- package/numkong/test/test_cross_wasm.cpp +141 -0
- package/numkong/test/test_cross_x86.cpp +442 -0
- package/numkong/test/test_curved.cpp +182 -0
- package/numkong/test/test_curved.py +207 -0
- package/numkong/test/test_dot.cpp +353 -0
- package/numkong/test/test_dot.py +296 -0
- package/numkong/test/test_each.cpp +437 -0
- package/numkong/test/test_each.py +756 -0
- package/numkong/test/test_geospatial.cpp +155 -0
- package/numkong/test/test_geospatial.py +241 -0
- package/numkong/test/test_maxsim.cpp +138 -0
- package/numkong/test/test_maxsim.py +209 -0
- package/numkong/test/test_mesh.cpp +203 -0
- package/numkong/test/test_mesh.py +394 -0
- package/numkong/test/test_probability.cpp +136 -0
- package/numkong/test/test_probability.py +166 -0
- package/numkong/test/test_reduce.cpp +563 -0
- package/numkong/test/test_reduce.py +781 -0
- package/numkong/test/test_set.cpp +151 -0
- package/numkong/test/test_set.py +120 -0
- package/numkong/test/test_similarities.py +579 -0
- package/numkong/test/test_sparse.cpp +121 -0
- package/numkong/test/test_sparse.py +118 -0
- package/numkong/test/test_spatial.cpp +518 -0
- package/numkong/test/test_spatial.py +269 -0
- package/numkong/test/test_tensor.cpp +884 -0
- package/numkong/test/test_tensor.py +1417 -0
- package/numkong/test/test_trigonometry.cpp +156 -0
- package/numkong/test/test_trigonometry.py +180 -0
- package/package.json +7 -8
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/fp16/CMakeLists.txt +0 -176
- package/fp16/LICENSE +0 -11
- package/fp16/README.md +0 -20
- package/fp16/bench/alt-element.cc +0 -89
- package/fp16/bench/from-alt-array.cc +0 -175
- package/fp16/bench/from-ieee-array.cc +0 -399
- package/fp16/bench/ieee-element.cc +0 -272
- package/fp16/bench/to-alt-array.cc +0 -91
- package/fp16/bench/to-ieee-array.cc +0 -303
- package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
- package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
- package/fp16/cmake/DownloadPSimd.cmake +0 -15
- package/fp16/configure.py +0 -65
- package/fp16/confu.yaml +0 -8
- package/fp16/include/fp16/__init__.py +0 -0
- package/fp16/include/fp16/avx.py +0 -50
- package/fp16/include/fp16/avx2.py +0 -53
- package/fp16/include/fp16/bitcasts.h +0 -92
- package/fp16/include/fp16/fp16.h +0 -451
- package/fp16/include/fp16/psimd.h +0 -131
- package/fp16/include/fp16.h +0 -11
- package/fp16/jni/Android.mk +0 -6
- package/fp16/jni/Application.mk +0 -4
- package/fp16/test/alt-from-fp32-value.cc +0 -498
- package/fp16/test/alt-to-fp32-bits.cc +0 -263
- package/fp16/test/alt-to-fp32-psimd.cc +0 -145
- package/fp16/test/alt-to-fp32-value.cc +0 -348
- package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
- package/fp16/test/bitcasts.cc +0 -56
- package/fp16/test/ieee-from-fp32-value.cc +0 -523
- package/fp16/test/ieee-to-fp32-bits.cc +0 -333
- package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
- package/fp16/test/ieee-to-fp32-value.cc +0 -420
- package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
- package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
- package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
- package/fp16/test/peachpy/stubs.py +0 -38
- package/fp16/test/tables.cc +0 -530
- package/fp16/test/tables.h +0 -13
- package/fp16/third-party/THHalf.h +0 -92
- package/fp16/third-party/eigen-half.h +0 -170
- package/fp16/third-party/float16-compressor.h +0 -80
- package/fp16/third-party/half.hpp +0 -2916
- package/fp16/third-party/npy-halffloat.h +0 -328
- package/simsimd/.git-blame-ignore-revs +0 -2
- package/simsimd/CONTRIBUTING.md +0 -321
- package/simsimd/Cargo.toml +0 -49
- package/simsimd/MANIFEST.in +0 -4
- package/simsimd/Package.swift +0 -28
- package/simsimd/README.md +0 -1493
- package/simsimd/binding.gyp +0 -35
- package/simsimd/build.rs +0 -70
- package/simsimd/c/lib.c +0 -374
- package/simsimd/include/module.modulemap +0 -4
- package/simsimd/include/simsimd/binary.h +0 -486
- package/simsimd/include/simsimd/curved.h +0 -1541
- package/simsimd/include/simsimd/dot.h +0 -1853
- package/simsimd/include/simsimd/elementwise.h +0 -2465
- package/simsimd/include/simsimd/geospatial.h +0 -43
- package/simsimd/include/simsimd/mesh.h +0 -69
- package/simsimd/include/simsimd/probability.h +0 -606
- package/simsimd/include/simsimd/simsimd.h +0 -2567
- package/simsimd/include/simsimd/sparse.h +0 -1384
- package/simsimd/include/simsimd/spatial.h +0 -2335
- package/simsimd/include/simsimd/types.h +0 -666
- package/simsimd/javascript/fallback.ts +0 -233
- package/simsimd/javascript/lib.c +0 -125
- package/simsimd/javascript/node-gyp-build.d.ts +0 -1
- package/simsimd/javascript/simsimd.ts +0 -179
- package/simsimd/javascript/tsconfig-cjs.json +0 -8
- package/simsimd/package-lock.json +0 -1761
- package/simsimd/package.json +0 -61
- package/simsimd/rust/lib.rs +0 -1821
- package/simsimd/scripts/bench.cxx +0 -1170
- package/simsimd/scripts/bench.ipynb +0 -187
- package/simsimd/scripts/bench.js +0 -127
- package/simsimd/scripts/bench.rs +0 -876
- package/simsimd/scripts/bench_vectors.py +0 -734
- package/simsimd/scripts/bench_vectors_live.py +0 -213
- package/simsimd/scripts/test.c +0 -187
- package/simsimd/scripts/test.mjs +0 -220
- package/simsimd/scripts/test.py +0 -1505
- package/simsimd/swift/SimSIMD.swift +0 -149
- package/simsimd/swift/Test.swift +0 -128
- /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
- /package/{simsimd → numkong}/LICENSE +0 -0
- /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
- /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Scalar Math Primitives in NumKong
|
|
2
|
+
|
|
3
|
+
NumKong provides single-element math operations — square root, reciprocal square root, fused multiply-add, and saturating integer arithmetic — with per-ISA implementations.
|
|
4
|
+
These primitives serve as building blocks for vectorized kernels: distance finalizers call `nk_f32_rsqrt` for angular normalization, packing routines call `nk_f32_sqrt` for norm computation.
|
|
5
|
+
Ordering functions (`nk_f16_order`, `nk_bf16_order`, `nk_e4m3_order`) convert floating-point bit patterns to integers that sort in the same order as the original floats.
|
|
6
|
+
|
|
7
|
+
Reciprocal square root:
|
|
8
|
+
|
|
9
|
+
$$
|
|
10
|
+
\text{rsqrt}(x) = \frac{1}{\sqrt{x}}
|
|
11
|
+
$$
|
|
12
|
+
|
|
13
|
+
Fused multiply-add:
|
|
14
|
+
|
|
15
|
+
$$
|
|
16
|
+
\text{fma}(a, b, c) = a \cdot b + c
|
|
17
|
+
$$
|
|
18
|
+
|
|
19
|
+
Saturating addition:
|
|
20
|
+
|
|
21
|
+
$$
|
|
22
|
+
\text{sat\_add}(a, b) = \text{clamp}(a + b, \text{T\_MIN}, \text{T\_MAX})
|
|
23
|
+
$$
|
|
24
|
+
|
|
25
|
+
Reformulating as Python pseudocode:
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import numpy as np
|
|
29
|
+
|
|
30
|
+
def rsqrt(x: float) -> float:
|
|
31
|
+
return 1.0 / np.sqrt(x)
|
|
32
|
+
|
|
33
|
+
def fma(a: float, b: float, c: float) -> float:
|
|
34
|
+
return a * b + c
|
|
35
|
+
|
|
36
|
+
def saturating_add(a: int, b: int, bits: int, signed: bool) -> int:
|
|
37
|
+
lo, hi = (-(1 << (bits-1)), (1 << (bits-1)) - 1) if signed else (0, (1 << bits) - 1)
|
|
38
|
+
return max(lo, min(a + b, hi))
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Input & Output Types
|
|
42
|
+
|
|
43
|
+
| Input Type | Output Type | Description |
|
|
44
|
+
| ---------- | ----------- | ----------------------------------------------- |
|
|
45
|
+
| `f64` | `f64` | sqrt, rsqrt, fma for 64-bit doubles |
|
|
46
|
+
| `f32` | `f32` | sqrt, rsqrt, fma for 32-bit floats |
|
|
47
|
+
| `f16` | `f16` | sqrt, rsqrt, fma for 16-bit halfs |
|
|
48
|
+
| `i8` | `i8` | Saturating add and multiply |
|
|
49
|
+
| `u8` | `u8` | Saturating add and multiply |
|
|
50
|
+
| `i16` | `i16` | Saturating add and multiply |
|
|
51
|
+
| `u16` | `u16` | Saturating add and multiply |
|
|
52
|
+
| `i32` | `i32` | Saturating add and multiply |
|
|
53
|
+
| `u32` | `u32` | Saturating add and multiply |
|
|
54
|
+
| `i64` | `i64` | Saturating add and multiply |
|
|
55
|
+
| `u64` | `u64` | Saturating add and multiply |
|
|
56
|
+
| `i4x2` | `i4x2` | Saturating add for packed signed nibble pairs |
|
|
57
|
+
| `u4x2` | `u4x2` | Saturating add for packed unsigned nibble pairs |
|
|
58
|
+
| `f16` | `u16` | Ordering: bit pattern to sortable integer |
|
|
59
|
+
| `bf16` | `u16` | Ordering: bit pattern to sortable integer |
|
|
60
|
+
| `e4m3` | `u8` | Ordering: bit pattern to sortable integer |
|
|
61
|
+
| `e5m2` | `u8` | Ordering: bit pattern to sortable integer |
|
|
62
|
+
| `e2m3` | `u8` | Ordering: bit pattern to sortable integer |
|
|
63
|
+
| `e3m2` | `u8` | Ordering: bit pattern to sortable integer |
|
|
64
|
+
|
|
65
|
+
## Optimizations
|
|
66
|
+
|
|
67
|
+
### Quake 3 Fast Inverse Square Root
|
|
68
|
+
|
|
69
|
+
`nk_f32_rsqrt_serial` uses the classic bit-manipulation trick: reinterpret Float32 bits as Int32, compute `0x5F375A86 - (bits >> 1)`, reinterpret back to Float32, then refine with 3 Newton-Raphson iterations reaching ~34.9 correct bits.
|
|
70
|
+
Each Newton-Raphson iteration: `y = y * (1.5f - 0.5f * x * y * y)` — 2 multiplies and 1 subtract, ~4cy per iteration.
|
|
71
|
+
`nk_f32_rsqrt_haswell` replaces this with hardware `VRSQRT14PS` ($2^{-14}$ relative error, ~4cy latency) plus one Newton-Raphson refinement (~22-24 correct bits).
|
|
72
|
+
`nk_f64_rsqrt_serial` uses the Float64 magic constant `0x5FE6EB50C7B537A9` with 4 iterations for 52-bit mantissa coverage.
|
|
73
|
+
|
|
74
|
+
### Dekker Error-Free Multiplication for FMA
|
|
75
|
+
|
|
76
|
+
`nk_f32_fma_serial` emulates fused multiply-add on platforms without hardware FMA using Dekker's algorithm: splits each operand into high and low halves via `a_hi = (a * 134217729.0f) - ((a * 134217729.0f) - a)`, then computes the exact product error term.
|
|
77
|
+
The magic constant $134217729 = 2^{27} + 1$ splits a 24-bit mantissa into two 12-bit halves that multiply without rounding.
|
|
78
|
+
`nk_f32_fma_haswell` uses hardware `VFMADD231SS` — single instruction, single cycle, exact to the last bit.
|
|
79
|
+
|
|
80
|
+
### Float-to-Integer Ordering
|
|
81
|
+
|
|
82
|
+
`nk_f16_order_serial`, `nk_bf16_order_serial`, `nk_e4m3_order_serial` convert floating-point bit patterns to unsigned integers that preserve the total order.
|
|
83
|
+
Positive floats are already ordered by their bit patterns; negative floats need bit inversion: `if (bits & sign_bit) bits = ~bits; else bits ^= sign_bit`.
|
|
84
|
+
This enables integer comparison instructions (`VPCMPUD`) for floating-point sorting without branching — used by `nk_reduce_minmax_*` for Float8 and sub-32-bit types that lack native SIMD comparison.
|
|
85
|
+
|
|
86
|
+
## Performance
|
|
87
|
+
|
|
88
|
+
Scalar primitives operate on single elements and are not independently benchmarked.
|
|
89
|
+
Their performance is captured within the vector kernels that call them.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Scalar Math Helpers for Haswell.
|
|
3
|
+
* @file include/numkong/scalar/haswell.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 1, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*
|
|
9
|
+
* @section scalars_haswell_instructions Key AVX2/FMA Scalar Instructions
|
|
10
|
+
*
|
|
11
|
+
* Intrinsic Instruction Haswell Genoa
|
|
12
|
+
* _mm_sqrt_ps VSQRTPS (XMM, XMM) 11cy @ p0 15cy @ p01
|
|
13
|
+
* _mm_sqrt_pd VSQRTPD (XMM, XMM) 16cy @ p0 15cy @ p01
|
|
14
|
+
* _mm_fmadd_ss VFMADD (XMM, XMM, XMM) 5cy @ p01 4cy @ p01
|
|
15
|
+
* _mm_fmadd_sd VFMADD (XMM, XMM, XMM) 5cy @ p01 4cy @ p01
|
|
16
|
+
* _mm_cvtps_ph VCVTPS2PH (XMM, XMM, I8) 5cy @ p01 4cy @ p12+p23
|
|
17
|
+
* _mm_cvtph_ps VCVTPH2PS (XMM, XMM) 5cy @ p01 4cy @ p12+p23
|
|
18
|
+
*/
|
|
19
|
+
#ifndef NK_SCALAR_HASWELL_H
|
|
20
|
+
#define NK_SCALAR_HASWELL_H
|
|
21
|
+
|
|
22
|
+
#if NK_TARGET_X8664_
|
|
23
|
+
#if NK_TARGET_HASWELL
|
|
24
|
+
|
|
25
|
+
#include "numkong/types.h"
|
|
26
|
+
|
|
27
|
+
#if defined(__cplusplus)
|
|
28
|
+
extern "C" {
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#if defined(__clang__)
|
|
32
|
+
#pragma clang attribute push(__attribute__((target("avx2,f16c,fma,bmi,bmi2"))), apply_to = function)
|
|
33
|
+
#elif defined(__GNUC__)
|
|
34
|
+
#pragma GCC push_options
|
|
35
|
+
#pragma GCC target("avx2", "f16c", "fma", "bmi", "bmi2")
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
NK_PUBLIC nk_f32_t nk_f32_sqrt_haswell(nk_f32_t x) { return _mm_cvtss_f32(_mm_sqrt_ps(_mm_set_ss(x))); }
|
|
39
|
+
NK_PUBLIC nk_f64_t nk_f64_sqrt_haswell(nk_f64_t x) { return _mm_cvtsd_f64(_mm_sqrt_pd(_mm_set_sd(x))); }
|
|
40
|
+
NK_PUBLIC nk_f32_t nk_f32_rsqrt_haswell(nk_f32_t x) {
|
|
41
|
+
__m128 x_f32x4 = _mm_set_ss(x);
|
|
42
|
+
__m128 estimate_f32x4 = _mm_rsqrt_ss(x_f32x4);
|
|
43
|
+
__m128 refinement_f32x4 = _mm_mul_ss(_mm_mul_ss(x_f32x4, estimate_f32x4), estimate_f32x4);
|
|
44
|
+
refinement_f32x4 = _mm_sub_ss(_mm_set_ss(3.0f), refinement_f32x4);
|
|
45
|
+
return _mm_cvtss_f32(_mm_mul_ss(_mm_mul_ss(_mm_set_ss(0.5f), estimate_f32x4), refinement_f32x4));
|
|
46
|
+
}
|
|
47
|
+
NK_PUBLIC nk_f64_t nk_f64_rsqrt_haswell(nk_f64_t x) { return 1.0 / nk_f64_sqrt_haswell(x); }
|
|
48
|
+
NK_PUBLIC nk_f32_t nk_f32_fma_haswell(nk_f32_t a, nk_f32_t b, nk_f32_t c) {
|
|
49
|
+
return _mm_cvtss_f32(_mm_fmadd_ss(_mm_set_ss(a), _mm_set_ss(b), _mm_set_ss(c)));
|
|
50
|
+
}
|
|
51
|
+
NK_PUBLIC nk_f64_t nk_f64_fma_haswell(nk_f64_t a, nk_f64_t b, nk_f64_t c) {
|
|
52
|
+
return _mm_cvtsd_f64(_mm_fmadd_sd(_mm_set_sd(a), _mm_set_sd(b), _mm_set_sd(c)));
|
|
53
|
+
}
|
|
54
|
+
NK_PUBLIC nk_f16_t nk_f16_sqrt_haswell(nk_f16_t x) {
|
|
55
|
+
nk_fui16_t x_fui, out_fui;
|
|
56
|
+
x_fui.f = x;
|
|
57
|
+
__m128 x_f32x4 = _mm_cvtph_ps(_mm_cvtsi32_si128(x_fui.u));
|
|
58
|
+
out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(_mm_cvtps_ph(_mm_sqrt_ps(x_f32x4), _MM_FROUND_TO_NEAREST_INT));
|
|
59
|
+
return out_fui.f;
|
|
60
|
+
}
|
|
61
|
+
NK_PUBLIC nk_f16_t nk_f16_rsqrt_haswell(nk_f16_t x) {
|
|
62
|
+
nk_fui16_t x_fui, out_fui;
|
|
63
|
+
x_fui.f = x;
|
|
64
|
+
__m128 x_f32x4 = _mm_cvtph_ps(_mm_cvtsi32_si128(x_fui.u));
|
|
65
|
+
__m128 estimate_f32x4 = _mm_rsqrt_ss(x_f32x4);
|
|
66
|
+
__m128 refinement_f32x4 = _mm_mul_ss(_mm_mul_ss(x_f32x4, estimate_f32x4), estimate_f32x4);
|
|
67
|
+
refinement_f32x4 = _mm_sub_ss(_mm_set_ss(3.0f), refinement_f32x4);
|
|
68
|
+
estimate_f32x4 = _mm_mul_ss(_mm_mul_ss(_mm_set_ss(0.5f), estimate_f32x4), refinement_f32x4);
|
|
69
|
+
out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(_mm_cvtps_ph(estimate_f32x4, _MM_FROUND_TO_NEAREST_INT));
|
|
70
|
+
return out_fui.f;
|
|
71
|
+
}
|
|
72
|
+
NK_PUBLIC nk_f16_t nk_f16_fma_haswell(nk_f16_t a, nk_f16_t b, nk_f16_t c) {
|
|
73
|
+
nk_fui16_t a_fui, b_fui, c_fui, out_fui;
|
|
74
|
+
a_fui.f = a, b_fui.f = b, c_fui.f = c;
|
|
75
|
+
__m128 a_f32x4 = _mm_cvtph_ps(_mm_cvtsi32_si128(a_fui.u));
|
|
76
|
+
__m128 b_f32x4 = _mm_cvtph_ps(_mm_cvtsi32_si128(b_fui.u));
|
|
77
|
+
__m128 c_f32x4 = _mm_cvtph_ps(_mm_cvtsi32_si128(c_fui.u));
|
|
78
|
+
out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(
|
|
79
|
+
_mm_cvtps_ph(_mm_fmadd_ss(a_f32x4, b_f32x4, c_f32x4), _MM_FROUND_TO_NEAREST_INT));
|
|
80
|
+
return out_fui.f;
|
|
81
|
+
}
|
|
82
|
+
NK_PUBLIC nk_u8_t nk_u8_saturating_add_haswell(nk_u8_t a, nk_u8_t b) {
|
|
83
|
+
return (nk_u8_t)_mm_cvtsi128_si32(_mm_adds_epu8(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b)));
|
|
84
|
+
}
|
|
85
|
+
NK_PUBLIC nk_i8_t nk_i8_saturating_add_haswell(nk_i8_t a, nk_i8_t b) {
|
|
86
|
+
return (nk_i8_t)_mm_cvtsi128_si32(_mm_adds_epi8(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b)));
|
|
87
|
+
}
|
|
88
|
+
NK_PUBLIC nk_u16_t nk_u16_saturating_add_haswell(nk_u16_t a, nk_u16_t b) {
|
|
89
|
+
return (nk_u16_t)_mm_cvtsi128_si32(_mm_adds_epu16(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b)));
|
|
90
|
+
}
|
|
91
|
+
NK_PUBLIC nk_i16_t nk_i16_saturating_add_haswell(nk_i16_t a, nk_i16_t b) {
|
|
92
|
+
return (nk_i16_t)_mm_cvtsi128_si32(_mm_adds_epi16(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b)));
|
|
93
|
+
}
|
|
94
|
+
NK_PUBLIC nk_u64_t nk_u64_saturating_mul_haswell(nk_u64_t a, nk_u64_t b) {
|
|
95
|
+
unsigned long long high;
|
|
96
|
+
unsigned long long low = _mulx_u64(a, b, &high);
|
|
97
|
+
return high ? 18446744073709551615ull : low;
|
|
98
|
+
}
|
|
99
|
+
NK_PUBLIC nk_i64_t nk_i64_saturating_mul_haswell(nk_i64_t a, nk_i64_t b) {
|
|
100
|
+
int sign = (a < 0) ^ (b < 0);
|
|
101
|
+
nk_u64_t abs_a = a < 0 ? (0u - (nk_u64_t)a) : (nk_u64_t)a;
|
|
102
|
+
nk_u64_t abs_b = b < 0 ? (0u - (nk_u64_t)b) : (nk_u64_t)b;
|
|
103
|
+
unsigned long long high;
|
|
104
|
+
unsigned long long low = _mulx_u64(abs_a, abs_b, &high);
|
|
105
|
+
if (high || (sign && low > 9223372036854775808ull) || (!sign && low > 9223372036854775807ull))
|
|
106
|
+
return sign ? (-9223372036854775807ll - 1ll) : 9223372036854775807ll;
|
|
107
|
+
return sign ? -(nk_i64_t)low : (nk_i64_t)low;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#if defined(__clang__)
|
|
111
|
+
#pragma clang attribute pop
|
|
112
|
+
#elif defined(__GNUC__)
|
|
113
|
+
#pragma GCC pop_options
|
|
114
|
+
#endif
|
|
115
|
+
|
|
116
|
+
#if defined(__cplusplus)
|
|
117
|
+
} // extern "C"
|
|
118
|
+
#endif
|
|
119
|
+
|
|
120
|
+
#endif // NK_TARGET_HASWELL
|
|
121
|
+
#endif // NK_TARGET_X8664_
|
|
122
|
+
#endif // NK_SCALAR_HASWELL_H
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Scalar Math Helpers for LoongArch LASX.
|
|
3
|
+
* @file include/numkong/scalar/loongsonasx.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 23, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*
|
|
9
|
+
* LASX provides `xvfrsqrt` (full-precision reciprocal sqrt) and `xvfsqrt`
|
|
10
|
+
* (full-precision sqrt). No Newton-Raphson refinement needed.
|
|
11
|
+
* Full-precision sqrt uses the hardware `xvfsqrt` instruction.
|
|
12
|
+
* Broadcast via `xvreplgr2vr`, extract via `xvpickve2gr` — no memory round-trips.
|
|
13
|
+
*/
|
|
14
|
+
#ifndef NK_SCALAR_LOONGSONASX_H
|
|
15
|
+
#define NK_SCALAR_LOONGSONASX_H
|
|
16
|
+
|
|
17
|
+
#if NK_TARGET_LOONGARCH64_
|
|
18
|
+
#if NK_TARGET_LOONGSONASX
|
|
19
|
+
|
|
20
|
+
#include "numkong/types.h"
|
|
21
|
+
|
|
22
|
+
#if defined(__cplusplus)
|
|
23
|
+
extern "C" {
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
/** @brief Broadcast f32 scalar into all 4 lanes of a 128-bit register (GCC/Clang portable). */
|
|
27
|
+
NK_INTERNAL __m128 nk_xvreplgr2vr_s_128_(float x) {
|
|
28
|
+
nk_fui32_t c;
|
|
29
|
+
c.f = x;
|
|
30
|
+
return (__m128)__lsx_vreplgr2vr_w((int)c.u);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** @brief Broadcast f32 scalar into all 8 lanes of a 256-bit register (GCC/Clang portable). */
|
|
34
|
+
NK_INTERNAL __m256 nk_xvfreplgr2vr_s_(float x) {
|
|
35
|
+
nk_fui32_t c;
|
|
36
|
+
c.f = x;
|
|
37
|
+
return (__m256)__lasx_xvreplgr2vr_w((int)c.u);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** @brief Broadcast f64 scalar into all 4 lanes of a 256-bit register (GCC/Clang portable). */
|
|
41
|
+
NK_INTERNAL __m256d nk_xvfreplgr2vr_d_(double x) {
|
|
42
|
+
nk_fui64_t c;
|
|
43
|
+
c.f = x;
|
|
44
|
+
return (__m256d)__lasx_xvreplgr2vr_d((long long)c.u);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
NK_PUBLIC nk_f32_t nk_f32_rsqrt_loongsonasx(nk_f32_t x) {
|
|
48
|
+
// xvfrsqrt.s is full precision — no Newton-Raphson needed
|
|
49
|
+
__m256 x_f32x8 = nk_xvfreplgr2vr_s_(x);
|
|
50
|
+
__m256 result_f32x8 = __lasx_xvfrsqrt_s(x_f32x8);
|
|
51
|
+
nk_fui32_t c;
|
|
52
|
+
c.u = (nk_u32_t)__lasx_xvpickve2gr_w((__m256i)result_f32x8, 0);
|
|
53
|
+
return c.f;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
NK_PUBLIC nk_f32_t nk_f32_sqrt_loongsonasx(nk_f32_t x) { return x > 0 ? x * nk_f32_rsqrt_loongsonasx(x) : 0; }
|
|
57
|
+
|
|
58
|
+
NK_PUBLIC nk_f64_t nk_f64_sqrt_loongsonasx(nk_f64_t x) {
|
|
59
|
+
__m256d x_f64x4 = nk_xvfreplgr2vr_d_(x);
|
|
60
|
+
__m256d result_f64x4 = __lasx_xvfsqrt_d(x_f64x4);
|
|
61
|
+
nk_fui64_t c;
|
|
62
|
+
c.u = (nk_u64_t)__lasx_xvpickve2gr_du((__m256i)result_f64x4, 0);
|
|
63
|
+
return c.f;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
NK_PUBLIC nk_f64_t nk_f64_rsqrt_loongsonasx(nk_f64_t x) { return 1.0 / nk_f64_sqrt_loongsonasx(x); }
|
|
67
|
+
|
|
68
|
+
#if defined(__cplusplus)
|
|
69
|
+
} // extern "C"
|
|
70
|
+
#endif
|
|
71
|
+
|
|
72
|
+
#endif // NK_TARGET_LOONGSONASX
|
|
73
|
+
#endif // NK_TARGET_LOONGARCH64_
|
|
74
|
+
#endif // NK_SCALAR_LOONGSONASX_H
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Scalar Math Helpers for NEON.
|
|
3
|
+
* @file include/numkong/scalar/neon.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 1, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*
|
|
9
|
+
* @section scalars_neon_instructions Key NEON Scalar Instructions
|
|
10
|
+
*
|
|
11
|
+
* Intrinsic Instruction A76 M5
|
|
12
|
+
* vsqrt_f32 FSQRT (S) 12cy @ 1p 9cy @ 1p
|
|
13
|
+
* vsqrt_f64 FSQRT (D) 12cy @ 1p 9cy @ 1p
|
|
14
|
+
* vfmas_f32 FMADD (S, S, S, S) 4cy @ 2p 3cy @ 4p
|
|
15
|
+
* vfmad_f64 FMADD (D, D, D, D) 4cy @ 2p 3cy @ 4p
|
|
16
|
+
* vqaddb_u8 UQADD (B) 2cy @ 2p 3cy @ 2p
|
|
17
|
+
* vqaddb_s8 SQADD (B) 2cy @ 2p 3cy @ 2p
|
|
18
|
+
*/
|
|
19
|
+
#ifndef NK_SCALAR_NEON_H
|
|
20
|
+
#define NK_SCALAR_NEON_H
|
|
21
|
+
|
|
22
|
+
#if NK_TARGET_ARM64_
|
|
23
|
+
#if NK_TARGET_NEON
|
|
24
|
+
|
|
25
|
+
#include "numkong/types.h"
|
|
26
|
+
|
|
27
|
+
#if defined(__cplusplus)
|
|
28
|
+
extern "C" {
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#if defined(__clang__)
|
|
32
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8-a+simd"))), apply_to = function)
|
|
33
|
+
#elif defined(__GNUC__)
|
|
34
|
+
#pragma GCC push_options
|
|
35
|
+
#pragma GCC target("arch=armv8-a+simd")
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
NK_PUBLIC nk_f32_t nk_f32_sqrt_neon(nk_f32_t x) { return vget_lane_f32(vsqrt_f32(vdup_n_f32(x)), 0); }
|
|
39
|
+
NK_PUBLIC nk_f64_t nk_f64_sqrt_neon(nk_f64_t x) { return vget_lane_f64(vsqrt_f64(vdup_n_f64(x)), 0); }
|
|
40
|
+
NK_PUBLIC nk_f32_t nk_f32_rsqrt_neon(nk_f32_t x) {
|
|
41
|
+
nk_f32_t r = vrsqrtes_f32(x);
|
|
42
|
+
r *= vrsqrtss_f32(x * r, r);
|
|
43
|
+
r *= vrsqrtss_f32(x * r, r);
|
|
44
|
+
return r;
|
|
45
|
+
}
|
|
46
|
+
NK_PUBLIC nk_f64_t nk_f64_rsqrt_neon(nk_f64_t x) {
|
|
47
|
+
nk_f64_t r = vrsqrted_f64(x);
|
|
48
|
+
r *= vrsqrtsd_f64(x * r, r);
|
|
49
|
+
r *= vrsqrtsd_f64(x * r, r);
|
|
50
|
+
r *= vrsqrtsd_f64(x * r, r);
|
|
51
|
+
return r;
|
|
52
|
+
}
|
|
53
|
+
NK_PUBLIC nk_f32_t nk_f32_fma_neon(nk_f32_t a, nk_f32_t b, nk_f32_t c) {
|
|
54
|
+
// MSVC lacks both GCC inline asm and scalar ACLE FMA intrinsics (vfmas_f32/vfmad_f64).
|
|
55
|
+
// GCC/Clang: use inline asm for scalar FMADD.
|
|
56
|
+
// MSVC: use vector FMA + lane extract (compiler may optimize to scalar FMADD).
|
|
57
|
+
#if defined(_MSC_VER)
|
|
58
|
+
return vget_lane_f32(vfma_f32(vdup_n_f32(c), vdup_n_f32(a), vdup_n_f32(b)), 0);
|
|
59
|
+
#else
|
|
60
|
+
nk_f32_t r;
|
|
61
|
+
__asm__("fmadd %s0, %s1, %s2, %s3" : "=w"(r) : "w"(a), "w"(b), "w"(c));
|
|
62
|
+
return r;
|
|
63
|
+
#endif
|
|
64
|
+
}
|
|
65
|
+
NK_PUBLIC nk_f64_t nk_f64_fma_neon(nk_f64_t a, nk_f64_t b, nk_f64_t c) {
|
|
66
|
+
// MSVC lacks both GCC inline asm and scalar ACLE FMA intrinsics (vfmas_f32/vfmad_f64).
|
|
67
|
+
// GCC/Clang: use inline asm for scalar FMADD.
|
|
68
|
+
// MSVC: use vector FMA + lane extract (compiler may optimize to scalar FMADD).
|
|
69
|
+
#if defined(_MSC_VER)
|
|
70
|
+
return vget_lane_f64(vfma_f64(vdup_n_f64(c), vdup_n_f64(a), vdup_n_f64(b)), 0);
|
|
71
|
+
#else
|
|
72
|
+
nk_f64_t r;
|
|
73
|
+
__asm__("fmadd %d0, %d1, %d2, %d3" : "=w"(r) : "w"(a), "w"(b), "w"(c));
|
|
74
|
+
return r;
|
|
75
|
+
#endif
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
NK_PUBLIC nk_u8_t nk_u8_saturating_add_neon(nk_u8_t a, nk_u8_t b) { return vqaddb_u8(a, b); }
|
|
79
|
+
NK_PUBLIC nk_i8_t nk_i8_saturating_add_neon(nk_i8_t a, nk_i8_t b) { return vqaddb_s8(a, b); }
|
|
80
|
+
NK_PUBLIC nk_u16_t nk_u16_saturating_add_neon(nk_u16_t a, nk_u16_t b) { return vqaddh_u16(a, b); }
|
|
81
|
+
NK_PUBLIC nk_i16_t nk_i16_saturating_add_neon(nk_i16_t a, nk_i16_t b) { return vqaddh_s16(a, b); }
|
|
82
|
+
NK_PUBLIC nk_u32_t nk_u32_saturating_add_neon(nk_u32_t a, nk_u32_t b) { return vqadds_u32(a, b); }
|
|
83
|
+
NK_PUBLIC nk_i32_t nk_i32_saturating_add_neon(nk_i32_t a, nk_i32_t b) { return vqadds_s32(a, b); }
|
|
84
|
+
NK_PUBLIC nk_u64_t nk_u64_saturating_add_neon(nk_u64_t a, nk_u64_t b) { return vqaddd_u64(a, b); }
|
|
85
|
+
NK_PUBLIC nk_i64_t nk_i64_saturating_add_neon(nk_i64_t a, nk_i64_t b) { return vqaddd_s64(a, b); }
|
|
86
|
+
|
|
87
|
+
NK_INTERNAL nk_u64_t nk_u64_mulhigh_neon_(nk_u64_t a, nk_u64_t b) {
|
|
88
|
+
#if defined(_MSC_VER)
|
|
89
|
+
return __umulh(a, b);
|
|
90
|
+
#else
|
|
91
|
+
nk_u64_t high;
|
|
92
|
+
__asm__("umulh %0, %1, %2" : "=r"(high) : "r"(a), "r"(b));
|
|
93
|
+
return high;
|
|
94
|
+
#endif
|
|
95
|
+
}
|
|
96
|
+
NK_PUBLIC nk_u64_t nk_u64_saturating_mul_neon(nk_u64_t a, nk_u64_t b) {
|
|
97
|
+
return nk_u64_mulhigh_neon_(a, b) ? 18446744073709551615ull : (a * b);
|
|
98
|
+
}
|
|
99
|
+
NK_PUBLIC nk_i64_t nk_i64_saturating_mul_neon(nk_i64_t a, nk_i64_t b) {
|
|
100
|
+
int sign = (a < 0) ^ (b < 0);
|
|
101
|
+
nk_u64_t abs_a = a < 0 ? (0u - (nk_u64_t)a) : (nk_u64_t)a;
|
|
102
|
+
nk_u64_t abs_b = b < 0 ? (0u - (nk_u64_t)b) : (nk_u64_t)b;
|
|
103
|
+
nk_u64_t high = nk_u64_mulhigh_neon_(abs_a, abs_b);
|
|
104
|
+
nk_u64_t low = abs_a * abs_b;
|
|
105
|
+
if (high || (sign && low > 9223372036854775808ull) || (!sign && low > 9223372036854775807ull))
|
|
106
|
+
return sign ? (-9223372036854775807ll - 1ll) : 9223372036854775807ll;
|
|
107
|
+
return sign ? -(nk_i64_t)low : (nk_i64_t)low;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#if defined(__clang__)
|
|
111
|
+
#pragma clang attribute pop
|
|
112
|
+
#elif defined(__GNUC__)
|
|
113
|
+
#pragma GCC pop_options
|
|
114
|
+
#endif
|
|
115
|
+
|
|
116
|
+
#if defined(__cplusplus)
|
|
117
|
+
} // extern "C"
|
|
118
|
+
#endif
|
|
119
|
+
|
|
120
|
+
#endif // NK_TARGET_NEON
|
|
121
|
+
#endif // NK_TARGET_ARM64_
|
|
122
|
+
#endif // NK_SCALAR_NEON_H
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Scalar Math Helpers for NEON FP16 (FEAT_FP16).
|
|
3
|
+
* @file include/numkong/scalar/neonhalf.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 1, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*
|
|
9
|
+
* ARMv8.2-A FEAT_FP16 provides native scalar f16 sqrt, rsqrt estimate, and fma.
|
|
10
|
+
* `vrsqrte_f16` gives ~4-bit estimate; 2 Newton-Raphson steps refine to ~16 bits,
|
|
11
|
+
* exceeding f16's 10-bit mantissa precision.
|
|
12
|
+
*/
|
|
13
|
+
#ifndef NK_SCALAR_NEONHALF_H
|
|
14
|
+
#define NK_SCALAR_NEONHALF_H
|
|
15
|
+
|
|
16
|
+
#if NK_TARGET_ARM64_
|
|
17
|
+
#if NK_TARGET_NEONHALF
|
|
18
|
+
|
|
19
|
+
#include "numkong/types.h"
|
|
20
|
+
|
|
21
|
+
#if defined(__cplusplus)
|
|
22
|
+
extern "C" {
|
|
23
|
+
#endif
|
|
24
|
+
|
|
25
|
+
#if defined(__clang__)
|
|
26
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8.2-a+simd+fp16"))), apply_to = function)
|
|
27
|
+
#elif defined(__GNUC__)
|
|
28
|
+
#pragma GCC push_options
|
|
29
|
+
#pragma GCC target("arch=armv8.2-a+simd+fp16")
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
NK_PUBLIC nk_f16_t nk_f16_sqrt_neonhalf(nk_f16_t x) {
|
|
33
|
+
float16x4_t x_f16x4 = vld1_dup_f16((nk_f16_for_arm_simd_t const *)&x);
|
|
34
|
+
x_f16x4 = vsqrt_f16(x_f16x4);
|
|
35
|
+
nk_f16_t result;
|
|
36
|
+
vst1_lane_f16((nk_f16_for_arm_simd_t *)&result, x_f16x4, 0);
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
NK_PUBLIC nk_f16_t nk_f16_rsqrt_neonhalf(nk_f16_t x) {
|
|
40
|
+
float16x4_t x_f16x4 = vld1_dup_f16((nk_f16_for_arm_simd_t const *)&x);
|
|
41
|
+
float16x4_t estimate_f16x4 = vrsqrte_f16(x_f16x4);
|
|
42
|
+
estimate_f16x4 = vmul_f16(estimate_f16x4, vrsqrts_f16(vmul_f16(x_f16x4, estimate_f16x4), estimate_f16x4));
|
|
43
|
+
estimate_f16x4 = vmul_f16(estimate_f16x4, vrsqrts_f16(vmul_f16(x_f16x4, estimate_f16x4), estimate_f16x4));
|
|
44
|
+
nk_f16_t result;
|
|
45
|
+
vst1_lane_f16((nk_f16_for_arm_simd_t *)&result, estimate_f16x4, 0);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
NK_PUBLIC nk_f16_t nk_f16_fma_neonhalf(nk_f16_t a, nk_f16_t b, nk_f16_t c) {
|
|
49
|
+
float16x4_t a_f16x4 = vld1_dup_f16((nk_f16_for_arm_simd_t const *)&a);
|
|
50
|
+
float16x4_t b_f16x4 = vld1_dup_f16((nk_f16_for_arm_simd_t const *)&b);
|
|
51
|
+
float16x4_t c_f16x4 = vld1_dup_f16((nk_f16_for_arm_simd_t const *)&c);
|
|
52
|
+
c_f16x4 = vfma_f16(c_f16x4, a_f16x4, b_f16x4);
|
|
53
|
+
nk_f16_t result;
|
|
54
|
+
vst1_lane_f16((nk_f16_for_arm_simd_t *)&result, c_f16x4, 0);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#if defined(__clang__)
|
|
59
|
+
#pragma clang attribute pop
|
|
60
|
+
#elif defined(__GNUC__)
|
|
61
|
+
#pragma GCC pop_options
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
#if defined(__cplusplus)
|
|
65
|
+
} // extern "C"
|
|
66
|
+
#endif
|
|
67
|
+
|
|
68
|
+
#endif // NK_TARGET_NEONHALF
|
|
69
|
+
#endif // NK_TARGET_ARM64_
|
|
70
|
+
#endif // NK_SCALAR_NEONHALF_H
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Scalar Math Helpers for Power VSX.
|
|
3
|
+
* @file include/numkong/scalar/powervsx.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 24, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*
|
|
9
|
+
* @section scalars_powervsx_instructions Key Power VSX Scalar Instructions
|
|
10
|
+
*
|
|
11
|
+
* Instruction Description Latency
|
|
12
|
+
* xssqrtsp Scalar √ (f32) 26cy
|
|
13
|
+
* xssqrtdp Scalar √ (f64) 33cy
|
|
14
|
+
* xsrsqrtesp Scalar 1/√ estimate (f32) 6cy
|
|
15
|
+
* xsrsqrtedp Scalar 1/√ estimate (f64) 6cy
|
|
16
|
+
* xsmaddadp Scalar FMA (f64) 5cy
|
|
17
|
+
* xsmaddasp Scalar FMA (f32) 5cy
|
|
18
|
+
*/
|
|
19
|
+
#ifndef NK_SCALAR_POWERVSX_H
|
|
20
|
+
#define NK_SCALAR_POWERVSX_H
|
|
21
|
+
|
|
22
|
+
#if NK_TARGET_POWER64_
|
|
23
|
+
#if NK_TARGET_POWERVSX
|
|
24
|
+
|
|
25
|
+
#include "numkong/types.h"
|
|
26
|
+
|
|
27
|
+
#if defined(__cplusplus)
|
|
28
|
+
extern "C" {
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#if defined(__clang__)
|
|
32
|
+
#pragma clang attribute push(__attribute__((target("power9-vector"))), apply_to = function)
|
|
33
|
+
#elif defined(__GNUC__)
|
|
34
|
+
#pragma GCC push_options
|
|
35
|
+
#pragma GCC target("power9-vector")
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
NK_PUBLIC nk_f32_t nk_f32_sqrt_powervsx(nk_f32_t x) {
|
|
39
|
+
nk_f32_t result;
|
|
40
|
+
__asm__("xssqrtsp %0, %1" : "=f"(result) : "f"(x));
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
NK_PUBLIC nk_f64_t nk_f64_sqrt_powervsx(nk_f64_t x) {
|
|
44
|
+
nk_f64_t result;
|
|
45
|
+
__asm__("xssqrtdp %0, %1" : "=d"(result) : "d"(x));
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
NK_PUBLIC nk_f32_t nk_f32_rsqrt_powervsx(nk_f32_t x) {
|
|
49
|
+
// xsrsqrtesp → ~12-bit estimate, then 2 Newton→Raphson iterations → ~24-bit precision
|
|
50
|
+
nk_f32_t r;
|
|
51
|
+
__asm__("xsrsqrtesp %0, %1" : "=f"(r) : "f"(x));
|
|
52
|
+
// Newton→Raphson: r = r * (3 - x * r * r) / 2
|
|
53
|
+
nk_f32_t half_x = x * 0.5f;
|
|
54
|
+
nk_f32_t three_half = 1.5f;
|
|
55
|
+
r = r * (three_half - half_x * r * r);
|
|
56
|
+
r = r * (three_half - half_x * r * r);
|
|
57
|
+
return r;
|
|
58
|
+
}
|
|
59
|
+
NK_PUBLIC nk_f64_t nk_f64_rsqrt_powervsx(nk_f64_t x) {
|
|
60
|
+
// xsrsqrtedp → ~14-bit estimate, then 3 Newton→Raphson iterations → ~48-bit precision
|
|
61
|
+
nk_f64_t r;
|
|
62
|
+
__asm__("xsrsqrtedp %0, %1" : "=d"(r) : "d"(x));
|
|
63
|
+
// Newton→Raphson: r = r * (3 - x * r * r) / 2
|
|
64
|
+
nk_f64_t half_x = x * 0.5;
|
|
65
|
+
nk_f64_t three_half = 1.5;
|
|
66
|
+
r = r * (three_half - half_x * r * r);
|
|
67
|
+
r = r * (three_half - half_x * r * r);
|
|
68
|
+
r = r * (three_half - half_x * r * r);
|
|
69
|
+
return r;
|
|
70
|
+
}
|
|
71
|
+
NK_PUBLIC nk_f32_t nk_f32_fma_powervsx(nk_f32_t a, nk_f32_t b, nk_f32_t c) {
|
|
72
|
+
// xsmaddasp: result = a * b + c (scalar f32 FMA)
|
|
73
|
+
nk_f32_t r = c;
|
|
74
|
+
__asm__("xsmaddasp %0, %1, %2" : "+f"(r) : "f"(a), "f"(b));
|
|
75
|
+
return r;
|
|
76
|
+
}
|
|
77
|
+
NK_PUBLIC nk_f64_t nk_f64_fma_powervsx(nk_f64_t a, nk_f64_t b, nk_f64_t c) {
|
|
78
|
+
// xsmaddadp: result = a * b + c (scalar f64 FMA)
|
|
79
|
+
nk_f64_t r = c;
|
|
80
|
+
__asm__("xsmaddadp %0, %1, %2" : "+d"(r) : "d"(a), "d"(b));
|
|
81
|
+
return r;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#if defined(__clang__)
|
|
85
|
+
#pragma clang attribute pop
|
|
86
|
+
#elif defined(__GNUC__)
|
|
87
|
+
#pragma GCC pop_options
|
|
88
|
+
#endif
|
|
89
|
+
|
|
90
|
+
#if defined(__cplusplus)
|
|
91
|
+
} // extern "C"
|
|
92
|
+
#endif
|
|
93
|
+
|
|
94
|
+
#endif // NK_TARGET_POWERVSX
|
|
95
|
+
#endif // NK_TARGET_POWER64_
|
|
96
|
+
#endif // NK_SCALAR_POWERVSX_H
|