usearch 2.21.4 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +224 -48
- 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,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Set Similarity Measures for NEON.
|
|
3
|
+
* @file include/numkong/set/neon.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date December 27, 2025
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/set.h
|
|
8
|
+
*
|
|
9
|
+
* @section set_neon_instructions NEON Set Instructions
|
|
10
|
+
*
|
|
11
|
+
* Key NEON instructions for binary/bitwise operations (Cortex-A76 class):
|
|
12
|
+
*
|
|
13
|
+
* Intrinsic Instruction A76 M5
|
|
14
|
+
* vcntq_u8 CNT (V.16B, V.16B) 2cy @ 2p 2cy @ 4p
|
|
15
|
+
* veorq_u8 EOR (V.16B, V.16B, V.16B) 1cy @ 2p 2cy @ 4p
|
|
16
|
+
* vandq_u8 AND (V.16B, V.16B, V.16B) 1cy @ 2p 2cy @ 4p
|
|
17
|
+
* vorrq_u8 ORR (V.16B, V.16B, V.16B) 1cy @ 2p 2cy @ 4p
|
|
18
|
+
* vpaddlq_u8 UADDLP (V.8H, V.16B) 2cy @ 2p 2cy @ 4p
|
|
19
|
+
* vaddvq_u32 ADDV (S, V.4S) 4cy @ 1p 5cy @ 1p
|
|
20
|
+
*
|
|
21
|
+
* According to the available literature, the throughput for those basic integer ops is
|
|
22
|
+
* identical across most Apple, Qualcomm, and AWS Graviton chips. As long as we avoid widening
|
|
23
|
+
* operations and horizontal reductions, we won't face any reasonable bottlenecks.
|
|
24
|
+
*
|
|
25
|
+
* @section set_neon_stateful Stateful Streaming Logic
|
|
26
|
+
*
|
|
27
|
+
* To build memory-optimal tiled algorithms, this file defines:
|
|
28
|
+
*
|
|
29
|
+
* - nk_hamming_u1x128_state_neon_t for streaming Hamming distance
|
|
30
|
+
* - nk_jaccard_u1x128_state_neon_t for streaming Jaccard similarity
|
|
31
|
+
*
|
|
32
|
+
* @code{c}
|
|
33
|
+
* nk_jaccard_u1x128_state_neon_t state_first, state_second, state_third, state_fourth;
|
|
34
|
+
* nk_jaccard_u1x128_init_neon(&state_first);
|
|
35
|
+
* // ... stream through packed binary vectors ...
|
|
36
|
+
* nk_jaccard_u1x128_finalize_neon(&state_first, &state_second, &state_third, &state_fourth,
|
|
37
|
+
* query_popcount, target_popcount_a, target_popcount_b, target_popcount_c, target_popcount_d,
|
|
38
|
+
* total_dimensions, &results);
|
|
39
|
+
* @endcode
|
|
40
|
+
*/
|
|
41
|
+
#ifndef NK_SET_NEON_H
|
|
42
|
+
#define NK_SET_NEON_H
|
|
43
|
+
|
|
44
|
+
#if NK_TARGET_ARM64_
|
|
45
|
+
#if NK_TARGET_NEON
|
|
46
|
+
|
|
47
|
+
#include "numkong/types.h" // `nk_u1x8_t`
|
|
48
|
+
#include "numkong/set/serial.h" // `nk_u1x8_popcount_`
|
|
49
|
+
|
|
50
|
+
#if defined(__cplusplus)
|
|
51
|
+
extern "C" {
|
|
52
|
+
#endif
|
|
53
|
+
|
|
54
|
+
#if defined(__clang__)
|
|
55
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8-a+simd"))), apply_to = function)
|
|
56
|
+
#elif defined(__GNUC__)
|
|
57
|
+
#pragma GCC push_options
|
|
58
|
+
#pragma GCC target("arch=armv8-a+simd")
|
|
59
|
+
#endif
|
|
60
|
+
|
|
61
|
+
#pragma region Binary Sets
|
|
62
|
+
|
|
63
|
+
NK_PUBLIC void nk_hamming_u1_neon(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
64
|
+
nk_size_t n_bytes = nk_size_divide_round_up_(n, NK_BITS_PER_BYTE);
|
|
65
|
+
nk_u32_t differences = 0;
|
|
66
|
+
nk_size_t i = 0;
|
|
67
|
+
// In each 8-bit word we may have up to 8 differences.
|
|
68
|
+
// So for up-to 31 cycles (31 * 16 = 496 word-dimensions = 3968 bits)
|
|
69
|
+
// we can aggregate the differences into a `uint8x16_t` vector,
|
|
70
|
+
// where each component will be up-to 255.
|
|
71
|
+
while (i + 16 <= n_bytes) {
|
|
72
|
+
uint8x16_t popcount_u8x16 = vdupq_n_u8(0);
|
|
73
|
+
for (nk_size_t cycle = 0; cycle < 31 && i + 16 <= n_bytes; ++cycle, i += 16) {
|
|
74
|
+
uint8x16_t a_u8x16 = vld1q_u8(a + i);
|
|
75
|
+
uint8x16_t b_u8x16 = vld1q_u8(b + i);
|
|
76
|
+
uint8x16_t xor_popcount_u8x16 = vcntq_u8(veorq_u8(a_u8x16, b_u8x16));
|
|
77
|
+
popcount_u8x16 = vaddq_u8(popcount_u8x16, xor_popcount_u8x16);
|
|
78
|
+
}
|
|
79
|
+
differences += (nk_u32_t)vaddlvq_u8(popcount_u8x16);
|
|
80
|
+
}
|
|
81
|
+
// Handle the tail
|
|
82
|
+
for (; i != n_bytes; ++i) differences += nk_u1x8_popcount_(a[i] ^ b[i]);
|
|
83
|
+
*result = differences;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
NK_PUBLIC void nk_jaccard_u1_neon(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
87
|
+
nk_size_t n_bytes = nk_size_divide_round_up_(n, NK_BITS_PER_BYTE);
|
|
88
|
+
nk_u32_t intersection_count = 0, union_count = 0;
|
|
89
|
+
nk_size_t i = 0;
|
|
90
|
+
// In each 8-bit word we may have up to 8 intersections/unions.
|
|
91
|
+
// So for up-to 31 cycles (31 * 16 = 496 word-dimensions = 3968 bits)
|
|
92
|
+
// we can aggregate the intersections/unions into a `uint8x16_t` vector,
|
|
93
|
+
// where each component will be up-to 255.
|
|
94
|
+
while (i + 16 <= n_bytes) {
|
|
95
|
+
uint8x16_t intersection_popcount_u8x16 = vdupq_n_u8(0);
|
|
96
|
+
uint8x16_t union_popcount_u8x16 = vdupq_n_u8(0);
|
|
97
|
+
for (nk_size_t cycle = 0; cycle < 31 && i + 16 <= n_bytes; ++cycle, i += 16) {
|
|
98
|
+
uint8x16_t a_u8x16 = vld1q_u8(a + i);
|
|
99
|
+
uint8x16_t b_u8x16 = vld1q_u8(b + i);
|
|
100
|
+
intersection_popcount_u8x16 = vaddq_u8(intersection_popcount_u8x16, vcntq_u8(vandq_u8(a_u8x16, b_u8x16)));
|
|
101
|
+
union_popcount_u8x16 = vaddq_u8(union_popcount_u8x16, vcntq_u8(vorrq_u8(a_u8x16, b_u8x16)));
|
|
102
|
+
}
|
|
103
|
+
intersection_count += (nk_u32_t)vaddlvq_u8(intersection_popcount_u8x16);
|
|
104
|
+
union_count += (nk_u32_t)vaddlvq_u8(union_popcount_u8x16);
|
|
105
|
+
}
|
|
106
|
+
// Handle the tail
|
|
107
|
+
for (; i != n_bytes; ++i)
|
|
108
|
+
intersection_count += nk_u1x8_popcount_(a[i] & b[i]), union_count += nk_u1x8_popcount_(a[i] | b[i]);
|
|
109
|
+
*result = (union_count != 0) ? 1.0f - (nk_f32_t)intersection_count / (nk_f32_t)union_count : 0.0f;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
#pragma endregion Binary Sets
|
|
113
|
+
|
|
114
|
+
#pragma region Integer Sets
|
|
115
|
+
|
|
116
|
+
NK_PUBLIC void nk_jaccard_u32_neon(nk_u32_t const *a, nk_u32_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
117
|
+
nk_u32_t intersection_count = 0;
|
|
118
|
+
nk_size_t i = 0;
|
|
119
|
+
uint32x4_t intersection_count_u32x4 = vdupq_n_u32(0);
|
|
120
|
+
for (; i + 4 <= n; i += 4) {
|
|
121
|
+
uint32x4_t a_u32x4 = vld1q_u32(a + i);
|
|
122
|
+
uint32x4_t b_u32x4 = vld1q_u32(b + i);
|
|
123
|
+
uint32x4_t equality_mask = vceqq_u32(a_u32x4, b_u32x4);
|
|
124
|
+
intersection_count_u32x4 = vaddq_u32(intersection_count_u32x4, vshrq_n_u32(equality_mask, 31));
|
|
125
|
+
}
|
|
126
|
+
intersection_count += vaddvq_u32(intersection_count_u32x4);
|
|
127
|
+
for (; i != n; ++i) intersection_count += (a[i] == b[i]);
|
|
128
|
+
*result = (n != 0) ? 1.0f - (nk_f32_t)intersection_count / (nk_f32_t)n : 0.0f;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
NK_PUBLIC void nk_hamming_u8_neon(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
132
|
+
nk_size_t i = 0;
|
|
133
|
+
uint32x4_t diff_count_u32x4 = vdupq_n_u32(0);
|
|
134
|
+
// Process 16 bytes at a time using NEON with widening adds to avoid overflow.
|
|
135
|
+
// Uses pairwise widening chain: 16 u8 → 8 u16 → 4 u32 per iteration.
|
|
136
|
+
for (; i + 16 <= n; i += 16) {
|
|
137
|
+
uint8x16_t a_u8x16 = vld1q_u8(a + i);
|
|
138
|
+
uint8x16_t b_u8x16 = vld1q_u8(b + i);
|
|
139
|
+
// vceqq_u8 returns 0xFF for equal, 0x00 for not-equal
|
|
140
|
+
// Invert to get 0xFF for not-equal, then shift right by 7 to get 1
|
|
141
|
+
uint8x16_t not_equal_u8x16 = vmvnq_u8(vceqq_u8(a_u8x16, b_u8x16));
|
|
142
|
+
uint8x16_t diff_bits_u8x16 = vshrq_n_u8(not_equal_u8x16, 7);
|
|
143
|
+
// Widen: 16 u8 → 8 u16 → 4 u32 using pairwise add and widen
|
|
144
|
+
uint16x8_t diff_u16x8 = vpaddlq_u8(diff_bits_u8x16);
|
|
145
|
+
uint32x4_t diff_u32x4 = vpaddlq_u16(diff_u16x8);
|
|
146
|
+
diff_count_u32x4 = vaddq_u32(diff_count_u32x4, diff_u32x4);
|
|
147
|
+
}
|
|
148
|
+
nk_u32_t differences = vaddvq_u32(diff_count_u32x4);
|
|
149
|
+
// Handle tail elements
|
|
150
|
+
for (; i != n; ++i) differences += (a[i] != b[i]);
|
|
151
|
+
*result = differences;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
NK_PUBLIC void nk_jaccard_u16_neon(nk_u16_t const *a, nk_u16_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
155
|
+
nk_u32_t matches = 0;
|
|
156
|
+
nk_size_t i = 0;
|
|
157
|
+
uint32x4_t match_count_u32x4 = vdupq_n_u32(0);
|
|
158
|
+
// Process 8 u16 values at a time using NEON
|
|
159
|
+
for (; i + 8 <= n; i += 8) {
|
|
160
|
+
uint16x8_t a_u16x8 = vld1q_u16(a + i);
|
|
161
|
+
uint16x8_t b_u16x8 = vld1q_u16(b + i);
|
|
162
|
+
// vceqq_u16 returns 0xFFFF for equal, 0x0000 for not-equal
|
|
163
|
+
uint16x8_t equality_mask = vceqq_u16(a_u16x8, b_u16x8);
|
|
164
|
+
// Count matches by shifting right by 15 to get 1 for match, 0 for non-match
|
|
165
|
+
// Then widen and accumulate into u32
|
|
166
|
+
uint16x8_t match_bits = vshrq_n_u16(equality_mask, 15);
|
|
167
|
+
// Pairwise add and widen to u32
|
|
168
|
+
uint32x4_t match_u32x4 = vpaddlq_u16(match_bits);
|
|
169
|
+
match_count_u32x4 = vaddq_u32(match_count_u32x4, match_u32x4);
|
|
170
|
+
}
|
|
171
|
+
matches += vaddvq_u32(match_count_u32x4);
|
|
172
|
+
// Handle tail elements
|
|
173
|
+
for (; i != n; ++i) matches += (a[i] == b[i]);
|
|
174
|
+
*result = (n != 0) ? 1.0f - (nk_f32_t)matches / (nk_f32_t)n : 0.0f;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
#pragma endregion Integer Sets
|
|
178
|
+
|
|
179
|
+
#pragma region Stateful Streaming
|
|
180
|
+
|
|
181
|
+
typedef struct nk_hamming_u1x128_state_neon_t {
|
|
182
|
+
uint32x4_t intersection_count_u32x4;
|
|
183
|
+
} nk_hamming_u1x128_state_neon_t;
|
|
184
|
+
|
|
185
|
+
NK_INTERNAL void nk_hamming_u1x128_init_neon(nk_hamming_u1x128_state_neon_t *state) {
|
|
186
|
+
state->intersection_count_u32x4 = vdupq_n_u32(0);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
NK_INTERNAL void nk_hamming_u1x128_update_neon(nk_hamming_u1x128_state_neon_t *state, nk_b128_vec_t a, nk_b128_vec_t b,
|
|
190
|
+
nk_size_t depth_offset, nk_size_t active_dimensions) {
|
|
191
|
+
nk_unused_(depth_offset);
|
|
192
|
+
nk_unused_(active_dimensions);
|
|
193
|
+
|
|
194
|
+
// Process one 128-bit chunk (native ARM NEON register size).
|
|
195
|
+
// Uses vector accumulation - horizontal sum deferred to finalize.
|
|
196
|
+
//
|
|
197
|
+
// ARM NEON instruction characteristics:
|
|
198
|
+
// - `veorq_u8`: XOR (V.16B, V.16B, V.16B) 1cy
|
|
199
|
+
// - `vcntq_u8`: CNT (V.16B, V.16B) 1-2cy, byte popcount
|
|
200
|
+
// - `vpaddlq_u8`: UADDLP (V.8H, V.16B) 1cy, pairwise widen u8 → u16
|
|
201
|
+
// - `vpaddlq_u16`: UADDLP (V.4S, V.8H) 1cy, pairwise widen u16 → u32
|
|
202
|
+
// - `vaddq_u32`: ADD (V.4S, V.4S, V.4S) 1cy
|
|
203
|
+
// Total: ~5-6cy per 128-bit chunk (horizontal sum deferred to finalize)
|
|
204
|
+
|
|
205
|
+
// Step 1: Compute intersection bits (A XOR B)
|
|
206
|
+
uint8x16_t intersection_u8x16 = veorq_u8(a.u8x16, b.u8x16);
|
|
207
|
+
|
|
208
|
+
// Step 2: Byte-level popcount - each byte contains count of set bits (0-8)
|
|
209
|
+
uint8x16_t popcount_u8x16 = vcntq_u8(intersection_u8x16);
|
|
210
|
+
|
|
211
|
+
// Step 3: Pairwise widening reduction chain
|
|
212
|
+
// u8x16 → u16x8: pairs of adjacent bytes summed into 16-bit
|
|
213
|
+
uint16x8_t popcount_u16x8 = vpaddlq_u8(popcount_u8x16);
|
|
214
|
+
// u16x8 → u32x4: pairs of 16-bit values summed into 32-bit
|
|
215
|
+
uint32x4_t popcount_u32x4 = vpaddlq_u16(popcount_u16x8);
|
|
216
|
+
|
|
217
|
+
// Step 4: Vector accumulation (defers horizontal sum to finalize)
|
|
218
|
+
state->intersection_count_u32x4 = vaddq_u32(state->intersection_count_u32x4, popcount_u32x4);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
NK_INTERNAL void nk_hamming_u1x128_finalize_neon( //
|
|
222
|
+
nk_hamming_u1x128_state_neon_t const *state_a, nk_hamming_u1x128_state_neon_t const *state_b,
|
|
223
|
+
nk_hamming_u1x128_state_neon_t const *state_c, nk_hamming_u1x128_state_neon_t const *state_d,
|
|
224
|
+
nk_size_t total_dimensions, nk_b128_vec_t *result) {
|
|
225
|
+
nk_unused_(total_dimensions);
|
|
226
|
+
|
|
227
|
+
// Horizontal sum using pairwise adds - same pattern as Jaccard.
|
|
228
|
+
// 3× ADDP to reduce 4 state vectors into [sum_a, sum_b, sum_c, sum_d].
|
|
229
|
+
uint32x4_t ab_sum_u32x4 = vpaddq_u32(state_a->intersection_count_u32x4, state_b->intersection_count_u32x4);
|
|
230
|
+
uint32x4_t cd_sum_u32x4 = vpaddq_u32(state_c->intersection_count_u32x4, state_d->intersection_count_u32x4);
|
|
231
|
+
result->u32x4 = vpaddq_u32(ab_sum_u32x4, cd_sum_u32x4);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
typedef struct nk_jaccard_u1x128_state_neon_t {
|
|
235
|
+
uint32x4_t intersection_count_u32x4;
|
|
236
|
+
} nk_jaccard_u1x128_state_neon_t;
|
|
237
|
+
|
|
238
|
+
NK_INTERNAL void nk_jaccard_u1x128_init_neon(nk_jaccard_u1x128_state_neon_t *state) {
|
|
239
|
+
state->intersection_count_u32x4 = vdupq_n_u32(0);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
NK_INTERNAL void nk_jaccard_u1x128_update_neon(nk_jaccard_u1x128_state_neon_t *state, nk_b128_vec_t a, nk_b128_vec_t b,
|
|
243
|
+
nk_size_t depth_offset, nk_size_t active_dimensions) {
|
|
244
|
+
nk_unused_(depth_offset);
|
|
245
|
+
nk_unused_(active_dimensions);
|
|
246
|
+
|
|
247
|
+
// Process one 128-bit chunk (native ARM NEON register size).
|
|
248
|
+
// Uses vector accumulation - horizontal sum deferred to finalize.
|
|
249
|
+
//
|
|
250
|
+
// ARM NEON instruction characteristics:
|
|
251
|
+
// - `vandq_u8`: AND (V.16B, V.16B, V.16B) 1cy
|
|
252
|
+
// - `vcntq_u8`: CNT (V.16B, V.16B) 1-2cy, byte popcount
|
|
253
|
+
// - `vpaddlq_u8`: UADDLP (V.8H, V.16B) 1cy, pairwise widen u8 → u16
|
|
254
|
+
// - `vpaddlq_u16`: UADDLP (V.4S, V.8H) 1cy, pairwise widen u16 → u32
|
|
255
|
+
// - `vaddq_u32`: ADD (V.4S, V.4S, V.4S) 1cy
|
|
256
|
+
// Total: ~5-6cy per 128-bit chunk (horizontal sum deferred to finalize)
|
|
257
|
+
|
|
258
|
+
// Step 1: Compute intersection bits (A AND B)
|
|
259
|
+
uint8x16_t intersection_u8x16 = vandq_u8(a.u8x16, b.u8x16);
|
|
260
|
+
|
|
261
|
+
// Step 2: Byte-level popcount - each byte contains count of set bits (0-8)
|
|
262
|
+
uint8x16_t popcount_u8x16 = vcntq_u8(intersection_u8x16);
|
|
263
|
+
|
|
264
|
+
// Step 3: Pairwise widening reduction chain
|
|
265
|
+
// u8x16 → u16x8: pairs of adjacent bytes summed into 16-bit
|
|
266
|
+
uint16x8_t popcount_u16x8 = vpaddlq_u8(popcount_u8x16);
|
|
267
|
+
// u16x8 → u32x4: pairs of 16-bit values summed into 32-bit
|
|
268
|
+
uint32x4_t popcount_u32x4 = vpaddlq_u16(popcount_u16x8);
|
|
269
|
+
|
|
270
|
+
// Step 4: Vector accumulation (defers horizontal sum to finalize)
|
|
271
|
+
state->intersection_count_u32x4 = vaddq_u32(state->intersection_count_u32x4, popcount_u32x4);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
NK_INTERNAL void nk_jaccard_u1x128_finalize_neon( //
|
|
275
|
+
nk_jaccard_u1x128_state_neon_t const *state_a, nk_jaccard_u1x128_state_neon_t const *state_b,
|
|
276
|
+
nk_jaccard_u1x128_state_neon_t const *state_c, nk_jaccard_u1x128_state_neon_t const *state_d,
|
|
277
|
+
nk_f32_t query_popcount, nk_f32_t target_popcount_a, nk_f32_t target_popcount_b, nk_f32_t target_popcount_c,
|
|
278
|
+
nk_f32_t target_popcount_d, nk_size_t total_dimensions, nk_b128_vec_t *result) {
|
|
279
|
+
nk_unused_(total_dimensions);
|
|
280
|
+
|
|
281
|
+
// Horizontal sum using pairwise adds instead of `vaddvq_u32` (ADDV).
|
|
282
|
+
// `vpaddq_u32` (ADDP) has better throughput: 2/cy vs 1/cy for ADDV on Cortex-A76.
|
|
283
|
+
// 3 ADDP instructions vs 4 ADDV + union store/load.
|
|
284
|
+
//
|
|
285
|
+
// Step 1: vpaddq_u32(A, B) = [a0+a1, a2+a3, b0+b1, b2+b3]
|
|
286
|
+
uint32x4_t ab_sum_u32x4 = vpaddq_u32(state_a->intersection_count_u32x4, state_b->intersection_count_u32x4);
|
|
287
|
+
uint32x4_t cd_sum_u32x4 = vpaddq_u32(state_c->intersection_count_u32x4, state_d->intersection_count_u32x4);
|
|
288
|
+
// Step 2: Final pairwise reduction gives [sum_a, sum_b, sum_c, sum_d]
|
|
289
|
+
uint32x4_t intersection_u32x4 = vpaddq_u32(ab_sum_u32x4, cd_sum_u32x4);
|
|
290
|
+
float32x4_t intersection_f32x4 = vcvtq_f32_u32(intersection_u32x4);
|
|
291
|
+
|
|
292
|
+
// Compute union using |A ∪ B| = |A| + |B| - |A ∩ B|
|
|
293
|
+
// Build target popcounts vector from two independent halves (avoids serial lane insertion chain).
|
|
294
|
+
float32x4_t query_f32x4 = vdupq_n_f32(query_popcount);
|
|
295
|
+
float32x2_t targets_ab_f32x2 = vset_lane_f32(target_popcount_b, vdup_n_f32(target_popcount_a), 1);
|
|
296
|
+
float32x2_t targets_cd_f32x2 = vset_lane_f32(target_popcount_d, vdup_n_f32(target_popcount_c), 1);
|
|
297
|
+
float32x4_t targets_f32x4 = vcombine_f32(targets_ab_f32x2, targets_cd_f32x2);
|
|
298
|
+
float32x4_t union_f32x4 = vsubq_f32(vaddq_f32(query_f32x4, targets_f32x4), intersection_f32x4);
|
|
299
|
+
|
|
300
|
+
// Handle zero-union edge case (empty vectors → distance = 0.0, matching scipy convention)
|
|
301
|
+
float32x4_t one_f32x4 = vdupq_n_f32(1.0f);
|
|
302
|
+
uint32x4_t zero_union_mask = vceqq_f32(union_f32x4, vdupq_n_f32(0.0f));
|
|
303
|
+
float32x4_t safe_union_f32x4 = vbslq_f32(zero_union_mask, one_f32x4, union_f32x4);
|
|
304
|
+
|
|
305
|
+
// Fast reciprocal with Newton-Raphson refinement:
|
|
306
|
+
// - `vrecpeq_f32`: ~12-bit estimate, 1 cycle
|
|
307
|
+
// - `vrecpsq_f32`: Newton-Raphson step computes (2 - a × b), 1 cycle
|
|
308
|
+
// - `vmulq_f32`: multiply, 1 cycle
|
|
309
|
+
// One N-R iteration: ~24-bit accuracy, sufficient for f32 (23 mantissa bits).
|
|
310
|
+
// Total: ~3-4 cycles vs ~10-14 cycles for division.
|
|
311
|
+
float32x4_t union_reciprocal_f32x4 = vrecpeq_f32(safe_union_f32x4);
|
|
312
|
+
union_reciprocal_f32x4 = vmulq_f32(union_reciprocal_f32x4, vrecpsq_f32(safe_union_f32x4, union_reciprocal_f32x4));
|
|
313
|
+
|
|
314
|
+
// Compute Jaccard distance = 1 - intersection ÷ union
|
|
315
|
+
float32x4_t ratio_f32x4 = vmulq_f32(intersection_f32x4, union_reciprocal_f32x4);
|
|
316
|
+
float32x4_t jaccard_f32x4 = vsubq_f32(one_f32x4, ratio_f32x4);
|
|
317
|
+
result->f32x4 = vbslq_f32(zero_union_mask, vdupq_n_f32(0.0f), jaccard_f32x4);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/** @brief Hamming from_dot: computes pop_a + pop_b - 2*dot for 4 pairs (NEON). */
|
|
321
|
+
NK_INTERNAL void nk_hamming_u32x4_from_dot_neon_(nk_b128_vec_t dots, nk_u32_t query_pop, nk_b128_vec_t target_pops,
|
|
322
|
+
nk_b128_vec_t *results) {
|
|
323
|
+
uint32x4_t dots_u32x4 = dots.u32x4;
|
|
324
|
+
uint32x4_t query_u32x4 = vdupq_n_u32(query_pop);
|
|
325
|
+
uint32x4_t target_u32x4 = target_pops.u32x4;
|
|
326
|
+
results->u32x4 = vsubq_u32(vaddq_u32(query_u32x4, target_u32x4), vshlq_n_u32(dots_u32x4, 1));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** @brief Jaccard from_dot: computes 1 - dot / (pop_a + pop_b - dot) for 4 pairs (NEON). */
|
|
330
|
+
NK_INTERNAL void nk_jaccard_f32x4_from_dot_neon_(nk_b128_vec_t dots, nk_u32_t query_pop, nk_b128_vec_t target_pops,
|
|
331
|
+
nk_b128_vec_t *results) {
|
|
332
|
+
float32x4_t dot_f32x4 = vcvtq_f32_u32(dots.u32x4);
|
|
333
|
+
float32x4_t query_f32x4 = vdupq_n_f32((nk_f32_t)query_pop);
|
|
334
|
+
float32x4_t target_f32x4 = vcvtq_f32_u32(target_pops.u32x4);
|
|
335
|
+
float32x4_t union_f32x4 = vsubq_f32(vaddq_f32(query_f32x4, target_f32x4), dot_f32x4);
|
|
336
|
+
|
|
337
|
+
float32x4_t one_f32x4 = vdupq_n_f32(1.0f);
|
|
338
|
+
uint32x4_t zero_union_mask = vceqq_f32(union_f32x4, vdupq_n_f32(0.0f));
|
|
339
|
+
float32x4_t safe_union_f32x4 = vbslq_f32(zero_union_mask, one_f32x4, union_f32x4);
|
|
340
|
+
|
|
341
|
+
float32x4_t union_reciprocal_f32x4 = vrecpeq_f32(safe_union_f32x4);
|
|
342
|
+
union_reciprocal_f32x4 = vmulq_f32(union_reciprocal_f32x4, vrecpsq_f32(safe_union_f32x4, union_reciprocal_f32x4));
|
|
343
|
+
|
|
344
|
+
float32x4_t ratio_f32x4 = vmulq_f32(dot_f32x4, union_reciprocal_f32x4);
|
|
345
|
+
float32x4_t jaccard_f32x4 = vsubq_f32(one_f32x4, ratio_f32x4);
|
|
346
|
+
results->f32x4 = vbslq_f32(zero_union_mask, vdupq_n_f32(0.0f), jaccard_f32x4);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
#pragma endregion Stateful Streaming
|
|
350
|
+
|
|
351
|
+
#if defined(__clang__)
|
|
352
|
+
#pragma clang attribute pop
|
|
353
|
+
#elif defined(__GNUC__)
|
|
354
|
+
#pragma GCC pop_options
|
|
355
|
+
#endif
|
|
356
|
+
|
|
357
|
+
#if defined(__cplusplus)
|
|
358
|
+
} // extern "C"
|
|
359
|
+
#endif
|
|
360
|
+
|
|
361
|
+
#endif // NK_TARGET_NEON
|
|
362
|
+
#endif // NK_TARGET_ARM64_
|
|
363
|
+
#endif // NK_SET_NEON_H
|