usearch 2.21.4 → 2.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -69
- package/binding.gyp +15 -37
- package/c/CMakeLists.txt +4 -5
- package/c/README.md +8 -8
- package/c/lib.cpp +32 -14
- package/c/test.c +124 -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 +224 -48
- package/include/usearch/index_dense.hpp +105 -40
- package/include/usearch/index_plugins.hpp +1387 -204
- package/javascript/README.md +1 -1
- 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.test.js +117 -94
- 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,504 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SVE2-accelerated Sparse Vector Operations.
|
|
3
|
+
* @file include/numkong/sparse/sve2.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date February 6, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/sparse.h
|
|
8
|
+
*/
|
|
9
|
+
#ifndef NK_SPARSE_SVE2_H
|
|
10
|
+
#define NK_SPARSE_SVE2_H
|
|
11
|
+
|
|
12
|
+
#if NK_TARGET_ARM64_
|
|
13
|
+
|
|
14
|
+
#include "numkong/types.h"
|
|
15
|
+
#include "numkong/reduce/sve.h" // `nk_svaddv_f64_`
|
|
16
|
+
|
|
17
|
+
#if defined(__cplusplus)
|
|
18
|
+
extern "C" {
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
/* SVE2 introduces many new integer-oriented instructions, extending some of the NEON functionality
|
|
22
|
+
* to variable-length SVE registers. Those include "compare multiple" intrinsics:
|
|
23
|
+
*
|
|
24
|
+
* - `svmatch[_u16]` that matches each scalar in first vector against all members of a 128-bit lane in the second.
|
|
25
|
+
* - `svhistcnt[_s32]_z` does something similar, performing an inclusive prefix scan.
|
|
26
|
+
* - `svtbx[_u16]` does extended table lookup
|
|
27
|
+
*
|
|
28
|
+
* Other notable instructions:
|
|
29
|
+
*
|
|
30
|
+
* - `DUP`: Broadcast indexed predicate element
|
|
31
|
+
* https://developer.arm.com/documentation/ddi0602/2021-06/SVE-Instructions/DUP--predicate---Broadcast-indexed-predicate-element-?lang=en
|
|
32
|
+
* - `SCLAMP` and `UCLAMP`: clamp values, i.e. combined min+max
|
|
33
|
+
* https://developer.arm.com/documentation/ddi0602/2021-06/SVE-Instructions/SCLAMP--Signed-clamp-to-minimum-maximum-vector-?lang=en
|
|
34
|
+
* https://developer.arm.com/documentation/ddi0602/2021-06/SVE-Instructions/UCLAMP--Unsigned-clamp-to-minimum-maximum-vector-?lang=en
|
|
35
|
+
* - `TBLQ`: Table lookup quadword
|
|
36
|
+
* https://developer.arm.com/documentation/ddi0602/2022-12/SVE-Instructions/TBLQ--Programmable-table-lookup-within-each-quadword-vector-segment--zeroing--?lang=en
|
|
37
|
+
*
|
|
38
|
+
* Great resources for SVE2 intrinsics:
|
|
39
|
+
*
|
|
40
|
+
* > ARM's Scalable Vector Extensions: A Critical Look at SVE2 For Integer Workloads
|
|
41
|
+
* https://gist.github.com/zingaburga/805669eb891c820bd220418ee3f0d6bd
|
|
42
|
+
*/
|
|
43
|
+
#if NK_TARGET_SVE2
|
|
44
|
+
#if defined(__clang__)
|
|
45
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8.2-a+sve+sve2"))), apply_to = function)
|
|
46
|
+
#elif defined(__GNUC__)
|
|
47
|
+
#pragma GCC push_options
|
|
48
|
+
#pragma GCC target("arch=armv8.2-a+sve+sve2")
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
NK_PUBLIC void nk_sparse_intersect_u16_sve2( //
|
|
52
|
+
nk_u16_t const *a, nk_u16_t const *b, //
|
|
53
|
+
nk_size_t a_length, nk_size_t b_length, //
|
|
54
|
+
nk_u16_t *result, nk_size_t *count) {
|
|
55
|
+
|
|
56
|
+
// A single SVE lane is 128 bits wide, so one lane fits 8 values.
|
|
57
|
+
nk_size_t const register_size = svcnth();
|
|
58
|
+
nk_size_t const lanes_count = register_size / 8;
|
|
59
|
+
nk_size_t a_idx = 0, b_idx = 0;
|
|
60
|
+
nk_size_t c = 0;
|
|
61
|
+
|
|
62
|
+
while (a_idx < a_length && b_idx < b_length) {
|
|
63
|
+
// Load `a_member` and broadcast it, load `b_members_vec` from memory
|
|
64
|
+
svbool_t a_progress_b16x = svwhilelt_b16_u64(a_idx, a_length);
|
|
65
|
+
svbool_t b_progress_b16x = svwhilelt_b16_u64(b_idx, b_length);
|
|
66
|
+
svuint16_t a_u16x = svld1_u16(a_progress_b16x, a + a_idx);
|
|
67
|
+
svuint16_t b_u16x = svld1_u16(b_progress_b16x, b + b_idx);
|
|
68
|
+
|
|
69
|
+
// Intersecting registers with `svmatch_u16` involves a lot of shuffling
|
|
70
|
+
// and comparisons, so we want to avoid it if the slices don't overlap at all..
|
|
71
|
+
nk_u16_t a_min;
|
|
72
|
+
nk_u16_t a_max = svlastb(a_progress_b16x, a_u16x);
|
|
73
|
+
nk_u16_t b_min = svlasta(svpfalse_b(), b_u16x);
|
|
74
|
+
nk_u16_t b_max = svlastb(b_progress_b16x, b_u16x);
|
|
75
|
+
|
|
76
|
+
// If the slices don't overlap, advance the appropriate pointer
|
|
77
|
+
while (a_max < b_min && (a_idx + register_size) <= a_length) {
|
|
78
|
+
a_idx += register_size;
|
|
79
|
+
a_progress_b16x = svwhilelt_b16_u64(a_idx, a_length);
|
|
80
|
+
a_u16x = svld1_u16(a_progress_b16x, a + a_idx);
|
|
81
|
+
a_max = svlastb(a_progress_b16x, a_u16x);
|
|
82
|
+
}
|
|
83
|
+
a_min = svlasta(svpfalse_b(), a_u16x);
|
|
84
|
+
while (b_max < a_min && (b_idx + register_size) <= b_length) {
|
|
85
|
+
b_idx += register_size;
|
|
86
|
+
b_progress_b16x = svwhilelt_b16_u64(b_idx, b_length);
|
|
87
|
+
b_u16x = svld1_u16(b_progress_b16x, b + b_idx);
|
|
88
|
+
b_max = svlastb(b_progress_b16x, b_u16x);
|
|
89
|
+
}
|
|
90
|
+
b_min = svlasta(svpfalse_b(), b_u16x);
|
|
91
|
+
|
|
92
|
+
// Before we evaluate the intersection size, obfurscating the order in `b_u16x`,
|
|
93
|
+
// let's estimate how much we will need to advance the pointers afterwards.
|
|
94
|
+
// For that, we don't even need to broadcast the values in SVE, as the whole
|
|
95
|
+
// register can be compared against a scalar:
|
|
96
|
+
//
|
|
97
|
+
// svuint16_t a_last_broadcasted = svdup_n_u16(a_max);
|
|
98
|
+
// svuint16_t b_last_broadcasted = svdup_n_u16(b_max);
|
|
99
|
+
svbool_t a_mask_b16x = svcmple_n_u16(a_progress_b16x, a_u16x, b_max);
|
|
100
|
+
svbool_t b_mask_b16x = svcmple_n_u16(b_progress_b16x, b_u16x, a_max);
|
|
101
|
+
nk_u64_t a_step = svcntp_b16(a_progress_b16x, a_mask_b16x);
|
|
102
|
+
nk_u64_t b_step = svcntp_b16(b_progress_b16x, b_mask_b16x);
|
|
103
|
+
|
|
104
|
+
// Compare `a_u16x` with each lane of `b_u16x`
|
|
105
|
+
svbool_t equal_mask_b16x = svmatch_u16(a_progress_b16x, a_u16x, b_u16x);
|
|
106
|
+
for (nk_size_t i = 1; i < lanes_count; i++) {
|
|
107
|
+
b_u16x = svext_u16(b_u16x, b_u16x, 8);
|
|
108
|
+
equal_mask_b16x = svorr_z(svptrue_b16(), equal_mask_b16x, svmatch_u16(a_progress_b16x, a_u16x, b_u16x));
|
|
109
|
+
}
|
|
110
|
+
nk_size_t equal_count = svcntp_b16(svptrue_b16(), equal_mask_b16x);
|
|
111
|
+
|
|
112
|
+
// Manually compact and store matching elements (svcompact_u16 is not defined)
|
|
113
|
+
if (result) {
|
|
114
|
+
nk_u16_t a_data[16];
|
|
115
|
+
nk_u16_t mask_data[16];
|
|
116
|
+
|
|
117
|
+
svst1_u16(svptrue_b16(), a_data, a_u16x);
|
|
118
|
+
svst1_u16(svptrue_b16(), mask_data, svdup_n_u16_z(equal_mask_b16x, 1));
|
|
119
|
+
|
|
120
|
+
for (nk_size_t i = 0; i < svcnth(); i++)
|
|
121
|
+
if (mask_data[i]) result[c++] = a_data[i];
|
|
122
|
+
c -= equal_count;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Advance
|
|
126
|
+
a_idx += a_step;
|
|
127
|
+
b_idx += b_step;
|
|
128
|
+
c += equal_count;
|
|
129
|
+
}
|
|
130
|
+
*count = c;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
NK_PUBLIC void nk_sparse_intersect_u32_sve2( //
|
|
134
|
+
nk_u32_t const *a, nk_u32_t const *b, //
|
|
135
|
+
nk_size_t a_length, nk_size_t b_length, //
|
|
136
|
+
nk_u32_t *result, nk_size_t *count) {
|
|
137
|
+
|
|
138
|
+
// A single SVE lane is 128 bits wide, so one lane fits 4 values.
|
|
139
|
+
nk_size_t const register_size = svcntw();
|
|
140
|
+
nk_size_t const lanes_count = register_size / 4;
|
|
141
|
+
nk_size_t a_idx = 0, b_idx = 0;
|
|
142
|
+
nk_size_t c = 0;
|
|
143
|
+
|
|
144
|
+
while (a_idx < a_length && b_idx < b_length) {
|
|
145
|
+
// Load `a_member` and broadcast it, load `b_members_vec` from memory
|
|
146
|
+
svbool_t a_progress_b32x = svwhilelt_b32_u64(a_idx, a_length);
|
|
147
|
+
svbool_t b_progress_b32x = svwhilelt_b32_u64(b_idx, b_length);
|
|
148
|
+
svuint32_t a_u32x = svld1_u32(a_progress_b32x, a + a_idx);
|
|
149
|
+
svuint32_t b_u32x = svld1_u32(b_progress_b32x, b + b_idx);
|
|
150
|
+
|
|
151
|
+
// Intersecting registers with `svmatch_u16` involves a lot of shuffling
|
|
152
|
+
// and comparisons, so we want to avoid it if the slices don't overlap at all..
|
|
153
|
+
nk_u32_t a_min;
|
|
154
|
+
nk_u32_t a_max = svlastb(a_progress_b32x, a_u32x);
|
|
155
|
+
nk_u32_t b_min = svlasta(svpfalse_b(), b_u32x);
|
|
156
|
+
nk_u32_t b_max = svlastb(b_progress_b32x, b_u32x);
|
|
157
|
+
|
|
158
|
+
// If the slices don't overlap, advance the appropriate pointer
|
|
159
|
+
while (a_max < b_min && (a_idx + register_size) <= a_length) {
|
|
160
|
+
a_idx += register_size;
|
|
161
|
+
a_progress_b32x = svwhilelt_b32_u64(a_idx, a_length);
|
|
162
|
+
a_u32x = svld1_u32(a_progress_b32x, a + a_idx);
|
|
163
|
+
a_max = svlastb(a_progress_b32x, a_u32x);
|
|
164
|
+
}
|
|
165
|
+
a_min = svlasta(svpfalse_b(), a_u32x);
|
|
166
|
+
while (b_max < a_min && (b_idx + register_size) <= b_length) {
|
|
167
|
+
b_idx += register_size;
|
|
168
|
+
b_progress_b32x = svwhilelt_b32_u64(b_idx, b_length);
|
|
169
|
+
b_u32x = svld1_u32(b_progress_b32x, b + b_idx);
|
|
170
|
+
b_max = svlastb(b_progress_b32x, b_u32x);
|
|
171
|
+
}
|
|
172
|
+
b_min = svlasta(svpfalse_b(), b_u32x);
|
|
173
|
+
|
|
174
|
+
// Before we evaluate the intersection size, obfurscating the order in `b_u32x`,
|
|
175
|
+
// let's estimate how much we will need to advance the pointers afterwards.
|
|
176
|
+
// For that, we don't even need to broadcast the values in SVE, as the whole
|
|
177
|
+
// register can be compared against a scalar:
|
|
178
|
+
//
|
|
179
|
+
// svuint32_t a_last_broadcasted = svdup_n_u32(a_max);
|
|
180
|
+
// svuint32_t b_last_broadcasted = svdup_n_u32(b_max);
|
|
181
|
+
svbool_t a_mask_b32x = svcmple_n_u32(a_progress_b32x, a_u32x, b_max);
|
|
182
|
+
svbool_t b_mask_b32x = svcmple_n_u32(b_progress_b32x, b_u32x, a_max);
|
|
183
|
+
nk_u64_t a_step = svcntp_b32(a_progress_b32x, a_mask_b32x);
|
|
184
|
+
nk_u64_t b_step = svcntp_b32(b_progress_b32x, b_mask_b32x);
|
|
185
|
+
|
|
186
|
+
// Comparing `a_u32x` with each lane of `b_u32x` can't be done with `svmatch`,
|
|
187
|
+
// the same way as in `nk_sparse_intersect_u16_sve2`, as that instruction is only
|
|
188
|
+
// available for 8-bit and 16-bit integers.
|
|
189
|
+
//
|
|
190
|
+
// svbool_t equal_mask_b32x = svpfalse_b();
|
|
191
|
+
// for (nk_size_t i = 0; i < register_size; i++) {
|
|
192
|
+
// equal_mask_b32x = svorr_z(svptrue_b32(), equal_mask_b32x, svcmpeq_u32(a_progress, a_u32x, b_u32x));
|
|
193
|
+
// b_u32x = svext_u32(b_u32x, b_u32x, 1);
|
|
194
|
+
// }
|
|
195
|
+
// nk_size_t equal_count = svcntp_b32(a_progress, equal_mask_b32x);
|
|
196
|
+
//
|
|
197
|
+
// Alternatively, one can use histogram instructions, like `svhistcnt_u32_z`.
|
|
198
|
+
// They practically compute the prefix-matching count, which is equivalent to
|
|
199
|
+
// the lower triangle of the row-major intersection matrix.
|
|
200
|
+
// To compute the upper triangle, we can reverse (with `svrev_b32`) the order of
|
|
201
|
+
// elements and repeat the operation, accumulating the results for top and bottom.
|
|
202
|
+
// Let's look at 4x element registers as an example:
|
|
203
|
+
//
|
|
204
|
+
// ⊐ α = {A, B, C, D}, β = {X, Y, Z, W}:
|
|
205
|
+
//
|
|
206
|
+
// hist(α, β): hist(α_rev, β_rev):
|
|
207
|
+
//
|
|
208
|
+
// X Y Z W W Z Y X
|
|
209
|
+
// A 1 0 0 0 D 1 0 0 0
|
|
210
|
+
// B 1 1 0 0 C 1 1 0 0
|
|
211
|
+
// C 1 1 1 0 B 1 1 1 0
|
|
212
|
+
// D 1 1 1 1 A 1 1 1 1
|
|
213
|
+
//
|
|
214
|
+
svuint32_t hist_low_u32x = svhistcnt_u32_z(a_progress_b32x, a_u32x, b_u32x);
|
|
215
|
+
svuint32_t a_rev_u32x = svrev_u32(a_u32x);
|
|
216
|
+
svuint32_t b_rev_u32x = svrev_u32(b_u32x);
|
|
217
|
+
svuint32_t hist_high_u32x = svrev_u32(svhistcnt_u32_z(svptrue_b32(), a_rev_u32x, b_rev_u32x));
|
|
218
|
+
svuint32_t hist_u32x = svorr_u32_x(a_progress_b32x, hist_low_u32x, hist_high_u32x);
|
|
219
|
+
svbool_t equal_mask_b32x = svcmpne_n_u32(a_progress_b32x, hist_u32x, 0);
|
|
220
|
+
nk_size_t equal_count = svcntp_b32(a_progress_b32x, equal_mask_b32x);
|
|
221
|
+
|
|
222
|
+
// Use SVE2 svcompact to compress matching elements and store to result buffer
|
|
223
|
+
if (result) {
|
|
224
|
+
svuint32_t compacted_u32x = svcompact_u32(equal_mask_b32x, a_u32x);
|
|
225
|
+
svbool_t store_predicate_b32x = svwhilelt_b32_u64(0u, equal_count);
|
|
226
|
+
svst1_u32(store_predicate_b32x, result + c, compacted_u32x);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Advance
|
|
230
|
+
a_idx += a_step;
|
|
231
|
+
b_idx += b_step;
|
|
232
|
+
c += equal_count;
|
|
233
|
+
}
|
|
234
|
+
*count = c;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
NK_PUBLIC void nk_sparse_intersect_u64_sve2( //
|
|
238
|
+
nk_u64_t const *a, nk_u64_t const *b, //
|
|
239
|
+
nk_size_t a_length, nk_size_t b_length, //
|
|
240
|
+
nk_u64_t *result, nk_size_t *count) {
|
|
241
|
+
|
|
242
|
+
// A single SVE lane is 128 bits wide, so one lane fits 2 values.
|
|
243
|
+
nk_size_t const register_size = svcntd();
|
|
244
|
+
nk_size_t const lanes_count = register_size / 2;
|
|
245
|
+
nk_size_t a_idx = 0, b_idx = 0;
|
|
246
|
+
nk_size_t c = 0;
|
|
247
|
+
|
|
248
|
+
while (a_idx < a_length && b_idx < b_length) {
|
|
249
|
+
// Load `a_member` and broadcast it, load `b_members_vec` from memory
|
|
250
|
+
svbool_t a_progress_b64x = svwhilelt_b64_u64(a_idx, a_length);
|
|
251
|
+
svbool_t b_progress_b64x = svwhilelt_b64_u64(b_idx, b_length);
|
|
252
|
+
svuint64_t a_u64x = svld1_u64(a_progress_b64x, a + a_idx);
|
|
253
|
+
svuint64_t b_u64x = svld1_u64(b_progress_b64x, b + b_idx);
|
|
254
|
+
|
|
255
|
+
// Intersecting registers involves comparisons,
|
|
256
|
+
// so we want to avoid it if the slices don't overlap at all.
|
|
257
|
+
nk_u64_t a_min;
|
|
258
|
+
nk_u64_t a_max = svlastb(a_progress_b64x, a_u64x);
|
|
259
|
+
nk_u64_t b_min = svlasta(svpfalse_b(), b_u64x);
|
|
260
|
+
nk_u64_t b_max = svlastb(b_progress_b64x, b_u64x);
|
|
261
|
+
|
|
262
|
+
// If the slices don't overlap, advance the appropriate pointer
|
|
263
|
+
while (a_max < b_min && (a_idx + register_size) <= a_length) {
|
|
264
|
+
a_idx += register_size;
|
|
265
|
+
a_progress_b64x = svwhilelt_b64_u64(a_idx, a_length);
|
|
266
|
+
a_u64x = svld1_u64(a_progress_b64x, a + a_idx);
|
|
267
|
+
a_max = svlastb(a_progress_b64x, a_u64x);
|
|
268
|
+
}
|
|
269
|
+
a_min = svlasta(svpfalse_b(), a_u64x);
|
|
270
|
+
while (b_max < a_min && (b_idx + register_size) <= b_length) {
|
|
271
|
+
b_idx += register_size;
|
|
272
|
+
b_progress_b64x = svwhilelt_b64_u64(b_idx, b_length);
|
|
273
|
+
b_u64x = svld1_u64(b_progress_b64x, b + b_idx);
|
|
274
|
+
b_max = svlastb(b_progress_b64x, b_u64x);
|
|
275
|
+
}
|
|
276
|
+
b_min = svlasta(svpfalse_b(), b_u64x);
|
|
277
|
+
|
|
278
|
+
// Estimate how much we will need to advance the pointers afterwards.
|
|
279
|
+
svbool_t a_mask_b64x = svcmple_n_u64(a_progress_b64x, a_u64x, b_max);
|
|
280
|
+
svbool_t b_mask_b64x = svcmple_n_u64(b_progress_b64x, b_u64x, a_max);
|
|
281
|
+
nk_u64_t a_step = svcntp_b64(a_progress_b64x, a_mask_b64x);
|
|
282
|
+
nk_u64_t b_step = svcntp_b64(b_progress_b64x, b_mask_b64x);
|
|
283
|
+
|
|
284
|
+
// Use histogram instructions like `svhistcnt_u64_z` to compute intersection.
|
|
285
|
+
// They compute the prefix-matching count, equivalent to the lower triangle
|
|
286
|
+
// of the row-major intersection matrix.
|
|
287
|
+
svuint64_t hist_low_u64x = svhistcnt_u64_z(a_progress_b64x, a_u64x, b_u64x);
|
|
288
|
+
svuint64_t a_rev_u64x = svrev_u64(a_u64x);
|
|
289
|
+
svuint64_t b_rev_u64x = svrev_u64(b_u64x);
|
|
290
|
+
svuint64_t hist_high_u64x = svrev_u64(svhistcnt_u64_z(svptrue_b64(), a_rev_u64x, b_rev_u64x));
|
|
291
|
+
svuint64_t hist_u64x = svorr_u64_x(a_progress_b64x, hist_low_u64x, hist_high_u64x);
|
|
292
|
+
svbool_t equal_mask_b64x = svcmpne_n_u64(a_progress_b64x, hist_u64x, 0);
|
|
293
|
+
nk_size_t equal_count = svcntp_b64(a_progress_b64x, equal_mask_b64x);
|
|
294
|
+
|
|
295
|
+
// Use SVE2 svcompact to compress matching elements and store to result buffer
|
|
296
|
+
if (result) {
|
|
297
|
+
svuint64_t compacted_u64x = svcompact_u64(equal_mask_b64x, a_u64x);
|
|
298
|
+
svbool_t store_predicate_b64x = svwhilelt_b64_u64(0u, equal_count);
|
|
299
|
+
svst1_u64(store_predicate_b64x, result + c, compacted_u64x);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Advance
|
|
303
|
+
a_idx += a_step;
|
|
304
|
+
b_idx += b_step;
|
|
305
|
+
c += equal_count;
|
|
306
|
+
}
|
|
307
|
+
*count = c;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
NK_PUBLIC void nk_sparse_dot_u32f32_sve2( //
|
|
311
|
+
nk_u32_t const *a, nk_u32_t const *b, //
|
|
312
|
+
nk_f32_t const *a_weights, nk_f32_t const *b_weights, //
|
|
313
|
+
nk_size_t a_length, nk_size_t b_length, //
|
|
314
|
+
nk_f64_t *product) {
|
|
315
|
+
|
|
316
|
+
nk_size_t const register_size = svcntw();
|
|
317
|
+
nk_size_t const vector_length_f64 = svcntd();
|
|
318
|
+
nk_size_t a_idx = 0, b_idx = 0;
|
|
319
|
+
svbool_t const predicate_all_b32x = svptrue_b32();
|
|
320
|
+
svbool_t const predicate_all_b64x = svptrue_b64();
|
|
321
|
+
svfloat64_t product_f64x = svdup_f64(0.0);
|
|
322
|
+
|
|
323
|
+
while (a_idx < a_length && b_idx < b_length) {
|
|
324
|
+
// Load indices with progress predicates
|
|
325
|
+
svbool_t a_progress_b32x = svwhilelt_b32_u64(a_idx, a_length);
|
|
326
|
+
svbool_t b_progress_b32x = svwhilelt_b32_u64(b_idx, b_length);
|
|
327
|
+
svuint32_t a_u32x = svld1_u32(a_progress_b32x, a + a_idx);
|
|
328
|
+
svuint32_t b_u32x = svld1_u32(b_progress_b32x, b + b_idx);
|
|
329
|
+
|
|
330
|
+
// Avoid expensive intersection if slices don't overlap at all
|
|
331
|
+
nk_u32_t a_min;
|
|
332
|
+
nk_u32_t a_max = svlastb(a_progress_b32x, a_u32x);
|
|
333
|
+
nk_u32_t b_min = svlasta(svpfalse_b(), b_u32x);
|
|
334
|
+
nk_u32_t b_max = svlastb(b_progress_b32x, b_u32x);
|
|
335
|
+
|
|
336
|
+
// If the slices don't overlap, advance the appropriate pointer
|
|
337
|
+
while (a_max < b_min && (a_idx + register_size) <= a_length) {
|
|
338
|
+
a_idx += register_size;
|
|
339
|
+
a_progress_b32x = svwhilelt_b32_u64(a_idx, a_length);
|
|
340
|
+
a_u32x = svld1_u32(a_progress_b32x, a + a_idx);
|
|
341
|
+
a_max = svlastb(a_progress_b32x, a_u32x);
|
|
342
|
+
}
|
|
343
|
+
a_min = svlasta(svpfalse_b(), a_u32x);
|
|
344
|
+
while (b_max < a_min && (b_idx + register_size) <= b_length) {
|
|
345
|
+
b_idx += register_size;
|
|
346
|
+
b_progress_b32x = svwhilelt_b32_u64(b_idx, b_length);
|
|
347
|
+
b_u32x = svld1_u32(b_progress_b32x, b + b_idx);
|
|
348
|
+
b_max = svlastb(b_progress_b32x, b_u32x);
|
|
349
|
+
}
|
|
350
|
+
b_min = svlasta(svpfalse_b(), b_u32x);
|
|
351
|
+
|
|
352
|
+
// Calculate step sizes before modifying vectors
|
|
353
|
+
svbool_t a_mask_b32x = svcmple_n_u32(a_progress_b32x, a_u32x, b_max);
|
|
354
|
+
svbool_t b_mask_b32x = svcmple_n_u32(b_progress_b32x, b_u32x, a_max);
|
|
355
|
+
nk_u64_t a_step = svcntp_b32(a_progress_b32x, a_mask_b32x);
|
|
356
|
+
nk_u64_t b_step = svcntp_b32(b_progress_b32x, b_mask_b32x);
|
|
357
|
+
|
|
358
|
+
// Use histogram-based intersection (svmatch_u32 doesn't exist)
|
|
359
|
+
svuint32_t hist_low_u32x = svhistcnt_u32_z(a_progress_b32x, a_u32x, b_u32x);
|
|
360
|
+
svuint32_t a_rev_u32x = svrev_u32(a_u32x);
|
|
361
|
+
svuint32_t b_rev_u32x = svrev_u32(b_u32x);
|
|
362
|
+
svuint32_t hist_high_u32x = svrev_u32(svhistcnt_u32_z(predicate_all_b32x, a_rev_u32x, b_rev_u32x));
|
|
363
|
+
svuint32_t hist_u32x = svorr_u32_x(a_progress_b32x, hist_low_u32x, hist_high_u32x);
|
|
364
|
+
svbool_t a_equal_mask_b32x = svcmpne_n_u32(a_progress_b32x, hist_u32x, 0);
|
|
365
|
+
svbool_t a_overlap_mask_b32x = svand_b_z(predicate_all_b32x, a_progress_b32x, a_equal_mask_b32x);
|
|
366
|
+
|
|
367
|
+
if (!svptest_any(a_progress_b32x, a_overlap_mask_b32x)) {
|
|
368
|
+
a_idx += a_step;
|
|
369
|
+
b_idx += b_step;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Compute b overlap mask (symmetric histogram: which b elements match something in a)
|
|
374
|
+
svuint32_t b_hist_low_u32x = svhistcnt_u32_z(b_progress_b32x, b_u32x, a_u32x);
|
|
375
|
+
svuint32_t b_hist_high_u32x = svrev_u32(svhistcnt_u32_z(predicate_all_b32x, b_rev_u32x, a_rev_u32x));
|
|
376
|
+
svuint32_t b_hist_u32x = svorr_u32_x(b_progress_b32x, b_hist_low_u32x, b_hist_high_u32x);
|
|
377
|
+
svbool_t b_overlap_mask_b32x = svand_b_z(predicate_all_b32x, b_progress_b32x,
|
|
378
|
+
svcmpne_n_u32(b_progress_b32x, b_hist_u32x, 0));
|
|
379
|
+
|
|
380
|
+
// Compact matching weights — both arrays are sorted, so svcompact
|
|
381
|
+
// preserves relative order and aligns corresponding intersection pairs.
|
|
382
|
+
svfloat32_t a_matched_f32x = svcompact_f32(a_overlap_mask_b32x, svld1_f32(a_progress_b32x, a_weights + a_idx));
|
|
383
|
+
svfloat32_t b_matched_f32x = svcompact_f32(b_overlap_mask_b32x, svld1_f32(b_progress_b32x, b_weights + b_idx));
|
|
384
|
+
|
|
385
|
+
// Widen to f64 and accumulate. svcvt_f64_f32 converts even-indexed f32
|
|
386
|
+
// elements; svcvtlt_f64_f32 converts odd-indexed f32 elements.
|
|
387
|
+
nk_size_t match_count = svcntp_b32(a_progress_b32x, a_overlap_mask_b32x);
|
|
388
|
+
svbool_t pred_even_b64x = svwhilelt_b64_u64(0u, (match_count + 1) / 2);
|
|
389
|
+
svbool_t pred_odd_b64x = svwhilelt_b64_u64(0u, match_count / 2);
|
|
390
|
+
product_f64x = svmla_f64_x(pred_even_b64x, product_f64x, svcvt_f64_f32_x(pred_even_b64x, a_matched_f32x),
|
|
391
|
+
svcvt_f64_f32_x(pred_even_b64x, b_matched_f32x));
|
|
392
|
+
product_f64x = svmla_f64_x(pred_odd_b64x, product_f64x, svcvtlt_f64_f32_x(pred_odd_b64x, a_matched_f32x),
|
|
393
|
+
svcvtlt_f64_f32_x(pred_odd_b64x, b_matched_f32x));
|
|
394
|
+
|
|
395
|
+
// Advance
|
|
396
|
+
a_idx += a_step;
|
|
397
|
+
b_idx += b_step;
|
|
398
|
+
}
|
|
399
|
+
*product = nk_svaddv_f64_(predicate_all_b64x, product_f64x);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
#if defined(__clang__)
|
|
403
|
+
#pragma clang attribute pop
|
|
404
|
+
#elif defined(__GNUC__)
|
|
405
|
+
#pragma GCC pop_options
|
|
406
|
+
#endif
|
|
407
|
+
#endif // NK_TARGET_SVE2
|
|
408
|
+
|
|
409
|
+
#if NK_TARGET_SVE2 && NK_TARGET_SVEBFDOT
|
|
410
|
+
#if defined(__clang__)
|
|
411
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8.6-a+sve+sve2+bf16"))), apply_to = function)
|
|
412
|
+
#elif defined(__GNUC__)
|
|
413
|
+
#pragma GCC push_options
|
|
414
|
+
#pragma GCC target("arch=armv8.6-a+sve+sve2+bf16")
|
|
415
|
+
#endif
|
|
416
|
+
|
|
417
|
+
NK_PUBLIC void nk_sparse_dot_u16bf16_sve2( //
|
|
418
|
+
nk_u16_t const *a, nk_u16_t const *b, //
|
|
419
|
+
nk_bf16_t const *a_weights, nk_bf16_t const *b_weights, //
|
|
420
|
+
nk_size_t a_length, nk_size_t b_length, //
|
|
421
|
+
nk_f32_t *product) {
|
|
422
|
+
|
|
423
|
+
// A single SVE lane is 128 bits wide, so one lane fits 8 values.
|
|
424
|
+
nk_size_t const register_size = svcnth();
|
|
425
|
+
nk_size_t const lanes_count = register_size / 8;
|
|
426
|
+
nk_size_t a_idx = 0, b_idx = 0;
|
|
427
|
+
svfloat32_t product_f32x = svdupq_n_f32(0.f, 0.f, 0.f, 0.f);
|
|
428
|
+
|
|
429
|
+
while (a_idx < a_length && b_idx < b_length) {
|
|
430
|
+
// Load `a_member` and broadcast it, load `b_members_vec` from memory
|
|
431
|
+
svbool_t a_progress_b16x = svwhilelt_b16_u64(a_idx, a_length);
|
|
432
|
+
svbool_t b_progress_b16x = svwhilelt_b16_u64(b_idx, b_length);
|
|
433
|
+
svuint16_t a_u16x = svld1_u16(a_progress_b16x, a + a_idx);
|
|
434
|
+
svuint16_t b_u16x = svld1_u16(b_progress_b16x, b + b_idx);
|
|
435
|
+
|
|
436
|
+
// Intersecting registers with `svmatch_u16` involves a lot of shuffling
|
|
437
|
+
// and comparisons, so we want to avoid it if the slices don't overlap at all..
|
|
438
|
+
nk_u16_t a_min;
|
|
439
|
+
nk_u16_t a_max = svlastb(a_progress_b16x, a_u16x);
|
|
440
|
+
nk_u16_t b_min = svlasta(svpfalse_b(), b_u16x);
|
|
441
|
+
nk_u16_t b_max = svlastb(b_progress_b16x, b_u16x);
|
|
442
|
+
|
|
443
|
+
// If the slices don't overlap, advance the appropriate pointer
|
|
444
|
+
while (a_max < b_min && (a_idx + register_size) <= a_length) {
|
|
445
|
+
a_idx += register_size;
|
|
446
|
+
a_progress_b16x = svwhilelt_b16_u64(a_idx, a_length);
|
|
447
|
+
a_u16x = svld1_u16(a_progress_b16x, a + a_idx);
|
|
448
|
+
a_max = svlastb(a_progress_b16x, a_u16x);
|
|
449
|
+
}
|
|
450
|
+
a_min = svlasta(svpfalse_b(), a_u16x);
|
|
451
|
+
while (b_max < a_min && (b_idx + register_size) <= b_length) {
|
|
452
|
+
b_idx += register_size;
|
|
453
|
+
b_progress_b16x = svwhilelt_b16_u64(b_idx, b_length);
|
|
454
|
+
b_u16x = svld1_u16(b_progress_b16x, b + b_idx);
|
|
455
|
+
b_max = svlastb(b_progress_b16x, b_u16x);
|
|
456
|
+
}
|
|
457
|
+
b_min = svlasta(svpfalse_b(), b_u16x);
|
|
458
|
+
|
|
459
|
+
// Before we evaluate the intersection size, obfurscating the order in `b_u16x`,
|
|
460
|
+
// let's estimate how much we will need to advance the pointers afterwards.
|
|
461
|
+
// For that, we don't even need to broadcast the values in SVE, as the whole
|
|
462
|
+
// register can be compared against a scalar:
|
|
463
|
+
//
|
|
464
|
+
// svuint16_t a_last_broadcasted = svdup_n_u16(a_max);
|
|
465
|
+
// svuint16_t b_last_broadcasted = svdup_n_u16(b_max);
|
|
466
|
+
svbool_t a_mask_b16x = svcmple_n_u16(a_progress_b16x, a_u16x, b_max);
|
|
467
|
+
svbool_t b_mask_b16x = svcmple_n_u16(b_progress_b16x, b_u16x, a_max);
|
|
468
|
+
nk_u64_t a_step = svcntp_b16(a_progress_b16x, a_mask_b16x);
|
|
469
|
+
nk_u64_t b_step = svcntp_b16(b_progress_b16x, b_mask_b16x);
|
|
470
|
+
|
|
471
|
+
// Compare `a_u16x` with each lane of `b_u16x`
|
|
472
|
+
svbfloat16_t a_weights_bf16x = svld1_bf16(a_progress_b16x, (__bf16 const *)a_weights + a_idx);
|
|
473
|
+
svbfloat16_t b_weights_bf16x = svld1_bf16(b_progress_b16x, (__bf16 const *)b_weights + b_idx);
|
|
474
|
+
for (nk_size_t i = 0; i < lanes_count; i++) {
|
|
475
|
+
svbool_t equal_mask_b16x = svmatch_u16(a_progress_b16x, a_u16x, b_u16x);
|
|
476
|
+
//! The `svsel_bf16` intrinsic is broken in many compilers, not returning the correct type.
|
|
477
|
+
//! So we reinterprete floats as integers and apply `svsel_s16`, but the `svreinterpret_s16_bs16`
|
|
478
|
+
//! and `svreinterpret_bf16_s16` are not always properly defined!
|
|
479
|
+
svint16_t b_equal_weights_s16x = svsel_s16(equal_mask_b16x, svreinterpret_s16_bf16(b_weights_bf16x),
|
|
480
|
+
svdup_n_s16(0));
|
|
481
|
+
product_f32x = svbfdot_f32(product_f32x, a_weights_bf16x, svreinterpret_bf16_s16(b_equal_weights_s16x));
|
|
482
|
+
b_u16x = svext_u16(b_u16x, b_u16x, 8);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Advance
|
|
486
|
+
a_idx += a_step;
|
|
487
|
+
b_idx += b_step;
|
|
488
|
+
}
|
|
489
|
+
*product = nk_svaddv_f32_(svptrue_b32(), product_f32x);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
#if defined(__clang__)
|
|
493
|
+
#pragma clang attribute pop
|
|
494
|
+
#elif defined(__GNUC__)
|
|
495
|
+
#pragma GCC pop_options
|
|
496
|
+
#endif
|
|
497
|
+
#endif // NK_TARGET_SVE2 && NK_TARGET_SVEBFDOT
|
|
498
|
+
|
|
499
|
+
#if defined(__cplusplus)
|
|
500
|
+
} // extern "C"
|
|
501
|
+
#endif
|
|
502
|
+
|
|
503
|
+
#endif // NK_TARGET_ARM64_
|
|
504
|
+
#endif // NK_SPARSE_SVE2_H
|