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
|
@@ -1,2567 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file simsimd.h
|
|
3
|
-
* @brief SIMD-accelerated Similarity Measures and Distance Functions.
|
|
4
|
-
* @author Ash Vardanian
|
|
5
|
-
* @date March 14, 2023
|
|
6
|
-
*
|
|
7
|
-
* References:
|
|
8
|
-
* x86 intrinsics: https://www.intel.com/content/www/us/en/docs/intrinsics-guide
|
|
9
|
-
* Arm intrinsics: https://developer.arm.com/architectures/instruction-sets/intrinsics
|
|
10
|
-
* Detecting target CPU features at compile time: https://stackoverflow.com/a/28939692/2766161
|
|
11
|
-
*
|
|
12
|
-
* @section Choosing x86 Target Generations
|
|
13
|
-
*
|
|
14
|
-
* It's important to provide fine-grained controls over AVX512 families, as they are very fragmented:
|
|
15
|
-
*
|
|
16
|
-
* - Intel Skylake servers: F, CD, VL, DQ, BW
|
|
17
|
-
* - Intel Cascade Lake workstations: F, CD, VL, DQ, BW, VNNI
|
|
18
|
-
* > In other words, it extends Skylake with VNNI support
|
|
19
|
-
* - Intel Sunny Cove (Ice Lake) servers:
|
|
20
|
-
* F, CD, VL, DQ, BW, VNNI, VPOPCNTDQ, IFMA, VBMI, VAES, GFNI, VBMI2, BITALG, VPCLMULQDQ
|
|
21
|
-
* - AMD Zen4 (Genoa):
|
|
22
|
-
* F, CD, VL, DQ, BW, VNNI, VPOPCNTDQ, IFMA, VBMI, VAES, GFNI, VBMI2, BITALG, VPCLMULQDQ, BF16
|
|
23
|
-
* > In other words, it extends Sunny Cove with BF16 support
|
|
24
|
-
* - Intel Golden Cove (Sapphire Rapids): extends Zen4 and Sunny Cove with FP16 support
|
|
25
|
-
* - AMD Zen5 (Turin): makes VP2INTERSECT cool again
|
|
26
|
-
*
|
|
27
|
-
* Intel Palm Cove was an irrelevant intermediate release extending Skylake with IFMA and VBMI.
|
|
28
|
-
* Intel Willow Cove was an irrelevant intermediate release extending Sunny Cove with VP2INTERSECT,
|
|
29
|
-
* which are not supported by other CPUs to date and are only available in Tiger Lake laptops.
|
|
30
|
-
* Intel Cooper Lake was the only intermediary platform, that supported BF16, but not FP16.
|
|
31
|
-
* It's mostly used in 4-socket and 8-socket high-memory configurations.
|
|
32
|
-
*
|
|
33
|
-
* For us, it makes sense to differentiate only these AVX512 generations:
|
|
34
|
-
* 1. Intel Skylake (pre 2019): supports single-precision dot-products.
|
|
35
|
-
* 2. Intel Ice Lake (2019-2021): advanced integer algorithms.
|
|
36
|
-
* 3. AMD Genoa (2023+): brain-floating point support.
|
|
37
|
-
* 4. Intel Sapphire Rapids (2023+): advanced mixed-precision float processing.
|
|
38
|
-
* 5. AMD Turin (2024+): advanced sparse algorithms.
|
|
39
|
-
*
|
|
40
|
-
* Beyond those, we support AVX2 for old Haswell generation CPUs, and AVX2+VNNI for modern Sierra generation.
|
|
41
|
-
*
|
|
42
|
-
* To list all available macros for x86, take a recent compiler, like GCC 12 and run:
|
|
43
|
-
* gcc-12 -march=sapphirerapids -dM -E - < /dev/null | egrep "SSE|AVX" | sort
|
|
44
|
-
* On Arm machines you may want to check for other flags:
|
|
45
|
-
* gcc-12 -march=native -dM -E - < /dev/null | egrep "NEON|SVE|FP16|FMA" | sort
|
|
46
|
-
*
|
|
47
|
-
* @section Choosing Arm Target Generations
|
|
48
|
-
*
|
|
49
|
-
* Arm CPUs share design IP, but are produced by different vendors, potentially making the platform
|
|
50
|
-
* even more fragmented than x86. There are 2 important families of SIMD extensions - NEON and SVE.
|
|
51
|
-
*
|
|
52
|
-
* - Armv8-A: +fp, +simd
|
|
53
|
-
* - Armv8.1-A: armv8-a, +crc, +lse, +rdma
|
|
54
|
-
* - Armv8.2-A: armv8.1-a
|
|
55
|
-
* - Armv8.3-A: armv8.2-a, +pauth
|
|
56
|
-
* - Armv8.4-A: armv8.3-a, +flagm, +fp16fml, +dotprod
|
|
57
|
-
* - Armv8.5-A: armv8.4-a, +sb, +ssbs, +predres
|
|
58
|
-
* - Armv8.6-A: armv8.5-a, +bf16, +i8mm
|
|
59
|
-
* - Armv8.7-A: armv8.6-a, +ls64
|
|
60
|
-
* - Armv8.8-A: armv8.7-a, +mops
|
|
61
|
-
* - Armv8.9-A: armv8.8-a
|
|
62
|
-
* - Armv9-A: armv8.5-a, +sve, +sve2
|
|
63
|
-
* - Armv9.1-A: armv9-a, +bf16, +i8mm
|
|
64
|
-
* - Armv9.2-A: armv9.1-a, +ls64
|
|
65
|
-
* - Armv9.3-A: armv9.2-a, +mops
|
|
66
|
-
* - Armv9.4-A: armv9.3-a
|
|
67
|
-
*
|
|
68
|
-
* SVE has been optional since Armv8.2-A, but it's a requirement for Armv9.0-A.
|
|
69
|
-
* A 512-bit SVE variant has already been implemented on the Fugaku supercomputer.
|
|
70
|
-
* A more flexible version, 2x256 SVE, was implemented by the AWS Graviton3 ARM processor.
|
|
71
|
-
* Here are the most important recent families of CPU cores designed by Arm:
|
|
72
|
-
*
|
|
73
|
-
* - Neoverse N1: armv8.2-a, extended with Armv8.4 "dotprod" instructions.
|
|
74
|
-
* Used in AWS @b Graviton2 and Ampere @b Altra.
|
|
75
|
-
* https://developer.arm.com/Processors/Neoverse%20N1
|
|
76
|
-
* - Neoverse V1: armv8.4-a, extended with Armv8.6 bfloat/int8 "matmul" instructions.
|
|
77
|
-
* Used in AWS @b Graviton3, which also enables `sve`, `svebf16`, and `svei8mm`.
|
|
78
|
-
* https://developer.arm.com/Processors/Neoverse%20V1
|
|
79
|
-
* - Neoverse V2: armv9.0 with SVE2 and SVE bit-permutes
|
|
80
|
-
* Used in AWS @b Graviton4, NVIDIA @b Grace, Google @b Axion.
|
|
81
|
-
* https://developer.arm.com/Processors/Neoverse%20V2
|
|
82
|
-
* The N2 core is very similar to V2 and is used by Microsoft @b Cobalt.
|
|
83
|
-
* https://developer.arm.com/Processors/Neoverse%20N2
|
|
84
|
-
*
|
|
85
|
-
* On the consumer side, Apple is the biggest player with mobile @b A chips and desktop @b M chips.
|
|
86
|
-
* The M1 implements Armv8.5-A, both M2 and M3 implement Armv8.6-A, and M4 is expected to have Armv9.1-A.
|
|
87
|
-
*/
|
|
88
|
-
|
|
89
|
-
#ifndef SIMSIMD_H
|
|
90
|
-
#define SIMSIMD_H
|
|
91
|
-
|
|
92
|
-
#define SIMSIMD_VERSION_MAJOR 6
|
|
93
|
-
#define SIMSIMD_VERSION_MINOR 5
|
|
94
|
-
#define SIMSIMD_VERSION_PATCH 5
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @brief Removes compile-time dispatching, and replaces it with runtime dispatching.
|
|
98
|
-
* So the `simsimd_dot_f32` function will invoke the most advanced backend supported by the CPU,
|
|
99
|
-
* that runs the program, rather than the most advanced backend supported by the CPU
|
|
100
|
-
* used to compile the library or the downstream application.
|
|
101
|
-
*/
|
|
102
|
-
#if !defined(SIMSIMD_DYNAMIC_DISPATCH)
|
|
103
|
-
#define SIMSIMD_DYNAMIC_DISPATCH (0) // true or false
|
|
104
|
-
#endif
|
|
105
|
-
|
|
106
|
-
#include "binary.h" // Hamming, Jaccard
|
|
107
|
-
#include "curved.h" // Mahalanobis, Bilinear Forms
|
|
108
|
-
#include "dot.h" // Inner (dot) product, and its conjugate
|
|
109
|
-
#include "elementwise.h" // Weighted Sum, Fused-Multiply-Add
|
|
110
|
-
#include "geospatial.h" // Haversine and Vincenty
|
|
111
|
-
#include "probability.h" // Kullback-Leibler, Jensen–Shannon
|
|
112
|
-
#include "sparse.h" // Intersect
|
|
113
|
-
#include "spatial.h" // L2, Cosine
|
|
114
|
-
|
|
115
|
-
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
116
|
-
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
117
|
-
#include <fenv.h> // `fesetenv` - part of C 99 standard
|
|
118
|
-
#include <sys/sysctl.h> // `sysctlbyname`
|
|
119
|
-
#endif
|
|
120
|
-
|
|
121
|
-
// Detect POSIX extensions availability for signal handling.
|
|
122
|
-
// POSIX extensions provide `sigaction`, `sigjmp_buf`, and `sigsetjmp` for safe signal handling.
|
|
123
|
-
// These are needed on Linux ARM for safely testing `mrs` instruction availability.
|
|
124
|
-
#if defined(_SIMSIMD_DEFINED_LINUX) && defined(_POSIX_VERSION)
|
|
125
|
-
#include <setjmp.h> // `sigjmp_buf`, `sigsetjmp`, `siglongjmp`
|
|
126
|
-
#include <signal.h> // `sigaction`, `SIGILL`
|
|
127
|
-
#define _SIMSIMD_HAS_POSIX_EXTENSIONS 1
|
|
128
|
-
#else
|
|
129
|
-
#define _SIMSIMD_HAS_POSIX_EXTENSIONS 0
|
|
130
|
-
#endif
|
|
131
|
-
|
|
132
|
-
// On Windows ARM, we use IsProcessorFeaturePresent API for capability detection
|
|
133
|
-
#if defined(_SIMSIMD_DEFINED_WINDOWS) && _SIMSIMD_TARGET_ARM
|
|
134
|
-
#include <processthreadsapi.h> // `IsProcessorFeaturePresent`
|
|
135
|
-
#endif
|
|
136
|
-
|
|
137
|
-
#ifdef __cplusplus
|
|
138
|
-
extern "C" {
|
|
139
|
-
#endif
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* @brief Enumeration of supported metric kinds.
|
|
143
|
-
* Some have aliases for convenience.
|
|
144
|
-
*/
|
|
145
|
-
typedef enum {
|
|
146
|
-
simsimd_metric_unknown_k = 0, ///< Unknown metric kind
|
|
147
|
-
|
|
148
|
-
// Classics:
|
|
149
|
-
simsimd_metric_dot_k = 'i', ///< Inner product
|
|
150
|
-
simsimd_metric_inner_k = 'i', ///< Inner product alias
|
|
151
|
-
|
|
152
|
-
simsimd_metric_vdot_k = 'v', ///< Complex inner product
|
|
153
|
-
|
|
154
|
-
simsimd_metric_cos_k = 'c', ///< Cosine similarity
|
|
155
|
-
simsimd_metric_cosine_k = 'c', ///< Cosine similarity alias
|
|
156
|
-
simsimd_metric_angular_k = 'c', ///< Cosine similarity alias
|
|
157
|
-
|
|
158
|
-
simsimd_metric_l2_k = '2', ///< Euclidean distance alias
|
|
159
|
-
simsimd_metric_euclidean_k = '2', ///< Euclidean distance alias
|
|
160
|
-
simsimd_metric_l2sq_k = 'e', ///< Squared Euclidean distance
|
|
161
|
-
simsimd_metric_sqeuclidean_k = 'e', ///< Squared Euclidean distance alias
|
|
162
|
-
|
|
163
|
-
// Binary:
|
|
164
|
-
simsimd_metric_hamming_k = 'h', ///< Hamming distance
|
|
165
|
-
simsimd_metric_manhattan_k = 'h', ///< Manhattan distance is same as Hamming
|
|
166
|
-
|
|
167
|
-
simsimd_metric_jaccard_k = 'j', ///< Jaccard coefficient
|
|
168
|
-
simsimd_metric_tanimoto_k = 'j', ///< Tanimoto coefficient is same as Jaccard
|
|
169
|
-
|
|
170
|
-
// Sets:
|
|
171
|
-
simsimd_metric_intersect_k = 'x', ///< Equivalent to unnormalized Jaccard
|
|
172
|
-
simsimd_metric_spdot_counts_k = 'y', ///< Sparse sets with integer weights
|
|
173
|
-
simsimd_metric_spdot_weights_k = 'z', ///< Sparse sets with brain floating-point weights
|
|
174
|
-
|
|
175
|
-
// Curved Spaces:
|
|
176
|
-
simsimd_metric_bilinear_k = 'b', ///< Bilinear form
|
|
177
|
-
simsimd_metric_mahalanobis_k = 'm', ///< Mahalanobis distance
|
|
178
|
-
|
|
179
|
-
// Probability:
|
|
180
|
-
simsimd_metric_kl_k = 'k', ///< Kullback-Leibler divergence
|
|
181
|
-
simsimd_metric_kullback_leibler_k = 'k', ///< Kullback-Leibler divergence alias
|
|
182
|
-
|
|
183
|
-
simsimd_metric_js_k = 's', ///< Jensen-Shannon divergence
|
|
184
|
-
simsimd_metric_jensen_shannon_k = 's', ///< Jensen-Shannon divergence alias
|
|
185
|
-
|
|
186
|
-
// BLAS-like operations:
|
|
187
|
-
simsimd_metric_fma_k = 'f', ///< Fused Multiply-Add
|
|
188
|
-
simsimd_metric_wsum_k = 'w', ///< Weighted Sum
|
|
189
|
-
|
|
190
|
-
} simsimd_metric_kind_t;
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* @brief Enumeration of SIMD capabilities of the target architecture.
|
|
194
|
-
*/
|
|
195
|
-
typedef enum {
|
|
196
|
-
simsimd_cap_serial_k = 1, ///< Serial (non-SIMD) capability
|
|
197
|
-
simsimd_cap_any_k = 0x7FFFFFFF, ///< Mask representing any capability with `INT_MAX`
|
|
198
|
-
|
|
199
|
-
simsimd_cap_haswell_k = 1 << 10, ///< x86 AVX2 capability with FMA and F16C extensions
|
|
200
|
-
simsimd_cap_skylake_k = 1 << 11, ///< x86 AVX512 baseline capability
|
|
201
|
-
simsimd_cap_ice_k = 1 << 12, ///< x86 AVX512 capability with advanced integer algos
|
|
202
|
-
simsimd_cap_genoa_k = 1 << 13, ///< x86 AVX512 capability with `bf16` support
|
|
203
|
-
simsimd_cap_sapphire_k = 1 << 14, ///< x86 AVX512 capability with `f16` support
|
|
204
|
-
simsimd_cap_turin_k = 1 << 15, ///< x86 AVX512 capability with conflict detection
|
|
205
|
-
simsimd_cap_sierra_k = 1 << 16, ///< x86 AVX2+VNNI capability with `i8` dot-products
|
|
206
|
-
|
|
207
|
-
simsimd_cap_neon_k = 1 << 20, ///< ARM NEON baseline capability
|
|
208
|
-
simsimd_cap_neon_f16_k = 1 << 21, ///< ARM NEON `f16` capability
|
|
209
|
-
simsimd_cap_neon_bf16_k = 1 << 22, ///< ARM NEON `bf16` capability
|
|
210
|
-
simsimd_cap_neon_i8_k = 1 << 23, ///< ARM NEON `i8` capability
|
|
211
|
-
simsimd_cap_sve_k = 1 << 24, ///< ARM SVE baseline capability
|
|
212
|
-
simsimd_cap_sve_f16_k = 1 << 25, ///< ARM SVE `f16` capability
|
|
213
|
-
simsimd_cap_sve_bf16_k = 1 << 26, ///< ARM SVE `bf16` capability
|
|
214
|
-
simsimd_cap_sve_i8_k = 1 << 27, ///< ARM SVE `i8` capability
|
|
215
|
-
simsimd_cap_sve2_k = 1 << 28, ///< ARM SVE2 capability
|
|
216
|
-
simsimd_cap_sve2p1_k = 1 << 29, ///< ARM SVE2p1 capability
|
|
217
|
-
|
|
218
|
-
} simsimd_capability_t;
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* @brief Enumeration of supported data types.
|
|
222
|
-
*
|
|
223
|
-
* Includes complex type descriptors which in C code would use the real counterparts,
|
|
224
|
-
* but the independent flags contain metadata to be passed between programming language
|
|
225
|
-
* interfaces.
|
|
226
|
-
*/
|
|
227
|
-
typedef enum {
|
|
228
|
-
simsimd_datatype_unknown_k = 0, ///< Unknown data type
|
|
229
|
-
simsimd_datatype_b8_k = 1 << 1, ///< Single-bit values packed into 8-bit words
|
|
230
|
-
simsimd_datatype_b1x8_k = simsimd_datatype_b8_k, ///< Single-bit values packed into 8-bit words
|
|
231
|
-
simsimd_datatype_i4x2_k = 1 << 19, ///< 4-bit signed integers packed into 8-bit words
|
|
232
|
-
|
|
233
|
-
simsimd_datatype_i8_k = 1 << 2, ///< 8-bit signed integer
|
|
234
|
-
simsimd_datatype_i16_k = 1 << 3, ///< 16-bit signed integer
|
|
235
|
-
simsimd_datatype_i32_k = 1 << 4, ///< 32-bit signed integer
|
|
236
|
-
simsimd_datatype_i64_k = 1 << 5, ///< 64-bit signed integer
|
|
237
|
-
|
|
238
|
-
simsimd_datatype_u8_k = 1 << 6, ///< 8-bit unsigned integer
|
|
239
|
-
simsimd_datatype_u16_k = 1 << 7, ///< 16-bit unsigned integer
|
|
240
|
-
simsimd_datatype_u32_k = 1 << 8, ///< 32-bit unsigned integer
|
|
241
|
-
simsimd_datatype_u64_k = 1 << 9, ///< 64-bit unsigned integer
|
|
242
|
-
|
|
243
|
-
simsimd_datatype_f64_k = 1 << 10, ///< Double precision floating point
|
|
244
|
-
simsimd_datatype_f32_k = 1 << 11, ///< Single precision floating point
|
|
245
|
-
simsimd_datatype_f16_k = 1 << 12, ///< Half precision floating point
|
|
246
|
-
simsimd_datatype_bf16_k = 1 << 13, ///< Brain floating point
|
|
247
|
-
|
|
248
|
-
simsimd_datatype_f64c_k = 1 << 20, ///< Complex double precision floating point
|
|
249
|
-
simsimd_datatype_f32c_k = 1 << 21, ///< Complex single precision floating point
|
|
250
|
-
simsimd_datatype_f16c_k = 1 << 22, ///< Complex half precision floating point
|
|
251
|
-
simsimd_datatype_bf16c_k = 1 << 23, ///< Complex brain floating point
|
|
252
|
-
} simsimd_datatype_t;
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* @brief Type-punned function pointer for dense vector representations and simplest similarity measures.
|
|
256
|
-
*
|
|
257
|
-
* @param[in] a Pointer to the first data array.
|
|
258
|
-
* @param[in] b Pointer to the second data array.
|
|
259
|
-
* @param[in] n Number of scalar words in the input arrays.
|
|
260
|
-
* When dealing with sub-byte types, the number of scalar words is the number of bytes.
|
|
261
|
-
* When dealing with complex types, the number of scalar words is the sum of real and imaginary parts.
|
|
262
|
-
* @param[out] d Output value as a double-precision float.
|
|
263
|
-
* In complex dot-products @b two scalars are exported for the real and imaginary parts.
|
|
264
|
-
*/
|
|
265
|
-
typedef void (*simsimd_metric_dense_punned_t)(void const *a, void const *b, simsimd_size_t n, simsimd_distance_t *d);
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* @brief Type-punned function pointer for sparse vector representations and similarity measures.
|
|
269
|
-
*
|
|
270
|
-
* @param[in] a Pointer to the first data array, generally a sorted array of integers.
|
|
271
|
-
* @param[in] b Pointer to the second data array, generally a sorted array of integers.
|
|
272
|
-
* @param[in] a_length Number of scalar words in the first input array.
|
|
273
|
-
* @param[in] b_length Number of scalar words in the second input array.
|
|
274
|
-
* @param[out] d Output value as a double-precision float, generally without decimals.
|
|
275
|
-
*/
|
|
276
|
-
typedef void (*simsimd_metric_sparse_punned_t)( //
|
|
277
|
-
void const *a, void const *b, //
|
|
278
|
-
simsimd_size_t a_length, simsimd_size_t b_length, //
|
|
279
|
-
simsimd_distance_t *d);
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* @brief Type-punned function pointer for curved vector spaces and similarity measures.
|
|
283
|
-
*
|
|
284
|
-
* @param[in] a Pointer to the first data array.
|
|
285
|
-
* @param[in] b Pointer to the second data array.
|
|
286
|
-
* @param[in] c Pointer to the metric tensor array or some covariance matrix.
|
|
287
|
-
* @param[in] n Number of scalar words in the input arrays.
|
|
288
|
-
* @param[out] d Output value as a double-precision float.
|
|
289
|
-
*/
|
|
290
|
-
typedef void (*simsimd_metric_curved_punned_t)( //
|
|
291
|
-
void const *a, void const *b, void const *c, //
|
|
292
|
-
simsimd_size_t n, simsimd_distance_t *d);
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* @brief Type-punned function pointer for FMA operations on dense vector representations.
|
|
296
|
-
* Implements the `y = alpha * a * b + beta * c` operation.
|
|
297
|
-
*
|
|
298
|
-
* @param[in] a Pointer to the first data array.
|
|
299
|
-
* @param[in] b Pointer to the second data array.
|
|
300
|
-
* @param[in] c Pointer to the third data array.
|
|
301
|
-
* @param[in] n Number of scalar words in the input arrays.
|
|
302
|
-
* @param[in] alpha Scaling factor for the first two arrays.
|
|
303
|
-
* @param[in] beta Scaling factor for the third array.
|
|
304
|
-
* @param[out] y Output value in the same precision as the input arrays.
|
|
305
|
-
*/
|
|
306
|
-
typedef void (*simsimd_kernel_fma_punned_t)( //
|
|
307
|
-
void const *a, void const *b, void const *c, //
|
|
308
|
-
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta, void *y);
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* @brief Type-punned function pointer for Weighted Sum operations on dense vector representations.
|
|
312
|
-
* Implements the `y = alpha * a + beta * b` operation.
|
|
313
|
-
*
|
|
314
|
-
* @param[in] a Pointer to the first data array.
|
|
315
|
-
* @param[in] b Pointer to the second data array.
|
|
316
|
-
* @param[in] n Number of scalar words in the input arrays.
|
|
317
|
-
* @param[in] alpha Scaling factor for the first array.
|
|
318
|
-
* @param[in] beta Scaling factor for the second array.
|
|
319
|
-
* @param[out] y Output value in the same precision as the input arrays.
|
|
320
|
-
*/
|
|
321
|
-
typedef void (*simsimd_kernel_wsum_punned_t)( //
|
|
322
|
-
void const *a, void const *b, //
|
|
323
|
-
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta, void *y);
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* @brief Type-punned function pointer for a SimSIMD public interface.
|
|
327
|
-
*
|
|
328
|
-
* Can be a `simsimd_metric_dense_punned_t`, `simsimd_metric_sparse_punned_t`, `simsimd_metric_curved_punned_t`,
|
|
329
|
-
* `simsimd_kernel_fma_punned_t`, or `simsimd_kernel_wsum_punned_t`.
|
|
330
|
-
*/
|
|
331
|
-
typedef void (*simsimd_kernel_punned_t)(void *);
|
|
332
|
-
|
|
333
|
-
#if SIMSIMD_DYNAMIC_DISPATCH
|
|
334
|
-
SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void);
|
|
335
|
-
SIMSIMD_DYNAMIC void simsimd_find_kernel_punned( //
|
|
336
|
-
simsimd_metric_kind_t kind, //
|
|
337
|
-
simsimd_datatype_t datatype, //
|
|
338
|
-
simsimd_capability_t supported, //
|
|
339
|
-
simsimd_capability_t allowed, //
|
|
340
|
-
simsimd_kernel_punned_t *kernel_output, //
|
|
341
|
-
simsimd_capability_t *capability_output);
|
|
342
|
-
SIMSIMD_DYNAMIC int simsimd_flush_denormals(void);
|
|
343
|
-
#else
|
|
344
|
-
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void);
|
|
345
|
-
SIMSIMD_PUBLIC void simsimd_find_kernel_punned( //
|
|
346
|
-
simsimd_metric_kind_t kind, //
|
|
347
|
-
simsimd_datatype_t datatype, //
|
|
348
|
-
simsimd_capability_t supported, //
|
|
349
|
-
simsimd_capability_t allowed, //
|
|
350
|
-
simsimd_kernel_punned_t *kernel_output, //
|
|
351
|
-
simsimd_capability_t *capability_output);
|
|
352
|
-
SIMSIMD_PUBLIC int simsimd_flush_denormals(void);
|
|
353
|
-
#endif
|
|
354
|
-
|
|
355
|
-
#if _SIMSIMD_TARGET_X86
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* @brief Function to flush denormalized numbers to zero on x86 CPUs.
|
|
359
|
-
* @note This should be called on each thread before any SIMD operations to avoid performance penalties.
|
|
360
|
-
* @return 1 if the operation was successful, 0 otherwise.
|
|
361
|
-
*/
|
|
362
|
-
SIMSIMD_PUBLIC int _simsimd_flush_denormals_x86(void) {
|
|
363
|
-
#if defined(_MSC_VER)
|
|
364
|
-
unsigned int mxcsr = _mm_getcsr();
|
|
365
|
-
mxcsr |= 1 << 15; // bit 15 = Flush-To-Zero (FTZ)
|
|
366
|
-
mxcsr |= 1 << 6; // bit 6 = Denormals-Are-Zero (DAZ)
|
|
367
|
-
_mm_setcsr(mxcsr);
|
|
368
|
-
#else // GCC, Clang, ICC
|
|
369
|
-
unsigned int mxcsr;
|
|
370
|
-
__asm__ __volatile__("stmxcsr %0" : "=m"(mxcsr));
|
|
371
|
-
mxcsr |= 1 << 15; // bit 15 = Flush-To-Zero (FTZ)
|
|
372
|
-
mxcsr |= 1 << 6; // bit 6 = Denormals-Are-Zero (DAZ)
|
|
373
|
-
__asm__ __volatile__("ldmxcsr %0" : : "m"(mxcsr));
|
|
374
|
-
#endif
|
|
375
|
-
return 1;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
380
|
-
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
381
|
-
*/
|
|
382
|
-
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_x86(void) {
|
|
383
|
-
|
|
384
|
-
/// The states of 4 registers populated for a specific "cpuid" assembly call
|
|
385
|
-
union four_registers_t {
|
|
386
|
-
int array[4];
|
|
387
|
-
struct separate_t {
|
|
388
|
-
unsigned eax, ebx, ecx, edx;
|
|
389
|
-
} named;
|
|
390
|
-
} info1, info7, info7sub1;
|
|
391
|
-
|
|
392
|
-
#if defined(_MSC_VER)
|
|
393
|
-
__cpuidex(info1.array, 1, 0);
|
|
394
|
-
__cpuidex(info7.array, 7, 0);
|
|
395
|
-
__cpuidex(info7sub1.array, 7, 1);
|
|
396
|
-
#else // GCC, Clang, ICC
|
|
397
|
-
__asm__ __volatile__( //
|
|
398
|
-
"cpuid"
|
|
399
|
-
: "=a"(info1.named.eax), "=b"(info1.named.ebx), "=c"(info1.named.ecx), "=d"(info1.named.edx)
|
|
400
|
-
: "a"(1), "c"(0));
|
|
401
|
-
__asm__ __volatile__( //
|
|
402
|
-
"cpuid"
|
|
403
|
-
: "=a"(info7.named.eax), "=b"(info7.named.ebx), "=c"(info7.named.ecx), "=d"(info7.named.edx)
|
|
404
|
-
: "a"(7), "c"(0));
|
|
405
|
-
__asm__ __volatile__( //
|
|
406
|
-
"cpuid"
|
|
407
|
-
: "=a"(info7sub1.named.eax), "=b"(info7sub1.named.ebx), "=c"(info7sub1.named.ecx), "=d"(info7sub1.named.edx)
|
|
408
|
-
: "a"(7), "c"(1));
|
|
409
|
-
#endif
|
|
410
|
-
|
|
411
|
-
// Check for AVX2 (Function ID 7, EBX register)
|
|
412
|
-
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L148
|
|
413
|
-
unsigned supports_avx2 = (info7.named.ebx & 0x00000020) != 0;
|
|
414
|
-
// Check for F16C (Function ID 1, ECX register)
|
|
415
|
-
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L107
|
|
416
|
-
unsigned supports_f16c = (info1.named.ecx & 0x20000000) != 0;
|
|
417
|
-
unsigned supports_fma = (info1.named.ecx & 0x00001000) != 0;
|
|
418
|
-
// Check for AVX512F (Function ID 7, EBX register)
|
|
419
|
-
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L155
|
|
420
|
-
unsigned supports_avx512f = (info7.named.ebx & 0x00010000) != 0;
|
|
421
|
-
// Check for AVX512FP16 (Function ID 7, EDX register)
|
|
422
|
-
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L198C9-L198C23
|
|
423
|
-
unsigned supports_avx512fp16 = (info7.named.edx & 0x00800000) != 0;
|
|
424
|
-
// Check for AVX512VNNI (Function ID 7, ECX register)
|
|
425
|
-
unsigned supports_avx512vnni = (info7.named.ecx & 0x00000800) != 0;
|
|
426
|
-
// Check for AVX512IFMA (Function ID 7, EBX register)
|
|
427
|
-
unsigned supports_avx512ifma = (info7.named.ebx & 0x00200000) != 0;
|
|
428
|
-
// Check for AVX512BITALG (Function ID 7, ECX register)
|
|
429
|
-
unsigned supports_avx512bitalg = (info7.named.ecx & 0x00001000) != 0;
|
|
430
|
-
// Check for AVX512VBMI2 (Function ID 7, ECX register)
|
|
431
|
-
unsigned supports_avx512vbmi2 = (info7.named.ecx & 0x00000040) != 0;
|
|
432
|
-
// Check for AVX512VPOPCNTDQ (Function ID 7, ECX register)
|
|
433
|
-
unsigned supports_avx512vpopcntdq = (info7.named.ecx & 0x00004000) != 0;
|
|
434
|
-
// Check for AVX512BF16 (Function ID 7, Sub-leaf 1, EAX register)
|
|
435
|
-
// https://github.com/llvm/llvm-project/blob/50598f0ff44f3a4e75706f8c53f3380fe7faa896/clang/lib/Headers/cpuid.h#L205
|
|
436
|
-
unsigned supports_avx512bf16 = (info7sub1.named.eax & 0x00000020) != 0;
|
|
437
|
-
// Clang doesn't show the VP2INTERSECT flag, but we can get it from QEMU
|
|
438
|
-
// https://stackoverflow.com/a/68289220/2766161
|
|
439
|
-
unsigned supports_avx512vp2intersect = (info7.named.edx & 0x00000100) != 0;
|
|
440
|
-
|
|
441
|
-
// Convert specific features into CPU generations
|
|
442
|
-
unsigned supports_haswell = supports_avx2 && supports_f16c && supports_fma;
|
|
443
|
-
unsigned supports_skylake = supports_avx512f;
|
|
444
|
-
unsigned supports_ice = supports_avx512vnni && supports_avx512ifma && supports_avx512bitalg &&
|
|
445
|
-
supports_avx512vbmi2 && supports_avx512vpopcntdq;
|
|
446
|
-
unsigned supports_genoa = supports_avx512bf16;
|
|
447
|
-
unsigned supports_sapphire = supports_avx512fp16;
|
|
448
|
-
// We don't want to accidentally enable AVX512VP2INTERSECT on Intel Tiger Lake CPUs
|
|
449
|
-
unsigned supports_turin = supports_avx512vp2intersect && supports_avx512bf16;
|
|
450
|
-
unsigned supports_sierra = 0;
|
|
451
|
-
|
|
452
|
-
return (simsimd_capability_t)( //
|
|
453
|
-
(simsimd_cap_haswell_k * supports_haswell) | //
|
|
454
|
-
(simsimd_cap_skylake_k * supports_skylake) | //
|
|
455
|
-
(simsimd_cap_ice_k * supports_ice) | //
|
|
456
|
-
(simsimd_cap_genoa_k * supports_genoa) | //
|
|
457
|
-
(simsimd_cap_sapphire_k * supports_sapphire) | //
|
|
458
|
-
(simsimd_cap_turin_k * supports_turin) | //
|
|
459
|
-
(simsimd_cap_sierra_k * supports_sierra) | //
|
|
460
|
-
(simsimd_cap_serial_k));
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
#endif // _SIMSIMD_TARGET_X86
|
|
464
|
-
|
|
465
|
-
#if _SIMSIMD_TARGET_ARM
|
|
466
|
-
|
|
467
|
-
/* Compiling the next section one may get: selected processor does not support system register name 'id_aa64zfr0_el1'.
|
|
468
|
-
* Suppressing assembler errors is very complicated, so when dealing with older ARM CPUs it's simpler to compile this
|
|
469
|
-
* function targeting newer ones.
|
|
470
|
-
*/
|
|
471
|
-
#pragma GCC push_options
|
|
472
|
-
#pragma GCC target("arch=armv8.5-a+sve")
|
|
473
|
-
#pragma clang attribute push(__attribute__((target("arch=armv8.5-a+sve"))), apply_to = function)
|
|
474
|
-
|
|
475
|
-
#if _SIMSIMD_HAS_POSIX_EXTENSIONS
|
|
476
|
-
/** @brief SIGILL handler for `mrs` instruction testing on Linux ARM */
|
|
477
|
-
static sigjmp_buf _simsimd_mrs_test_jump_buffer;
|
|
478
|
-
static void _simsimd_mrs_test_sigill_handler(int sig) {
|
|
479
|
-
(void)sig; // Unused parameter
|
|
480
|
-
siglongjmp(_simsimd_mrs_test_jump_buffer, 1);
|
|
481
|
-
}
|
|
482
|
-
#endif
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* @brief Function to flush denormalized numbers to zero on Arm CPUs.
|
|
486
|
-
* @note This should be called on each thread before any SIMD operations to avoid performance penalties.
|
|
487
|
-
* @note On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
488
|
-
* @return 1 if the operation was successful, 0 otherwise.
|
|
489
|
-
*/
|
|
490
|
-
SIMSIMD_PUBLIC int _simsimd_flush_denormals_arm(void) {
|
|
491
|
-
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
492
|
-
// https://stackoverflow.com/a/19904907/2766161
|
|
493
|
-
// https://stackoverflow.com/a/78252076/2766161
|
|
494
|
-
int is_success = fesetenv(FE_DFL_DISABLE_DENORMS_ENV) == 0;
|
|
495
|
-
return is_success;
|
|
496
|
-
#elif defined(_SIMSIMD_DEFINED_LINUX)
|
|
497
|
-
// For Linux, we can toggle bits in the Floating-point Control Register (FPCR)
|
|
498
|
-
// https://developer.arm.com/documentation/ddi0601/2024-12/AArch64-Registers/FPCR--Floating-point-Control-Register
|
|
499
|
-
uint64_t fpcr;
|
|
500
|
-
__asm__ volatile("mrs %0, fpcr" : "=r"(fpcr));
|
|
501
|
-
fpcr |= (1 << 19); // bit 19 = FZ16 (Flush half-precision to zero)
|
|
502
|
-
fpcr |= (1 << 24); // bit 24 = FZ (Flush subnormals to zero)
|
|
503
|
-
fpcr |= (1 << 25); // bit 25 = DN (Force Default NaN instead of preserving payload)
|
|
504
|
-
__asm__ volatile("msr fpcr, %0" : : "r"(fpcr));
|
|
505
|
-
return 1;
|
|
506
|
-
#else
|
|
507
|
-
return 0;
|
|
508
|
-
#endif
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* @brief Function to determine the SIMD capabilities of the current 64-bit Arm machine at @b runtime.
|
|
513
|
-
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
514
|
-
*/
|
|
515
|
-
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_arm(void) {
|
|
516
|
-
#if defined(_SIMSIMD_DEFINED_APPLE)
|
|
517
|
-
// On Apple Silicon, `mrs` is not allowed in user-space, so we need to use the `sysctl` API.
|
|
518
|
-
unsigned supports_neon = 0, supports_fp16 = 0, supports_bf16 = 0, supports_i8mm = 0;
|
|
519
|
-
size_t size = sizeof(supports_neon);
|
|
520
|
-
if (sysctlbyname("hw.optional.neon", &supports_neon, &size, NULL, 0) != 0) supports_neon = 0;
|
|
521
|
-
if (sysctlbyname("hw.optional.arm.FEAT_FP16", &supports_fp16, &size, NULL, 0) != 0) supports_fp16 = 0;
|
|
522
|
-
if (sysctlbyname("hw.optional.arm.FEAT_BF16", &supports_bf16, &size, NULL, 0) != 0) supports_bf16 = 0;
|
|
523
|
-
if (sysctlbyname("hw.optional.arm.FEAT_I8MM", &supports_i8mm, &size, NULL, 0) != 0) supports_i8mm = 0;
|
|
524
|
-
|
|
525
|
-
return (simsimd_capability_t)( //
|
|
526
|
-
(simsimd_cap_neon_k * (supports_neon)) | //
|
|
527
|
-
(simsimd_cap_neon_f16_k * (supports_neon && supports_fp16)) | //
|
|
528
|
-
(simsimd_cap_neon_bf16_k * (supports_neon && supports_bf16)) | //
|
|
529
|
-
(simsimd_cap_neon_i8_k * (supports_neon && supports_i8mm)) | //
|
|
530
|
-
(simsimd_cap_serial_k));
|
|
531
|
-
|
|
532
|
-
#elif defined(_SIMSIMD_DEFINED_LINUX)
|
|
533
|
-
|
|
534
|
-
// Depending on the environment, reading system registers may cause SIGILL.
|
|
535
|
-
// One option to avoid the crash is to use `getauxval(AT_HWCAP)` and `getauxval(AT_HWCAP2)`,
|
|
536
|
-
// Linux APIs, but those aren't as informative as reading the registers directly.
|
|
537
|
-
// So before reading the ID registers, we set up a signal handler to catch SIGILL
|
|
538
|
-
// and probe one of the registers, reverting back to the old signal handler afterwards.
|
|
539
|
-
//
|
|
540
|
-
// This issue was originally observed in: https://github.com/ashvardanian/SimSIMD/issues/279
|
|
541
|
-
#if _SIMSIMD_HAS_POSIX_EXTENSIONS
|
|
542
|
-
struct sigaction action_new, action_old;
|
|
543
|
-
action_new.sa_handler = _simsimd_mrs_test_sigill_handler;
|
|
544
|
-
sigemptyset(&action_new.sa_mask);
|
|
545
|
-
action_new.sa_flags = 0;
|
|
546
|
-
|
|
547
|
-
int mrs_works = 0;
|
|
548
|
-
if (sigaction(SIGILL, &action_new, &action_old) == 0) {
|
|
549
|
-
if (sigsetjmp(_simsimd_mrs_test_jump_buffer, 1) == 0) {
|
|
550
|
-
unsigned long midr_value;
|
|
551
|
-
__asm__ __volatile__("mrs %0, MIDR_EL1" : "=r"(midr_value));
|
|
552
|
-
mrs_works = 1;
|
|
553
|
-
}
|
|
554
|
-
sigaction(SIGILL, &action_old, NULL);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
// Early exit if `mrs` doesn't work - return conservative NEON-only capabilities
|
|
558
|
-
if (!mrs_works) return (simsimd_capability_t)(simsimd_cap_neon_k | simsimd_cap_serial_k);
|
|
559
|
-
#else // _SIMSIMD_HAS_POSIX_EXTENSIONS
|
|
560
|
-
// Without POSIX signal handlers, fall back to conservative NEON capabilities.
|
|
561
|
-
return (simsimd_capability_t)(simsimd_cap_neon_k | simsimd_cap_serial_k);
|
|
562
|
-
#endif // _SIMSIMD_HAS_POSIX_EXTENSIONS
|
|
563
|
-
|
|
564
|
-
// Read CPUID registers directly
|
|
565
|
-
unsigned long id_aa64isar0_el1 = 0, id_aa64isar1_el1 = 0, id_aa64pfr0_el1 = 0, id_aa64zfr0_el1 = 0;
|
|
566
|
-
|
|
567
|
-
// Now let's unpack the status flags from ID_AA64ISAR0_EL1
|
|
568
|
-
// https://developer.arm.com/documentation/ddi0601/2024-03/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0?lang=en
|
|
569
|
-
__asm__ __volatile__("mrs %0, ID_AA64ISAR0_EL1" : "=r"(id_aa64isar0_el1));
|
|
570
|
-
// DP, bits [47:44] of ID_AA64ISAR0_EL1
|
|
571
|
-
unsigned supports_integer_dot_products = ((id_aa64isar0_el1 >> 44) & 0xF) >= 1;
|
|
572
|
-
// Now let's unpack the status flags from ID_AA64ISAR1_EL1
|
|
573
|
-
// https://developer.arm.com/documentation/ddi0601/2024-03/AArch64-Registers/ID-AA64ISAR1-EL1--AArch64-Instruction-Set-Attribute-Register-1?lang=en
|
|
574
|
-
__asm__ __volatile__("mrs %0, ID_AA64ISAR1_EL1" : "=r"(id_aa64isar1_el1));
|
|
575
|
-
// I8MM, bits [55:52] of ID_AA64ISAR1_EL1
|
|
576
|
-
unsigned supports_i8mm = ((id_aa64isar1_el1 >> 52) & 0xF) >= 1;
|
|
577
|
-
// BF16, bits [47:44] of ID_AA64ISAR1_EL1
|
|
578
|
-
unsigned supports_bf16 = ((id_aa64isar1_el1 >> 44) & 0xF) >= 1;
|
|
579
|
-
|
|
580
|
-
// Now let's unpack the status flags from ID_AA64PFR0_EL1
|
|
581
|
-
// https://developer.arm.com/documentation/ddi0601/2024-03/AArch64-Registers/ID-AA64PFR0-EL1--AArch64-Processor-Feature-Register-0?lang=en
|
|
582
|
-
__asm__ __volatile__("mrs %0, ID_AA64PFR0_EL1" : "=r"(id_aa64pfr0_el1));
|
|
583
|
-
// SVE, bits [35:32] of ID_AA64PFR0_EL1
|
|
584
|
-
unsigned supports_sve = ((id_aa64pfr0_el1 >> 32) & 0xF) >= 1;
|
|
585
|
-
// AdvSIMD, bits [23:20] of ID_AA64PFR0_EL1 can be used to check for `fp16` support
|
|
586
|
-
// - 0b0000: integers, single, double precision arithmetic
|
|
587
|
-
// - 0b0001: includes support for half-precision floating-point arithmetic
|
|
588
|
-
// - 0b1111: NEON is not supported?!
|
|
589
|
-
// That's a really weird way to encode lack of NEON support, but it's important to
|
|
590
|
-
// check in case we are running on R-profile CPUs.
|
|
591
|
-
unsigned supports_fp16 = ((id_aa64pfr0_el1 >> 20) & 0xF) == 0x1;
|
|
592
|
-
unsigned supports_neon = ((id_aa64pfr0_el1 >> 20) & 0xF) != 0xF;
|
|
593
|
-
|
|
594
|
-
// Now let's unpack the status flags from ID_AA64ZFR0_EL1
|
|
595
|
-
// https://developer.arm.com/documentation/ddi0601/2024-03/AArch64-Registers/ID-AA64ZFR0-EL1--SVE-Feature-ID-Register-0?lang=en
|
|
596
|
-
if (supports_sve) __asm__ __volatile__("mrs %0, ID_AA64ZFR0_EL1" : "=r"(id_aa64zfr0_el1));
|
|
597
|
-
// I8MM, bits [47:44] of ID_AA64ZFR0_EL1
|
|
598
|
-
unsigned supports_sve_i8mm = ((id_aa64zfr0_el1 >> 44) & 0xF) >= 1;
|
|
599
|
-
// BF16, bits [23:20] of ID_AA64ZFR0_EL1
|
|
600
|
-
unsigned supports_sve_bf16 = ((id_aa64zfr0_el1 >> 20) & 0xF) >= 1;
|
|
601
|
-
// SVEver, bits [3:0] can be used to check for capability levels:
|
|
602
|
-
// - 0b0000: SVE is implemented
|
|
603
|
-
// - 0b0001: SVE2 is implemented
|
|
604
|
-
// - 0b0010: SVE2.1 is implemented
|
|
605
|
-
// This value must match the existing indicator obtained from ID_AA64PFR0_EL1:
|
|
606
|
-
unsigned supports_sve2 = ((id_aa64zfr0_el1) & 0xF) >= 1;
|
|
607
|
-
unsigned supports_sve2p1 = ((id_aa64zfr0_el1) & 0xF) >= 2;
|
|
608
|
-
|
|
609
|
-
return (simsimd_capability_t)( //
|
|
610
|
-
(simsimd_cap_neon_k * (supports_neon)) | //
|
|
611
|
-
(simsimd_cap_neon_f16_k * (supports_neon && supports_fp16)) | //
|
|
612
|
-
(simsimd_cap_neon_bf16_k * (supports_neon && supports_bf16)) | //
|
|
613
|
-
(simsimd_cap_neon_i8_k * (supports_neon && supports_i8mm && supports_integer_dot_products)) | //
|
|
614
|
-
(simsimd_cap_sve_k * (supports_sve)) | //
|
|
615
|
-
(simsimd_cap_sve_f16_k * (supports_sve && supports_fp16)) | //
|
|
616
|
-
(simsimd_cap_sve_bf16_k * (supports_sve && supports_sve_bf16)) | //
|
|
617
|
-
(simsimd_cap_sve_i8_k * (supports_sve && supports_sve_i8mm)) | //
|
|
618
|
-
(simsimd_cap_sve2_k * (supports_sve2)) | //
|
|
619
|
-
(simsimd_cap_sve2p1_k * (supports_sve2p1)) | //
|
|
620
|
-
(simsimd_cap_serial_k));
|
|
621
|
-
|
|
622
|
-
#elif defined(_SIMSIMD_DEFINED_WINDOWS)
|
|
623
|
-
|
|
624
|
-
unsigned supports_neon = 0, supports_dp = 0;
|
|
625
|
-
|
|
626
|
-
// On Windows ARM, use the `IsProcessorFeaturePresent` API for capability detection.
|
|
627
|
-
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent
|
|
628
|
-
#if defined(PF_ARM_V8_INSTRUCTIONS_AVAILABLE)
|
|
629
|
-
supports_neon = IsProcessorFeaturePresent(PF_ARM_V8_INSTRUCTIONS_AVAILABLE);
|
|
630
|
-
#endif
|
|
631
|
-
#if defined(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE)
|
|
632
|
-
supports_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE);
|
|
633
|
-
#endif
|
|
634
|
-
|
|
635
|
-
// Windows API doesn't provide reliable detection for FP16, BF16.
|
|
636
|
-
return (simsimd_capability_t)( //
|
|
637
|
-
(simsimd_cap_neon_k * (supports_neon)) | //
|
|
638
|
-
(simsimd_cap_neon_i8_k * (supports_neon && supports_dp)) | //
|
|
639
|
-
(simsimd_cap_serial_k));
|
|
640
|
-
|
|
641
|
-
#else // Unknown platform
|
|
642
|
-
|
|
643
|
-
// Conservative fallback for unknown platforms: NEON is mandatory in ARMv8-A (ARM64)
|
|
644
|
-
return (simsimd_capability_t)(simsimd_cap_neon_k | simsimd_cap_serial_k);
|
|
645
|
-
|
|
646
|
-
#endif
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
#pragma clang attribute pop
|
|
650
|
-
#pragma GCC pop_options
|
|
651
|
-
|
|
652
|
-
#endif
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
* @brief Function to flush @b denormalized numbers to zero to avoid performance penalties.
|
|
656
|
-
* @return 1 if the operation was successful, 0 otherwise.
|
|
657
|
-
*
|
|
658
|
-
* When facing denormalized values Fused-Multiply-Add (FMA) operations can be up to 30x slower,
|
|
659
|
-
* as measured on Intel Sapphire Rapids: https://github.com/ashvardanian/ParallelReductionsBenchmark
|
|
660
|
-
*/
|
|
661
|
-
SIMSIMD_PUBLIC int _simsimd_flush_denormals(void) {
|
|
662
|
-
#if _SIMSIMD_TARGET_X86
|
|
663
|
-
return _simsimd_flush_denormals_x86();
|
|
664
|
-
#endif // _SIMSIMD_TARGET_X86
|
|
665
|
-
#if _SIMSIMD_TARGET_ARM
|
|
666
|
-
return _simsimd_flush_denormals_arm();
|
|
667
|
-
#endif // _SIMSIMD_TARGET_ARM
|
|
668
|
-
return 0;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
/**
|
|
672
|
-
* @brief Function to determine the SIMD capabilities of the current 64-bit x86 machine at @b runtime.
|
|
673
|
-
* @return A bitmask of the SIMD capabilities represented as a `simsimd_capability_t` enum value.
|
|
674
|
-
*/
|
|
675
|
-
SIMSIMD_PUBLIC simsimd_capability_t _simsimd_capabilities_implementation(void) {
|
|
676
|
-
#if _SIMSIMD_TARGET_X86
|
|
677
|
-
return _simsimd_capabilities_x86();
|
|
678
|
-
#endif // _SIMSIMD_TARGET_X86
|
|
679
|
-
#if _SIMSIMD_TARGET_ARM
|
|
680
|
-
return _simsimd_capabilities_arm();
|
|
681
|
-
#endif // _SIMSIMD_TARGET_ARM
|
|
682
|
-
return simsimd_cap_serial_k;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
#pragma GCC diagnostic push
|
|
686
|
-
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
|
687
|
-
#pragma clang diagnostic push
|
|
688
|
-
#pragma clang diagnostic ignored "-Wcast-function-type"
|
|
689
|
-
|
|
690
|
-
#ifdef __cplusplus //! option "-Wvolatile" is valid for C++/ObjC++ but not for C
|
|
691
|
-
#pragma GCC diagnostic ignored "-Wvolatile"
|
|
692
|
-
#pragma clang diagnostic ignored "-Wvolatile"
|
|
693
|
-
#endif
|
|
694
|
-
|
|
695
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_f64(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
696
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
697
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
698
|
-
#if SIMSIMD_TARGET_SVE
|
|
699
|
-
if (v & simsimd_cap_sve_k) switch (k) {
|
|
700
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
701
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
702
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
703
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_sve, *c = simsimd_cap_sve_k; return;
|
|
704
|
-
default: break;
|
|
705
|
-
}
|
|
706
|
-
#endif
|
|
707
|
-
#if SIMSIMD_TARGET_NEON
|
|
708
|
-
if (v & simsimd_cap_neon_k) switch (k) {
|
|
709
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
710
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
711
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_neon, *c = simsimd_cap_neon_k; return;
|
|
712
|
-
default: break;
|
|
713
|
-
}
|
|
714
|
-
#endif
|
|
715
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
716
|
-
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
717
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
718
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
719
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
720
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
721
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
722
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f64_skylake, *c = simsimd_cap_skylake_k; return;
|
|
723
|
-
default: break;
|
|
724
|
-
}
|
|
725
|
-
#endif
|
|
726
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
727
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
728
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
729
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
730
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
731
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
732
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f64_haswell, *c = simsimd_cap_haswell_k; return;
|
|
733
|
-
default: break;
|
|
734
|
-
}
|
|
735
|
-
#endif
|
|
736
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
737
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
738
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
739
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
740
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
741
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
742
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
743
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
744
|
-
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
745
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
746
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f64_serial, *c = simsimd_cap_serial_k; return;
|
|
747
|
-
default: break;
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_f32(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
752
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
753
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
754
|
-
#if SIMSIMD_TARGET_SVE
|
|
755
|
-
if (v & simsimd_cap_sve_k) switch (k) {
|
|
756
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
757
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
758
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
759
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_sve, *c = simsimd_cap_sve_k; return;
|
|
760
|
-
default: break;
|
|
761
|
-
}
|
|
762
|
-
#endif
|
|
763
|
-
#if SIMSIMD_TARGET_NEON
|
|
764
|
-
if (v & simsimd_cap_neon_k) switch (k) {
|
|
765
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
766
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
767
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
768
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
769
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
770
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
771
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
772
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f32_neon, *c = simsimd_cap_neon_k; return;
|
|
773
|
-
default: break;
|
|
774
|
-
}
|
|
775
|
-
#endif
|
|
776
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
777
|
-
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
778
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
779
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
780
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
781
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
782
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
783
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
784
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
785
|
-
case simsimd_metric_mahalanobis_k:
|
|
786
|
-
*m = (m_t)&simsimd_mahalanobis_f32_skylake, *c = simsimd_cap_skylake_k;
|
|
787
|
-
return;
|
|
788
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
789
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f32_skylake, *c = simsimd_cap_skylake_k; return;
|
|
790
|
-
default: break;
|
|
791
|
-
}
|
|
792
|
-
#endif
|
|
793
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
794
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
795
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
796
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
797
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
798
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
799
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
800
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f32_haswell, *c = simsimd_cap_haswell_k; return;
|
|
801
|
-
default: break;
|
|
802
|
-
}
|
|
803
|
-
#endif
|
|
804
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
805
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
806
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
807
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
808
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
809
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
810
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
811
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
812
|
-
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
813
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
814
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f32_serial, *c = simsimd_cap_serial_k; return;
|
|
815
|
-
default: break;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_f16(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
820
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
821
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
822
|
-
#if SIMSIMD_TARGET_SVE_F16
|
|
823
|
-
if (v & simsimd_cap_sve_k) switch (k) {
|
|
824
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
825
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
826
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
827
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
828
|
-
default: break;
|
|
829
|
-
}
|
|
830
|
-
#endif
|
|
831
|
-
#if SIMSIMD_TARGET_NEON_F16
|
|
832
|
-
if (v & simsimd_cap_neon_f16_k) switch (k) {
|
|
833
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
834
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
835
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
836
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
837
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
838
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
839
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
840
|
-
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
841
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
842
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f16_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
843
|
-
default: break;
|
|
844
|
-
}
|
|
845
|
-
#endif
|
|
846
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
847
|
-
if (v & simsimd_cap_sapphire_k) switch (k) {
|
|
848
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
849
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
850
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
851
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
852
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
853
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
854
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
855
|
-
case simsimd_metric_mahalanobis_k:
|
|
856
|
-
*m = (m_t)&simsimd_mahalanobis_f16_sapphire, *c = simsimd_cap_sapphire_k;
|
|
857
|
-
return;
|
|
858
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
859
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f16_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
860
|
-
default: break;
|
|
861
|
-
}
|
|
862
|
-
#endif
|
|
863
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
864
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
865
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
866
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
867
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
868
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
869
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
870
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
871
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
872
|
-
case simsimd_metric_mahalanobis_k:
|
|
873
|
-
*m = (m_t)&simsimd_mahalanobis_f16_haswell, *c = simsimd_cap_haswell_k;
|
|
874
|
-
return;
|
|
875
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
876
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
877
|
-
default: break;
|
|
878
|
-
}
|
|
879
|
-
#endif
|
|
880
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
881
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
882
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
883
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
884
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
885
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
886
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
887
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
888
|
-
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
889
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
890
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_f16_serial, *c = simsimd_cap_serial_k; return;
|
|
891
|
-
default: break;
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_bf16(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
896
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
897
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
898
|
-
#if SIMSIMD_TARGET_SVE_BF16
|
|
899
|
-
if (v & simsimd_cap_sve_bf16_k) switch (k) {
|
|
900
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
901
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
902
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_sve, *c = simsimd_cap_sve_bf16_k; return;
|
|
903
|
-
default: break;
|
|
904
|
-
}
|
|
905
|
-
#endif
|
|
906
|
-
#if SIMSIMD_TARGET_NEON_BF16
|
|
907
|
-
if (v & simsimd_cap_neon_bf16_k) switch (k) {
|
|
908
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
909
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
910
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
911
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
912
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
913
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_bf16_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
914
|
-
default: break;
|
|
915
|
-
}
|
|
916
|
-
#endif
|
|
917
|
-
#if SIMSIMD_TARGET_GENOA
|
|
918
|
-
if (v & simsimd_cap_genoa_k) switch (k) {
|
|
919
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
920
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
921
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
922
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
923
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
924
|
-
case simsimd_metric_mahalanobis_k: *m = (m_t)&simsimd_mahalanobis_bf16_genoa, *c = simsimd_cap_genoa_k; return;
|
|
925
|
-
default: break;
|
|
926
|
-
}
|
|
927
|
-
#endif
|
|
928
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
929
|
-
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
930
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_bf16_skylake, *c = simsimd_cap_skylake_k; return;
|
|
931
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_bf16_skylake, *c = simsimd_cap_skylake_k; return;
|
|
932
|
-
default: break;
|
|
933
|
-
}
|
|
934
|
-
#endif
|
|
935
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
936
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
937
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
938
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
939
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
940
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
941
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
942
|
-
case simsimd_metric_mahalanobis_k:
|
|
943
|
-
*m = (m_t)&simsimd_mahalanobis_bf16_haswell, *c = simsimd_cap_haswell_k;
|
|
944
|
-
return;
|
|
945
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
946
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_bf16_haswell, *c = simsimd_cap_haswell_k; return;
|
|
947
|
-
default: break;
|
|
948
|
-
}
|
|
949
|
-
#endif
|
|
950
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
951
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
952
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
953
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
954
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
955
|
-
case simsimd_metric_js_k: *m = (m_t)&simsimd_js_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
956
|
-
case simsimd_metric_kl_k: *m = (m_t)&simsimd_kl_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
957
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
958
|
-
case simsimd_metric_mahalanobis_k:
|
|
959
|
-
*m = (m_t)&simsimd_mahalanobis_bf16_serial, *c = simsimd_cap_serial_k;
|
|
960
|
-
return;
|
|
961
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
962
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_bf16_serial, *c = simsimd_cap_serial_k; return;
|
|
963
|
-
default: break;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_i8(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
968
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
969
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
970
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
971
|
-
if (v & simsimd_cap_neon_i8_k) switch (k) {
|
|
972
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
973
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
974
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
975
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
976
|
-
default: break;
|
|
977
|
-
}
|
|
978
|
-
#endif
|
|
979
|
-
#if SIMSIMD_TARGET_NEON_F16 //! Scaling of 8-bit integers is performed using 16-bit floats.
|
|
980
|
-
if (v & simsimd_cap_neon_f16_k) switch (k) {
|
|
981
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_i8_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
982
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_i8_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
983
|
-
default: break;
|
|
984
|
-
}
|
|
985
|
-
#endif
|
|
986
|
-
#if SIMSIMD_TARGET_SAPPHIRE //! Scaling of 8-bit integers is performed using 16-bit floats.
|
|
987
|
-
if (v & simsimd_cap_sapphire_k) switch (k) {
|
|
988
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_i8_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
989
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_i8_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
990
|
-
default: break;
|
|
991
|
-
}
|
|
992
|
-
#endif
|
|
993
|
-
#if SIMSIMD_TARGET_ICE
|
|
994
|
-
if (v & simsimd_cap_ice_k) switch (k) {
|
|
995
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
996
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
997
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
998
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_ice, *c = simsimd_cap_ice_k; return;
|
|
999
|
-
default: break;
|
|
1000
|
-
}
|
|
1001
|
-
#endif
|
|
1002
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
1003
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
1004
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1005
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1006
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1007
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1008
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1009
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_i8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1010
|
-
default: break;
|
|
1011
|
-
}
|
|
1012
|
-
#endif
|
|
1013
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1014
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
1015
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
1016
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
1017
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
1018
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
1019
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_i8_serial, *c = simsimd_cap_serial_k; return;
|
|
1020
|
-
default: break;
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_u8(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1024
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
1025
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
1026
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
1027
|
-
if (v & simsimd_cap_neon_i8_k) switch (k) {
|
|
1028
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_u8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
1029
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_u8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
1030
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_u8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
1031
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_u8_neon, *c = simsimd_cap_neon_i8_k; return;
|
|
1032
|
-
default: break;
|
|
1033
|
-
}
|
|
1034
|
-
#endif
|
|
1035
|
-
#if SIMSIMD_TARGET_NEON_F16 //! Scaling of 8-bit integers is performed using 16-bit floats.
|
|
1036
|
-
if (v & simsimd_cap_neon_f16_k) switch (k) {
|
|
1037
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_u8_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
1038
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_u8_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
1039
|
-
default: break;
|
|
1040
|
-
}
|
|
1041
|
-
#endif
|
|
1042
|
-
#if SIMSIMD_TARGET_SAPPHIRE //! Scaling of 8-bit integers is performed using 16-bit floats.
|
|
1043
|
-
if (v & simsimd_cap_sapphire_k) switch (k) {
|
|
1044
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_u8_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
1045
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_u8_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
1046
|
-
default: break;
|
|
1047
|
-
}
|
|
1048
|
-
#endif
|
|
1049
|
-
#if SIMSIMD_TARGET_ICE
|
|
1050
|
-
if (v & simsimd_cap_ice_k) switch (k) {
|
|
1051
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_u8_ice, *c = simsimd_cap_ice_k; return;
|
|
1052
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_u8_ice, *c = simsimd_cap_ice_k; return;
|
|
1053
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_u8_ice, *c = simsimd_cap_ice_k; return;
|
|
1054
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_u8_ice, *c = simsimd_cap_ice_k; return;
|
|
1055
|
-
default: break;
|
|
1056
|
-
}
|
|
1057
|
-
#endif
|
|
1058
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
1059
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
1060
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1061
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1062
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1063
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1064
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1065
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_u8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1066
|
-
default: break;
|
|
1067
|
-
}
|
|
1068
|
-
#endif
|
|
1069
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1070
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
1071
|
-
case simsimd_metric_cos_k: *m = (m_t)&simsimd_cos_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
1072
|
-
case simsimd_metric_l2sq_k: *m = (m_t)&simsimd_l2sq_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
1073
|
-
case simsimd_metric_l2_k: *m = (m_t)&simsimd_l2_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
1074
|
-
case simsimd_metric_fma_k: *m = (m_t)&simsimd_fma_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
1075
|
-
case simsimd_metric_wsum_k: *m = (m_t)&simsimd_wsum_u8_serial, *c = simsimd_cap_serial_k; return;
|
|
1076
|
-
default: break;
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_b8(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1081
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
1082
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
1083
|
-
#if SIMSIMD_TARGET_SVE
|
|
1084
|
-
if (v & simsimd_cap_sve_k) switch (k) {
|
|
1085
|
-
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_sve, *c = simsimd_cap_sve_k; return;
|
|
1086
|
-
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_sve, *c = simsimd_cap_sve_k; return;
|
|
1087
|
-
default: break;
|
|
1088
|
-
}
|
|
1089
|
-
#endif
|
|
1090
|
-
#if SIMSIMD_TARGET_NEON
|
|
1091
|
-
if (v & simsimd_cap_neon_k) switch (k) {
|
|
1092
|
-
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_neon, *c = simsimd_cap_neon_k; return;
|
|
1093
|
-
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_neon, *c = simsimd_cap_neon_k; return;
|
|
1094
|
-
default: break;
|
|
1095
|
-
}
|
|
1096
|
-
#endif
|
|
1097
|
-
#if SIMSIMD_TARGET_ICE
|
|
1098
|
-
if (v & simsimd_cap_ice_k) switch (k) {
|
|
1099
|
-
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_ice, *c = simsimd_cap_ice_k; return;
|
|
1100
|
-
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_ice, *c = simsimd_cap_ice_k; return;
|
|
1101
|
-
default: break;
|
|
1102
|
-
}
|
|
1103
|
-
#endif
|
|
1104
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
1105
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
1106
|
-
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1107
|
-
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1108
|
-
default: break;
|
|
1109
|
-
}
|
|
1110
|
-
#endif
|
|
1111
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1112
|
-
case simsimd_metric_hamming_k: *m = (m_t)&simsimd_hamming_b8_serial, *c = simsimd_cap_serial_k; return;
|
|
1113
|
-
case simsimd_metric_jaccard_k: *m = (m_t)&simsimd_jaccard_b8_serial, *c = simsimd_cap_serial_k; return;
|
|
1114
|
-
default: break;
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_f64c(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1119
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
1120
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
1121
|
-
#if SIMSIMD_TARGET_SVE
|
|
1122
|
-
if (v & simsimd_cap_sve_k) switch (k) {
|
|
1123
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64c_sve, *c = simsimd_cap_sve_k; return;
|
|
1124
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f64c_sve, *c = simsimd_cap_sve_k; return;
|
|
1125
|
-
default: break;
|
|
1126
|
-
}
|
|
1127
|
-
#endif
|
|
1128
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
1129
|
-
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
1130
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
1131
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f64c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
1132
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f64c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
1133
|
-
default: break;
|
|
1134
|
-
}
|
|
1135
|
-
#endif
|
|
1136
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1137
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f64c_serial, *c = simsimd_cap_serial_k; return;
|
|
1138
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f64c_serial, *c = simsimd_cap_serial_k; return;
|
|
1139
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f64c_serial, *c = simsimd_cap_serial_k; return;
|
|
1140
|
-
default: break;
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_f32c(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1145
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
1146
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
1147
|
-
#if SIMSIMD_TARGET_SVE
|
|
1148
|
-
if (v & simsimd_cap_sve_k) switch (k) {
|
|
1149
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_sve, *c = simsimd_cap_sve_k; return;
|
|
1150
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_sve, *c = simsimd_cap_sve_k; return;
|
|
1151
|
-
default: break;
|
|
1152
|
-
}
|
|
1153
|
-
#endif
|
|
1154
|
-
#if SIMSIMD_TARGET_NEON
|
|
1155
|
-
if (v & simsimd_cap_neon_k) switch (k) {
|
|
1156
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_neon, *c = simsimd_cap_neon_k; return;
|
|
1157
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_neon, *c = simsimd_cap_neon_k; return;
|
|
1158
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32c_neon, *c = simsimd_cap_neon_k; return;
|
|
1159
|
-
default: break;
|
|
1160
|
-
}
|
|
1161
|
-
#endif
|
|
1162
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
1163
|
-
if (v & simsimd_cap_skylake_k) switch (k) {
|
|
1164
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
1165
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
1166
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32c_skylake, *c = simsimd_cap_skylake_k; return;
|
|
1167
|
-
default: break;
|
|
1168
|
-
}
|
|
1169
|
-
#endif
|
|
1170
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
1171
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
1172
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1173
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1174
|
-
default: break;
|
|
1175
|
-
}
|
|
1176
|
-
#endif
|
|
1177
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1178
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f32c_serial, *c = simsimd_cap_serial_k; return;
|
|
1179
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f32c_serial, *c = simsimd_cap_serial_k; return;
|
|
1180
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f32c_serial, *c = simsimd_cap_serial_k; return;
|
|
1181
|
-
default: break;
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_f16c(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1186
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
1187
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
1188
|
-
#if SIMSIMD_TARGET_SVE_F16
|
|
1189
|
-
if (v & simsimd_cap_sve_k) switch (k) {
|
|
1190
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
1191
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_sve, *c = simsimd_cap_sve_f16_k; return;
|
|
1192
|
-
default: break;
|
|
1193
|
-
}
|
|
1194
|
-
#endif
|
|
1195
|
-
#if SIMSIMD_TARGET_NEON_F16
|
|
1196
|
-
if (v & simsimd_cap_neon_f16_k) switch (k) {
|
|
1197
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
1198
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_neon, *c = simsimd_cap_neon_f16_k; return;
|
|
1199
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16c_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
1200
|
-
default: break;
|
|
1201
|
-
}
|
|
1202
|
-
#endif
|
|
1203
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
1204
|
-
if (v & simsimd_cap_sapphire_k) switch (k) {
|
|
1205
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
1206
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
1207
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16c_sapphire, *c = simsimd_cap_sapphire_k; return;
|
|
1208
|
-
default: break;
|
|
1209
|
-
}
|
|
1210
|
-
#endif
|
|
1211
|
-
#if SIMSIMD_TARGET_HASWELL
|
|
1212
|
-
if (v & simsimd_cap_haswell_k) switch (k) {
|
|
1213
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1214
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_haswell, *c = simsimd_cap_haswell_k; return;
|
|
1215
|
-
default: break;
|
|
1216
|
-
}
|
|
1217
|
-
#endif
|
|
1218
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1219
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_f16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1220
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_f16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1221
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_f16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1222
|
-
default: break;
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_bf16c(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1227
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
1228
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
1229
|
-
#if SIMSIMD_TARGET_NEON_BF16
|
|
1230
|
-
if (v & simsimd_cap_neon_bf16_k) switch (k) {
|
|
1231
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16c_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
1232
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_bf16c_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
1233
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16c_neon, *c = simsimd_cap_neon_bf16_k; return;
|
|
1234
|
-
default: break;
|
|
1235
|
-
}
|
|
1236
|
-
#endif
|
|
1237
|
-
#if SIMSIMD_TARGET_GENOA
|
|
1238
|
-
if (v & simsimd_cap_genoa_k) switch (k) {
|
|
1239
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16c_genoa, *c = simsimd_cap_genoa_k; return;
|
|
1240
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_bf16c_genoa, *c = simsimd_cap_genoa_k; return;
|
|
1241
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16c_genoa, *c = simsimd_cap_genoa_k; return;
|
|
1242
|
-
default: break;
|
|
1243
|
-
}
|
|
1244
|
-
#endif
|
|
1245
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1246
|
-
case simsimd_metric_dot_k: *m = (m_t)&simsimd_dot_bf16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1247
|
-
case simsimd_metric_vdot_k: *m = (m_t)&simsimd_vdot_bf16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1248
|
-
case simsimd_metric_bilinear_k: *m = (m_t)&simsimd_bilinear_bf16c_serial, *c = simsimd_cap_serial_k; return;
|
|
1249
|
-
default: break;
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_u16(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1254
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
1255
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
1256
|
-
#if SIMSIMD_TARGET_SVE2
|
|
1257
|
-
if (v & simsimd_cap_sve2_k) switch (k) {
|
|
1258
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_sve2, *c = simsimd_cap_sve2_k; return;
|
|
1259
|
-
case simsimd_metric_spdot_counts_k: *m = (m_t)&simsimd_spdot_counts_u16_sve2, *c = simsimd_cap_sve2_k; return;
|
|
1260
|
-
#if SIMSIMD_TARGET_SVE_BF16 //! We also need `bf16` support for weights
|
|
1261
|
-
case simsimd_metric_spdot_weights_k: *m = (m_t)&simsimd_spdot_weights_u16_sve2, *c = simsimd_cap_sve2_k; return;
|
|
1262
|
-
#endif
|
|
1263
|
-
default: break;
|
|
1264
|
-
}
|
|
1265
|
-
#endif
|
|
1266
|
-
#if SIMSIMD_TARGET_NEON
|
|
1267
|
-
if (v & simsimd_cap_neon_k) switch (k) {
|
|
1268
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_neon, *c = simsimd_cap_neon_k; return;
|
|
1269
|
-
default: break;
|
|
1270
|
-
}
|
|
1271
|
-
#endif
|
|
1272
|
-
#if SIMSIMD_TARGET_TURIN
|
|
1273
|
-
if (v & simsimd_cap_turin_k) switch (k) {
|
|
1274
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_turin, *c = simsimd_cap_turin_k; return;
|
|
1275
|
-
case simsimd_metric_spdot_counts_k: *m = (m_t)&simsimd_spdot_counts_u16_turin, *c = simsimd_cap_turin_k; return;
|
|
1276
|
-
case simsimd_metric_spdot_weights_k:
|
|
1277
|
-
*m = (m_t)&simsimd_spdot_weights_u16_turin, *c = simsimd_cap_turin_k;
|
|
1278
|
-
return;
|
|
1279
|
-
default: break;
|
|
1280
|
-
}
|
|
1281
|
-
#endif
|
|
1282
|
-
#if SIMSIMD_TARGET_ICE
|
|
1283
|
-
if (v & simsimd_cap_ice_k) switch (k) {
|
|
1284
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_ice, *c = simsimd_cap_skylake_k; return;
|
|
1285
|
-
default: break;
|
|
1286
|
-
}
|
|
1287
|
-
#endif
|
|
1288
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1289
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u16_serial, *c = simsimd_cap_serial_k; return;
|
|
1290
|
-
default: break;
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_u32(simsimd_capability_t v, simsimd_metric_kind_t k,
|
|
1295
|
-
simsimd_kernel_punned_t *m, simsimd_capability_t *c) {
|
|
1296
|
-
typedef simsimd_kernel_punned_t m_t;
|
|
1297
|
-
#if SIMSIMD_TARGET_SVE2
|
|
1298
|
-
if (v & simsimd_cap_sve2_k) switch (k) {
|
|
1299
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_sve2, *c = simsimd_cap_sve2_k; return;
|
|
1300
|
-
default: break;
|
|
1301
|
-
}
|
|
1302
|
-
#endif
|
|
1303
|
-
#if SIMSIMD_TARGET_NEON
|
|
1304
|
-
if (v & simsimd_cap_neon_k) switch (k) {
|
|
1305
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_neon, *c = simsimd_cap_neon_k; return;
|
|
1306
|
-
default: break;
|
|
1307
|
-
}
|
|
1308
|
-
#endif
|
|
1309
|
-
#if SIMSIMD_TARGET_TURIN
|
|
1310
|
-
if (v & simsimd_cap_turin_k) switch (k) {
|
|
1311
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_turin, *c = simsimd_cap_skylake_k; return;
|
|
1312
|
-
default: break;
|
|
1313
|
-
}
|
|
1314
|
-
#endif
|
|
1315
|
-
#if SIMSIMD_TARGET_ICE
|
|
1316
|
-
if (v & simsimd_cap_ice_k) switch (k) {
|
|
1317
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_ice, *c = simsimd_cap_skylake_k; return;
|
|
1318
|
-
default: break;
|
|
1319
|
-
}
|
|
1320
|
-
#endif
|
|
1321
|
-
if (v & simsimd_cap_serial_k) switch (k) {
|
|
1322
|
-
case simsimd_metric_intersect_k: *m = (m_t)&simsimd_intersect_u32_serial, *c = simsimd_cap_serial_k; return;
|
|
1323
|
-
default: break;
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
|
-
/**
|
|
1328
|
-
* @brief Determines the best suited metric implementation based on the given datatype,
|
|
1329
|
-
* supported and allowed by hardware capabilities.
|
|
1330
|
-
*
|
|
1331
|
-
* @param kind The kind of metric to be evaluated.
|
|
1332
|
-
* @param datatype The data type for which the metric needs to be evaluated.
|
|
1333
|
-
* @param supported The hardware capabilities supported by the CPU.
|
|
1334
|
-
* @param allowed The hardware capabilities allowed for use.
|
|
1335
|
-
* @param kernel_output Output variable for the selected similarity function.
|
|
1336
|
-
* @param capability_output Output variable for the utilized hardware capabilities.
|
|
1337
|
-
*/
|
|
1338
|
-
SIMSIMD_INTERNAL void _simsimd_find_kernel_punned_implementation( //
|
|
1339
|
-
simsimd_metric_kind_t kind, //
|
|
1340
|
-
simsimd_datatype_t datatype, //
|
|
1341
|
-
simsimd_capability_t supported, //
|
|
1342
|
-
simsimd_capability_t allowed, //
|
|
1343
|
-
simsimd_kernel_punned_t *kernel_output, //
|
|
1344
|
-
simsimd_capability_t *capability_output) {
|
|
1345
|
-
|
|
1346
|
-
// Modern compilers abso-freaking-lutely love optimizing-out my logic!
|
|
1347
|
-
// Just marking the variables as `volatile` is not enough, so we have
|
|
1348
|
-
// to add inline assembly to further discourage them!
|
|
1349
|
-
#if defined(_MSC_VER)
|
|
1350
|
-
_ReadWriteBarrier();
|
|
1351
|
-
#else
|
|
1352
|
-
__asm__ __volatile__("" ::: "memory");
|
|
1353
|
-
#endif
|
|
1354
|
-
|
|
1355
|
-
simsimd_kernel_punned_t *m = kernel_output;
|
|
1356
|
-
simsimd_capability_t *c = capability_output;
|
|
1357
|
-
simsimd_capability_t viable = (simsimd_capability_t)(supported & allowed);
|
|
1358
|
-
|
|
1359
|
-
switch (datatype) {
|
|
1360
|
-
|
|
1361
|
-
case simsimd_datatype_f64_k: _simsimd_find_kernel_punned_f64(viable, kind, m, c); return;
|
|
1362
|
-
case simsimd_datatype_f32_k: _simsimd_find_kernel_punned_f32(viable, kind, m, c); return;
|
|
1363
|
-
case simsimd_datatype_f16_k: _simsimd_find_kernel_punned_f16(viable, kind, m, c); return;
|
|
1364
|
-
case simsimd_datatype_bf16_k: _simsimd_find_kernel_punned_bf16(viable, kind, m, c); return;
|
|
1365
|
-
case simsimd_datatype_i8_k: _simsimd_find_kernel_punned_i8(viable, kind, m, c); return;
|
|
1366
|
-
case simsimd_datatype_u8_k: _simsimd_find_kernel_punned_u8(viable, kind, m, c); return;
|
|
1367
|
-
case simsimd_datatype_b8_k: _simsimd_find_kernel_punned_b8(viable, kind, m, c); return;
|
|
1368
|
-
case simsimd_datatype_f32c_k: _simsimd_find_kernel_punned_f32c(viable, kind, m, c); return;
|
|
1369
|
-
case simsimd_datatype_f64c_k: _simsimd_find_kernel_punned_f64c(viable, kind, m, c); return;
|
|
1370
|
-
case simsimd_datatype_f16c_k: _simsimd_find_kernel_punned_f16c(viable, kind, m, c); return;
|
|
1371
|
-
case simsimd_datatype_bf16c_k: _simsimd_find_kernel_punned_bf16c(viable, kind, m, c); return;
|
|
1372
|
-
case simsimd_datatype_u16_k: _simsimd_find_kernel_punned_u16(viable, kind, m, c); return;
|
|
1373
|
-
case simsimd_datatype_u32_k: _simsimd_find_kernel_punned_u32(viable, kind, m, c); return;
|
|
1374
|
-
|
|
1375
|
-
// These data-types are not supported yet
|
|
1376
|
-
case simsimd_datatype_i4x2_k: break;
|
|
1377
|
-
case simsimd_datatype_i16_k: break;
|
|
1378
|
-
case simsimd_datatype_i32_k: break;
|
|
1379
|
-
case simsimd_datatype_i64_k: break;
|
|
1380
|
-
case simsimd_datatype_u64_k: break;
|
|
1381
|
-
case simsimd_datatype_unknown_k: break;
|
|
1382
|
-
default: break;
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
// Replace with zeros if no suitable implementation was found
|
|
1386
|
-
*m = (simsimd_kernel_punned_t)0;
|
|
1387
|
-
*c = (simsimd_capability_t)0;
|
|
1388
|
-
|
|
1389
|
-
// Modern compilers abso-freaking-lutely love optimizing-out my logic!
|
|
1390
|
-
// Just marking the variables as `volatile` is not enough, so we have
|
|
1391
|
-
// to add inline assembly to further discourage them!
|
|
1392
|
-
#if defined(_MSC_VER)
|
|
1393
|
-
_ReadWriteBarrier();
|
|
1394
|
-
#else
|
|
1395
|
-
__asm__ __volatile__("" ::: "memory");
|
|
1396
|
-
#endif
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
#pragma GCC diagnostic pop
|
|
1400
|
-
#pragma clang diagnostic pop
|
|
1401
|
-
|
|
1402
|
-
/**
|
|
1403
|
-
* @brief Selects the most suitable metric implementation based on the given metric kind, datatype,
|
|
1404
|
-
* and allowed capabilities. @b Don't call too often and prefer caching the `simsimd_capabilities()`.
|
|
1405
|
-
*
|
|
1406
|
-
* @param kind The kind of metric to be evaluated.
|
|
1407
|
-
* @param datatype The data type for which the metric needs to be evaluated.
|
|
1408
|
-
* @param allowed The hardware capabilities allowed for use.
|
|
1409
|
-
* @return A function pointer to the selected metric implementation.
|
|
1410
|
-
*/
|
|
1411
|
-
SIMSIMD_PUBLIC simsimd_kernel_punned_t simsimd_metric_punned( //
|
|
1412
|
-
simsimd_metric_kind_t kind, //
|
|
1413
|
-
simsimd_datatype_t datatype, //
|
|
1414
|
-
simsimd_capability_t allowed) {
|
|
1415
|
-
|
|
1416
|
-
simsimd_kernel_punned_t result = 0;
|
|
1417
|
-
simsimd_capability_t c = simsimd_cap_serial_k;
|
|
1418
|
-
simsimd_capability_t supported = simsimd_capabilities();
|
|
1419
|
-
simsimd_find_kernel_punned(kind, datatype, supported, allowed, &result, &c);
|
|
1420
|
-
return result;
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
#if SIMSIMD_DYNAMIC_DISPATCH
|
|
1424
|
-
|
|
1425
|
-
/* Run-time feature-testing functions
|
|
1426
|
-
* - Check if the CPU supports NEON or SVE extensions on Arm
|
|
1427
|
-
* - Check if the CPU supports AVX2 and F16C extensions on Haswell x86 CPUs and newer
|
|
1428
|
-
* - Check if the CPU supports AVX512F and AVX512BW extensions on Skylake x86 CPUs and newer
|
|
1429
|
-
* - Check if the CPU supports AVX512VNNI, AVX512IFMA, AVX512BITALG, AVX512VBMI2, and AVX512VPOPCNTDQ
|
|
1430
|
-
* extensions on Ice Lake x86 CPUs and newer
|
|
1431
|
-
* - Check if the CPU supports AVX512BF16 extensions on Genoa x86 CPUs and newer
|
|
1432
|
-
* - Check if the CPU supports AVX512FP16 extensions on Sapphire Rapids x86 CPUs and newer
|
|
1433
|
-
* - Check if the CPU supports AVX2VP2INTERSECT extensions on Turin x86 CPUs and newer
|
|
1434
|
-
*
|
|
1435
|
-
* @return 1 if the CPU supports the SIMD instruction set, 0 otherwise.
|
|
1436
|
-
*/
|
|
1437
|
-
SIMSIMD_DYNAMIC simsimd_capability_t simsimd_capabilities(void);
|
|
1438
|
-
SIMSIMD_DYNAMIC int simsimd_flush_denormals(void);
|
|
1439
|
-
SIMSIMD_DYNAMIC int simsimd_uses_dynamic_dispatch(void);
|
|
1440
|
-
SIMSIMD_DYNAMIC int simsimd_uses_neon(void);
|
|
1441
|
-
SIMSIMD_DYNAMIC int simsimd_uses_neon_f16(void);
|
|
1442
|
-
SIMSIMD_DYNAMIC int simsimd_uses_neon_bf16(void);
|
|
1443
|
-
SIMSIMD_DYNAMIC int simsimd_uses_neon_i8(void);
|
|
1444
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sve(void);
|
|
1445
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sve_f16(void);
|
|
1446
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sve_bf16(void);
|
|
1447
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sve_i8(void);
|
|
1448
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sve2(void);
|
|
1449
|
-
SIMSIMD_DYNAMIC int simsimd_uses_haswell(void);
|
|
1450
|
-
SIMSIMD_DYNAMIC int simsimd_uses_skylake(void);
|
|
1451
|
-
SIMSIMD_DYNAMIC int simsimd_uses_ice(void);
|
|
1452
|
-
SIMSIMD_DYNAMIC int simsimd_uses_genoa(void);
|
|
1453
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sapphire(void);
|
|
1454
|
-
SIMSIMD_DYNAMIC int simsimd_uses_turin(void);
|
|
1455
|
-
SIMSIMD_DYNAMIC int simsimd_uses_sierra(void);
|
|
1456
|
-
|
|
1457
|
-
/* Inner products
|
|
1458
|
-
* - Dot product: the sum of the products of the corresponding elements of two vectors.
|
|
1459
|
-
* - Complex Dot product: dot product with a conjugate first argument.
|
|
1460
|
-
* - Complex Conjugate Dot product: dot product with a conjugate first argument.
|
|
1461
|
-
*
|
|
1462
|
-
* @param a The first vector.
|
|
1463
|
-
* @param b The second vector.
|
|
1464
|
-
* @param n The number of elements in the vectors. Even for complex variants (the number of scalars).
|
|
1465
|
-
* @param d The output distance value.
|
|
1466
|
-
*
|
|
1467
|
-
* @note The dot product can be negative, to use as a distance, take `1 - a * b`.
|
|
1468
|
-
* @note The dot product is zero if and only if the two vectors are orthogonal.
|
|
1469
|
-
* @note Defined only for floating-point and integer data types.
|
|
1470
|
-
*/
|
|
1471
|
-
SIMSIMD_DYNAMIC void simsimd_dot_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1472
|
-
simsimd_distance_t *d);
|
|
1473
|
-
SIMSIMD_DYNAMIC void simsimd_dot_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1474
|
-
simsimd_distance_t *d);
|
|
1475
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1476
|
-
simsimd_distance_t *d);
|
|
1477
|
-
SIMSIMD_DYNAMIC void simsimd_dot_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1478
|
-
simsimd_distance_t *d);
|
|
1479
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1480
|
-
simsimd_distance_t *d);
|
|
1481
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1482
|
-
simsimd_distance_t *d);
|
|
1483
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f16c(simsimd_f16c_t const *a, simsimd_f16c_t const *b, simsimd_size_t n,
|
|
1484
|
-
simsimd_distance_t *d);
|
|
1485
|
-
SIMSIMD_DYNAMIC void simsimd_dot_bf16c(simsimd_bf16c_t const *a, simsimd_bf16c_t const *b, simsimd_size_t n,
|
|
1486
|
-
simsimd_distance_t *d);
|
|
1487
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f32c(simsimd_f32c_t const *a, simsimd_f32c_t const *b, simsimd_size_t n,
|
|
1488
|
-
simsimd_distance_t *d);
|
|
1489
|
-
SIMSIMD_DYNAMIC void simsimd_dot_f64c(simsimd_f64c_t const *a, simsimd_f64c_t const *b, simsimd_size_t n,
|
|
1490
|
-
simsimd_distance_t *d);
|
|
1491
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f16c(simsimd_f16c_t const *a, simsimd_f16c_t const *b, simsimd_size_t n,
|
|
1492
|
-
simsimd_distance_t *d);
|
|
1493
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_bf16c(simsimd_bf16c_t const *a, simsimd_bf16c_t const *b, simsimd_size_t n,
|
|
1494
|
-
simsimd_distance_t *d);
|
|
1495
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f32c(simsimd_f32c_t const *a, simsimd_f32c_t const *b, simsimd_size_t n,
|
|
1496
|
-
simsimd_distance_t *d);
|
|
1497
|
-
SIMSIMD_DYNAMIC void simsimd_vdot_f64c(simsimd_f64c_t const *a, simsimd_f64c_t const *b, simsimd_size_t n,
|
|
1498
|
-
simsimd_distance_t *d);
|
|
1499
|
-
|
|
1500
|
-
/* Spatial distances
|
|
1501
|
-
* - Cosine distance: the cosine of the angle between two vectors.
|
|
1502
|
-
* - L2 squared distance: the squared Euclidean distance between two vectors.
|
|
1503
|
-
*
|
|
1504
|
-
* @param a The first vector.
|
|
1505
|
-
* @param b The second vector.
|
|
1506
|
-
* @param n The number of elements in the vectors.
|
|
1507
|
-
* @param d The output distance value.
|
|
1508
|
-
*
|
|
1509
|
-
* @note The output distance value is non-negative.
|
|
1510
|
-
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1511
|
-
* @note Defined only for floating-point and integer data types.
|
|
1512
|
-
*/
|
|
1513
|
-
SIMSIMD_DYNAMIC void simsimd_cos_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1514
|
-
simsimd_distance_t *d);
|
|
1515
|
-
SIMSIMD_DYNAMIC void simsimd_cos_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1516
|
-
simsimd_distance_t *d);
|
|
1517
|
-
SIMSIMD_DYNAMIC void simsimd_cos_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1518
|
-
simsimd_distance_t *d);
|
|
1519
|
-
SIMSIMD_DYNAMIC void simsimd_cos_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1520
|
-
simsimd_distance_t *d);
|
|
1521
|
-
SIMSIMD_DYNAMIC void simsimd_cos_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1522
|
-
simsimd_distance_t *d);
|
|
1523
|
-
SIMSIMD_DYNAMIC void simsimd_cos_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1524
|
-
simsimd_distance_t *d);
|
|
1525
|
-
SIMSIMD_DYNAMIC void simsimd_l2sq_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1526
|
-
simsimd_distance_t *d);
|
|
1527
|
-
SIMSIMD_DYNAMIC void simsimd_l2sq_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1528
|
-
simsimd_distance_t *d);
|
|
1529
|
-
SIMSIMD_DYNAMIC void simsimd_l2sq_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1530
|
-
simsimd_distance_t *d);
|
|
1531
|
-
SIMSIMD_DYNAMIC void simsimd_l2sq_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1532
|
-
simsimd_distance_t *d);
|
|
1533
|
-
SIMSIMD_DYNAMIC void simsimd_l2sq_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1534
|
-
simsimd_distance_t *d);
|
|
1535
|
-
SIMSIMD_DYNAMIC void simsimd_l2sq_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1536
|
-
simsimd_distance_t *d);
|
|
1537
|
-
SIMSIMD_DYNAMIC void simsimd_l2_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1538
|
-
simsimd_distance_t *d);
|
|
1539
|
-
SIMSIMD_DYNAMIC void simsimd_l2_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1540
|
-
simsimd_distance_t *d);
|
|
1541
|
-
SIMSIMD_DYNAMIC void simsimd_l2_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1542
|
-
simsimd_distance_t *d);
|
|
1543
|
-
SIMSIMD_DYNAMIC void simsimd_l2_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1544
|
-
simsimd_distance_t *d);
|
|
1545
|
-
SIMSIMD_DYNAMIC void simsimd_l2_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1546
|
-
simsimd_distance_t *d);
|
|
1547
|
-
SIMSIMD_DYNAMIC void simsimd_l2_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1548
|
-
simsimd_distance_t *d);
|
|
1549
|
-
|
|
1550
|
-
/* Binary distances
|
|
1551
|
-
* - Hamming distance: the number of positions at which the corresponding bits are different.
|
|
1552
|
-
* - Jaccard distance: ratio of bit-level matching positions (intersection) to the total number of positions (union).
|
|
1553
|
-
*
|
|
1554
|
-
* @param a The first binary vector.
|
|
1555
|
-
* @param b The second binary vector.
|
|
1556
|
-
* @param n The number of 8-bit words in the vectors.
|
|
1557
|
-
* @param d The output distance value.
|
|
1558
|
-
*
|
|
1559
|
-
* @note The output distance value is non-negative.
|
|
1560
|
-
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1561
|
-
* @note Defined only for binary data.
|
|
1562
|
-
*/
|
|
1563
|
-
SIMSIMD_DYNAMIC void simsimd_hamming_b8(simsimd_b8_t const *a, simsimd_b8_t const *b, simsimd_size_t n,
|
|
1564
|
-
simsimd_distance_t *d);
|
|
1565
|
-
SIMSIMD_DYNAMIC void simsimd_jaccard_b8(simsimd_b8_t const *a, simsimd_b8_t const *b, simsimd_size_t n,
|
|
1566
|
-
simsimd_distance_t *d);
|
|
1567
|
-
|
|
1568
|
-
/* Probability distributions
|
|
1569
|
-
* - Jensen-Shannon divergence: a measure of similarity between two probability distributions.
|
|
1570
|
-
* - Kullback-Leibler divergence: a measure of how one probability distribution diverges from a second.
|
|
1571
|
-
*
|
|
1572
|
-
* @param a The first discrete probability distribution.
|
|
1573
|
-
* @param b The second discrete probability distribution.
|
|
1574
|
-
* @param n The number of elements in the discrete distributions.
|
|
1575
|
-
* @param d The output divergence value.
|
|
1576
|
-
*
|
|
1577
|
-
* @note The distributions are assumed to be normalized.
|
|
1578
|
-
* @note The output divergence value is non-negative.
|
|
1579
|
-
* @note The output divergence value is zero if and only if the two distributions are identical.
|
|
1580
|
-
* @note Defined only for floating-point data types.
|
|
1581
|
-
*/
|
|
1582
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1583
|
-
simsimd_distance_t *d);
|
|
1584
|
-
SIMSIMD_DYNAMIC void simsimd_kl_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1585
|
-
simsimd_distance_t *d);
|
|
1586
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1587
|
-
simsimd_distance_t *d);
|
|
1588
|
-
SIMSIMD_DYNAMIC void simsimd_kl_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1589
|
-
simsimd_distance_t *d);
|
|
1590
|
-
SIMSIMD_DYNAMIC void simsimd_js_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1591
|
-
simsimd_distance_t *d);
|
|
1592
|
-
SIMSIMD_DYNAMIC void simsimd_js_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1593
|
-
simsimd_distance_t *d);
|
|
1594
|
-
SIMSIMD_DYNAMIC void simsimd_js_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1595
|
-
simsimd_distance_t *d);
|
|
1596
|
-
SIMSIMD_DYNAMIC void simsimd_js_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1597
|
-
simsimd_distance_t *d);
|
|
1598
|
-
|
|
1599
|
-
#else
|
|
1600
|
-
|
|
1601
|
-
/* Compile-time feature-testing functions
|
|
1602
|
-
* - Check if the CPU supports NEON or SVE extensions on Arm
|
|
1603
|
-
* - Check if the CPU supports AVX2 and F16C extensions on Haswell x86 CPUs and newer
|
|
1604
|
-
* - Check if the CPU supports AVX512F and AVX512BW extensions on Skylake x86 CPUs and newer
|
|
1605
|
-
* - Check if the CPU supports AVX512VNNI, AVX512IFMA, AVX512BITALG, AVX512VBMI2, and AVX512VPOPCNTDQ
|
|
1606
|
-
* extensions on Ice Lake x86 CPUs and newer
|
|
1607
|
-
* - Check if the CPU supports AVX512BF16 extensions on Genoa x86 CPUs and newer
|
|
1608
|
-
* - Check if the CPU supports AVX512FP16 extensions on Sapphire Rapids x86 CPUs and newer
|
|
1609
|
-
*
|
|
1610
|
-
* @return 1 if the CPU supports the SIMD instruction set, 0 otherwise.
|
|
1611
|
-
*/
|
|
1612
|
-
|
|
1613
|
-
// clang-format off
|
|
1614
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON; }
|
|
1615
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_f16(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_F16 ; }
|
|
1616
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_bf16(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_BF16; }
|
|
1617
|
-
SIMSIMD_PUBLIC int simsimd_uses_neon_i8(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_NEON_I8; }
|
|
1618
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE; }
|
|
1619
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_f16(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_F16; }
|
|
1620
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_bf16(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_BF16; }
|
|
1621
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve_i8(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE_I8; }
|
|
1622
|
-
SIMSIMD_PUBLIC int simsimd_uses_sve2(void) { return _SIMSIMD_TARGET_ARM && SIMSIMD_TARGET_SVE2; }
|
|
1623
|
-
SIMSIMD_PUBLIC int simsimd_uses_haswell(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_HASWELL; }
|
|
1624
|
-
SIMSIMD_PUBLIC int simsimd_uses_skylake(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SKYLAKE; }
|
|
1625
|
-
SIMSIMD_PUBLIC int simsimd_uses_ice(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_ICE; }
|
|
1626
|
-
SIMSIMD_PUBLIC int simsimd_uses_genoa(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_GENOA; }
|
|
1627
|
-
SIMSIMD_PUBLIC int simsimd_uses_sapphire(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SAPPHIRE; }
|
|
1628
|
-
SIMSIMD_PUBLIC int simsimd_uses_turin(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_TURIN; }
|
|
1629
|
-
SIMSIMD_PUBLIC int simsimd_uses_sierra(void) { return _SIMSIMD_TARGET_X86 && SIMSIMD_TARGET_SIERRA; }
|
|
1630
|
-
SIMSIMD_PUBLIC int simsimd_uses_dynamic_dispatch(void) { return 0; }
|
|
1631
|
-
SIMSIMD_PUBLIC int simsimd_flush_denormals(void) { return _simsimd_flush_denormals(); }
|
|
1632
|
-
SIMSIMD_PUBLIC simsimd_capability_t simsimd_capabilities(void) { return _simsimd_capabilities_implementation(); }
|
|
1633
|
-
SIMSIMD_PUBLIC void simsimd_find_kernel_punned( //
|
|
1634
|
-
simsimd_metric_kind_t kind, //
|
|
1635
|
-
simsimd_datatype_t datatype, //
|
|
1636
|
-
simsimd_capability_t supported, //
|
|
1637
|
-
simsimd_capability_t allowed, //
|
|
1638
|
-
simsimd_kernel_punned_t* kernel_output, //
|
|
1639
|
-
simsimd_capability_t* capability_output) {
|
|
1640
|
-
_simsimd_find_kernel_punned_implementation(kind, datatype, supported, allowed, kernel_output, capability_output);
|
|
1641
|
-
}
|
|
1642
|
-
// clang-format on
|
|
1643
|
-
|
|
1644
|
-
/* Inner products
|
|
1645
|
-
* - Dot product: the sum of the products of the corresponding elements of two vectors.
|
|
1646
|
-
* - Complex Dot product: dot product with a conjugate first argument.
|
|
1647
|
-
* - Complex Conjugate Dot product: dot product with a conjugate first argument.
|
|
1648
|
-
*
|
|
1649
|
-
* @param a The first vector.
|
|
1650
|
-
* @param b The second vector.
|
|
1651
|
-
* @param n The number of elements in the vectors. Even for complex variants (the number of scalars).
|
|
1652
|
-
* @param d The output distance value.
|
|
1653
|
-
*
|
|
1654
|
-
* @note The dot product can be negative, to use as a distance, take `1 - a * b`.
|
|
1655
|
-
* @note The dot product is zero if and only if the two vectors are orthogonal.
|
|
1656
|
-
* @note Defined only for floating-point and integer data types.
|
|
1657
|
-
*/
|
|
1658
|
-
SIMSIMD_PUBLIC void simsimd_dot_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1659
|
-
simsimd_distance_t *d) {
|
|
1660
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
1661
|
-
simsimd_dot_i8_neon(a, b, n, d);
|
|
1662
|
-
#elif SIMSIMD_TARGET_ICE
|
|
1663
|
-
simsimd_dot_i8_ice(a, b, n, d);
|
|
1664
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1665
|
-
simsimd_dot_i8_haswell(a, b, n, d);
|
|
1666
|
-
#else
|
|
1667
|
-
simsimd_dot_i8_serial(a, b, n, d);
|
|
1668
|
-
#endif
|
|
1669
|
-
}
|
|
1670
|
-
SIMSIMD_PUBLIC void simsimd_dot_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1671
|
-
simsimd_distance_t *d) {
|
|
1672
|
-
#if SIMSIMD_TARGET_NEON_F16
|
|
1673
|
-
simsimd_dot_u8_neon(a, b, n, d);
|
|
1674
|
-
#elif SIMSIMD_TARGET_ICE
|
|
1675
|
-
simsimd_dot_u8_ice(a, b, n, d);
|
|
1676
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1677
|
-
simsimd_dot_u8_haswell(a, b, n, d);
|
|
1678
|
-
#else
|
|
1679
|
-
simsimd_dot_u8_serial(a, b, n, d);
|
|
1680
|
-
#endif
|
|
1681
|
-
}
|
|
1682
|
-
SIMSIMD_PUBLIC void simsimd_dot_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1683
|
-
simsimd_distance_t *d) {
|
|
1684
|
-
#if SIMSIMD_TARGET_SVE_F16
|
|
1685
|
-
simsimd_dot_f16_sve(a, b, n, d);
|
|
1686
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
1687
|
-
simsimd_dot_f16_neon(a, b, n, d);
|
|
1688
|
-
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1689
|
-
simsimd_dot_f16_sapphire(a, b, n, d);
|
|
1690
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1691
|
-
simsimd_dot_f16_haswell(a, b, n, d);
|
|
1692
|
-
#else
|
|
1693
|
-
simsimd_dot_f16_serial(a, b, n, d);
|
|
1694
|
-
#endif
|
|
1695
|
-
}
|
|
1696
|
-
SIMSIMD_PUBLIC void simsimd_dot_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1697
|
-
simsimd_distance_t *d) {
|
|
1698
|
-
#if SIMSIMD_TARGET_GENOA
|
|
1699
|
-
simsimd_dot_bf16_genoa(a, b, n, d);
|
|
1700
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1701
|
-
simsimd_dot_bf16_haswell(a, b, n, d);
|
|
1702
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1703
|
-
simsimd_dot_bf16_neon(a, b, n, d);
|
|
1704
|
-
#else
|
|
1705
|
-
simsimd_dot_bf16_serial(a, b, n, d);
|
|
1706
|
-
#endif
|
|
1707
|
-
}
|
|
1708
|
-
SIMSIMD_PUBLIC void simsimd_dot_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1709
|
-
simsimd_distance_t *d) {
|
|
1710
|
-
#if SIMSIMD_TARGET_SVE
|
|
1711
|
-
simsimd_dot_f32_sve(a, b, n, d);
|
|
1712
|
-
#elif SIMSIMD_TARGET_NEON
|
|
1713
|
-
simsimd_dot_f32_neon(a, b, n, d);
|
|
1714
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1715
|
-
simsimd_dot_f32_skylake(a, b, n, d);
|
|
1716
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1717
|
-
simsimd_dot_f32_haswell(a, b, n, d);
|
|
1718
|
-
#else
|
|
1719
|
-
simsimd_dot_f32_serial(a, b, n, d);
|
|
1720
|
-
#endif
|
|
1721
|
-
}
|
|
1722
|
-
SIMSIMD_PUBLIC void simsimd_dot_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1723
|
-
simsimd_distance_t *d) {
|
|
1724
|
-
#if SIMSIMD_TARGET_SVE
|
|
1725
|
-
simsimd_dot_f64_sve(a, b, n, d);
|
|
1726
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1727
|
-
simsimd_dot_f64_skylake(a, b, n, d);
|
|
1728
|
-
#else
|
|
1729
|
-
simsimd_dot_f64_serial(a, b, n, d);
|
|
1730
|
-
#endif
|
|
1731
|
-
}
|
|
1732
|
-
SIMSIMD_PUBLIC void simsimd_dot_f16c(simsimd_f16c_t const *a, simsimd_f16c_t const *b, simsimd_size_t n,
|
|
1733
|
-
simsimd_distance_t *d) {
|
|
1734
|
-
#if SIMSIMD_TARGET_SVE_F16
|
|
1735
|
-
simsimd_dot_f16c_sve(a, b, n, d);
|
|
1736
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
1737
|
-
simsimd_dot_f16c_neon(a, b, n, d);
|
|
1738
|
-
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1739
|
-
simsimd_dot_f16c_sapphire(a, b, n, d);
|
|
1740
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1741
|
-
simsimd_dot_f16c_haswell(a, b, n, d);
|
|
1742
|
-
#else
|
|
1743
|
-
simsimd_dot_f16c_serial(a, b, n, d);
|
|
1744
|
-
#endif
|
|
1745
|
-
}
|
|
1746
|
-
SIMSIMD_PUBLIC void simsimd_dot_bf16c(simsimd_bf16c_t const *a, simsimd_bf16c_t const *b, simsimd_size_t n,
|
|
1747
|
-
simsimd_distance_t *d) {
|
|
1748
|
-
#if SIMSIMD_TARGET_GENOA
|
|
1749
|
-
simsimd_dot_bf16c_genoa(a, b, n, d);
|
|
1750
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1751
|
-
simsimd_dot_bf16c_neon(a, b, n, d);
|
|
1752
|
-
#else
|
|
1753
|
-
simsimd_dot_bf16c_serial(a, b, n, d);
|
|
1754
|
-
#endif
|
|
1755
|
-
}
|
|
1756
|
-
SIMSIMD_PUBLIC void simsimd_dot_f32c(simsimd_f32c_t const *a, simsimd_f32c_t const *b, simsimd_size_t n,
|
|
1757
|
-
simsimd_distance_t *d) {
|
|
1758
|
-
#if SIMSIMD_TARGET_SVE
|
|
1759
|
-
simsimd_dot_f32c_sve(a, b, n, d);
|
|
1760
|
-
#elif SIMSIMD_TARGET_NEON
|
|
1761
|
-
simsimd_dot_f32c_neon(a, b, n, d);
|
|
1762
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1763
|
-
simsimd_dot_f32c_skylake(a, b, n, d);
|
|
1764
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1765
|
-
simsimd_dot_f32c_haswell(a, b, n, d);
|
|
1766
|
-
#else
|
|
1767
|
-
simsimd_dot_f32c_serial(a, b, n, d);
|
|
1768
|
-
#endif
|
|
1769
|
-
}
|
|
1770
|
-
SIMSIMD_PUBLIC void simsimd_dot_f64c(simsimd_f64c_t const *a, simsimd_f64c_t const *b, simsimd_size_t n,
|
|
1771
|
-
simsimd_distance_t *d) {
|
|
1772
|
-
#if SIMSIMD_TARGET_SVE
|
|
1773
|
-
simsimd_dot_f64c_sve(a, b, n, d);
|
|
1774
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1775
|
-
simsimd_dot_f64c_skylake(a, b, n, d);
|
|
1776
|
-
#else
|
|
1777
|
-
simsimd_dot_f64c_serial(a, b, n, d);
|
|
1778
|
-
#endif
|
|
1779
|
-
}
|
|
1780
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f16c(simsimd_f16c_t const *a, simsimd_f16c_t const *b, simsimd_size_t n,
|
|
1781
|
-
simsimd_distance_t *d) {
|
|
1782
|
-
#if SIMSIMD_TARGET_SVE
|
|
1783
|
-
simsimd_vdot_f16c_sve(a, b, n, d);
|
|
1784
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
1785
|
-
simsimd_dot_f16c_neon(a, b, n, d);
|
|
1786
|
-
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1787
|
-
simsimd_dot_f16c_sapphire(a, b, n, d);
|
|
1788
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1789
|
-
simsimd_dot_f16c_haswell(a, b, n, d);
|
|
1790
|
-
#else
|
|
1791
|
-
simsimd_vdot_f16c_serial(a, b, n, d);
|
|
1792
|
-
#endif
|
|
1793
|
-
}
|
|
1794
|
-
SIMSIMD_PUBLIC void simsimd_vdot_bf16c(simsimd_bf16c_t const *a, simsimd_bf16c_t const *b, simsimd_size_t n,
|
|
1795
|
-
simsimd_distance_t *d) {
|
|
1796
|
-
#if SIMSIMD_TARGET_GENOA
|
|
1797
|
-
simsimd_vdot_bf16c_genoa(a, b, n, d);
|
|
1798
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1799
|
-
simsimd_dot_bf16c_neon(a, b, n, d);
|
|
1800
|
-
#else
|
|
1801
|
-
simsimd_vdot_bf16c_serial(a, b, n, d);
|
|
1802
|
-
#endif
|
|
1803
|
-
}
|
|
1804
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f32c(simsimd_f32c_t const *a, simsimd_f32c_t const *b, simsimd_size_t n,
|
|
1805
|
-
simsimd_distance_t *d) {
|
|
1806
|
-
#if SIMSIMD_TARGET_SVE
|
|
1807
|
-
simsimd_vdot_f32c_sve(a, b, n, d);
|
|
1808
|
-
#elif SIMSIMD_TARGET_NEON
|
|
1809
|
-
simsimd_dot_f32c_neon(a, b, n, d);
|
|
1810
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1811
|
-
simsimd_dot_f32c_skylake(a, b, n, d);
|
|
1812
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1813
|
-
simsimd_dot_f32c_haswell(a, b, n, d);
|
|
1814
|
-
#else
|
|
1815
|
-
simsimd_vdot_f32c_serial(a, b, n, d);
|
|
1816
|
-
#endif
|
|
1817
|
-
}
|
|
1818
|
-
SIMSIMD_PUBLIC void simsimd_vdot_f64c(simsimd_f64c_t const *a, simsimd_f64c_t const *b, simsimd_size_t n,
|
|
1819
|
-
simsimd_distance_t *d) {
|
|
1820
|
-
#if SIMSIMD_TARGET_SVE
|
|
1821
|
-
simsimd_vdot_f64c_sve(a, b, n, d);
|
|
1822
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1823
|
-
simsimd_vdot_f64c_skylake(a, b, n, d);
|
|
1824
|
-
#else
|
|
1825
|
-
simsimd_vdot_f64c_serial(a, b, n, d);
|
|
1826
|
-
#endif
|
|
1827
|
-
}
|
|
1828
|
-
|
|
1829
|
-
/* Spatial distances
|
|
1830
|
-
* - Cosine distance: the cosine of the angle between two vectors.
|
|
1831
|
-
* - L2 squared distance: the squared Euclidean distance between two vectors.
|
|
1832
|
-
*
|
|
1833
|
-
* @param a The first vector.
|
|
1834
|
-
* @param b The second vector.
|
|
1835
|
-
* @param n The number of elements in the vectors.
|
|
1836
|
-
* @param d The output distance value.
|
|
1837
|
-
*
|
|
1838
|
-
* @note The output distance value is non-negative.
|
|
1839
|
-
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
1840
|
-
* @note Defined only for floating-point and integer data types.
|
|
1841
|
-
*/
|
|
1842
|
-
SIMSIMD_PUBLIC void simsimd_cos_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1843
|
-
simsimd_distance_t *d) {
|
|
1844
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
1845
|
-
simsimd_cos_i8_neon(a, b, n, d);
|
|
1846
|
-
#elif SIMSIMD_TARGET_ICE
|
|
1847
|
-
simsimd_cos_i8_ice(a, b, n, d);
|
|
1848
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1849
|
-
simsimd_cos_i8_haswell(a, b, n, d);
|
|
1850
|
-
#else
|
|
1851
|
-
simsimd_cos_i8_serial(a, b, n, d);
|
|
1852
|
-
#endif
|
|
1853
|
-
}
|
|
1854
|
-
SIMSIMD_PUBLIC void simsimd_cos_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1855
|
-
simsimd_distance_t *d) {
|
|
1856
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
1857
|
-
simsimd_cos_u8_neon(a, b, n, d);
|
|
1858
|
-
#elif SIMSIMD_TARGET_ICE
|
|
1859
|
-
simsimd_cos_u8_ice(a, b, n, d);
|
|
1860
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1861
|
-
simsimd_cos_u8_haswell(a, b, n, d);
|
|
1862
|
-
#else
|
|
1863
|
-
simsimd_cos_u8_serial(a, b, n, d);
|
|
1864
|
-
#endif
|
|
1865
|
-
}
|
|
1866
|
-
SIMSIMD_PUBLIC void simsimd_cos_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1867
|
-
simsimd_distance_t *d) {
|
|
1868
|
-
#if SIMSIMD_TARGET_SVE_F16
|
|
1869
|
-
simsimd_cos_f16_sve(a, b, n, d);
|
|
1870
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
1871
|
-
simsimd_cos_f16_neon(a, b, n, d);
|
|
1872
|
-
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1873
|
-
simsimd_cos_f16_sapphire(a, b, n, d);
|
|
1874
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1875
|
-
simsimd_cos_f16_haswell(a, b, n, d);
|
|
1876
|
-
#else
|
|
1877
|
-
simsimd_cos_f16_serial(a, b, n, d);
|
|
1878
|
-
#endif
|
|
1879
|
-
}
|
|
1880
|
-
SIMSIMD_PUBLIC void simsimd_cos_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1881
|
-
simsimd_distance_t *d) {
|
|
1882
|
-
#if SIMSIMD_TARGET_GENOA
|
|
1883
|
-
simsimd_cos_bf16_genoa(a, b, n, d);
|
|
1884
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1885
|
-
simsimd_cos_bf16_haswell(a, b, n, d);
|
|
1886
|
-
#elif SIMSIMD_TARGET_SVE_BF16
|
|
1887
|
-
simsimd_cos_bf16_sve(a, b, n, d);
|
|
1888
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1889
|
-
simsimd_cos_bf16_neon(a, b, n, d);
|
|
1890
|
-
#else
|
|
1891
|
-
simsimd_cos_bf16_serial(a, b, n, d);
|
|
1892
|
-
#endif
|
|
1893
|
-
}
|
|
1894
|
-
SIMSIMD_PUBLIC void simsimd_cos_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1895
|
-
simsimd_distance_t *d) {
|
|
1896
|
-
#if SIMSIMD_TARGET_SVE
|
|
1897
|
-
simsimd_cos_f32_sve(a, b, n, d);
|
|
1898
|
-
#elif SIMSIMD_TARGET_NEON
|
|
1899
|
-
simsimd_cos_f32_neon(a, b, n, d);
|
|
1900
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1901
|
-
simsimd_cos_f32_skylake(a, b, n, d);
|
|
1902
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1903
|
-
simsimd_cos_f32_haswell(a, b, n, d);
|
|
1904
|
-
#else
|
|
1905
|
-
simsimd_cos_f32_serial(a, b, n, d);
|
|
1906
|
-
#endif
|
|
1907
|
-
}
|
|
1908
|
-
SIMSIMD_PUBLIC void simsimd_cos_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1909
|
-
simsimd_distance_t *d) {
|
|
1910
|
-
#if SIMSIMD_TARGET_SVE
|
|
1911
|
-
simsimd_cos_f64_sve(a, b, n, d);
|
|
1912
|
-
#elif SIMSIMD_TARGET_NEON
|
|
1913
|
-
simsimd_cos_f64_neon(a, b, n, d);
|
|
1914
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1915
|
-
simsimd_cos_f64_skylake(a, b, n, d);
|
|
1916
|
-
#else
|
|
1917
|
-
simsimd_cos_f64_serial(a, b, n, d);
|
|
1918
|
-
#endif
|
|
1919
|
-
}
|
|
1920
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1921
|
-
simsimd_distance_t *d) {
|
|
1922
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
1923
|
-
simsimd_l2sq_i8_neon(a, b, n, d);
|
|
1924
|
-
#elif SIMSIMD_TARGET_ICE
|
|
1925
|
-
simsimd_l2sq_i8_ice(a, b, n, d);
|
|
1926
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1927
|
-
simsimd_l2sq_i8_haswell(a, b, n, d);
|
|
1928
|
-
#else
|
|
1929
|
-
simsimd_l2sq_i8_serial(a, b, n, d);
|
|
1930
|
-
#endif
|
|
1931
|
-
}
|
|
1932
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
1933
|
-
simsimd_distance_t *d) {
|
|
1934
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
1935
|
-
simsimd_l2sq_u8_neon(a, b, n, d);
|
|
1936
|
-
#elif SIMSIMD_TARGET_ICE
|
|
1937
|
-
simsimd_l2sq_u8_ice(a, b, n, d);
|
|
1938
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1939
|
-
simsimd_l2sq_u8_haswell(a, b, n, d);
|
|
1940
|
-
#else
|
|
1941
|
-
simsimd_l2sq_u8_serial(a, b, n, d);
|
|
1942
|
-
#endif
|
|
1943
|
-
}
|
|
1944
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
1945
|
-
simsimd_distance_t *d) {
|
|
1946
|
-
#if SIMSIMD_TARGET_SVE_F16
|
|
1947
|
-
simsimd_l2sq_f16_sve(a, b, n, d);
|
|
1948
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
1949
|
-
simsimd_l2sq_f16_neon(a, b, n, d);
|
|
1950
|
-
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
1951
|
-
simsimd_l2sq_f16_sapphire(a, b, n, d);
|
|
1952
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1953
|
-
simsimd_l2sq_f16_haswell(a, b, n, d);
|
|
1954
|
-
#else
|
|
1955
|
-
simsimd_l2sq_f16_serial(a, b, n, d);
|
|
1956
|
-
#endif
|
|
1957
|
-
}
|
|
1958
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
1959
|
-
simsimd_distance_t *d) {
|
|
1960
|
-
#if SIMSIMD_TARGET_GENOA
|
|
1961
|
-
simsimd_l2sq_bf16_genoa(a, b, n, d);
|
|
1962
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1963
|
-
simsimd_l2sq_bf16_haswell(a, b, n, d);
|
|
1964
|
-
#elif SIMSIMD_TARGET_SVE_BF16
|
|
1965
|
-
simsimd_l2sq_bf16_sve(a, b, n, d);
|
|
1966
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
1967
|
-
simsimd_l2sq_bf16_neon(a, b, n, d);
|
|
1968
|
-
#else
|
|
1969
|
-
simsimd_l2sq_bf16_serial(a, b, n, d);
|
|
1970
|
-
#endif
|
|
1971
|
-
}
|
|
1972
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
1973
|
-
simsimd_distance_t *d) {
|
|
1974
|
-
#if SIMSIMD_TARGET_SVE
|
|
1975
|
-
simsimd_l2sq_f32_sve(a, b, n, d);
|
|
1976
|
-
#elif SIMSIMD_TARGET_NEON
|
|
1977
|
-
simsimd_l2sq_f32_neon(a, b, n, d);
|
|
1978
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1979
|
-
simsimd_l2sq_f32_skylake(a, b, n, d);
|
|
1980
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
1981
|
-
simsimd_l2sq_f32_haswell(a, b, n, d);
|
|
1982
|
-
#else
|
|
1983
|
-
simsimd_l2sq_f32_serial(a, b, n, d);
|
|
1984
|
-
#endif
|
|
1985
|
-
}
|
|
1986
|
-
SIMSIMD_PUBLIC void simsimd_l2sq_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
1987
|
-
simsimd_distance_t *d) {
|
|
1988
|
-
#if SIMSIMD_TARGET_SVE
|
|
1989
|
-
simsimd_l2sq_f64_sve(a, b, n, d);
|
|
1990
|
-
#elif SIMSIMD_TARGET_NEON
|
|
1991
|
-
simsimd_l2sq_f64_neon(a, b, n, d);
|
|
1992
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
1993
|
-
simsimd_l2sq_f64_skylake(a, b, n, d);
|
|
1994
|
-
#else
|
|
1995
|
-
simsimd_l2sq_f64_serial(a, b, n, d);
|
|
1996
|
-
#endif
|
|
1997
|
-
}
|
|
1998
|
-
SIMSIMD_PUBLIC void simsimd_l2_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
1999
|
-
simsimd_distance_t *d) {
|
|
2000
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
2001
|
-
simsimd_l2_i8_neon(a, b, n, d);
|
|
2002
|
-
#elif SIMSIMD_TARGET_ICE
|
|
2003
|
-
simsimd_l2_i8_ice(a, b, n, d);
|
|
2004
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2005
|
-
simsimd_l2_i8_haswell(a, b, n, d);
|
|
2006
|
-
#else
|
|
2007
|
-
simsimd_l2_i8_serial(a, b, n, d);
|
|
2008
|
-
#endif
|
|
2009
|
-
}
|
|
2010
|
-
SIMSIMD_PUBLIC void simsimd_l2_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
2011
|
-
simsimd_distance_t *d) {
|
|
2012
|
-
#if SIMSIMD_TARGET_NEON_I8
|
|
2013
|
-
simsimd_l2_u8_neon(a, b, n, d);
|
|
2014
|
-
#elif SIMSIMD_TARGET_ICE
|
|
2015
|
-
simsimd_l2_u8_ice(a, b, n, d);
|
|
2016
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2017
|
-
simsimd_l2_u8_haswell(a, b, n, d);
|
|
2018
|
-
#else
|
|
2019
|
-
simsimd_l2_u8_serial(a, b, n, d);
|
|
2020
|
-
#endif
|
|
2021
|
-
}
|
|
2022
|
-
SIMSIMD_PUBLIC void simsimd_l2_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
2023
|
-
simsimd_distance_t *d) {
|
|
2024
|
-
#if SIMSIMD_TARGET_SVE_F16
|
|
2025
|
-
simsimd_l2_f16_sve(a, b, n, d);
|
|
2026
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2027
|
-
simsimd_l2_f16_neon(a, b, n, d);
|
|
2028
|
-
#elif SIMSIMD_TARGET_SAPPHIRE
|
|
2029
|
-
simsimd_l2_f16_sapphire(a, b, n, d);
|
|
2030
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2031
|
-
simsimd_l2_f16_haswell(a, b, n, d);
|
|
2032
|
-
#else
|
|
2033
|
-
simsimd_l2_f16_serial(a, b, n, d);
|
|
2034
|
-
#endif
|
|
2035
|
-
}
|
|
2036
|
-
SIMSIMD_PUBLIC void simsimd_l2_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
2037
|
-
simsimd_distance_t *d) {
|
|
2038
|
-
#if SIMSIMD_TARGET_GENOA
|
|
2039
|
-
simsimd_l2_bf16_genoa(a, b, n, d);
|
|
2040
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2041
|
-
simsimd_l2_bf16_haswell(a, b, n, d);
|
|
2042
|
-
#elif SIMSIMD_TARGET_SVE_BF16
|
|
2043
|
-
simsimd_l2_bf16_sve(a, b, n, d);
|
|
2044
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2045
|
-
simsimd_l2_bf16_neon(a, b, n, d);
|
|
2046
|
-
#else
|
|
2047
|
-
simsimd_l2_bf16_serial(a, b, n, d);
|
|
2048
|
-
#endif
|
|
2049
|
-
}
|
|
2050
|
-
SIMSIMD_PUBLIC void simsimd_l2_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
2051
|
-
simsimd_distance_t *d) {
|
|
2052
|
-
#if SIMSIMD_TARGET_SVE
|
|
2053
|
-
simsimd_l2_f32_sve(a, b, n, d);
|
|
2054
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2055
|
-
simsimd_l2_f32_neon(a, b, n, d);
|
|
2056
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
2057
|
-
simsimd_l2_f32_skylake(a, b, n, d);
|
|
2058
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2059
|
-
simsimd_l2_f32_haswell(a, b, n, d);
|
|
2060
|
-
#else
|
|
2061
|
-
simsimd_l2_f32_serial(a, b, n, d);
|
|
2062
|
-
#endif
|
|
2063
|
-
}
|
|
2064
|
-
SIMSIMD_PUBLIC void simsimd_l2_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
2065
|
-
simsimd_distance_t *d) {
|
|
2066
|
-
#if SIMSIMD_TARGET_SVE
|
|
2067
|
-
simsimd_l2_f64_sve(a, b, n, d);
|
|
2068
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2069
|
-
simsimd_l2_f64_neon(a, b, n, d);
|
|
2070
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
2071
|
-
simsimd_l2_f64_skylake(a, b, n, d);
|
|
2072
|
-
#else
|
|
2073
|
-
simsimd_l2_f64_serial(a, b, n, d);
|
|
2074
|
-
#endif
|
|
2075
|
-
}
|
|
2076
|
-
|
|
2077
|
-
/* Binary distances
|
|
2078
|
-
* - Hamming distance: the number of positions at which the corresponding bits are different.
|
|
2079
|
-
* - Jaccard distance: ratio of bit-level matching positions (intersection) to the total number of positions (union).
|
|
2080
|
-
*
|
|
2081
|
-
* @param a The first binary vector.
|
|
2082
|
-
* @param b The second binary vector.
|
|
2083
|
-
* @param n The number of 8-bit words in the vectors.
|
|
2084
|
-
* @param d The output distance value.
|
|
2085
|
-
*
|
|
2086
|
-
* @note The output distance value is non-negative.
|
|
2087
|
-
* @note The output distance value is zero if and only if the two vectors are identical.
|
|
2088
|
-
* @note Defined only for binary data.
|
|
2089
|
-
*/
|
|
2090
|
-
SIMSIMD_PUBLIC void simsimd_hamming_b8(simsimd_b8_t const *a, simsimd_b8_t const *b, simsimd_size_t n,
|
|
2091
|
-
simsimd_distance_t *d) {
|
|
2092
|
-
#if SIMSIMD_TARGET_SVE
|
|
2093
|
-
simsimd_hamming_b8_sve(a, b, n, d);
|
|
2094
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2095
|
-
simsimd_hamming_b8_neon(a, b, n, d);
|
|
2096
|
-
#elif SIMSIMD_TARGET_ICE
|
|
2097
|
-
simsimd_hamming_b8_ice(a, b, n, d);
|
|
2098
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2099
|
-
simsimd_hamming_b8_haswell(a, b, n, d);
|
|
2100
|
-
#else
|
|
2101
|
-
simsimd_hamming_b8_serial(a, b, n, d);
|
|
2102
|
-
#endif
|
|
2103
|
-
}
|
|
2104
|
-
SIMSIMD_PUBLIC void simsimd_jaccard_b8(simsimd_b8_t const *a, simsimd_b8_t const *b, simsimd_size_t n,
|
|
2105
|
-
simsimd_distance_t *d) {
|
|
2106
|
-
#if SIMSIMD_TARGET_SVE
|
|
2107
|
-
simsimd_jaccard_b8_sve(a, b, n, d);
|
|
2108
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2109
|
-
simsimd_jaccard_b8_neon(a, b, n, d);
|
|
2110
|
-
#elif SIMSIMD_TARGET_ICE
|
|
2111
|
-
simsimd_jaccard_b8_ice(a, b, n, d);
|
|
2112
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2113
|
-
simsimd_jaccard_b8_haswell(a, b, n, d);
|
|
2114
|
-
#else
|
|
2115
|
-
simsimd_jaccard_b8_serial(a, b, n, d);
|
|
2116
|
-
#endif
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
/* Probability distributions
|
|
2120
|
-
* - Jensen-Shannon divergence: a measure of similarity between two probability distributions.
|
|
2121
|
-
* - Kullback-Leibler divergence: a measure of how one probability distribution diverges from a second.
|
|
2122
|
-
*
|
|
2123
|
-
* @param a The first discrete probability distribution.
|
|
2124
|
-
* @param b The second discrete probability distribution.
|
|
2125
|
-
* @param n The number of elements in the discrete distributions.
|
|
2126
|
-
* @param d The output divergence value.
|
|
2127
|
-
*
|
|
2128
|
-
* @note The distributions are assumed to be normalized.
|
|
2129
|
-
* @note The output divergence value is non-negative.
|
|
2130
|
-
* @note The output divergence value is zero if and only if the two distributions are identical.
|
|
2131
|
-
* @note Defined only for floating-point data types.
|
|
2132
|
-
*/
|
|
2133
|
-
SIMSIMD_PUBLIC void simsimd_kl_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
2134
|
-
simsimd_distance_t *d) {
|
|
2135
|
-
#if SIMSIMD_TARGET_NEON_F16
|
|
2136
|
-
simsimd_kl_f16_neon(a, b, n, d);
|
|
2137
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2138
|
-
simsimd_kl_f16_haswell(a, b, n, d);
|
|
2139
|
-
#else
|
|
2140
|
-
simsimd_kl_f16_serial(a, b, n, d);
|
|
2141
|
-
#endif
|
|
2142
|
-
}
|
|
2143
|
-
SIMSIMD_PUBLIC void simsimd_kl_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
2144
|
-
simsimd_distance_t *d) {
|
|
2145
|
-
simsimd_kl_bf16_serial(a, b, n, d);
|
|
2146
|
-
}
|
|
2147
|
-
SIMSIMD_PUBLIC void simsimd_kl_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
2148
|
-
simsimd_distance_t *d) {
|
|
2149
|
-
#if SIMSIMD_TARGET_NEON
|
|
2150
|
-
simsimd_kl_f32_neon(a, b, n, d);
|
|
2151
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
2152
|
-
simsimd_kl_f32_skylake(a, b, n, d);
|
|
2153
|
-
#else
|
|
2154
|
-
simsimd_kl_f32_serial(a, b, n, d);
|
|
2155
|
-
#endif
|
|
2156
|
-
}
|
|
2157
|
-
SIMSIMD_PUBLIC void simsimd_kl_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
2158
|
-
simsimd_distance_t *d) {
|
|
2159
|
-
simsimd_kl_f64_serial(a, b, n, d);
|
|
2160
|
-
}
|
|
2161
|
-
SIMSIMD_PUBLIC void simsimd_js_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
2162
|
-
simsimd_distance_t *d) {
|
|
2163
|
-
#if SIMSIMD_TARGET_NEON_F16
|
|
2164
|
-
simsimd_js_f16_neon(a, b, n, d);
|
|
2165
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2166
|
-
simsimd_js_f16_haswell(a, b, n, d);
|
|
2167
|
-
#else
|
|
2168
|
-
simsimd_js_f16_serial(a, b, n, d);
|
|
2169
|
-
#endif
|
|
2170
|
-
}
|
|
2171
|
-
SIMSIMD_PUBLIC void simsimd_js_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
2172
|
-
simsimd_distance_t *d) {
|
|
2173
|
-
simsimd_js_bf16_serial(a, b, n, d);
|
|
2174
|
-
}
|
|
2175
|
-
SIMSIMD_PUBLIC void simsimd_js_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
2176
|
-
simsimd_distance_t *d) {
|
|
2177
|
-
#if SIMSIMD_TARGET_NEON
|
|
2178
|
-
simsimd_js_f32_neon(a, b, n, d);
|
|
2179
|
-
#elif SIMSIMD_TARGET_SKYLAKE
|
|
2180
|
-
simsimd_js_f32_skylake(a, b, n, d);
|
|
2181
|
-
#else
|
|
2182
|
-
simsimd_js_f32_serial(a, b, n, d);
|
|
2183
|
-
#endif
|
|
2184
|
-
}
|
|
2185
|
-
SIMSIMD_PUBLIC void simsimd_js_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
2186
|
-
simsimd_distance_t *d) {
|
|
2187
|
-
simsimd_js_f64_serial(a, b, n, d);
|
|
2188
|
-
}
|
|
2189
|
-
|
|
2190
|
-
/* Set operations
|
|
2191
|
-
*
|
|
2192
|
-
* @param a The first sorted array of integers.
|
|
2193
|
-
* @param b The second sorted array of integers.
|
|
2194
|
-
* @param a_length The number of elements in the first array.
|
|
2195
|
-
* @param b_length The number of elements in the second array.
|
|
2196
|
-
* @param d The output for the number of elements in the intersection.
|
|
2197
|
-
*/
|
|
2198
|
-
SIMSIMD_PUBLIC void simsimd_intersect_u16(simsimd_u16_t const *a, simsimd_u16_t const *b, simsimd_size_t a_length,
|
|
2199
|
-
simsimd_size_t b_length, simsimd_distance_t *d) {
|
|
2200
|
-
#if SIMSIMD_TARGET_SVE2
|
|
2201
|
-
simsimd_intersect_u16_sve2(a, b, a_length, b_length, d);
|
|
2202
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2203
|
-
simsimd_intersect_u16_neon(a, b, a_length, b_length, d);
|
|
2204
|
-
#elif SIMSIMD_TARGET_TURIN
|
|
2205
|
-
simsimd_intersect_u16_turin(a, b, a_length, b_length, d);
|
|
2206
|
-
#elif SIMSIMD_TARGET_ICE
|
|
2207
|
-
simsimd_intersect_u16_ice(a, b, a_length, b_length, d);
|
|
2208
|
-
#else
|
|
2209
|
-
simsimd_intersect_u16_serial(a, b, a_length, b_length, d);
|
|
2210
|
-
#endif
|
|
2211
|
-
}
|
|
2212
|
-
|
|
2213
|
-
SIMSIMD_PUBLIC void simsimd_intersect_u32(simsimd_u32_t const *a, simsimd_u32_t const *b, simsimd_size_t a_length,
|
|
2214
|
-
simsimd_size_t b_length, simsimd_distance_t *d) {
|
|
2215
|
-
#if SIMSIMD_TARGET_SVE2
|
|
2216
|
-
simsimd_intersect_u32_sve2(a, b, a_length, b_length, d);
|
|
2217
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2218
|
-
simsimd_intersect_u32_neon(a, b, a_length, b_length, d);
|
|
2219
|
-
#elif SIMSIMD_TARGET_TURIN
|
|
2220
|
-
simsimd_intersect_u32_turin(a, b, a_length, b_length, d);
|
|
2221
|
-
#elif SIMSIMD_TARGET_ICE
|
|
2222
|
-
simsimd_intersect_u32_ice(a, b, a_length, b_length, d);
|
|
2223
|
-
#else
|
|
2224
|
-
simsimd_intersect_u32_serial(a, b, a_length, b_length, d);
|
|
2225
|
-
#endif
|
|
2226
|
-
}
|
|
2227
|
-
|
|
2228
|
-
/* Weighted set operations
|
|
2229
|
-
*
|
|
2230
|
-
* @param a The first sorted array of integers.
|
|
2231
|
-
* @param b The second sorted array of integers.
|
|
2232
|
-
* @param a_weights The weights for the first array.
|
|
2233
|
-
* @param b_weights The weights for the second array.
|
|
2234
|
-
* @param a_length The number of elements in the first array.
|
|
2235
|
-
* @param b_length The number of elements in the second array.
|
|
2236
|
-
* @param d The output for the number of elements in the intersection.
|
|
2237
|
-
*/
|
|
2238
|
-
SIMSIMD_PUBLIC void simsimd_spdot_counts_u16(simsimd_u16_t const *a, simsimd_u16_t const *b,
|
|
2239
|
-
simsimd_i16_t const *a_weights, simsimd_i16_t const *b_weights,
|
|
2240
|
-
simsimd_size_t a_length, simsimd_size_t b_length, simsimd_distance_t *d) {
|
|
2241
|
-
#if SIMSIMD_TARGET_SVE2
|
|
2242
|
-
simsimd_spdot_counts_u16_sve2(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2243
|
-
#elif SIMSIMD_TARGET_TURIN
|
|
2244
|
-
simsimd_spdot_counts_u16_turin(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2245
|
-
#else
|
|
2246
|
-
simsimd_spdot_counts_u16_serial(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2247
|
-
#endif
|
|
2248
|
-
}
|
|
2249
|
-
|
|
2250
|
-
SIMSIMD_PUBLIC void simsimd_spdot_weights_u16(simsimd_u16_t const *a, simsimd_u16_t const *b,
|
|
2251
|
-
simsimd_bf16_t const *a_weights, simsimd_bf16_t const *b_weights,
|
|
2252
|
-
simsimd_size_t a_length, simsimd_size_t b_length, simsimd_distance_t *d) {
|
|
2253
|
-
#if SIMSIMD_TARGET_SVE2
|
|
2254
|
-
simsimd_spdot_weights_u16_sve2(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2255
|
-
#elif SIMSIMD_TARGET_TURIN
|
|
2256
|
-
simsimd_spdot_weights_u16_turin(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2257
|
-
#else
|
|
2258
|
-
simsimd_spdot_weights_u16_serial(a, b, a_weights, b_weights, a_length, b_length, d);
|
|
2259
|
-
#endif
|
|
2260
|
-
}
|
|
2261
|
-
|
|
2262
|
-
/* Curved space distances
|
|
2263
|
-
*
|
|
2264
|
-
* @param a The first vector of floating point values.
|
|
2265
|
-
* @param b The second vector of floating point values.
|
|
2266
|
-
* @param c The metric tensor or covariance matrix.
|
|
2267
|
-
* @param n The number of dimensions in the vectors.
|
|
2268
|
-
* @param d The output for the number of elements in the intersection.
|
|
2269
|
-
*/
|
|
2270
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_f64_t const *c,
|
|
2271
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2272
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2273
|
-
simsimd_bilinear_f64_skylake(a, b, c, n, d);
|
|
2274
|
-
#else
|
|
2275
|
-
simsimd_bilinear_f64_serial(a, b, c, n, d);
|
|
2276
|
-
#endif
|
|
2277
|
-
}
|
|
2278
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
2279
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2280
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2281
|
-
simsimd_bilinear_f32_skylake(a, b, c, n, d);
|
|
2282
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2283
|
-
simsimd_bilinear_f32_neon(a, b, c, n, d);
|
|
2284
|
-
#else
|
|
2285
|
-
simsimd_bilinear_f32_serial(a, b, c, n, d);
|
|
2286
|
-
#endif
|
|
2287
|
-
}
|
|
2288
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
2289
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2290
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2291
|
-
simsimd_bilinear_f16_sapphire(a, b, c, n, d);
|
|
2292
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2293
|
-
simsimd_bilinear_f16_haswell(a, b, c, n, d);
|
|
2294
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2295
|
-
simsimd_bilinear_f16_neon(a, b, c, n, d);
|
|
2296
|
-
#else
|
|
2297
|
-
simsimd_bilinear_f16_serial(a, b, c, n, d);
|
|
2298
|
-
#endif
|
|
2299
|
-
}
|
|
2300
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_bf16_t const *c,
|
|
2301
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2302
|
-
#if SIMSIMD_TARGET_GENOA
|
|
2303
|
-
simsimd_bilinear_bf16_genoa(a, b, c, n, d);
|
|
2304
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2305
|
-
simsimd_bilinear_bf16_haswell(a, b, c, n, d);
|
|
2306
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2307
|
-
simsimd_bilinear_bf16_neon(a, b, c, n, d);
|
|
2308
|
-
#else
|
|
2309
|
-
simsimd_bilinear_bf16_serial(a, b, c, n, d);
|
|
2310
|
-
#endif
|
|
2311
|
-
}
|
|
2312
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f64c(simsimd_f64c_t const *a, simsimd_f64c_t const *b, simsimd_f64c_t const *c,
|
|
2313
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2314
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2315
|
-
simsimd_bilinear_f64c_skylake(a, b, c, n, d);
|
|
2316
|
-
#else
|
|
2317
|
-
simsimd_bilinear_f64c_serial(a, b, c, n, d);
|
|
2318
|
-
#endif
|
|
2319
|
-
}
|
|
2320
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f32c(simsimd_f32c_t const *a, simsimd_f32c_t const *b, simsimd_f32c_t const *c,
|
|
2321
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2322
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2323
|
-
simsimd_bilinear_f32c_skylake(a, b, c, n, d);
|
|
2324
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2325
|
-
simsimd_bilinear_f32c_neon(a, b, c, n, d);
|
|
2326
|
-
#else
|
|
2327
|
-
simsimd_bilinear_f32c_serial(a, b, c, n, d);
|
|
2328
|
-
#endif
|
|
2329
|
-
}
|
|
2330
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_f16c(simsimd_f16c_t const *a, simsimd_f16c_t const *b, simsimd_f16c_t const *c,
|
|
2331
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2332
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2333
|
-
simsimd_bilinear_f16c_sapphire(a, b, c, n, d);
|
|
2334
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2335
|
-
simsimd_bilinear_f16c_neon(a, b, c, n, d);
|
|
2336
|
-
#else
|
|
2337
|
-
simsimd_bilinear_f16c_serial(a, b, c, n, d);
|
|
2338
|
-
#endif
|
|
2339
|
-
}
|
|
2340
|
-
SIMSIMD_PUBLIC void simsimd_bilinear_bf16c(simsimd_bf16c_t const *a, simsimd_bf16c_t const *b, simsimd_bf16c_t const *c,
|
|
2341
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2342
|
-
#if SIMSIMD_TARGET_GENOA
|
|
2343
|
-
simsimd_bilinear_bf16c_genoa(a, b, c, n, d);
|
|
2344
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2345
|
-
simsimd_bilinear_bf16c_neon(a, b, c, n, d);
|
|
2346
|
-
#else
|
|
2347
|
-
simsimd_bilinear_bf16c_serial(a, b, c, n, d);
|
|
2348
|
-
#endif
|
|
2349
|
-
}
|
|
2350
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_f64_t const *c,
|
|
2351
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2352
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2353
|
-
simsimd_mahalanobis_f64_skylake(a, b, c, n, d);
|
|
2354
|
-
#else
|
|
2355
|
-
simsimd_mahalanobis_f64_serial(a, b, c, n, d);
|
|
2356
|
-
#endif
|
|
2357
|
-
}
|
|
2358
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
2359
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2360
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2361
|
-
simsimd_mahalanobis_f32_skylake(a, b, c, n, d);
|
|
2362
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2363
|
-
simsimd_mahalanobis_f32_neon(a, b, c, n, d);
|
|
2364
|
-
#else
|
|
2365
|
-
simsimd_mahalanobis_f32_serial(a, b, c, n, d);
|
|
2366
|
-
#endif
|
|
2367
|
-
}
|
|
2368
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
2369
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2370
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2371
|
-
simsimd_mahalanobis_f16_sapphire(a, b, c, n, d);
|
|
2372
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2373
|
-
simsimd_mahalanobis_f16_haswell(a, b, c, n, d);
|
|
2374
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2375
|
-
simsimd_mahalanobis_f16_neon(a, b, c, n, d);
|
|
2376
|
-
#else
|
|
2377
|
-
simsimd_mahalanobis_f16_serial(a, b, c, n, d);
|
|
2378
|
-
#endif
|
|
2379
|
-
}
|
|
2380
|
-
SIMSIMD_PUBLIC void simsimd_mahalanobis_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_bf16_t const *c,
|
|
2381
|
-
simsimd_size_t n, simsimd_distance_t *d) {
|
|
2382
|
-
#if SIMSIMD_TARGET_GENOA
|
|
2383
|
-
simsimd_mahalanobis_bf16_genoa(a, b, c, n, d);
|
|
2384
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2385
|
-
simsimd_mahalanobis_bf16_haswell(a, b, c, n, d);
|
|
2386
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2387
|
-
simsimd_mahalanobis_bf16_neon(a, b, c, n, d);
|
|
2388
|
-
#else
|
|
2389
|
-
simsimd_mahalanobis_bf16_serial(a, b, c, n, d);
|
|
2390
|
-
#endif
|
|
2391
|
-
}
|
|
2392
|
-
|
|
2393
|
-
/* Elementwise operations
|
|
2394
|
-
*
|
|
2395
|
-
* @param a The first vector of integral or floating point values.
|
|
2396
|
-
* @param b The second vector of integral or floating point values.
|
|
2397
|
-
* @param c The third vector of integral or floating point values.
|
|
2398
|
-
* @param n The number of dimensions in the vectors.
|
|
2399
|
-
* @param alpha The first scaling factor.
|
|
2400
|
-
* @param beta The first scaling factor.
|
|
2401
|
-
* @param r The output vector or integral or floating point values.
|
|
2402
|
-
*/
|
|
2403
|
-
SIMSIMD_PUBLIC void simsimd_wsum_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_size_t n,
|
|
2404
|
-
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_f64_t *r) {
|
|
2405
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2406
|
-
simsimd_wsum_f64_skylake(a, b, n, alpha, beta, r);
|
|
2407
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2408
|
-
simsimd_wsum_f64_haswell(a, b, n, alpha, beta, r);
|
|
2409
|
-
#else
|
|
2410
|
-
simsimd_wsum_f64_serial(a, b, n, alpha, beta, r);
|
|
2411
|
-
#endif
|
|
2412
|
-
}
|
|
2413
|
-
|
|
2414
|
-
SIMSIMD_PUBLIC void simsimd_wsum_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_size_t n,
|
|
2415
|
-
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_f32_t *r) {
|
|
2416
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2417
|
-
simsimd_wsum_f32_skylake(a, b, n, alpha, beta, r);
|
|
2418
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2419
|
-
simsimd_wsum_f32_haswell(a, b, n, alpha, beta, r);
|
|
2420
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2421
|
-
simsimd_wsum_f32_neon(a, b, n, alpha, beta, r);
|
|
2422
|
-
#else
|
|
2423
|
-
simsimd_wsum_f32_serial(a, b, n, alpha, beta, r);
|
|
2424
|
-
#endif
|
|
2425
|
-
}
|
|
2426
|
-
|
|
2427
|
-
SIMSIMD_PUBLIC void simsimd_wsum_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_size_t n,
|
|
2428
|
-
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_bf16_t *r) {
|
|
2429
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2430
|
-
simsimd_wsum_bf16_skylake(a, b, n, alpha, beta, r);
|
|
2431
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2432
|
-
simsimd_wsum_bf16_haswell(a, b, n, alpha, beta, r);
|
|
2433
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2434
|
-
simsimd_wsum_bf16_neon(a, b, n, alpha, beta, r);
|
|
2435
|
-
#else
|
|
2436
|
-
simsimd_wsum_bf16_serial(a, b, n, alpha, beta, r);
|
|
2437
|
-
#endif
|
|
2438
|
-
}
|
|
2439
|
-
|
|
2440
|
-
SIMSIMD_PUBLIC void simsimd_wsum_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_size_t n,
|
|
2441
|
-
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_f16_t *r) {
|
|
2442
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2443
|
-
simsimd_wsum_f16_sapphire(a, b, n, alpha, beta, r);
|
|
2444
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2445
|
-
simsimd_wsum_f16_haswell(a, b, n, alpha, beta, r);
|
|
2446
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2447
|
-
simsimd_wsum_f16_neon(a, b, n, alpha, beta, r);
|
|
2448
|
-
#else
|
|
2449
|
-
simsimd_wsum_f16_serial(a, b, n, alpha, beta, r);
|
|
2450
|
-
#endif
|
|
2451
|
-
}
|
|
2452
|
-
|
|
2453
|
-
SIMSIMD_PUBLIC void simsimd_wsum_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_size_t n,
|
|
2454
|
-
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_i8_t *r) {
|
|
2455
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2456
|
-
simsimd_wsum_i8_sapphire(a, b, n, alpha, beta, r);
|
|
2457
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2458
|
-
simsimd_wsum_i8_haswell(a, b, n, alpha, beta, r);
|
|
2459
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2460
|
-
simsimd_wsum_i8_neon(a, b, n, alpha, beta, r);
|
|
2461
|
-
#else
|
|
2462
|
-
simsimd_wsum_i8_serial(a, b, n, alpha, beta, r);
|
|
2463
|
-
#endif
|
|
2464
|
-
}
|
|
2465
|
-
|
|
2466
|
-
SIMSIMD_PUBLIC void simsimd_wsum_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_size_t n,
|
|
2467
|
-
simsimd_distance_t alpha, simsimd_distance_t beta, simsimd_u8_t *r) {
|
|
2468
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2469
|
-
simsimd_wsum_u8_sapphire(a, b, n, alpha, beta, r);
|
|
2470
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2471
|
-
simsimd_wsum_u8_haswell(a, b, n, alpha, beta, r);
|
|
2472
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2473
|
-
simsimd_wsum_u8_neon(a, b, n, alpha, beta, r);
|
|
2474
|
-
#else
|
|
2475
|
-
simsimd_wsum_u8_serial(a, b, n, alpha, beta, r);
|
|
2476
|
-
#endif
|
|
2477
|
-
}
|
|
2478
|
-
|
|
2479
|
-
SIMSIMD_PUBLIC void simsimd_fma_f64(simsimd_f64_t const *a, simsimd_f64_t const *b, simsimd_f64_t const *c,
|
|
2480
|
-
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2481
|
-
simsimd_f64_t *r) {
|
|
2482
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2483
|
-
simsimd_fma_f64_skylake(a, b, c, n, alpha, beta, r);
|
|
2484
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2485
|
-
simsimd_fma_f64_haswell(a, b, c, n, alpha, beta, r);
|
|
2486
|
-
#else
|
|
2487
|
-
simsimd_fma_f64_serial(a, b, c, n, alpha, beta, r);
|
|
2488
|
-
#endif
|
|
2489
|
-
}
|
|
2490
|
-
|
|
2491
|
-
SIMSIMD_PUBLIC void simsimd_fma_f32(simsimd_f32_t const *a, simsimd_f32_t const *b, simsimd_f32_t const *c,
|
|
2492
|
-
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2493
|
-
simsimd_f32_t *r) {
|
|
2494
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2495
|
-
simsimd_fma_f32_skylake(a, b, c, n, alpha, beta, r);
|
|
2496
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2497
|
-
simsimd_fma_f32_haswell(a, b, c, n, alpha, beta, r);
|
|
2498
|
-
#elif SIMSIMD_TARGET_NEON
|
|
2499
|
-
simsimd_fma_f32_neon(a, b, c, n, alpha, beta, r);
|
|
2500
|
-
#else
|
|
2501
|
-
simsimd_fma_f32_serial(a, b, c, n, alpha, beta, r);
|
|
2502
|
-
#endif
|
|
2503
|
-
}
|
|
2504
|
-
|
|
2505
|
-
SIMSIMD_PUBLIC void simsimd_fma_bf16(simsimd_bf16_t const *a, simsimd_bf16_t const *b, simsimd_bf16_t const *c,
|
|
2506
|
-
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2507
|
-
simsimd_bf16_t *r) {
|
|
2508
|
-
#if SIMSIMD_TARGET_SKYLAKE
|
|
2509
|
-
simsimd_fma_bf16_skylake(a, b, c, n, alpha, beta, r);
|
|
2510
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2511
|
-
simsimd_fma_bf16_haswell(a, b, c, n, alpha, beta, r);
|
|
2512
|
-
#elif SIMSIMD_TARGET_NEON_BF16
|
|
2513
|
-
simsimd_fma_bf16_neon(a, b, c, n, alpha, beta, r);
|
|
2514
|
-
#else
|
|
2515
|
-
simsimd_fma_bf16_serial(a, b, c, n, alpha, beta, r);
|
|
2516
|
-
#endif
|
|
2517
|
-
}
|
|
2518
|
-
|
|
2519
|
-
SIMSIMD_PUBLIC void simsimd_fma_f16(simsimd_f16_t const *a, simsimd_f16_t const *b, simsimd_f16_t const *c,
|
|
2520
|
-
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2521
|
-
simsimd_f16_t *r) {
|
|
2522
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2523
|
-
simsimd_fma_f16_sapphire(a, b, c, n, alpha, beta, r);
|
|
2524
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2525
|
-
simsimd_fma_f16_haswell(a, b, c, n, alpha, beta, r);
|
|
2526
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2527
|
-
simsimd_fma_f16_neon(a, b, c, n, alpha, beta, r);
|
|
2528
|
-
#else
|
|
2529
|
-
simsimd_fma_f16_serial(a, b, c, n, alpha, beta, r);
|
|
2530
|
-
#endif
|
|
2531
|
-
}
|
|
2532
|
-
|
|
2533
|
-
SIMSIMD_PUBLIC void simsimd_fma_i8(simsimd_i8_t const *a, simsimd_i8_t const *b, simsimd_i8_t const *c,
|
|
2534
|
-
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2535
|
-
simsimd_i8_t *r) {
|
|
2536
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2537
|
-
simsimd_fma_i8_sapphire(a, b, c, n, alpha, beta, r);
|
|
2538
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2539
|
-
simsimd_fma_i8_haswell(a, b, c, n, alpha, beta, r);
|
|
2540
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2541
|
-
simsimd_fma_i8_neon(a, b, c, n, alpha, beta, r);
|
|
2542
|
-
#else
|
|
2543
|
-
simsimd_fma_i8_serial(a, b, c, n, alpha, beta, r);
|
|
2544
|
-
#endif
|
|
2545
|
-
}
|
|
2546
|
-
|
|
2547
|
-
SIMSIMD_PUBLIC void simsimd_fma_u8(simsimd_u8_t const *a, simsimd_u8_t const *b, simsimd_u8_t const *c,
|
|
2548
|
-
simsimd_size_t n, simsimd_distance_t alpha, simsimd_distance_t beta,
|
|
2549
|
-
simsimd_u8_t *r) {
|
|
2550
|
-
#if SIMSIMD_TARGET_SAPPHIRE
|
|
2551
|
-
simsimd_fma_u8_sapphire(a, b, c, n, alpha, beta, r);
|
|
2552
|
-
#elif SIMSIMD_TARGET_HASWELL
|
|
2553
|
-
simsimd_fma_u8_haswell(a, b, c, n, alpha, beta, r);
|
|
2554
|
-
#elif SIMSIMD_TARGET_NEON_F16
|
|
2555
|
-
simsimd_fma_u8_neon(a, b, c, n, alpha, beta, r);
|
|
2556
|
-
#else
|
|
2557
|
-
simsimd_fma_u8_serial(a, b, c, n, alpha, beta, r);
|
|
2558
|
-
#endif
|
|
2559
|
-
}
|
|
2560
|
-
|
|
2561
|
-
#endif
|
|
2562
|
-
|
|
2563
|
-
#ifdef __cplusplus
|
|
2564
|
-
}
|
|
2565
|
-
#endif
|
|
2566
|
-
|
|
2567
|
-
#endif // SIMSIMD_H
|