usearch 2.21.4 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/binding.gyp +15 -37
- package/c/CMakeLists.txt +4 -5
- package/c/README.md +7 -7
- package/c/lib.cpp +32 -14
- package/c/test.c +83 -1
- package/c/usearch.h +24 -3
- package/cpp/CMakeLists.txt +4 -0
- package/cpp/README.md +5 -5
- package/cpp/bench.cpp +97 -116
- package/cpp/test.cpp +117 -20
- package/include/usearch/index.hpp +224 -48
- package/include/usearch/index_dense.hpp +105 -40
- package/include/usearch/index_plugins.hpp +1387 -204
- package/javascript/dist/cjs/usearch.d.ts +8 -3
- package/javascript/dist/cjs/usearch.js +12 -4
- package/javascript/dist/esm/usearch.d.ts +8 -3
- package/javascript/dist/esm/usearch.js +12 -4
- package/javascript/lib.cpp +17 -0
- package/javascript/usearch.ts +14 -6
- package/numkong/.clang-tidy +30 -0
- package/{simsimd → numkong}/.cmake-format.py +18 -0
- package/numkong/.editorconfig +12 -0
- package/numkong/.git-blame-ignore-revs +123 -0
- package/numkong/.mailmap +15 -0
- package/numkong/.spi.yml +11 -0
- package/numkong/.swift-format +14 -0
- package/numkong/CITATION.cff +81 -0
- package/numkong/CONTRIBUTING.md +500 -0
- package/numkong/Cargo.toml +54 -0
- package/numkong/MANIFEST.in +8 -0
- package/numkong/Package.swift +84 -0
- package/numkong/README.md +569 -0
- package/numkong/bench/README.md +217 -0
- package/numkong/bench/bench-browser.html +323 -0
- package/numkong/bench/bench.cpp +344 -0
- package/numkong/bench/bench.hpp +816 -0
- package/numkong/bench/bench.js +148 -0
- package/numkong/bench/bench.mjs +616 -0
- package/numkong/bench/bench_attention.cpp +113 -0
- package/numkong/bench/bench_cast.cpp +264 -0
- package/numkong/bench/bench_cross_amx.cpp +62 -0
- package/numkong/bench/bench_cross_arm.cpp +245 -0
- package/numkong/bench/bench_cross_blas.cpp +309 -0
- package/numkong/bench/bench_cross_loongarch.cpp +106 -0
- package/numkong/bench/bench_cross_power.cpp +84 -0
- package/numkong/bench/bench_cross_rvv.cpp +121 -0
- package/numkong/bench/bench_cross_serial.cpp +151 -0
- package/numkong/bench/bench_cross_sme.cpp +163 -0
- package/numkong/bench/bench_cross_wasm.cpp +142 -0
- package/numkong/bench/bench_cross_x86.cpp +455 -0
- package/numkong/bench/bench_curved.cpp +210 -0
- package/numkong/bench/bench_dot.cpp +315 -0
- package/numkong/bench/bench_each.cpp +503 -0
- package/numkong/bench/bench_geospatial.cpp +112 -0
- package/numkong/bench/bench_maxsim.cpp +154 -0
- package/numkong/bench/bench_mesh.cpp +148 -0
- package/numkong/bench/bench_probability.cpp +60 -0
- package/numkong/bench/bench_reduce.cpp +371 -0
- package/numkong/bench/bench_set.cpp +73 -0
- package/numkong/bench/bench_sparse.cpp +198 -0
- package/numkong/bench/bench_spatial.cpp +347 -0
- package/numkong/bench/bench_trigonometry.cpp +137 -0
- package/numkong/bench/swift/Bench.swift +506 -0
- package/numkong/binding.gyp +169 -0
- package/numkong/build.rs +484 -0
- package/numkong/c/dispatch.h +512 -0
- package/numkong/c/dispatch_bf16.c +447 -0
- package/numkong/c/dispatch_bf16c.c +52 -0
- package/numkong/c/dispatch_e2m3.c +296 -0
- package/numkong/c/dispatch_e3m2.c +284 -0
- package/numkong/c/dispatch_e4m3.c +318 -0
- package/numkong/c/dispatch_e5m2.c +316 -0
- package/numkong/c/dispatch_f16.c +452 -0
- package/numkong/c/dispatch_f16c.c +58 -0
- package/numkong/c/dispatch_f32.c +434 -0
- package/numkong/c/dispatch_f32c.c +99 -0
- package/numkong/c/dispatch_f64.c +348 -0
- package/numkong/c/dispatch_f64c.c +98 -0
- package/numkong/c/dispatch_i16.c +96 -0
- package/numkong/c/dispatch_i32.c +89 -0
- package/numkong/c/dispatch_i4.c +153 -0
- package/numkong/c/dispatch_i64.c +86 -0
- package/numkong/c/dispatch_i8.c +348 -0
- package/numkong/c/dispatch_other.c +348 -0
- package/numkong/c/dispatch_u1.c +193 -0
- package/numkong/c/dispatch_u16.c +124 -0
- package/numkong/c/dispatch_u32.c +118 -0
- package/numkong/c/dispatch_u4.c +153 -0
- package/numkong/c/dispatch_u64.c +102 -0
- package/numkong/c/dispatch_u8.c +364 -0
- package/numkong/c/numkong.c +940 -0
- package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
- package/numkong/cmake/nk_isa_probe.cmake +90 -0
- package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
- package/numkong/cmake/nk_math_lib.cmake +46 -0
- package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
- package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
- package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
- package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
- package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
- package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
- package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
- package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
- package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
- package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
- package/numkong/cmake/toolchain-wasi.cmake +77 -0
- package/numkong/cmake/toolchain-wasm.cmake +70 -0
- package/numkong/cmake/toolchain-wasm64.cmake +62 -0
- package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
- package/numkong/include/README.md +643 -0
- package/numkong/include/module.modulemap +129 -0
- package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
- package/numkong/include/numkong/attention/sme.h +2075 -0
- package/numkong/include/numkong/attention.h +49 -0
- package/numkong/include/numkong/capabilities.h +930 -0
- package/numkong/include/numkong/cast/README.md +262 -0
- package/numkong/include/numkong/cast/diamond.h +64 -0
- package/numkong/include/numkong/cast/haswell.h +823 -0
- package/numkong/include/numkong/cast/icelake.h +475 -0
- package/numkong/include/numkong/cast/loongsonasx.h +252 -0
- package/numkong/include/numkong/cast/neon.h +1174 -0
- package/numkong/include/numkong/cast/powervsx.h +449 -0
- package/numkong/include/numkong/cast/rvv.h +970 -0
- package/numkong/include/numkong/cast/sapphire.h +262 -0
- package/numkong/include/numkong/cast/serial.h +2336 -0
- package/numkong/include/numkong/cast/skylake.h +915 -0
- package/numkong/include/numkong/cast/v128relaxed.h +537 -0
- package/numkong/include/numkong/cast.h +254 -0
- package/numkong/include/numkong/cast.hpp +44 -0
- package/numkong/include/numkong/curved/README.md +223 -0
- package/numkong/include/numkong/curved/genoa.h +182 -0
- package/numkong/include/numkong/curved/haswell.h +276 -0
- package/numkong/include/numkong/curved/neon.h +329 -0
- package/numkong/include/numkong/curved/neonbfdot.h +211 -0
- package/numkong/include/numkong/curved/rvv.h +305 -0
- package/numkong/include/numkong/curved/serial.h +207 -0
- package/numkong/include/numkong/curved/skylake.h +457 -0
- package/numkong/include/numkong/curved/smef64.h +530 -0
- package/numkong/include/numkong/curved.h +513 -0
- package/numkong/include/numkong/curved.hpp +144 -0
- package/numkong/include/numkong/dot/README.md +442 -0
- package/numkong/include/numkong/dot/alder.h +563 -0
- package/numkong/include/numkong/dot/diamond.h +158 -0
- package/numkong/include/numkong/dot/genoa.h +289 -0
- package/numkong/include/numkong/dot/haswell.h +1723 -0
- package/numkong/include/numkong/dot/icelake.h +997 -0
- package/numkong/include/numkong/dot/loongsonasx.h +671 -0
- package/numkong/include/numkong/dot/neon.h +869 -0
- package/numkong/include/numkong/dot/neonbfdot.h +243 -0
- package/numkong/include/numkong/dot/neonfhm.h +358 -0
- package/numkong/include/numkong/dot/neonfp8.h +323 -0
- package/numkong/include/numkong/dot/neonsdot.h +622 -0
- package/numkong/include/numkong/dot/powervsx.h +752 -0
- package/numkong/include/numkong/dot/rvv.h +722 -0
- package/numkong/include/numkong/dot/rvvbb.h +72 -0
- package/numkong/include/numkong/dot/rvvbf16.h +123 -0
- package/numkong/include/numkong/dot/rvvhalf.h +129 -0
- package/numkong/include/numkong/dot/sapphire.h +141 -0
- package/numkong/include/numkong/dot/serial.h +874 -0
- package/numkong/include/numkong/dot/sierra.h +405 -0
- package/numkong/include/numkong/dot/skylake.h +1116 -0
- package/numkong/include/numkong/dot/sve.h +420 -0
- package/numkong/include/numkong/dot/svebfdot.h +75 -0
- package/numkong/include/numkong/dot/svehalf.h +168 -0
- package/numkong/include/numkong/dot/svesdot.h +90 -0
- package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
- package/numkong/include/numkong/dot.h +1136 -0
- package/numkong/include/numkong/dot.hpp +94 -0
- package/numkong/include/numkong/dots/README.md +496 -0
- package/numkong/include/numkong/dots/alder.h +117 -0
- package/numkong/include/numkong/dots/diamond.h +86 -0
- package/numkong/include/numkong/dots/genoa.h +100 -0
- package/numkong/include/numkong/dots/graniteamx.h +733 -0
- package/numkong/include/numkong/dots/haswell.h +310 -0
- package/numkong/include/numkong/dots/icelake.h +180 -0
- package/numkong/include/numkong/dots/loongsonasx.h +176 -0
- package/numkong/include/numkong/dots/neon.h +123 -0
- package/numkong/include/numkong/dots/neonbfdot.h +59 -0
- package/numkong/include/numkong/dots/neonfhm.h +96 -0
- package/numkong/include/numkong/dots/neonfp8.h +99 -0
- package/numkong/include/numkong/dots/neonsdot.h +144 -0
- package/numkong/include/numkong/dots/powervsx.h +194 -0
- package/numkong/include/numkong/dots/rvv.h +2593 -0
- package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
- package/numkong/include/numkong/dots/serial.h +2867 -0
- package/numkong/include/numkong/dots/sierra.h +100 -0
- package/numkong/include/numkong/dots/skylake.h +207 -0
- package/numkong/include/numkong/dots/sme.h +5041 -0
- package/numkong/include/numkong/dots/smebi32.h +477 -0
- package/numkong/include/numkong/dots/smef64.h +1328 -0
- package/numkong/include/numkong/dots/smehalf.h +47 -0
- package/numkong/include/numkong/dots/v128relaxed.h +317 -0
- package/numkong/include/numkong/dots.h +3110 -0
- package/numkong/include/numkong/dots.hpp +641 -0
- package/numkong/include/numkong/each/README.md +465 -0
- package/numkong/include/numkong/each/haswell.h +1658 -0
- package/numkong/include/numkong/each/icelake.h +272 -0
- package/numkong/include/numkong/each/neon.h +1138 -0
- package/numkong/include/numkong/each/neonbfdot.h +211 -0
- package/numkong/include/numkong/each/neonhalf.h +318 -0
- package/numkong/include/numkong/each/rvv.h +1121 -0
- package/numkong/include/numkong/each/sapphire.h +343 -0
- package/numkong/include/numkong/each/serial.h +282 -0
- package/numkong/include/numkong/each/skylake.h +1562 -0
- package/numkong/include/numkong/each/v128relaxed.h +562 -0
- package/numkong/include/numkong/each.h +2232 -0
- package/numkong/include/numkong/each.hpp +434 -0
- package/numkong/include/numkong/geospatial/README.md +147 -0
- package/numkong/include/numkong/geospatial/haswell.h +633 -0
- package/numkong/include/numkong/geospatial/neon.h +615 -0
- package/numkong/include/numkong/geospatial/rvv.h +701 -0
- package/numkong/include/numkong/geospatial/serial.h +309 -0
- package/numkong/include/numkong/geospatial/skylake.h +613 -0
- package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
- package/numkong/include/numkong/geospatial.h +453 -0
- package/numkong/include/numkong/geospatial.hpp +235 -0
- package/numkong/include/numkong/matrix.hpp +336 -0
- package/numkong/include/numkong/maxsim/README.md +187 -0
- package/numkong/include/numkong/maxsim/alder.h +511 -0
- package/numkong/include/numkong/maxsim/genoa.h +115 -0
- package/numkong/include/numkong/maxsim/haswell.h +553 -0
- package/numkong/include/numkong/maxsim/icelake.h +480 -0
- package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
- package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
- package/numkong/include/numkong/maxsim/serial.h +490 -0
- package/numkong/include/numkong/maxsim/sme.h +993 -0
- package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
- package/numkong/include/numkong/maxsim.h +571 -0
- package/numkong/include/numkong/maxsim.hpp +133 -0
- package/numkong/include/numkong/mesh/README.md +219 -0
- package/numkong/include/numkong/mesh/haswell.h +2013 -0
- package/numkong/include/numkong/mesh/neon.h +1821 -0
- package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
- package/numkong/include/numkong/mesh/rvv.h +936 -0
- package/numkong/include/numkong/mesh/serial.h +721 -0
- package/numkong/include/numkong/mesh/skylake.h +2344 -0
- package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
- package/numkong/include/numkong/mesh.h +666 -0
- package/numkong/include/numkong/mesh.hpp +701 -0
- package/numkong/include/numkong/numkong.h +78 -0
- package/numkong/include/numkong/numkong.hpp +58 -0
- package/numkong/include/numkong/probability/README.md +177 -0
- package/numkong/include/numkong/probability/haswell.h +267 -0
- package/numkong/include/numkong/probability/neon.h +255 -0
- package/numkong/include/numkong/probability/rvv.h +414 -0
- package/numkong/include/numkong/probability/serial.h +181 -0
- package/numkong/include/numkong/probability/skylake.h +324 -0
- package/numkong/include/numkong/probability.h +380 -0
- package/numkong/include/numkong/probability.hpp +120 -0
- package/numkong/include/numkong/random.h +50 -0
- package/numkong/include/numkong/random.hpp +285 -0
- package/numkong/include/numkong/reduce/README.md +552 -0
- package/numkong/include/numkong/reduce/alder.h +636 -0
- package/numkong/include/numkong/reduce/genoa.h +201 -0
- package/numkong/include/numkong/reduce/haswell.h +3785 -0
- package/numkong/include/numkong/reduce/icelake.h +549 -0
- package/numkong/include/numkong/reduce/neon.h +3980 -0
- package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
- package/numkong/include/numkong/reduce/neonfhm.h +293 -0
- package/numkong/include/numkong/reduce/neonsdot.h +357 -0
- package/numkong/include/numkong/reduce/rvv.h +3533 -0
- package/numkong/include/numkong/reduce/serial.h +753 -0
- package/numkong/include/numkong/reduce/sierra.h +338 -0
- package/numkong/include/numkong/reduce/skylake.h +3794 -0
- package/numkong/include/numkong/reduce/sve.h +52 -0
- package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
- package/numkong/include/numkong/reduce.h +1582 -0
- package/numkong/include/numkong/reduce.hpp +778 -0
- package/numkong/include/numkong/scalar/README.md +89 -0
- package/numkong/include/numkong/scalar/haswell.h +122 -0
- package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
- package/numkong/include/numkong/scalar/neon.h +122 -0
- package/numkong/include/numkong/scalar/neonhalf.h +70 -0
- package/numkong/include/numkong/scalar/powervsx.h +96 -0
- package/numkong/include/numkong/scalar/rvv.h +211 -0
- package/numkong/include/numkong/scalar/sapphire.h +74 -0
- package/numkong/include/numkong/scalar/serial.h +332 -0
- package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
- package/numkong/include/numkong/scalar.h +696 -0
- package/numkong/include/numkong/set/README.md +179 -0
- package/numkong/include/numkong/set/haswell.h +334 -0
- package/numkong/include/numkong/set/icelake.h +485 -0
- package/numkong/include/numkong/set/loongsonasx.h +181 -0
- package/numkong/include/numkong/set/neon.h +363 -0
- package/numkong/include/numkong/set/powervsx.h +326 -0
- package/numkong/include/numkong/set/rvv.h +226 -0
- package/numkong/include/numkong/set/rvvbb.h +117 -0
- package/numkong/include/numkong/set/serial.h +174 -0
- package/numkong/include/numkong/set/sve.h +187 -0
- package/numkong/include/numkong/set/v128relaxed.h +240 -0
- package/numkong/include/numkong/set.h +471 -0
- package/numkong/include/numkong/set.hpp +114 -0
- package/numkong/include/numkong/sets/README.md +149 -0
- package/numkong/include/numkong/sets/haswell.h +63 -0
- package/numkong/include/numkong/sets/icelake.h +66 -0
- package/numkong/include/numkong/sets/loongsonasx.h +52 -0
- package/numkong/include/numkong/sets/neon.h +61 -0
- package/numkong/include/numkong/sets/powervsx.h +65 -0
- package/numkong/include/numkong/sets/serial.h +43 -0
- package/numkong/include/numkong/sets/smebi32.h +1135 -0
- package/numkong/include/numkong/sets/v128relaxed.h +58 -0
- package/numkong/include/numkong/sets.h +382 -0
- package/numkong/include/numkong/sparse/README.md +156 -0
- package/numkong/include/numkong/sparse/icelake.h +463 -0
- package/numkong/include/numkong/sparse/neon.h +288 -0
- package/numkong/include/numkong/sparse/serial.h +117 -0
- package/numkong/include/numkong/sparse/sve2.h +504 -0
- package/numkong/include/numkong/sparse/turin.h +322 -0
- package/numkong/include/numkong/sparse.h +363 -0
- package/numkong/include/numkong/sparse.hpp +113 -0
- package/numkong/include/numkong/spatial/README.md +439 -0
- package/numkong/include/numkong/spatial/alder.h +604 -0
- package/numkong/include/numkong/spatial/diamond.h +240 -0
- package/numkong/include/numkong/spatial/genoa.h +222 -0
- package/numkong/include/numkong/spatial/haswell.h +979 -0
- package/numkong/include/numkong/spatial/icelake.h +1067 -0
- package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
- package/numkong/include/numkong/spatial/neon.h +846 -0
- package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
- package/numkong/include/numkong/spatial/neonfp8.h +258 -0
- package/numkong/include/numkong/spatial/neonsdot.h +429 -0
- package/numkong/include/numkong/spatial/powervsx.h +738 -0
- package/numkong/include/numkong/spatial/rvv.h +991 -0
- package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
- package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
- package/numkong/include/numkong/spatial/serial.h +347 -0
- package/numkong/include/numkong/spatial/sierra.h +516 -0
- package/numkong/include/numkong/spatial/skylake.h +605 -0
- package/numkong/include/numkong/spatial/sve.h +246 -0
- package/numkong/include/numkong/spatial/svebfdot.h +125 -0
- package/numkong/include/numkong/spatial/svehalf.h +136 -0
- package/numkong/include/numkong/spatial/svesdot.h +143 -0
- package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
- package/numkong/include/numkong/spatial.h +1681 -0
- package/numkong/include/numkong/spatial.hpp +183 -0
- package/numkong/include/numkong/spatials/README.md +580 -0
- package/numkong/include/numkong/spatials/alder.h +94 -0
- package/numkong/include/numkong/spatials/diamond.h +82 -0
- package/numkong/include/numkong/spatials/genoa.h +94 -0
- package/numkong/include/numkong/spatials/graniteamx.h +173 -0
- package/numkong/include/numkong/spatials/haswell.h +219 -0
- package/numkong/include/numkong/spatials/icelake.h +113 -0
- package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
- package/numkong/include/numkong/spatials/neon.h +109 -0
- package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
- package/numkong/include/numkong/spatials/neonfhm.h +92 -0
- package/numkong/include/numkong/spatials/neonfp8.h +111 -0
- package/numkong/include/numkong/spatials/neonsdot.h +143 -0
- package/numkong/include/numkong/spatials/powervsx.h +153 -0
- package/numkong/include/numkong/spatials/rvv.h +1976 -0
- package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
- package/numkong/include/numkong/spatials/serial.h +248 -0
- package/numkong/include/numkong/spatials/sierra.h +96 -0
- package/numkong/include/numkong/spatials/skylake.h +184 -0
- package/numkong/include/numkong/spatials/sme.h +1927 -0
- package/numkong/include/numkong/spatials/smef64.h +483 -0
- package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
- package/numkong/include/numkong/spatials.h +3374 -0
- package/numkong/include/numkong/spatials.hpp +509 -0
- package/numkong/include/numkong/tensor.hpp +1981 -0
- package/numkong/include/numkong/trigonometry/README.md +184 -0
- package/numkong/include/numkong/trigonometry/haswell.h +653 -0
- package/numkong/include/numkong/trigonometry/neon.h +638 -0
- package/numkong/include/numkong/trigonometry/rvv.h +700 -0
- package/numkong/include/numkong/trigonometry/serial.h +703 -0
- package/numkong/include/numkong/trigonometry/skylake.h +725 -0
- package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
- package/numkong/include/numkong/trigonometry.h +467 -0
- package/numkong/include/numkong/trigonometry.hpp +166 -0
- package/numkong/include/numkong/types.h +1695 -0
- package/numkong/include/numkong/types.hpp +6027 -0
- package/numkong/include/numkong/vector.hpp +766 -0
- package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
- package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
- package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
- package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
- package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
- package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
- package/numkong/javascript/README.md +254 -0
- package/numkong/javascript/node-gyp-build.d.ts +4 -0
- package/numkong/javascript/numkong-browser.ts +40 -0
- package/numkong/javascript/numkong-wasm.ts +750 -0
- package/numkong/javascript/numkong.c +712 -0
- package/numkong/javascript/numkong.ts +613 -0
- package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
- package/numkong/javascript/tsconfig-cjs.json +13 -0
- package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
- package/numkong/javascript/types.ts +784 -0
- package/numkong/numkong.gypi +104 -0
- package/numkong/package.json +108 -0
- package/numkong/probes/arm_neon.c +8 -0
- package/numkong/probes/arm_neon_bfdot.c +9 -0
- package/numkong/probes/arm_neon_fhm.c +9 -0
- package/numkong/probes/arm_neon_half.c +8 -0
- package/numkong/probes/arm_neon_sdot.c +9 -0
- package/numkong/probes/arm_neonfp8.c +9 -0
- package/numkong/probes/arm_sme.c +16 -0
- package/numkong/probes/arm_sme2.c +16 -0
- package/numkong/probes/arm_sme2p1.c +16 -0
- package/numkong/probes/arm_sme_bf16.c +16 -0
- package/numkong/probes/arm_sme_bi32.c +16 -0
- package/numkong/probes/arm_sme_f64.c +16 -0
- package/numkong/probes/arm_sme_fa64.c +14 -0
- package/numkong/probes/arm_sme_half.c +16 -0
- package/numkong/probes/arm_sme_lut2.c +15 -0
- package/numkong/probes/arm_sve.c +18 -0
- package/numkong/probes/arm_sve2.c +20 -0
- package/numkong/probes/arm_sve2p1.c +18 -0
- package/numkong/probes/arm_sve_bfdot.c +20 -0
- package/numkong/probes/arm_sve_half.c +18 -0
- package/numkong/probes/arm_sve_sdot.c +21 -0
- package/numkong/probes/loongarch_lasx.c +12 -0
- package/numkong/probes/power_vsx.c +12 -0
- package/numkong/probes/probe.js +127 -0
- package/numkong/probes/riscv_rvv.c +14 -0
- package/numkong/probes/riscv_rvv_bb.c +15 -0
- package/numkong/probes/riscv_rvv_bf16.c +17 -0
- package/numkong/probes/riscv_rvv_half.c +14 -0
- package/numkong/probes/wasm_v128relaxed.c +11 -0
- package/numkong/probes/x86_alder.c +17 -0
- package/numkong/probes/x86_diamond.c +17 -0
- package/numkong/probes/x86_genoa.c +17 -0
- package/numkong/probes/x86_graniteamx.c +19 -0
- package/numkong/probes/x86_haswell.c +11 -0
- package/numkong/probes/x86_icelake.c +17 -0
- package/numkong/probes/x86_sapphire.c +16 -0
- package/numkong/probes/x86_sapphireamx.c +18 -0
- package/numkong/probes/x86_sierra.c +17 -0
- package/numkong/probes/x86_skylake.c +15 -0
- package/numkong/probes/x86_turin.c +17 -0
- package/numkong/rust/README.md +698 -0
- package/numkong/rust/capabilities.rs +96 -0
- package/numkong/rust/cast.rs +314 -0
- package/numkong/rust/curved.rs +391 -0
- package/numkong/rust/each.rs +2721 -0
- package/numkong/rust/geospatial.rs +343 -0
- package/numkong/rust/matrix.rs +5424 -0
- package/numkong/rust/maxsim.rs +540 -0
- package/numkong/rust/mesh.rs +837 -0
- package/numkong/rust/numkong.rs +409 -0
- package/numkong/rust/probability.rs +272 -0
- package/numkong/rust/reduce.rs +1249 -0
- package/numkong/rust/set.rs +194 -0
- package/numkong/rust/sparse.rs +513 -0
- package/numkong/rust/spatial.rs +1815 -0
- package/numkong/rust/tensor.rs +7565 -0
- package/numkong/rust/types.rs +3666 -0
- package/numkong/rust/vector.rs +1899 -0
- package/numkong/rustfmt.toml +2 -0
- package/numkong/swift/Matrix.swift +1388 -0
- package/numkong/swift/MaxSim.swift +151 -0
- package/numkong/swift/NumKong.swift +283 -0
- package/numkong/swift/Numerics.swift +329 -0
- package/numkong/swift/README.md +433 -0
- package/numkong/swift/Scalar.swift +741 -0
- package/numkong/swift/Tensor.swift +209 -0
- package/numkong/test/README.md +315 -0
- package/numkong/test/playwright.config.ts +16 -0
- package/numkong/test/swift/Test.swift +534 -0
- package/numkong/test/test-browser-bundle-runner.mjs +36 -0
- package/numkong/test/test-browser-bundle.html +188 -0
- package/numkong/test/test-browser-runner.mjs +43 -0
- package/numkong/test/test-browser.html +305 -0
- package/numkong/test/test-dtypes.mjs +453 -0
- package/numkong/test/test-wasm.mjs +267 -0
- package/numkong/test/test.cpp +442 -0
- package/numkong/test/test.hpp +580 -0
- package/numkong/test/test.mjs +363 -0
- package/numkong/test/test_base.py +1041 -0
- package/numkong/test/test_cast.cpp +242 -0
- package/numkong/test/test_cross.hpp +551 -0
- package/numkong/test/test_cross.py +467 -0
- package/numkong/test/test_cross_amx.cpp +50 -0
- package/numkong/test/test_cross_arm.cpp +225 -0
- package/numkong/test/test_cross_blas.cpp +354 -0
- package/numkong/test/test_cross_loongarch.cpp +90 -0
- package/numkong/test/test_cross_power.cpp +73 -0
- package/numkong/test/test_cross_rvv.cpp +109 -0
- package/numkong/test/test_cross_serial.cpp +181 -0
- package/numkong/test/test_cross_sme.cpp +148 -0
- package/numkong/test/test_cross_wasm.cpp +141 -0
- package/numkong/test/test_cross_x86.cpp +442 -0
- package/numkong/test/test_curved.cpp +182 -0
- package/numkong/test/test_curved.py +207 -0
- package/numkong/test/test_dot.cpp +353 -0
- package/numkong/test/test_dot.py +296 -0
- package/numkong/test/test_each.cpp +437 -0
- package/numkong/test/test_each.py +756 -0
- package/numkong/test/test_geospatial.cpp +155 -0
- package/numkong/test/test_geospatial.py +241 -0
- package/numkong/test/test_maxsim.cpp +138 -0
- package/numkong/test/test_maxsim.py +209 -0
- package/numkong/test/test_mesh.cpp +203 -0
- package/numkong/test/test_mesh.py +394 -0
- package/numkong/test/test_probability.cpp +136 -0
- package/numkong/test/test_probability.py +166 -0
- package/numkong/test/test_reduce.cpp +563 -0
- package/numkong/test/test_reduce.py +781 -0
- package/numkong/test/test_set.cpp +151 -0
- package/numkong/test/test_set.py +120 -0
- package/numkong/test/test_similarities.py +579 -0
- package/numkong/test/test_sparse.cpp +121 -0
- package/numkong/test/test_sparse.py +118 -0
- package/numkong/test/test_spatial.cpp +518 -0
- package/numkong/test/test_spatial.py +269 -0
- package/numkong/test/test_tensor.cpp +884 -0
- package/numkong/test/test_tensor.py +1417 -0
- package/numkong/test/test_trigonometry.cpp +156 -0
- package/numkong/test/test_trigonometry.py +180 -0
- package/package.json +7 -8
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/fp16/CMakeLists.txt +0 -176
- package/fp16/LICENSE +0 -11
- package/fp16/README.md +0 -20
- package/fp16/bench/alt-element.cc +0 -89
- package/fp16/bench/from-alt-array.cc +0 -175
- package/fp16/bench/from-ieee-array.cc +0 -399
- package/fp16/bench/ieee-element.cc +0 -272
- package/fp16/bench/to-alt-array.cc +0 -91
- package/fp16/bench/to-ieee-array.cc +0 -303
- package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
- package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
- package/fp16/cmake/DownloadPSimd.cmake +0 -15
- package/fp16/configure.py +0 -65
- package/fp16/confu.yaml +0 -8
- package/fp16/include/fp16/__init__.py +0 -0
- package/fp16/include/fp16/avx.py +0 -50
- package/fp16/include/fp16/avx2.py +0 -53
- package/fp16/include/fp16/bitcasts.h +0 -92
- package/fp16/include/fp16/fp16.h +0 -451
- package/fp16/include/fp16/psimd.h +0 -131
- package/fp16/include/fp16.h +0 -11
- package/fp16/jni/Android.mk +0 -6
- package/fp16/jni/Application.mk +0 -4
- package/fp16/test/alt-from-fp32-value.cc +0 -498
- package/fp16/test/alt-to-fp32-bits.cc +0 -263
- package/fp16/test/alt-to-fp32-psimd.cc +0 -145
- package/fp16/test/alt-to-fp32-value.cc +0 -348
- package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
- package/fp16/test/bitcasts.cc +0 -56
- package/fp16/test/ieee-from-fp32-value.cc +0 -523
- package/fp16/test/ieee-to-fp32-bits.cc +0 -333
- package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
- package/fp16/test/ieee-to-fp32-value.cc +0 -420
- package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
- package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
- package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
- package/fp16/test/peachpy/stubs.py +0 -38
- package/fp16/test/tables.cc +0 -530
- package/fp16/test/tables.h +0 -13
- package/fp16/third-party/THHalf.h +0 -92
- package/fp16/third-party/eigen-half.h +0 -170
- package/fp16/third-party/float16-compressor.h +0 -80
- package/fp16/third-party/half.hpp +0 -2916
- package/fp16/third-party/npy-halffloat.h +0 -328
- package/simsimd/.git-blame-ignore-revs +0 -2
- package/simsimd/CONTRIBUTING.md +0 -321
- package/simsimd/Cargo.toml +0 -49
- package/simsimd/MANIFEST.in +0 -4
- package/simsimd/Package.swift +0 -28
- package/simsimd/README.md +0 -1493
- package/simsimd/binding.gyp +0 -35
- package/simsimd/build.rs +0 -70
- package/simsimd/c/lib.c +0 -374
- package/simsimd/include/module.modulemap +0 -4
- package/simsimd/include/simsimd/binary.h +0 -486
- package/simsimd/include/simsimd/curved.h +0 -1541
- package/simsimd/include/simsimd/dot.h +0 -1853
- package/simsimd/include/simsimd/elementwise.h +0 -2465
- package/simsimd/include/simsimd/geospatial.h +0 -43
- package/simsimd/include/simsimd/mesh.h +0 -69
- package/simsimd/include/simsimd/probability.h +0 -606
- package/simsimd/include/simsimd/simsimd.h +0 -2567
- package/simsimd/include/simsimd/sparse.h +0 -1384
- package/simsimd/include/simsimd/spatial.h +0 -2335
- package/simsimd/include/simsimd/types.h +0 -666
- package/simsimd/javascript/fallback.ts +0 -233
- package/simsimd/javascript/lib.c +0 -125
- package/simsimd/javascript/node-gyp-build.d.ts +0 -1
- package/simsimd/javascript/simsimd.ts +0 -179
- package/simsimd/javascript/tsconfig-cjs.json +0 -8
- package/simsimd/package-lock.json +0 -1761
- package/simsimd/package.json +0 -61
- package/simsimd/rust/lib.rs +0 -1821
- package/simsimd/scripts/bench.cxx +0 -1170
- package/simsimd/scripts/bench.ipynb +0 -187
- package/simsimd/scripts/bench.js +0 -127
- package/simsimd/scripts/bench.rs +0 -876
- package/simsimd/scripts/bench_vectors.py +0 -734
- package/simsimd/scripts/bench_vectors_live.py +0 -213
- package/simsimd/scripts/test.c +0 -187
- package/simsimd/scripts/test.mjs +0 -220
- package/simsimd/scripts/test.py +0 -1505
- package/simsimd/swift/SimSIMD.swift +0 -149
- package/simsimd/swift/Test.swift +0 -128
- /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
- /package/{simsimd → numkong}/LICENSE +0 -0
- /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
- /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Geospatial Distances for Skylake.
|
|
3
|
+
* @file include/numkong/geospatial/skylake.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date February 6, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/geospatial.h
|
|
8
|
+
*
|
|
9
|
+
* @section geospatial_skylake_instructions Key AVX-512 Geospatial Instructions
|
|
10
|
+
*
|
|
11
|
+
* Intrinsic Instruction Icelake Genoa
|
|
12
|
+
* _mm512_sqrt_ps VSQRTPS (ZMM, ZMM) 19cy @ p0+p0+p05 15cy @ p01
|
|
13
|
+
* _mm512_sqrt_pd VSQRTPD (ZMM, ZMM) 23cy @ p0+p0+p05 21cy @ p01
|
|
14
|
+
* _mm256_div_ps VDIVPS (YMM, YMM, YMM) 11cy @ p0 11cy @ p01
|
|
15
|
+
* _mm256_div_pd VDIVPD (YMM, YMM, YMM) 13cy @ p0 13cy @ p01
|
|
16
|
+
* _mm256_fmadd_ps VFMADD231PS (YMM, YMM, YMM) 4cy @ p01 4cy @ p01
|
|
17
|
+
* _mm256_fmadd_pd VFMADD231PD (YMM, YMM, YMM) 4cy @ p01 4cy @ p01
|
|
18
|
+
* _mm512_cmp_ps_mask VCMPPS (K, ZMM, ZMM, I8) 4cy @ p5 5cy @ p01
|
|
19
|
+
*/
|
|
20
|
+
#ifndef NK_GEOSPATIAL_SKYLAKE_H
|
|
21
|
+
#define NK_GEOSPATIAL_SKYLAKE_H
|
|
22
|
+
|
|
23
|
+
#if NK_TARGET_X8664_
|
|
24
|
+
#if NK_TARGET_SKYLAKE
|
|
25
|
+
|
|
26
|
+
#include "numkong/types.h"
|
|
27
|
+
#include "numkong/trigonometry/skylake.h" // `nk_sin_f64x8_skylake_`, `nk_cos_f64x8_skylake_`, `nk_atan2_f64x8_skylake_`
|
|
28
|
+
|
|
29
|
+
#if defined(__cplusplus)
|
|
30
|
+
extern "C" {
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
#if defined(__clang__)
|
|
34
|
+
#pragma clang attribute push(__attribute__((target("avx2,avx512f,avx512vl,avx512bw,avx512dq,f16c,fma,bmi,bmi2"))), \
|
|
35
|
+
apply_to = function)
|
|
36
|
+
#elif defined(__GNUC__)
|
|
37
|
+
#pragma GCC push_options
|
|
38
|
+
#pragma GCC target("avx2", "avx512f", "avx512vl", "avx512bw", "avx512dq", "f16c", "fma", "bmi", "bmi2")
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
NK_INTERNAL __m512d nk_haversine_f64x8_skylake_( //
|
|
42
|
+
__m512d first_latitudes_f64x8, __m512d first_longitudes_f64x8, //
|
|
43
|
+
__m512d second_latitudes_f64x8, __m512d second_longitudes_f64x8) {
|
|
44
|
+
|
|
45
|
+
__m512d const earth_radius_f64x8 = _mm512_set1_pd(NK_EARTH_MEDIATORIAL_RADIUS);
|
|
46
|
+
__m512d const half_f64x8 = _mm512_set1_pd(0.5);
|
|
47
|
+
__m512d const one_f64x8 = _mm512_set1_pd(1.0);
|
|
48
|
+
__m512d const two_f64x8 = _mm512_set1_pd(2.0);
|
|
49
|
+
|
|
50
|
+
__m512d latitude_delta_f64x8 = _mm512_sub_pd(second_latitudes_f64x8, first_latitudes_f64x8);
|
|
51
|
+
__m512d longitude_delta_f64x8 = _mm512_sub_pd(second_longitudes_f64x8, first_longitudes_f64x8);
|
|
52
|
+
|
|
53
|
+
// Haversine terms: sin²(Δ/2)
|
|
54
|
+
__m512d latitude_delta_half_f64x8 = _mm512_mul_pd(latitude_delta_f64x8, half_f64x8);
|
|
55
|
+
__m512d longitude_delta_half_f64x8 = _mm512_mul_pd(longitude_delta_f64x8, half_f64x8);
|
|
56
|
+
__m512d sin_latitude_delta_half_f64x8 = nk_sin_f64x8_skylake_(latitude_delta_half_f64x8);
|
|
57
|
+
__m512d sin_longitude_delta_half_f64x8 = nk_sin_f64x8_skylake_(longitude_delta_half_f64x8);
|
|
58
|
+
__m512d sin_squared_latitude_delta_half_f64x8 = _mm512_mul_pd(sin_latitude_delta_half_f64x8,
|
|
59
|
+
sin_latitude_delta_half_f64x8);
|
|
60
|
+
__m512d sin_squared_longitude_delta_half_f64x8 = _mm512_mul_pd(sin_longitude_delta_half_f64x8,
|
|
61
|
+
sin_longitude_delta_half_f64x8);
|
|
62
|
+
|
|
63
|
+
// Latitude cosine product
|
|
64
|
+
__m512d cos_first_latitude_f64x8 = nk_cos_f64x8_skylake_(first_latitudes_f64x8);
|
|
65
|
+
__m512d cos_second_latitude_f64x8 = nk_cos_f64x8_skylake_(second_latitudes_f64x8);
|
|
66
|
+
__m512d cos_latitude_product_f64x8 = _mm512_mul_pd(cos_first_latitude_f64x8, cos_second_latitude_f64x8);
|
|
67
|
+
|
|
68
|
+
// a = sin²(Δlat/2) + cos(lat1) × cos(lat2) × sin²(Δlon/2)
|
|
69
|
+
__m512d haversine_term_f64x8 = _mm512_add_pd(
|
|
70
|
+
sin_squared_latitude_delta_half_f64x8,
|
|
71
|
+
_mm512_mul_pd(cos_latitude_product_f64x8, sin_squared_longitude_delta_half_f64x8));
|
|
72
|
+
// Clamp haversine_term_f64x8 to [0, 1] to prevent NaN from sqrt of negative values
|
|
73
|
+
__m512d zero_f64x8 = _mm512_setzero_pd();
|
|
74
|
+
haversine_term_f64x8 = _mm512_max_pd(zero_f64x8, _mm512_min_pd(one_f64x8, haversine_term_f64x8));
|
|
75
|
+
|
|
76
|
+
// Central angle: c = 2 × atan2(√a, √(1-a))
|
|
77
|
+
__m512d sqrt_haversine_f64x8 = _mm512_sqrt_pd(haversine_term_f64x8);
|
|
78
|
+
__m512d sqrt_complement_f64x8 = _mm512_sqrt_pd(_mm512_sub_pd(one_f64x8, haversine_term_f64x8));
|
|
79
|
+
__m512d central_angle_f64x8 = _mm512_mul_pd(two_f64x8,
|
|
80
|
+
nk_atan2_f64x8_skylake_(sqrt_haversine_f64x8, sqrt_complement_f64x8));
|
|
81
|
+
|
|
82
|
+
return _mm512_mul_pd(earth_radius_f64x8, central_angle_f64x8);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
NK_PUBLIC void nk_haversine_f64_skylake( //
|
|
86
|
+
nk_f64_t const *a_lats, nk_f64_t const *a_lons, //
|
|
87
|
+
nk_f64_t const *b_lats, nk_f64_t const *b_lons, //
|
|
88
|
+
nk_size_t n, nk_f64_t *results) {
|
|
89
|
+
|
|
90
|
+
while (n >= 8) {
|
|
91
|
+
__m512d first_latitudes_f64x8 = _mm512_loadu_pd(a_lats);
|
|
92
|
+
__m512d first_longitudes_f64x8 = _mm512_loadu_pd(a_lons);
|
|
93
|
+
__m512d second_latitudes_f64x8 = _mm512_loadu_pd(b_lats);
|
|
94
|
+
__m512d second_longitudes_f64x8 = _mm512_loadu_pd(b_lons);
|
|
95
|
+
|
|
96
|
+
__m512d distances_f64x8 = nk_haversine_f64x8_skylake_(first_latitudes_f64x8, first_longitudes_f64x8,
|
|
97
|
+
second_latitudes_f64x8, second_longitudes_f64x8);
|
|
98
|
+
_mm512_storeu_pd(results, distances_f64x8);
|
|
99
|
+
|
|
100
|
+
a_lats += 8, a_lons += 8, b_lats += 8, b_lons += 8, results += 8, n -= 8;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Handle remaining elements with masked operations
|
|
104
|
+
if (n > 0) {
|
|
105
|
+
__mmask8 mask = (__mmask8)_bzhi_u32(0xFF, n);
|
|
106
|
+
__m512d first_latitudes_f64x8 = _mm512_maskz_loadu_pd(mask, a_lats);
|
|
107
|
+
__m512d first_longitudes_f64x8 = _mm512_maskz_loadu_pd(mask, a_lons);
|
|
108
|
+
__m512d second_latitudes_f64x8 = _mm512_maskz_loadu_pd(mask, b_lats);
|
|
109
|
+
__m512d second_longitudes_f64x8 = _mm512_maskz_loadu_pd(mask, b_lons);
|
|
110
|
+
|
|
111
|
+
__m512d distances_f64x8 = nk_haversine_f64x8_skylake_(first_latitudes_f64x8, first_longitudes_f64x8,
|
|
112
|
+
second_latitudes_f64x8, second_longitudes_f64x8);
|
|
113
|
+
_mm512_mask_storeu_pd(results, mask, distances_f64x8);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @brief AVX-512 helper for Vincenty's geodesic distance on 8 f64 point pairs.
|
|
119
|
+
* @note This is a true SIMD implementation using masked convergence tracking.
|
|
120
|
+
*/
|
|
121
|
+
NK_INTERNAL __m512d nk_vincenty_f64x8_skylake_( //
|
|
122
|
+
__m512d first_latitudes_f64x8, __m512d first_longitudes_f64x8, //
|
|
123
|
+
__m512d second_latitudes_f64x8, __m512d second_longitudes_f64x8) {
|
|
124
|
+
|
|
125
|
+
__m512d const equatorial_radius_f64x8 = _mm512_set1_pd(NK_EARTH_ELLIPSOID_EQUATORIAL_RADIUS);
|
|
126
|
+
__m512d const polar_radius_f64x8 = _mm512_set1_pd(NK_EARTH_ELLIPSOID_POLAR_RADIUS);
|
|
127
|
+
__m512d const flattening_f64x8 = _mm512_set1_pd(1.0 / NK_EARTH_ELLIPSOID_INVERSE_FLATTENING);
|
|
128
|
+
__m512d const convergence_threshold_f64x8 = _mm512_set1_pd(NK_VINCENTY_CONVERGENCE_THRESHOLD_F64);
|
|
129
|
+
__m512d const one_f64x8 = _mm512_set1_pd(1.0);
|
|
130
|
+
__m512d const two_f64x8 = _mm512_set1_pd(2.0);
|
|
131
|
+
__m512d const three_f64x8 = _mm512_set1_pd(3.0);
|
|
132
|
+
__m512d const four_f64x8 = _mm512_set1_pd(4.0);
|
|
133
|
+
__m512d const six_f64x8 = _mm512_set1_pd(6.0);
|
|
134
|
+
__m512d const sixteen_f64x8 = _mm512_set1_pd(16.0);
|
|
135
|
+
|
|
136
|
+
// Longitude difference
|
|
137
|
+
__m512d longitude_difference_f64x8 = _mm512_sub_pd(second_longitudes_f64x8, first_longitudes_f64x8);
|
|
138
|
+
|
|
139
|
+
// Reduced latitudes: tan(U) = (1-f) * tan(lat)
|
|
140
|
+
__m512d one_minus_f_f64x8 = _mm512_sub_pd(one_f64x8, flattening_f64x8);
|
|
141
|
+
__m512d tan_first_f64x8 = _mm512_div_pd(nk_sin_f64x8_skylake_(first_latitudes_f64x8),
|
|
142
|
+
nk_cos_f64x8_skylake_(first_latitudes_f64x8));
|
|
143
|
+
__m512d tan_second_f64x8 = _mm512_div_pd(nk_sin_f64x8_skylake_(second_latitudes_f64x8),
|
|
144
|
+
nk_cos_f64x8_skylake_(second_latitudes_f64x8));
|
|
145
|
+
__m512d tan_reduced_first_f64x8 = _mm512_mul_pd(one_minus_f_f64x8, tan_first_f64x8);
|
|
146
|
+
__m512d tan_reduced_second_f64x8 = _mm512_mul_pd(one_minus_f_f64x8, tan_second_f64x8);
|
|
147
|
+
|
|
148
|
+
// cos(U) = 1/√(1 + tan²(U)), sin(U) = tan(U) × cos(U)
|
|
149
|
+
__m512d cos_reduced_first_f64x8 = _mm512_div_pd(
|
|
150
|
+
one_f64x8, _mm512_sqrt_pd(_mm512_fmadd_pd(tan_reduced_first_f64x8, tan_reduced_first_f64x8, one_f64x8)));
|
|
151
|
+
__m512d sin_reduced_first_f64x8 = _mm512_mul_pd(tan_reduced_first_f64x8, cos_reduced_first_f64x8);
|
|
152
|
+
__m512d cos_reduced_second_f64x8 = _mm512_div_pd(
|
|
153
|
+
one_f64x8, _mm512_sqrt_pd(_mm512_fmadd_pd(tan_reduced_second_f64x8, tan_reduced_second_f64x8, one_f64x8)));
|
|
154
|
+
__m512d sin_reduced_second_f64x8 = _mm512_mul_pd(tan_reduced_second_f64x8, cos_reduced_second_f64x8);
|
|
155
|
+
|
|
156
|
+
// Initialize lambda_f64x8 and tracking variables
|
|
157
|
+
__m512d lambda_f64x8 = longitude_difference_f64x8;
|
|
158
|
+
__m512d sin_angular_distance_f64x8, cos_angular_distance_f64x8, angular_distance_f64x8;
|
|
159
|
+
__m512d sin_azimuth_f64x8, cos_squared_azimuth_f64x8, cos_double_angular_midpoint_f64x8;
|
|
160
|
+
|
|
161
|
+
// Track convergence and coincident points
|
|
162
|
+
__mmask8 converged_mask = 0;
|
|
163
|
+
__mmask8 coincident_mask = 0;
|
|
164
|
+
|
|
165
|
+
for (nk_u32_t iteration = 0; iteration < NK_VINCENTY_MAX_ITERATIONS && converged_mask != 0xFF; ++iteration) {
|
|
166
|
+
__m512d sin_lambda_f64x8 = nk_sin_f64x8_skylake_(lambda_f64x8);
|
|
167
|
+
__m512d cos_lambda_f64x8 = nk_cos_f64x8_skylake_(lambda_f64x8);
|
|
168
|
+
|
|
169
|
+
// sin²(angular_distance_f64x8) = (cos(U₂) × sin(λ))² + (cos(U₁) × sin(U₂) - sin(U₁) × cos(U₂) × cos(λ))²
|
|
170
|
+
__m512d cross_term_f64x8 = _mm512_mul_pd(cos_reduced_second_f64x8, sin_lambda_f64x8);
|
|
171
|
+
__m512d mixed_term_f64x8 = _mm512_sub_pd(
|
|
172
|
+
_mm512_mul_pd(cos_reduced_first_f64x8, sin_reduced_second_f64x8),
|
|
173
|
+
_mm512_mul_pd(_mm512_mul_pd(sin_reduced_first_f64x8, cos_reduced_second_f64x8), cos_lambda_f64x8));
|
|
174
|
+
__m512d sin_angular_dist_sq_f64x8 = _mm512_fmadd_pd(cross_term_f64x8, cross_term_f64x8,
|
|
175
|
+
_mm512_mul_pd(mixed_term_f64x8, mixed_term_f64x8));
|
|
176
|
+
sin_angular_distance_f64x8 = _mm512_sqrt_pd(sin_angular_dist_sq_f64x8);
|
|
177
|
+
|
|
178
|
+
// Check for coincident points (sin_angular_distance_f64x8 ≈ 0)
|
|
179
|
+
coincident_mask = _mm512_cmp_pd_mask(sin_angular_distance_f64x8, _mm512_set1_pd(1e-15), _CMP_LT_OS);
|
|
180
|
+
|
|
181
|
+
// cos(angular_distance_f64x8) = sin(U₁) × sin(U₂) + cos(U₁) × cos(U₂) × cos(λ)
|
|
182
|
+
cos_angular_distance_f64x8 = _mm512_fmadd_pd(_mm512_mul_pd(cos_reduced_first_f64x8, cos_reduced_second_f64x8),
|
|
183
|
+
cos_lambda_f64x8,
|
|
184
|
+
_mm512_mul_pd(sin_reduced_first_f64x8, sin_reduced_second_f64x8));
|
|
185
|
+
|
|
186
|
+
// angular_distance_f64x8 = atan2(sin, cos)
|
|
187
|
+
angular_distance_f64x8 = nk_atan2_f64x8_skylake_(sin_angular_distance_f64x8, cos_angular_distance_f64x8);
|
|
188
|
+
|
|
189
|
+
// sin(azimuth) = cos(U₁) × cos(U₂) × sin(λ) / sin(angular_distance_f64x8)
|
|
190
|
+
// Use masked divide: zero result for coincident lanes, avoids division by zero
|
|
191
|
+
sin_azimuth_f64x8 = _mm512_maskz_div_pd(
|
|
192
|
+
_knot_mask8(coincident_mask),
|
|
193
|
+
_mm512_mul_pd(_mm512_mul_pd(cos_reduced_first_f64x8, cos_reduced_second_f64x8), sin_lambda_f64x8),
|
|
194
|
+
sin_angular_distance_f64x8);
|
|
195
|
+
cos_squared_azimuth_f64x8 = _mm512_sub_pd(one_f64x8, _mm512_mul_pd(sin_azimuth_f64x8, sin_azimuth_f64x8));
|
|
196
|
+
|
|
197
|
+
// Handle equatorial case: cos²α = 0
|
|
198
|
+
__mmask8 equatorial_mask = _mm512_cmp_pd_mask(cos_squared_azimuth_f64x8, _mm512_set1_pd(1e-15), _CMP_LT_OS);
|
|
199
|
+
|
|
200
|
+
// cos(2σₘ) = cos(σ) - 2 × sin(U₁) × sin(U₂) / cos²(α)
|
|
201
|
+
// Use masked divide: for equatorial lanes, quotient_f64x8 = cos_angular_distance_f64x8 (passthrough),
|
|
202
|
+
// so subtraction yields zero. Avoids division by zero.
|
|
203
|
+
__m512d sin_product_f64x8 = _mm512_mul_pd(sin_reduced_first_f64x8, sin_reduced_second_f64x8);
|
|
204
|
+
__m512d quotient_f64x8 = _mm512_mask_div_pd(cos_angular_distance_f64x8, _knot_mask8(equatorial_mask),
|
|
205
|
+
_mm512_mul_pd(two_f64x8, sin_product_f64x8),
|
|
206
|
+
cos_squared_azimuth_f64x8);
|
|
207
|
+
cos_double_angular_midpoint_f64x8 = _mm512_sub_pd(cos_angular_distance_f64x8, quotient_f64x8);
|
|
208
|
+
|
|
209
|
+
// C = f/16 * cos²α * (4 + f*(4 - 3*cos²α))
|
|
210
|
+
__m512d correction_factor_f64x8 = _mm512_mul_pd(
|
|
211
|
+
_mm512_div_pd(flattening_f64x8, sixteen_f64x8),
|
|
212
|
+
_mm512_mul_pd(
|
|
213
|
+
cos_squared_azimuth_f64x8,
|
|
214
|
+
_mm512_fmadd_pd(flattening_f64x8, _mm512_fnmadd_pd(three_f64x8, cos_squared_azimuth_f64x8, four_f64x8),
|
|
215
|
+
four_f64x8)));
|
|
216
|
+
|
|
217
|
+
// λ' = L + (1-C) × f × sin(α) × (σ + C × sin(σ) × (cos(2σₘ) + C × cos(σ) × (-1 + 2 × cos²(2σₘ))))
|
|
218
|
+
__m512d cos_2sm_sq_f64x8 = _mm512_mul_pd(cos_double_angular_midpoint_f64x8, cos_double_angular_midpoint_f64x8);
|
|
219
|
+
// innermost_f64x8 = -1 + 2 × cos²(2σₘ)
|
|
220
|
+
__m512d innermost_f64x8 = _mm512_fmadd_pd(two_f64x8, cos_2sm_sq_f64x8, _mm512_set1_pd(-1.0));
|
|
221
|
+
// middle_f64x8 = cos(2σₘ) + C × cos(σ) × innermost_f64x8
|
|
222
|
+
__m512d middle_f64x8 = _mm512_fmadd_pd(_mm512_mul_pd(correction_factor_f64x8, cos_angular_distance_f64x8),
|
|
223
|
+
innermost_f64x8, cos_double_angular_midpoint_f64x8);
|
|
224
|
+
// inner_f64x8 = C × sin(σ) × middle_f64x8
|
|
225
|
+
__m512d inner_f64x8 = _mm512_mul_pd(_mm512_mul_pd(correction_factor_f64x8, sin_angular_distance_f64x8),
|
|
226
|
+
middle_f64x8);
|
|
227
|
+
|
|
228
|
+
// λ' = L + (1-C) * f * sin_α * (σ + inner_f64x8)
|
|
229
|
+
__m512d lambda_new_f64x8 = _mm512_fmadd_pd(
|
|
230
|
+
_mm512_mul_pd(_mm512_mul_pd(_mm512_sub_pd(one_f64x8, correction_factor_f64x8), flattening_f64x8),
|
|
231
|
+
sin_azimuth_f64x8),
|
|
232
|
+
_mm512_add_pd(angular_distance_f64x8, inner_f64x8), longitude_difference_f64x8);
|
|
233
|
+
|
|
234
|
+
// Check convergence: |λ - λ'| < threshold
|
|
235
|
+
__m512d lambda_diff_f64x8 = _mm512_abs_pd(_mm512_sub_pd(lambda_new_f64x8, lambda_f64x8));
|
|
236
|
+
converged_mask = _mm512_cmp_pd_mask(lambda_diff_f64x8, convergence_threshold_f64x8, _CMP_LT_OS);
|
|
237
|
+
|
|
238
|
+
lambda_f64x8 = lambda_new_f64x8;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Final distance calculation
|
|
242
|
+
// u² = cos²α * (a² - b²) / b²
|
|
243
|
+
__m512d a_sq_f64x8 = _mm512_mul_pd(equatorial_radius_f64x8, equatorial_radius_f64x8);
|
|
244
|
+
__m512d b_sq_f64x8 = _mm512_mul_pd(polar_radius_f64x8, polar_radius_f64x8);
|
|
245
|
+
__m512d u_squared_f64x8 = _mm512_div_pd(
|
|
246
|
+
_mm512_mul_pd(cos_squared_azimuth_f64x8, _mm512_sub_pd(a_sq_f64x8, b_sq_f64x8)), b_sq_f64x8);
|
|
247
|
+
|
|
248
|
+
// A = 1 + u²/16384 * (4096 + u²*(-768 + u²*(320 - 175*u²)))
|
|
249
|
+
__m512d series_a_f64x8 = _mm512_fmadd_pd(u_squared_f64x8, _mm512_set1_pd(-175.0), _mm512_set1_pd(320.0));
|
|
250
|
+
series_a_f64x8 = _mm512_fmadd_pd(u_squared_f64x8, series_a_f64x8, _mm512_set1_pd(-768.0));
|
|
251
|
+
series_a_f64x8 = _mm512_fmadd_pd(u_squared_f64x8, series_a_f64x8, _mm512_set1_pd(4096.0));
|
|
252
|
+
series_a_f64x8 = _mm512_fmadd_pd(_mm512_div_pd(u_squared_f64x8, _mm512_set1_pd(16384.0)), series_a_f64x8,
|
|
253
|
+
one_f64x8);
|
|
254
|
+
|
|
255
|
+
// B = u²/1024 * (256 + u²*(-128 + u²*(74 - 47*u²)))
|
|
256
|
+
__m512d series_b_f64x8 = _mm512_fmadd_pd(u_squared_f64x8, _mm512_set1_pd(-47.0), _mm512_set1_pd(74.0));
|
|
257
|
+
series_b_f64x8 = _mm512_fmadd_pd(u_squared_f64x8, series_b_f64x8, _mm512_set1_pd(-128.0));
|
|
258
|
+
series_b_f64x8 = _mm512_fmadd_pd(u_squared_f64x8, series_b_f64x8, _mm512_set1_pd(256.0));
|
|
259
|
+
series_b_f64x8 = _mm512_mul_pd(_mm512_div_pd(u_squared_f64x8, _mm512_set1_pd(1024.0)), series_b_f64x8);
|
|
260
|
+
|
|
261
|
+
// Δσ = B × sin(σ) × (cos(2σₘ) +
|
|
262
|
+
// B/4 × (cos(σ) × (-1 + 2 × cos²(2σₘ)) - B/6 × cos(2σₘ) × (-3 + 4 × sin²(σ)) × (-3 + 4 × cos²(2σₘ))))
|
|
263
|
+
__m512d cos_2sm_sq_f64x8 = _mm512_mul_pd(cos_double_angular_midpoint_f64x8, cos_double_angular_midpoint_f64x8);
|
|
264
|
+
__m512d sin_sq_f64x8 = _mm512_mul_pd(sin_angular_distance_f64x8, sin_angular_distance_f64x8);
|
|
265
|
+
__m512d term1_f64x8 = _mm512_fmadd_pd(two_f64x8, cos_2sm_sq_f64x8, _mm512_set1_pd(-1.0));
|
|
266
|
+
term1_f64x8 = _mm512_mul_pd(cos_angular_distance_f64x8, term1_f64x8);
|
|
267
|
+
__m512d term2_f64x8 = _mm512_fmadd_pd(four_f64x8, sin_sq_f64x8, _mm512_set1_pd(-3.0));
|
|
268
|
+
__m512d term3_f64x8 = _mm512_fmadd_pd(four_f64x8, cos_2sm_sq_f64x8, _mm512_set1_pd(-3.0));
|
|
269
|
+
term2_f64x8 = _mm512_mul_pd(
|
|
270
|
+
_mm512_mul_pd(_mm512_div_pd(series_b_f64x8, six_f64x8), cos_double_angular_midpoint_f64x8),
|
|
271
|
+
_mm512_mul_pd(term2_f64x8, term3_f64x8));
|
|
272
|
+
__m512d delta_sigma_f64x8 = _mm512_mul_pd(
|
|
273
|
+
series_b_f64x8, _mm512_mul_pd(sin_angular_distance_f64x8,
|
|
274
|
+
_mm512_add_pd(cos_double_angular_midpoint_f64x8,
|
|
275
|
+
_mm512_mul_pd(_mm512_div_pd(series_b_f64x8, four_f64x8),
|
|
276
|
+
_mm512_sub_pd(term1_f64x8, term2_f64x8)))));
|
|
277
|
+
|
|
278
|
+
// s = b * A * (σ - Δσ)
|
|
279
|
+
__m512d distances_f64x8 = _mm512_mul_pd(_mm512_mul_pd(polar_radius_f64x8, series_a_f64x8),
|
|
280
|
+
_mm512_sub_pd(angular_distance_f64x8, delta_sigma_f64x8));
|
|
281
|
+
|
|
282
|
+
// Set coincident points to zero
|
|
283
|
+
distances_f64x8 = _mm512_mask_blend_pd(coincident_mask, distances_f64x8, _mm512_setzero_pd());
|
|
284
|
+
|
|
285
|
+
return distances_f64x8;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
NK_PUBLIC void nk_vincenty_f64_skylake( //
|
|
289
|
+
nk_f64_t const *a_lats, nk_f64_t const *a_lons, //
|
|
290
|
+
nk_f64_t const *b_lats, nk_f64_t const *b_lons, //
|
|
291
|
+
nk_size_t n, nk_f64_t *results) {
|
|
292
|
+
|
|
293
|
+
while (n >= 8) {
|
|
294
|
+
__m512d first_latitudes_f64x8 = _mm512_loadu_pd(a_lats);
|
|
295
|
+
__m512d first_longitudes_f64x8 = _mm512_loadu_pd(a_lons);
|
|
296
|
+
__m512d second_latitudes_f64x8 = _mm512_loadu_pd(b_lats);
|
|
297
|
+
__m512d second_longitudes_f64x8 = _mm512_loadu_pd(b_lons);
|
|
298
|
+
|
|
299
|
+
__m512d distances_f64x8 = nk_vincenty_f64x8_skylake_(first_latitudes_f64x8, first_longitudes_f64x8,
|
|
300
|
+
second_latitudes_f64x8, second_longitudes_f64x8);
|
|
301
|
+
_mm512_storeu_pd(results, distances_f64x8);
|
|
302
|
+
|
|
303
|
+
a_lats += 8, a_lons += 8, b_lats += 8, b_lons += 8, results += 8, n -= 8;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Handle remaining elements with masked operations
|
|
307
|
+
if (n > 0) {
|
|
308
|
+
__mmask8 mask = (__mmask8)_bzhi_u32(0xFF, n);
|
|
309
|
+
__m512d first_latitudes_f64x8 = _mm512_maskz_loadu_pd(mask, a_lats);
|
|
310
|
+
__m512d first_longitudes_f64x8 = _mm512_maskz_loadu_pd(mask, a_lons);
|
|
311
|
+
__m512d second_latitudes_f64x8 = _mm512_maskz_loadu_pd(mask, b_lats);
|
|
312
|
+
__m512d second_longitudes_f64x8 = _mm512_maskz_loadu_pd(mask, b_lons);
|
|
313
|
+
|
|
314
|
+
__m512d distances_f64x8 = nk_vincenty_f64x8_skylake_(first_latitudes_f64x8, first_longitudes_f64x8,
|
|
315
|
+
second_latitudes_f64x8, second_longitudes_f64x8);
|
|
316
|
+
_mm512_mask_storeu_pd(results, mask, distances_f64x8);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
NK_INTERNAL __m512 nk_haversine_f32x16_skylake_( //
|
|
321
|
+
__m512 first_latitudes_f32x16, __m512 first_longitudes_f32x16, //
|
|
322
|
+
__m512 second_latitudes_f32x16, __m512 second_longitudes_f32x16) {
|
|
323
|
+
|
|
324
|
+
__m512 const earth_radius_f32x16 = _mm512_set1_ps((float)NK_EARTH_MEDIATORIAL_RADIUS);
|
|
325
|
+
__m512 const half_f32x16 = _mm512_set1_ps(0.5f);
|
|
326
|
+
__m512 const one_f32x16 = _mm512_set1_ps(1.0f);
|
|
327
|
+
__m512 const two_f32x16 = _mm512_set1_ps(2.0f);
|
|
328
|
+
|
|
329
|
+
__m512 latitude_delta_f32x16 = _mm512_sub_ps(second_latitudes_f32x16, first_latitudes_f32x16);
|
|
330
|
+
__m512 longitude_delta_f32x16 = _mm512_sub_ps(second_longitudes_f32x16, first_longitudes_f32x16);
|
|
331
|
+
|
|
332
|
+
// Haversine terms: sin²(Δ/2)
|
|
333
|
+
__m512 latitude_delta_half_f32x16 = _mm512_mul_ps(latitude_delta_f32x16, half_f32x16);
|
|
334
|
+
__m512 longitude_delta_half_f32x16 = _mm512_mul_ps(longitude_delta_f32x16, half_f32x16);
|
|
335
|
+
__m512 sin_latitude_delta_half_f32x16 = nk_sin_f32x16_skylake_(latitude_delta_half_f32x16);
|
|
336
|
+
__m512 sin_longitude_delta_half_f32x16 = nk_sin_f32x16_skylake_(longitude_delta_half_f32x16);
|
|
337
|
+
__m512 sin_squared_latitude_delta_half_f32x16 = _mm512_mul_ps(sin_latitude_delta_half_f32x16,
|
|
338
|
+
sin_latitude_delta_half_f32x16);
|
|
339
|
+
__m512 sin_squared_longitude_delta_half_f32x16 = _mm512_mul_ps(sin_longitude_delta_half_f32x16,
|
|
340
|
+
sin_longitude_delta_half_f32x16);
|
|
341
|
+
|
|
342
|
+
// Latitude cosine product
|
|
343
|
+
__m512 cos_first_latitude_f32x16 = nk_cos_f32x16_skylake_(first_latitudes_f32x16);
|
|
344
|
+
__m512 cos_second_latitude_f32x16 = nk_cos_f32x16_skylake_(second_latitudes_f32x16);
|
|
345
|
+
__m512 cos_latitude_product_f32x16 = _mm512_mul_ps(cos_first_latitude_f32x16, cos_second_latitude_f32x16);
|
|
346
|
+
|
|
347
|
+
// a = sin²(Δlat/2) + cos(lat1) × cos(lat2) × sin²(Δlon/2)
|
|
348
|
+
__m512 haversine_term_f32x16 = _mm512_add_ps(
|
|
349
|
+
sin_squared_latitude_delta_half_f32x16,
|
|
350
|
+
_mm512_mul_ps(cos_latitude_product_f32x16, sin_squared_longitude_delta_half_f32x16));
|
|
351
|
+
|
|
352
|
+
// Clamp to [0, 1] to avoid NaN from sqrt of negative numbers (due to floating point errors)
|
|
353
|
+
__m512 zero_f32x16 = _mm512_setzero_ps();
|
|
354
|
+
haversine_term_f32x16 = _mm512_max_ps(zero_f32x16, _mm512_min_ps(one_f32x16, haversine_term_f32x16));
|
|
355
|
+
|
|
356
|
+
// Central angle: c = 2 × atan2(√a, √(1-a))
|
|
357
|
+
__m512 sqrt_haversine_f32x16 = _mm512_sqrt_ps(haversine_term_f32x16);
|
|
358
|
+
__m512 sqrt_complement_f32x16 = _mm512_sqrt_ps(_mm512_sub_ps(one_f32x16, haversine_term_f32x16));
|
|
359
|
+
__m512 central_angle_f32x16 = _mm512_mul_ps(
|
|
360
|
+
two_f32x16, nk_atan2_f32x16_skylake_(sqrt_haversine_f32x16, sqrt_complement_f32x16));
|
|
361
|
+
|
|
362
|
+
return _mm512_mul_ps(earth_radius_f32x16, central_angle_f32x16);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
NK_PUBLIC void nk_haversine_f32_skylake( //
|
|
366
|
+
nk_f32_t const *a_lats, nk_f32_t const *a_lons, //
|
|
367
|
+
nk_f32_t const *b_lats, nk_f32_t const *b_lons, //
|
|
368
|
+
nk_size_t n, nk_f32_t *results) {
|
|
369
|
+
|
|
370
|
+
while (n >= 16) {
|
|
371
|
+
__m512 first_latitudes_f32x16 = _mm512_loadu_ps(a_lats);
|
|
372
|
+
__m512 first_longitudes_f32x16 = _mm512_loadu_ps(a_lons);
|
|
373
|
+
__m512 second_latitudes_f32x16 = _mm512_loadu_ps(b_lats);
|
|
374
|
+
__m512 second_longitudes_f32x16 = _mm512_loadu_ps(b_lons);
|
|
375
|
+
|
|
376
|
+
__m512 distances_f32x16 = nk_haversine_f32x16_skylake_(first_latitudes_f32x16, first_longitudes_f32x16,
|
|
377
|
+
second_latitudes_f32x16, second_longitudes_f32x16);
|
|
378
|
+
_mm512_storeu_ps(results, distances_f32x16);
|
|
379
|
+
|
|
380
|
+
a_lats += 16, a_lons += 16, b_lats += 16, b_lons += 16, results += 16, n -= 16;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Handle remaining elements with masked operations
|
|
384
|
+
if (n > 0) {
|
|
385
|
+
__mmask16 mask = (__mmask16)_bzhi_u32(0xFFFF, n);
|
|
386
|
+
__m512 first_latitudes_f32x16 = _mm512_maskz_loadu_ps(mask, a_lats);
|
|
387
|
+
__m512 first_longitudes_f32x16 = _mm512_maskz_loadu_ps(mask, a_lons);
|
|
388
|
+
__m512 second_latitudes_f32x16 = _mm512_maskz_loadu_ps(mask, b_lats);
|
|
389
|
+
__m512 second_longitudes_f32x16 = _mm512_maskz_loadu_ps(mask, b_lons);
|
|
390
|
+
|
|
391
|
+
__m512 distances_f32x16 = nk_haversine_f32x16_skylake_(first_latitudes_f32x16, first_longitudes_f32x16,
|
|
392
|
+
second_latitudes_f32x16, second_longitudes_f32x16);
|
|
393
|
+
_mm512_mask_storeu_ps(results, mask, distances_f32x16);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* @brief AVX-512 helper for Vincenty's geodesic distance on 16 f32 point pairs.
|
|
399
|
+
* @note This is a true SIMD implementation using masked convergence tracking.
|
|
400
|
+
*/
|
|
401
|
+
NK_INTERNAL __m512 nk_vincenty_f32x16_skylake_( //
|
|
402
|
+
__m512 first_latitudes_f32x16, __m512 first_longitudes_f32x16, //
|
|
403
|
+
__m512 second_latitudes_f32x16, __m512 second_longitudes_f32x16) {
|
|
404
|
+
|
|
405
|
+
__m512 const equatorial_radius_f32x16 = _mm512_set1_ps((float)NK_EARTH_ELLIPSOID_EQUATORIAL_RADIUS);
|
|
406
|
+
__m512 const polar_radius_f32x16 = _mm512_set1_ps((float)NK_EARTH_ELLIPSOID_POLAR_RADIUS);
|
|
407
|
+
__m512 const flattening_f32x16 = _mm512_set1_ps(1.0f / (float)NK_EARTH_ELLIPSOID_INVERSE_FLATTENING);
|
|
408
|
+
__m512 const convergence_threshold_f32x16 = _mm512_set1_ps(NK_VINCENTY_CONVERGENCE_THRESHOLD_F32);
|
|
409
|
+
__m512 const one_f32x16 = _mm512_set1_ps(1.0f);
|
|
410
|
+
__m512 const two_f32x16 = _mm512_set1_ps(2.0f);
|
|
411
|
+
__m512 const three_f32x16 = _mm512_set1_ps(3.0f);
|
|
412
|
+
__m512 const four_f32x16 = _mm512_set1_ps(4.0f);
|
|
413
|
+
__m512 const six_f32x16 = _mm512_set1_ps(6.0f);
|
|
414
|
+
__m512 const sixteen_f32x16 = _mm512_set1_ps(16.0f);
|
|
415
|
+
|
|
416
|
+
// Longitude difference
|
|
417
|
+
__m512 longitude_difference_f32x16 = _mm512_sub_ps(second_longitudes_f32x16, first_longitudes_f32x16);
|
|
418
|
+
|
|
419
|
+
// Reduced latitudes: tan(U) = (1-f) * tan(lat)
|
|
420
|
+
__m512 one_minus_f_f32x16 = _mm512_sub_ps(one_f32x16, flattening_f32x16);
|
|
421
|
+
__m512 tan_first_f32x16 = _mm512_div_ps(nk_sin_f32x16_skylake_(first_latitudes_f32x16),
|
|
422
|
+
nk_cos_f32x16_skylake_(first_latitudes_f32x16));
|
|
423
|
+
__m512 tan_second_f32x16 = _mm512_div_ps(nk_sin_f32x16_skylake_(second_latitudes_f32x16),
|
|
424
|
+
nk_cos_f32x16_skylake_(second_latitudes_f32x16));
|
|
425
|
+
__m512 tan_reduced_first_f32x16 = _mm512_mul_ps(one_minus_f_f32x16, tan_first_f32x16);
|
|
426
|
+
__m512 tan_reduced_second_f32x16 = _mm512_mul_ps(one_minus_f_f32x16, tan_second_f32x16);
|
|
427
|
+
|
|
428
|
+
// cos(U) = 1/√(1 + tan²(U)), sin(U) = tan(U) × cos(U)
|
|
429
|
+
__m512 cos_reduced_first_f32x16 = _mm512_div_ps(
|
|
430
|
+
one_f32x16, _mm512_sqrt_ps(_mm512_fmadd_ps(tan_reduced_first_f32x16, tan_reduced_first_f32x16, one_f32x16)));
|
|
431
|
+
__m512 sin_reduced_first_f32x16 = _mm512_mul_ps(tan_reduced_first_f32x16, cos_reduced_first_f32x16);
|
|
432
|
+
__m512 cos_reduced_second_f32x16 = _mm512_div_ps(
|
|
433
|
+
one_f32x16, _mm512_sqrt_ps(_mm512_fmadd_ps(tan_reduced_second_f32x16, tan_reduced_second_f32x16, one_f32x16)));
|
|
434
|
+
__m512 sin_reduced_second_f32x16 = _mm512_mul_ps(tan_reduced_second_f32x16, cos_reduced_second_f32x16);
|
|
435
|
+
|
|
436
|
+
// Initialize lambda_f32x16 and tracking variables
|
|
437
|
+
__m512 lambda_f32x16 = longitude_difference_f32x16;
|
|
438
|
+
__m512 sin_angular_distance_f32x16, cos_angular_distance_f32x16, angular_distance_f32x16;
|
|
439
|
+
__m512 sin_azimuth_f32x16, cos_squared_azimuth_f32x16, cos_double_angular_midpoint_f32x16;
|
|
440
|
+
|
|
441
|
+
// Track convergence and coincident points
|
|
442
|
+
__mmask16 converged_mask = 0;
|
|
443
|
+
__mmask16 coincident_mask = 0;
|
|
444
|
+
|
|
445
|
+
for (nk_u32_t iteration = 0; iteration < NK_VINCENTY_MAX_ITERATIONS && converged_mask != 0xFFFF; ++iteration) {
|
|
446
|
+
__m512 sin_lambda_f32x16 = nk_sin_f32x16_skylake_(lambda_f32x16);
|
|
447
|
+
__m512 cos_lambda_f32x16 = nk_cos_f32x16_skylake_(lambda_f32x16);
|
|
448
|
+
|
|
449
|
+
// sin²(angular_distance_f32x16) = (cos(U₂) × sin(λ))² + (cos(U₁) × sin(U₂) - sin(U₁) × cos(U₂) × cos(λ))²
|
|
450
|
+
__m512 cross_term_f32x16 = _mm512_mul_ps(cos_reduced_second_f32x16, sin_lambda_f32x16);
|
|
451
|
+
__m512 mixed_term_f32x16 = _mm512_sub_ps(
|
|
452
|
+
_mm512_mul_ps(cos_reduced_first_f32x16, sin_reduced_second_f32x16),
|
|
453
|
+
_mm512_mul_ps(_mm512_mul_ps(sin_reduced_first_f32x16, cos_reduced_second_f32x16), cos_lambda_f32x16));
|
|
454
|
+
__m512 sin_angular_dist_sq_f32x16 = _mm512_fmadd_ps(cross_term_f32x16, cross_term_f32x16,
|
|
455
|
+
_mm512_mul_ps(mixed_term_f32x16, mixed_term_f32x16));
|
|
456
|
+
sin_angular_distance_f32x16 = _mm512_sqrt_ps(sin_angular_dist_sq_f32x16);
|
|
457
|
+
|
|
458
|
+
// Check for coincident points (sin_angular_distance_f32x16 ≈ 0)
|
|
459
|
+
coincident_mask = _mm512_cmp_ps_mask(sin_angular_distance_f32x16, _mm512_set1_ps(1e-7f), _CMP_LT_OS);
|
|
460
|
+
|
|
461
|
+
// cos(angular_distance_f32x16) = sin(U₁) × sin(U₂) + cos(U₁) × cos(U₂) × cos(λ)
|
|
462
|
+
cos_angular_distance_f32x16 = _mm512_fmadd_ps(
|
|
463
|
+
_mm512_mul_ps(cos_reduced_first_f32x16, cos_reduced_second_f32x16), cos_lambda_f32x16,
|
|
464
|
+
_mm512_mul_ps(sin_reduced_first_f32x16, sin_reduced_second_f32x16));
|
|
465
|
+
|
|
466
|
+
// angular_distance_f32x16 = atan2(sin, cos)
|
|
467
|
+
angular_distance_f32x16 = nk_atan2_f32x16_skylake_(sin_angular_distance_f32x16, cos_angular_distance_f32x16);
|
|
468
|
+
|
|
469
|
+
// sin(azimuth) = cos(U₁) × cos(U₂) × sin(λ) / sin(angular_distance_f32x16)
|
|
470
|
+
// Use masked divide: zero result for coincident lanes, avoids division by zero
|
|
471
|
+
sin_azimuth_f32x16 = _mm512_maskz_div_ps(
|
|
472
|
+
_knot_mask16(coincident_mask),
|
|
473
|
+
_mm512_mul_ps(_mm512_mul_ps(cos_reduced_first_f32x16, cos_reduced_second_f32x16), sin_lambda_f32x16),
|
|
474
|
+
sin_angular_distance_f32x16);
|
|
475
|
+
cos_squared_azimuth_f32x16 = _mm512_sub_ps(one_f32x16, _mm512_mul_ps(sin_azimuth_f32x16, sin_azimuth_f32x16));
|
|
476
|
+
|
|
477
|
+
// Handle equatorial case: cos²α = 0
|
|
478
|
+
__mmask16 equatorial_mask = _mm512_cmp_ps_mask(cos_squared_azimuth_f32x16, _mm512_set1_ps(1e-7f), _CMP_LT_OS);
|
|
479
|
+
|
|
480
|
+
// cos(2σₘ) = cos(σ) - 2 × sin(U₁) × sin(U₂) / cos²(α)
|
|
481
|
+
// Use masked divide: for equatorial lanes, quotient_f32x16 = cos_angular_distance_f32x16 (passthrough),
|
|
482
|
+
// so subtraction yields zero. Avoids division by zero.
|
|
483
|
+
__m512 sin_product_f32x16 = _mm512_mul_ps(sin_reduced_first_f32x16, sin_reduced_second_f32x16);
|
|
484
|
+
__m512 quotient_f32x16 = _mm512_mask_div_ps(cos_angular_distance_f32x16, _knot_mask16(equatorial_mask),
|
|
485
|
+
_mm512_mul_ps(two_f32x16, sin_product_f32x16),
|
|
486
|
+
cos_squared_azimuth_f32x16);
|
|
487
|
+
cos_double_angular_midpoint_f32x16 = _mm512_sub_ps(cos_angular_distance_f32x16, quotient_f32x16);
|
|
488
|
+
|
|
489
|
+
// C = f/16 * cos²α * (4 + f*(4 - 3*cos²α))
|
|
490
|
+
__m512 correction_factor_f32x16 = _mm512_mul_ps(
|
|
491
|
+
_mm512_div_ps(flattening_f32x16, sixteen_f32x16),
|
|
492
|
+
_mm512_mul_ps(
|
|
493
|
+
cos_squared_azimuth_f32x16,
|
|
494
|
+
_mm512_fmadd_ps(flattening_f32x16,
|
|
495
|
+
_mm512_fnmadd_ps(three_f32x16, cos_squared_azimuth_f32x16, four_f32x16), four_f32x16)));
|
|
496
|
+
|
|
497
|
+
// λ' = L + (1-C) × f × sin(α) × (σ + C × sin(σ) × (cos(2σₘ) + C × cos(σ) × (-1 + 2 × cos²(2σₘ))))
|
|
498
|
+
__m512 cos_2sm_sq_f32x16 = _mm512_mul_ps(cos_double_angular_midpoint_f32x16,
|
|
499
|
+
cos_double_angular_midpoint_f32x16);
|
|
500
|
+
// innermost_f32x16 = -1 + 2 × cos²(2σₘ)
|
|
501
|
+
__m512 innermost_f32x16 = _mm512_fmadd_ps(two_f32x16, cos_2sm_sq_f32x16, _mm512_set1_ps(-1.0f));
|
|
502
|
+
// middle_f32x16 = cos(2σₘ) + C × cos(σ) × innermost_f32x16
|
|
503
|
+
__m512 middle_f32x16 = _mm512_fmadd_ps(_mm512_mul_ps(correction_factor_f32x16, cos_angular_distance_f32x16),
|
|
504
|
+
innermost_f32x16, cos_double_angular_midpoint_f32x16);
|
|
505
|
+
// inner_f32x16 = C × sin(σ) × middle_f32x16
|
|
506
|
+
__m512 inner_f32x16 = _mm512_mul_ps(_mm512_mul_ps(correction_factor_f32x16, sin_angular_distance_f32x16),
|
|
507
|
+
middle_f32x16);
|
|
508
|
+
|
|
509
|
+
// λ' = L + (1-C) * f * sin_α * (σ + inner_f32x16)
|
|
510
|
+
__m512 lambda_new_f32x16 = _mm512_fmadd_ps(
|
|
511
|
+
_mm512_mul_ps(_mm512_mul_ps(_mm512_sub_ps(one_f32x16, correction_factor_f32x16), flattening_f32x16),
|
|
512
|
+
sin_azimuth_f32x16),
|
|
513
|
+
_mm512_add_ps(angular_distance_f32x16, inner_f32x16), longitude_difference_f32x16);
|
|
514
|
+
|
|
515
|
+
// Check convergence: |λ - λ'| < threshold
|
|
516
|
+
__m512 lambda_diff_f32x16 = _mm512_abs_ps(_mm512_sub_ps(lambda_new_f32x16, lambda_f32x16));
|
|
517
|
+
converged_mask = _mm512_cmp_ps_mask(lambda_diff_f32x16, convergence_threshold_f32x16, _CMP_LT_OS);
|
|
518
|
+
|
|
519
|
+
lambda_f32x16 = lambda_new_f32x16;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Final distance calculation
|
|
523
|
+
// u² = cos²α * (a² - b²) / b²
|
|
524
|
+
__m512 a_sq_f32x16 = _mm512_mul_ps(equatorial_radius_f32x16, equatorial_radius_f32x16);
|
|
525
|
+
__m512 b_sq_f32x16 = _mm512_mul_ps(polar_radius_f32x16, polar_radius_f32x16);
|
|
526
|
+
__m512 u_squared_f32x16 = _mm512_div_ps(
|
|
527
|
+
_mm512_mul_ps(cos_squared_azimuth_f32x16, _mm512_sub_ps(a_sq_f32x16, b_sq_f32x16)), b_sq_f32x16);
|
|
528
|
+
|
|
529
|
+
// A = 1 + u²/16384 * (4096 + u²*(-768 + u²*(320 - 175*u²)))
|
|
530
|
+
__m512 series_a_f32x16 = _mm512_fmadd_ps(u_squared_f32x16, _mm512_set1_ps(-175.0f), _mm512_set1_ps(320.0f));
|
|
531
|
+
series_a_f32x16 = _mm512_fmadd_ps(u_squared_f32x16, series_a_f32x16, _mm512_set1_ps(-768.0f));
|
|
532
|
+
series_a_f32x16 = _mm512_fmadd_ps(u_squared_f32x16, series_a_f32x16, _mm512_set1_ps(4096.0f));
|
|
533
|
+
series_a_f32x16 = _mm512_fmadd_ps(_mm512_div_ps(u_squared_f32x16, _mm512_set1_ps(16384.0f)), series_a_f32x16,
|
|
534
|
+
one_f32x16);
|
|
535
|
+
|
|
536
|
+
// B = u²/1024 * (256 + u²*(-128 + u²*(74 - 47*u²)))
|
|
537
|
+
__m512 series_b_f32x16 = _mm512_fmadd_ps(u_squared_f32x16, _mm512_set1_ps(-47.0f), _mm512_set1_ps(74.0f));
|
|
538
|
+
series_b_f32x16 = _mm512_fmadd_ps(u_squared_f32x16, series_b_f32x16, _mm512_set1_ps(-128.0f));
|
|
539
|
+
series_b_f32x16 = _mm512_fmadd_ps(u_squared_f32x16, series_b_f32x16, _mm512_set1_ps(256.0f));
|
|
540
|
+
series_b_f32x16 = _mm512_mul_ps(_mm512_div_ps(u_squared_f32x16, _mm512_set1_ps(1024.0f)), series_b_f32x16);
|
|
541
|
+
|
|
542
|
+
// Δσ = B × sin(σ) × (cos(2σₘ) +
|
|
543
|
+
// B/4 × (cos(σ) × (-1 + 2 × cos²(2σₘ)) - B/6 × cos(2σₘ) × (-3 + 4 × sin²(σ)) × (-3 + 4 × cos²(2σₘ))))
|
|
544
|
+
__m512 cos_2sm_sq_f32x16 = _mm512_mul_ps(cos_double_angular_midpoint_f32x16, cos_double_angular_midpoint_f32x16);
|
|
545
|
+
__m512 sin_sq_f32x16 = _mm512_mul_ps(sin_angular_distance_f32x16, sin_angular_distance_f32x16);
|
|
546
|
+
__m512 term1_f32x16 = _mm512_fmadd_ps(two_f32x16, cos_2sm_sq_f32x16, _mm512_set1_ps(-1.0f));
|
|
547
|
+
term1_f32x16 = _mm512_mul_ps(cos_angular_distance_f32x16, term1_f32x16);
|
|
548
|
+
__m512 term2_f32x16 = _mm512_fmadd_ps(four_f32x16, sin_sq_f32x16, _mm512_set1_ps(-3.0f));
|
|
549
|
+
__m512 term3_f32x16 = _mm512_fmadd_ps(four_f32x16, cos_2sm_sq_f32x16, _mm512_set1_ps(-3.0f));
|
|
550
|
+
term2_f32x16 = _mm512_mul_ps(
|
|
551
|
+
_mm512_mul_ps(_mm512_div_ps(series_b_f32x16, six_f32x16), cos_double_angular_midpoint_f32x16),
|
|
552
|
+
_mm512_mul_ps(term2_f32x16, term3_f32x16));
|
|
553
|
+
__m512 delta_sigma_f32x16 = _mm512_mul_ps(
|
|
554
|
+
series_b_f32x16, _mm512_mul_ps(sin_angular_distance_f32x16,
|
|
555
|
+
_mm512_add_ps(cos_double_angular_midpoint_f32x16,
|
|
556
|
+
_mm512_mul_ps(_mm512_div_ps(series_b_f32x16, four_f32x16),
|
|
557
|
+
_mm512_sub_ps(term1_f32x16, term2_f32x16)))));
|
|
558
|
+
|
|
559
|
+
// s = b * A * (σ - Δσ)
|
|
560
|
+
__m512 distances_f32x16 = _mm512_mul_ps(_mm512_mul_ps(polar_radius_f32x16, series_a_f32x16),
|
|
561
|
+
_mm512_sub_ps(angular_distance_f32x16, delta_sigma_f32x16));
|
|
562
|
+
|
|
563
|
+
// Set coincident points to zero
|
|
564
|
+
distances_f32x16 = _mm512_mask_blend_ps(coincident_mask, distances_f32x16, _mm512_setzero_ps());
|
|
565
|
+
|
|
566
|
+
return distances_f32x16;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
NK_PUBLIC void nk_vincenty_f32_skylake( //
|
|
570
|
+
nk_f32_t const *a_lats, nk_f32_t const *a_lons, //
|
|
571
|
+
nk_f32_t const *b_lats, nk_f32_t const *b_lons, //
|
|
572
|
+
nk_size_t n, nk_f32_t *results) {
|
|
573
|
+
|
|
574
|
+
while (n >= 16) {
|
|
575
|
+
__m512 first_latitudes_f32x16 = _mm512_loadu_ps(a_lats);
|
|
576
|
+
__m512 first_longitudes_f32x16 = _mm512_loadu_ps(a_lons);
|
|
577
|
+
__m512 second_latitudes_f32x16 = _mm512_loadu_ps(b_lats);
|
|
578
|
+
__m512 second_longitudes_f32x16 = _mm512_loadu_ps(b_lons);
|
|
579
|
+
|
|
580
|
+
__m512 distances_f32x16 = nk_vincenty_f32x16_skylake_(first_latitudes_f32x16, first_longitudes_f32x16,
|
|
581
|
+
second_latitudes_f32x16, second_longitudes_f32x16);
|
|
582
|
+
_mm512_storeu_ps(results, distances_f32x16);
|
|
583
|
+
|
|
584
|
+
a_lats += 16, a_lons += 16, b_lats += 16, b_lons += 16, results += 16, n -= 16;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Handle remaining elements with masked operations
|
|
588
|
+
if (n > 0) {
|
|
589
|
+
__mmask16 mask = (__mmask16)_bzhi_u32(0xFFFF, n);
|
|
590
|
+
__m512 first_latitudes_f32x16 = _mm512_maskz_loadu_ps(mask, a_lats);
|
|
591
|
+
__m512 first_longitudes_f32x16 = _mm512_maskz_loadu_ps(mask, a_lons);
|
|
592
|
+
__m512 second_latitudes_f32x16 = _mm512_maskz_loadu_ps(mask, b_lats);
|
|
593
|
+
__m512 second_longitudes_f32x16 = _mm512_maskz_loadu_ps(mask, b_lons);
|
|
594
|
+
|
|
595
|
+
__m512 distances_f32x16 = nk_vincenty_f32x16_skylake_(first_latitudes_f32x16, first_longitudes_f32x16,
|
|
596
|
+
second_latitudes_f32x16, second_longitudes_f32x16);
|
|
597
|
+
_mm512_mask_storeu_ps(results, mask, distances_f32x16);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
#if defined(__clang__)
|
|
602
|
+
#pragma clang attribute pop
|
|
603
|
+
#elif defined(__GNUC__)
|
|
604
|
+
#pragma GCC pop_options
|
|
605
|
+
#endif
|
|
606
|
+
|
|
607
|
+
#if defined(__cplusplus)
|
|
608
|
+
} // extern "C"
|
|
609
|
+
#endif
|
|
610
|
+
|
|
611
|
+
#endif // NK_TARGET_SKYLAKE
|
|
612
|
+
#endif // NK_TARGET_X8664_
|
|
613
|
+
#endif // NK_GEOSPATIAL_SKYLAKE_H
|