Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'

This commit is contained in:
ruv
2026-02-28 14:39:40 -05:00
7854 changed files with 3522914 additions and 0 deletions

View File

@@ -0,0 +1,947 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "approx"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
dependencies = [
"num-traits",
]
[[package]]
name = "async-trait"
version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bumpalo"
version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
[[package]]
name = "bytemuck"
version = "1.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if",
"wasm-bindgen",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "find-msvc-tools"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41"
[[package]]
name = "futures-core"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-task"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-util"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "getrandom"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasm-bindgen",
]
[[package]]
name = "glam"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da"
[[package]]
name = "glam"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3abb554f8ee44336b72d522e0a7fe86a29e09f839a36022fa869a7dfe941a54b"
[[package]]
name = "glam"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4126c0479ccf7e8664c36a2d719f5f2c140fbb4f9090008098d2c291fa5b3f16"
[[package]]
name = "glam"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01732b97afd8508eee3333a541b9f7610f454bb818669e66e90f5f57c93a776"
[[package]]
name = "glam"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525a3e490ba77b8e326fb67d4b44b4bd2f920f44d4cc73ccec50adc68e3bee34"
[[package]]
name = "glam"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b8509e6791516e81c1a630d0bd7fbac36d2fa8712a9da8662e716b52d5051ca"
[[package]]
name = "glam"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f"
[[package]]
name = "glam"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815"
[[package]]
name = "glam"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774"
[[package]]
name = "glam"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c"
[[package]]
name = "glam"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"
[[package]]
name = "glam"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
[[package]]
name = "glam"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9"
[[package]]
name = "glam"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
[[package]]
name = "glam"
version = "0.29.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
[[package]]
name = "glam"
version = "0.30.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9"
[[package]]
name = "itoa"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
[[package]]
name = "js-sys"
version = "0.3.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.180"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "matrixmultiply"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
dependencies = [
"autocfg",
"rawpointer",
]
[[package]]
name = "memchr"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "minicov"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4869b6a491569605d66d3952bcdf03df789e5b536e5f0cf7758a7f08a55ae24d"
dependencies = [
"cc",
"walkdir",
]
[[package]]
name = "nalgebra"
version = "0.34.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4d5b3eff5cd580f93da45e64715e8c20a3996342f1e466599cf7a267a0c2f5f"
dependencies = [
"approx",
"glam 0.14.0",
"glam 0.15.2",
"glam 0.16.0",
"glam 0.17.3",
"glam 0.18.0",
"glam 0.19.0",
"glam 0.20.5",
"glam 0.21.3",
"glam 0.22.0",
"glam 0.23.0",
"glam 0.24.2",
"glam 0.25.0",
"glam 0.27.0",
"glam 0.28.0",
"glam 0.29.3",
"glam 0.30.10",
"matrixmultiply",
"nalgebra-macros",
"num-complex",
"num-rational",
"num-traits",
"simba",
"typenum",
]
[[package]]
name = "nalgebra-macros"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "973e7178a678cfd059ccec50887658d482ce16b0aa9da3888ddeab5cd5eb4889"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ndarray"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d"
dependencies = [
"matrixmultiply",
"num-complex",
"num-integer",
"num-traits",
"portable-atomic",
"portable-atomic-util",
"rawpointer",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"libm",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "oorandom"
version = "11.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "portable-atomic"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950"
[[package]]
name = "portable-atomic-util"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
dependencies = [
"portable-atomic",
]
[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_distr"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
dependencies = [
"num-traits",
"rand",
]
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]]
name = "rayon"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
"wasm_sync",
]
[[package]]
name = "rayon-core"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
"wasm_sync",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ruvector-hyperbolic-hnsw"
version = "0.1.0"
dependencies = [
"nalgebra",
"ndarray",
"rand",
"rand_distr",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "ruvector-hyperbolic-hnsw-wasm"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"getrandom",
"js-sys",
"rayon",
"ruvector-hyperbolic-hnsw",
"serde",
"serde-wasm-bindgen",
"serde_json",
"wasm-bindgen",
"wasm-bindgen-rayon",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "safe_arch"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
dependencies = [
"bytemuck",
]
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [
"itoa",
"memchr",
"serde",
"serde_core",
"zmij",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simba"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c99284beb21666094ba2b75bbceda012e610f5479dfcc2d6e2426f53197ffd95"
dependencies = [
"approx",
"num-complex",
"num-traits",
"paste",
"wide",
]
[[package]]
name = "slab"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
[[package]]
name = "syn"
version = "2.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasm-bindgen"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f"
dependencies = [
"cfg-if",
"futures-util",
"js-sys",
"once_cell",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-rayon"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a16c60a56c81e4dc3b9c43d76ba5633e1c0278211d59a9cb07d61b6cd1c6583"
dependencies = [
"crossbeam-channel",
"js-sys",
"rayon",
"wasm-bindgen",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
dependencies = [
"unicode-ident",
]
[[package]]
name = "wasm-bindgen-test"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45649196a53b0b7a15101d845d44d2dda7374fc1b5b5e2bbf58b7577ff4b346d"
dependencies = [
"async-trait",
"cast",
"js-sys",
"libm",
"minicov",
"nu-ansi-term",
"num-traits",
"oorandom",
"serde",
"serde_json",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
"wasm-bindgen-test-shared",
]
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f579cdd0123ac74b94e1a4a72bd963cf30ebac343f2df347da0b8df24cdebed2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "wasm-bindgen-test-shared"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8145dd1593bf0fb137dbfa85b8be79ec560a447298955877804640e40c2d6ea"
[[package]]
name = "wasm_sync"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff360cade7fec41ff0e9d2cda57fe58258c5f16def0e21302394659e6bbb0ea"
dependencies = [
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "web-sys"
version = "0.3.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wide"
version = "0.7.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
dependencies = [
"bytemuck",
"safe_arch",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "zerocopy"
version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zmij"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd8f3f50b848df28f887acb68e41201b5aea6bc8a8dacc00fb40635ff9a72fea"

View File

@@ -0,0 +1,37 @@
[package]
name = "ruvector-hyperbolic-hnsw-wasm"
version = "0.1.0"
edition = "2021"
rust-version = "1.77"
license = "MIT"
authors = ["RuVector Team"]
repository = "https://github.com/ruvnet/ruvector"
description = "WebAssembly bindings for hyperbolic HNSW embeddings - hierarchy-aware vector search in the browser"
keywords = ["wasm", "hyperbolic", "poincare", "hnsw", "vector-search"]
categories = ["wasm", "mathematics", "algorithms"]
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
parallel = ["rayon", "wasm-bindgen-rayon"]
[dependencies]
ruvector-hyperbolic-hnsw = { path = "../ruvector-hyperbolic-hnsw", default-features = false }
wasm-bindgen = "0.2.106"
js-sys = "0.3"
web-sys = { version = "0.3", features = ["console"] }
getrandom = { version = "0.2", features = ["js"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde-wasm-bindgen = "0.6"
console_error_panic_hook = { version = "0.1", optional = true }
rayon = { version = "1.10", optional = true }
wasm-bindgen-rayon = { version = "1.2", optional = true }
[package.metadata.wasm-pack.profile.release]
wasm-opt = ["-O3", "--enable-simd"]
[dev-dependencies]
wasm-bindgen-test = "0.3"

View File

@@ -0,0 +1,632 @@
//! WebAssembly Bindings for Hyperbolic HNSW
//!
//! This module provides JavaScript/TypeScript bindings for hyperbolic embeddings
//! and HNSW search in the browser and Node.js environments.
//!
//! # Usage in JavaScript
//!
//! ```javascript
//! import init, {
//! HyperbolicIndex,
//! poincareDistance,
//! mobiusAdd,
//! expMap,
//! logMap
//! } from 'ruvector-hyperbolic-hnsw-wasm';
//!
//! // Initialize WASM module
//! await init();
//!
//! // Create index
//! const index = new HyperbolicIndex(16, 1.0); // ef_search=16, curvature=1.0
//!
//! // Insert vectors
//! index.insert(new Float32Array([0.1, 0.2, 0.3]));
//! index.insert(new Float32Array([-0.1, 0.15, 0.25]));
//!
//! // Search
//! const results = index.search(new Float32Array([0.15, 0.1, 0.2]), 2);
//! console.log(results); // [{id: 0, distance: 0.123}, ...]
//!
//! // Use low-level math operations
//! const d = poincareDistance(
//! new Float32Array([0.3, 0.2]),
//! new Float32Array([-0.1, 0.4]),
//! 1.0
//! );
//! ```
use ruvector_hyperbolic_hnsw::{
exp_map, frechet_mean, log_map, mobius_add, mobius_scalar_mult, poincare_distance,
project_to_ball, HyperbolicHnsw, HyperbolicHnswConfig, PoincareConfig, ShardedHyperbolicHnsw,
TangentCache, DEFAULT_CURVATURE, EPS,
};
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
#[cfg(feature = "console_error_panic_hook")]
fn set_panic_hook() {
console_error_panic_hook::set_once();
}
/// Initialize the WASM module
#[wasm_bindgen(start)]
pub fn init() {
#[cfg(feature = "console_error_panic_hook")]
set_panic_hook();
}
// ============================================================================
// Low-Level Math Operations
// ============================================================================
/// Compute Poincaré distance between two points
///
/// @param u - First point (Float32Array)
/// @param v - Second point (Float32Array)
/// @param curvature - Curvature parameter (positive)
/// @returns Geodesic distance in hyperbolic space
#[wasm_bindgen(js_name = poincareDistance)]
pub fn wasm_poincare_distance(u: &[f32], v: &[f32], curvature: f32) -> f32 {
poincare_distance(u, v, curvature)
}
/// Möbius addition in Poincaré ball
///
/// Computes the hyperbolic analog of vector addition: x ⊕_c y
///
/// @param x - First point (Float32Array)
/// @param y - Second point (Float32Array)
/// @param curvature - Curvature parameter
/// @returns Result of Möbius addition (Float32Array)
#[wasm_bindgen(js_name = mobiusAdd)]
pub fn wasm_mobius_add(x: &[f32], y: &[f32], curvature: f32) -> Vec<f32> {
mobius_add(x, y, curvature)
}
/// Möbius scalar multiplication
///
/// Computes r ⊗_c x for scalar r and point x
///
/// @param r - Scalar value
/// @param x - Point in Poincaré ball (Float32Array)
/// @param curvature - Curvature parameter
/// @returns Scaled point (Float32Array)
#[wasm_bindgen(js_name = mobiusScalarMult)]
pub fn wasm_mobius_scalar_mult(r: f32, x: &[f32], curvature: f32) -> Vec<f32> {
mobius_scalar_mult(r, x, curvature)
}
/// Exponential map at point p
///
/// Maps a tangent vector v at point p to the Poincaré ball
///
/// @param v - Tangent vector (Float32Array)
/// @param p - Base point (Float32Array)
/// @param curvature - Curvature parameter
/// @returns Point on the manifold (Float32Array)
#[wasm_bindgen(js_name = expMap)]
pub fn wasm_exp_map(v: &[f32], p: &[f32], curvature: f32) -> Vec<f32> {
exp_map(v, p, curvature)
}
/// Logarithmic map at point p
///
/// Maps a point y to the tangent space at point p
///
/// @param y - Target point (Float32Array)
/// @param p - Base point (Float32Array)
/// @param curvature - Curvature parameter
/// @returns Tangent vector at p (Float32Array)
#[wasm_bindgen(js_name = logMap)]
pub fn wasm_log_map(y: &[f32], p: &[f32], curvature: f32) -> Vec<f32> {
log_map(y, p, curvature)
}
/// Project point to Poincaré ball
///
/// Ensures ||x|| < 1/√c - eps for numerical stability
///
/// @param x - Point to project (Float32Array)
/// @param curvature - Curvature parameter
/// @returns Projected point (Float32Array)
#[wasm_bindgen(js_name = projectToBall)]
pub fn wasm_project_to_ball(x: &[f32], curvature: f32) -> Vec<f32> {
project_to_ball(x, curvature, EPS)
}
/// Compute Fréchet mean (hyperbolic centroid)
///
/// @param points - Array of points as flat Float32Array
/// @param dim - Dimension of each point
/// @param curvature - Curvature parameter
/// @returns Centroid point (Float32Array)
#[wasm_bindgen(js_name = frechetMean)]
pub fn wasm_frechet_mean(points: &[f32], dim: usize, curvature: f32) -> Result<Vec<f32>, JsValue> {
if points.is_empty() || dim == 0 {
return Err(JsValue::from_str("Empty points or invalid dimension"));
}
let point_vecs: Vec<Vec<f32>> = points.chunks(dim).map(|c| c.to_vec()).collect();
let point_refs: Vec<&[f32]> = point_vecs.iter().map(|v| v.as_slice()).collect();
let config = PoincareConfig::with_curvature(curvature)
.map_err(|e| JsValue::from_str(&e.to_string()))?;
frechet_mean(&point_refs, None, &config).map_err(|e| JsValue::from_str(&e.to_string()))
}
// ============================================================================
// Search Result Type
// ============================================================================
/// Search result from hyperbolic HNSW
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct WasmSearchResult {
/// Vector ID
pub id: usize,
/// Hyperbolic distance to query
pub distance: f32,
}
#[wasm_bindgen]
impl WasmSearchResult {
#[wasm_bindgen(constructor)]
pub fn new(id: usize, distance: f32) -> Self {
Self { id, distance }
}
}
// ============================================================================
// Hyperbolic HNSW Index
// ============================================================================
/// Hyperbolic HNSW Index for hierarchy-aware vector search
///
/// @example
/// ```javascript
/// const index = new HyperbolicIndex(16, 1.0);
/// index.insert(new Float32Array([0.1, 0.2]));
/// index.insert(new Float32Array([-0.1, 0.3]));
/// const results = index.search(new Float32Array([0.05, 0.25]), 2);
/// ```
#[wasm_bindgen]
pub struct HyperbolicIndex {
inner: HyperbolicHnsw,
}
#[wasm_bindgen]
impl HyperbolicIndex {
/// Create a new hyperbolic HNSW index
///
/// @param ef_search - Size of dynamic candidate list during search (default: 50)
/// @param curvature - Curvature parameter for Poincaré ball (default: 1.0)
#[wasm_bindgen(constructor)]
pub fn new(ef_search: Option<usize>, curvature: Option<f32>) -> Self {
let mut config = HyperbolicHnswConfig::default();
config.ef_search = ef_search.unwrap_or(50);
config.curvature = curvature.unwrap_or(DEFAULT_CURVATURE);
Self {
inner: HyperbolicHnsw::new(config),
}
}
/// Create with custom configuration
///
/// @param config - JSON configuration object
#[wasm_bindgen(js_name = fromConfig)]
pub fn from_config(config: JsValue) -> Result<HyperbolicIndex, JsValue> {
let config: HyperbolicHnswConfig =
serde_wasm_bindgen::from_value(config).map_err(|e| JsValue::from_str(&e.to_string()))?;
Ok(Self {
inner: HyperbolicHnsw::new(config),
})
}
/// Insert a vector into the index
///
/// @param vector - Vector to insert (Float32Array)
/// @returns ID of inserted vector
#[wasm_bindgen]
pub fn insert(&mut self, vector: &[f32]) -> Result<usize, JsValue> {
self.inner
.insert(vector.to_vec())
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Insert batch of vectors
///
/// @param vectors - Flat array of vectors
/// @param dim - Dimension of each vector
/// @returns Array of inserted IDs
#[wasm_bindgen(js_name = insertBatch)]
pub fn insert_batch(&mut self, vectors: &[f32], dim: usize) -> Result<Vec<usize>, JsValue> {
let vecs: Vec<Vec<f32>> = vectors.chunks(dim).map(|c| c.to_vec()).collect();
self.inner
.insert_batch(vecs)
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Search for k nearest neighbors
///
/// @param query - Query vector (Float32Array)
/// @param k - Number of neighbors to return
/// @returns Array of search results as JSON
#[wasm_bindgen]
pub fn search(&self, query: &[f32], k: usize) -> Result<JsValue, JsValue> {
let results = self
.inner
.search(query, k)
.map_err(|e| JsValue::from_str(&e.to_string()))?;
let wasm_results: Vec<WasmSearchResult> = results
.into_iter()
.map(|r| WasmSearchResult::new(r.id, r.distance))
.collect();
serde_wasm_bindgen::to_value(&wasm_results).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Search with tangent space pruning (optimized)
///
/// @param query - Query vector (Float32Array)
/// @param k - Number of neighbors to return
/// @returns Array of search results as JSON
#[wasm_bindgen(js_name = searchWithPruning)]
pub fn search_with_pruning(&self, query: &[f32], k: usize) -> Result<JsValue, JsValue> {
let results = self
.inner
.search_with_pruning(query, k)
.map_err(|e| JsValue::from_str(&e.to_string()))?;
let wasm_results: Vec<WasmSearchResult> = results
.into_iter()
.map(|r| WasmSearchResult::new(r.id, r.distance))
.collect();
serde_wasm_bindgen::to_value(&wasm_results).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Build tangent cache for optimized search
#[wasm_bindgen(js_name = buildTangentCache)]
pub fn build_tangent_cache(&mut self) -> Result<(), JsValue> {
self.inner
.build_tangent_cache()
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get number of vectors in index
#[wasm_bindgen]
pub fn len(&self) -> usize {
self.inner.len()
}
/// Check if index is empty
#[wasm_bindgen(js_name = isEmpty)]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// Get vector dimension
#[wasm_bindgen]
pub fn dim(&self) -> Option<usize> {
self.inner.dim()
}
/// Update curvature parameter
///
/// @param curvature - New curvature value (must be positive)
#[wasm_bindgen(js_name = setCurvature)]
pub fn set_curvature(&mut self, curvature: f32) -> Result<(), JsValue> {
self.inner
.set_curvature(curvature)
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get a vector by ID
///
/// @param id - Vector ID
/// @returns Vector data or null if not found
#[wasm_bindgen(js_name = getVector)]
pub fn get_vector(&self, id: usize) -> Option<Vec<f32>> {
self.inner.get_vector(id).map(|v| v.to_vec())
}
/// Export index configuration as JSON
#[wasm_bindgen(js_name = exportConfig)]
pub fn export_config(&self) -> Result<JsValue, JsValue> {
serde_wasm_bindgen::to_value(&self.inner.config)
.map_err(|e| JsValue::from_str(&e.to_string()))
}
}
// ============================================================================
// Sharded Index
// ============================================================================
/// Sharded Hyperbolic HNSW with per-shard curvature
///
/// @example
/// ```javascript
/// const manager = new ShardedIndex(1.0);
/// manager.insertToShard("taxonomy", new Float32Array([0.1, 0.2]), 0);
/// manager.insertToShard("taxonomy", new Float32Array([0.3, 0.1]), 3);
/// manager.updateCurvature("taxonomy", 0.5);
/// const results = manager.search(new Float32Array([0.2, 0.15]), 5);
/// ```
#[wasm_bindgen]
pub struct ShardedIndex {
inner: ShardedHyperbolicHnsw,
}
#[wasm_bindgen]
impl ShardedIndex {
/// Create a new sharded index
///
/// @param default_curvature - Default curvature for new shards
#[wasm_bindgen(constructor)]
pub fn new(default_curvature: f32) -> Self {
Self {
inner: ShardedHyperbolicHnsw::new(default_curvature),
}
}
/// Insert vector with automatic shard assignment
///
/// @param vector - Vector to insert (Float32Array)
/// @param depth - Optional hierarchy depth for shard assignment
/// @returns Global vector ID
#[wasm_bindgen]
pub fn insert(&mut self, vector: &[f32], depth: Option<usize>) -> Result<usize, JsValue> {
self.inner
.insert(vector.to_vec(), depth)
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Insert vector into specific shard
///
/// @param shard_id - Target shard ID
/// @param vector - Vector to insert (Float32Array)
/// @returns Global vector ID
#[wasm_bindgen(js_name = insertToShard)]
pub fn insert_to_shard(&mut self, shard_id: &str, vector: &[f32]) -> Result<usize, JsValue> {
self.inner
.insert_to_shard(shard_id, vector.to_vec())
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Search across all shards
///
/// @param query - Query vector (Float32Array)
/// @param k - Number of neighbors to return
/// @returns Array of search results as JSON
#[wasm_bindgen]
pub fn search(&self, query: &[f32], k: usize) -> Result<JsValue, JsValue> {
let results = self
.inner
.search(query, k)
.map_err(|e| JsValue::from_str(&e.to_string()))?;
let wasm_results: Vec<WasmSearchResult> = results
.into_iter()
.map(|(id, r)| WasmSearchResult::new(id, r.distance))
.collect();
serde_wasm_bindgen::to_value(&wasm_results).map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Update curvature for a shard
///
/// @param shard_id - Shard ID
/// @param curvature - New curvature value
#[wasm_bindgen(js_name = updateCurvature)]
pub fn update_curvature(&mut self, shard_id: &str, curvature: f32) -> Result<(), JsValue> {
self.inner
.update_curvature(shard_id, curvature)
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Set canary curvature for A/B testing
///
/// @param shard_id - Shard ID
/// @param curvature - Canary curvature value
/// @param traffic - Percentage of traffic for canary (0-100)
#[wasm_bindgen(js_name = setCanaryCurvature)]
pub fn set_canary_curvature(&mut self, shard_id: &str, curvature: f32, traffic: u8) {
self.inner.registry.set_canary(shard_id, curvature, traffic);
}
/// Promote canary to production
///
/// @param shard_id - Shard ID
#[wasm_bindgen(js_name = promoteCanary)]
pub fn promote_canary(&mut self, shard_id: &str) -> Result<(), JsValue> {
if let Some(shard_curv) = self.inner.registry.shards.get_mut(shard_id) {
shard_curv.promote_canary();
}
self.inner
.reload_curvatures()
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Rollback canary
///
/// @param shard_id - Shard ID
#[wasm_bindgen(js_name = rollbackCanary)]
pub fn rollback_canary(&mut self, shard_id: &str) {
if let Some(shard_curv) = self.inner.registry.shards.get_mut(shard_id) {
shard_curv.rollback_canary();
}
}
/// Build tangent caches for all shards
#[wasm_bindgen(js_name = buildCaches)]
pub fn build_caches(&mut self) -> Result<(), JsValue> {
self.inner
.build_caches()
.map_err(|e| JsValue::from_str(&e.to_string()))
}
/// Get total vector count
#[wasm_bindgen]
pub fn len(&self) -> usize {
self.inner.len()
}
/// Check if empty
#[wasm_bindgen(js_name = isEmpty)]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
/// Get number of shards
#[wasm_bindgen(js_name = numShards)]
pub fn num_shards(&self) -> usize {
self.inner.num_shards()
}
/// Get curvature registry as JSON
#[wasm_bindgen(js_name = getRegistry)]
pub fn get_registry(&self) -> Result<JsValue, JsValue> {
serde_wasm_bindgen::to_value(&self.inner.registry)
.map_err(|e| JsValue::from_str(&e.to_string()))
}
}
// ============================================================================
// Tangent Cache Operations
// ============================================================================
/// Tangent space cache for fast pruning
#[wasm_bindgen]
pub struct WasmTangentCache {
inner: TangentCache,
}
#[wasm_bindgen]
impl WasmTangentCache {
/// Create tangent cache from points
///
/// @param points - Flat array of points
/// @param dim - Dimension of each point
/// @param curvature - Curvature parameter
#[wasm_bindgen(constructor)]
pub fn new(points: &[f32], dim: usize, curvature: f32) -> Result<WasmTangentCache, JsValue> {
let point_vecs: Vec<Vec<f32>> = points.chunks(dim).map(|c| c.to_vec()).collect();
let indices: Vec<usize> = (0..point_vecs.len()).collect();
let cache = TangentCache::new(&point_vecs, &indices, curvature)
.map_err(|e| JsValue::from_str(&e.to_string()))?;
Ok(Self { inner: cache })
}
/// Get centroid of the cache
#[wasm_bindgen]
pub fn centroid(&self) -> Vec<f32> {
self.inner.centroid.clone()
}
/// Get tangent coordinates for a query
///
/// @param query - Query point (Float32Array)
/// @returns Tangent coordinates (Float32Array)
#[wasm_bindgen(js_name = queryTangent)]
pub fn query_tangent(&self, query: &[f32]) -> Vec<f32> {
self.inner.query_tangent(query)
}
/// Compute tangent distance squared (for fast pruning)
///
/// @param query_tangent - Query in tangent space (Float32Array)
/// @param idx - Index of cached point
/// @returns Squared distance in tangent space
#[wasm_bindgen(js_name = tangentDistanceSquared)]
pub fn tangent_distance_squared(&self, query_tangent: &[f32], idx: usize) -> f32 {
self.inner.tangent_distance_squared(query_tangent, idx)
}
/// Get number of cached points
#[wasm_bindgen]
pub fn len(&self) -> usize {
self.inner.len()
}
/// Get dimension
#[wasm_bindgen]
pub fn dim(&self) -> usize {
self.inner.dim()
}
}
// ============================================================================
// Utility Functions
// ============================================================================
/// Get library version
#[wasm_bindgen(js_name = getVersion)]
pub fn get_version() -> String {
ruvector_hyperbolic_hnsw::VERSION.to_string()
}
/// Get default curvature value
#[wasm_bindgen(js_name = getDefaultCurvature)]
pub fn get_default_curvature() -> f32 {
DEFAULT_CURVATURE
}
/// Get numerical stability epsilon
#[wasm_bindgen(js_name = getEps)]
pub fn get_eps() -> f32 {
EPS
}
/// Compute vector norm
#[wasm_bindgen(js_name = vectorNorm)]
pub fn vector_norm(x: &[f32]) -> f32 {
ruvector_hyperbolic_hnsw::norm(x)
}
/// Compute squared vector norm
#[wasm_bindgen(js_name = vectorNormSquared)]
pub fn vector_norm_squared(x: &[f32]) -> f32 {
ruvector_hyperbolic_hnsw::norm_squared(x)
}
#[cfg(test)]
mod tests {
use super::*;
use wasm_bindgen_test::*;
#[wasm_bindgen_test]
fn test_poincare_distance() {
let u = vec![0.3, 0.2];
let v = vec![-0.1, 0.4];
let d = wasm_poincare_distance(&u, &v, 1.0);
assert!(d > 0.0);
}
#[wasm_bindgen_test]
fn test_mobius_add() {
let x = vec![0.2, 0.1];
let y = vec![0.1, -0.1];
let z = wasm_mobius_add(&x, &y, 1.0);
assert_eq!(z.len(), 2);
}
#[wasm_bindgen_test]
fn test_hyperbolic_index() {
let mut index = HyperbolicIndex::new(Some(16), Some(1.0));
index.insert(&[0.1, 0.2, 0.3]).unwrap();
index.insert(&[-0.1, 0.15, 0.25]).unwrap();
index.insert(&[0.2, -0.1, 0.1]).unwrap();
assert_eq!(index.len(), 3);
assert!(!index.is_empty());
assert_eq!(index.dim(), Some(3));
}
}