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,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Scalar Math Helpers for RISC-V.
|
|
3
|
+
* @file include/numkong/scalar/rvv.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 1, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*
|
|
9
|
+
* RVV scalar helpers use vector instructions with VL=1 for hardware sqrt/rsqrt.
|
|
10
|
+
* `vfrsqrt7` provides 7-bit mantissa precision; Newton-Raphson refines to full precision.
|
|
11
|
+
*/
|
|
12
|
+
#ifndef NK_SCALAR_RVV_H
|
|
13
|
+
#define NK_SCALAR_RVV_H
|
|
14
|
+
|
|
15
|
+
#if NK_TARGET_RISCV64_
|
|
16
|
+
#if NK_TARGET_RVV
|
|
17
|
+
|
|
18
|
+
#include "numkong/types.h"
|
|
19
|
+
|
|
20
|
+
#if defined(__clang__)
|
|
21
|
+
#pragma clang attribute push(__attribute__((target("arch=+v"))), apply_to = function)
|
|
22
|
+
#elif defined(__GNUC__)
|
|
23
|
+
#pragma GCC push_options
|
|
24
|
+
#pragma GCC target("arch=+v")
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
#if defined(__cplusplus)
|
|
28
|
+
extern "C" {
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
NK_PUBLIC nk_f32_t nk_f32_rsqrt_rvv(nk_f32_t number) {
|
|
32
|
+
vfloat32m1_t x_f32m1 = __riscv_vfmv_s_f_f32m1(number, 1);
|
|
33
|
+
vfloat32m1_t estimate_f32m1 = __riscv_vfrsqrt7_v_f32m1(x_f32m1, 1);
|
|
34
|
+
vfloat32m1_t half_f32m1 = __riscv_vfmv_s_f_f32m1(0.5f, 1);
|
|
35
|
+
vfloat32m1_t three_half_f32m1 = __riscv_vfmv_s_f_f32m1(1.5f, 1);
|
|
36
|
+
vfloat32m1_t half_x_f32m1 = __riscv_vfmul_vv_f32m1(half_f32m1, x_f32m1, 1);
|
|
37
|
+
// Iteration 1
|
|
38
|
+
vfloat32m1_t estimate_sq_f32m1 = __riscv_vfmul_vv_f32m1(estimate_f32m1, estimate_f32m1, 1);
|
|
39
|
+
vfloat32m1_t correction_f32m1 = __riscv_vfmul_vv_f32m1(half_x_f32m1, estimate_sq_f32m1, 1);
|
|
40
|
+
vfloat32m1_t factor_f32m1 = __riscv_vfsub_vv_f32m1(three_half_f32m1, correction_f32m1, 1);
|
|
41
|
+
estimate_f32m1 = __riscv_vfmul_vv_f32m1(estimate_f32m1, factor_f32m1, 1);
|
|
42
|
+
// Iteration 2
|
|
43
|
+
estimate_sq_f32m1 = __riscv_vfmul_vv_f32m1(estimate_f32m1, estimate_f32m1, 1);
|
|
44
|
+
correction_f32m1 = __riscv_vfmul_vv_f32m1(half_x_f32m1, estimate_sq_f32m1, 1);
|
|
45
|
+
factor_f32m1 = __riscv_vfsub_vv_f32m1(three_half_f32m1, correction_f32m1, 1);
|
|
46
|
+
estimate_f32m1 = __riscv_vfmul_vv_f32m1(estimate_f32m1, factor_f32m1, 1);
|
|
47
|
+
return __riscv_vfmv_f_s_f32m1_f32(estimate_f32m1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
NK_PUBLIC nk_f32_t nk_f32_sqrt_rvv(nk_f32_t number) {
|
|
51
|
+
vfloat32m1_t x_f32m1 = __riscv_vfmv_s_f_f32m1(number, 1);
|
|
52
|
+
return __riscv_vfmv_f_s_f32m1_f32(__riscv_vfsqrt_v_f32m1(x_f32m1, 1));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
NK_PUBLIC nk_f64_t nk_f64_rsqrt_rvv(nk_f64_t number) {
|
|
56
|
+
vfloat64m1_t x_f64m1 = __riscv_vfmv_s_f_f64m1(number, 1);
|
|
57
|
+
vfloat64m1_t estimate_f64m1 = __riscv_vfrsqrt7_v_f64m1(x_f64m1, 1);
|
|
58
|
+
vfloat64m1_t half_f64m1 = __riscv_vfmv_s_f_f64m1(0.5, 1);
|
|
59
|
+
vfloat64m1_t three_half_f64m1 = __riscv_vfmv_s_f_f64m1(1.5, 1);
|
|
60
|
+
vfloat64m1_t half_x_f64m1 = __riscv_vfmul_vv_f64m1(half_f64m1, x_f64m1, 1);
|
|
61
|
+
// Iteration 1
|
|
62
|
+
vfloat64m1_t estimate_sq_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, estimate_f64m1, 1);
|
|
63
|
+
vfloat64m1_t correction_f64m1 = __riscv_vfmul_vv_f64m1(half_x_f64m1, estimate_sq_f64m1, 1);
|
|
64
|
+
vfloat64m1_t factor_f64m1 = __riscv_vfsub_vv_f64m1(three_half_f64m1, correction_f64m1, 1);
|
|
65
|
+
estimate_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, factor_f64m1, 1);
|
|
66
|
+
// Iteration 2
|
|
67
|
+
estimate_sq_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, estimate_f64m1, 1);
|
|
68
|
+
correction_f64m1 = __riscv_vfmul_vv_f64m1(half_x_f64m1, estimate_sq_f64m1, 1);
|
|
69
|
+
factor_f64m1 = __riscv_vfsub_vv_f64m1(three_half_f64m1, correction_f64m1, 1);
|
|
70
|
+
estimate_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, factor_f64m1, 1);
|
|
71
|
+
// Iteration 3
|
|
72
|
+
estimate_sq_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, estimate_f64m1, 1);
|
|
73
|
+
correction_f64m1 = __riscv_vfmul_vv_f64m1(half_x_f64m1, estimate_sq_f64m1, 1);
|
|
74
|
+
factor_f64m1 = __riscv_vfsub_vv_f64m1(three_half_f64m1, correction_f64m1, 1);
|
|
75
|
+
estimate_f64m1 = __riscv_vfmul_vv_f64m1(estimate_f64m1, factor_f64m1, 1);
|
|
76
|
+
return __riscv_vfmv_f_s_f64m1_f64(estimate_f64m1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
NK_PUBLIC nk_f64_t nk_f64_sqrt_rvv(nk_f64_t number) {
|
|
80
|
+
vfloat64m1_t x_f64m1 = __riscv_vfmv_s_f_f64m1(number, 1);
|
|
81
|
+
return __riscv_vfmv_f_s_f64m1_f64(__riscv_vfsqrt_v_f64m1(x_f64m1, 1));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
NK_PUBLIC nk_f32_t nk_f32_fma_rvv(nk_f32_t a, nk_f32_t b, nk_f32_t c) {
|
|
85
|
+
vfloat32m1_t a_f32m1 = __riscv_vfmv_s_f_f32m1(a, 1);
|
|
86
|
+
vfloat32m1_t c_f32m1 = __riscv_vfmv_s_f_f32m1(c, 1);
|
|
87
|
+
return __riscv_vfmv_f_s_f32m1_f32(__riscv_vfmacc_vf_f32m1(c_f32m1, b, a_f32m1, 1));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
NK_PUBLIC nk_f64_t nk_f64_fma_rvv(nk_f64_t a, nk_f64_t b, nk_f64_t c) {
|
|
91
|
+
vfloat64m1_t a_f64m1 = __riscv_vfmv_s_f_f64m1(a, 1);
|
|
92
|
+
vfloat64m1_t c_f64m1 = __riscv_vfmv_s_f_f64m1(c, 1);
|
|
93
|
+
return __riscv_vfmv_f_s_f64m1_f64(__riscv_vfmacc_vf_f64m1(c_f64m1, b, a_f64m1, 1));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
NK_PUBLIC nk_u8_t nk_u8_saturating_add_rvv(nk_u8_t a, nk_u8_t b) {
|
|
97
|
+
vuint8m1_t a_u8m1 = __riscv_vmv_v_x_u8m1(a, 1);
|
|
98
|
+
vuint8m1_t b_u8m1 = __riscv_vmv_v_x_u8m1(b, 1);
|
|
99
|
+
return __riscv_vmv_x_s_u8m1_u8(__riscv_vsaddu_vv_u8m1(a_u8m1, b_u8m1, 1));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
NK_PUBLIC nk_i8_t nk_i8_saturating_add_rvv(nk_i8_t a, nk_i8_t b) {
|
|
103
|
+
vint8m1_t a_i8m1 = __riscv_vmv_v_x_i8m1(a, 1);
|
|
104
|
+
vint8m1_t b_i8m1 = __riscv_vmv_v_x_i8m1(b, 1);
|
|
105
|
+
return __riscv_vmv_x_s_i8m1_i8(__riscv_vsadd_vv_i8m1(a_i8m1, b_i8m1, 1));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
NK_PUBLIC nk_u16_t nk_u16_saturating_add_rvv(nk_u16_t a, nk_u16_t b) {
|
|
109
|
+
vuint16m1_t a_u16m1 = __riscv_vmv_v_x_u16m1(a, 1);
|
|
110
|
+
vuint16m1_t b_u16m1 = __riscv_vmv_v_x_u16m1(b, 1);
|
|
111
|
+
return __riscv_vmv_x_s_u16m1_u16(__riscv_vsaddu_vv_u16m1(a_u16m1, b_u16m1, 1));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
NK_PUBLIC nk_i16_t nk_i16_saturating_add_rvv(nk_i16_t a, nk_i16_t b) {
|
|
115
|
+
vint16m1_t a_i16m1 = __riscv_vmv_v_x_i16m1(a, 1);
|
|
116
|
+
vint16m1_t b_i16m1 = __riscv_vmv_v_x_i16m1(b, 1);
|
|
117
|
+
return __riscv_vmv_x_s_i16m1_i16(__riscv_vsadd_vv_i16m1(a_i16m1, b_i16m1, 1));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
NK_PUBLIC nk_u32_t nk_u32_saturating_add_rvv(nk_u32_t a, nk_u32_t b) {
|
|
121
|
+
vuint32m1_t a_u32m1 = __riscv_vmv_v_x_u32m1(a, 1);
|
|
122
|
+
vuint32m1_t b_u32m1 = __riscv_vmv_v_x_u32m1(b, 1);
|
|
123
|
+
return __riscv_vmv_x_s_u32m1_u32(__riscv_vsaddu_vv_u32m1(a_u32m1, b_u32m1, 1));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
NK_PUBLIC nk_i32_t nk_i32_saturating_add_rvv(nk_i32_t a, nk_i32_t b) {
|
|
127
|
+
vint32m1_t a_i32m1 = __riscv_vmv_v_x_i32m1(a, 1);
|
|
128
|
+
vint32m1_t b_i32m1 = __riscv_vmv_v_x_i32m1(b, 1);
|
|
129
|
+
return __riscv_vmv_x_s_i32m1_i32(__riscv_vsadd_vv_i32m1(a_i32m1, b_i32m1, 1));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
NK_PUBLIC nk_u64_t nk_u64_saturating_add_rvv(nk_u64_t a, nk_u64_t b) {
|
|
133
|
+
vuint64m1_t a_u64m1 = __riscv_vmv_v_x_u64m1(a, 1);
|
|
134
|
+
vuint64m1_t b_u64m1 = __riscv_vmv_v_x_u64m1(b, 1);
|
|
135
|
+
return __riscv_vmv_x_s_u64m1_u64(__riscv_vsaddu_vv_u64m1(a_u64m1, b_u64m1, 1));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
NK_PUBLIC nk_i64_t nk_i64_saturating_add_rvv(nk_i64_t a, nk_i64_t b) {
|
|
139
|
+
vint64m1_t a_i64m1 = __riscv_vmv_v_x_i64m1(a, 1);
|
|
140
|
+
vint64m1_t b_i64m1 = __riscv_vmv_v_x_i64m1(b, 1);
|
|
141
|
+
return __riscv_vmv_x_s_i64m1_i64(__riscv_vsadd_vv_i64m1(a_i64m1, b_i64m1, 1));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
NK_PUBLIC nk_u8_t nk_u8_saturating_mul_rvv(nk_u8_t a, nk_u8_t b) {
|
|
145
|
+
vuint8m1_t a_u8m1 = __riscv_vmv_v_x_u8m1(a, 1);
|
|
146
|
+
vuint8m1_t b_u8m1 = __riscv_vmv_v_x_u8m1(b, 1);
|
|
147
|
+
vuint16m2_t product_u16m2 = __riscv_vwmulu_vv_u16m2(a_u8m1, b_u8m1, 1);
|
|
148
|
+
return __riscv_vmv_x_s_u8m1_u8(__riscv_vnclipu_wx_u8m1(product_u16m2, 0, __RISCV_VXRM_RDN, 1));
|
|
149
|
+
}
|
|
150
|
+
NK_PUBLIC nk_i8_t nk_i8_saturating_mul_rvv(nk_i8_t a, nk_i8_t b) {
|
|
151
|
+
vint8m1_t a_i8m1 = __riscv_vmv_v_x_i8m1(a, 1);
|
|
152
|
+
vint8m1_t b_i8m1 = __riscv_vmv_v_x_i8m1(b, 1);
|
|
153
|
+
vint16m2_t product_i16m2 = __riscv_vwmul_vv_i16m2(a_i8m1, b_i8m1, 1);
|
|
154
|
+
return __riscv_vmv_x_s_i8m1_i8(__riscv_vnclip_wx_i8m1(product_i16m2, 0, __RISCV_VXRM_RDN, 1));
|
|
155
|
+
}
|
|
156
|
+
NK_PUBLIC nk_u16_t nk_u16_saturating_mul_rvv(nk_u16_t a, nk_u16_t b) {
|
|
157
|
+
vuint16m1_t a_u16m1 = __riscv_vmv_v_x_u16m1(a, 1);
|
|
158
|
+
vuint16m1_t b_u16m1 = __riscv_vmv_v_x_u16m1(b, 1);
|
|
159
|
+
vuint32m2_t product_u32m2 = __riscv_vwmulu_vv_u32m2(a_u16m1, b_u16m1, 1);
|
|
160
|
+
return __riscv_vmv_x_s_u16m1_u16(__riscv_vnclipu_wx_u16m1(product_u32m2, 0, __RISCV_VXRM_RDN, 1));
|
|
161
|
+
}
|
|
162
|
+
NK_PUBLIC nk_i16_t nk_i16_saturating_mul_rvv(nk_i16_t a, nk_i16_t b) {
|
|
163
|
+
vint16m1_t a_i16m1 = __riscv_vmv_v_x_i16m1(a, 1);
|
|
164
|
+
vint16m1_t b_i16m1 = __riscv_vmv_v_x_i16m1(b, 1);
|
|
165
|
+
vint32m2_t product_i32m2 = __riscv_vwmul_vv_i32m2(a_i16m1, b_i16m1, 1);
|
|
166
|
+
return __riscv_vmv_x_s_i16m1_i16(__riscv_vnclip_wx_i16m1(product_i32m2, 0, __RISCV_VXRM_RDN, 1));
|
|
167
|
+
}
|
|
168
|
+
NK_PUBLIC nk_u32_t nk_u32_saturating_mul_rvv(nk_u32_t a, nk_u32_t b) {
|
|
169
|
+
vuint32m1_t a_u32m1 = __riscv_vmv_v_x_u32m1(a, 1);
|
|
170
|
+
vuint32m1_t b_u32m1 = __riscv_vmv_v_x_u32m1(b, 1);
|
|
171
|
+
vuint64m2_t product_u64m2 = __riscv_vwmulu_vv_u64m2(a_u32m1, b_u32m1, 1);
|
|
172
|
+
return __riscv_vmv_x_s_u32m1_u32(__riscv_vnclipu_wx_u32m1(product_u64m2, 0, __RISCV_VXRM_RDN, 1));
|
|
173
|
+
}
|
|
174
|
+
NK_PUBLIC nk_i32_t nk_i32_saturating_mul_rvv(nk_i32_t a, nk_i32_t b) {
|
|
175
|
+
vint32m1_t a_i32m1 = __riscv_vmv_v_x_i32m1(a, 1);
|
|
176
|
+
vint32m1_t b_i32m1 = __riscv_vmv_v_x_i32m1(b, 1);
|
|
177
|
+
vint64m2_t product_i64m2 = __riscv_vwmul_vv_i64m2(a_i32m1, b_i32m1, 1);
|
|
178
|
+
return __riscv_vmv_x_s_i32m1_i32(__riscv_vnclip_wx_i32m1(product_i64m2, 0, __RISCV_VXRM_RDN, 1));
|
|
179
|
+
}
|
|
180
|
+
NK_PUBLIC nk_u64_t nk_u64_saturating_mul_rvv(nk_u64_t a, nk_u64_t b) {
|
|
181
|
+
vuint64m1_t a_u64m1 = __riscv_vmv_v_x_u64m1(a, 1);
|
|
182
|
+
vuint64m1_t b_u64m1 = __riscv_vmv_v_x_u64m1(b, 1);
|
|
183
|
+
nk_u64_t high = __riscv_vmv_x_s_u64m1_u64(__riscv_vmulhu_vv_u64m1(a_u64m1, b_u64m1, 1));
|
|
184
|
+
return high ? 18446744073709551615ull : (a * b);
|
|
185
|
+
}
|
|
186
|
+
NK_PUBLIC nk_i64_t nk_i64_saturating_mul_rvv(nk_i64_t a, nk_i64_t b) {
|
|
187
|
+
int sign = (a < 0) ^ (b < 0);
|
|
188
|
+
nk_u64_t abs_a = a < 0 ? (0u - (nk_u64_t)a) : (nk_u64_t)a;
|
|
189
|
+
nk_u64_t abs_b = b < 0 ? (0u - (nk_u64_t)b) : (nk_u64_t)b;
|
|
190
|
+
vuint64m1_t a_u64m1 = __riscv_vmv_v_x_u64m1(abs_a, 1);
|
|
191
|
+
vuint64m1_t b_u64m1 = __riscv_vmv_v_x_u64m1(abs_b, 1);
|
|
192
|
+
nk_u64_t high = __riscv_vmv_x_s_u64m1_u64(__riscv_vmulhu_vv_u64m1(a_u64m1, b_u64m1, 1));
|
|
193
|
+
nk_u64_t low = abs_a * abs_b;
|
|
194
|
+
if (high || (sign && low > 9223372036854775808ull) || (!sign && low > 9223372036854775807ull))
|
|
195
|
+
return sign ? (-9223372036854775807ll - 1ll) : 9223372036854775807ll;
|
|
196
|
+
return sign ? -(nk_i64_t)low : (nk_i64_t)low;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
#if defined(__cplusplus)
|
|
200
|
+
} // extern "C"
|
|
201
|
+
#endif
|
|
202
|
+
|
|
203
|
+
#if defined(__clang__)
|
|
204
|
+
#pragma clang attribute pop
|
|
205
|
+
#elif defined(__GNUC__)
|
|
206
|
+
#pragma GCC pop_options
|
|
207
|
+
#endif
|
|
208
|
+
|
|
209
|
+
#endif // NK_TARGET_RVV
|
|
210
|
+
#endif // NK_TARGET_RISCV64_
|
|
211
|
+
#endif // NK_SCALAR_RVV_H
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Scalar Math Helpers for Sapphire Rapids.
|
|
3
|
+
* @file include/numkong/scalar/sapphire.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 1, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*
|
|
9
|
+
* Provides native AVX-512 FP16 scalar ordering via `VCOMISH`.
|
|
10
|
+
*/
|
|
11
|
+
#ifndef NK_SCALAR_SAPPHIRE_H
|
|
12
|
+
#define NK_SCALAR_SAPPHIRE_H
|
|
13
|
+
|
|
14
|
+
#if NK_TARGET_X8664_
|
|
15
|
+
#if NK_TARGET_SAPPHIRE
|
|
16
|
+
|
|
17
|
+
#include "numkong/types.h"
|
|
18
|
+
|
|
19
|
+
#if defined(__cplusplus)
|
|
20
|
+
extern "C" {
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
#if defined(__clang__)
|
|
24
|
+
#pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,avx512bw,avx512fp16,f16c,fma,bmi,bmi2"))), \
|
|
25
|
+
apply_to = function)
|
|
26
|
+
#elif defined(__GNUC__)
|
|
27
|
+
#pragma GCC push_options
|
|
28
|
+
#pragma GCC target("avx2", "avx512f", "avx512vl", "avx512bw", "avx512fp16", "f16c", "fma", "bmi", "bmi2")
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
NK_PUBLIC int nk_f16_order_sapphire(nk_f16_t a, nk_f16_t b) {
|
|
32
|
+
nk_fui16_t a_fui, b_fui;
|
|
33
|
+
a_fui.f = a, b_fui.f = b;
|
|
34
|
+
__m128h a_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(a_fui.u));
|
|
35
|
+
__m128h b_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(b_fui.u));
|
|
36
|
+
return _mm_comigt_sh(a_f16x8, b_f16x8) - _mm_comilt_sh(a_f16x8, b_f16x8);
|
|
37
|
+
}
|
|
38
|
+
NK_PUBLIC nk_f16_t nk_f16_sqrt_sapphire(nk_f16_t x) {
|
|
39
|
+
nk_fui16_t x_fui, out_fui;
|
|
40
|
+
x_fui.f = x;
|
|
41
|
+
__m128h x_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(x_fui.u));
|
|
42
|
+
out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(_mm_castph_si128(_mm_sqrt_sh(x_f16x8, x_f16x8)));
|
|
43
|
+
return out_fui.f;
|
|
44
|
+
}
|
|
45
|
+
NK_PUBLIC nk_f16_t nk_f16_rsqrt_sapphire(nk_f16_t x) {
|
|
46
|
+
nk_fui16_t x_fui, out_fui;
|
|
47
|
+
x_fui.f = x;
|
|
48
|
+
__m128h x_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(x_fui.u));
|
|
49
|
+
out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(_mm_castph_si128(_mm_rsqrt_sh(x_f16x8, x_f16x8)));
|
|
50
|
+
return out_fui.f;
|
|
51
|
+
}
|
|
52
|
+
NK_PUBLIC nk_f16_t nk_f16_fma_sapphire(nk_f16_t a, nk_f16_t b, nk_f16_t c) {
|
|
53
|
+
nk_fui16_t a_fui, b_fui, c_fui, out_fui;
|
|
54
|
+
a_fui.f = a, b_fui.f = b, c_fui.f = c;
|
|
55
|
+
__m128h a_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(a_fui.u));
|
|
56
|
+
__m128h b_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(b_fui.u));
|
|
57
|
+
__m128h c_f16x8 = _mm_castsi128_ph(_mm_cvtsi32_si128(c_fui.u));
|
|
58
|
+
out_fui.u = (nk_u16_t)_mm_cvtsi128_si32(_mm_castph_si128(_mm_fmadd_sh(a_f16x8, b_f16x8, c_f16x8)));
|
|
59
|
+
return out_fui.f;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#if defined(__clang__)
|
|
63
|
+
#pragma clang attribute pop
|
|
64
|
+
#elif defined(__GNUC__)
|
|
65
|
+
#pragma GCC pop_options
|
|
66
|
+
#endif
|
|
67
|
+
|
|
68
|
+
#if defined(__cplusplus)
|
|
69
|
+
} // extern "C"
|
|
70
|
+
#endif
|
|
71
|
+
|
|
72
|
+
#endif // NK_TARGET_SAPPHIRE
|
|
73
|
+
#endif // NK_TARGET_X8664_
|
|
74
|
+
#endif // NK_SCALAR_SAPPHIRE_H
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief Software-emulated Scalar Math Helpers for SIMD-free CPUs.
|
|
3
|
+
* @file include/numkong/scalar/serial.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 1, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*
|
|
9
|
+
* Uses the Quake 3 fast inverse square root trick with Newton-Raphson refinement.
|
|
10
|
+
* Three iterations for f32 (~34.9 correct bits), four for f64 (~69.3 correct bits).
|
|
11
|
+
*/
|
|
12
|
+
#ifndef NK_SCALAR_SERIAL_H
|
|
13
|
+
#define NK_SCALAR_SERIAL_H
|
|
14
|
+
|
|
15
|
+
#include "numkong/types.h"
|
|
16
|
+
#include "numkong/cast/serial.h"
|
|
17
|
+
|
|
18
|
+
#if defined(__cplusplus)
|
|
19
|
+
extern "C" {
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
NK_PUBLIC nk_f32_t nk_f32_rsqrt_serial(nk_f32_t number) {
|
|
23
|
+
nk_fui32_t conv;
|
|
24
|
+
conv.f = number;
|
|
25
|
+
conv.u = 0x5F375A86 - (conv.u >> 1);
|
|
26
|
+
nk_f32_t y = conv.f;
|
|
27
|
+
y = y * (1.5f - 0.5f * number * y * y);
|
|
28
|
+
y = y * (1.5f - 0.5f * number * y * y);
|
|
29
|
+
y = y * (1.5f - 0.5f * number * y * y);
|
|
30
|
+
return y;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
NK_PUBLIC nk_f32_t nk_f32_sqrt_serial(nk_f32_t number) { return number > 0 ? number * nk_f32_rsqrt_serial(number) : 0; }
|
|
34
|
+
|
|
35
|
+
NK_PUBLIC nk_f64_t nk_f64_rsqrt_serial(nk_f64_t number) {
|
|
36
|
+
nk_fui64_t conv;
|
|
37
|
+
conv.f = number;
|
|
38
|
+
conv.u = 0x5FE6EB50C7B537A9ULL - (conv.u >> 1);
|
|
39
|
+
nk_f64_t y = conv.f;
|
|
40
|
+
y = y * (1.5 - 0.5 * number * y * y);
|
|
41
|
+
y = y * (1.5 - 0.5 * number * y * y);
|
|
42
|
+
y = y * (1.5 - 0.5 * number * y * y);
|
|
43
|
+
y = y * (1.5 - 0.5 * number * y * y);
|
|
44
|
+
return y;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
NK_PUBLIC nk_f64_t nk_f64_sqrt_serial(nk_f64_t number) { return number > 0 ? number * nk_f64_rsqrt_serial(number) : 0; }
|
|
48
|
+
|
|
49
|
+
NK_PUBLIC nk_f16_t nk_f16_sqrt_serial(nk_f16_t x) {
|
|
50
|
+
nk_f32_t x_f32;
|
|
51
|
+
nk_f16_to_f32_serial(&x, &x_f32);
|
|
52
|
+
x_f32 = nk_f32_sqrt_serial(x_f32);
|
|
53
|
+
nk_f16_t result;
|
|
54
|
+
nk_f32_to_f16_serial(&x_f32, &result);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
NK_PUBLIC nk_f16_t nk_f16_rsqrt_serial(nk_f16_t x) {
|
|
59
|
+
nk_f32_t x_f32;
|
|
60
|
+
nk_f16_to_f32_serial(&x, &x_f32);
|
|
61
|
+
x_f32 = nk_f32_rsqrt_serial(x_f32);
|
|
62
|
+
nk_f16_t result;
|
|
63
|
+
nk_f32_to_f16_serial(&x_f32, &result);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @brief Software FMA (Fused Multiply-Add) emulation for f64.
|
|
69
|
+
* Computes (multiplicand * multiplier + addend) with improved precision
|
|
70
|
+
* using Dekker's error-free multiplication and Knuth's TwoSum.
|
|
71
|
+
* @sa std::fma, @sa Rust f64::mul_add
|
|
72
|
+
*/
|
|
73
|
+
NK_PUBLIC nk_f64_t nk_f64_fma_serial(nk_f64_t multiplicand, nk_f64_t multiplier, nk_f64_t addend) {
|
|
74
|
+
nk_f64_t product = multiplicand * multiplier;
|
|
75
|
+
// Dekker splitting: break each operand into non-overlapping high and low halves
|
|
76
|
+
nk_f64_t const dekker_split = 134217729.0; // 2^27 + 1 for double precision
|
|
77
|
+
nk_f64_t multiplicand_high = dekker_split * multiplicand;
|
|
78
|
+
nk_f64_t multiplicand_low = multiplicand - (multiplicand_high - (multiplicand_high - multiplicand));
|
|
79
|
+
multiplicand_high = multiplicand_high - (multiplicand_high - multiplicand);
|
|
80
|
+
nk_f64_t multiplier_high = dekker_split * multiplier;
|
|
81
|
+
nk_f64_t multiplier_low = multiplier - (multiplier_high - (multiplier_high - multiplier));
|
|
82
|
+
multiplier_high = multiplier_high - (multiplier_high - multiplier);
|
|
83
|
+
// Exact multiplication error from the four cross-products
|
|
84
|
+
nk_f64_t product_error = ((multiplicand_high * multiplier_high - product) + multiplicand_high * multiplier_low +
|
|
85
|
+
multiplicand_low * multiplier_high) +
|
|
86
|
+
multiplicand_low * multiplier_low;
|
|
87
|
+
// Knuth TwoSum: add the addend with error tracking
|
|
88
|
+
nk_f64_t result = product + addend;
|
|
89
|
+
nk_f64_t addend_recovered = result - product;
|
|
90
|
+
nk_f64_t product_recovered = result - addend_recovered;
|
|
91
|
+
nk_f64_t addition_error = (product - product_recovered) + (addend - addend_recovered);
|
|
92
|
+
return result + (product_error + addition_error);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @brief Software FMA (Fused Multiply-Add) emulation for f32.
|
|
97
|
+
* Computes (multiplicand * multiplier + addend) with improved precision
|
|
98
|
+
* using Dekker's error-free multiplication and Knuth's TwoSum.
|
|
99
|
+
* @sa std::fma, @sa Rust f32::mul_add
|
|
100
|
+
*/
|
|
101
|
+
NK_PUBLIC nk_f32_t nk_f32_fma_serial(nk_f32_t multiplicand, nk_f32_t multiplier, nk_f32_t addend) {
|
|
102
|
+
nk_f32_t product = multiplicand * multiplier;
|
|
103
|
+
// Dekker splitting: break each operand into non-overlapping high and low halves
|
|
104
|
+
nk_f32_t const dekker_split = 4097.0f; // 2^12 + 1 for single precision
|
|
105
|
+
nk_f32_t multiplicand_high = dekker_split * multiplicand;
|
|
106
|
+
nk_f32_t multiplicand_low = multiplicand - (multiplicand_high - (multiplicand_high - multiplicand));
|
|
107
|
+
multiplicand_high = multiplicand_high - (multiplicand_high - multiplicand);
|
|
108
|
+
nk_f32_t multiplier_high = dekker_split * multiplier;
|
|
109
|
+
nk_f32_t multiplier_low = multiplier - (multiplier_high - (multiplier_high - multiplier));
|
|
110
|
+
multiplier_high = multiplier_high - (multiplier_high - multiplier);
|
|
111
|
+
// Exact multiplication error from the four cross-products
|
|
112
|
+
nk_f32_t product_error = ((multiplicand_high * multiplier_high - product) + multiplicand_high * multiplier_low +
|
|
113
|
+
multiplicand_low * multiplier_high) +
|
|
114
|
+
multiplicand_low * multiplier_low;
|
|
115
|
+
// Knuth TwoSum: add the addend with error tracking
|
|
116
|
+
nk_f32_t result = product + addend;
|
|
117
|
+
nk_f32_t addend_recovered = result - product;
|
|
118
|
+
nk_f32_t product_recovered = result - addend_recovered;
|
|
119
|
+
nk_f32_t addition_error = (product - product_recovered) + (addend - addend_recovered);
|
|
120
|
+
return result + (product_error + addition_error);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @brief Scalar Dot2 accumulator: sum += a * b with error compensation.
|
|
125
|
+
* Uses TwoProd (via FMA) and TwoSum error-free transformations.
|
|
126
|
+
* @see Ogita, T., Rump, S.M., Oishi, S. (2005). "Accurate Sum and Dot Product"
|
|
127
|
+
*/
|
|
128
|
+
NK_INTERNAL void nk_f64_dot2_(nk_f64_t *sum, nk_f64_t *compensation, nk_f64_t a, nk_f64_t b) NK_STREAMING_COMPATIBLE_ {
|
|
129
|
+
nk_f64_t product = a * b;
|
|
130
|
+
nk_f64_t product_error = nk_f64_fma_serial(a, b, -product);
|
|
131
|
+
nk_f64_t running_sum = *sum + product;
|
|
132
|
+
nk_f64_t recovered_addend = running_sum - *sum;
|
|
133
|
+
nk_f64_t sum_error = (*sum - (running_sum - recovered_addend)) + (product - recovered_addend);
|
|
134
|
+
*sum = running_sum;
|
|
135
|
+
*compensation += sum_error + product_error;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
NK_PUBLIC nk_f16_t nk_f16_fma_serial(nk_f16_t a, nk_f16_t b, nk_f16_t c) {
|
|
139
|
+
nk_f32_t a_f32, b_f32, c_f32;
|
|
140
|
+
nk_f16_to_f32_serial(&a, &a_f32);
|
|
141
|
+
nk_f16_to_f32_serial(&b, &b_f32);
|
|
142
|
+
nk_f16_to_f32_serial(&c, &c_f32);
|
|
143
|
+
nk_f32_t result_f32 = nk_f32_fma_serial(a_f32, b_f32, c_f32);
|
|
144
|
+
nk_f16_t result;
|
|
145
|
+
nk_f32_to_f16_serial(&result_f32, &result);
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
NK_PUBLIC nk_u8_t nk_u8_saturating_add_serial(nk_u8_t a, nk_u8_t b) {
|
|
150
|
+
nk_u16_t result = (nk_u16_t)a + (nk_u16_t)b;
|
|
151
|
+
return (result > 255u) ? (nk_u8_t)255u : (nk_u8_t)result;
|
|
152
|
+
}
|
|
153
|
+
NK_PUBLIC nk_u16_t nk_u16_saturating_add_serial(nk_u16_t a, nk_u16_t b) {
|
|
154
|
+
nk_u32_t result = (nk_u32_t)a + (nk_u32_t)b;
|
|
155
|
+
return (result > 65535u) ? (nk_u16_t)65535u : (nk_u16_t)result;
|
|
156
|
+
}
|
|
157
|
+
NK_PUBLIC nk_u32_t nk_u32_saturating_add_serial(nk_u32_t a, nk_u32_t b) {
|
|
158
|
+
nk_u64_t result = (nk_u64_t)a + (nk_u64_t)b;
|
|
159
|
+
return (result > 4294967295u) ? (nk_u32_t)4294967295u : (nk_u32_t)result;
|
|
160
|
+
}
|
|
161
|
+
NK_PUBLIC nk_u64_t nk_u64_saturating_add_serial(nk_u64_t a, nk_u64_t b) {
|
|
162
|
+
return (a + b < a) ? 18446744073709551615ull : (a + b);
|
|
163
|
+
}
|
|
164
|
+
NK_PUBLIC nk_i8_t nk_i8_saturating_add_serial(nk_i8_t a, nk_i8_t b) {
|
|
165
|
+
nk_i16_t result = (nk_i16_t)a + (nk_i16_t)b;
|
|
166
|
+
return (result > 127) ? 127 : (result < -128 ? -128 : result);
|
|
167
|
+
}
|
|
168
|
+
NK_PUBLIC nk_i16_t nk_i16_saturating_add_serial(nk_i16_t a, nk_i16_t b) {
|
|
169
|
+
nk_i32_t result = (nk_i32_t)a + (nk_i32_t)b;
|
|
170
|
+
return (result > 32767) ? 32767 : (result < -32768 ? -32768 : result);
|
|
171
|
+
}
|
|
172
|
+
NK_PUBLIC nk_i32_t nk_i32_saturating_add_serial(nk_i32_t a, nk_i32_t b) {
|
|
173
|
+
nk_i64_t result = (nk_i64_t)a + (nk_i64_t)b;
|
|
174
|
+
return (result > 2147483647ll) ? 2147483647ll : (result < -2147483648ll ? -2147483648ll : (nk_i32_t)result);
|
|
175
|
+
}
|
|
176
|
+
NK_PUBLIC nk_i64_t nk_i64_saturating_add_serial(nk_i64_t a, nk_i64_t b) {
|
|
177
|
+
//? We can't just write `-9223372036854775808ll`, even though it's the smallest signed 64-bit value.
|
|
178
|
+
//? The compiler will complain about the number being too large for the type, as it will process the
|
|
179
|
+
//? constant and the sign separately. So we use the same hint that compilers use to define the `INT64_MIN`.
|
|
180
|
+
if ((b > 0) && (a > (9223372036854775807ll) - b)) return 9223372036854775807ll;
|
|
181
|
+
if ((b < 0) && (a < (-9223372036854775807ll - 1ll) - b)) return -9223372036854775807ll - 1ll;
|
|
182
|
+
return a + b;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
NK_PUBLIC nk_u8_t nk_u8_saturating_mul_serial(nk_u8_t a, nk_u8_t b) {
|
|
186
|
+
nk_u16_t result = (nk_u16_t)a * (nk_u16_t)b;
|
|
187
|
+
return (result > 255) ? 255 : (nk_u8_t)result;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
NK_PUBLIC nk_u16_t nk_u16_saturating_mul_serial(nk_u16_t a, nk_u16_t b) {
|
|
191
|
+
nk_u32_t result = (nk_u32_t)a * (nk_u32_t)b;
|
|
192
|
+
return (result > 65535) ? 65535 : (nk_u16_t)result;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
NK_PUBLIC nk_u32_t nk_u32_saturating_mul_serial(nk_u32_t a, nk_u32_t b) {
|
|
196
|
+
nk_u64_t result = (nk_u64_t)a * (nk_u64_t)b;
|
|
197
|
+
return (result > 4294967295u) ? 4294967295u : (nk_u32_t)result;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
NK_PUBLIC nk_u64_t nk_u64_saturating_mul_serial(nk_u64_t a, nk_u64_t b) {
|
|
201
|
+
// Split the inputs into high and low 32-bit parts
|
|
202
|
+
nk_u64_t a_high = a >> 32;
|
|
203
|
+
nk_u64_t a_low = a & 0xFFFFFFFF;
|
|
204
|
+
nk_u64_t b_high = b >> 32;
|
|
205
|
+
nk_u64_t b_low = b & 0xFFFFFFFF;
|
|
206
|
+
|
|
207
|
+
// Compute partial products
|
|
208
|
+
nk_u64_t upper_product = a_high * b_high;
|
|
209
|
+
nk_u64_t cross_ab = a_high * b_low;
|
|
210
|
+
nk_u64_t cross_ba = a_low * b_high;
|
|
211
|
+
nk_u64_t lower_product = a_low * b_low;
|
|
212
|
+
|
|
213
|
+
// Check if the high part of the result overflows
|
|
214
|
+
nk_u64_t cross_sum = cross_ab + cross_ba;
|
|
215
|
+
if (upper_product || (cross_ab >> 32) || (cross_ba >> 32) || (cross_sum < cross_ab) || (cross_sum >> 32))
|
|
216
|
+
return 18446744073709551615ull;
|
|
217
|
+
nk_u64_t result = (cross_sum << 32) + lower_product;
|
|
218
|
+
if (result < lower_product) return 18446744073709551615ull;
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
NK_PUBLIC nk_i8_t nk_i8_saturating_mul_serial(nk_i8_t a, nk_i8_t b) {
|
|
223
|
+
nk_i16_t result = (nk_i16_t)a * (nk_i16_t)b;
|
|
224
|
+
return (result > 127) ? 127 : (result < -128 ? -128 : (nk_i8_t)result);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
NK_PUBLIC nk_i16_t nk_i16_saturating_mul_serial(nk_i16_t a, nk_i16_t b) {
|
|
228
|
+
nk_i32_t result = (nk_i32_t)a * (nk_i32_t)b;
|
|
229
|
+
return (result > 32767) ? 32767 : (result < -32768 ? -32768 : (nk_i16_t)result);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
NK_PUBLIC nk_i32_t nk_i32_saturating_mul_serial(nk_i32_t a, nk_i32_t b) {
|
|
233
|
+
nk_i64_t result = (nk_i64_t)a * (nk_i64_t)b;
|
|
234
|
+
return (result > 2147483647ll) ? 2147483647ll : (result < -2147483648ll ? -2147483648ll : (nk_i32_t)result);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
NK_PUBLIC nk_i64_t nk_i64_saturating_mul_serial(nk_i64_t a, nk_i64_t b) {
|
|
238
|
+
int sign = ((a < 0) ^ (b < 0)) ? -1 : 1; // Track the sign of the result
|
|
239
|
+
|
|
240
|
+
// Take absolute values for easy multiplication and overflow detection
|
|
241
|
+
nk_u64_t abs_a = (a < 0) ? (0u - (nk_u64_t)a) : (nk_u64_t)a;
|
|
242
|
+
nk_u64_t abs_b = (b < 0) ? (0u - (nk_u64_t)b) : (nk_u64_t)b;
|
|
243
|
+
|
|
244
|
+
// Split the absolute values into high and low 32-bit parts
|
|
245
|
+
nk_u64_t a_high = abs_a >> 32;
|
|
246
|
+
nk_u64_t a_low = abs_a & 0xFFFFFFFF;
|
|
247
|
+
nk_u64_t b_high = abs_b >> 32;
|
|
248
|
+
nk_u64_t b_low = abs_b & 0xFFFFFFFF;
|
|
249
|
+
|
|
250
|
+
// Compute partial products
|
|
251
|
+
nk_u64_t upper_product = a_high * b_high;
|
|
252
|
+
nk_u64_t cross_ab = a_high * b_low;
|
|
253
|
+
nk_u64_t cross_ba = a_low * b_high;
|
|
254
|
+
nk_u64_t lower_product = a_low * b_low;
|
|
255
|
+
|
|
256
|
+
// Check for overflow and saturate based on sign
|
|
257
|
+
nk_u64_t cross_sum = cross_ab + cross_ba;
|
|
258
|
+
if (upper_product || (cross_ab >> 32) || (cross_ba >> 32) || (cross_sum < cross_ab) || (cross_sum >> 32))
|
|
259
|
+
return (sign > 0) ? 9223372036854775807ll : (-9223372036854775807ll - 1ll);
|
|
260
|
+
// Combine parts if no overflow, then apply the sign
|
|
261
|
+
nk_u64_t result = (cross_sum << 32) + lower_product;
|
|
262
|
+
return (sign < 0) ? -((nk_i64_t)result) : (nk_i64_t)result;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
NK_PUBLIC nk_i4x2_t nk_i4x2_saturating_add_serial(nk_i4x2_t a, nk_i4x2_t b) {
|
|
266
|
+
nk_i8_t low = nk_i4x2_low_(a) + nk_i4x2_low_(b);
|
|
267
|
+
nk_i8_t high = nk_i4x2_high_(a) + nk_i4x2_high_(b);
|
|
268
|
+
low = (low > 7) ? 7 : (low < -8 ? -8 : low);
|
|
269
|
+
high = (high > 7) ? 7 : (high < -8 ? -8 : high);
|
|
270
|
+
return (nk_i4x2_t)((low & 0x0F) | ((high & 0x0F) << 4));
|
|
271
|
+
}
|
|
272
|
+
NK_PUBLIC nk_u4x2_t nk_u4x2_saturating_add_serial(nk_u4x2_t a, nk_u4x2_t b) {
|
|
273
|
+
nk_u8_t low = nk_u4x2_low_(a) + nk_u4x2_low_(b);
|
|
274
|
+
nk_u8_t high = nk_u4x2_high_(a) + nk_u4x2_high_(b);
|
|
275
|
+
low = (low > 15) ? 15 : low;
|
|
276
|
+
high = (high > 15) ? 15 : high;
|
|
277
|
+
return (nk_u4x2_t)((low & 0x0F) | ((high & 0x0F) << 4));
|
|
278
|
+
}
|
|
279
|
+
NK_PUBLIC nk_i4x2_t nk_i4x2_saturating_mul_serial(nk_i4x2_t a, nk_i4x2_t b) {
|
|
280
|
+
nk_i8_t low = nk_i4x2_low_(a) * nk_i4x2_low_(b);
|
|
281
|
+
nk_i8_t high = nk_i4x2_high_(a) * nk_i4x2_high_(b);
|
|
282
|
+
low = (low > 7) ? 7 : (low < -8 ? -8 : low);
|
|
283
|
+
high = (high > 7) ? 7 : (high < -8 ? -8 : high);
|
|
284
|
+
return (nk_i4x2_t)((low & 0x0F) | ((high & 0x0F) << 4));
|
|
285
|
+
}
|
|
286
|
+
NK_PUBLIC nk_u4x2_t nk_u4x2_saturating_mul_serial(nk_u4x2_t a, nk_u4x2_t b) {
|
|
287
|
+
nk_u8_t low = nk_u4x2_low_(a) * nk_u4x2_low_(b);
|
|
288
|
+
nk_u8_t high = nk_u4x2_high_(a) * nk_u4x2_high_(b);
|
|
289
|
+
low = (low > 15) ? 15 : low;
|
|
290
|
+
high = (high > 15) ? 15 : high;
|
|
291
|
+
return (nk_u4x2_t)((low & 0x0F) | ((high & 0x0F) << 4));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
NK_PUBLIC int nk_e4m3_order_serial(nk_e4m3_t a, nk_e4m3_t b) {
|
|
295
|
+
int sign_a = a >> 7, sign_b = b >> 7;
|
|
296
|
+
return (a ^ -sign_a) - (b ^ -sign_b);
|
|
297
|
+
}
|
|
298
|
+
NK_PUBLIC int nk_e5m2_order_serial(nk_e5m2_t a, nk_e5m2_t b) {
|
|
299
|
+
int sign_a = a >> 7, sign_b = b >> 7;
|
|
300
|
+
return (a ^ -sign_a) - (b ^ -sign_b);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
NK_PUBLIC int nk_e2m3_order_serial(nk_e2m3_t a, nk_e2m3_t b) {
|
|
304
|
+
int value_a = a & 0x3F, value_b = b & 0x3F;
|
|
305
|
+
int sign_a = value_a >> 5, sign_b = value_b >> 5;
|
|
306
|
+
return (value_a ^ -sign_a) - (value_b ^ -sign_b);
|
|
307
|
+
}
|
|
308
|
+
NK_PUBLIC int nk_e3m2_order_serial(nk_e3m2_t a, nk_e3m2_t b) {
|
|
309
|
+
int value_a = a & 0x3F, value_b = b & 0x3F;
|
|
310
|
+
int sign_a = value_a >> 5, sign_b = value_b >> 5;
|
|
311
|
+
return (value_a ^ -sign_a) - (value_b ^ -sign_b);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
NK_PUBLIC int nk_bf16_order_serial(nk_bf16_t a, nk_bf16_t b) {
|
|
315
|
+
nk_fui16_t a_fui, b_fui;
|
|
316
|
+
a_fui.bf = a, b_fui.bf = b;
|
|
317
|
+
int sign_a = a_fui.u >> 15, sign_b = b_fui.u >> 15;
|
|
318
|
+
return ((int)a_fui.u ^ -sign_a) - ((int)b_fui.u ^ -sign_b);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
NK_PUBLIC int nk_f16_order_serial(nk_f16_t a, nk_f16_t b) {
|
|
322
|
+
nk_fui16_t a_fui, b_fui;
|
|
323
|
+
a_fui.f = a, b_fui.f = b;
|
|
324
|
+
int sign_a = a_fui.u >> 15, sign_b = b_fui.u >> 15;
|
|
325
|
+
return ((int)a_fui.u ^ -sign_a) - ((int)b_fui.u ^ -sign_b);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
#if defined(__cplusplus)
|
|
329
|
+
} // extern "C"
|
|
330
|
+
#endif
|
|
331
|
+
|
|
332
|
+
#endif // NK_SCALAR_SERIAL_H
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Scalar Math Helpers for WASM.
|
|
3
|
+
* @file include/numkong/scalar/v128relaxed.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date March 1, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/scalar.h
|
|
8
|
+
*/
|
|
9
|
+
#ifndef NK_SCALAR_V128RELAXED_H
|
|
10
|
+
#define NK_SCALAR_V128RELAXED_H
|
|
11
|
+
|
|
12
|
+
#if NK_TARGET_V128RELAXED
|
|
13
|
+
|
|
14
|
+
#include "numkong/types.h"
|
|
15
|
+
|
|
16
|
+
#if defined(__cplusplus)
|
|
17
|
+
extern "C" {
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
#if defined(__clang__)
|
|
21
|
+
#pragma clang attribute push(__attribute__((target("relaxed-simd"))), apply_to = function)
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
NK_PUBLIC nk_f32_t nk_f32_sqrt_v128relaxed(nk_f32_t x) {
|
|
25
|
+
return wasm_f32x4_extract_lane(wasm_f32x4_sqrt(wasm_f32x4_splat(x)), 0);
|
|
26
|
+
}
|
|
27
|
+
NK_PUBLIC nk_f64_t nk_f64_sqrt_v128relaxed(nk_f64_t x) {
|
|
28
|
+
return wasm_f64x2_extract_lane(wasm_f64x2_sqrt(wasm_f64x2_splat(x)), 0);
|
|
29
|
+
}
|
|
30
|
+
NK_PUBLIC nk_f32_t nk_f32_rsqrt_v128relaxed(nk_f32_t x) {
|
|
31
|
+
v128_t sqrt_f32x4 = wasm_f32x4_sqrt(wasm_f32x4_splat(x));
|
|
32
|
+
return wasm_f32x4_extract_lane(wasm_f32x4_div(wasm_f32x4_splat(1.0f), sqrt_f32x4), 0);
|
|
33
|
+
}
|
|
34
|
+
NK_PUBLIC nk_f64_t nk_f64_rsqrt_v128relaxed(nk_f64_t x) {
|
|
35
|
+
v128_t sqrt_f64x2 = wasm_f64x2_sqrt(wasm_f64x2_splat(x));
|
|
36
|
+
return wasm_f64x2_extract_lane(wasm_f64x2_div(wasm_f64x2_splat(1.0), sqrt_f64x2), 0);
|
|
37
|
+
}
|
|
38
|
+
NK_PUBLIC nk_f32_t nk_f32_fma_v128relaxed(nk_f32_t a, nk_f32_t b, nk_f32_t c) {
|
|
39
|
+
v128_t result_f32x4 = wasm_f32x4_relaxed_madd(wasm_f32x4_splat(a), wasm_f32x4_splat(b), wasm_f32x4_splat(c));
|
|
40
|
+
return wasm_f32x4_extract_lane(result_f32x4, 0);
|
|
41
|
+
}
|
|
42
|
+
NK_PUBLIC nk_f64_t nk_f64_fma_v128relaxed(nk_f64_t a, nk_f64_t b, nk_f64_t c) {
|
|
43
|
+
v128_t result_f64x2 = wasm_f64x2_relaxed_madd(wasm_f64x2_splat(a), wasm_f64x2_splat(b), wasm_f64x2_splat(c));
|
|
44
|
+
return wasm_f64x2_extract_lane(result_f64x2, 0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#if defined(__clang__)
|
|
48
|
+
#pragma clang attribute pop
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
#if defined(__cplusplus)
|
|
52
|
+
} // extern "C"
|
|
53
|
+
#endif
|
|
54
|
+
|
|
55
|
+
#endif // NK_TARGET_V128RELAXED
|
|
56
|
+
#endif // NK_SCALAR_V128RELAXED_H
|