UNPKG

usearch

Version:

Smaller & Faster Single-File Vector Search Engine from Unum

160 lines (144 loc) 5.72 kB
import build from "node-gyp-build"; import * as path from "node:path"; import { existsSync } from "node:fs"; import { getFileName, getRoot } from "bindings"; import * as fallback from "./fallback.js"; let compiled: any; try { let builddir = getBuildDir(getDirName()); compiled = build(builddir); } catch (e) { compiled = fallback; console.warn( "It seems like your environment does't support the native simsimd module, so we are providing a JS fallback." ); } /** * @brief Computes the squared Euclidean distance between two vectors. * @param {Float64Array|Float32Array|Int8Array} a - The first vector. * @param {Float64Array|Float32Array|Int8Array} b - The second vector. * @returns {number} The squared Euclidean distance between vectors a and b. */ export const sqeuclidean = ( a: Float64Array | Float32Array | Int8Array, b: Float64Array | Float32Array | Int8Array ): number => { return compiled.sqeuclidean(a, b); }; /** * @brief Computes the cosine distance between two vectors. * @param {Float64Array|Float32Array|Int8Array} a - The first vector. * @param {Float64Array|Float32Array|Int8Array} b - The second vector. * @returns {number} The cosine distance between vectors a and b. */ export const cosine = ( a: Float64Array | Float32Array | Int8Array, b: Float64Array | Float32Array | Int8Array ): number => { return compiled.cosine(a, b); }; /** * @brief Computes the inner product of two vectors (same as dot product). * @param {Float64Array|Float32Array} a - The first vector. * @param {Float64Array|Float32Array} b - The second vector. * @returns {number} The inner product of vectors a and b. */ export const inner = (a: Float64Array | Float32Array, b: Float64Array | Float32Array): number => { return compiled.inner(a, b); }; /** * @brief Computes the dot product of two vectors (same as inner product). * @param {Float64Array|Float32Array} a - The first vector. * @param {Float64Array|Float32Array} b - The second vector. * @returns {number} The dot product of vectors a and b. */ export const dot = (a: Float64Array | Float32Array, b: Float64Array | Float32Array): number => { return compiled.dot(a, b); }; /** * @brief Computes the bitwise Hamming distance between two vectors. * @param {Uint8Array} a - The first vector. * @param {Uint8Array} b - The second vector. * @returns {number} The Hamming distance between vectors a and b. */ export const hamming = (a: Uint8Array, b: Uint8Array): number => { return compiled.hamming(a, b); }; /** * @brief Computes the bitwise Jaccard similarity coefficient between two vectors. * @param {Uint8Array} a - The first vector. * @param {Uint8Array} b - The second vector. * @returns {number} The Jaccard similarity coefficient between vectors a and b. */ export const jaccard = (a: Uint8Array, b: Uint8Array): number => { return compiled.jaccard(a, b); }; /** * @brief Computes the kullbackleibler similarity coefficient between two vectors. * @param {Float64Array|Float32Array} a - The first vector. * @param {Float64Array|Float32Array} b - The second vector. * @returns {number} The Jaccard similarity coefficient between vectors a and b. */ export const kullbackleibler = (a: Float64Array | Float32Array, b: Float64Array | Float32Array): number => { return compiled.kullbackleibler(a, b); }; /** * @brief Computes the jensenshannon similarity coefficient between two vectors. * @param {Float64Array|Float32Array} a - The first vector. * @param {Float64Array|Float32Array} b - The second vector. * @returns {number} The Jaccard similarity coefficient between vectors a and b. */ export const jensenshannon = (a: Float64Array | Float32Array, b: Float64Array | Float32Array): number => { return compiled.jensenshannon(a, b); }; /** * Quantizes a floating-point vector into a binary vector (1 for positive values, 0 for non-positive values) and packs the result into a Uint8Array, where each element represents 8 binary values from the original vector. * This function is useful for preparing data for bitwise distance or similarity computations, such as Hamming or Jaccard indices. * * @param {Float32Array | Float64Array | Int8Array} vector The floating-point vector to be quantized and packed. * @returns {Uint8Array} A Uint8Array where each byte represents 8 binary quantized values from the input vector. */ export const toBinary = (vector: Float32Array | Float64Array | Int8Array): Uint8Array => { const byteLength = Math.ceil(vector.length / 8); const packedVector = new Uint8Array(byteLength); for (let i = 0; i < vector.length; i++) { if (vector[i] > 0) { const byteIndex = Math.floor(i / 8); const bitPosition = 7 - (i % 8); packedVector[byteIndex] |= (1 << bitPosition); } } return packedVector; }; export default { dot, inner, sqeuclidean, cosine, hamming, jaccard, kullbackleibler, jensenshannon, toBinary, }; /** * @brief Finds the directory where the native build of the simsimd module is located. * @param {string} dir - The directory to start the search from. */ function getBuildDir(dir: string) { if (existsSync(path.join(dir, "build"))) return dir; if (existsSync(path.join(dir, "prebuilds"))) return dir; if (path.basename(dir) === ".next") { // special case for next.js on custom node (not vercel) const sideways = path.join(dir, "..", "node_modules", "simsimd"); if (existsSync(sideways)) return getBuildDir(sideways); } if (dir === "/") throw new Error("Could not find native build for simsimd"); return getBuildDir(path.join(dir, "..")); } function getDirName() { try { if (__dirname) return __dirname; } catch (e) { } return getRoot(getFileName()); }