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,633 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Geospatial Distances for Haswell.
|
|
3
|
+
* @file include/numkong/geospatial/haswell.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date February 6, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/geospatial.h
|
|
8
|
+
*
|
|
9
|
+
* @section geospatial_haswell_instructions Key AVX2 Geospatial Instructions
|
|
10
|
+
*
|
|
11
|
+
* Intrinsic Instruction Icelake Genoa
|
|
12
|
+
* _mm256_sqrt_ps VSQRTPS (YMM, YMM) 12cy @ p0 15cy @ p01
|
|
13
|
+
* _mm256_sqrt_pd VSQRTPD (YMM, YMM) 13cy @ p0 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
|
+
* _mm256_cmp_ps VCMPPS (YMM, YMM, YMM, I8) 3cy @ p01 3cy @ p01
|
|
19
|
+
*/
|
|
20
|
+
#ifndef NK_GEOSPATIAL_HASWELL_H
|
|
21
|
+
#define NK_GEOSPATIAL_HASWELL_H
|
|
22
|
+
|
|
23
|
+
#if NK_TARGET_X8664_
|
|
24
|
+
#if NK_TARGET_HASWELL
|
|
25
|
+
|
|
26
|
+
#include "numkong/types.h"
|
|
27
|
+
#include "numkong/trigonometry/haswell.h" // `nk_sin_f64x4_haswell_`, `nk_cos_f64x4_haswell_`, `nk_atan2_f64x4_haswell_`
|
|
28
|
+
|
|
29
|
+
#if defined(__cplusplus)
|
|
30
|
+
extern "C" {
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
#if defined(__clang__)
|
|
34
|
+
#pragma clang attribute push(__attribute__((target("avx2,f16c,fma,bmi,bmi2"))), apply_to = function)
|
|
35
|
+
#elif defined(__GNUC__)
|
|
36
|
+
#pragma GCC push_options
|
|
37
|
+
#pragma GCC target("avx2", "f16c", "fma", "bmi", "bmi2")
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
/* Haswell AVX2 implementations using 4-wide f64 and 8-wide f32 SIMD.
|
|
41
|
+
* These require AVX2 trigonometric kernels from trigonometry.h.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
NK_INTERNAL __m256d nk_haversine_f64x4_haswell_( //
|
|
45
|
+
__m256d first_latitudes_f64x4, __m256d first_longitudes_f64x4, //
|
|
46
|
+
__m256d second_latitudes_f64x4, __m256d second_longitudes_f64x4) {
|
|
47
|
+
|
|
48
|
+
__m256d const earth_radius_f64x4 = _mm256_set1_pd(NK_EARTH_MEDIATORIAL_RADIUS);
|
|
49
|
+
__m256d const half_f64x4 = _mm256_set1_pd(0.5);
|
|
50
|
+
__m256d const one_f64x4 = _mm256_set1_pd(1.0);
|
|
51
|
+
__m256d const two_f64x4 = _mm256_set1_pd(2.0);
|
|
52
|
+
|
|
53
|
+
__m256d latitude_delta_f64x4 = _mm256_sub_pd(second_latitudes_f64x4, first_latitudes_f64x4);
|
|
54
|
+
__m256d longitude_delta_f64x4 = _mm256_sub_pd(second_longitudes_f64x4, first_longitudes_f64x4);
|
|
55
|
+
|
|
56
|
+
// Haversine terms: sin²(Δ/2)
|
|
57
|
+
__m256d latitude_delta_half_f64x4 = _mm256_mul_pd(latitude_delta_f64x4, half_f64x4);
|
|
58
|
+
__m256d longitude_delta_half_f64x4 = _mm256_mul_pd(longitude_delta_f64x4, half_f64x4);
|
|
59
|
+
__m256d sin_latitude_delta_half_f64x4 = nk_sin_f64x4_haswell_(latitude_delta_half_f64x4);
|
|
60
|
+
__m256d sin_longitude_delta_half_f64x4 = nk_sin_f64x4_haswell_(longitude_delta_half_f64x4);
|
|
61
|
+
__m256d sin_squared_latitude_delta_half_f64x4 = _mm256_mul_pd(sin_latitude_delta_half_f64x4,
|
|
62
|
+
sin_latitude_delta_half_f64x4);
|
|
63
|
+
__m256d sin_squared_longitude_delta_half_f64x4 = _mm256_mul_pd(sin_longitude_delta_half_f64x4,
|
|
64
|
+
sin_longitude_delta_half_f64x4);
|
|
65
|
+
|
|
66
|
+
// Latitude cosine product
|
|
67
|
+
__m256d cos_first_latitude_f64x4 = nk_cos_f64x4_haswell_(first_latitudes_f64x4);
|
|
68
|
+
__m256d cos_second_latitude_f64x4 = nk_cos_f64x4_haswell_(second_latitudes_f64x4);
|
|
69
|
+
__m256d cos_latitude_product_f64x4 = _mm256_mul_pd(cos_first_latitude_f64x4, cos_second_latitude_f64x4);
|
|
70
|
+
|
|
71
|
+
// a = sin²(Δlat/2) + cos(lat1) × cos(lat2) × sin²(Δlon/2)
|
|
72
|
+
__m256d haversine_term_f64x4 = _mm256_add_pd(
|
|
73
|
+
sin_squared_latitude_delta_half_f64x4,
|
|
74
|
+
_mm256_mul_pd(cos_latitude_product_f64x4, sin_squared_longitude_delta_half_f64x4));
|
|
75
|
+
// Clamp haversine_term_f64x4 to [0, 1] to prevent NaN from sqrt of negative values
|
|
76
|
+
__m256d zero_f64x4 = _mm256_setzero_pd();
|
|
77
|
+
haversine_term_f64x4 = _mm256_max_pd(zero_f64x4, _mm256_min_pd(one_f64x4, haversine_term_f64x4));
|
|
78
|
+
|
|
79
|
+
// Central angle: c = 2 × atan2(√a, √(1-a))
|
|
80
|
+
__m256d sqrt_haversine_f64x4 = _mm256_sqrt_pd(haversine_term_f64x4);
|
|
81
|
+
__m256d sqrt_complement_f64x4 = _mm256_sqrt_pd(_mm256_sub_pd(one_f64x4, haversine_term_f64x4));
|
|
82
|
+
__m256d central_angle_f64x4 = _mm256_mul_pd(two_f64x4,
|
|
83
|
+
nk_atan2_f64x4_haswell_(sqrt_haversine_f64x4, sqrt_complement_f64x4));
|
|
84
|
+
|
|
85
|
+
return _mm256_mul_pd(earth_radius_f64x4, central_angle_f64x4);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
NK_PUBLIC void nk_haversine_f64_haswell( //
|
|
89
|
+
nk_f64_t const *a_lats, nk_f64_t const *a_lons, //
|
|
90
|
+
nk_f64_t const *b_lats, nk_f64_t const *b_lons, //
|
|
91
|
+
nk_size_t n, nk_f64_t *results) {
|
|
92
|
+
|
|
93
|
+
while (n >= 4) {
|
|
94
|
+
__m256d first_latitudes_f64x4 = _mm256_loadu_pd(a_lats);
|
|
95
|
+
__m256d first_longitudes_f64x4 = _mm256_loadu_pd(a_lons);
|
|
96
|
+
__m256d second_latitudes_f64x4 = _mm256_loadu_pd(b_lats);
|
|
97
|
+
__m256d second_longitudes_f64x4 = _mm256_loadu_pd(b_lons);
|
|
98
|
+
|
|
99
|
+
__m256d distances_f64x4 = nk_haversine_f64x4_haswell_(first_latitudes_f64x4, first_longitudes_f64x4,
|
|
100
|
+
second_latitudes_f64x4, second_longitudes_f64x4);
|
|
101
|
+
_mm256_storeu_pd(results, distances_f64x4);
|
|
102
|
+
|
|
103
|
+
a_lats += 4, a_lons += 4, b_lats += 4, b_lons += 4, results += 4, n -= 4;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Handle remaining elements with partial loads (n can be 1-3 here)
|
|
107
|
+
if (n > 0) {
|
|
108
|
+
nk_b256_vec_t a_lat_vec, a_lon_vec, b_lat_vec, b_lon_vec, result_vec;
|
|
109
|
+
nk_partial_load_b64x4_haswell_(a_lats, &a_lat_vec, n);
|
|
110
|
+
nk_partial_load_b64x4_haswell_(a_lons, &a_lon_vec, n);
|
|
111
|
+
nk_partial_load_b64x4_haswell_(b_lats, &b_lat_vec, n);
|
|
112
|
+
nk_partial_load_b64x4_haswell_(b_lons, &b_lon_vec, n);
|
|
113
|
+
__m256d distances_f64x4 = nk_haversine_f64x4_haswell_(a_lat_vec.ymm_pd, a_lon_vec.ymm_pd, b_lat_vec.ymm_pd,
|
|
114
|
+
b_lon_vec.ymm_pd);
|
|
115
|
+
result_vec.ymm_pd = distances_f64x4;
|
|
116
|
+
nk_partial_store_b64x4_haswell_(&result_vec, results, n);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
NK_INTERNAL __m256 nk_haversine_f32x8_haswell_( //
|
|
121
|
+
__m256 first_latitudes_f32x8, __m256 first_longitudes_f32x8, //
|
|
122
|
+
__m256 second_latitudes_f32x8, __m256 second_longitudes_f32x8) {
|
|
123
|
+
|
|
124
|
+
__m256 const earth_radius_f32x8 = _mm256_set1_ps((float)NK_EARTH_MEDIATORIAL_RADIUS);
|
|
125
|
+
__m256 const half_f32x8 = _mm256_set1_ps(0.5f);
|
|
126
|
+
__m256 const one_f32x8 = _mm256_set1_ps(1.0f);
|
|
127
|
+
__m256 const two_f32x8 = _mm256_set1_ps(2.0f);
|
|
128
|
+
|
|
129
|
+
__m256 latitude_delta_f32x8 = _mm256_sub_ps(second_latitudes_f32x8, first_latitudes_f32x8);
|
|
130
|
+
__m256 longitude_delta_f32x8 = _mm256_sub_ps(second_longitudes_f32x8, first_longitudes_f32x8);
|
|
131
|
+
|
|
132
|
+
// Haversine terms: sin²(Δ/2)
|
|
133
|
+
__m256 latitude_delta_half_f32x8 = _mm256_mul_ps(latitude_delta_f32x8, half_f32x8);
|
|
134
|
+
__m256 longitude_delta_half_f32x8 = _mm256_mul_ps(longitude_delta_f32x8, half_f32x8);
|
|
135
|
+
__m256 sin_latitude_delta_half_f32x8 = nk_sin_f32x8_haswell_(latitude_delta_half_f32x8);
|
|
136
|
+
__m256 sin_longitude_delta_half_f32x8 = nk_sin_f32x8_haswell_(longitude_delta_half_f32x8);
|
|
137
|
+
__m256 sin_squared_latitude_delta_half_f32x8 = _mm256_mul_ps(sin_latitude_delta_half_f32x8,
|
|
138
|
+
sin_latitude_delta_half_f32x8);
|
|
139
|
+
__m256 sin_squared_longitude_delta_half_f32x8 = _mm256_mul_ps(sin_longitude_delta_half_f32x8,
|
|
140
|
+
sin_longitude_delta_half_f32x8);
|
|
141
|
+
|
|
142
|
+
// Latitude cosine product
|
|
143
|
+
__m256 cos_first_latitude_f32x8 = nk_cos_f32x8_haswell_(first_latitudes_f32x8);
|
|
144
|
+
__m256 cos_second_latitude_f32x8 = nk_cos_f32x8_haswell_(second_latitudes_f32x8);
|
|
145
|
+
__m256 cos_latitude_product_f32x8 = _mm256_mul_ps(cos_first_latitude_f32x8, cos_second_latitude_f32x8);
|
|
146
|
+
|
|
147
|
+
// a = sin²(Δlat/2) + cos(lat1) × cos(lat2) × sin²(Δlon/2)
|
|
148
|
+
__m256 haversine_term_f32x8 = _mm256_add_ps(
|
|
149
|
+
sin_squared_latitude_delta_half_f32x8,
|
|
150
|
+
_mm256_mul_ps(cos_latitude_product_f32x8, sin_squared_longitude_delta_half_f32x8));
|
|
151
|
+
|
|
152
|
+
// Clamp to [0, 1] to avoid NaN from sqrt of negative numbers (due to floating point errors)
|
|
153
|
+
__m256 zero_f32x8 = _mm256_setzero_ps();
|
|
154
|
+
haversine_term_f32x8 = _mm256_max_ps(zero_f32x8, _mm256_min_ps(one_f32x8, haversine_term_f32x8));
|
|
155
|
+
|
|
156
|
+
// Central angle: c = 2 × atan2(√a, √(1-a))
|
|
157
|
+
__m256 sqrt_haversine_f32x8 = _mm256_sqrt_ps(haversine_term_f32x8);
|
|
158
|
+
__m256 sqrt_complement_f32x8 = _mm256_sqrt_ps(_mm256_sub_ps(one_f32x8, haversine_term_f32x8));
|
|
159
|
+
__m256 central_angle_f32x8 = _mm256_mul_ps(two_f32x8,
|
|
160
|
+
nk_atan2_f32x8_haswell_(sqrt_haversine_f32x8, sqrt_complement_f32x8));
|
|
161
|
+
|
|
162
|
+
return _mm256_mul_ps(earth_radius_f32x8, central_angle_f32x8);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
NK_PUBLIC void nk_haversine_f32_haswell( //
|
|
166
|
+
nk_f32_t const *a_lats, nk_f32_t const *a_lons, //
|
|
167
|
+
nk_f32_t const *b_lats, nk_f32_t const *b_lons, //
|
|
168
|
+
nk_size_t n, nk_f32_t *results) {
|
|
169
|
+
|
|
170
|
+
while (n >= 8) {
|
|
171
|
+
__m256 first_latitudes_f32x8 = _mm256_loadu_ps(a_lats);
|
|
172
|
+
__m256 first_longitudes_f32x8 = _mm256_loadu_ps(a_lons);
|
|
173
|
+
__m256 second_latitudes_f32x8 = _mm256_loadu_ps(b_lats);
|
|
174
|
+
__m256 second_longitudes_f32x8 = _mm256_loadu_ps(b_lons);
|
|
175
|
+
|
|
176
|
+
__m256 distances_f32x8 = nk_haversine_f32x8_haswell_(first_latitudes_f32x8, first_longitudes_f32x8,
|
|
177
|
+
second_latitudes_f32x8, second_longitudes_f32x8);
|
|
178
|
+
_mm256_storeu_ps(results, distances_f32x8);
|
|
179
|
+
|
|
180
|
+
a_lats += 8, a_lons += 8, b_lats += 8, b_lons += 8, results += 8, n -= 8;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Handle remaining elements with partial loads (n can be 1-7 here)
|
|
184
|
+
if (n > 0) {
|
|
185
|
+
nk_b256_vec_t a_lat_vec, a_lon_vec, b_lat_vec, b_lon_vec, result_vec;
|
|
186
|
+
nk_partial_load_b32x8_serial_(a_lats, &a_lat_vec, n);
|
|
187
|
+
nk_partial_load_b32x8_serial_(a_lons, &a_lon_vec, n);
|
|
188
|
+
nk_partial_load_b32x8_serial_(b_lats, &b_lat_vec, n);
|
|
189
|
+
nk_partial_load_b32x8_serial_(b_lons, &b_lon_vec, n);
|
|
190
|
+
__m256 distances_f32x8 = nk_haversine_f32x8_haswell_(a_lat_vec.ymm_ps, a_lon_vec.ymm_ps, b_lat_vec.ymm_ps,
|
|
191
|
+
b_lon_vec.ymm_ps);
|
|
192
|
+
result_vec.ymm_ps = distances_f32x8;
|
|
193
|
+
nk_partial_store_b32x8_serial_(&result_vec, results, n);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @brief AVX2 helper for Vincenty's geodesic distance on 4 f64 point pairs.
|
|
199
|
+
* @note This is a true SIMD implementation using masked convergence tracking via blending.
|
|
200
|
+
*/
|
|
201
|
+
NK_INTERNAL __m256d nk_vincenty_f64x4_haswell_( //
|
|
202
|
+
__m256d first_latitudes_f64x4, __m256d first_longitudes_f64x4, //
|
|
203
|
+
__m256d second_latitudes_f64x4, __m256d second_longitudes_f64x4) {
|
|
204
|
+
|
|
205
|
+
__m256d const equatorial_radius_f64x4 = _mm256_set1_pd(NK_EARTH_ELLIPSOID_EQUATORIAL_RADIUS);
|
|
206
|
+
__m256d const polar_radius_f64x4 = _mm256_set1_pd(NK_EARTH_ELLIPSOID_POLAR_RADIUS);
|
|
207
|
+
__m256d const flattening_f64x4 = _mm256_set1_pd(1.0 / NK_EARTH_ELLIPSOID_INVERSE_FLATTENING);
|
|
208
|
+
__m256d const convergence_threshold_f64x4 = _mm256_set1_pd(NK_VINCENTY_CONVERGENCE_THRESHOLD_F64);
|
|
209
|
+
__m256d const one_f64x4 = _mm256_set1_pd(1.0);
|
|
210
|
+
__m256d const two_f64x4 = _mm256_set1_pd(2.0);
|
|
211
|
+
__m256d const three_f64x4 = _mm256_set1_pd(3.0);
|
|
212
|
+
__m256d const four_f64x4 = _mm256_set1_pd(4.0);
|
|
213
|
+
__m256d const six_f64x4 = _mm256_set1_pd(6.0);
|
|
214
|
+
__m256d const sixteen_f64x4 = _mm256_set1_pd(16.0);
|
|
215
|
+
__m256d const epsilon_f64x4 = _mm256_set1_pd(1e-15);
|
|
216
|
+
|
|
217
|
+
// Longitude difference
|
|
218
|
+
__m256d longitude_difference_f64x4 = _mm256_sub_pd(second_longitudes_f64x4, first_longitudes_f64x4);
|
|
219
|
+
|
|
220
|
+
// Reduced latitudes: tan(U) = (1-f) * tan(lat)
|
|
221
|
+
__m256d one_minus_f_f64x4 = _mm256_sub_pd(one_f64x4, flattening_f64x4);
|
|
222
|
+
__m256d tan_first_f64x4 = _mm256_div_pd(nk_sin_f64x4_haswell_(first_latitudes_f64x4),
|
|
223
|
+
nk_cos_f64x4_haswell_(first_latitudes_f64x4));
|
|
224
|
+
__m256d tan_second_f64x4 = _mm256_div_pd(nk_sin_f64x4_haswell_(second_latitudes_f64x4),
|
|
225
|
+
nk_cos_f64x4_haswell_(second_latitudes_f64x4));
|
|
226
|
+
__m256d tan_reduced_first_f64x4 = _mm256_mul_pd(one_minus_f_f64x4, tan_first_f64x4);
|
|
227
|
+
__m256d tan_reduced_second_f64x4 = _mm256_mul_pd(one_minus_f_f64x4, tan_second_f64x4);
|
|
228
|
+
|
|
229
|
+
// cos(U) = 1/√(1 + tan²(U)), sin(U) = tan(U) × cos(U)
|
|
230
|
+
__m256d cos_reduced_first_f64x4 = _mm256_div_pd(
|
|
231
|
+
one_f64x4, _mm256_sqrt_pd(_mm256_fmadd_pd(tan_reduced_first_f64x4, tan_reduced_first_f64x4, one_f64x4)));
|
|
232
|
+
__m256d sin_reduced_first_f64x4 = _mm256_mul_pd(tan_reduced_first_f64x4, cos_reduced_first_f64x4);
|
|
233
|
+
__m256d cos_reduced_second_f64x4 = _mm256_div_pd(
|
|
234
|
+
one_f64x4, _mm256_sqrt_pd(_mm256_fmadd_pd(tan_reduced_second_f64x4, tan_reduced_second_f64x4, one_f64x4)));
|
|
235
|
+
__m256d sin_reduced_second_f64x4 = _mm256_mul_pd(tan_reduced_second_f64x4, cos_reduced_second_f64x4);
|
|
236
|
+
|
|
237
|
+
// Initialize lambda_f64x4 and tracking variables
|
|
238
|
+
__m256d lambda_f64x4 = longitude_difference_f64x4;
|
|
239
|
+
__m256d sin_angular_distance_f64x4, cos_angular_distance_f64x4, angular_distance_f64x4;
|
|
240
|
+
__m256d sin_azimuth_f64x4, cos_squared_azimuth_f64x4, cos_double_angular_midpoint_f64x4;
|
|
241
|
+
|
|
242
|
+
// Track convergence and coincident points using masks
|
|
243
|
+
__m256d converged_mask_f64x4 = _mm256_setzero_pd();
|
|
244
|
+
__m256d coincident_mask_f64x4 = _mm256_setzero_pd();
|
|
245
|
+
|
|
246
|
+
for (nk_u32_t iteration = 0; iteration < NK_VINCENTY_MAX_ITERATIONS; ++iteration) {
|
|
247
|
+
// Check if all lanes converged
|
|
248
|
+
int converged_bits = _mm256_movemask_pd(converged_mask_f64x4);
|
|
249
|
+
if (converged_bits == 0xF) break;
|
|
250
|
+
|
|
251
|
+
__m256d sin_lambda_f64x4 = nk_sin_f64x4_haswell_(lambda_f64x4);
|
|
252
|
+
__m256d cos_lambda_f64x4 = nk_cos_f64x4_haswell_(lambda_f64x4);
|
|
253
|
+
|
|
254
|
+
// sin²(angular_distance_f64x4) = (cos(U₂) × sin(λ))² + (cos(U₁) × sin(U₂) - sin(U₁) × cos(U₂) × cos(λ))²
|
|
255
|
+
__m256d cross_term_f64x4 = _mm256_mul_pd(cos_reduced_second_f64x4, sin_lambda_f64x4);
|
|
256
|
+
__m256d mixed_term_f64x4 = _mm256_sub_pd(
|
|
257
|
+
_mm256_mul_pd(cos_reduced_first_f64x4, sin_reduced_second_f64x4),
|
|
258
|
+
_mm256_mul_pd(_mm256_mul_pd(sin_reduced_first_f64x4, cos_reduced_second_f64x4), cos_lambda_f64x4));
|
|
259
|
+
__m256d sin_angular_dist_sq_f64x4 = _mm256_fmadd_pd(cross_term_f64x4, cross_term_f64x4,
|
|
260
|
+
_mm256_mul_pd(mixed_term_f64x4, mixed_term_f64x4));
|
|
261
|
+
sin_angular_distance_f64x4 = _mm256_sqrt_pd(sin_angular_dist_sq_f64x4);
|
|
262
|
+
|
|
263
|
+
// Check for coincident points (sin_angular_distance_f64x4 ≈ 0)
|
|
264
|
+
coincident_mask_f64x4 = _mm256_cmp_pd(sin_angular_distance_f64x4, epsilon_f64x4, _CMP_LT_OS);
|
|
265
|
+
|
|
266
|
+
// cos(angular_distance_f64x4) = sin(U₁) × sin(U₂) + cos(U₁) × cos(U₂) × cos(λ)
|
|
267
|
+
cos_angular_distance_f64x4 = _mm256_fmadd_pd(_mm256_mul_pd(cos_reduced_first_f64x4, cos_reduced_second_f64x4),
|
|
268
|
+
cos_lambda_f64x4,
|
|
269
|
+
_mm256_mul_pd(sin_reduced_first_f64x4, sin_reduced_second_f64x4));
|
|
270
|
+
|
|
271
|
+
// angular_distance_f64x4 = atan2(sin, cos)
|
|
272
|
+
angular_distance_f64x4 = nk_atan2_f64x4_haswell_(sin_angular_distance_f64x4, cos_angular_distance_f64x4);
|
|
273
|
+
|
|
274
|
+
// sin(azimuth) = cos(U₁) × cos(U₂) × sin(λ) / sin(angular_distance_f64x4)
|
|
275
|
+
// Avoid division by zero by using blending
|
|
276
|
+
__m256d safe_sin_angular_f64x4 = _mm256_blendv_pd(sin_angular_distance_f64x4, one_f64x4, coincident_mask_f64x4);
|
|
277
|
+
sin_azimuth_f64x4 = _mm256_div_pd(
|
|
278
|
+
_mm256_mul_pd(_mm256_mul_pd(cos_reduced_first_f64x4, cos_reduced_second_f64x4), sin_lambda_f64x4),
|
|
279
|
+
safe_sin_angular_f64x4);
|
|
280
|
+
cos_squared_azimuth_f64x4 = _mm256_sub_pd(one_f64x4, _mm256_mul_pd(sin_azimuth_f64x4, sin_azimuth_f64x4));
|
|
281
|
+
|
|
282
|
+
// Handle equatorial case: cos²α ≈ 0
|
|
283
|
+
__m256d equatorial_mask_f64x4 = _mm256_cmp_pd(cos_squared_azimuth_f64x4, epsilon_f64x4, _CMP_LT_OS);
|
|
284
|
+
__m256d safe_cos_sq_azimuth_f64x4 = _mm256_blendv_pd(cos_squared_azimuth_f64x4, one_f64x4,
|
|
285
|
+
equatorial_mask_f64x4);
|
|
286
|
+
|
|
287
|
+
// cos(2σₘ) = cos(σ) - 2 × sin(U₁) × sin(U₂) / cos²(α)
|
|
288
|
+
__m256d sin_product_f64x4 = _mm256_mul_pd(sin_reduced_first_f64x4, sin_reduced_second_f64x4);
|
|
289
|
+
cos_double_angular_midpoint_f64x4 = _mm256_sub_pd(
|
|
290
|
+
cos_angular_distance_f64x4,
|
|
291
|
+
_mm256_div_pd(_mm256_mul_pd(two_f64x4, sin_product_f64x4), safe_cos_sq_azimuth_f64x4));
|
|
292
|
+
cos_double_angular_midpoint_f64x4 = _mm256_blendv_pd(cos_double_angular_midpoint_f64x4, _mm256_setzero_pd(),
|
|
293
|
+
equatorial_mask_f64x4);
|
|
294
|
+
|
|
295
|
+
// C = f/16 * cos²α * (4 + f*(4 - 3*cos²α))
|
|
296
|
+
__m256d correction_factor_f64x4 = _mm256_mul_pd(
|
|
297
|
+
_mm256_div_pd(flattening_f64x4, sixteen_f64x4),
|
|
298
|
+
_mm256_mul_pd(
|
|
299
|
+
cos_squared_azimuth_f64x4,
|
|
300
|
+
_mm256_fmadd_pd(flattening_f64x4, _mm256_fnmadd_pd(three_f64x4, cos_squared_azimuth_f64x4, four_f64x4),
|
|
301
|
+
four_f64x4)));
|
|
302
|
+
|
|
303
|
+
// λ' = L + (1-C) × f × sin(α) × (σ + C × sin(σ) × (cos(2σₘ) + C × cos(σ) × (-1 + 2 × cos²(2σₘ))))
|
|
304
|
+
__m256d cos_2sm_sq_f64x4 = _mm256_mul_pd(cos_double_angular_midpoint_f64x4, cos_double_angular_midpoint_f64x4);
|
|
305
|
+
// innermost_f64x4 = -1 + 2 × cos²(2σₘ)
|
|
306
|
+
__m256d innermost_f64x4 = _mm256_fmadd_pd(two_f64x4, cos_2sm_sq_f64x4, _mm256_set1_pd(-1.0));
|
|
307
|
+
// middle_f64x4 = cos(2σₘ) + C × cos(σ) × innermost_f64x4
|
|
308
|
+
__m256d middle_f64x4 = _mm256_fmadd_pd(_mm256_mul_pd(correction_factor_f64x4, cos_angular_distance_f64x4),
|
|
309
|
+
innermost_f64x4, cos_double_angular_midpoint_f64x4);
|
|
310
|
+
// inner_f64x4 = C × sin(σ) × middle_f64x4
|
|
311
|
+
__m256d inner_f64x4 = _mm256_mul_pd(_mm256_mul_pd(correction_factor_f64x4, sin_angular_distance_f64x4),
|
|
312
|
+
middle_f64x4);
|
|
313
|
+
|
|
314
|
+
// λ' = L + (1-C) * f * sin_α * (σ + inner_f64x4)
|
|
315
|
+
__m256d lambda_new_f64x4 = _mm256_fmadd_pd(
|
|
316
|
+
_mm256_mul_pd(_mm256_mul_pd(_mm256_sub_pd(one_f64x4, correction_factor_f64x4), flattening_f64x4),
|
|
317
|
+
sin_azimuth_f64x4),
|
|
318
|
+
_mm256_add_pd(angular_distance_f64x4, inner_f64x4), longitude_difference_f64x4);
|
|
319
|
+
|
|
320
|
+
// Check convergence: |λ - λ'| < threshold
|
|
321
|
+
__m256d lambda_diff_abs_f64x4 = _mm256_andnot_pd(_mm256_set1_pd(-0.0),
|
|
322
|
+
_mm256_sub_pd(lambda_new_f64x4, lambda_f64x4));
|
|
323
|
+
__m256d newly_converged_f64x4 = _mm256_cmp_pd(lambda_diff_abs_f64x4, convergence_threshold_f64x4, _CMP_LT_OS);
|
|
324
|
+
converged_mask_f64x4 = _mm256_or_pd(converged_mask_f64x4, newly_converged_f64x4);
|
|
325
|
+
|
|
326
|
+
// Only update lambda_f64x4 for non-converged lanes
|
|
327
|
+
lambda_f64x4 = _mm256_blendv_pd(lambda_new_f64x4, lambda_f64x4, converged_mask_f64x4);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Final distance calculation
|
|
331
|
+
// u² = cos²α * (a² - b²) / b²
|
|
332
|
+
__m256d a_sq_f64x4 = _mm256_mul_pd(equatorial_radius_f64x4, equatorial_radius_f64x4);
|
|
333
|
+
__m256d b_sq_f64x4 = _mm256_mul_pd(polar_radius_f64x4, polar_radius_f64x4);
|
|
334
|
+
__m256d u_squared_f64x4 = _mm256_div_pd(
|
|
335
|
+
_mm256_mul_pd(cos_squared_azimuth_f64x4, _mm256_sub_pd(a_sq_f64x4, b_sq_f64x4)), b_sq_f64x4);
|
|
336
|
+
|
|
337
|
+
// A = 1 + u²/16384 * (4096 + u²*(-768 + u²*(320 - 175*u²)))
|
|
338
|
+
__m256d series_a_f64x4 = _mm256_fmadd_pd(u_squared_f64x4, _mm256_set1_pd(-175.0), _mm256_set1_pd(320.0));
|
|
339
|
+
series_a_f64x4 = _mm256_fmadd_pd(u_squared_f64x4, series_a_f64x4, _mm256_set1_pd(-768.0));
|
|
340
|
+
series_a_f64x4 = _mm256_fmadd_pd(u_squared_f64x4, series_a_f64x4, _mm256_set1_pd(4096.0));
|
|
341
|
+
series_a_f64x4 = _mm256_fmadd_pd(_mm256_div_pd(u_squared_f64x4, _mm256_set1_pd(16384.0)), series_a_f64x4,
|
|
342
|
+
one_f64x4);
|
|
343
|
+
|
|
344
|
+
// B = u²/1024 * (256 + u²*(-128 + u²*(74 - 47*u²)))
|
|
345
|
+
__m256d series_b_f64x4 = _mm256_fmadd_pd(u_squared_f64x4, _mm256_set1_pd(-47.0), _mm256_set1_pd(74.0));
|
|
346
|
+
series_b_f64x4 = _mm256_fmadd_pd(u_squared_f64x4, series_b_f64x4, _mm256_set1_pd(-128.0));
|
|
347
|
+
series_b_f64x4 = _mm256_fmadd_pd(u_squared_f64x4, series_b_f64x4, _mm256_set1_pd(256.0));
|
|
348
|
+
series_b_f64x4 = _mm256_mul_pd(_mm256_div_pd(u_squared_f64x4, _mm256_set1_pd(1024.0)), series_b_f64x4);
|
|
349
|
+
|
|
350
|
+
// Δσ = B × sin(σ) × (cos(2σₘ) +
|
|
351
|
+
// B/4 × (cos(σ) × (-1 + 2 × cos²(2σₘ)) - B/6 × cos(2σₘ) × (-3 + 4 × sin²(σ)) × (-3 + 4 × cos²(2σₘ))))
|
|
352
|
+
__m256d cos_2sm_sq_f64x4 = _mm256_mul_pd(cos_double_angular_midpoint_f64x4, cos_double_angular_midpoint_f64x4);
|
|
353
|
+
__m256d sin_sq_f64x4 = _mm256_mul_pd(sin_angular_distance_f64x4, sin_angular_distance_f64x4);
|
|
354
|
+
__m256d term1_f64x4 = _mm256_fmadd_pd(two_f64x4, cos_2sm_sq_f64x4, _mm256_set1_pd(-1.0));
|
|
355
|
+
term1_f64x4 = _mm256_mul_pd(cos_angular_distance_f64x4, term1_f64x4);
|
|
356
|
+
__m256d term2_f64x4 = _mm256_fmadd_pd(four_f64x4, sin_sq_f64x4, _mm256_set1_pd(-3.0));
|
|
357
|
+
__m256d term3_f64x4 = _mm256_fmadd_pd(four_f64x4, cos_2sm_sq_f64x4, _mm256_set1_pd(-3.0));
|
|
358
|
+
term2_f64x4 = _mm256_mul_pd(
|
|
359
|
+
_mm256_mul_pd(_mm256_div_pd(series_b_f64x4, six_f64x4), cos_double_angular_midpoint_f64x4),
|
|
360
|
+
_mm256_mul_pd(term2_f64x4, term3_f64x4));
|
|
361
|
+
__m256d delta_sigma_f64x4 = _mm256_mul_pd(
|
|
362
|
+
series_b_f64x4, _mm256_mul_pd(sin_angular_distance_f64x4,
|
|
363
|
+
_mm256_add_pd(cos_double_angular_midpoint_f64x4,
|
|
364
|
+
_mm256_mul_pd(_mm256_div_pd(series_b_f64x4, four_f64x4),
|
|
365
|
+
_mm256_sub_pd(term1_f64x4, term2_f64x4)))));
|
|
366
|
+
|
|
367
|
+
// s = b * A * (σ - Δσ)
|
|
368
|
+
__m256d distances_f64x4 = _mm256_mul_pd(_mm256_mul_pd(polar_radius_f64x4, series_a_f64x4),
|
|
369
|
+
_mm256_sub_pd(angular_distance_f64x4, delta_sigma_f64x4));
|
|
370
|
+
|
|
371
|
+
// Set coincident points to zero
|
|
372
|
+
distances_f64x4 = _mm256_blendv_pd(distances_f64x4, _mm256_setzero_pd(), coincident_mask_f64x4);
|
|
373
|
+
|
|
374
|
+
return distances_f64x4;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
NK_PUBLIC void nk_vincenty_f64_haswell( //
|
|
378
|
+
nk_f64_t const *a_lats, nk_f64_t const *a_lons, //
|
|
379
|
+
nk_f64_t const *b_lats, nk_f64_t const *b_lons, //
|
|
380
|
+
nk_size_t n, nk_f64_t *results) {
|
|
381
|
+
|
|
382
|
+
while (n >= 4) {
|
|
383
|
+
__m256d first_latitudes_f64x4 = _mm256_loadu_pd(a_lats);
|
|
384
|
+
__m256d first_longitudes_f64x4 = _mm256_loadu_pd(a_lons);
|
|
385
|
+
__m256d second_latitudes_f64x4 = _mm256_loadu_pd(b_lats);
|
|
386
|
+
__m256d second_longitudes_f64x4 = _mm256_loadu_pd(b_lons);
|
|
387
|
+
|
|
388
|
+
__m256d distances_f64x4 = nk_vincenty_f64x4_haswell_(first_latitudes_f64x4, first_longitudes_f64x4,
|
|
389
|
+
second_latitudes_f64x4, second_longitudes_f64x4);
|
|
390
|
+
_mm256_storeu_pd(results, distances_f64x4);
|
|
391
|
+
|
|
392
|
+
a_lats += 4, a_lons += 4, b_lats += 4, b_lons += 4, results += 4, n -= 4;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Handle remaining elements with partial loads (n can be 1-3 here)
|
|
396
|
+
if (n > 0) {
|
|
397
|
+
nk_b256_vec_t a_lat_vec, a_lon_vec, b_lat_vec, b_lon_vec, result_vec;
|
|
398
|
+
nk_partial_load_b64x4_haswell_(a_lats, &a_lat_vec, n);
|
|
399
|
+
nk_partial_load_b64x4_haswell_(a_lons, &a_lon_vec, n);
|
|
400
|
+
nk_partial_load_b64x4_haswell_(b_lats, &b_lat_vec, n);
|
|
401
|
+
nk_partial_load_b64x4_haswell_(b_lons, &b_lon_vec, n);
|
|
402
|
+
__m256d distances_f64x4 = nk_vincenty_f64x4_haswell_(a_lat_vec.ymm_pd, a_lon_vec.ymm_pd, b_lat_vec.ymm_pd,
|
|
403
|
+
b_lon_vec.ymm_pd);
|
|
404
|
+
result_vec.ymm_pd = distances_f64x4;
|
|
405
|
+
nk_partial_store_b64x4_haswell_(&result_vec, results, n);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @brief AVX2 helper for Vincenty's geodesic distance on 8 f32 point pairs.
|
|
411
|
+
* @note This is a true SIMD implementation using masked convergence tracking via blending.
|
|
412
|
+
*/
|
|
413
|
+
NK_INTERNAL __m256 nk_vincenty_f32x8_haswell_( //
|
|
414
|
+
__m256 first_latitudes_f32x8, __m256 first_longitudes_f32x8, //
|
|
415
|
+
__m256 second_latitudes_f32x8, __m256 second_longitudes_f32x8) {
|
|
416
|
+
|
|
417
|
+
__m256 const equatorial_radius_f32x8 = _mm256_set1_ps((float)NK_EARTH_ELLIPSOID_EQUATORIAL_RADIUS);
|
|
418
|
+
__m256 const polar_radius_f32x8 = _mm256_set1_ps((float)NK_EARTH_ELLIPSOID_POLAR_RADIUS);
|
|
419
|
+
__m256 const flattening_f32x8 = _mm256_set1_ps(1.0f / (float)NK_EARTH_ELLIPSOID_INVERSE_FLATTENING);
|
|
420
|
+
__m256 const convergence_threshold_f32x8 = _mm256_set1_ps(NK_VINCENTY_CONVERGENCE_THRESHOLD_F32);
|
|
421
|
+
__m256 const one_f32x8 = _mm256_set1_ps(1.0f);
|
|
422
|
+
__m256 const two_f32x8 = _mm256_set1_ps(2.0f);
|
|
423
|
+
__m256 const three_f32x8 = _mm256_set1_ps(3.0f);
|
|
424
|
+
__m256 const four_f32x8 = _mm256_set1_ps(4.0f);
|
|
425
|
+
__m256 const six_f32x8 = _mm256_set1_ps(6.0f);
|
|
426
|
+
__m256 const sixteen_f32x8 = _mm256_set1_ps(16.0f);
|
|
427
|
+
__m256 const epsilon_f32x8 = _mm256_set1_ps(1e-7f);
|
|
428
|
+
|
|
429
|
+
// Longitude difference
|
|
430
|
+
__m256 longitude_difference_f32x8 = _mm256_sub_ps(second_longitudes_f32x8, first_longitudes_f32x8);
|
|
431
|
+
|
|
432
|
+
// Reduced latitudes: tan(U) = (1-f) * tan(lat)
|
|
433
|
+
__m256 one_minus_f_f32x8 = _mm256_sub_ps(one_f32x8, flattening_f32x8);
|
|
434
|
+
__m256 tan_first_f32x8 = _mm256_div_ps(nk_sin_f32x8_haswell_(first_latitudes_f32x8),
|
|
435
|
+
nk_cos_f32x8_haswell_(first_latitudes_f32x8));
|
|
436
|
+
__m256 tan_second_f32x8 = _mm256_div_ps(nk_sin_f32x8_haswell_(second_latitudes_f32x8),
|
|
437
|
+
nk_cos_f32x8_haswell_(second_latitudes_f32x8));
|
|
438
|
+
__m256 tan_reduced_first_f32x8 = _mm256_mul_ps(one_minus_f_f32x8, tan_first_f32x8);
|
|
439
|
+
__m256 tan_reduced_second_f32x8 = _mm256_mul_ps(one_minus_f_f32x8, tan_second_f32x8);
|
|
440
|
+
|
|
441
|
+
// cos(U) = 1/√(1 + tan²(U)), sin(U) = tan(U) × cos(U)
|
|
442
|
+
__m256 cos_reduced_first_f32x8 = _mm256_div_ps(
|
|
443
|
+
one_f32x8, _mm256_sqrt_ps(_mm256_fmadd_ps(tan_reduced_first_f32x8, tan_reduced_first_f32x8, one_f32x8)));
|
|
444
|
+
__m256 sin_reduced_first_f32x8 = _mm256_mul_ps(tan_reduced_first_f32x8, cos_reduced_first_f32x8);
|
|
445
|
+
__m256 cos_reduced_second_f32x8 = _mm256_div_ps(
|
|
446
|
+
one_f32x8, _mm256_sqrt_ps(_mm256_fmadd_ps(tan_reduced_second_f32x8, tan_reduced_second_f32x8, one_f32x8)));
|
|
447
|
+
__m256 sin_reduced_second_f32x8 = _mm256_mul_ps(tan_reduced_second_f32x8, cos_reduced_second_f32x8);
|
|
448
|
+
|
|
449
|
+
// Initialize lambda_f32x8 and tracking variables
|
|
450
|
+
__m256 lambda_f32x8 = longitude_difference_f32x8;
|
|
451
|
+
__m256 sin_angular_distance_f32x8, cos_angular_distance_f32x8, angular_distance_f32x8;
|
|
452
|
+
__m256 sin_azimuth_f32x8, cos_squared_azimuth_f32x8, cos_double_angular_midpoint_f32x8;
|
|
453
|
+
|
|
454
|
+
// Track convergence and coincident points using masks
|
|
455
|
+
__m256 converged_mask_f32x8 = _mm256_setzero_ps();
|
|
456
|
+
__m256 coincident_mask_f32x8 = _mm256_setzero_ps();
|
|
457
|
+
|
|
458
|
+
for (nk_u32_t iteration = 0; iteration < NK_VINCENTY_MAX_ITERATIONS; ++iteration) {
|
|
459
|
+
// Check if all lanes converged
|
|
460
|
+
int converged_bits = _mm256_movemask_ps(converged_mask_f32x8);
|
|
461
|
+
if (converged_bits == 0xFF) break;
|
|
462
|
+
|
|
463
|
+
__m256 sin_lambda_f32x8 = nk_sin_f32x8_haswell_(lambda_f32x8);
|
|
464
|
+
__m256 cos_lambda_f32x8 = nk_cos_f32x8_haswell_(lambda_f32x8);
|
|
465
|
+
|
|
466
|
+
// sin²(angular_distance_f32x8) = (cos(U₂) × sin(λ))² + (cos(U₁) × sin(U₂) - sin(U₁) × cos(U₂) × cos(λ))²
|
|
467
|
+
__m256 cross_term_f32x8 = _mm256_mul_ps(cos_reduced_second_f32x8, sin_lambda_f32x8);
|
|
468
|
+
__m256 mixed_term_f32x8 = _mm256_sub_ps(
|
|
469
|
+
_mm256_mul_ps(cos_reduced_first_f32x8, sin_reduced_second_f32x8),
|
|
470
|
+
_mm256_mul_ps(_mm256_mul_ps(sin_reduced_first_f32x8, cos_reduced_second_f32x8), cos_lambda_f32x8));
|
|
471
|
+
__m256 sin_angular_dist_sq_f32x8 = _mm256_fmadd_ps(cross_term_f32x8, cross_term_f32x8,
|
|
472
|
+
_mm256_mul_ps(mixed_term_f32x8, mixed_term_f32x8));
|
|
473
|
+
sin_angular_distance_f32x8 = _mm256_sqrt_ps(sin_angular_dist_sq_f32x8);
|
|
474
|
+
|
|
475
|
+
// Check for coincident points (sin_angular_distance_f32x8 ≈ 0)
|
|
476
|
+
coincident_mask_f32x8 = _mm256_cmp_ps(sin_angular_distance_f32x8, epsilon_f32x8, _CMP_LT_OS);
|
|
477
|
+
|
|
478
|
+
// cos(angular_distance_f32x8) = sin(U₁) × sin(U₂) + cos(U₁) × cos(U₂) × cos(λ)
|
|
479
|
+
cos_angular_distance_f32x8 = _mm256_fmadd_ps(_mm256_mul_ps(cos_reduced_first_f32x8, cos_reduced_second_f32x8),
|
|
480
|
+
cos_lambda_f32x8,
|
|
481
|
+
_mm256_mul_ps(sin_reduced_first_f32x8, sin_reduced_second_f32x8));
|
|
482
|
+
|
|
483
|
+
// angular_distance_f32x8 = atan2(sin, cos)
|
|
484
|
+
angular_distance_f32x8 = nk_atan2_f32x8_haswell_(sin_angular_distance_f32x8, cos_angular_distance_f32x8);
|
|
485
|
+
|
|
486
|
+
// sin(azimuth) = cos(U₁) × cos(U₂) × sin(λ) / sin(angular_distance_f32x8)
|
|
487
|
+
// Avoid division by zero by using blending
|
|
488
|
+
__m256 safe_sin_angular_f32x8 = _mm256_blendv_ps(sin_angular_distance_f32x8, one_f32x8, coincident_mask_f32x8);
|
|
489
|
+
sin_azimuth_f32x8 = _mm256_div_ps(
|
|
490
|
+
_mm256_mul_ps(_mm256_mul_ps(cos_reduced_first_f32x8, cos_reduced_second_f32x8), sin_lambda_f32x8),
|
|
491
|
+
safe_sin_angular_f32x8);
|
|
492
|
+
cos_squared_azimuth_f32x8 = _mm256_sub_ps(one_f32x8, _mm256_mul_ps(sin_azimuth_f32x8, sin_azimuth_f32x8));
|
|
493
|
+
|
|
494
|
+
// Handle equatorial case: cos²α ≈ 0
|
|
495
|
+
__m256 equatorial_mask_f32x8 = _mm256_cmp_ps(cos_squared_azimuth_f32x8, epsilon_f32x8, _CMP_LT_OS);
|
|
496
|
+
__m256 safe_cos_sq_azimuth_f32x8 = _mm256_blendv_ps(cos_squared_azimuth_f32x8, one_f32x8,
|
|
497
|
+
equatorial_mask_f32x8);
|
|
498
|
+
|
|
499
|
+
// cos(2σₘ) = cos(σ) - 2 × sin(U₁) × sin(U₂) / cos²(α)
|
|
500
|
+
__m256 sin_product_f32x8 = _mm256_mul_ps(sin_reduced_first_f32x8, sin_reduced_second_f32x8);
|
|
501
|
+
cos_double_angular_midpoint_f32x8 = _mm256_sub_ps(
|
|
502
|
+
cos_angular_distance_f32x8,
|
|
503
|
+
_mm256_div_ps(_mm256_mul_ps(two_f32x8, sin_product_f32x8), safe_cos_sq_azimuth_f32x8));
|
|
504
|
+
cos_double_angular_midpoint_f32x8 = _mm256_blendv_ps(cos_double_angular_midpoint_f32x8, _mm256_setzero_ps(),
|
|
505
|
+
equatorial_mask_f32x8);
|
|
506
|
+
|
|
507
|
+
// C = f/16 * cos²α * (4 + f*(4 - 3*cos²α))
|
|
508
|
+
__m256 correction_factor_f32x8 = _mm256_mul_ps(
|
|
509
|
+
_mm256_div_ps(flattening_f32x8, sixteen_f32x8),
|
|
510
|
+
_mm256_mul_ps(
|
|
511
|
+
cos_squared_azimuth_f32x8,
|
|
512
|
+
_mm256_fmadd_ps(flattening_f32x8, _mm256_fnmadd_ps(three_f32x8, cos_squared_azimuth_f32x8, four_f32x8),
|
|
513
|
+
four_f32x8)));
|
|
514
|
+
|
|
515
|
+
// λ' = L + (1-C) × f × sin(α) × (σ + C × sin(σ) × (cos(2σₘ) + C × cos(σ) × (-1 + 2 × cos²(2σₘ))))
|
|
516
|
+
__m256 cos_2sm_sq_f32x8 = _mm256_mul_ps(cos_double_angular_midpoint_f32x8, cos_double_angular_midpoint_f32x8);
|
|
517
|
+
// innermost_f32x8 = -1 + 2 × cos²(2σₘ)
|
|
518
|
+
__m256 innermost_f32x8 = _mm256_fmadd_ps(two_f32x8, cos_2sm_sq_f32x8, _mm256_set1_ps(-1.0f));
|
|
519
|
+
// middle_f32x8 = cos(2σₘ) + C × cos(σ) × innermost_f32x8
|
|
520
|
+
__m256 middle_f32x8 = _mm256_fmadd_ps(_mm256_mul_ps(correction_factor_f32x8, cos_angular_distance_f32x8),
|
|
521
|
+
innermost_f32x8, cos_double_angular_midpoint_f32x8);
|
|
522
|
+
// inner_f32x8 = C × sin(σ) × middle_f32x8
|
|
523
|
+
__m256 inner_f32x8 = _mm256_mul_ps(_mm256_mul_ps(correction_factor_f32x8, sin_angular_distance_f32x8),
|
|
524
|
+
middle_f32x8);
|
|
525
|
+
|
|
526
|
+
// λ' = L + (1-C) * f * sin_α * (σ + inner_f32x8)
|
|
527
|
+
__m256 lambda_new_f32x8 = _mm256_fmadd_ps(
|
|
528
|
+
_mm256_mul_ps(_mm256_mul_ps(_mm256_sub_ps(one_f32x8, correction_factor_f32x8), flattening_f32x8),
|
|
529
|
+
sin_azimuth_f32x8),
|
|
530
|
+
_mm256_add_ps(angular_distance_f32x8, inner_f32x8), longitude_difference_f32x8);
|
|
531
|
+
|
|
532
|
+
// Check convergence: |λ - λ'| < threshold
|
|
533
|
+
__m256 lambda_diff_abs_f32x8 = _mm256_andnot_ps(_mm256_set1_ps(-0.0f),
|
|
534
|
+
_mm256_sub_ps(lambda_new_f32x8, lambda_f32x8));
|
|
535
|
+
__m256 newly_converged_f32x8 = _mm256_cmp_ps(lambda_diff_abs_f32x8, convergence_threshold_f32x8, _CMP_LT_OS);
|
|
536
|
+
converged_mask_f32x8 = _mm256_or_ps(converged_mask_f32x8, newly_converged_f32x8);
|
|
537
|
+
|
|
538
|
+
// Only update lambda_f32x8 for non-converged lanes
|
|
539
|
+
lambda_f32x8 = _mm256_blendv_ps(lambda_new_f32x8, lambda_f32x8, converged_mask_f32x8);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Final distance calculation
|
|
543
|
+
// u² = cos²α * (a² - b²) / b²
|
|
544
|
+
__m256 a_sq_f32x8 = _mm256_mul_ps(equatorial_radius_f32x8, equatorial_radius_f32x8);
|
|
545
|
+
__m256 b_sq_f32x8 = _mm256_mul_ps(polar_radius_f32x8, polar_radius_f32x8);
|
|
546
|
+
__m256 u_squared_f32x8 = _mm256_div_ps(
|
|
547
|
+
_mm256_mul_ps(cos_squared_azimuth_f32x8, _mm256_sub_ps(a_sq_f32x8, b_sq_f32x8)), b_sq_f32x8);
|
|
548
|
+
|
|
549
|
+
// A = 1 + u²/16384 * (4096 + u²*(-768 + u²*(320 - 175*u²)))
|
|
550
|
+
__m256 series_a_f32x8 = _mm256_fmadd_ps(u_squared_f32x8, _mm256_set1_ps(-175.0f), _mm256_set1_ps(320.0f));
|
|
551
|
+
series_a_f32x8 = _mm256_fmadd_ps(u_squared_f32x8, series_a_f32x8, _mm256_set1_ps(-768.0f));
|
|
552
|
+
series_a_f32x8 = _mm256_fmadd_ps(u_squared_f32x8, series_a_f32x8, _mm256_set1_ps(4096.0f));
|
|
553
|
+
series_a_f32x8 = _mm256_fmadd_ps(_mm256_div_ps(u_squared_f32x8, _mm256_set1_ps(16384.0f)), series_a_f32x8,
|
|
554
|
+
one_f32x8);
|
|
555
|
+
|
|
556
|
+
// B = u²/1024 * (256 + u²*(-128 + u²*(74 - 47*u²)))
|
|
557
|
+
__m256 series_b_f32x8 = _mm256_fmadd_ps(u_squared_f32x8, _mm256_set1_ps(-47.0f), _mm256_set1_ps(74.0f));
|
|
558
|
+
series_b_f32x8 = _mm256_fmadd_ps(u_squared_f32x8, series_b_f32x8, _mm256_set1_ps(-128.0f));
|
|
559
|
+
series_b_f32x8 = _mm256_fmadd_ps(u_squared_f32x8, series_b_f32x8, _mm256_set1_ps(256.0f));
|
|
560
|
+
series_b_f32x8 = _mm256_mul_ps(_mm256_div_ps(u_squared_f32x8, _mm256_set1_ps(1024.0f)), series_b_f32x8);
|
|
561
|
+
|
|
562
|
+
// Δσ = B × sin(σ) × (cos(2σₘ) +
|
|
563
|
+
// B/4 × (cos(σ) × (-1 + 2 × cos²(2σₘ)) - B/6 × cos(2σₘ) × (-3 + 4 × sin²(σ)) × (-3 + 4 × cos²(2σₘ))))
|
|
564
|
+
__m256 cos_2sm_sq_f32x8 = _mm256_mul_ps(cos_double_angular_midpoint_f32x8, cos_double_angular_midpoint_f32x8);
|
|
565
|
+
__m256 sin_sq_f32x8 = _mm256_mul_ps(sin_angular_distance_f32x8, sin_angular_distance_f32x8);
|
|
566
|
+
__m256 term1_f32x8 = _mm256_fmadd_ps(two_f32x8, cos_2sm_sq_f32x8, _mm256_set1_ps(-1.0f));
|
|
567
|
+
term1_f32x8 = _mm256_mul_ps(cos_angular_distance_f32x8, term1_f32x8);
|
|
568
|
+
__m256 term2_f32x8 = _mm256_fmadd_ps(four_f32x8, sin_sq_f32x8, _mm256_set1_ps(-3.0f));
|
|
569
|
+
__m256 term3_f32x8 = _mm256_fmadd_ps(four_f32x8, cos_2sm_sq_f32x8, _mm256_set1_ps(-3.0f));
|
|
570
|
+
term2_f32x8 = _mm256_mul_ps(
|
|
571
|
+
_mm256_mul_ps(_mm256_div_ps(series_b_f32x8, six_f32x8), cos_double_angular_midpoint_f32x8),
|
|
572
|
+
_mm256_mul_ps(term2_f32x8, term3_f32x8));
|
|
573
|
+
__m256 delta_sigma_f32x8 = _mm256_mul_ps(
|
|
574
|
+
series_b_f32x8, _mm256_mul_ps(sin_angular_distance_f32x8,
|
|
575
|
+
_mm256_add_ps(cos_double_angular_midpoint_f32x8,
|
|
576
|
+
_mm256_mul_ps(_mm256_div_ps(series_b_f32x8, four_f32x8),
|
|
577
|
+
_mm256_sub_ps(term1_f32x8, term2_f32x8)))));
|
|
578
|
+
|
|
579
|
+
// s = b * A * (σ - Δσ)
|
|
580
|
+
__m256 distances_f32x8 = _mm256_mul_ps(_mm256_mul_ps(polar_radius_f32x8, series_a_f32x8),
|
|
581
|
+
_mm256_sub_ps(angular_distance_f32x8, delta_sigma_f32x8));
|
|
582
|
+
|
|
583
|
+
// Set coincident points to zero
|
|
584
|
+
distances_f32x8 = _mm256_blendv_ps(distances_f32x8, _mm256_setzero_ps(), coincident_mask_f32x8);
|
|
585
|
+
|
|
586
|
+
return distances_f32x8;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
NK_PUBLIC void nk_vincenty_f32_haswell( //
|
|
590
|
+
nk_f32_t const *a_lats, nk_f32_t const *a_lons, //
|
|
591
|
+
nk_f32_t const *b_lats, nk_f32_t const *b_lons, //
|
|
592
|
+
nk_size_t n, nk_f32_t *results) {
|
|
593
|
+
|
|
594
|
+
while (n >= 8) {
|
|
595
|
+
__m256 first_latitudes_f32x8 = _mm256_loadu_ps(a_lats);
|
|
596
|
+
__m256 first_longitudes_f32x8 = _mm256_loadu_ps(a_lons);
|
|
597
|
+
__m256 second_latitudes_f32x8 = _mm256_loadu_ps(b_lats);
|
|
598
|
+
__m256 second_longitudes_f32x8 = _mm256_loadu_ps(b_lons);
|
|
599
|
+
|
|
600
|
+
__m256 distances_f32x8 = nk_vincenty_f32x8_haswell_(first_latitudes_f32x8, first_longitudes_f32x8,
|
|
601
|
+
second_latitudes_f32x8, second_longitudes_f32x8);
|
|
602
|
+
_mm256_storeu_ps(results, distances_f32x8);
|
|
603
|
+
|
|
604
|
+
a_lats += 8, a_lons += 8, b_lats += 8, b_lons += 8, results += 8, n -= 8;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// Handle remaining elements with partial loads (n can be 1-7 here)
|
|
608
|
+
if (n > 0) {
|
|
609
|
+
nk_b256_vec_t a_lat_vec, a_lon_vec, b_lat_vec, b_lon_vec, result_vec;
|
|
610
|
+
nk_partial_load_b32x8_serial_(a_lats, &a_lat_vec, n);
|
|
611
|
+
nk_partial_load_b32x8_serial_(a_lons, &a_lon_vec, n);
|
|
612
|
+
nk_partial_load_b32x8_serial_(b_lats, &b_lat_vec, n);
|
|
613
|
+
nk_partial_load_b32x8_serial_(b_lons, &b_lon_vec, n);
|
|
614
|
+
__m256 distances_f32x8 = nk_vincenty_f32x8_haswell_(a_lat_vec.ymm_ps, a_lon_vec.ymm_ps, b_lat_vec.ymm_ps,
|
|
615
|
+
b_lon_vec.ymm_ps);
|
|
616
|
+
result_vec.ymm_ps = distances_f32x8;
|
|
617
|
+
nk_partial_store_b32x8_serial_(&result_vec, results, n);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
#if defined(__clang__)
|
|
622
|
+
#pragma clang attribute pop
|
|
623
|
+
#elif defined(__GNUC__)
|
|
624
|
+
#pragma GCC pop_options
|
|
625
|
+
#endif
|
|
626
|
+
|
|
627
|
+
#if defined(__cplusplus)
|
|
628
|
+
} // extern "C"
|
|
629
|
+
#endif
|
|
630
|
+
|
|
631
|
+
#endif // NK_TARGET_HASWELL
|
|
632
|
+
#endif // NK_TARGET_X8664_
|
|
633
|
+
#endif // NK_GEOSPATIAL_HASWELL_H
|