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,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Spatial Similarity Measures for NEON SDOT.
|
|
3
|
+
* @file include/numkong/spatial/neonsdot.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date December 27, 2025
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/spatial.h
|
|
8
|
+
*
|
|
9
|
+
* @section spatial_neonsdot_instructions ARM NEON SDOT/UDOT Instructions (ARMv8.4-DotProd)
|
|
10
|
+
*
|
|
11
|
+
* Intrinsic Instruction A76 M5
|
|
12
|
+
* vdotq_s32 SDOT (V.4S, V.16B, V.16B) 3cy @ 2p 3cy @ 4p
|
|
13
|
+
* vdotq_u32 UDOT (V.4S, V.16B, V.16B) 3cy @ 2p 3cy @ 4p
|
|
14
|
+
* vabdq_s8 SABD (V.16B, V.16B, V.16B) 3cy @ 2p 3cy @ 2p
|
|
15
|
+
* vabdq_u8 UABD (V.16B, V.16B, V.16B) 3cy @ 2p 3cy @ 2p
|
|
16
|
+
* vld1q_s8 LD1 (V.16B) 4cy @ 2p 4cy @ 3p
|
|
17
|
+
* vld1q_u8 LD1 (V.16B) 4cy @ 2p 4cy @ 3p
|
|
18
|
+
* vaddvq_s32 ADDV (V.4S) 4cy @ 1p 5cy @ 1p
|
|
19
|
+
* vaddvq_u32 ADDV (V.4S) 4cy @ 1p 5cy @ 1p
|
|
20
|
+
*
|
|
21
|
+
* The ARMv8.4-DotProd extension provides SDOT/UDOT for int8 dot products and SABD/UABD for
|
|
22
|
+
* absolute differences, enabling L2 and angular distance on quantized embeddings.
|
|
23
|
+
* For L2 distance, SABD computes |a-b| per byte, then UDOT squares and accumulates.
|
|
24
|
+
*
|
|
25
|
+
* Angular distance uses SDOT/UDOT directly for dot product and norm computations. This enables
|
|
26
|
+
* similarity search on int8-quantized embeddings, achieving 4x memory reduction vs FP32
|
|
27
|
+
* while maintaining reasonable precision for nearest-neighbor search applications.
|
|
28
|
+
*/
|
|
29
|
+
#ifndef NK_SPATIAL_NEONSDOT_H
|
|
30
|
+
#define NK_SPATIAL_NEONSDOT_H
|
|
31
|
+
|
|
32
|
+
#if NK_TARGET_ARM64_
|
|
33
|
+
#if NK_TARGET_NEONSDOT
|
|
34
|
+
|
|
35
|
+
#include "numkong/types.h"
|
|
36
|
+
#include "numkong/cast/serial.h" // `nk_partial_load_b4x32_serial_`
|
|
37
|
+
#include "numkong/spatial/neon.h" // `nk_angular_normalize_f32_neon_`, `nk_f32_sqrt_neon`
|
|
38
|
+
|
|
39
|
+
#if defined(__cplusplus)
|
|
40
|
+
extern "C" {
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
#if defined(__clang__)
|
|
44
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8.2-a+dotprod"))), apply_to = function)
|
|
45
|
+
#elif defined(__GNUC__)
|
|
46
|
+
#pragma GCC push_options
|
|
47
|
+
#pragma GCC target("arch=armv8.2-a+dotprod")
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
NK_PUBLIC void nk_sqeuclidean_i8_neonsdot(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
51
|
+
|
|
52
|
+
// The naive approach is to upcast 8-bit signed integers into 16-bit signed integers
|
|
53
|
+
// for subtraction, then multiply within 16-bit integers and accumulate the results
|
|
54
|
+
// into 32-bit integers. This approach is slow on modern Arm CPUs. On Graviton 4,
|
|
55
|
+
// that approach results in 17 GB/s of throughput, compared to 39 GB/s for `i8`
|
|
56
|
+
// dot-products.
|
|
57
|
+
//
|
|
58
|
+
// Luckily we can use the `vabdq_s8` which technically returns `i8` values, but it's a
|
|
59
|
+
// matter of reinterpret-casting! That approach boosts us to 33 GB/s of throughput.
|
|
60
|
+
uint32x4_t distance_sq_u32x4 = vdupq_n_u32(0);
|
|
61
|
+
nk_size_t i = 0;
|
|
62
|
+
for (; i + 16 <= n; i += 16) {
|
|
63
|
+
int8x16_t a_i8x16 = vld1q_s8(a + i);
|
|
64
|
+
int8x16_t b_i8x16 = vld1q_s8(b + i);
|
|
65
|
+
uint8x16_t diff_u8x16 = vreinterpretq_u8_s8(vabdq_s8(a_i8x16, b_i8x16));
|
|
66
|
+
distance_sq_u32x4 = vdotq_u32(distance_sq_u32x4, diff_u8x16, diff_u8x16);
|
|
67
|
+
}
|
|
68
|
+
nk_u32_t distance_sq_u32 = vaddvq_u32(distance_sq_u32x4);
|
|
69
|
+
for (; i < n; ++i) {
|
|
70
|
+
nk_i32_t diff_i32 = (nk_i32_t)a[i] - b[i];
|
|
71
|
+
distance_sq_u32 += (nk_u32_t)(diff_i32 * diff_i32);
|
|
72
|
+
}
|
|
73
|
+
*result = distance_sq_u32;
|
|
74
|
+
}
|
|
75
|
+
NK_PUBLIC void nk_euclidean_i8_neonsdot(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
76
|
+
nk_u32_t distance_sq_u32;
|
|
77
|
+
nk_sqeuclidean_i8_neonsdot(a, b, n, &distance_sq_u32);
|
|
78
|
+
*result = nk_f32_sqrt_neon((nk_f32_t)distance_sq_u32);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
NK_PUBLIC void nk_angular_i8_neonsdot(nk_i8_t const *a, nk_i8_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
82
|
+
|
|
83
|
+
nk_size_t i = 0;
|
|
84
|
+
|
|
85
|
+
// Variant 1.
|
|
86
|
+
// If the 128-bit `vdot_s32` intrinsic is unavailable, we can use the 64-bit `vdot_s32`.
|
|
87
|
+
//
|
|
88
|
+
// int32x4_t ab_vec = vdupq_n_s32(0);
|
|
89
|
+
// int32x4_t a2_vec = vdupq_n_s32(0);
|
|
90
|
+
// int32x4_t b2_vec = vdupq_n_s32(0);
|
|
91
|
+
// for (nk_size_t i = 0; i != n; i += 8) {
|
|
92
|
+
// int16x8_t a_vec = vmovl_s8(vld1_s8(a + i));
|
|
93
|
+
// int16x8_t b_vec = vmovl_s8(vld1_s8(b + i));
|
|
94
|
+
// int16x8_t ab_part_vec = vmulq_s16(a_vec, b_vec);
|
|
95
|
+
// int16x8_t a2_part_vec = vmulq_s16(a_vec, a_vec);
|
|
96
|
+
// int16x8_t b2_part_vec = vmulq_s16(b_vec, b_vec);
|
|
97
|
+
// ab_vec = vaddq_s32(ab_vec, vaddq_s32(vmovl_s16(vget_high_s16(ab_part_vec)), //
|
|
98
|
+
// vmovl_s16(vget_low_s16(ab_part_vec))));
|
|
99
|
+
// a2_vec = vaddq_s32(a2_vec, vaddq_s32(vmovl_s16(vget_high_s16(a2_part_vec)), //
|
|
100
|
+
// vmovl_s16(vget_low_s16(a2_part_vec))));
|
|
101
|
+
// b2_vec = vaddq_s32(b2_vec, vaddq_s32(vmovl_s16(vget_high_s16(b2_part_vec)), //
|
|
102
|
+
// vmovl_s16(vget_low_s16(b2_part_vec))));
|
|
103
|
+
// }
|
|
104
|
+
//
|
|
105
|
+
// Variant 2.
|
|
106
|
+
// With the 128-bit `vdotq_s32` intrinsic, we can use the following code:
|
|
107
|
+
//
|
|
108
|
+
// for (; i + 16 <= n; i += 16) {
|
|
109
|
+
// int8x16_t a_vec = vld1q_s8(a + i);
|
|
110
|
+
// int8x16_t b_vec = vld1q_s8(b + i);
|
|
111
|
+
// ab_vec = vdotq_s32(ab_vec, a_vec, b_vec);
|
|
112
|
+
// a2_vec = vdotq_s32(a2_vec, a_vec, a_vec);
|
|
113
|
+
// b2_vec = vdotq_s32(b2_vec, b_vec, b_vec);
|
|
114
|
+
// }
|
|
115
|
+
//
|
|
116
|
+
// Variant 3.
|
|
117
|
+
// To use MMLA instructions, we need to reorganize the contents of the vectors.
|
|
118
|
+
// On input we have `a_vec` and `b_vec`:
|
|
119
|
+
//
|
|
120
|
+
// a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]
|
|
121
|
+
// b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]
|
|
122
|
+
//
|
|
123
|
+
// We will be multiplying matrices of size 2x8 and 8x2. So we need to perform a few shuffles:
|
|
124
|
+
//
|
|
125
|
+
// X =
|
|
126
|
+
// a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
|
|
127
|
+
// b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]
|
|
128
|
+
// Y =
|
|
129
|
+
// a[0], b[0],
|
|
130
|
+
// a[1], b[1],
|
|
131
|
+
// a[2], b[2],
|
|
132
|
+
// a[3], b[3],
|
|
133
|
+
// a[4], b[4],
|
|
134
|
+
// a[5], b[5],
|
|
135
|
+
// a[6], b[6],
|
|
136
|
+
// a[7], b[7]
|
|
137
|
+
//
|
|
138
|
+
// V =
|
|
139
|
+
// a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15],
|
|
140
|
+
// b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]
|
|
141
|
+
// W =
|
|
142
|
+
// a[8], b[8],
|
|
143
|
+
// a[9], b[9],
|
|
144
|
+
// a[10], b[10],
|
|
145
|
+
// a[11], b[11],
|
|
146
|
+
// a[12], b[12],
|
|
147
|
+
// a[13], b[13],
|
|
148
|
+
// a[14], b[14],
|
|
149
|
+
// a[15], b[15]
|
|
150
|
+
//
|
|
151
|
+
// Performing matrix multiplications we can aggregate into a matrix `products_low_vec` and `products_high_vec`:
|
|
152
|
+
//
|
|
153
|
+
// X * X, X * Y V * W, V * V
|
|
154
|
+
// Y * X, Y * Y W * W, W * V
|
|
155
|
+
//
|
|
156
|
+
// Of those values we need only 3/4, as the (X * Y) and (Y * X) are the same.
|
|
157
|
+
//
|
|
158
|
+
// int32x4_t products_low_vec = vdupq_n_s32(0), products_high_vec = vdupq_n_s32(0);
|
|
159
|
+
// int8x16_t a_low_b_low_vec, a_high_b_high_vec;
|
|
160
|
+
// for (; i + 16 <= n; i += 16) {
|
|
161
|
+
// int8x16_t a_vec = vld1q_s8(a + i);
|
|
162
|
+
// int8x16_t b_vec = vld1q_s8(b + i);
|
|
163
|
+
// int8x16x2_t y_w_vecs = vzipq_s8(a_vec, b_vec);
|
|
164
|
+
// int8x16_t x_vec = vcombine_s8(vget_low_s8(a_vec), vget_low_s8(b_vec));
|
|
165
|
+
// int8x16_t v_vec = vcombine_s8(vget_high_s8(a_vec), vget_high_s8(b_vec));
|
|
166
|
+
// products_low_vec = vmmlaq_s32(products_low_vec, x_vec, y_w_vecs.val[0]);
|
|
167
|
+
// products_high_vec = vmmlaq_s32(products_high_vec, v_vec, y_w_vecs.val[1]);
|
|
168
|
+
// }
|
|
169
|
+
// int32x4_t products_vec = vaddq_s32(products_high_vec, products_low_vec);
|
|
170
|
+
// nk_i32_t a2 = products_vec[0];
|
|
171
|
+
// nk_i32_t ab = products_vec[1];
|
|
172
|
+
// nk_i32_t b2 = products_vec[3];
|
|
173
|
+
//
|
|
174
|
+
// That solution is elegant, but it requires the additional `+i8mm` extension and is currently slower,
|
|
175
|
+
// at least on AWS Graviton 3.
|
|
176
|
+
int32x4_t dot_product_i32x4 = vdupq_n_s32(0);
|
|
177
|
+
int32x4_t a_norm_sq_i32x4 = vdupq_n_s32(0);
|
|
178
|
+
int32x4_t b_norm_sq_i32x4 = vdupq_n_s32(0);
|
|
179
|
+
for (; i + 16 <= n; i += 16) {
|
|
180
|
+
int8x16_t a_i8x16 = vld1q_s8(a + i);
|
|
181
|
+
int8x16_t b_i8x16 = vld1q_s8(b + i);
|
|
182
|
+
dot_product_i32x4 = vdotq_s32(dot_product_i32x4, a_i8x16, b_i8x16);
|
|
183
|
+
a_norm_sq_i32x4 = vdotq_s32(a_norm_sq_i32x4, a_i8x16, a_i8x16);
|
|
184
|
+
b_norm_sq_i32x4 = vdotq_s32(b_norm_sq_i32x4, b_i8x16, b_i8x16);
|
|
185
|
+
}
|
|
186
|
+
nk_i32_t dot_product_i32 = vaddvq_s32(dot_product_i32x4);
|
|
187
|
+
nk_i32_t a_norm_sq_i32 = vaddvq_s32(a_norm_sq_i32x4);
|
|
188
|
+
nk_i32_t b_norm_sq_i32 = vaddvq_s32(b_norm_sq_i32x4);
|
|
189
|
+
|
|
190
|
+
// Take care of the tail:
|
|
191
|
+
for (; i < n; ++i) {
|
|
192
|
+
nk_i32_t a_element_i32 = a[i], b_element_i32 = b[i];
|
|
193
|
+
dot_product_i32 += a_element_i32 * b_element_i32;
|
|
194
|
+
a_norm_sq_i32 += a_element_i32 * a_element_i32;
|
|
195
|
+
b_norm_sq_i32 += b_element_i32 * b_element_i32;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
*result = nk_angular_normalize_f32_neon_((nk_f32_t)dot_product_i32, (nk_f32_t)a_norm_sq_i32,
|
|
199
|
+
(nk_f32_t)b_norm_sq_i32);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
NK_PUBLIC void nk_sqeuclidean_u8_neonsdot(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
203
|
+
uint32x4_t distance_sq_u32x4 = vdupq_n_u32(0);
|
|
204
|
+
nk_size_t i = 0;
|
|
205
|
+
for (; i + 16 <= n; i += 16) {
|
|
206
|
+
uint8x16_t a_u8x16 = vld1q_u8(a + i);
|
|
207
|
+
uint8x16_t b_u8x16 = vld1q_u8(b + i);
|
|
208
|
+
uint8x16_t diff_u8x16 = vabdq_u8(a_u8x16, b_u8x16);
|
|
209
|
+
distance_sq_u32x4 = vdotq_u32(distance_sq_u32x4, diff_u8x16, diff_u8x16);
|
|
210
|
+
}
|
|
211
|
+
nk_u32_t distance_sq_u32 = vaddvq_u32(distance_sq_u32x4);
|
|
212
|
+
for (; i < n; ++i) {
|
|
213
|
+
nk_i32_t diff_i32 = (nk_i32_t)a[i] - b[i];
|
|
214
|
+
distance_sq_u32 += (nk_u32_t)(diff_i32 * diff_i32);
|
|
215
|
+
}
|
|
216
|
+
*result = distance_sq_u32;
|
|
217
|
+
}
|
|
218
|
+
NK_PUBLIC void nk_euclidean_u8_neonsdot(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
219
|
+
nk_u32_t d2;
|
|
220
|
+
nk_sqeuclidean_u8_neonsdot(a, b, n, &d2);
|
|
221
|
+
*result = nk_f32_sqrt_neon((nk_f32_t)d2);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
NK_PUBLIC void nk_angular_u8_neonsdot(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
225
|
+
|
|
226
|
+
nk_size_t i = 0;
|
|
227
|
+
uint32x4_t ab_vec = vdupq_n_u32(0);
|
|
228
|
+
uint32x4_t a2_vec = vdupq_n_u32(0);
|
|
229
|
+
uint32x4_t b2_vec = vdupq_n_u32(0);
|
|
230
|
+
for (; i + 16 <= n; i += 16) {
|
|
231
|
+
uint8x16_t a_vec = vld1q_u8(a + i);
|
|
232
|
+
uint8x16_t b_vec = vld1q_u8(b + i);
|
|
233
|
+
ab_vec = vdotq_u32(ab_vec, a_vec, b_vec);
|
|
234
|
+
a2_vec = vdotq_u32(a2_vec, a_vec, a_vec);
|
|
235
|
+
b2_vec = vdotq_u32(b2_vec, b_vec, b_vec);
|
|
236
|
+
}
|
|
237
|
+
nk_u32_t ab = vaddvq_u32(ab_vec);
|
|
238
|
+
nk_u32_t a2 = vaddvq_u32(a2_vec);
|
|
239
|
+
nk_u32_t b2 = vaddvq_u32(b2_vec);
|
|
240
|
+
|
|
241
|
+
// Take care of the tail:
|
|
242
|
+
for (; i < n; ++i) {
|
|
243
|
+
nk_u32_t ai = a[i], bi = b[i];
|
|
244
|
+
ab += ai * bi, a2 += ai * ai, b2 += bi * bi;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
*result = nk_angular_normalize_f32_neon_((nk_f32_t)ab, (nk_f32_t)a2, (nk_f32_t)b2);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
NK_PUBLIC void nk_sqeuclidean_i4_neonsdot(nk_i4x2_t const *a, nk_i4x2_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
251
|
+
n = nk_size_round_up_to_multiple_(n, 2);
|
|
252
|
+
nk_size_t n_bytes = n / 2;
|
|
253
|
+
uint32x4_t d2_u32x4 = vdupq_n_u32(0);
|
|
254
|
+
uint8x16_t a_u8x16, b_u8x16;
|
|
255
|
+
|
|
256
|
+
nk_sqeuclidean_i4_neonsdot_cycle:
|
|
257
|
+
if (n_bytes < 16) {
|
|
258
|
+
nk_b128_vec_t a_vec, b_vec;
|
|
259
|
+
nk_partial_load_b4x32_serial_(a, &a_vec, n_bytes * 2);
|
|
260
|
+
nk_partial_load_b4x32_serial_(b, &b_vec, n_bytes * 2);
|
|
261
|
+
a_u8x16 = a_vec.u8x16;
|
|
262
|
+
b_u8x16 = b_vec.u8x16;
|
|
263
|
+
n_bytes = 0;
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
a_u8x16 = vld1q_u8((nk_u8_t const *)a);
|
|
267
|
+
b_u8x16 = vld1q_u8((nk_u8_t const *)b);
|
|
268
|
+
a += 16, b += 16, n_bytes -= 16;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Sign-extend low nibbles, compute |a-b|, reinterpret as unsigned for UDOT squaring
|
|
272
|
+
int8x16_t a_low_i8x16 = vshrq_n_s8(vshlq_n_s8(vreinterpretq_s8_u8(a_u8x16), 4), 4);
|
|
273
|
+
int8x16_t b_low_i8x16 = vshrq_n_s8(vshlq_n_s8(vreinterpretq_s8_u8(b_u8x16), 4), 4);
|
|
274
|
+
int8x16_t a_high_i8x16 = vshrq_n_s8(vreinterpretq_s8_u8(a_u8x16), 4);
|
|
275
|
+
int8x16_t b_high_i8x16 = vshrq_n_s8(vreinterpretq_s8_u8(b_u8x16), 4);
|
|
276
|
+
|
|
277
|
+
uint8x16_t diff_low_u8x16 = vreinterpretq_u8_s8(vabdq_s8(a_low_i8x16, b_low_i8x16));
|
|
278
|
+
uint8x16_t diff_high_u8x16 = vreinterpretq_u8_s8(vabdq_s8(a_high_i8x16, b_high_i8x16));
|
|
279
|
+
d2_u32x4 = vdotq_u32(d2_u32x4, diff_low_u8x16, diff_low_u8x16);
|
|
280
|
+
d2_u32x4 = vdotq_u32(d2_u32x4, diff_high_u8x16, diff_high_u8x16);
|
|
281
|
+
|
|
282
|
+
if (n_bytes) goto nk_sqeuclidean_i4_neonsdot_cycle;
|
|
283
|
+
*result = vaddvq_u32(d2_u32x4);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
NK_PUBLIC void nk_euclidean_i4_neonsdot(nk_i4x2_t const *a, nk_i4x2_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
287
|
+
nk_u32_t d2;
|
|
288
|
+
nk_sqeuclidean_i4_neonsdot(a, b, n, &d2);
|
|
289
|
+
*result = nk_f32_sqrt_neon((nk_f32_t)d2);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
NK_PUBLIC void nk_angular_i4_neonsdot(nk_i4x2_t const *a, nk_i4x2_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
293
|
+
n = nk_size_round_up_to_multiple_(n, 2);
|
|
294
|
+
nk_size_t n_bytes = n / 2;
|
|
295
|
+
int32x4_t ab_i32x4 = vdupq_n_s32(0);
|
|
296
|
+
int32x4_t a2_i32x4 = vdupq_n_s32(0);
|
|
297
|
+
int32x4_t b2_i32x4 = vdupq_n_s32(0);
|
|
298
|
+
uint8x16_t a_u8x16, b_u8x16;
|
|
299
|
+
|
|
300
|
+
nk_angular_i4_neonsdot_cycle:
|
|
301
|
+
if (n_bytes < 16) {
|
|
302
|
+
nk_b128_vec_t a_vec, b_vec;
|
|
303
|
+
nk_partial_load_b4x32_serial_(a, &a_vec, n_bytes * 2);
|
|
304
|
+
nk_partial_load_b4x32_serial_(b, &b_vec, n_bytes * 2);
|
|
305
|
+
a_u8x16 = a_vec.u8x16;
|
|
306
|
+
b_u8x16 = b_vec.u8x16;
|
|
307
|
+
n_bytes = 0;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
a_u8x16 = vld1q_u8((nk_u8_t const *)a);
|
|
311
|
+
b_u8x16 = vld1q_u8((nk_u8_t const *)b);
|
|
312
|
+
a += 16, b += 16, n_bytes -= 16;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
int8x16_t a_low_i8x16 = vshrq_n_s8(vshlq_n_s8(vreinterpretq_s8_u8(a_u8x16), 4), 4);
|
|
316
|
+
int8x16_t b_low_i8x16 = vshrq_n_s8(vshlq_n_s8(vreinterpretq_s8_u8(b_u8x16), 4), 4);
|
|
317
|
+
int8x16_t a_high_i8x16 = vshrq_n_s8(vreinterpretq_s8_u8(a_u8x16), 4);
|
|
318
|
+
int8x16_t b_high_i8x16 = vshrq_n_s8(vreinterpretq_s8_u8(b_u8x16), 4);
|
|
319
|
+
|
|
320
|
+
ab_i32x4 = vdotq_s32(ab_i32x4, a_low_i8x16, b_low_i8x16);
|
|
321
|
+
ab_i32x4 = vdotq_s32(ab_i32x4, a_high_i8x16, b_high_i8x16);
|
|
322
|
+
a2_i32x4 = vdotq_s32(a2_i32x4, a_low_i8x16, a_low_i8x16);
|
|
323
|
+
a2_i32x4 = vdotq_s32(a2_i32x4, a_high_i8x16, a_high_i8x16);
|
|
324
|
+
b2_i32x4 = vdotq_s32(b2_i32x4, b_low_i8x16, b_low_i8x16);
|
|
325
|
+
b2_i32x4 = vdotq_s32(b2_i32x4, b_high_i8x16, b_high_i8x16);
|
|
326
|
+
|
|
327
|
+
if (n_bytes) goto nk_angular_i4_neonsdot_cycle;
|
|
328
|
+
|
|
329
|
+
*result = nk_angular_normalize_f32_neon_((nk_f32_t)vaddvq_s32(ab_i32x4), (nk_f32_t)vaddvq_s32(a2_i32x4),
|
|
330
|
+
(nk_f32_t)vaddvq_s32(b2_i32x4));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
NK_PUBLIC void nk_sqeuclidean_u4_neonsdot(nk_u4x2_t const *a, nk_u4x2_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
334
|
+
n = nk_size_round_up_to_multiple_(n, 2);
|
|
335
|
+
nk_size_t n_bytes = n / 2;
|
|
336
|
+
uint8x16_t const nibble_mask_u8x16 = vdupq_n_u8(0x0F);
|
|
337
|
+
uint32x4_t d2_u32x4 = vdupq_n_u32(0);
|
|
338
|
+
uint8x16_t a_u8x16, b_u8x16;
|
|
339
|
+
|
|
340
|
+
nk_sqeuclidean_u4_neonsdot_cycle:
|
|
341
|
+
if (n_bytes < 16) {
|
|
342
|
+
nk_b128_vec_t a_vec, b_vec;
|
|
343
|
+
nk_partial_load_b4x32_serial_(a, &a_vec, n_bytes * 2);
|
|
344
|
+
nk_partial_load_b4x32_serial_(b, &b_vec, n_bytes * 2);
|
|
345
|
+
a_u8x16 = a_vec.u8x16;
|
|
346
|
+
b_u8x16 = b_vec.u8x16;
|
|
347
|
+
n_bytes = 0;
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
a_u8x16 = vld1q_u8((nk_u8_t const *)a);
|
|
351
|
+
b_u8x16 = vld1q_u8((nk_u8_t const *)b);
|
|
352
|
+
a += 16, b += 16, n_bytes -= 16;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
uint8x16_t a_low_u8x16 = vandq_u8(a_u8x16, nibble_mask_u8x16);
|
|
356
|
+
uint8x16_t a_high_u8x16 = vshrq_n_u8(a_u8x16, 4);
|
|
357
|
+
uint8x16_t b_low_u8x16 = vandq_u8(b_u8x16, nibble_mask_u8x16);
|
|
358
|
+
uint8x16_t b_high_u8x16 = vshrq_n_u8(b_u8x16, 4);
|
|
359
|
+
|
|
360
|
+
uint8x16_t diff_low_u8x16 = vabdq_u8(a_low_u8x16, b_low_u8x16);
|
|
361
|
+
uint8x16_t diff_high_u8x16 = vabdq_u8(a_high_u8x16, b_high_u8x16);
|
|
362
|
+
d2_u32x4 = vdotq_u32(d2_u32x4, diff_low_u8x16, diff_low_u8x16);
|
|
363
|
+
d2_u32x4 = vdotq_u32(d2_u32x4, diff_high_u8x16, diff_high_u8x16);
|
|
364
|
+
|
|
365
|
+
if (n_bytes) goto nk_sqeuclidean_u4_neonsdot_cycle;
|
|
366
|
+
*result = vaddvq_u32(d2_u32x4);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
NK_PUBLIC void nk_euclidean_u4_neonsdot(nk_u4x2_t const *a, nk_u4x2_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
370
|
+
nk_u32_t d2;
|
|
371
|
+
nk_sqeuclidean_u4_neonsdot(a, b, n, &d2);
|
|
372
|
+
*result = nk_f32_sqrt_neon((nk_f32_t)d2);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
NK_PUBLIC void nk_angular_u4_neonsdot(nk_u4x2_t const *a, nk_u4x2_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
376
|
+
n = nk_size_round_up_to_multiple_(n, 2);
|
|
377
|
+
nk_size_t n_bytes = n / 2;
|
|
378
|
+
uint8x16_t const nibble_mask_u8x16 = vdupq_n_u8(0x0F);
|
|
379
|
+
uint32x4_t ab_u32x4 = vdupq_n_u32(0);
|
|
380
|
+
uint32x4_t a2_u32x4 = vdupq_n_u32(0);
|
|
381
|
+
uint32x4_t b2_u32x4 = vdupq_n_u32(0);
|
|
382
|
+
uint8x16_t a_u8x16, b_u8x16;
|
|
383
|
+
|
|
384
|
+
nk_angular_u4_neonsdot_cycle:
|
|
385
|
+
if (n_bytes < 16) {
|
|
386
|
+
nk_b128_vec_t a_vec, b_vec;
|
|
387
|
+
nk_partial_load_b4x32_serial_(a, &a_vec, n_bytes * 2);
|
|
388
|
+
nk_partial_load_b4x32_serial_(b, &b_vec, n_bytes * 2);
|
|
389
|
+
a_u8x16 = a_vec.u8x16;
|
|
390
|
+
b_u8x16 = b_vec.u8x16;
|
|
391
|
+
n_bytes = 0;
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
a_u8x16 = vld1q_u8((nk_u8_t const *)a);
|
|
395
|
+
b_u8x16 = vld1q_u8((nk_u8_t const *)b);
|
|
396
|
+
a += 16, b += 16, n_bytes -= 16;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
uint8x16_t a_low_u8x16 = vandq_u8(a_u8x16, nibble_mask_u8x16);
|
|
400
|
+
uint8x16_t a_high_u8x16 = vshrq_n_u8(a_u8x16, 4);
|
|
401
|
+
uint8x16_t b_low_u8x16 = vandq_u8(b_u8x16, nibble_mask_u8x16);
|
|
402
|
+
uint8x16_t b_high_u8x16 = vshrq_n_u8(b_u8x16, 4);
|
|
403
|
+
|
|
404
|
+
ab_u32x4 = vdotq_u32(ab_u32x4, a_low_u8x16, b_low_u8x16);
|
|
405
|
+
ab_u32x4 = vdotq_u32(ab_u32x4, a_high_u8x16, b_high_u8x16);
|
|
406
|
+
a2_u32x4 = vdotq_u32(a2_u32x4, a_low_u8x16, a_low_u8x16);
|
|
407
|
+
a2_u32x4 = vdotq_u32(a2_u32x4, a_high_u8x16, a_high_u8x16);
|
|
408
|
+
b2_u32x4 = vdotq_u32(b2_u32x4, b_low_u8x16, b_low_u8x16);
|
|
409
|
+
b2_u32x4 = vdotq_u32(b2_u32x4, b_high_u8x16, b_high_u8x16);
|
|
410
|
+
|
|
411
|
+
if (n_bytes) goto nk_angular_u4_neonsdot_cycle;
|
|
412
|
+
|
|
413
|
+
*result = nk_angular_normalize_f32_neon_((nk_f32_t)vaddvq_u32(ab_u32x4), (nk_f32_t)vaddvq_u32(a2_u32x4),
|
|
414
|
+
(nk_f32_t)vaddvq_u32(b2_u32x4));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
#if defined(__clang__)
|
|
418
|
+
#pragma clang attribute pop
|
|
419
|
+
#elif defined(__GNUC__)
|
|
420
|
+
#pragma GCC pop_options
|
|
421
|
+
#endif
|
|
422
|
+
|
|
423
|
+
#if defined(__cplusplus)
|
|
424
|
+
} // extern "C"
|
|
425
|
+
#endif
|
|
426
|
+
|
|
427
|
+
#endif // NK_TARGET_NEONSDOT
|
|
428
|
+
#endif // NK_TARGET_ARM64_
|
|
429
|
+
#endif // NK_SPATIAL_NEONSDOT_H
|