usearch 2.21.3 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/binding.gyp +15 -37
- package/c/CMakeLists.txt +4 -5
- package/c/README.md +7 -7
- package/c/lib.cpp +32 -14
- package/c/test.c +83 -1
- package/c/usearch.h +24 -3
- package/cpp/CMakeLists.txt +4 -0
- package/cpp/README.md +5 -5
- package/cpp/bench.cpp +97 -116
- package/cpp/test.cpp +117 -20
- package/include/usearch/index.hpp +235 -52
- package/include/usearch/index_dense.hpp +105 -40
- package/include/usearch/index_plugins.hpp +1387 -204
- package/javascript/dist/cjs/usearch.d.ts +8 -3
- package/javascript/dist/cjs/usearch.js +12 -4
- package/javascript/dist/esm/usearch.d.ts +8 -3
- package/javascript/dist/esm/usearch.js +12 -4
- package/javascript/lib.cpp +17 -0
- package/javascript/usearch.ts +14 -6
- package/numkong/.clang-tidy +30 -0
- package/{simsimd → numkong}/.cmake-format.py +18 -0
- package/numkong/.editorconfig +12 -0
- package/numkong/.git-blame-ignore-revs +123 -0
- package/numkong/.mailmap +15 -0
- package/numkong/.spi.yml +11 -0
- package/numkong/.swift-format +14 -0
- package/numkong/CITATION.cff +81 -0
- package/numkong/CONTRIBUTING.md +500 -0
- package/numkong/Cargo.toml +54 -0
- package/numkong/MANIFEST.in +8 -0
- package/numkong/Package.swift +84 -0
- package/numkong/README.md +569 -0
- package/numkong/bench/README.md +217 -0
- package/numkong/bench/bench-browser.html +323 -0
- package/numkong/bench/bench.cpp +344 -0
- package/numkong/bench/bench.hpp +816 -0
- package/numkong/bench/bench.js +148 -0
- package/numkong/bench/bench.mjs +616 -0
- package/numkong/bench/bench_attention.cpp +113 -0
- package/numkong/bench/bench_cast.cpp +264 -0
- package/numkong/bench/bench_cross_amx.cpp +62 -0
- package/numkong/bench/bench_cross_arm.cpp +245 -0
- package/numkong/bench/bench_cross_blas.cpp +309 -0
- package/numkong/bench/bench_cross_loongarch.cpp +106 -0
- package/numkong/bench/bench_cross_power.cpp +84 -0
- package/numkong/bench/bench_cross_rvv.cpp +121 -0
- package/numkong/bench/bench_cross_serial.cpp +151 -0
- package/numkong/bench/bench_cross_sme.cpp +163 -0
- package/numkong/bench/bench_cross_wasm.cpp +142 -0
- package/numkong/bench/bench_cross_x86.cpp +455 -0
- package/numkong/bench/bench_curved.cpp +210 -0
- package/numkong/bench/bench_dot.cpp +315 -0
- package/numkong/bench/bench_each.cpp +503 -0
- package/numkong/bench/bench_geospatial.cpp +112 -0
- package/numkong/bench/bench_maxsim.cpp +154 -0
- package/numkong/bench/bench_mesh.cpp +148 -0
- package/numkong/bench/bench_probability.cpp +60 -0
- package/numkong/bench/bench_reduce.cpp +371 -0
- package/numkong/bench/bench_set.cpp +73 -0
- package/numkong/bench/bench_sparse.cpp +198 -0
- package/numkong/bench/bench_spatial.cpp +347 -0
- package/numkong/bench/bench_trigonometry.cpp +137 -0
- package/numkong/bench/swift/Bench.swift +506 -0
- package/numkong/binding.gyp +169 -0
- package/numkong/build.rs +484 -0
- package/numkong/c/dispatch.h +512 -0
- package/numkong/c/dispatch_bf16.c +447 -0
- package/numkong/c/dispatch_bf16c.c +52 -0
- package/numkong/c/dispatch_e2m3.c +296 -0
- package/numkong/c/dispatch_e3m2.c +284 -0
- package/numkong/c/dispatch_e4m3.c +318 -0
- package/numkong/c/dispatch_e5m2.c +316 -0
- package/numkong/c/dispatch_f16.c +452 -0
- package/numkong/c/dispatch_f16c.c +58 -0
- package/numkong/c/dispatch_f32.c +434 -0
- package/numkong/c/dispatch_f32c.c +99 -0
- package/numkong/c/dispatch_f64.c +348 -0
- package/numkong/c/dispatch_f64c.c +98 -0
- package/numkong/c/dispatch_i16.c +96 -0
- package/numkong/c/dispatch_i32.c +89 -0
- package/numkong/c/dispatch_i4.c +153 -0
- package/numkong/c/dispatch_i64.c +86 -0
- package/numkong/c/dispatch_i8.c +348 -0
- package/numkong/c/dispatch_other.c +348 -0
- package/numkong/c/dispatch_u1.c +193 -0
- package/numkong/c/dispatch_u16.c +124 -0
- package/numkong/c/dispatch_u32.c +118 -0
- package/numkong/c/dispatch_u4.c +153 -0
- package/numkong/c/dispatch_u64.c +102 -0
- package/numkong/c/dispatch_u8.c +364 -0
- package/numkong/c/numkong.c +940 -0
- package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
- package/numkong/cmake/nk_isa_probe.cmake +90 -0
- package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
- package/numkong/cmake/nk_math_lib.cmake +46 -0
- package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
- package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
- package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
- package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
- package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
- package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
- package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
- package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
- package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
- package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
- package/numkong/cmake/toolchain-wasi.cmake +77 -0
- package/numkong/cmake/toolchain-wasm.cmake +70 -0
- package/numkong/cmake/toolchain-wasm64.cmake +62 -0
- package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
- package/numkong/include/README.md +643 -0
- package/numkong/include/module.modulemap +129 -0
- package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
- package/numkong/include/numkong/attention/sme.h +2075 -0
- package/numkong/include/numkong/attention.h +49 -0
- package/numkong/include/numkong/capabilities.h +930 -0
- package/numkong/include/numkong/cast/README.md +262 -0
- package/numkong/include/numkong/cast/diamond.h +64 -0
- package/numkong/include/numkong/cast/haswell.h +823 -0
- package/numkong/include/numkong/cast/icelake.h +475 -0
- package/numkong/include/numkong/cast/loongsonasx.h +252 -0
- package/numkong/include/numkong/cast/neon.h +1174 -0
- package/numkong/include/numkong/cast/powervsx.h +449 -0
- package/numkong/include/numkong/cast/rvv.h +970 -0
- package/numkong/include/numkong/cast/sapphire.h +262 -0
- package/numkong/include/numkong/cast/serial.h +2336 -0
- package/numkong/include/numkong/cast/skylake.h +915 -0
- package/numkong/include/numkong/cast/v128relaxed.h +537 -0
- package/numkong/include/numkong/cast.h +254 -0
- package/numkong/include/numkong/cast.hpp +44 -0
- package/numkong/include/numkong/curved/README.md +223 -0
- package/numkong/include/numkong/curved/genoa.h +182 -0
- package/numkong/include/numkong/curved/haswell.h +276 -0
- package/numkong/include/numkong/curved/neon.h +329 -0
- package/numkong/include/numkong/curved/neonbfdot.h +211 -0
- package/numkong/include/numkong/curved/rvv.h +305 -0
- package/numkong/include/numkong/curved/serial.h +207 -0
- package/numkong/include/numkong/curved/skylake.h +457 -0
- package/numkong/include/numkong/curved/smef64.h +530 -0
- package/numkong/include/numkong/curved.h +513 -0
- package/numkong/include/numkong/curved.hpp +144 -0
- package/numkong/include/numkong/dot/README.md +442 -0
- package/numkong/include/numkong/dot/alder.h +563 -0
- package/numkong/include/numkong/dot/diamond.h +158 -0
- package/numkong/include/numkong/dot/genoa.h +289 -0
- package/numkong/include/numkong/dot/haswell.h +1723 -0
- package/numkong/include/numkong/dot/icelake.h +997 -0
- package/numkong/include/numkong/dot/loongsonasx.h +671 -0
- package/numkong/include/numkong/dot/neon.h +869 -0
- package/numkong/include/numkong/dot/neonbfdot.h +243 -0
- package/numkong/include/numkong/dot/neonfhm.h +358 -0
- package/numkong/include/numkong/dot/neonfp8.h +323 -0
- package/numkong/include/numkong/dot/neonsdot.h +622 -0
- package/numkong/include/numkong/dot/powervsx.h +752 -0
- package/numkong/include/numkong/dot/rvv.h +722 -0
- package/numkong/include/numkong/dot/rvvbb.h +72 -0
- package/numkong/include/numkong/dot/rvvbf16.h +123 -0
- package/numkong/include/numkong/dot/rvvhalf.h +129 -0
- package/numkong/include/numkong/dot/sapphire.h +141 -0
- package/numkong/include/numkong/dot/serial.h +874 -0
- package/numkong/include/numkong/dot/sierra.h +405 -0
- package/numkong/include/numkong/dot/skylake.h +1116 -0
- package/numkong/include/numkong/dot/sve.h +420 -0
- package/numkong/include/numkong/dot/svebfdot.h +75 -0
- package/numkong/include/numkong/dot/svehalf.h +168 -0
- package/numkong/include/numkong/dot/svesdot.h +90 -0
- package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
- package/numkong/include/numkong/dot.h +1136 -0
- package/numkong/include/numkong/dot.hpp +94 -0
- package/numkong/include/numkong/dots/README.md +496 -0
- package/numkong/include/numkong/dots/alder.h +117 -0
- package/numkong/include/numkong/dots/diamond.h +86 -0
- package/numkong/include/numkong/dots/genoa.h +100 -0
- package/numkong/include/numkong/dots/graniteamx.h +733 -0
- package/numkong/include/numkong/dots/haswell.h +310 -0
- package/numkong/include/numkong/dots/icelake.h +180 -0
- package/numkong/include/numkong/dots/loongsonasx.h +176 -0
- package/numkong/include/numkong/dots/neon.h +123 -0
- package/numkong/include/numkong/dots/neonbfdot.h +59 -0
- package/numkong/include/numkong/dots/neonfhm.h +96 -0
- package/numkong/include/numkong/dots/neonfp8.h +99 -0
- package/numkong/include/numkong/dots/neonsdot.h +144 -0
- package/numkong/include/numkong/dots/powervsx.h +194 -0
- package/numkong/include/numkong/dots/rvv.h +2593 -0
- package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
- package/numkong/include/numkong/dots/serial.h +2867 -0
- package/numkong/include/numkong/dots/sierra.h +100 -0
- package/numkong/include/numkong/dots/skylake.h +207 -0
- package/numkong/include/numkong/dots/sme.h +5041 -0
- package/numkong/include/numkong/dots/smebi32.h +477 -0
- package/numkong/include/numkong/dots/smef64.h +1328 -0
- package/numkong/include/numkong/dots/smehalf.h +47 -0
- package/numkong/include/numkong/dots/v128relaxed.h +317 -0
- package/numkong/include/numkong/dots.h +3110 -0
- package/numkong/include/numkong/dots.hpp +641 -0
- package/numkong/include/numkong/each/README.md +465 -0
- package/numkong/include/numkong/each/haswell.h +1658 -0
- package/numkong/include/numkong/each/icelake.h +272 -0
- package/numkong/include/numkong/each/neon.h +1138 -0
- package/numkong/include/numkong/each/neonbfdot.h +211 -0
- package/numkong/include/numkong/each/neonhalf.h +318 -0
- package/numkong/include/numkong/each/rvv.h +1121 -0
- package/numkong/include/numkong/each/sapphire.h +343 -0
- package/numkong/include/numkong/each/serial.h +282 -0
- package/numkong/include/numkong/each/skylake.h +1562 -0
- package/numkong/include/numkong/each/v128relaxed.h +562 -0
- package/numkong/include/numkong/each.h +2232 -0
- package/numkong/include/numkong/each.hpp +434 -0
- package/numkong/include/numkong/geospatial/README.md +147 -0
- package/numkong/include/numkong/geospatial/haswell.h +633 -0
- package/numkong/include/numkong/geospatial/neon.h +615 -0
- package/numkong/include/numkong/geospatial/rvv.h +701 -0
- package/numkong/include/numkong/geospatial/serial.h +309 -0
- package/numkong/include/numkong/geospatial/skylake.h +613 -0
- package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
- package/numkong/include/numkong/geospatial.h +453 -0
- package/numkong/include/numkong/geospatial.hpp +235 -0
- package/numkong/include/numkong/matrix.hpp +336 -0
- package/numkong/include/numkong/maxsim/README.md +187 -0
- package/numkong/include/numkong/maxsim/alder.h +511 -0
- package/numkong/include/numkong/maxsim/genoa.h +115 -0
- package/numkong/include/numkong/maxsim/haswell.h +553 -0
- package/numkong/include/numkong/maxsim/icelake.h +480 -0
- package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
- package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
- package/numkong/include/numkong/maxsim/serial.h +490 -0
- package/numkong/include/numkong/maxsim/sme.h +993 -0
- package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
- package/numkong/include/numkong/maxsim.h +571 -0
- package/numkong/include/numkong/maxsim.hpp +133 -0
- package/numkong/include/numkong/mesh/README.md +219 -0
- package/numkong/include/numkong/mesh/haswell.h +2013 -0
- package/numkong/include/numkong/mesh/neon.h +1821 -0
- package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
- package/numkong/include/numkong/mesh/rvv.h +936 -0
- package/numkong/include/numkong/mesh/serial.h +721 -0
- package/numkong/include/numkong/mesh/skylake.h +2344 -0
- package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
- package/numkong/include/numkong/mesh.h +666 -0
- package/numkong/include/numkong/mesh.hpp +701 -0
- package/numkong/include/numkong/numkong.h +78 -0
- package/numkong/include/numkong/numkong.hpp +58 -0
- package/numkong/include/numkong/probability/README.md +177 -0
- package/numkong/include/numkong/probability/haswell.h +267 -0
- package/numkong/include/numkong/probability/neon.h +255 -0
- package/numkong/include/numkong/probability/rvv.h +414 -0
- package/numkong/include/numkong/probability/serial.h +181 -0
- package/numkong/include/numkong/probability/skylake.h +324 -0
- package/numkong/include/numkong/probability.h +380 -0
- package/numkong/include/numkong/probability.hpp +120 -0
- package/numkong/include/numkong/random.h +50 -0
- package/numkong/include/numkong/random.hpp +285 -0
- package/numkong/include/numkong/reduce/README.md +552 -0
- package/numkong/include/numkong/reduce/alder.h +636 -0
- package/numkong/include/numkong/reduce/genoa.h +201 -0
- package/numkong/include/numkong/reduce/haswell.h +3785 -0
- package/numkong/include/numkong/reduce/icelake.h +549 -0
- package/numkong/include/numkong/reduce/neon.h +3980 -0
- package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
- package/numkong/include/numkong/reduce/neonfhm.h +293 -0
- package/numkong/include/numkong/reduce/neonsdot.h +357 -0
- package/numkong/include/numkong/reduce/rvv.h +3533 -0
- package/numkong/include/numkong/reduce/serial.h +753 -0
- package/numkong/include/numkong/reduce/sierra.h +338 -0
- package/numkong/include/numkong/reduce/skylake.h +3794 -0
- package/numkong/include/numkong/reduce/sve.h +52 -0
- package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
- package/numkong/include/numkong/reduce.h +1582 -0
- package/numkong/include/numkong/reduce.hpp +778 -0
- package/numkong/include/numkong/scalar/README.md +89 -0
- package/numkong/include/numkong/scalar/haswell.h +122 -0
- package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
- package/numkong/include/numkong/scalar/neon.h +122 -0
- package/numkong/include/numkong/scalar/neonhalf.h +70 -0
- package/numkong/include/numkong/scalar/powervsx.h +96 -0
- package/numkong/include/numkong/scalar/rvv.h +211 -0
- package/numkong/include/numkong/scalar/sapphire.h +74 -0
- package/numkong/include/numkong/scalar/serial.h +332 -0
- package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
- package/numkong/include/numkong/scalar.h +696 -0
- package/numkong/include/numkong/set/README.md +179 -0
- package/numkong/include/numkong/set/haswell.h +334 -0
- package/numkong/include/numkong/set/icelake.h +485 -0
- package/numkong/include/numkong/set/loongsonasx.h +181 -0
- package/numkong/include/numkong/set/neon.h +363 -0
- package/numkong/include/numkong/set/powervsx.h +326 -0
- package/numkong/include/numkong/set/rvv.h +226 -0
- package/numkong/include/numkong/set/rvvbb.h +117 -0
- package/numkong/include/numkong/set/serial.h +174 -0
- package/numkong/include/numkong/set/sve.h +187 -0
- package/numkong/include/numkong/set/v128relaxed.h +240 -0
- package/numkong/include/numkong/set.h +471 -0
- package/numkong/include/numkong/set.hpp +114 -0
- package/numkong/include/numkong/sets/README.md +149 -0
- package/numkong/include/numkong/sets/haswell.h +63 -0
- package/numkong/include/numkong/sets/icelake.h +66 -0
- package/numkong/include/numkong/sets/loongsonasx.h +52 -0
- package/numkong/include/numkong/sets/neon.h +61 -0
- package/numkong/include/numkong/sets/powervsx.h +65 -0
- package/numkong/include/numkong/sets/serial.h +43 -0
- package/numkong/include/numkong/sets/smebi32.h +1135 -0
- package/numkong/include/numkong/sets/v128relaxed.h +58 -0
- package/numkong/include/numkong/sets.h +382 -0
- package/numkong/include/numkong/sparse/README.md +156 -0
- package/numkong/include/numkong/sparse/icelake.h +463 -0
- package/numkong/include/numkong/sparse/neon.h +288 -0
- package/numkong/include/numkong/sparse/serial.h +117 -0
- package/numkong/include/numkong/sparse/sve2.h +504 -0
- package/numkong/include/numkong/sparse/turin.h +322 -0
- package/numkong/include/numkong/sparse.h +363 -0
- package/numkong/include/numkong/sparse.hpp +113 -0
- package/numkong/include/numkong/spatial/README.md +439 -0
- package/numkong/include/numkong/spatial/alder.h +604 -0
- package/numkong/include/numkong/spatial/diamond.h +240 -0
- package/numkong/include/numkong/spatial/genoa.h +222 -0
- package/numkong/include/numkong/spatial/haswell.h +979 -0
- package/numkong/include/numkong/spatial/icelake.h +1067 -0
- package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
- package/numkong/include/numkong/spatial/neon.h +846 -0
- package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
- package/numkong/include/numkong/spatial/neonfp8.h +258 -0
- package/numkong/include/numkong/spatial/neonsdot.h +429 -0
- package/numkong/include/numkong/spatial/powervsx.h +738 -0
- package/numkong/include/numkong/spatial/rvv.h +991 -0
- package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
- package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
- package/numkong/include/numkong/spatial/serial.h +347 -0
- package/numkong/include/numkong/spatial/sierra.h +516 -0
- package/numkong/include/numkong/spatial/skylake.h +605 -0
- package/numkong/include/numkong/spatial/sve.h +246 -0
- package/numkong/include/numkong/spatial/svebfdot.h +125 -0
- package/numkong/include/numkong/spatial/svehalf.h +136 -0
- package/numkong/include/numkong/spatial/svesdot.h +143 -0
- package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
- package/numkong/include/numkong/spatial.h +1681 -0
- package/numkong/include/numkong/spatial.hpp +183 -0
- package/numkong/include/numkong/spatials/README.md +580 -0
- package/numkong/include/numkong/spatials/alder.h +94 -0
- package/numkong/include/numkong/spatials/diamond.h +82 -0
- package/numkong/include/numkong/spatials/genoa.h +94 -0
- package/numkong/include/numkong/spatials/graniteamx.h +173 -0
- package/numkong/include/numkong/spatials/haswell.h +219 -0
- package/numkong/include/numkong/spatials/icelake.h +113 -0
- package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
- package/numkong/include/numkong/spatials/neon.h +109 -0
- package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
- package/numkong/include/numkong/spatials/neonfhm.h +92 -0
- package/numkong/include/numkong/spatials/neonfp8.h +111 -0
- package/numkong/include/numkong/spatials/neonsdot.h +143 -0
- package/numkong/include/numkong/spatials/powervsx.h +153 -0
- package/numkong/include/numkong/spatials/rvv.h +1976 -0
- package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
- package/numkong/include/numkong/spatials/serial.h +248 -0
- package/numkong/include/numkong/spatials/sierra.h +96 -0
- package/numkong/include/numkong/spatials/skylake.h +184 -0
- package/numkong/include/numkong/spatials/sme.h +1927 -0
- package/numkong/include/numkong/spatials/smef64.h +483 -0
- package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
- package/numkong/include/numkong/spatials.h +3374 -0
- package/numkong/include/numkong/spatials.hpp +509 -0
- package/numkong/include/numkong/tensor.hpp +1981 -0
- package/numkong/include/numkong/trigonometry/README.md +184 -0
- package/numkong/include/numkong/trigonometry/haswell.h +653 -0
- package/numkong/include/numkong/trigonometry/neon.h +638 -0
- package/numkong/include/numkong/trigonometry/rvv.h +700 -0
- package/numkong/include/numkong/trigonometry/serial.h +703 -0
- package/numkong/include/numkong/trigonometry/skylake.h +725 -0
- package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
- package/numkong/include/numkong/trigonometry.h +467 -0
- package/numkong/include/numkong/trigonometry.hpp +166 -0
- package/numkong/include/numkong/types.h +1695 -0
- package/numkong/include/numkong/types.hpp +6027 -0
- package/numkong/include/numkong/vector.hpp +766 -0
- package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
- package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
- package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
- package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
- package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
- package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
- package/numkong/javascript/README.md +254 -0
- package/numkong/javascript/node-gyp-build.d.ts +4 -0
- package/numkong/javascript/numkong-browser.ts +40 -0
- package/numkong/javascript/numkong-wasm.ts +750 -0
- package/numkong/javascript/numkong.c +712 -0
- package/numkong/javascript/numkong.ts +613 -0
- package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
- package/numkong/javascript/tsconfig-cjs.json +13 -0
- package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
- package/numkong/javascript/types.ts +784 -0
- package/numkong/numkong.gypi +104 -0
- package/numkong/package.json +108 -0
- package/numkong/probes/arm_neon.c +8 -0
- package/numkong/probes/arm_neon_bfdot.c +9 -0
- package/numkong/probes/arm_neon_fhm.c +9 -0
- package/numkong/probes/arm_neon_half.c +8 -0
- package/numkong/probes/arm_neon_sdot.c +9 -0
- package/numkong/probes/arm_neonfp8.c +9 -0
- package/numkong/probes/arm_sme.c +16 -0
- package/numkong/probes/arm_sme2.c +16 -0
- package/numkong/probes/arm_sme2p1.c +16 -0
- package/numkong/probes/arm_sme_bf16.c +16 -0
- package/numkong/probes/arm_sme_bi32.c +16 -0
- package/numkong/probes/arm_sme_f64.c +16 -0
- package/numkong/probes/arm_sme_fa64.c +14 -0
- package/numkong/probes/arm_sme_half.c +16 -0
- package/numkong/probes/arm_sme_lut2.c +15 -0
- package/numkong/probes/arm_sve.c +18 -0
- package/numkong/probes/arm_sve2.c +20 -0
- package/numkong/probes/arm_sve2p1.c +18 -0
- package/numkong/probes/arm_sve_bfdot.c +20 -0
- package/numkong/probes/arm_sve_half.c +18 -0
- package/numkong/probes/arm_sve_sdot.c +21 -0
- package/numkong/probes/loongarch_lasx.c +12 -0
- package/numkong/probes/power_vsx.c +12 -0
- package/numkong/probes/probe.js +127 -0
- package/numkong/probes/riscv_rvv.c +14 -0
- package/numkong/probes/riscv_rvv_bb.c +15 -0
- package/numkong/probes/riscv_rvv_bf16.c +17 -0
- package/numkong/probes/riscv_rvv_half.c +14 -0
- package/numkong/probes/wasm_v128relaxed.c +11 -0
- package/numkong/probes/x86_alder.c +17 -0
- package/numkong/probes/x86_diamond.c +17 -0
- package/numkong/probes/x86_genoa.c +17 -0
- package/numkong/probes/x86_graniteamx.c +19 -0
- package/numkong/probes/x86_haswell.c +11 -0
- package/numkong/probes/x86_icelake.c +17 -0
- package/numkong/probes/x86_sapphire.c +16 -0
- package/numkong/probes/x86_sapphireamx.c +18 -0
- package/numkong/probes/x86_sierra.c +17 -0
- package/numkong/probes/x86_skylake.c +15 -0
- package/numkong/probes/x86_turin.c +17 -0
- package/numkong/rust/README.md +698 -0
- package/numkong/rust/capabilities.rs +96 -0
- package/numkong/rust/cast.rs +314 -0
- package/numkong/rust/curved.rs +391 -0
- package/numkong/rust/each.rs +2721 -0
- package/numkong/rust/geospatial.rs +343 -0
- package/numkong/rust/matrix.rs +5424 -0
- package/numkong/rust/maxsim.rs +540 -0
- package/numkong/rust/mesh.rs +837 -0
- package/numkong/rust/numkong.rs +409 -0
- package/numkong/rust/probability.rs +272 -0
- package/numkong/rust/reduce.rs +1249 -0
- package/numkong/rust/set.rs +194 -0
- package/numkong/rust/sparse.rs +513 -0
- package/numkong/rust/spatial.rs +1815 -0
- package/numkong/rust/tensor.rs +7565 -0
- package/numkong/rust/types.rs +3666 -0
- package/numkong/rust/vector.rs +1899 -0
- package/numkong/rustfmt.toml +2 -0
- package/numkong/swift/Matrix.swift +1388 -0
- package/numkong/swift/MaxSim.swift +151 -0
- package/numkong/swift/NumKong.swift +283 -0
- package/numkong/swift/Numerics.swift +329 -0
- package/numkong/swift/README.md +433 -0
- package/numkong/swift/Scalar.swift +741 -0
- package/numkong/swift/Tensor.swift +209 -0
- package/numkong/test/README.md +315 -0
- package/numkong/test/playwright.config.ts +16 -0
- package/numkong/test/swift/Test.swift +534 -0
- package/numkong/test/test-browser-bundle-runner.mjs +36 -0
- package/numkong/test/test-browser-bundle.html +188 -0
- package/numkong/test/test-browser-runner.mjs +43 -0
- package/numkong/test/test-browser.html +305 -0
- package/numkong/test/test-dtypes.mjs +453 -0
- package/numkong/test/test-wasm.mjs +267 -0
- package/numkong/test/test.cpp +442 -0
- package/numkong/test/test.hpp +580 -0
- package/numkong/test/test.mjs +363 -0
- package/numkong/test/test_base.py +1041 -0
- package/numkong/test/test_cast.cpp +242 -0
- package/numkong/test/test_cross.hpp +551 -0
- package/numkong/test/test_cross.py +467 -0
- package/numkong/test/test_cross_amx.cpp +50 -0
- package/numkong/test/test_cross_arm.cpp +225 -0
- package/numkong/test/test_cross_blas.cpp +354 -0
- package/numkong/test/test_cross_loongarch.cpp +90 -0
- package/numkong/test/test_cross_power.cpp +73 -0
- package/numkong/test/test_cross_rvv.cpp +109 -0
- package/numkong/test/test_cross_serial.cpp +181 -0
- package/numkong/test/test_cross_sme.cpp +148 -0
- package/numkong/test/test_cross_wasm.cpp +141 -0
- package/numkong/test/test_cross_x86.cpp +442 -0
- package/numkong/test/test_curved.cpp +182 -0
- package/numkong/test/test_curved.py +207 -0
- package/numkong/test/test_dot.cpp +353 -0
- package/numkong/test/test_dot.py +296 -0
- package/numkong/test/test_each.cpp +437 -0
- package/numkong/test/test_each.py +756 -0
- package/numkong/test/test_geospatial.cpp +155 -0
- package/numkong/test/test_geospatial.py +241 -0
- package/numkong/test/test_maxsim.cpp +138 -0
- package/numkong/test/test_maxsim.py +209 -0
- package/numkong/test/test_mesh.cpp +203 -0
- package/numkong/test/test_mesh.py +394 -0
- package/numkong/test/test_probability.cpp +136 -0
- package/numkong/test/test_probability.py +166 -0
- package/numkong/test/test_reduce.cpp +563 -0
- package/numkong/test/test_reduce.py +781 -0
- package/numkong/test/test_set.cpp +151 -0
- package/numkong/test/test_set.py +120 -0
- package/numkong/test/test_similarities.py +579 -0
- package/numkong/test/test_sparse.cpp +121 -0
- package/numkong/test/test_sparse.py +118 -0
- package/numkong/test/test_spatial.cpp +518 -0
- package/numkong/test/test_spatial.py +269 -0
- package/numkong/test/test_tensor.cpp +884 -0
- package/numkong/test/test_tensor.py +1417 -0
- package/numkong/test/test_trigonometry.cpp +156 -0
- package/numkong/test/test_trigonometry.py +180 -0
- package/package.json +7 -8
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/fp16/CMakeLists.txt +0 -176
- package/fp16/LICENSE +0 -11
- package/fp16/README.md +0 -20
- package/fp16/bench/alt-element.cc +0 -89
- package/fp16/bench/from-alt-array.cc +0 -175
- package/fp16/bench/from-ieee-array.cc +0 -399
- package/fp16/bench/ieee-element.cc +0 -272
- package/fp16/bench/to-alt-array.cc +0 -91
- package/fp16/bench/to-ieee-array.cc +0 -303
- package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
- package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
- package/fp16/cmake/DownloadPSimd.cmake +0 -15
- package/fp16/configure.py +0 -65
- package/fp16/confu.yaml +0 -8
- package/fp16/include/fp16/__init__.py +0 -0
- package/fp16/include/fp16/avx.py +0 -50
- package/fp16/include/fp16/avx2.py +0 -53
- package/fp16/include/fp16/bitcasts.h +0 -92
- package/fp16/include/fp16/fp16.h +0 -451
- package/fp16/include/fp16/psimd.h +0 -131
- package/fp16/include/fp16.h +0 -11
- package/fp16/jni/Android.mk +0 -6
- package/fp16/jni/Application.mk +0 -4
- package/fp16/test/alt-from-fp32-value.cc +0 -498
- package/fp16/test/alt-to-fp32-bits.cc +0 -263
- package/fp16/test/alt-to-fp32-psimd.cc +0 -145
- package/fp16/test/alt-to-fp32-value.cc +0 -348
- package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
- package/fp16/test/bitcasts.cc +0 -56
- package/fp16/test/ieee-from-fp32-value.cc +0 -523
- package/fp16/test/ieee-to-fp32-bits.cc +0 -333
- package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
- package/fp16/test/ieee-to-fp32-value.cc +0 -420
- package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
- package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
- package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
- package/fp16/test/peachpy/stubs.py +0 -38
- package/fp16/test/tables.cc +0 -530
- package/fp16/test/tables.h +0 -13
- package/fp16/third-party/THHalf.h +0 -92
- package/fp16/third-party/eigen-half.h +0 -170
- package/fp16/third-party/float16-compressor.h +0 -80
- package/fp16/third-party/half.hpp +0 -2916
- package/fp16/third-party/npy-halffloat.h +0 -328
- package/simsimd/.git-blame-ignore-revs +0 -2
- package/simsimd/CONTRIBUTING.md +0 -321
- package/simsimd/Cargo.toml +0 -49
- package/simsimd/MANIFEST.in +0 -4
- package/simsimd/Package.swift +0 -28
- package/simsimd/README.md +0 -1493
- package/simsimd/binding.gyp +0 -35
- package/simsimd/build.rs +0 -70
- package/simsimd/c/lib.c +0 -374
- package/simsimd/include/module.modulemap +0 -4
- package/simsimd/include/simsimd/binary.h +0 -486
- package/simsimd/include/simsimd/curved.h +0 -1541
- package/simsimd/include/simsimd/dot.h +0 -1853
- package/simsimd/include/simsimd/elementwise.h +0 -2465
- package/simsimd/include/simsimd/geospatial.h +0 -43
- package/simsimd/include/simsimd/mesh.h +0 -69
- package/simsimd/include/simsimd/probability.h +0 -606
- package/simsimd/include/simsimd/simsimd.h +0 -2567
- package/simsimd/include/simsimd/sparse.h +0 -1384
- package/simsimd/include/simsimd/spatial.h +0 -2335
- package/simsimd/include/simsimd/types.h +0 -666
- package/simsimd/javascript/fallback.ts +0 -233
- package/simsimd/javascript/lib.c +0 -125
- package/simsimd/javascript/node-gyp-build.d.ts +0 -1
- package/simsimd/javascript/simsimd.ts +0 -179
- package/simsimd/javascript/tsconfig-cjs.json +0 -8
- package/simsimd/package-lock.json +0 -1761
- package/simsimd/package.json +0 -61
- package/simsimd/rust/lib.rs +0 -1821
- package/simsimd/scripts/bench.cxx +0 -1170
- package/simsimd/scripts/bench.ipynb +0 -187
- package/simsimd/scripts/bench.js +0 -127
- package/simsimd/scripts/bench.rs +0 -876
- package/simsimd/scripts/bench_vectors.py +0 -734
- package/simsimd/scripts/bench_vectors_live.py +0 -213
- package/simsimd/scripts/test.c +0 -187
- package/simsimd/scripts/test.mjs +0 -220
- package/simsimd/scripts/test.py +0 -1505
- package/simsimd/swift/SimSIMD.swift +0 -149
- package/simsimd/swift/Test.swift +0 -128
- /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
- /package/{simsimd → numkong}/LICENSE +0 -0
- /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
- /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Spatial Similarity Measures for RISC-V BF16.
|
|
3
|
+
* @file include/numkong/spatial/rvvbf16.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date January 5, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/spatial.h
|
|
8
|
+
*
|
|
9
|
+
* Zvfbfwma provides widening bf16 fused multiply-accumulate to f32:
|
|
10
|
+
* vfwmaccbf16: f32 ← bf16 × bf16
|
|
11
|
+
*
|
|
12
|
+
* For L2 distance, we use the identity: (a−b)² = a² + b² − 2 × a × b
|
|
13
|
+
* This allows us to use vfwmaccbf16 for all computations.
|
|
14
|
+
*
|
|
15
|
+
* Requires: RVV 1.0 + Zvfbfwma extension (GCC 14+ or Clang 18+)
|
|
16
|
+
*/
|
|
17
|
+
#ifndef NK_SPATIAL_RVVBF16_H
|
|
18
|
+
#define NK_SPATIAL_RVVBF16_H
|
|
19
|
+
|
|
20
|
+
#if NK_TARGET_RISCV64_
|
|
21
|
+
#if NK_TARGET_RVVBF16
|
|
22
|
+
|
|
23
|
+
#include "numkong/types.h"
|
|
24
|
+
#include "numkong/spatial/rvv.h" // `nk_f32_sqrt_rvv`
|
|
25
|
+
|
|
26
|
+
#if defined(__clang__)
|
|
27
|
+
#pragma clang attribute push(__attribute__((target("arch=+v,+zvfbfwma"))), apply_to = function)
|
|
28
|
+
#elif defined(__GNUC__)
|
|
29
|
+
#pragma GCC push_options
|
|
30
|
+
#pragma GCC target("arch=+v,+zvfbfwma")
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
#if defined(__cplusplus)
|
|
34
|
+
extern "C" {
|
|
35
|
+
#endif
|
|
36
|
+
|
|
37
|
+
NK_PUBLIC void nk_sqeuclidean_bf16_rvvbf16(nk_bf16_t const *a_scalars, nk_bf16_t const *b_scalars,
|
|
38
|
+
nk_size_t count_scalars, nk_f32_t *result) {
|
|
39
|
+
// Per-lane accumulators — deferred horizontal reduction
|
|
40
|
+
nk_size_t max_vector_length = __riscv_vsetvlmax_e32m2();
|
|
41
|
+
vfloat32m2_t sq_sum_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length); // a² + b²
|
|
42
|
+
vfloat32m2_t ab_sum_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length); // a × b
|
|
43
|
+
|
|
44
|
+
for (nk_size_t vector_length; count_scalars > 0;
|
|
45
|
+
count_scalars -= vector_length, a_scalars += vector_length, b_scalars += vector_length) {
|
|
46
|
+
vector_length = __riscv_vsetvl_e16m1(count_scalars);
|
|
47
|
+
vuint16m1_t a_u16m1 = __riscv_vle16_v_u16m1((unsigned short const *)a_scalars, vector_length);
|
|
48
|
+
vuint16m1_t b_u16m1 = __riscv_vle16_v_u16m1((unsigned short const *)b_scalars, vector_length);
|
|
49
|
+
vbfloat16m1_t a_bf16m1 = __riscv_vreinterpret_v_u16m1_bf16m1(a_u16m1);
|
|
50
|
+
vbfloat16m1_t b_bf16m1 = __riscv_vreinterpret_v_u16m1_bf16m1(b_u16m1);
|
|
51
|
+
|
|
52
|
+
// Accumulate a², b², and a×b per-lane (no per-iteration reduction)
|
|
53
|
+
sq_sum_f32m2 = __riscv_vfwmaccbf16_vv_f32m2_tu(sq_sum_f32m2, a_bf16m1, a_bf16m1, vector_length);
|
|
54
|
+
sq_sum_f32m2 = __riscv_vfwmaccbf16_vv_f32m2_tu(sq_sum_f32m2, b_bf16m1, b_bf16m1, vector_length);
|
|
55
|
+
ab_sum_f32m2 = __riscv_vfwmaccbf16_vv_f32m2_tu(ab_sum_f32m2, a_bf16m1, b_bf16m1, vector_length);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Single horizontal reduction after the loop
|
|
59
|
+
vfloat32m1_t zero_f32m1 = __riscv_vfmv_v_f_f32m1(0.0f, 1);
|
|
60
|
+
nk_f32_t sq_sum = __riscv_vfmv_f_s_f32m1_f32(
|
|
61
|
+
__riscv_vfredusum_vs_f32m2_f32m1(sq_sum_f32m2, zero_f32m1, max_vector_length));
|
|
62
|
+
nk_f32_t ab_sum = __riscv_vfmv_f_s_f32m1_f32(
|
|
63
|
+
__riscv_vfredusum_vs_f32m2_f32m1(ab_sum_f32m2, zero_f32m1, max_vector_length));
|
|
64
|
+
*result = sq_sum - 2.0f * ab_sum;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
NK_PUBLIC void nk_euclidean_bf16_rvvbf16(nk_bf16_t const *a_scalars, nk_bf16_t const *b_scalars,
|
|
68
|
+
nk_size_t count_scalars, nk_f32_t *result) {
|
|
69
|
+
nk_sqeuclidean_bf16_rvvbf16(a_scalars, b_scalars, count_scalars, result);
|
|
70
|
+
// Handle potential negative values from floating point errors
|
|
71
|
+
*result = *result > 0.0f ? nk_f32_sqrt_rvv(*result) : 0.0f;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
NK_PUBLIC void nk_angular_bf16_rvvbf16(nk_bf16_t const *a_scalars, nk_bf16_t const *b_scalars, nk_size_t count_scalars,
|
|
75
|
+
nk_f32_t *result) {
|
|
76
|
+
// Per-lane accumulators — deferred horizontal reduction
|
|
77
|
+
nk_size_t max_vector_length = __riscv_vsetvlmax_e32m2();
|
|
78
|
+
vfloat32m2_t dot_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length);
|
|
79
|
+
vfloat32m2_t a_sq_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length);
|
|
80
|
+
vfloat32m2_t b_sq_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length);
|
|
81
|
+
|
|
82
|
+
for (nk_size_t vector_length; count_scalars > 0;
|
|
83
|
+
count_scalars -= vector_length, a_scalars += vector_length, b_scalars += vector_length) {
|
|
84
|
+
vector_length = __riscv_vsetvl_e16m1(count_scalars);
|
|
85
|
+
vuint16m1_t a_u16m1 = __riscv_vle16_v_u16m1((unsigned short const *)a_scalars, vector_length);
|
|
86
|
+
vuint16m1_t b_u16m1 = __riscv_vle16_v_u16m1((unsigned short const *)b_scalars, vector_length);
|
|
87
|
+
vbfloat16m1_t a_bf16m1 = __riscv_vreinterpret_v_u16m1_bf16m1(a_u16m1);
|
|
88
|
+
vbfloat16m1_t b_bf16m1 = __riscv_vreinterpret_v_u16m1_bf16m1(b_u16m1);
|
|
89
|
+
|
|
90
|
+
// dot += a × b
|
|
91
|
+
dot_f32m2 = __riscv_vfwmaccbf16_vv_f32m2_tu(dot_f32m2, a_bf16m1, b_bf16m1, vector_length);
|
|
92
|
+
// a_sq += a × a
|
|
93
|
+
a_sq_f32m2 = __riscv_vfwmaccbf16_vv_f32m2_tu(a_sq_f32m2, a_bf16m1, a_bf16m1, vector_length);
|
|
94
|
+
// b_sq += b × b
|
|
95
|
+
b_sq_f32m2 = __riscv_vfwmaccbf16_vv_f32m2_tu(b_sq_f32m2, b_bf16m1, b_bf16m1, vector_length);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Single horizontal reduction after the loop
|
|
99
|
+
vfloat32m1_t zero_f32m1 = __riscv_vfmv_v_f_f32m1(0.0f, 1);
|
|
100
|
+
nk_f32_t dot = __riscv_vfmv_f_s_f32m1_f32(
|
|
101
|
+
__riscv_vfredusum_vs_f32m2_f32m1(dot_f32m2, zero_f32m1, max_vector_length));
|
|
102
|
+
nk_f32_t a_sq = __riscv_vfmv_f_s_f32m1_f32(
|
|
103
|
+
__riscv_vfredusum_vs_f32m2_f32m1(a_sq_f32m2, zero_f32m1, max_vector_length));
|
|
104
|
+
nk_f32_t b_sq = __riscv_vfmv_f_s_f32m1_f32(
|
|
105
|
+
__riscv_vfredusum_vs_f32m2_f32m1(b_sq_f32m2, zero_f32m1, max_vector_length));
|
|
106
|
+
|
|
107
|
+
// Normalize: 1 − dot / sqrt(‖a‖² × ‖b‖²)
|
|
108
|
+
if (a_sq == 0.0f && b_sq == 0.0f) { *result = 0.0f; }
|
|
109
|
+
else if (dot == 0.0f) { *result = 1.0f; }
|
|
110
|
+
else {
|
|
111
|
+
nk_f32_t unclipped = 1.0f - dot * nk_f32_rsqrt_rvv(a_sq) * nk_f32_rsqrt_rvv(b_sq);
|
|
112
|
+
*result = unclipped > 0.0f ? unclipped : 0.0f;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#if defined(__cplusplus)
|
|
117
|
+
} // extern "C"
|
|
118
|
+
#endif
|
|
119
|
+
|
|
120
|
+
#if defined(__clang__)
|
|
121
|
+
#pragma clang attribute pop
|
|
122
|
+
#elif defined(__GNUC__)
|
|
123
|
+
#pragma GCC pop_options
|
|
124
|
+
#endif
|
|
125
|
+
|
|
126
|
+
#endif // NK_TARGET_RVVBF16
|
|
127
|
+
#endif // NK_TARGET_RISCV64_
|
|
128
|
+
#endif // NK_SPATIAL_RVVBF16_H
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Spatial Similarity Measures for RISC-V FP16.
|
|
3
|
+
* @file include/numkong/spatial/rvvhalf.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date January 5, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/spatial.h
|
|
8
|
+
*
|
|
9
|
+
* Zvfh provides native half-precision (f16) vector operations.
|
|
10
|
+
* Uses widening operations (f16 → f32) for precision accumulation.
|
|
11
|
+
*
|
|
12
|
+
* Requires: RVV 1.0 + Zvfh extension (GCC 14+ or Clang 18+)
|
|
13
|
+
*/
|
|
14
|
+
#ifndef NK_SPATIAL_RVVHALF_H
|
|
15
|
+
#define NK_SPATIAL_RVVHALF_H
|
|
16
|
+
|
|
17
|
+
#if NK_TARGET_RISCV64_
|
|
18
|
+
#if NK_TARGET_RVVHALF
|
|
19
|
+
|
|
20
|
+
#include "numkong/types.h"
|
|
21
|
+
#include "numkong/spatial/rvv.h" // `nk_f32_sqrt_rvv`
|
|
22
|
+
|
|
23
|
+
#if defined(__clang__)
|
|
24
|
+
#pragma clang attribute push(__attribute__((target("arch=+v,+zvfh"))), apply_to = function)
|
|
25
|
+
#elif defined(__GNUC__)
|
|
26
|
+
#pragma GCC push_options
|
|
27
|
+
#pragma GCC target("arch=+v,+zvfh")
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#if defined(__cplusplus)
|
|
31
|
+
extern "C" {
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
NK_PUBLIC void nk_sqeuclidean_f16_rvvhalf(nk_f16_t const *a_scalars, nk_f16_t const *b_scalars, nk_size_t count_scalars,
|
|
35
|
+
nk_f32_t *result) {
|
|
36
|
+
// Per-lane accumulator — deferred horizontal reduction
|
|
37
|
+
nk_size_t max_vector_length = __riscv_vsetvlmax_e32m2();
|
|
38
|
+
vfloat32m2_t sum_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length);
|
|
39
|
+
|
|
40
|
+
for (nk_size_t vector_length; count_scalars > 0;
|
|
41
|
+
count_scalars -= vector_length, a_scalars += vector_length, b_scalars += vector_length) {
|
|
42
|
+
vector_length = __riscv_vsetvl_e16m1(count_scalars);
|
|
43
|
+
vuint16m1_t a_u16m1 = __riscv_vle16_v_u16m1((unsigned short const *)a_scalars, vector_length);
|
|
44
|
+
vuint16m1_t b_u16m1 = __riscv_vle16_v_u16m1((unsigned short const *)b_scalars, vector_length);
|
|
45
|
+
vfloat16m1_t a_f16m1 = __riscv_vreinterpret_v_u16m1_f16m1(a_u16m1);
|
|
46
|
+
vfloat16m1_t b_f16m1 = __riscv_vreinterpret_v_u16m1_f16m1(b_u16m1);
|
|
47
|
+
// Upcast to f32 before subtraction to avoid catastrophic cancellation in f16
|
|
48
|
+
vfloat32m2_t a_f32m2 = __riscv_vfwcvt_f_f_v_f32m2(a_f16m1, vector_length);
|
|
49
|
+
vfloat32m2_t b_f32m2 = __riscv_vfwcvt_f_f_v_f32m2(b_f16m1, vector_length);
|
|
50
|
+
vfloat32m2_t diff_f32m2 = __riscv_vfsub_vv_f32m2(a_f32m2, b_f32m2, vector_length);
|
|
51
|
+
// Accumulate diff² in f32
|
|
52
|
+
sum_f32m2 = __riscv_vfmacc_vv_f32m2_tu(sum_f32m2, diff_f32m2, diff_f32m2, vector_length);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Single horizontal reduction after the loop
|
|
56
|
+
vfloat32m1_t zero_f32m1 = __riscv_vfmv_v_f_f32m1(0.0f, 1);
|
|
57
|
+
*result = __riscv_vfmv_f_s_f32m1_f32(__riscv_vfredusum_vs_f32m2_f32m1(sum_f32m2, zero_f32m1, max_vector_length));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
NK_PUBLIC void nk_euclidean_f16_rvvhalf(nk_f16_t const *a_scalars, nk_f16_t const *b_scalars, nk_size_t count_scalars,
|
|
61
|
+
nk_f32_t *result) {
|
|
62
|
+
nk_sqeuclidean_f16_rvvhalf(a_scalars, b_scalars, count_scalars, result);
|
|
63
|
+
*result = nk_f32_sqrt_rvv(*result);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
NK_PUBLIC void nk_angular_f16_rvvhalf(nk_f16_t const *a_scalars, nk_f16_t const *b_scalars, nk_size_t count_scalars,
|
|
67
|
+
nk_f32_t *result) {
|
|
68
|
+
// Per-lane accumulators — deferred horizontal reduction
|
|
69
|
+
nk_size_t max_vector_length = __riscv_vsetvlmax_e32m2();
|
|
70
|
+
vfloat32m2_t dot_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length);
|
|
71
|
+
vfloat32m2_t a_sq_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length);
|
|
72
|
+
vfloat32m2_t b_sq_f32m2 = __riscv_vfmv_v_f_f32m2(0.0f, max_vector_length);
|
|
73
|
+
|
|
74
|
+
for (nk_size_t vector_length; count_scalars > 0;
|
|
75
|
+
count_scalars -= vector_length, a_scalars += vector_length, b_scalars += vector_length) {
|
|
76
|
+
vector_length = __riscv_vsetvl_e16m1(count_scalars);
|
|
77
|
+
vuint16m1_t a_u16m1 = __riscv_vle16_v_u16m1((unsigned short const *)a_scalars, vector_length);
|
|
78
|
+
vuint16m1_t b_u16m1 = __riscv_vle16_v_u16m1((unsigned short const *)b_scalars, vector_length);
|
|
79
|
+
vfloat16m1_t a_f16m1 = __riscv_vreinterpret_v_u16m1_f16m1(a_u16m1);
|
|
80
|
+
vfloat16m1_t b_f16m1 = __riscv_vreinterpret_v_u16m1_f16m1(b_u16m1);
|
|
81
|
+
|
|
82
|
+
// dot += a × b (widened to f32)
|
|
83
|
+
dot_f32m2 = __riscv_vfwmacc_vv_f32m2_tu(dot_f32m2, a_f16m1, b_f16m1, vector_length);
|
|
84
|
+
// a_sq += a × a
|
|
85
|
+
a_sq_f32m2 = __riscv_vfwmacc_vv_f32m2_tu(a_sq_f32m2, a_f16m1, a_f16m1, vector_length);
|
|
86
|
+
// b_sq += b × b
|
|
87
|
+
b_sq_f32m2 = __riscv_vfwmacc_vv_f32m2_tu(b_sq_f32m2, b_f16m1, b_f16m1, vector_length);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Single horizontal reduction after the loop
|
|
91
|
+
vfloat32m1_t zero_f32m1 = __riscv_vfmv_v_f_f32m1(0.0f, 1);
|
|
92
|
+
nk_f32_t dot = __riscv_vfmv_f_s_f32m1_f32(
|
|
93
|
+
__riscv_vfredusum_vs_f32m2_f32m1(dot_f32m2, zero_f32m1, max_vector_length));
|
|
94
|
+
nk_f32_t a_sq = __riscv_vfmv_f_s_f32m1_f32(
|
|
95
|
+
__riscv_vfredusum_vs_f32m2_f32m1(a_sq_f32m2, zero_f32m1, max_vector_length));
|
|
96
|
+
nk_f32_t b_sq = __riscv_vfmv_f_s_f32m1_f32(
|
|
97
|
+
__riscv_vfredusum_vs_f32m2_f32m1(b_sq_f32m2, zero_f32m1, max_vector_length));
|
|
98
|
+
|
|
99
|
+
// Normalize: 1 − dot / sqrt(‖a‖² × ‖b‖²)
|
|
100
|
+
if (a_sq == 0.0f && b_sq == 0.0f) { *result = 0.0f; }
|
|
101
|
+
else if (dot == 0.0f) { *result = 1.0f; }
|
|
102
|
+
else {
|
|
103
|
+
nk_f32_t unclipped = 1.0f - dot * nk_f32_rsqrt_rvv(a_sq) * nk_f32_rsqrt_rvv(b_sq);
|
|
104
|
+
*result = unclipped > 0.0f ? unclipped : 0.0f;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#if defined(__cplusplus)
|
|
109
|
+
} // extern "C"
|
|
110
|
+
#endif
|
|
111
|
+
|
|
112
|
+
#if defined(__clang__)
|
|
113
|
+
#pragma clang attribute pop
|
|
114
|
+
#elif defined(__GNUC__)
|
|
115
|
+
#pragma GCC pop_options
|
|
116
|
+
#endif
|
|
117
|
+
|
|
118
|
+
#endif // NK_TARGET_RVVHALF
|
|
119
|
+
#endif // NK_TARGET_RISCV64_
|
|
120
|
+
#endif // NK_SPATIAL_RVVHALF_H
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SWAR-accelerated Spatial Similarity Measures for SIMD-free CPUs.
|
|
3
|
+
* @file include/numkong/spatial/serial.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date December 27, 2025
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/spatial.h
|
|
8
|
+
*/
|
|
9
|
+
#ifndef NK_SPATIAL_SERIAL_H
|
|
10
|
+
#define NK_SPATIAL_SERIAL_H
|
|
11
|
+
|
|
12
|
+
#include "numkong/types.h"
|
|
13
|
+
#include "numkong/scalar/serial.h" // `nk_f32_rsqrt_serial`
|
|
14
|
+
#include "numkong/cast/serial.h"
|
|
15
|
+
#include "numkong/dot/serial.h" // `nk_dot_f64x2_state_serial_t`
|
|
16
|
+
|
|
17
|
+
#if defined(__cplusplus)
|
|
18
|
+
extern "C" {
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @brief Macro for L2 squared distance with Neumaier compensated summation.
|
|
23
|
+
*
|
|
24
|
+
* Implements Neumaier's Kahan-Babuška variant to minimize floating-point rounding errors.
|
|
25
|
+
* Unlike Kahan, Neumaier handles the case where the term being added is larger than the
|
|
26
|
+
* running sum. Achieves O(1) error growth regardless of vector dimension.
|
|
27
|
+
*
|
|
28
|
+
* Performance vs Accuracy Tradeoff:
|
|
29
|
+
* - Adds ~30% overhead (3 extra FP operations per iteration) compared to naive summation
|
|
30
|
+
* - Reduces relative error from ~10⁻⁵ to ~10⁻⁷ at n=100K for f32
|
|
31
|
+
* - Benefits all floating-point types: f64, f32, f16, bf16
|
|
32
|
+
* - Integer types (i8) maintain perfect accuracy regardless
|
|
33
|
+
*
|
|
34
|
+
* Algorithm: For each term, compute t = sum + term, then:
|
|
35
|
+
* - If |sum| ≥ |term|: c += (sum − t) + term (lost low-order bits of term)
|
|
36
|
+
* - Else: c += (term − t) + sum (lost low-order bits of sum)
|
|
37
|
+
*
|
|
38
|
+
* @see Neumaier, A. (1974). "Rundungsfehleranalyse einiger Verfahren zur Summation endlicher Summen"
|
|
39
|
+
*/
|
|
40
|
+
#define nk_define_sqeuclidean_(input_type, accumulator_type, output_type, load_and_convert) \
|
|
41
|
+
NK_PUBLIC void nk_sqeuclidean_##input_type##_serial(nk_##input_type##_t const *a, nk_##input_type##_t const *b, \
|
|
42
|
+
nk_size_t n, nk_##output_type##_t *result) { \
|
|
43
|
+
nk_##accumulator_type##_t sum = 0, compensation = 0, a_value, b_value; \
|
|
44
|
+
for (nk_size_t i = 0; i != n; ++i) { \
|
|
45
|
+
load_and_convert(a + i, &a_value); \
|
|
46
|
+
load_and_convert(b + i, &b_value); \
|
|
47
|
+
nk_##accumulator_type##_t diff = a_value - b_value; \
|
|
48
|
+
nk_##accumulator_type##_t term = diff * diff, t = sum + term; \
|
|
49
|
+
compensation += (nk_##accumulator_type##_abs_(sum) >= nk_##accumulator_type##_abs_(term)) \
|
|
50
|
+
? ((sum - t) + term) \
|
|
51
|
+
: ((term - t) + sum); \
|
|
52
|
+
sum = t; \
|
|
53
|
+
} \
|
|
54
|
+
*result = (nk_##output_type##_t)(sum + compensation); \
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#define nk_define_euclidean_(input_type, accumulator_type, l2sq_output_type, output_type, load_and_convert, \
|
|
58
|
+
compute_sqrt) \
|
|
59
|
+
NK_PUBLIC void nk_euclidean_##input_type##_serial(nk_##input_type##_t const *a, nk_##input_type##_t const *b, \
|
|
60
|
+
nk_size_t n, nk_##output_type##_t *result) { \
|
|
61
|
+
nk_##l2sq_output_type##_t distance_sq; \
|
|
62
|
+
nk_sqeuclidean_##input_type##_serial(a, b, n, &distance_sq); \
|
|
63
|
+
*result = compute_sqrt((nk_##output_type##_t)distance_sq); \
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @brief Macro for cosine/angular distance with Neumaier compensated summation.
|
|
68
|
+
*
|
|
69
|
+
* Uses Neumaier summation for all three accumulators (dot_product, a_norm_sq, b_norm_sq).
|
|
70
|
+
* Achieves O(1) error growth regardless of vector dimension.
|
|
71
|
+
*
|
|
72
|
+
* @see nk_define_sqeuclidean_ for detailed documentation on Neumaier summation.
|
|
73
|
+
*/
|
|
74
|
+
#define nk_define_angular_(input_type, accumulator_type, output_type, load_and_convert, compute_rsqrt) \
|
|
75
|
+
NK_PUBLIC void nk_angular_##input_type##_serial(nk_##input_type##_t const *a, nk_##input_type##_t const *b, \
|
|
76
|
+
nk_size_t n, nk_##output_type##_t *result) { \
|
|
77
|
+
nk_##accumulator_type##_t dot_sum = 0, a_sum = 0, b_sum = 0, a_value, b_value; \
|
|
78
|
+
nk_##accumulator_type##_t compensation_dot = 0, compensation_a = 0, compensation_b = 0; \
|
|
79
|
+
for (nk_size_t i = 0; i != n; ++i) { \
|
|
80
|
+
load_and_convert(a + i, &a_value); \
|
|
81
|
+
load_and_convert(b + i, &b_value); \
|
|
82
|
+
nk_##accumulator_type##_t term_dot = a_value * b_value, t_dot = dot_sum + term_dot; \
|
|
83
|
+
nk_##accumulator_type##_t term_a = a_value * a_value, t_a = a_sum + term_a; \
|
|
84
|
+
nk_##accumulator_type##_t term_b = b_value * b_value, t_b = b_sum + term_b; \
|
|
85
|
+
compensation_dot += (nk_##accumulator_type##_abs_(dot_sum) >= nk_##accumulator_type##_abs_(term_dot)) \
|
|
86
|
+
? ((dot_sum - t_dot) + term_dot) \
|
|
87
|
+
: ((term_dot - t_dot) + dot_sum); \
|
|
88
|
+
compensation_a += (nk_##accumulator_type##_abs_(a_sum) >= nk_##accumulator_type##_abs_(term_a)) \
|
|
89
|
+
? ((a_sum - t_a) + term_a) \
|
|
90
|
+
: ((term_a - t_a) + a_sum); \
|
|
91
|
+
compensation_b += (nk_##accumulator_type##_abs_(b_sum) >= nk_##accumulator_type##_abs_(term_b)) \
|
|
92
|
+
? ((b_sum - t_b) + term_b) \
|
|
93
|
+
: ((term_b - t_b) + b_sum); \
|
|
94
|
+
dot_sum = t_dot; \
|
|
95
|
+
a_sum = t_a; \
|
|
96
|
+
b_sum = t_b; \
|
|
97
|
+
} \
|
|
98
|
+
nk_##accumulator_type##_t dot_product = dot_sum + compensation_dot; \
|
|
99
|
+
nk_##accumulator_type##_t a_norm_sq = a_sum + compensation_a; \
|
|
100
|
+
nk_##accumulator_type##_t b_norm_sq = b_sum + compensation_b; \
|
|
101
|
+
if (a_norm_sq == 0 && b_norm_sq == 0) { *result = 0; } \
|
|
102
|
+
else if (dot_product == 0) { *result = 1; } \
|
|
103
|
+
else { \
|
|
104
|
+
nk_##output_type##_t unclipped_distance = (nk_##output_type##_t)( \
|
|
105
|
+
1 - (nk_##output_type##_t)dot_product * compute_rsqrt((nk_##output_type##_t)a_norm_sq) * \
|
|
106
|
+
compute_rsqrt((nk_##output_type##_t)b_norm_sq)); \
|
|
107
|
+
*result = unclipped_distance > 0 ? unclipped_distance : 0; \
|
|
108
|
+
} \
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
nk_define_angular_(f64, f64, f64, nk_assign_from_to_, nk_f64_rsqrt_serial) // nk_angular_f64_serial
|
|
112
|
+
nk_define_sqeuclidean_(f64, f64, f64, nk_assign_from_to_) // nk_sqeuclidean_f64_serial
|
|
113
|
+
nk_define_euclidean_(f64, f64, f64, f64, nk_assign_from_to_, nk_f64_sqrt_serial) // nk_euclidean_f64_serial
|
|
114
|
+
|
|
115
|
+
nk_define_angular_(f32, f64, f64, nk_assign_from_to_, nk_f64_rsqrt_serial) // nk_angular_f32_serial
|
|
116
|
+
nk_define_sqeuclidean_(f32, f64, f64, nk_assign_from_to_) // nk_sqeuclidean_f32_serial
|
|
117
|
+
nk_define_euclidean_(f32, f64, f64, f64, nk_assign_from_to_, nk_f64_sqrt_serial) // nk_euclidean_f32_serial
|
|
118
|
+
|
|
119
|
+
nk_define_angular_(f16, f32, f32, nk_f16_to_f32_serial, nk_f32_rsqrt_serial) // nk_angular_f16_serial
|
|
120
|
+
nk_define_sqeuclidean_(f16, f32, f32, nk_f16_to_f32_serial) // nk_sqeuclidean_f16_serial
|
|
121
|
+
nk_define_euclidean_(f16, f32, f32, f32, nk_f16_to_f32_serial, nk_f32_sqrt_serial) // nk_euclidean_f16_serial
|
|
122
|
+
|
|
123
|
+
nk_define_angular_(bf16, f32, f32, nk_bf16_to_f32_serial, nk_f32_rsqrt_serial) // nk_angular_bf16_serial
|
|
124
|
+
nk_define_sqeuclidean_(bf16, f32, f32, nk_bf16_to_f32_serial) // nk_sqeuclidean_bf16_serial
|
|
125
|
+
nk_define_euclidean_(bf16, f32, f32, f32, nk_bf16_to_f32_serial, nk_f32_sqrt_serial) // nk_euclidean_bf16_serial
|
|
126
|
+
|
|
127
|
+
nk_define_angular_(e4m3, f32, f32, nk_e4m3_to_f32_serial, nk_f32_rsqrt_serial) // nk_angular_e4m3_serial
|
|
128
|
+
nk_define_sqeuclidean_(e4m3, f32, f32, nk_e4m3_to_f32_serial) // nk_sqeuclidean_e4m3_serial
|
|
129
|
+
nk_define_euclidean_(e4m3, f32, f32, f32, nk_e4m3_to_f32_serial, nk_f32_sqrt_serial) // nk_euclidean_e4m3_serial
|
|
130
|
+
|
|
131
|
+
nk_define_angular_(e5m2, f32, f32, nk_e5m2_to_f32_serial, nk_f32_rsqrt_serial) // nk_angular_e5m2_serial
|
|
132
|
+
nk_define_sqeuclidean_(e5m2, f32, f32, nk_e5m2_to_f32_serial) // nk_sqeuclidean_e5m2_serial
|
|
133
|
+
nk_define_euclidean_(e5m2, f32, f32, f32, nk_e5m2_to_f32_serial, nk_f32_sqrt_serial) // nk_euclidean_e5m2_serial
|
|
134
|
+
|
|
135
|
+
nk_define_angular_(e2m3, f32, f32, nk_e2m3_to_f32_serial, nk_f32_rsqrt_serial) // nk_angular_e2m3_serial
|
|
136
|
+
nk_define_sqeuclidean_(e2m3, f32, f32, nk_e2m3_to_f32_serial) // nk_sqeuclidean_e2m3_serial
|
|
137
|
+
nk_define_euclidean_(e2m3, f32, f32, f32, nk_e2m3_to_f32_serial, nk_f32_sqrt_serial) // nk_euclidean_e2m3_serial
|
|
138
|
+
|
|
139
|
+
nk_define_angular_(e3m2, f32, f32, nk_e3m2_to_f32_serial, nk_f32_rsqrt_serial) // nk_angular_e3m2_serial
|
|
140
|
+
nk_define_sqeuclidean_(e3m2, f32, f32, nk_e3m2_to_f32_serial) // nk_sqeuclidean_e3m2_serial
|
|
141
|
+
nk_define_euclidean_(e3m2, f32, f32, f32, nk_e3m2_to_f32_serial, nk_f32_sqrt_serial) // nk_euclidean_e3m2_serial
|
|
142
|
+
|
|
143
|
+
nk_define_angular_(i8, i32, f32, nk_assign_from_to_, nk_f32_rsqrt_serial) // nk_angular_i8_serial
|
|
144
|
+
nk_define_sqeuclidean_(i8, i32, u32, nk_assign_from_to_) // nk_sqeuclidean_i8_serial
|
|
145
|
+
nk_define_euclidean_(i8, i32, u32, f32, nk_assign_from_to_, nk_f32_sqrt_serial) // nk_euclidean_i8_serial
|
|
146
|
+
|
|
147
|
+
nk_define_angular_(u8, u32, f32, nk_assign_from_to_, nk_f32_rsqrt_serial) // nk_angular_u8_serial
|
|
148
|
+
nk_define_sqeuclidean_(u8, u32, u32, nk_assign_from_to_) // nk_sqeuclidean_u8_serial
|
|
149
|
+
nk_define_euclidean_(u8, u32, u32, f32, nk_assign_from_to_, nk_f32_sqrt_serial) // nk_euclidean_u8_serial
|
|
150
|
+
|
|
151
|
+
#undef nk_define_sqeuclidean_
|
|
152
|
+
#undef nk_define_euclidean_
|
|
153
|
+
#undef nk_define_angular_
|
|
154
|
+
|
|
155
|
+
NK_PUBLIC void nk_sqeuclidean_i4_serial(nk_i4x2_t const *a, nk_i4x2_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
156
|
+
// i4 values are packed as nibbles: two 4-bit signed values per byte.
|
|
157
|
+
// Parameter `n` is the number of 4-bit values (dimensions), not bytes.
|
|
158
|
+
// Sign extension: (nibble ^ 8) - 8 maps [0,15] to [-8,7]
|
|
159
|
+
n = nk_size_round_up_to_multiple_(n, 2);
|
|
160
|
+
nk_size_t n_bytes = n / 2;
|
|
161
|
+
nk_i32_t sum = 0;
|
|
162
|
+
for (nk_size_t i = 0; i < n_bytes; ++i) {
|
|
163
|
+
nk_i32_t a_low = (nk_i32_t)nk_i4x2_low_(a[i]);
|
|
164
|
+
nk_i32_t b_low = (nk_i32_t)nk_i4x2_low_(b[i]);
|
|
165
|
+
nk_i32_t a_high = (nk_i32_t)nk_i4x2_high_(a[i]);
|
|
166
|
+
nk_i32_t b_high = (nk_i32_t)nk_i4x2_high_(b[i]);
|
|
167
|
+
nk_i32_t diff_low = a_low - b_low, diff_high = a_high - b_high;
|
|
168
|
+
sum += diff_low * diff_low + diff_high * diff_high;
|
|
169
|
+
}
|
|
170
|
+
*result = (nk_u32_t)sum;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
NK_PUBLIC void nk_euclidean_i4_serial(nk_i4x2_t const *a, nk_i4x2_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
174
|
+
nk_u32_t distance_sq;
|
|
175
|
+
nk_sqeuclidean_i4_serial(a, b, n, &distance_sq);
|
|
176
|
+
*result = nk_f32_sqrt_serial((nk_f32_t)distance_sq);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
NK_PUBLIC void nk_angular_i4_serial(nk_i4x2_t const *a, nk_i4x2_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
180
|
+
n = nk_size_round_up_to_multiple_(n, 2);
|
|
181
|
+
nk_size_t n_bytes = n / 2;
|
|
182
|
+
nk_i32_t dot_sum = 0, a_norm_sq = 0, b_norm_sq = 0;
|
|
183
|
+
for (nk_size_t i = 0; i < n_bytes; ++i) {
|
|
184
|
+
nk_i32_t a_low = (nk_i32_t)nk_i4x2_low_(a[i]);
|
|
185
|
+
nk_i32_t b_low = (nk_i32_t)nk_i4x2_low_(b[i]);
|
|
186
|
+
nk_i32_t a_high = (nk_i32_t)nk_i4x2_high_(a[i]);
|
|
187
|
+
nk_i32_t b_high = (nk_i32_t)nk_i4x2_high_(b[i]);
|
|
188
|
+
dot_sum += a_low * b_low + a_high * b_high;
|
|
189
|
+
a_norm_sq += a_low * a_low + a_high * a_high;
|
|
190
|
+
b_norm_sq += b_low * b_low + b_high * b_high;
|
|
191
|
+
}
|
|
192
|
+
if (a_norm_sq == 0 && b_norm_sq == 0) { *result = 0; }
|
|
193
|
+
else if (dot_sum == 0) { *result = 1; }
|
|
194
|
+
else {
|
|
195
|
+
nk_f32_t unclipped = 1.0f - (nk_f32_t)dot_sum * nk_f32_rsqrt_serial((nk_f32_t)a_norm_sq) *
|
|
196
|
+
nk_f32_rsqrt_serial((nk_f32_t)b_norm_sq);
|
|
197
|
+
*result = unclipped > 0 ? unclipped : 0;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
NK_PUBLIC void nk_sqeuclidean_u4_serial(nk_u4x2_t const *a, nk_u4x2_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
202
|
+
// u4 values are packed as nibbles: two 4-bit unsigned values per byte.
|
|
203
|
+
// Parameter `n` is the number of 4-bit values (dimensions), not bytes.
|
|
204
|
+
// No sign extension needed - values are in [0,15].
|
|
205
|
+
n = nk_size_round_up_to_multiple_(n, 2);
|
|
206
|
+
nk_size_t n_bytes = n / 2;
|
|
207
|
+
nk_u32_t sum = 0;
|
|
208
|
+
for (nk_size_t i = 0; i < n_bytes; ++i) {
|
|
209
|
+
nk_i32_t a_low = (nk_i32_t)nk_u4x2_low_(a[i]);
|
|
210
|
+
nk_i32_t b_low = (nk_i32_t)nk_u4x2_low_(b[i]);
|
|
211
|
+
nk_i32_t a_high = (nk_i32_t)nk_u4x2_high_(a[i]);
|
|
212
|
+
nk_i32_t b_high = (nk_i32_t)nk_u4x2_high_(b[i]);
|
|
213
|
+
nk_i32_t diff_low = a_low - b_low, diff_high = a_high - b_high;
|
|
214
|
+
sum += (nk_u32_t)(diff_low * diff_low + diff_high * diff_high);
|
|
215
|
+
}
|
|
216
|
+
*result = sum;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
NK_PUBLIC void nk_euclidean_u4_serial(nk_u4x2_t const *a, nk_u4x2_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
220
|
+
nk_u32_t distance_sq;
|
|
221
|
+
nk_sqeuclidean_u4_serial(a, b, n, &distance_sq);
|
|
222
|
+
*result = nk_f32_sqrt_serial((nk_f32_t)distance_sq);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
NK_PUBLIC void nk_angular_u4_serial(nk_u4x2_t const *a, nk_u4x2_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
226
|
+
n = nk_size_round_up_to_multiple_(n, 2);
|
|
227
|
+
nk_size_t n_bytes = n / 2;
|
|
228
|
+
nk_u32_t dot_sum = 0, a_norm_sq = 0, b_norm_sq = 0;
|
|
229
|
+
for (nk_size_t i = 0; i < n_bytes; ++i) {
|
|
230
|
+
nk_u32_t a_low = (nk_u32_t)nk_u4x2_low_(a[i]);
|
|
231
|
+
nk_u32_t b_low = (nk_u32_t)nk_u4x2_low_(b[i]);
|
|
232
|
+
nk_u32_t a_high = (nk_u32_t)nk_u4x2_high_(a[i]);
|
|
233
|
+
nk_u32_t b_high = (nk_u32_t)nk_u4x2_high_(b[i]);
|
|
234
|
+
dot_sum += a_low * b_low + a_high * b_high;
|
|
235
|
+
a_norm_sq += a_low * a_low + a_high * a_high;
|
|
236
|
+
b_norm_sq += b_low * b_low + b_high * b_high;
|
|
237
|
+
}
|
|
238
|
+
if (a_norm_sq == 0 && b_norm_sq == 0) { *result = 0; }
|
|
239
|
+
else if (dot_sum == 0) { *result = 1; }
|
|
240
|
+
else {
|
|
241
|
+
nk_f32_t unclipped = 1.0f - (nk_f32_t)dot_sum * nk_f32_rsqrt_serial((nk_f32_t)a_norm_sq) *
|
|
242
|
+
nk_f32_rsqrt_serial((nk_f32_t)b_norm_sq);
|
|
243
|
+
*result = unclipped > 0 ? unclipped : 0;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** @brief Angular from_dot: computes 1 − dot × rsqrt(query_sumsq × target_sumsq) for 4 pairs (serial). */
|
|
248
|
+
NK_INTERNAL void nk_angular_through_f32_from_dot_serial_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
|
|
249
|
+
nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
|
|
250
|
+
for (int i = 0; i < 4; ++i) {
|
|
251
|
+
nk_f32_t product = query_sumsq * target_sumsqs.f32s[i];
|
|
252
|
+
if (product > 0) {
|
|
253
|
+
nk_f32_t rsqrt_val = nk_f32_rsqrt_serial(product);
|
|
254
|
+
nk_f32_t normalized = dots.f32s[i] * rsqrt_val;
|
|
255
|
+
nk_f32_t result = 1.0f - normalized;
|
|
256
|
+
results->f32s[i] = result > 0 ? result : 0;
|
|
257
|
+
}
|
|
258
|
+
else { results->f32s[i] = (dots.f32s[i] == 0) ? 0.0f : 1.0f; }
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** @brief Euclidean from_dot: computes √(query_sumsq + target_sumsq − 2 × dot) for 4 pairs (serial). */
|
|
263
|
+
NK_INTERNAL void nk_euclidean_through_f32_from_dot_serial_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
|
|
264
|
+
nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
|
|
265
|
+
for (int i = 0; i < 4; ++i) {
|
|
266
|
+
nk_f32_t dist_sq = query_sumsq + target_sumsqs.f32s[i] - 2.0f * dots.f32s[i];
|
|
267
|
+
results->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** @brief Angular from_dot for f64 precision. */
|
|
272
|
+
NK_INTERNAL void nk_angular_through_f64_from_dot_serial_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
|
|
273
|
+
nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
|
|
274
|
+
for (int i = 0; i < 4; ++i) {
|
|
275
|
+
nk_f64_t product = query_sumsq * target_sumsqs.f64s[i];
|
|
276
|
+
if (product > 0) {
|
|
277
|
+
nk_f64_t rsqrt_val = nk_f64_rsqrt_serial(product);
|
|
278
|
+
nk_f64_t normalized = dots.f64s[i] * rsqrt_val;
|
|
279
|
+
nk_f64_t result = 1.0 - normalized;
|
|
280
|
+
results->f64s[i] = result > 0 ? result : 0;
|
|
281
|
+
}
|
|
282
|
+
else { results->f64s[i] = (dots.f64s[i] == 0) ? 0.0 : 1.0; }
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** @brief Euclidean from_dot for f64 precision. */
|
|
287
|
+
NK_INTERNAL void nk_euclidean_through_f64_from_dot_serial_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
|
|
288
|
+
nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
|
|
289
|
+
for (int i = 0; i < 4; ++i) {
|
|
290
|
+
nk_f64_t dist_sq = query_sumsq + target_sumsqs.f64s[i] - 2.0 * dots.f64s[i];
|
|
291
|
+
results->f64s[i] = dist_sq > 0 ? nk_f64_sqrt_serial(dist_sq) : 0.0;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** @brief Angular from_dot for i32 accumulators: cast to f32, then same math as f32 variant. */
|
|
296
|
+
NK_INTERNAL void nk_angular_through_i32_from_dot_serial_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
|
|
297
|
+
nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
|
|
298
|
+
for (int i = 0; i < 4; ++i) {
|
|
299
|
+
nk_f32_t product = (nk_f32_t)query_sumsq * (nk_f32_t)target_sumsqs.i32s[i];
|
|
300
|
+
if (product > 0) {
|
|
301
|
+
nk_f32_t rsqrt_val = nk_f32_rsqrt_serial(product);
|
|
302
|
+
nk_f32_t normalized = (nk_f32_t)dots.i32s[i] * rsqrt_val;
|
|
303
|
+
nk_f32_t result = 1.0f - normalized;
|
|
304
|
+
results->f32s[i] = result > 0 ? result : 0;
|
|
305
|
+
}
|
|
306
|
+
else { results->f32s[i] = (dots.i32s[i] == 0) ? 0.0f : 1.0f; }
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** @brief Euclidean from_dot for i32 accumulators: cast to f32, then same math as f32 variant. */
|
|
311
|
+
NK_INTERNAL void nk_euclidean_through_i32_from_dot_serial_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
|
|
312
|
+
nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
|
|
313
|
+
for (int i = 0; i < 4; ++i) {
|
|
314
|
+
nk_f32_t dist_sq = (nk_f32_t)query_sumsq + (nk_f32_t)target_sumsqs.i32s[i] - 2.0f * (nk_f32_t)dots.i32s[i];
|
|
315
|
+
results->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** @brief Angular from_dot for u32 accumulators: cast to f32, then same math as f32 variant. */
|
|
320
|
+
NK_INTERNAL void nk_angular_through_u32_from_dot_serial_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
|
|
321
|
+
nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
|
|
322
|
+
for (int i = 0; i < 4; ++i) {
|
|
323
|
+
nk_f32_t product = (nk_f32_t)query_sumsq * (nk_f32_t)target_sumsqs.u32s[i];
|
|
324
|
+
if (product > 0) {
|
|
325
|
+
nk_f32_t rsqrt_val = nk_f32_rsqrt_serial(product);
|
|
326
|
+
nk_f32_t normalized = (nk_f32_t)dots.u32s[i] * rsqrt_val;
|
|
327
|
+
nk_f32_t result = 1.0f - normalized;
|
|
328
|
+
results->f32s[i] = result > 0 ? result : 0;
|
|
329
|
+
}
|
|
330
|
+
else { results->f32s[i] = (dots.u32s[i] == 0) ? 0.0f : 1.0f; }
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** @brief Euclidean from_dot for u32 accumulators: cast to f32, then same math as f32 variant. */
|
|
335
|
+
NK_INTERNAL void nk_euclidean_through_u32_from_dot_serial_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
|
|
336
|
+
nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
|
|
337
|
+
for (int i = 0; i < 4; ++i) {
|
|
338
|
+
nk_f32_t dist_sq = (nk_f32_t)query_sumsq + (nk_f32_t)target_sumsqs.u32s[i] - 2.0f * (nk_f32_t)dots.u32s[i];
|
|
339
|
+
results->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
#if defined(__cplusplus)
|
|
344
|
+
} // extern "C"
|
|
345
|
+
#endif
|
|
346
|
+
|
|
347
|
+
#endif // NK_SPATIAL_SERIAL_H
|