usearch 2.21.4 → 2.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -69
- package/binding.gyp +15 -37
- package/c/CMakeLists.txt +4 -5
- package/c/README.md +8 -8
- package/c/lib.cpp +32 -14
- package/c/test.c +124 -1
- package/c/usearch.h +24 -3
- package/cpp/CMakeLists.txt +4 -0
- package/cpp/README.md +5 -5
- package/cpp/bench.cpp +97 -116
- package/cpp/test.cpp +117 -20
- package/include/usearch/index.hpp +224 -48
- package/include/usearch/index_dense.hpp +105 -40
- package/include/usearch/index_plugins.hpp +1387 -204
- package/javascript/README.md +1 -1
- package/javascript/dist/cjs/usearch.d.ts +8 -3
- package/javascript/dist/cjs/usearch.js +12 -4
- package/javascript/dist/esm/usearch.d.ts +8 -3
- package/javascript/dist/esm/usearch.js +12 -4
- package/javascript/lib.cpp +17 -0
- package/javascript/usearch.test.js +117 -94
- package/javascript/usearch.ts +14 -6
- package/numkong/.clang-tidy +30 -0
- package/{simsimd → numkong}/.cmake-format.py +18 -0
- package/numkong/.editorconfig +12 -0
- package/numkong/.git-blame-ignore-revs +123 -0
- package/numkong/.mailmap +15 -0
- package/numkong/.spi.yml +11 -0
- package/numkong/.swift-format +14 -0
- package/numkong/CITATION.cff +81 -0
- package/numkong/CONTRIBUTING.md +500 -0
- package/numkong/Cargo.toml +54 -0
- package/numkong/MANIFEST.in +8 -0
- package/numkong/Package.swift +84 -0
- package/numkong/README.md +569 -0
- package/numkong/bench/README.md +217 -0
- package/numkong/bench/bench-browser.html +323 -0
- package/numkong/bench/bench.cpp +344 -0
- package/numkong/bench/bench.hpp +816 -0
- package/numkong/bench/bench.js +148 -0
- package/numkong/bench/bench.mjs +616 -0
- package/numkong/bench/bench_attention.cpp +113 -0
- package/numkong/bench/bench_cast.cpp +264 -0
- package/numkong/bench/bench_cross_amx.cpp +62 -0
- package/numkong/bench/bench_cross_arm.cpp +245 -0
- package/numkong/bench/bench_cross_blas.cpp +309 -0
- package/numkong/bench/bench_cross_loongarch.cpp +106 -0
- package/numkong/bench/bench_cross_power.cpp +84 -0
- package/numkong/bench/bench_cross_rvv.cpp +121 -0
- package/numkong/bench/bench_cross_serial.cpp +151 -0
- package/numkong/bench/bench_cross_sme.cpp +163 -0
- package/numkong/bench/bench_cross_wasm.cpp +142 -0
- package/numkong/bench/bench_cross_x86.cpp +455 -0
- package/numkong/bench/bench_curved.cpp +210 -0
- package/numkong/bench/bench_dot.cpp +315 -0
- package/numkong/bench/bench_each.cpp +503 -0
- package/numkong/bench/bench_geospatial.cpp +112 -0
- package/numkong/bench/bench_maxsim.cpp +154 -0
- package/numkong/bench/bench_mesh.cpp +148 -0
- package/numkong/bench/bench_probability.cpp +60 -0
- package/numkong/bench/bench_reduce.cpp +371 -0
- package/numkong/bench/bench_set.cpp +73 -0
- package/numkong/bench/bench_sparse.cpp +198 -0
- package/numkong/bench/bench_spatial.cpp +347 -0
- package/numkong/bench/bench_trigonometry.cpp +137 -0
- package/numkong/bench/swift/Bench.swift +506 -0
- package/numkong/binding.gyp +169 -0
- package/numkong/build.rs +484 -0
- package/numkong/c/dispatch.h +512 -0
- package/numkong/c/dispatch_bf16.c +447 -0
- package/numkong/c/dispatch_bf16c.c +52 -0
- package/numkong/c/dispatch_e2m3.c +296 -0
- package/numkong/c/dispatch_e3m2.c +284 -0
- package/numkong/c/dispatch_e4m3.c +318 -0
- package/numkong/c/dispatch_e5m2.c +316 -0
- package/numkong/c/dispatch_f16.c +452 -0
- package/numkong/c/dispatch_f16c.c +58 -0
- package/numkong/c/dispatch_f32.c +434 -0
- package/numkong/c/dispatch_f32c.c +99 -0
- package/numkong/c/dispatch_f64.c +348 -0
- package/numkong/c/dispatch_f64c.c +98 -0
- package/numkong/c/dispatch_i16.c +96 -0
- package/numkong/c/dispatch_i32.c +89 -0
- package/numkong/c/dispatch_i4.c +153 -0
- package/numkong/c/dispatch_i64.c +86 -0
- package/numkong/c/dispatch_i8.c +348 -0
- package/numkong/c/dispatch_other.c +348 -0
- package/numkong/c/dispatch_u1.c +193 -0
- package/numkong/c/dispatch_u16.c +124 -0
- package/numkong/c/dispatch_u32.c +118 -0
- package/numkong/c/dispatch_u4.c +153 -0
- package/numkong/c/dispatch_u64.c +102 -0
- package/numkong/c/dispatch_u8.c +364 -0
- package/numkong/c/numkong.c +940 -0
- package/numkong/cmake/nk_arm_isa_probes.cmake +61 -0
- package/numkong/cmake/nk_isa_probe.cmake +90 -0
- package/numkong/cmake/nk_loongarch_isa_probes.cmake +15 -0
- package/numkong/cmake/nk_math_lib.cmake +46 -0
- package/numkong/cmake/nk_power_isa_probes.cmake +15 -0
- package/numkong/cmake/nk_riscv_isa_probes.cmake +19 -0
- package/numkong/cmake/nk_x86_isa_probes.cmake +35 -0
- package/numkong/cmake/toolchain-aarch64-gnu.cmake +86 -0
- package/numkong/cmake/toolchain-android-arm64.cmake +25 -0
- package/numkong/cmake/toolchain-android-armv7.cmake +25 -0
- package/numkong/cmake/toolchain-loongarch64-gnu.cmake +68 -0
- package/numkong/cmake/toolchain-ppc64le-gnu.cmake +74 -0
- package/numkong/cmake/toolchain-riscv64-gnu.cmake +107 -0
- package/numkong/cmake/toolchain-riscv64-llvm.cmake +114 -0
- package/numkong/cmake/toolchain-wasi.cmake +77 -0
- package/numkong/cmake/toolchain-wasm.cmake +70 -0
- package/numkong/cmake/toolchain-wasm64.cmake +62 -0
- package/numkong/cmake/toolchain-x86_64-llvm.cmake +47 -0
- package/numkong/include/README.md +643 -0
- package/numkong/include/module.modulemap +129 -0
- package/numkong/include/numkong/attention/sapphireamx.h +1363 -0
- package/numkong/include/numkong/attention/sme.h +2075 -0
- package/numkong/include/numkong/attention.h +49 -0
- package/numkong/include/numkong/capabilities.h +930 -0
- package/numkong/include/numkong/cast/README.md +262 -0
- package/numkong/include/numkong/cast/diamond.h +64 -0
- package/numkong/include/numkong/cast/haswell.h +823 -0
- package/numkong/include/numkong/cast/icelake.h +475 -0
- package/numkong/include/numkong/cast/loongsonasx.h +252 -0
- package/numkong/include/numkong/cast/neon.h +1174 -0
- package/numkong/include/numkong/cast/powervsx.h +449 -0
- package/numkong/include/numkong/cast/rvv.h +970 -0
- package/numkong/include/numkong/cast/sapphire.h +262 -0
- package/numkong/include/numkong/cast/serial.h +2336 -0
- package/numkong/include/numkong/cast/skylake.h +915 -0
- package/numkong/include/numkong/cast/v128relaxed.h +537 -0
- package/numkong/include/numkong/cast.h +254 -0
- package/numkong/include/numkong/cast.hpp +44 -0
- package/numkong/include/numkong/curved/README.md +223 -0
- package/numkong/include/numkong/curved/genoa.h +182 -0
- package/numkong/include/numkong/curved/haswell.h +276 -0
- package/numkong/include/numkong/curved/neon.h +329 -0
- package/numkong/include/numkong/curved/neonbfdot.h +211 -0
- package/numkong/include/numkong/curved/rvv.h +305 -0
- package/numkong/include/numkong/curved/serial.h +207 -0
- package/numkong/include/numkong/curved/skylake.h +457 -0
- package/numkong/include/numkong/curved/smef64.h +530 -0
- package/numkong/include/numkong/curved.h +513 -0
- package/numkong/include/numkong/curved.hpp +144 -0
- package/numkong/include/numkong/dot/README.md +442 -0
- package/numkong/include/numkong/dot/alder.h +563 -0
- package/numkong/include/numkong/dot/diamond.h +158 -0
- package/numkong/include/numkong/dot/genoa.h +289 -0
- package/numkong/include/numkong/dot/haswell.h +1723 -0
- package/numkong/include/numkong/dot/icelake.h +997 -0
- package/numkong/include/numkong/dot/loongsonasx.h +671 -0
- package/numkong/include/numkong/dot/neon.h +869 -0
- package/numkong/include/numkong/dot/neonbfdot.h +243 -0
- package/numkong/include/numkong/dot/neonfhm.h +358 -0
- package/numkong/include/numkong/dot/neonfp8.h +323 -0
- package/numkong/include/numkong/dot/neonsdot.h +622 -0
- package/numkong/include/numkong/dot/powervsx.h +752 -0
- package/numkong/include/numkong/dot/rvv.h +722 -0
- package/numkong/include/numkong/dot/rvvbb.h +72 -0
- package/numkong/include/numkong/dot/rvvbf16.h +123 -0
- package/numkong/include/numkong/dot/rvvhalf.h +129 -0
- package/numkong/include/numkong/dot/sapphire.h +141 -0
- package/numkong/include/numkong/dot/serial.h +874 -0
- package/numkong/include/numkong/dot/sierra.h +405 -0
- package/numkong/include/numkong/dot/skylake.h +1116 -0
- package/numkong/include/numkong/dot/sve.h +420 -0
- package/numkong/include/numkong/dot/svebfdot.h +75 -0
- package/numkong/include/numkong/dot/svehalf.h +168 -0
- package/numkong/include/numkong/dot/svesdot.h +90 -0
- package/numkong/include/numkong/dot/v128relaxed.h +1293 -0
- package/numkong/include/numkong/dot.h +1136 -0
- package/numkong/include/numkong/dot.hpp +94 -0
- package/numkong/include/numkong/dots/README.md +496 -0
- package/numkong/include/numkong/dots/alder.h +117 -0
- package/numkong/include/numkong/dots/diamond.h +86 -0
- package/numkong/include/numkong/dots/genoa.h +100 -0
- package/numkong/include/numkong/dots/graniteamx.h +733 -0
- package/numkong/include/numkong/dots/haswell.h +310 -0
- package/numkong/include/numkong/dots/icelake.h +180 -0
- package/numkong/include/numkong/dots/loongsonasx.h +176 -0
- package/numkong/include/numkong/dots/neon.h +123 -0
- package/numkong/include/numkong/dots/neonbfdot.h +59 -0
- package/numkong/include/numkong/dots/neonfhm.h +96 -0
- package/numkong/include/numkong/dots/neonfp8.h +99 -0
- package/numkong/include/numkong/dots/neonsdot.h +144 -0
- package/numkong/include/numkong/dots/powervsx.h +194 -0
- package/numkong/include/numkong/dots/rvv.h +2593 -0
- package/numkong/include/numkong/dots/sapphireamx.h +4017 -0
- package/numkong/include/numkong/dots/serial.h +2867 -0
- package/numkong/include/numkong/dots/sierra.h +100 -0
- package/numkong/include/numkong/dots/skylake.h +207 -0
- package/numkong/include/numkong/dots/sme.h +5041 -0
- package/numkong/include/numkong/dots/smebi32.h +477 -0
- package/numkong/include/numkong/dots/smef64.h +1328 -0
- package/numkong/include/numkong/dots/smehalf.h +47 -0
- package/numkong/include/numkong/dots/v128relaxed.h +317 -0
- package/numkong/include/numkong/dots.h +3110 -0
- package/numkong/include/numkong/dots.hpp +641 -0
- package/numkong/include/numkong/each/README.md +465 -0
- package/numkong/include/numkong/each/haswell.h +1658 -0
- package/numkong/include/numkong/each/icelake.h +272 -0
- package/numkong/include/numkong/each/neon.h +1138 -0
- package/numkong/include/numkong/each/neonbfdot.h +211 -0
- package/numkong/include/numkong/each/neonhalf.h +318 -0
- package/numkong/include/numkong/each/rvv.h +1121 -0
- package/numkong/include/numkong/each/sapphire.h +343 -0
- package/numkong/include/numkong/each/serial.h +282 -0
- package/numkong/include/numkong/each/skylake.h +1562 -0
- package/numkong/include/numkong/each/v128relaxed.h +562 -0
- package/numkong/include/numkong/each.h +2232 -0
- package/numkong/include/numkong/each.hpp +434 -0
- package/numkong/include/numkong/geospatial/README.md +147 -0
- package/numkong/include/numkong/geospatial/haswell.h +633 -0
- package/numkong/include/numkong/geospatial/neon.h +615 -0
- package/numkong/include/numkong/geospatial/rvv.h +701 -0
- package/numkong/include/numkong/geospatial/serial.h +309 -0
- package/numkong/include/numkong/geospatial/skylake.h +613 -0
- package/numkong/include/numkong/geospatial/v128relaxed.h +652 -0
- package/numkong/include/numkong/geospatial.h +453 -0
- package/numkong/include/numkong/geospatial.hpp +235 -0
- package/numkong/include/numkong/matrix.hpp +336 -0
- package/numkong/include/numkong/maxsim/README.md +187 -0
- package/numkong/include/numkong/maxsim/alder.h +511 -0
- package/numkong/include/numkong/maxsim/genoa.h +115 -0
- package/numkong/include/numkong/maxsim/haswell.h +553 -0
- package/numkong/include/numkong/maxsim/icelake.h +480 -0
- package/numkong/include/numkong/maxsim/neonsdot.h +394 -0
- package/numkong/include/numkong/maxsim/sapphireamx.h +877 -0
- package/numkong/include/numkong/maxsim/serial.h +490 -0
- package/numkong/include/numkong/maxsim/sme.h +993 -0
- package/numkong/include/numkong/maxsim/v128relaxed.h +280 -0
- package/numkong/include/numkong/maxsim.h +571 -0
- package/numkong/include/numkong/maxsim.hpp +133 -0
- package/numkong/include/numkong/mesh/README.md +219 -0
- package/numkong/include/numkong/mesh/haswell.h +2013 -0
- package/numkong/include/numkong/mesh/neon.h +1821 -0
- package/numkong/include/numkong/mesh/neonbfdot.h +771 -0
- package/numkong/include/numkong/mesh/rvv.h +936 -0
- package/numkong/include/numkong/mesh/serial.h +721 -0
- package/numkong/include/numkong/mesh/skylake.h +2344 -0
- package/numkong/include/numkong/mesh/v128relaxed.h +1081 -0
- package/numkong/include/numkong/mesh.h +666 -0
- package/numkong/include/numkong/mesh.hpp +701 -0
- package/numkong/include/numkong/numkong.h +78 -0
- package/numkong/include/numkong/numkong.hpp +58 -0
- package/numkong/include/numkong/probability/README.md +177 -0
- package/numkong/include/numkong/probability/haswell.h +267 -0
- package/numkong/include/numkong/probability/neon.h +255 -0
- package/numkong/include/numkong/probability/rvv.h +414 -0
- package/numkong/include/numkong/probability/serial.h +181 -0
- package/numkong/include/numkong/probability/skylake.h +324 -0
- package/numkong/include/numkong/probability.h +380 -0
- package/numkong/include/numkong/probability.hpp +120 -0
- package/numkong/include/numkong/random.h +50 -0
- package/numkong/include/numkong/random.hpp +285 -0
- package/numkong/include/numkong/reduce/README.md +552 -0
- package/numkong/include/numkong/reduce/alder.h +636 -0
- package/numkong/include/numkong/reduce/genoa.h +201 -0
- package/numkong/include/numkong/reduce/haswell.h +3785 -0
- package/numkong/include/numkong/reduce/icelake.h +549 -0
- package/numkong/include/numkong/reduce/neon.h +3980 -0
- package/numkong/include/numkong/reduce/neonbfdot.h +142 -0
- package/numkong/include/numkong/reduce/neonfhm.h +293 -0
- package/numkong/include/numkong/reduce/neonsdot.h +357 -0
- package/numkong/include/numkong/reduce/rvv.h +3533 -0
- package/numkong/include/numkong/reduce/serial.h +753 -0
- package/numkong/include/numkong/reduce/sierra.h +338 -0
- package/numkong/include/numkong/reduce/skylake.h +3794 -0
- package/numkong/include/numkong/reduce/sve.h +52 -0
- package/numkong/include/numkong/reduce/v128relaxed.h +2302 -0
- package/numkong/include/numkong/reduce.h +1582 -0
- package/numkong/include/numkong/reduce.hpp +778 -0
- package/numkong/include/numkong/scalar/README.md +89 -0
- package/numkong/include/numkong/scalar/haswell.h +122 -0
- package/numkong/include/numkong/scalar/loongsonasx.h +74 -0
- package/numkong/include/numkong/scalar/neon.h +122 -0
- package/numkong/include/numkong/scalar/neonhalf.h +70 -0
- package/numkong/include/numkong/scalar/powervsx.h +96 -0
- package/numkong/include/numkong/scalar/rvv.h +211 -0
- package/numkong/include/numkong/scalar/sapphire.h +74 -0
- package/numkong/include/numkong/scalar/serial.h +332 -0
- package/numkong/include/numkong/scalar/v128relaxed.h +56 -0
- package/numkong/include/numkong/scalar.h +696 -0
- package/numkong/include/numkong/set/README.md +179 -0
- package/numkong/include/numkong/set/haswell.h +334 -0
- package/numkong/include/numkong/set/icelake.h +485 -0
- package/numkong/include/numkong/set/loongsonasx.h +181 -0
- package/numkong/include/numkong/set/neon.h +363 -0
- package/numkong/include/numkong/set/powervsx.h +326 -0
- package/numkong/include/numkong/set/rvv.h +226 -0
- package/numkong/include/numkong/set/rvvbb.h +117 -0
- package/numkong/include/numkong/set/serial.h +174 -0
- package/numkong/include/numkong/set/sve.h +187 -0
- package/numkong/include/numkong/set/v128relaxed.h +240 -0
- package/numkong/include/numkong/set.h +471 -0
- package/numkong/include/numkong/set.hpp +114 -0
- package/numkong/include/numkong/sets/README.md +149 -0
- package/numkong/include/numkong/sets/haswell.h +63 -0
- package/numkong/include/numkong/sets/icelake.h +66 -0
- package/numkong/include/numkong/sets/loongsonasx.h +52 -0
- package/numkong/include/numkong/sets/neon.h +61 -0
- package/numkong/include/numkong/sets/powervsx.h +65 -0
- package/numkong/include/numkong/sets/serial.h +43 -0
- package/numkong/include/numkong/sets/smebi32.h +1135 -0
- package/numkong/include/numkong/sets/v128relaxed.h +58 -0
- package/numkong/include/numkong/sets.h +382 -0
- package/numkong/include/numkong/sparse/README.md +156 -0
- package/numkong/include/numkong/sparse/icelake.h +463 -0
- package/numkong/include/numkong/sparse/neon.h +288 -0
- package/numkong/include/numkong/sparse/serial.h +117 -0
- package/numkong/include/numkong/sparse/sve2.h +504 -0
- package/numkong/include/numkong/sparse/turin.h +322 -0
- package/numkong/include/numkong/sparse.h +363 -0
- package/numkong/include/numkong/sparse.hpp +113 -0
- package/numkong/include/numkong/spatial/README.md +439 -0
- package/numkong/include/numkong/spatial/alder.h +604 -0
- package/numkong/include/numkong/spatial/diamond.h +240 -0
- package/numkong/include/numkong/spatial/genoa.h +222 -0
- package/numkong/include/numkong/spatial/haswell.h +979 -0
- package/numkong/include/numkong/spatial/icelake.h +1067 -0
- package/numkong/include/numkong/spatial/loongsonasx.h +483 -0
- package/numkong/include/numkong/spatial/neon.h +846 -0
- package/numkong/include/numkong/spatial/neonbfdot.h +164 -0
- package/numkong/include/numkong/spatial/neonfp8.h +258 -0
- package/numkong/include/numkong/spatial/neonsdot.h +429 -0
- package/numkong/include/numkong/spatial/powervsx.h +738 -0
- package/numkong/include/numkong/spatial/rvv.h +991 -0
- package/numkong/include/numkong/spatial/rvvbf16.h +128 -0
- package/numkong/include/numkong/spatial/rvvhalf.h +120 -0
- package/numkong/include/numkong/spatial/serial.h +347 -0
- package/numkong/include/numkong/spatial/sierra.h +516 -0
- package/numkong/include/numkong/spatial/skylake.h +605 -0
- package/numkong/include/numkong/spatial/sve.h +246 -0
- package/numkong/include/numkong/spatial/svebfdot.h +125 -0
- package/numkong/include/numkong/spatial/svehalf.h +136 -0
- package/numkong/include/numkong/spatial/svesdot.h +143 -0
- package/numkong/include/numkong/spatial/v128relaxed.h +969 -0
- package/numkong/include/numkong/spatial.h +1681 -0
- package/numkong/include/numkong/spatial.hpp +183 -0
- package/numkong/include/numkong/spatials/README.md +580 -0
- package/numkong/include/numkong/spatials/alder.h +94 -0
- package/numkong/include/numkong/spatials/diamond.h +82 -0
- package/numkong/include/numkong/spatials/genoa.h +94 -0
- package/numkong/include/numkong/spatials/graniteamx.h +173 -0
- package/numkong/include/numkong/spatials/haswell.h +219 -0
- package/numkong/include/numkong/spatials/icelake.h +113 -0
- package/numkong/include/numkong/spatials/loongsonasx.h +153 -0
- package/numkong/include/numkong/spatials/neon.h +109 -0
- package/numkong/include/numkong/spatials/neonbfdot.h +60 -0
- package/numkong/include/numkong/spatials/neonfhm.h +92 -0
- package/numkong/include/numkong/spatials/neonfp8.h +111 -0
- package/numkong/include/numkong/spatials/neonsdot.h +143 -0
- package/numkong/include/numkong/spatials/powervsx.h +153 -0
- package/numkong/include/numkong/spatials/rvv.h +1976 -0
- package/numkong/include/numkong/spatials/sapphireamx.h +1149 -0
- package/numkong/include/numkong/spatials/serial.h +248 -0
- package/numkong/include/numkong/spatials/sierra.h +96 -0
- package/numkong/include/numkong/spatials/skylake.h +184 -0
- package/numkong/include/numkong/spatials/sme.h +1927 -0
- package/numkong/include/numkong/spatials/smef64.h +483 -0
- package/numkong/include/numkong/spatials/v128relaxed.h +240 -0
- package/numkong/include/numkong/spatials.h +3374 -0
- package/numkong/include/numkong/spatials.hpp +509 -0
- package/numkong/include/numkong/tensor.hpp +1981 -0
- package/numkong/include/numkong/trigonometry/README.md +184 -0
- package/numkong/include/numkong/trigonometry/haswell.h +653 -0
- package/numkong/include/numkong/trigonometry/neon.h +638 -0
- package/numkong/include/numkong/trigonometry/rvv.h +700 -0
- package/numkong/include/numkong/trigonometry/serial.h +703 -0
- package/numkong/include/numkong/trigonometry/skylake.h +725 -0
- package/numkong/include/numkong/trigonometry/v128relaxed.h +667 -0
- package/numkong/include/numkong/trigonometry.h +467 -0
- package/numkong/include/numkong/trigonometry.hpp +166 -0
- package/numkong/include/numkong/types.h +1695 -0
- package/numkong/include/numkong/types.hpp +6027 -0
- package/numkong/include/numkong/vector.hpp +766 -0
- package/numkong/javascript/@numkong-darwin-arm64/package.json +26 -0
- package/numkong/javascript/@numkong-darwin-x64/package.json +26 -0
- package/numkong/javascript/@numkong-linux-arm64/package.json +25 -0
- package/numkong/javascript/@numkong-linux-x64/package.json +25 -0
- package/numkong/javascript/@numkong-win32-arm64/package.json +25 -0
- package/numkong/javascript/@numkong-win32-x64/package.json +25 -0
- package/numkong/javascript/README.md +254 -0
- package/numkong/javascript/node-gyp-build.d.ts +4 -0
- package/numkong/javascript/numkong-browser.ts +40 -0
- package/numkong/javascript/numkong-wasm.ts +750 -0
- package/numkong/javascript/numkong.c +712 -0
- package/numkong/javascript/numkong.ts +613 -0
- package/{simsimd → numkong}/javascript/tsconfig-base.json +6 -3
- package/numkong/javascript/tsconfig-cjs.json +13 -0
- package/{simsimd → numkong}/javascript/tsconfig-esm.json +1 -1
- package/numkong/javascript/types.ts +784 -0
- package/numkong/numkong.gypi +104 -0
- package/numkong/package.json +108 -0
- package/numkong/probes/arm_neon.c +8 -0
- package/numkong/probes/arm_neon_bfdot.c +9 -0
- package/numkong/probes/arm_neon_fhm.c +9 -0
- package/numkong/probes/arm_neon_half.c +8 -0
- package/numkong/probes/arm_neon_sdot.c +9 -0
- package/numkong/probes/arm_neonfp8.c +9 -0
- package/numkong/probes/arm_sme.c +16 -0
- package/numkong/probes/arm_sme2.c +16 -0
- package/numkong/probes/arm_sme2p1.c +16 -0
- package/numkong/probes/arm_sme_bf16.c +16 -0
- package/numkong/probes/arm_sme_bi32.c +16 -0
- package/numkong/probes/arm_sme_f64.c +16 -0
- package/numkong/probes/arm_sme_fa64.c +14 -0
- package/numkong/probes/arm_sme_half.c +16 -0
- package/numkong/probes/arm_sme_lut2.c +15 -0
- package/numkong/probes/arm_sve.c +18 -0
- package/numkong/probes/arm_sve2.c +20 -0
- package/numkong/probes/arm_sve2p1.c +18 -0
- package/numkong/probes/arm_sve_bfdot.c +20 -0
- package/numkong/probes/arm_sve_half.c +18 -0
- package/numkong/probes/arm_sve_sdot.c +21 -0
- package/numkong/probes/loongarch_lasx.c +12 -0
- package/numkong/probes/power_vsx.c +12 -0
- package/numkong/probes/probe.js +127 -0
- package/numkong/probes/riscv_rvv.c +14 -0
- package/numkong/probes/riscv_rvv_bb.c +15 -0
- package/numkong/probes/riscv_rvv_bf16.c +17 -0
- package/numkong/probes/riscv_rvv_half.c +14 -0
- package/numkong/probes/wasm_v128relaxed.c +11 -0
- package/numkong/probes/x86_alder.c +17 -0
- package/numkong/probes/x86_diamond.c +17 -0
- package/numkong/probes/x86_genoa.c +17 -0
- package/numkong/probes/x86_graniteamx.c +19 -0
- package/numkong/probes/x86_haswell.c +11 -0
- package/numkong/probes/x86_icelake.c +17 -0
- package/numkong/probes/x86_sapphire.c +16 -0
- package/numkong/probes/x86_sapphireamx.c +18 -0
- package/numkong/probes/x86_sierra.c +17 -0
- package/numkong/probes/x86_skylake.c +15 -0
- package/numkong/probes/x86_turin.c +17 -0
- package/numkong/rust/README.md +698 -0
- package/numkong/rust/capabilities.rs +96 -0
- package/numkong/rust/cast.rs +314 -0
- package/numkong/rust/curved.rs +391 -0
- package/numkong/rust/each.rs +2721 -0
- package/numkong/rust/geospatial.rs +343 -0
- package/numkong/rust/matrix.rs +5424 -0
- package/numkong/rust/maxsim.rs +540 -0
- package/numkong/rust/mesh.rs +837 -0
- package/numkong/rust/numkong.rs +409 -0
- package/numkong/rust/probability.rs +272 -0
- package/numkong/rust/reduce.rs +1249 -0
- package/numkong/rust/set.rs +194 -0
- package/numkong/rust/sparse.rs +513 -0
- package/numkong/rust/spatial.rs +1815 -0
- package/numkong/rust/tensor.rs +7565 -0
- package/numkong/rust/types.rs +3666 -0
- package/numkong/rust/vector.rs +1899 -0
- package/numkong/rustfmt.toml +2 -0
- package/numkong/swift/Matrix.swift +1388 -0
- package/numkong/swift/MaxSim.swift +151 -0
- package/numkong/swift/NumKong.swift +283 -0
- package/numkong/swift/Numerics.swift +329 -0
- package/numkong/swift/README.md +433 -0
- package/numkong/swift/Scalar.swift +741 -0
- package/numkong/swift/Tensor.swift +209 -0
- package/numkong/test/README.md +315 -0
- package/numkong/test/playwright.config.ts +16 -0
- package/numkong/test/swift/Test.swift +534 -0
- package/numkong/test/test-browser-bundle-runner.mjs +36 -0
- package/numkong/test/test-browser-bundle.html +188 -0
- package/numkong/test/test-browser-runner.mjs +43 -0
- package/numkong/test/test-browser.html +305 -0
- package/numkong/test/test-dtypes.mjs +453 -0
- package/numkong/test/test-wasm.mjs +267 -0
- package/numkong/test/test.cpp +442 -0
- package/numkong/test/test.hpp +580 -0
- package/numkong/test/test.mjs +363 -0
- package/numkong/test/test_base.py +1041 -0
- package/numkong/test/test_cast.cpp +242 -0
- package/numkong/test/test_cross.hpp +551 -0
- package/numkong/test/test_cross.py +467 -0
- package/numkong/test/test_cross_amx.cpp +50 -0
- package/numkong/test/test_cross_arm.cpp +225 -0
- package/numkong/test/test_cross_blas.cpp +354 -0
- package/numkong/test/test_cross_loongarch.cpp +90 -0
- package/numkong/test/test_cross_power.cpp +73 -0
- package/numkong/test/test_cross_rvv.cpp +109 -0
- package/numkong/test/test_cross_serial.cpp +181 -0
- package/numkong/test/test_cross_sme.cpp +148 -0
- package/numkong/test/test_cross_wasm.cpp +141 -0
- package/numkong/test/test_cross_x86.cpp +442 -0
- package/numkong/test/test_curved.cpp +182 -0
- package/numkong/test/test_curved.py +207 -0
- package/numkong/test/test_dot.cpp +353 -0
- package/numkong/test/test_dot.py +296 -0
- package/numkong/test/test_each.cpp +437 -0
- package/numkong/test/test_each.py +756 -0
- package/numkong/test/test_geospatial.cpp +155 -0
- package/numkong/test/test_geospatial.py +241 -0
- package/numkong/test/test_maxsim.cpp +138 -0
- package/numkong/test/test_maxsim.py +209 -0
- package/numkong/test/test_mesh.cpp +203 -0
- package/numkong/test/test_mesh.py +394 -0
- package/numkong/test/test_probability.cpp +136 -0
- package/numkong/test/test_probability.py +166 -0
- package/numkong/test/test_reduce.cpp +563 -0
- package/numkong/test/test_reduce.py +781 -0
- package/numkong/test/test_set.cpp +151 -0
- package/numkong/test/test_set.py +120 -0
- package/numkong/test/test_similarities.py +579 -0
- package/numkong/test/test_sparse.cpp +121 -0
- package/numkong/test/test_sparse.py +118 -0
- package/numkong/test/test_spatial.cpp +518 -0
- package/numkong/test/test_spatial.py +269 -0
- package/numkong/test/test_tensor.cpp +884 -0
- package/numkong/test/test_tensor.py +1417 -0
- package/numkong/test/test_trigonometry.cpp +156 -0
- package/numkong/test/test_trigonometry.py +180 -0
- package/package.json +7 -8
- package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
- package/prebuilds/linux-arm64/usearch.node +0 -0
- package/prebuilds/linux-x64/usearch.node +0 -0
- package/fp16/CMakeLists.txt +0 -176
- package/fp16/LICENSE +0 -11
- package/fp16/README.md +0 -20
- package/fp16/bench/alt-element.cc +0 -89
- package/fp16/bench/from-alt-array.cc +0 -175
- package/fp16/bench/from-ieee-array.cc +0 -399
- package/fp16/bench/ieee-element.cc +0 -272
- package/fp16/bench/to-alt-array.cc +0 -91
- package/fp16/bench/to-ieee-array.cc +0 -303
- package/fp16/cmake/DownloadGoogleBenchmark.cmake +0 -15
- package/fp16/cmake/DownloadGoogleTest.cmake +0 -15
- package/fp16/cmake/DownloadPSimd.cmake +0 -15
- package/fp16/configure.py +0 -65
- package/fp16/confu.yaml +0 -8
- package/fp16/include/fp16/__init__.py +0 -0
- package/fp16/include/fp16/avx.py +0 -50
- package/fp16/include/fp16/avx2.py +0 -53
- package/fp16/include/fp16/bitcasts.h +0 -92
- package/fp16/include/fp16/fp16.h +0 -451
- package/fp16/include/fp16/psimd.h +0 -131
- package/fp16/include/fp16.h +0 -11
- package/fp16/jni/Android.mk +0 -6
- package/fp16/jni/Application.mk +0 -4
- package/fp16/test/alt-from-fp32-value.cc +0 -498
- package/fp16/test/alt-to-fp32-bits.cc +0 -263
- package/fp16/test/alt-to-fp32-psimd.cc +0 -145
- package/fp16/test/alt-to-fp32-value.cc +0 -348
- package/fp16/test/alt-to-fp32x2-psimd.cc +0 -245
- package/fp16/test/bitcasts.cc +0 -56
- package/fp16/test/ieee-from-fp32-value.cc +0 -523
- package/fp16/test/ieee-to-fp32-bits.cc +0 -333
- package/fp16/test/ieee-to-fp32-psimd.cc +0 -312
- package/fp16/test/ieee-to-fp32-value.cc +0 -420
- package/fp16/test/ieee-to-fp32x2-psimd.cc +0 -541
- package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +0 -96
- package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +0 -96
- package/fp16/test/peachpy/stubs.py +0 -38
- package/fp16/test/tables.cc +0 -530
- package/fp16/test/tables.h +0 -13
- package/fp16/third-party/THHalf.h +0 -92
- package/fp16/third-party/eigen-half.h +0 -170
- package/fp16/third-party/float16-compressor.h +0 -80
- package/fp16/third-party/half.hpp +0 -2916
- package/fp16/third-party/npy-halffloat.h +0 -328
- package/simsimd/.git-blame-ignore-revs +0 -2
- package/simsimd/CONTRIBUTING.md +0 -321
- package/simsimd/Cargo.toml +0 -49
- package/simsimd/MANIFEST.in +0 -4
- package/simsimd/Package.swift +0 -28
- package/simsimd/README.md +0 -1493
- package/simsimd/binding.gyp +0 -35
- package/simsimd/build.rs +0 -70
- package/simsimd/c/lib.c +0 -374
- package/simsimd/include/module.modulemap +0 -4
- package/simsimd/include/simsimd/binary.h +0 -486
- package/simsimd/include/simsimd/curved.h +0 -1541
- package/simsimd/include/simsimd/dot.h +0 -1853
- package/simsimd/include/simsimd/elementwise.h +0 -2465
- package/simsimd/include/simsimd/geospatial.h +0 -43
- package/simsimd/include/simsimd/mesh.h +0 -69
- package/simsimd/include/simsimd/probability.h +0 -606
- package/simsimd/include/simsimd/simsimd.h +0 -2567
- package/simsimd/include/simsimd/sparse.h +0 -1384
- package/simsimd/include/simsimd/spatial.h +0 -2335
- package/simsimd/include/simsimd/types.h +0 -666
- package/simsimd/javascript/fallback.ts +0 -233
- package/simsimd/javascript/lib.c +0 -125
- package/simsimd/javascript/node-gyp-build.d.ts +0 -1
- package/simsimd/javascript/simsimd.ts +0 -179
- package/simsimd/javascript/tsconfig-cjs.json +0 -8
- package/simsimd/package-lock.json +0 -1761
- package/simsimd/package.json +0 -61
- package/simsimd/rust/lib.rs +0 -1821
- package/simsimd/scripts/bench.cxx +0 -1170
- package/simsimd/scripts/bench.ipynb +0 -187
- package/simsimd/scripts/bench.js +0 -127
- package/simsimd/scripts/bench.rs +0 -876
- package/simsimd/scripts/bench_vectors.py +0 -734
- package/simsimd/scripts/bench_vectors_live.py +0 -213
- package/simsimd/scripts/test.c +0 -187
- package/simsimd/scripts/test.mjs +0 -220
- package/simsimd/scripts/test.py +0 -1505
- package/simsimd/swift/SimSIMD.swift +0 -149
- package/simsimd/swift/Test.swift +0 -128
- /package/{simsimd → numkong}/CODE_OF_CONDUCT.md +0 -0
- /package/{simsimd → numkong}/LICENSE +0 -0
- /package/{simsimd → numkong}/javascript/dist-package-cjs.json +0 -0
- /package/{simsimd → numkong}/javascript/dist-package-esm.json +0 -0
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
#define UNUM_USEARCH_HPP
|
|
9
9
|
|
|
10
10
|
#define USEARCH_VERSION_MAJOR 2
|
|
11
|
-
#define USEARCH_VERSION_MINOR
|
|
12
|
-
#define USEARCH_VERSION_PATCH
|
|
11
|
+
#define USEARCH_VERSION_MINOR 25
|
|
12
|
+
#define USEARCH_VERSION_PATCH 1
|
|
13
13
|
|
|
14
14
|
// Inferring C++ version
|
|
15
15
|
// https://stackoverflow.com/a/61552074
|
|
@@ -72,7 +72,9 @@
|
|
|
72
72
|
// OS-specific includes
|
|
73
73
|
#if defined(USEARCH_DEFINED_WINDOWS)
|
|
74
74
|
#define _USE_MATH_DEFINES
|
|
75
|
+
#ifndef NOMINMAX
|
|
75
76
|
#define NOMINMAX
|
|
77
|
+
#endif
|
|
76
78
|
#include <Windows.h>
|
|
77
79
|
#include <sys/stat.h> // `fstat` for file size
|
|
78
80
|
#undef NOMINMAX
|
|
@@ -500,7 +502,7 @@ template <typename allocator_at = std::allocator<byte_t>> class bitset_gt {
|
|
|
500
502
|
|
|
501
503
|
static constexpr std::size_t bits_per_slot() { return sizeof(compressed_slot_t) * CHAR_BIT; }
|
|
502
504
|
static constexpr compressed_slot_t bits_mask() { return sizeof(compressed_slot_t) * CHAR_BIT - 1; }
|
|
503
|
-
static constexpr std::size_t
|
|
505
|
+
static constexpr std::size_t bits_slots(std::size_t bits) { return divide_round_up<bits_per_slot()>(bits); }
|
|
504
506
|
|
|
505
507
|
compressed_slot_t* slots_{};
|
|
506
508
|
/// @brief Number of slots.
|
|
@@ -524,8 +526,8 @@ template <typename allocator_at = std::allocator<byte_t>> class bitset_gt {
|
|
|
524
526
|
}
|
|
525
527
|
|
|
526
528
|
bitset_gt(std::size_t capacity) noexcept
|
|
527
|
-
: slots_((compressed_slot_t*)allocator_t{}.allocate(
|
|
528
|
-
count_(slots_ ?
|
|
529
|
+
: slots_((compressed_slot_t*)allocator_t{}.allocate(bits_slots(capacity) * sizeof(compressed_slot_t))),
|
|
530
|
+
count_(slots_ ? bits_slots(capacity) : 0u) {
|
|
529
531
|
clear();
|
|
530
532
|
}
|
|
531
533
|
|
|
@@ -595,6 +597,125 @@ template <typename allocator_at = std::allocator<byte_t>> class bitset_gt {
|
|
|
595
597
|
|
|
596
598
|
using bitset_t = bitset_gt<>;
|
|
597
599
|
|
|
600
|
+
/**
|
|
601
|
+
* @brief Cache-line-padded striped spin-lock array for concurrent graph mutations.
|
|
602
|
+
* Maps node slots to lock stripes via Fibonacci hashing, with each stripe
|
|
603
|
+
* occupying its own cache line to eliminate false sharing.
|
|
604
|
+
* The number of stripes is proportional to `threads * connectivity`, not
|
|
605
|
+
* graph size, keeping the lock array comfortably within L2/L3 cache.
|
|
606
|
+
*/
|
|
607
|
+
template <typename allocator_at = std::allocator<byte_t>, std::size_t cache_line_ak = 128> //
|
|
608
|
+
class striped_locks_gt {
|
|
609
|
+
using allocator_t = allocator_at;
|
|
610
|
+
using byte_t = typename allocator_t::value_type;
|
|
611
|
+
static_assert(sizeof(byte_t) == 1, "Allocator must allocate separate addressable bytes");
|
|
612
|
+
|
|
613
|
+
static constexpr std::uint64_t fibonacci_k = 0x9E3779B97F4A7C15ull;
|
|
614
|
+
|
|
615
|
+
using atomic_flag_t = std::atomic<std::uint8_t>;
|
|
616
|
+
struct alignas(cache_line_ak) padded_lock_t {
|
|
617
|
+
atomic_flag_t flag{0};
|
|
618
|
+
char padding_[cache_line_ak - sizeof(atomic_flag_t)];
|
|
619
|
+
};
|
|
620
|
+
static_assert(sizeof(padded_lock_t) == cache_line_ak, "Lock stripe must be exactly one cache line");
|
|
621
|
+
|
|
622
|
+
// `padded_lock_t` is `alignas(cache_line_ak)` (128 B by default) which
|
|
623
|
+
// exceeds what a plain allocator guarantees (typically 16 B on x86-64).
|
|
624
|
+
// Rather than demanding an over-aligned allocator, we over-allocate and
|
|
625
|
+
// keep a pointer to the aligned sub-region — `raw_` is what we hand back
|
|
626
|
+
// to the allocator, `stripes_` is the aligned view used for reads/writes.
|
|
627
|
+
byte_t* raw_{};
|
|
628
|
+
std::size_t raw_bytes_{};
|
|
629
|
+
padded_lock_t* stripes_{};
|
|
630
|
+
std::size_t count_{};
|
|
631
|
+
unsigned shift_{};
|
|
632
|
+
|
|
633
|
+
inline std::size_t stripe_for_(std::size_t slot) const noexcept {
|
|
634
|
+
return static_cast<std::size_t>((static_cast<std::uint64_t>(slot) * fibonacci_k) >> shift_);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
public:
|
|
638
|
+
striped_locks_gt() noexcept {}
|
|
639
|
+
~striped_locks_gt() noexcept { reset(); }
|
|
640
|
+
|
|
641
|
+
explicit operator bool() const noexcept { return stripes_; }
|
|
642
|
+
|
|
643
|
+
void reset() noexcept {
|
|
644
|
+
if (stripes_)
|
|
645
|
+
for (std::size_t i = 0; i < count_; i++)
|
|
646
|
+
stripes_[i].~padded_lock_t();
|
|
647
|
+
if (raw_)
|
|
648
|
+
allocator_t{}.deallocate(raw_, raw_bytes_);
|
|
649
|
+
raw_ = nullptr;
|
|
650
|
+
raw_bytes_ = 0;
|
|
651
|
+
stripes_ = nullptr;
|
|
652
|
+
count_ = 0;
|
|
653
|
+
shift_ = 64;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
striped_locks_gt(std::size_t threads, std::size_t connectivity) noexcept {
|
|
657
|
+
std::size_t desired = threads * connectivity * 4;
|
|
658
|
+
if (desired < 256)
|
|
659
|
+
desired = 256;
|
|
660
|
+
count_ = ceil2(desired);
|
|
661
|
+
shift_ = 64;
|
|
662
|
+
for (std::size_t n = count_; n > 1; n >>= 1)
|
|
663
|
+
shift_--;
|
|
664
|
+
// Request one extra stripe's worth of slack so we can always land on a
|
|
665
|
+
// `cache_line_ak`-aligned address inside the allocation, regardless of
|
|
666
|
+
// what the underlying allocator returns.
|
|
667
|
+
constexpr std::size_t alignment_k = alignof(padded_lock_t);
|
|
668
|
+
raw_bytes_ = count_ * sizeof(padded_lock_t) + alignment_k;
|
|
669
|
+
raw_ = allocator_t{}.allocate(raw_bytes_);
|
|
670
|
+
if (!raw_) {
|
|
671
|
+
raw_bytes_ = 0;
|
|
672
|
+
count_ = 0;
|
|
673
|
+
shift_ = 64;
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
auto raw_address = reinterpret_cast<std::uintptr_t>(raw_);
|
|
677
|
+
auto aligned_address = (raw_address + alignment_k - 1) & ~(static_cast<std::uintptr_t>(alignment_k) - 1);
|
|
678
|
+
stripes_ = reinterpret_cast<padded_lock_t*>(aligned_address);
|
|
679
|
+
for (std::size_t i = 0; i < count_; i++)
|
|
680
|
+
new (&stripes_[i]) padded_lock_t();
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
striped_locks_gt(striped_locks_gt&& other) noexcept {
|
|
684
|
+
raw_ = exchange(other.raw_, (byte_t*)nullptr);
|
|
685
|
+
raw_bytes_ = exchange(other.raw_bytes_, std::size_t{0});
|
|
686
|
+
stripes_ = exchange(other.stripes_, nullptr);
|
|
687
|
+
count_ = exchange(other.count_, std::size_t{0});
|
|
688
|
+
shift_ = exchange(other.shift_, unsigned{64});
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
striped_locks_gt& operator=(striped_locks_gt&& other) noexcept {
|
|
692
|
+
std::swap(raw_, other.raw_);
|
|
693
|
+
std::swap(raw_bytes_, other.raw_bytes_);
|
|
694
|
+
std::swap(stripes_, other.stripes_);
|
|
695
|
+
std::swap(count_, other.count_);
|
|
696
|
+
std::swap(shift_, other.shift_);
|
|
697
|
+
return *this;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
striped_locks_gt(striped_locks_gt const&) = delete;
|
|
701
|
+
striped_locks_gt& operator=(striped_locks_gt const&) = delete;
|
|
702
|
+
|
|
703
|
+
inline bool atomic_set(std::size_t i) noexcept {
|
|
704
|
+
return stripes_[stripe_for_(i)].flag.exchange(1, std::memory_order_acquire);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
inline void atomic_reset(std::size_t i) noexcept {
|
|
708
|
+
stripes_[stripe_for_(i)].flag.store(0, std::memory_order_release);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
inline void lock(std::size_t i) noexcept {
|
|
712
|
+
while (atomic_set(i))
|
|
713
|
+
std::this_thread::yield();
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
inline void unlock(std::size_t i) noexcept { atomic_reset(i); }
|
|
717
|
+
};
|
|
718
|
+
|
|
598
719
|
/**
|
|
599
720
|
* @brief Similar to `std::priority_queue`, but allows raw access to underlying
|
|
600
721
|
* memory, in case you want to shuffle it or sort. Good for collections
|
|
@@ -726,10 +847,12 @@ class max_heap_gt {
|
|
|
726
847
|
*/
|
|
727
848
|
usearch_profiled_m bool reserve(std::size_t new_capacity) noexcept {
|
|
728
849
|
usearch_profile_name_m(max_heap_reserve);
|
|
729
|
-
if (new_capacity
|
|
850
|
+
if (new_capacity <= capacity_)
|
|
730
851
|
return true;
|
|
731
852
|
|
|
732
853
|
new_capacity = ceil2(new_capacity);
|
|
854
|
+
if (new_capacity == 0)
|
|
855
|
+
return false;
|
|
733
856
|
new_capacity = (std::max<std::size_t>)(new_capacity, (std::max<std::size_t>)(capacity_ * 2u, 16u));
|
|
734
857
|
auto allocator = allocator_t{};
|
|
735
858
|
auto new_elements = allocator.allocate(new_capacity);
|
|
@@ -892,10 +1015,12 @@ class sorted_buffer_gt {
|
|
|
892
1015
|
inline void clear() noexcept { size_ = 0; }
|
|
893
1016
|
|
|
894
1017
|
bool reserve(std::size_t new_capacity) noexcept {
|
|
895
|
-
if (new_capacity
|
|
1018
|
+
if (new_capacity <= capacity_)
|
|
896
1019
|
return true;
|
|
897
1020
|
|
|
898
1021
|
new_capacity = ceil2(new_capacity);
|
|
1022
|
+
if (new_capacity == 0)
|
|
1023
|
+
return false;
|
|
899
1024
|
new_capacity = (std::max<std::size_t>)(new_capacity, (std::max<std::size_t>)(capacity_ * 2u, 16u));
|
|
900
1025
|
auto allocator = allocator_t{};
|
|
901
1026
|
auto new_elements = allocator.allocate(new_capacity);
|
|
@@ -1011,8 +1136,10 @@ class usearch_pack_m uint40_t {
|
|
|
1011
1136
|
return result;
|
|
1012
1137
|
}
|
|
1013
1138
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1139
|
+
/* Parenthesized declarator keeps MSVC's preprocessor from expanding
|
|
1140
|
+
* `max` / `min` against `<windows.h>`'s `max(a,b)` / `min(a,b)` macros. */
|
|
1141
|
+
inline static uint40_t(max)() noexcept { return uint40_t{}.broadcast(0xFF); }
|
|
1142
|
+
inline static uint40_t(min)() noexcept { return uint40_t{}.broadcast(0); }
|
|
1016
1143
|
|
|
1017
1144
|
inline bool operator==(uint40_t const& other) const noexcept { return std::memcmp(octets, other.octets, 5) == 0; }
|
|
1018
1145
|
inline bool operator!=(uint40_t const& other) const noexcept { return !(*this == other); }
|
|
@@ -1044,7 +1171,7 @@ template <typename element_at> struct default_free_value_gt {
|
|
|
1044
1171
|
template <typename sfinae_element_at = element_at,
|
|
1045
1172
|
typename std::enable_if<std::is_integral<sfinae_element_at>::value>::type* = nullptr>
|
|
1046
1173
|
static sfinae_element_at value() noexcept {
|
|
1047
|
-
return std::numeric_limits<element_at>::max();
|
|
1174
|
+
return (std::numeric_limits<element_at>::max)();
|
|
1048
1175
|
}
|
|
1049
1176
|
template <typename sfinae_element_at = element_at,
|
|
1050
1177
|
typename std::enable_if<!std::is_integral<sfinae_element_at>::value>::type* = nullptr>
|
|
@@ -1054,7 +1181,7 @@ template <typename element_at> struct default_free_value_gt {
|
|
|
1054
1181
|
};
|
|
1055
1182
|
|
|
1056
1183
|
template <> struct default_free_value_gt<uint40_t> {
|
|
1057
|
-
static uint40_t value() noexcept { return uint40_t::max(); }
|
|
1184
|
+
static uint40_t value() noexcept { return (uint40_t::max)(); }
|
|
1058
1185
|
};
|
|
1059
1186
|
|
|
1060
1187
|
template <typename element_at> element_at default_free_value() { return default_free_value_gt<element_at>::value(); }
|
|
@@ -1778,7 +1905,7 @@ class memory_mapped_file_t {
|
|
|
1778
1905
|
#if defined(USEARCH_DEFINED_WINDOWS)
|
|
1779
1906
|
|
|
1780
1907
|
HANDLE file_handle =
|
|
1781
|
-
|
|
1908
|
+
CreateFileA(path_, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
|
1782
1909
|
if (file_handle == INVALID_HANDLE_VALUE)
|
|
1783
1910
|
return result.failed("Opening file failed!");
|
|
1784
1911
|
|
|
@@ -2029,8 +2156,8 @@ class index_gt {
|
|
|
2029
2156
|
friend inline vector_key_t get_key(member_iterator_gt const& it) noexcept { return it.key(); }
|
|
2030
2157
|
|
|
2031
2158
|
// clang-format off
|
|
2032
|
-
member_iterator_gt operator++(int) noexcept {
|
|
2033
|
-
member_iterator_gt operator--(int) noexcept {
|
|
2159
|
+
member_iterator_gt operator++(int) noexcept { member_iterator_gt old(index_, slot_); ++(*this); return old; }
|
|
2160
|
+
member_iterator_gt operator--(int) noexcept { member_iterator_gt old(index_, slot_); --(*this); return old; }
|
|
2034
2161
|
member_iterator_gt operator+(difference_type d) noexcept { return member_iterator_gt(index_, static_cast<compressed_slot_t>(static_cast<std::size_t>(slot_) + d)); }
|
|
2035
2162
|
member_iterator_gt operator-(difference_type d) noexcept { return member_iterator_gt(index_, static_cast<compressed_slot_t>(static_cast<std::size_t>(slot_) - d)); }
|
|
2036
2163
|
member_iterator_gt& operator++() noexcept { slot_ = static_cast<compressed_slot_t>(static_cast<std::size_t>(slot_) + 1); return *this; }
|
|
@@ -2084,7 +2211,7 @@ class index_gt {
|
|
|
2084
2211
|
*/
|
|
2085
2212
|
static constexpr std::size_t node_head_bytes_() { return sizeof(vector_key_t) + sizeof(level_t); }
|
|
2086
2213
|
|
|
2087
|
-
using nodes_mutexes_t =
|
|
2214
|
+
using nodes_mutexes_t = striped_locks_gt<dynamic_allocator_t>;
|
|
2088
2215
|
|
|
2089
2216
|
using visits_hash_set_t = growing_hash_set_gt<compressed_slot_t, hash_gt<compressed_slot_t>, dynamic_allocator_t>;
|
|
2090
2217
|
|
|
@@ -2189,7 +2316,7 @@ class index_gt {
|
|
|
2189
2316
|
misaligned_store<compressed_slot_t>(tape_ + shift(i - removed_count), slot);
|
|
2190
2317
|
}
|
|
2191
2318
|
}
|
|
2192
|
-
misaligned_store<neighbors_count_t>(tape_, old_count - removed_count);
|
|
2319
|
+
misaligned_store<neighbors_count_t>(tape_, static_cast<neighbors_count_t>(old_count - removed_count));
|
|
2193
2320
|
return removed_count;
|
|
2194
2321
|
}
|
|
2195
2322
|
};
|
|
@@ -2507,7 +2634,8 @@ class index_gt {
|
|
|
2507
2634
|
return true;
|
|
2508
2635
|
}
|
|
2509
2636
|
|
|
2510
|
-
|
|
2637
|
+
std::size_t connectivity_max = (std::max)(config_.connectivity_base, config_.connectivity);
|
|
2638
|
+
nodes_mutexes_t new_mutexes(limits.threads(), connectivity_max);
|
|
2511
2639
|
buffer_gt<node_t, nodes_allocator_t> new_nodes(limits.members);
|
|
2512
2640
|
buffer_gt<context_t, contexts_allocator_t> new_contexts(limits.threads());
|
|
2513
2641
|
if (!new_nodes || !new_contexts || !new_mutexes)
|
|
@@ -2516,10 +2644,6 @@ class index_gt {
|
|
|
2516
2644
|
// Move the nodes info, and deallocate previous buffers.
|
|
2517
2645
|
if (nodes_)
|
|
2518
2646
|
std::memcpy(new_nodes.data(), nodes_.data(), sizeof(node_t) * size());
|
|
2519
|
-
|
|
2520
|
-
// Pre-reserve the capacity for `top_for_refine`, which always contains at most one more
|
|
2521
|
-
// element than the connectivity factors.
|
|
2522
|
-
std::size_t connectivity_max = (std::max)(config_.connectivity_base, config_.connectivity);
|
|
2523
2647
|
for (std::size_t i = 0; i != new_contexts.size(); ++i)
|
|
2524
2648
|
if (!new_contexts[i].top_for_refine.reserve(connectivity_max + 1))
|
|
2525
2649
|
return false;
|
|
@@ -2567,7 +2691,7 @@ class index_gt {
|
|
|
2567
2691
|
member_cref_t member;
|
|
2568
2692
|
distance_t distance;
|
|
2569
2693
|
|
|
2570
|
-
inline match_t() noexcept : member({nullptr, 0}), distance(std::numeric_limits<distance_t>::max()) {}
|
|
2694
|
+
inline match_t() noexcept : member({nullptr, 0}), distance((std::numeric_limits<distance_t>::max)()) {}
|
|
2571
2695
|
|
|
2572
2696
|
inline match_t(member_cref_t member, distance_t distance) noexcept : member(member), distance(distance) {}
|
|
2573
2697
|
|
|
@@ -2719,7 +2843,7 @@ class index_gt {
|
|
|
2719
2843
|
keys[i] = vector_key_t{};
|
|
2720
2844
|
distances[i] = std::numeric_limits<distance_t>::has_signaling_NaN
|
|
2721
2845
|
? std::numeric_limits<distance_t>::signaling_NaN()
|
|
2722
|
-
: std::numeric_limits<distance_t>::max();
|
|
2846
|
+
: (std::numeric_limits<distance_t>::max)();
|
|
2723
2847
|
}
|
|
2724
2848
|
return initialized_count;
|
|
2725
2849
|
}
|
|
@@ -2786,6 +2910,10 @@ class index_gt {
|
|
|
2786
2910
|
callback_at&& callback = callback_at{}, //
|
|
2787
2911
|
prefetch_at&& prefetch = prefetch_at{}) usearch_noexcept_m {
|
|
2788
2912
|
|
|
2913
|
+
// Zero expansion is meaningless, fall back to default
|
|
2914
|
+
if (!config.expansion)
|
|
2915
|
+
config.expansion = default_expansion_add();
|
|
2916
|
+
|
|
2789
2917
|
add_result_t result;
|
|
2790
2918
|
if (is_immutable())
|
|
2791
2919
|
return result.failed("Can't add to an immutable index");
|
|
@@ -3101,6 +3229,9 @@ class index_gt {
|
|
|
3101
3229
|
predicate_at&& predicate = predicate_at{}, //
|
|
3102
3230
|
prefetch_at&& prefetch = prefetch_at{}) const noexcept {
|
|
3103
3231
|
|
|
3232
|
+
if (!config.expansion)
|
|
3233
|
+
config.expansion = default_expansion_search();
|
|
3234
|
+
|
|
3104
3235
|
context_t& context = contexts_[config.thread];
|
|
3105
3236
|
cluster_result_t result;
|
|
3106
3237
|
if (!nodes_count_)
|
|
@@ -3179,7 +3310,7 @@ class index_gt {
|
|
|
3179
3310
|
continue;
|
|
3180
3311
|
|
|
3181
3312
|
++result.nodes;
|
|
3182
|
-
result.edges += neighbors_(node, level).size();
|
|
3313
|
+
result.edges += neighbors_(node, static_cast<level_t>(level)).size();
|
|
3183
3314
|
result.allocated_bytes += node_head_bytes_() + neighbors_bytes;
|
|
3184
3315
|
}
|
|
3185
3316
|
|
|
@@ -3801,12 +3932,11 @@ class index_gt {
|
|
|
3801
3932
|
struct node_lock_t {
|
|
3802
3933
|
nodes_mutexes_t& mutexes;
|
|
3803
3934
|
std::size_t slot;
|
|
3804
|
-
inline ~node_lock_t() noexcept { mutexes.
|
|
3935
|
+
inline ~node_lock_t() noexcept { mutexes.unlock(slot); }
|
|
3805
3936
|
};
|
|
3806
3937
|
|
|
3807
3938
|
inline node_lock_t node_lock_(std::size_t slot) const noexcept {
|
|
3808
|
-
|
|
3809
|
-
;
|
|
3939
|
+
nodes_mutexes_.lock(slot);
|
|
3810
3940
|
return {nodes_mutexes_, slot};
|
|
3811
3941
|
}
|
|
3812
3942
|
|
|
@@ -3814,18 +3944,17 @@ class index_gt {
|
|
|
3814
3944
|
nodes_mutexes_t& mutexes;
|
|
3815
3945
|
std::size_t slot;
|
|
3816
3946
|
inline ~optional_node_lock_t() noexcept {
|
|
3817
|
-
if (slot != std::numeric_limits<std::size_t>::max())
|
|
3818
|
-
mutexes.
|
|
3947
|
+
if (slot != (std::numeric_limits<std::size_t>::max)())
|
|
3948
|
+
mutexes.unlock(slot);
|
|
3819
3949
|
}
|
|
3820
3950
|
};
|
|
3821
3951
|
|
|
3822
3952
|
inline optional_node_lock_t optional_node_lock_(std::size_t slot, bool condition) const noexcept {
|
|
3823
3953
|
if (condition) {
|
|
3824
|
-
|
|
3825
|
-
;
|
|
3954
|
+
nodes_mutexes_.lock(slot);
|
|
3826
3955
|
return {nodes_mutexes_, slot};
|
|
3827
3956
|
} else {
|
|
3828
|
-
return {nodes_mutexes_, std::numeric_limits<std::size_t>::max()};
|
|
3957
|
+
return {nodes_mutexes_, (std::numeric_limits<std::size_t>::max)()};
|
|
3829
3958
|
}
|
|
3830
3959
|
}
|
|
3831
3960
|
|
|
@@ -3833,8 +3962,8 @@ class index_gt {
|
|
|
3833
3962
|
nodes_mutexes_t& mutexes;
|
|
3834
3963
|
std::size_t slot;
|
|
3835
3964
|
inline ~node_conditional_lock_t() noexcept {
|
|
3836
|
-
if (slot != std::numeric_limits<std::size_t>::max())
|
|
3837
|
-
mutexes.
|
|
3965
|
+
if (slot != (std::numeric_limits<std::size_t>::max)())
|
|
3966
|
+
mutexes.unlock(slot);
|
|
3838
3967
|
}
|
|
3839
3968
|
};
|
|
3840
3969
|
|
|
@@ -3842,10 +3971,10 @@ class index_gt {
|
|
|
3842
3971
|
bool& failed_to_acquire) const noexcept {
|
|
3843
3972
|
if (!condition) {
|
|
3844
3973
|
failed_to_acquire = false;
|
|
3845
|
-
return {nodes_mutexes_, std::numeric_limits<std::size_t>::max()};
|
|
3974
|
+
return {nodes_mutexes_, (std::numeric_limits<std::size_t>::max)()};
|
|
3846
3975
|
}
|
|
3847
3976
|
failed_to_acquire = nodes_mutexes_.atomic_set(slot);
|
|
3848
|
-
return {nodes_mutexes_, failed_to_acquire ? std::numeric_limits<std::size_t>::max() : slot};
|
|
3977
|
+
return {nodes_mutexes_, failed_to_acquire ? (std::numeric_limits<std::size_t>::max)() : slot};
|
|
3849
3978
|
}
|
|
3850
3979
|
|
|
3851
3980
|
template <typename metric_at, bool require_non_empty_ak = false>
|
|
@@ -3896,8 +4025,12 @@ class index_gt {
|
|
|
3896
4025
|
usearch_assert_m(close_slot != new_slot, "Self-loops are impossible");
|
|
3897
4026
|
usearch_assert_m(level <= close_node.level(), "Linking to missing level");
|
|
3898
4027
|
|
|
3899
|
-
//
|
|
3900
|
-
|
|
4028
|
+
// Skip to prevent duplicate entries in the neighbor list.
|
|
4029
|
+
if (std::find_if(close_header.begin(), close_header.end(),
|
|
4030
|
+
[new_slot](compressed_slot_t slot) { return slot == new_slot; }) != close_header.end()) {
|
|
4031
|
+
continue;
|
|
4032
|
+
}
|
|
4033
|
+
|
|
3901
4034
|
if (close_header.size() < connectivity_max) {
|
|
3902
4035
|
close_header.push_back(new_slot);
|
|
3903
4036
|
continue;
|
|
@@ -3912,7 +4045,7 @@ class index_gt {
|
|
|
3912
4045
|
// Export the results:
|
|
3913
4046
|
close_header.clear();
|
|
3914
4047
|
candidates_view_t top_view = refine_(metric, connectivity_max, top_for_refine, context,
|
|
3915
|
-
context.computed_distances_in_reverse_refines);
|
|
4048
|
+
context.computed_distances_in_reverse_refines, new_slot, value);
|
|
3916
4049
|
usearch_assert_m(top_view.size(), "This would lead to isolated nodes");
|
|
3917
4050
|
for (std::size_t idx = 0; idx != top_view.size(); idx++)
|
|
3918
4051
|
close_header.push_back(top_view[idx].slot);
|
|
@@ -3960,7 +4093,9 @@ class index_gt {
|
|
|
3960
4093
|
std::size_t progress) noexcept
|
|
3961
4094
|
: index_(index), neighbors_(neighbors), visits_(visits), current_(progress) {}
|
|
3962
4095
|
candidates_iterator_t operator++(int) noexcept {
|
|
3963
|
-
|
|
4096
|
+
candidates_iterator_t old(index_, neighbors_, visits_, current_);
|
|
4097
|
+
++(*this);
|
|
4098
|
+
return old;
|
|
3964
4099
|
}
|
|
3965
4100
|
candidates_iterator_t& operator++() noexcept {
|
|
3966
4101
|
++current_;
|
|
@@ -3999,12 +4134,13 @@ class index_gt {
|
|
|
3999
4134
|
if (!is_dummy<prefetch_at>())
|
|
4000
4135
|
prefetch(citerator_at(closest_slot), citerator_at(closest_slot) + 1);
|
|
4001
4136
|
|
|
4137
|
+
bool const need_lock = !is_immutable();
|
|
4002
4138
|
distance_t closest_dist = context.measure(query, citerator_at(closest_slot), metric);
|
|
4003
4139
|
for (level_t level = begin_level; level > end_level; --level) {
|
|
4004
4140
|
bool changed;
|
|
4005
4141
|
do {
|
|
4006
4142
|
changed = false;
|
|
4007
|
-
|
|
4143
|
+
optional_node_lock_t closest_lock = optional_node_lock_(closest_slot, need_lock);
|
|
4008
4144
|
neighbors_ref_t closest_neighbors = neighbors_non_base_(node_at_(closest_slot), level);
|
|
4009
4145
|
|
|
4010
4146
|
// Optional prefetching
|
|
@@ -4050,6 +4186,10 @@ class index_gt {
|
|
|
4050
4186
|
// At the very least we are going to explore the starting node and its neighbors
|
|
4051
4187
|
if (!visits.reserve(config_.connectivity_base + 1u))
|
|
4052
4188
|
return false;
|
|
4189
|
+
if (!top.reserve(top_limit))
|
|
4190
|
+
return false;
|
|
4191
|
+
if (!next.reserve(top_limit))
|
|
4192
|
+
return false;
|
|
4053
4193
|
|
|
4054
4194
|
// Optional prefetching
|
|
4055
4195
|
if (!is_dummy<prefetch_at>())
|
|
@@ -4127,6 +4267,10 @@ class index_gt {
|
|
|
4127
4267
|
// At the very least we are going to explore the starting node and its neighbors
|
|
4128
4268
|
if (!visits.reserve(config_.connectivity_base + 1u))
|
|
4129
4269
|
return false;
|
|
4270
|
+
if (!top.reserve(top_limit))
|
|
4271
|
+
return false;
|
|
4272
|
+
if (!next.reserve(top_limit))
|
|
4273
|
+
return false;
|
|
4130
4274
|
|
|
4131
4275
|
// Optional prefetching
|
|
4132
4276
|
if (!is_dummy<prefetch_at>())
|
|
@@ -4295,16 +4439,50 @@ class index_gt {
|
|
|
4295
4439
|
}
|
|
4296
4440
|
}
|
|
4297
4441
|
|
|
4442
|
+
/// @brief Helper for `refine_()`: computes inter-neighbor distance, substituting
|
|
4443
|
+
/// @p override_value when either slot matches @p override_slot.
|
|
4444
|
+
/// The `std::nullptr_t` overload below avoids instantiating the override
|
|
4445
|
+
/// branch when no override is provided, keeping the code C++11 compatible.
|
|
4446
|
+
template <typename metric_at, typename override_value_at>
|
|
4447
|
+
distance_t inter_neighbor_distance_( //
|
|
4448
|
+
candidate_t const& candidate, candidate_t const& submitted, //
|
|
4449
|
+
compressed_slot_t override_slot, override_value_at override_value, //
|
|
4450
|
+
metric_at&& metric, context_t& context) const noexcept {
|
|
4451
|
+
if (candidate.slot == override_slot)
|
|
4452
|
+
return context.measure(override_value, citerator_at(submitted.slot), metric);
|
|
4453
|
+
else if (submitted.slot == override_slot)
|
|
4454
|
+
return context.measure(override_value, citerator_at(candidate.slot), metric);
|
|
4455
|
+
else
|
|
4456
|
+
return context.measure(citerator_at(candidate.slot), citerator_at(submitted.slot), metric);
|
|
4457
|
+
}
|
|
4458
|
+
|
|
4459
|
+
template <typename metric_at>
|
|
4460
|
+
distance_t inter_neighbor_distance_( //
|
|
4461
|
+
candidate_t const& candidate, candidate_t const& submitted, //
|
|
4462
|
+
compressed_slot_t, std::nullptr_t, //
|
|
4463
|
+
metric_at&& metric, context_t& context) const noexcept {
|
|
4464
|
+
return context.measure(citerator_at(candidate.slot), citerator_at(submitted.slot), metric);
|
|
4465
|
+
}
|
|
4466
|
+
|
|
4298
4467
|
/**
|
|
4299
4468
|
* @brief This algorithm from the original paper implements a heuristic,
|
|
4300
4469
|
* that massively reduces the number of connections a point has,
|
|
4301
4470
|
* to keep only the neighbors, that are from each other.
|
|
4471
|
+
*
|
|
4472
|
+
* @param[in] override_slot Optional slot whose stored vector is stale (e.g. during update,
|
|
4473
|
+
* where the callback has not yet committed the new vector).
|
|
4474
|
+
* When set, inter-result distances involving this slot will use
|
|
4475
|
+
* @p override_value instead of reading from `citerator_at()`.
|
|
4476
|
+
* @param[in] override_value The up-to-date vector for @p override_slot. Only used when
|
|
4477
|
+
* @p override_value_at is not `std::nullptr_t`.
|
|
4302
4478
|
*/
|
|
4303
|
-
template <typename metric_at>
|
|
4479
|
+
template <typename metric_at, typename override_value_at = std::nullptr_t>
|
|
4304
4480
|
candidates_view_t refine_( //
|
|
4305
4481
|
metric_at&& metric, //
|
|
4306
4482
|
std::size_t needed, top_candidates_t& top, context_t& context, //
|
|
4307
|
-
std::size_t& refines_counter
|
|
4483
|
+
std::size_t& refines_counter, //
|
|
4484
|
+
compressed_slot_t override_slot = ((std::numeric_limits<compressed_slot_t>::max))(),
|
|
4485
|
+
override_value_at override_value = {}) const noexcept {
|
|
4308
4486
|
|
|
4309
4487
|
// Avoid expensive computation, if the set is already small
|
|
4310
4488
|
candidate_t* top_data = top.data();
|
|
@@ -4323,10 +4501,8 @@ class index_gt {
|
|
|
4323
4501
|
std::size_t idx = 0;
|
|
4324
4502
|
for (; idx < submitted_count; idx++) {
|
|
4325
4503
|
candidate_t submitted = top_data[idx];
|
|
4326
|
-
distance_t inter_result_dist =
|
|
4327
|
-
|
|
4328
|
-
citerator_at(submitted.slot), //
|
|
4329
|
-
metric);
|
|
4504
|
+
distance_t inter_result_dist = inter_neighbor_distance_( //
|
|
4505
|
+
candidate, submitted, override_slot, override_value, metric, context);
|
|
4330
4506
|
if (inter_result_dist < candidate.distance) {
|
|
4331
4507
|
good = false;
|
|
4332
4508
|
break;
|
|
@@ -4417,7 +4593,7 @@ static join_result_t join( //
|
|
|
4417
4593
|
return result.failed("Can't join with itself, consider copying");
|
|
4418
4594
|
|
|
4419
4595
|
if (config.max_proposals == 0)
|
|
4420
|
-
config.max_proposals = std::log(men.size()) + executor.size();
|
|
4596
|
+
config.max_proposals = static_cast<std::size_t>(std::log(men.size())) + executor.size();
|
|
4421
4597
|
|
|
4422
4598
|
using proposals_count_t = std::uint16_t;
|
|
4423
4599
|
config.max_proposals = (std::min)(men.size(), config.max_proposals);
|