usearch 2.10.3 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -8
- package/binding.gyp +101 -0
- package/c/CMakeLists.txt +27 -0
- package/c/README.md +244 -0
- package/c/lib.cpp +459 -0
- package/c/test.c +386 -0
- package/c/usearch.h +451 -0
- package/cmake/clipp.cmake +7 -0
- package/cmake/config.cmake.in +15 -0
- package/cmake/emscripten.cmake +8 -0
- package/cmake/jemalloc.cmake +62 -0
- package/cmake/pkg-config.pc.in +4 -0
- package/cmake/usearchConfigVersion.cmake.in +20 -0
- package/cpp/CMakeLists.txt +14 -0
- package/cpp/README.md +161 -0
- package/cpp/bench.cpp +616 -0
- package/cpp/test.cpp +335 -0
- package/fp16/CMakeLists.txt +176 -0
- package/fp16/LICENSE +11 -0
- package/fp16/README.md +20 -0
- package/fp16/bench/alt-element.cc +89 -0
- package/fp16/bench/from-alt-array.cc +175 -0
- package/fp16/bench/from-ieee-array.cc +399 -0
- package/fp16/bench/ieee-element.cc +272 -0
- package/fp16/bench/to-alt-array.cc +91 -0
- package/fp16/bench/to-ieee-array.cc +303 -0
- package/fp16/cmake/DownloadGoogleBenchmark.cmake +15 -0
- package/fp16/cmake/DownloadGoogleTest.cmake +15 -0
- package/fp16/cmake/DownloadPSimd.cmake +15 -0
- package/fp16/configure.py +65 -0
- package/fp16/confu.yaml +8 -0
- package/fp16/include/fp16/__init__.py +0 -0
- package/fp16/include/fp16/avx.py +50 -0
- package/fp16/include/fp16/avx2.py +53 -0
- package/fp16/include/fp16/bitcasts.h +92 -0
- package/fp16/include/fp16/fp16.h +451 -0
- package/fp16/include/fp16/psimd.h +131 -0
- package/fp16/include/fp16.h +11 -0
- package/fp16/jni/Android.mk +6 -0
- package/fp16/jni/Application.mk +4 -0
- package/fp16/test/alt-from-fp32-value.cc +498 -0
- package/fp16/test/alt-to-fp32-bits.cc +263 -0
- package/fp16/test/alt-to-fp32-psimd.cc +145 -0
- package/fp16/test/alt-to-fp32-value.cc +348 -0
- package/fp16/test/alt-to-fp32x2-psimd.cc +245 -0
- package/fp16/test/bitcasts.cc +56 -0
- package/fp16/test/ieee-from-fp32-value.cc +523 -0
- package/fp16/test/ieee-to-fp32-bits.cc +333 -0
- package/fp16/test/ieee-to-fp32-psimd.cc +312 -0
- package/fp16/test/ieee-to-fp32-value.cc +420 -0
- package/fp16/test/ieee-to-fp32x2-psimd.cc +541 -0
- package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +96 -0
- package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +96 -0
- package/fp16/test/peachpy/stubs.py +38 -0
- package/fp16/test/tables.cc +530 -0
- package/fp16/test/tables.h +13 -0
- package/fp16/third-party/THHalf.h +92 -0
- package/fp16/third-party/eigen-half.h +170 -0
- package/fp16/third-party/float16-compressor.h +80 -0
- package/fp16/third-party/half.hpp +2916 -0
- package/fp16/third-party/npy-halffloat.h +328 -0
- package/include/usearch/index.hpp +3838 -0
- package/include/usearch/index_dense.hpp +2022 -0
- package/include/usearch/index_plugins.hpp +2317 -0
- package/javascript/dist/cjs/usearch.js +5 -5
- package/javascript/dist/esm/usearch.js +2 -2
- package/javascript/dist-package-cjs.json +3 -0
- package/javascript/dist-package-esm.json +3 -0
- package/javascript/lib.cpp +350 -0
- package/javascript/node-gyp-build.d.ts +1 -0
- package/javascript/tsconfig-base.json +25 -0
- package/javascript/tsconfig-cjs.json +8 -0
- package/javascript/tsconfig-esm.json +8 -0
- package/javascript/usearch.test.js +84 -0
- package/javascript/usearch.ts +640 -0
- package/package.json +14 -7
- 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/prebuilds/win32-ia32/usearch.node +0 -0
- package/prebuilds/win32-x64/usearch.node +0 -0
- package/simsimd/.releaserc +87 -0
- package/simsimd/CONTRIBUTING.md +114 -0
- package/simsimd/Cargo.lock +709 -0
- package/simsimd/Cargo.toml +44 -0
- package/simsimd/LICENSE +201 -0
- package/simsimd/README.md +708 -0
- package/simsimd/binding.gyp +36 -0
- package/simsimd/build.rs +51 -0
- package/simsimd/c/lib.c +110 -0
- package/simsimd/include/simsimd/binary.h +258 -0
- package/simsimd/include/simsimd/dot.h +1237 -0
- package/simsimd/include/simsimd/geospatial.h +37 -0
- package/simsimd/include/simsimd/probability.h +563 -0
- package/simsimd/include/simsimd/simsimd.h +1129 -0
- package/simsimd/include/simsimd/spatial.h +1019 -0
- package/simsimd/include/simsimd/types.h +309 -0
- package/simsimd/javascript/bench.js +127 -0
- package/simsimd/javascript/dist-package-cjs.json +3 -0
- package/simsimd/javascript/dist-package-esm.json +3 -0
- package/simsimd/javascript/fallback.ts +203 -0
- package/simsimd/javascript/lib.c +107 -0
- package/simsimd/javascript/node-gyp-build.d.ts +1 -0
- package/simsimd/javascript/simsimd.ts +135 -0
- package/simsimd/javascript/test.mjs +179 -0
- package/simsimd/javascript/tsconfig-base.json +37 -0
- package/simsimd/javascript/tsconfig-cjs.json +8 -0
- package/simsimd/javascript/tsconfig-esm.json +8 -0
- package/simsimd/package-lock.json +1709 -0
- package/simsimd/package.json +61 -0
- package/simsimd/rust/benches/cosine.rs +27 -0
- package/simsimd/rust/benches/native.rs +30 -0
- package/simsimd/rust/benches/sqeuclidean.rs +27 -0
- package/simsimd/rust/lib.rs +778 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file lib.c
|
|
3
|
+
* @brief JavaScript bindings for SimSIMD.
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date October 18, 2023
|
|
6
|
+
*
|
|
7
|
+
* @copyright Copyright (c) 2023
|
|
8
|
+
* @see NodeJS docs: https://nodejs.org/api/n-api.html
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#include <node_api.h> // `napi_*` functions
|
|
12
|
+
#include <simsimd/simsimd.h> // `simsimd_*` functions
|
|
13
|
+
|
|
14
|
+
/// @brief Global variable that caches the CPU capabilities, and is computed just onc, when the module is loaded.
|
|
15
|
+
simsimd_capability_t static_capabilities = simsimd_cap_serial_k;
|
|
16
|
+
|
|
17
|
+
napi_value runAPI(napi_env env, napi_callback_info info, simsimd_metric_kind_t metric_kind) {
|
|
18
|
+
size_t argc = 2;
|
|
19
|
+
napi_value args[2];
|
|
20
|
+
napi_status status;
|
|
21
|
+
|
|
22
|
+
// Get callback info and ensure the argument count is correct
|
|
23
|
+
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
|
24
|
+
if (status != napi_ok || argc != 2) {
|
|
25
|
+
napi_throw_error(env, NULL, "Wrong number of arguments");
|
|
26
|
+
return NULL;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Obtain the typed arrays from the arguments
|
|
30
|
+
void *data_a, *data_b;
|
|
31
|
+
size_t length_a, length_b;
|
|
32
|
+
napi_typedarray_type type_a, type_b;
|
|
33
|
+
napi_status status_a, status_b;
|
|
34
|
+
status_a = napi_get_typedarray_info(env, args[0], &type_a, &length_a, &data_a, NULL, NULL);
|
|
35
|
+
status_b = napi_get_typedarray_info(env, args[1], &type_b, &length_b, &data_b, NULL, NULL);
|
|
36
|
+
if (status_a != napi_ok || status_b != napi_ok || type_a != type_b || length_a != length_b) {
|
|
37
|
+
napi_throw_error(env, NULL, "Both arguments must be typed arrays of matching types and dimensionality");
|
|
38
|
+
return NULL;
|
|
39
|
+
}
|
|
40
|
+
if (type_a != napi_float64_array && type_a != napi_float32_array && //
|
|
41
|
+
type_a != napi_int8_array && type_a != napi_uint8_array) {
|
|
42
|
+
napi_throw_error(env, NULL,
|
|
43
|
+
"Only `float64`, `float32`, `int8` and `uint8` arrays are supported in JavaScript bindings");
|
|
44
|
+
return NULL;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
simsimd_datatype_t datatype = simsimd_datatype_unknown_k;
|
|
48
|
+
switch (type_a) {
|
|
49
|
+
case napi_float64_array: datatype = simsimd_datatype_f64_k; break;
|
|
50
|
+
case napi_float32_array: datatype = simsimd_datatype_f32_k; break;
|
|
51
|
+
case napi_int8_array: datatype = simsimd_datatype_i8_k; break;
|
|
52
|
+
case napi_uint8_array: datatype = simsimd_datatype_b8_k; break;
|
|
53
|
+
default: break;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
simsimd_metric_punned_t metric = NULL;
|
|
57
|
+
simsimd_capability_t capability = simsimd_cap_serial_k;
|
|
58
|
+
simsimd_find_metric_punned(metric_kind, datatype, static_capabilities, simsimd_cap_any_k, &metric, &capability);
|
|
59
|
+
if (metric == NULL) {
|
|
60
|
+
napi_throw_error(env, NULL, "Unsupported datatype for given metric");
|
|
61
|
+
return NULL;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
simsimd_distance_t result;
|
|
65
|
+
metric(data_a, data_b, length_a, &result);
|
|
66
|
+
|
|
67
|
+
// Convert the result to a JavaScript number
|
|
68
|
+
napi_value js_result;
|
|
69
|
+
status = napi_create_double(env, result, &js_result);
|
|
70
|
+
if (status != napi_ok)
|
|
71
|
+
return NULL;
|
|
72
|
+
|
|
73
|
+
return js_result;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
napi_value ipAPI(napi_env env, napi_callback_info info) { return runAPI(env, info, simsimd_metric_dot_k); }
|
|
77
|
+
napi_value cosAPI(napi_env env, napi_callback_info info) { return runAPI(env, info, simsimd_metric_cosine_k); }
|
|
78
|
+
napi_value l2sqAPI(napi_env env, napi_callback_info info) { return runAPI(env, info, simsimd_metric_sqeuclidean_k); }
|
|
79
|
+
napi_value klAPI(napi_env env, napi_callback_info info) { return runAPI(env, info, simsimd_metric_kl_k); }
|
|
80
|
+
napi_value jsAPI(napi_env env, napi_callback_info info) { return runAPI(env, info, simsimd_metric_js_k); }
|
|
81
|
+
napi_value hammingAPI(napi_env env, napi_callback_info info) { return runAPI(env, info, simsimd_metric_hamming_k); }
|
|
82
|
+
napi_value jaccardAPI(napi_env env, napi_callback_info info) { return runAPI(env, info, simsimd_metric_jaccard_k); }
|
|
83
|
+
|
|
84
|
+
napi_value Init(napi_env env, napi_value exports) {
|
|
85
|
+
|
|
86
|
+
// Define an array of property descriptors
|
|
87
|
+
napi_property_descriptor dotDesc = {"dot", 0, ipAPI, 0, 0, 0, napi_default, 0};
|
|
88
|
+
napi_property_descriptor innerDesc = {"inner", 0, ipAPI, 0, 0, 0, napi_default, 0};
|
|
89
|
+
napi_property_descriptor sqeuclideanDesc = {"sqeuclidean", 0, l2sqAPI, 0, 0, 0, napi_default, 0};
|
|
90
|
+
napi_property_descriptor cosineDesc = {"cosine", 0, cosAPI, 0, 0, 0, napi_default, 0};
|
|
91
|
+
napi_property_descriptor hammingDesc = {"hamming", 0, hammingAPI, 0, 0, 0, napi_default, 0};
|
|
92
|
+
napi_property_descriptor jaccardDesc = {"jaccard", 0, jaccardAPI, 0, 0, 0, napi_default, 0};
|
|
93
|
+
napi_property_descriptor klDesc = {"kullbackleibler", 0, klAPI, 0, 0, 0, napi_default, 0};
|
|
94
|
+
napi_property_descriptor jsDesc = {"jensenshannon", 0, jsAPI, 0, 0, 0, napi_default, 0};
|
|
95
|
+
napi_property_descriptor properties[] = {
|
|
96
|
+
dotDesc, innerDesc, sqeuclideanDesc, cosineDesc, hammingDesc, jaccardDesc, klDesc, jsDesc,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Define the properties on the `exports` object
|
|
100
|
+
size_t propertyCount = sizeof(properties) / sizeof(properties[0]);
|
|
101
|
+
napi_define_properties(env, exports, propertyCount, properties);
|
|
102
|
+
|
|
103
|
+
static_capabilities = simsimd_capabilities();
|
|
104
|
+
return exports;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module "node-gyp-build";
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import build from "node-gyp-build";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { getFileName, getRoot } from "bindings";
|
|
5
|
+
import * as fallback from "./fallback.js";
|
|
6
|
+
|
|
7
|
+
let compiled: any;
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
let builddir = getBuildDir(getDirName());
|
|
11
|
+
compiled = build(builddir);
|
|
12
|
+
} catch (e) {
|
|
13
|
+
compiled = fallback;
|
|
14
|
+
console.warn(
|
|
15
|
+
"It seems like your environment does't support the native simsimd module, so we are providing a JS fallback."
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @brief Computes the squared Euclidean distance between two vectors.
|
|
21
|
+
* @param {Float64Array|Float32Array|Int8Array} a - The first vector.
|
|
22
|
+
* @param {Float64Array|Float32Array|Int8Array} b - The second vector.
|
|
23
|
+
* @returns {number} The squared Euclidean distance between vectors a and b.
|
|
24
|
+
*/
|
|
25
|
+
export const sqeuclidean = (
|
|
26
|
+
a: Float64Array | Float32Array | Int8Array,
|
|
27
|
+
b: Float64Array | Float32Array | Int8Array
|
|
28
|
+
): number => {
|
|
29
|
+
return compiled.sqeuclidean(a, b);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @brief Computes the cosine distance between two vectors.
|
|
34
|
+
* @param {Float64Array|Float32Array|Int8Array} a - The first vector.
|
|
35
|
+
* @param {Float64Array|Float32Array|Int8Array} b - The second vector.
|
|
36
|
+
* @returns {number} The cosine distance between vectors a and b.
|
|
37
|
+
*/
|
|
38
|
+
export const cosine = (
|
|
39
|
+
a: Float64Array | Float32Array | Int8Array,
|
|
40
|
+
b: Float64Array | Float32Array | Int8Array
|
|
41
|
+
): number => {
|
|
42
|
+
return compiled.cosine(a, b);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @brief Computes the inner product of two vectors (same as dot product).
|
|
47
|
+
* @param {Float64Array|Float32Array} a - The first vector.
|
|
48
|
+
* @param {Float64Array|Float32Array} b - The second vector.
|
|
49
|
+
* @returns {number} The inner product of vectors a and b.
|
|
50
|
+
*/
|
|
51
|
+
export const inner = (a: Float64Array | Float32Array, b: Float64Array | Float32Array): number => {
|
|
52
|
+
return compiled.inner(a, b);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @brief Computes the dot product of two vectors (same as inner product).
|
|
57
|
+
* @param {Float64Array|Float32Array} a - The first vector.
|
|
58
|
+
* @param {Float64Array|Float32Array} b - The second vector.
|
|
59
|
+
* @returns {number} The dot product of vectors a and b.
|
|
60
|
+
*/
|
|
61
|
+
export const dot = (a: Float64Array | Float32Array, b: Float64Array | Float32Array): number => {
|
|
62
|
+
return compiled.dot(a, b);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @brief Computes the bitwise Hamming distance between two vectors.
|
|
67
|
+
* @param {Uint8Array} a - The first vector.
|
|
68
|
+
* @param {Uint8Array} b - The second vector.
|
|
69
|
+
* @returns {number} The Hamming distance between vectors a and b.
|
|
70
|
+
*/
|
|
71
|
+
export const hamming = (a: Uint8Array, b: Uint8Array): number => {
|
|
72
|
+
return compiled.hamming(a, b);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @brief Computes the bitwise Jaccard similarity coefficient between two vectors.
|
|
77
|
+
* @param {Uint8Array} a - The first vector.
|
|
78
|
+
* @param {Uint8Array} b - The second vector.
|
|
79
|
+
* @returns {number} The Jaccard similarity coefficient between vectors a and b.
|
|
80
|
+
*/
|
|
81
|
+
export const jaccard = (a: Uint8Array, b: Uint8Array): number => {
|
|
82
|
+
return compiled.jaccard(a, b);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @brief Computes the kullbackleibler similarity coefficient between two vectors.
|
|
87
|
+
* @param {Float64Array|Float32Array} a - The first vector.
|
|
88
|
+
* @param {Float64Array|Float32Array} b - The second vector.
|
|
89
|
+
* @returns {number} The Jaccard similarity coefficient between vectors a and b.
|
|
90
|
+
*/
|
|
91
|
+
export const kullbackleibler = (a: Float64Array | Float32Array, b: Float64Array | Float32Array): number => {
|
|
92
|
+
return compiled.kullbackleibler(a, b);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @brief Computes the jensenshannon similarity coefficient between two vectors.
|
|
97
|
+
* @param {Float64Array|Float32Array} a - The first vector.
|
|
98
|
+
* @param {Float64Array|Float32Array} b - The second vector.
|
|
99
|
+
* @returns {number} The Jaccard similarity coefficient between vectors a and b.
|
|
100
|
+
*/
|
|
101
|
+
export const jensenshannon = (a: Float64Array | Float32Array, b: Float64Array | Float32Array): number => {
|
|
102
|
+
return compiled.jensenshannon(a, b);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default {
|
|
106
|
+
dot,
|
|
107
|
+
inner,
|
|
108
|
+
sqeuclidean,
|
|
109
|
+
cosine,
|
|
110
|
+
hamming,
|
|
111
|
+
jaccard,
|
|
112
|
+
kullbackleibler,
|
|
113
|
+
jensenshannon,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// utility functions to help find native builds
|
|
117
|
+
|
|
118
|
+
function getBuildDir(dir: string) {
|
|
119
|
+
if (existsSync(path.join(dir, "build"))) return dir;
|
|
120
|
+
if (existsSync(path.join(dir, "prebuilds"))) return dir;
|
|
121
|
+
if (path.basename(dir) === ".next") {
|
|
122
|
+
// special case for next.js on custom node (not vercel)
|
|
123
|
+
const sideways = path.join(dir, "..", "node_modules", "simsimd");
|
|
124
|
+
if (existsSync(sideways)) return getBuildDir(sideways);
|
|
125
|
+
}
|
|
126
|
+
if (dir === "/") throw new Error("Could not find native build for simsimd");
|
|
127
|
+
return getBuildDir(path.join(dir, ".."));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function getDirName() {
|
|
131
|
+
try {
|
|
132
|
+
if (__dirname) return __dirname;
|
|
133
|
+
} catch (e) { }
|
|
134
|
+
return getRoot(getFileName());
|
|
135
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// Currently the builds are expected to run only on Node.js,
|
|
2
|
+
// but Deno tests pass as well.
|
|
3
|
+
//
|
|
4
|
+
// Bun supports `node:assert`, but not `node:test`.
|
|
5
|
+
// Using `require` we can make the tests compatible with Bun.
|
|
6
|
+
//
|
|
7
|
+
// const isBun = typeof Bun !== "undefined";
|
|
8
|
+
// let assert, test;
|
|
9
|
+
// if (isBun) {
|
|
10
|
+
// assert = require('node:assert');
|
|
11
|
+
// test = require('bun:test');
|
|
12
|
+
// } else {
|
|
13
|
+
// assert = require('node:assert');
|
|
14
|
+
// test = require('node:test');
|
|
15
|
+
// }
|
|
16
|
+
//
|
|
17
|
+
// That, however, leads to other issues, like the following:
|
|
18
|
+
//
|
|
19
|
+
// require is not defined in ES module scope, you can use import instead
|
|
20
|
+
//
|
|
21
|
+
// https://bun.sh/docs/runtime/nodejs-apis
|
|
22
|
+
// https://bun.sh/guides/util/detect-bun
|
|
23
|
+
import test from "node:test";
|
|
24
|
+
import assert from "node:assert";
|
|
25
|
+
|
|
26
|
+
import * as simsimd from "./dist/esm/simsimd.js";
|
|
27
|
+
|
|
28
|
+
import * as fallback from "./dist/esm/fallback.js";
|
|
29
|
+
|
|
30
|
+
function assertAlmostEqual(actual, expected, tolerance = 1e-6) {
|
|
31
|
+
const lowerBound = expected - tolerance;
|
|
32
|
+
const upperBound = expected + tolerance;
|
|
33
|
+
assert(
|
|
34
|
+
actual >= lowerBound && actual <= upperBound,
|
|
35
|
+
`Expected ${actual} to be almost equal to ${expected}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
test("Distance from itself", () => {
|
|
40
|
+
const f32s = new Float32Array([1.0, 2.0, 3.0]);
|
|
41
|
+
assertAlmostEqual(simsimd.sqeuclidean(f32s, f32s), 0.0, 0.01);
|
|
42
|
+
assertAlmostEqual(simsimd.cosine(f32s, f32s), 0.0, 0.01);
|
|
43
|
+
|
|
44
|
+
const f64s = new Float64Array([1.0, 2.0, 3.0]);
|
|
45
|
+
assertAlmostEqual(simsimd.sqeuclidean(f64s, f64s), 0.0, 0.01);
|
|
46
|
+
assertAlmostEqual(simsimd.cosine(f64s, f64s), 0.0, 0.01);
|
|
47
|
+
|
|
48
|
+
const f32sNormalized = new Float32Array([
|
|
49
|
+
1.0 / Math.sqrt(14),
|
|
50
|
+
2.0 / Math.sqrt(14),
|
|
51
|
+
3.0 / Math.sqrt(14),
|
|
52
|
+
]);
|
|
53
|
+
assertAlmostEqual(simsimd.inner(f32sNormalized, f32sNormalized), 1.0, 0.01);
|
|
54
|
+
|
|
55
|
+
const f32sDistribution = new Float32Array([1.0 / 6, 2.0 / 6, 3.0 / 6]);
|
|
56
|
+
assertAlmostEqual(
|
|
57
|
+
simsimd.kullbackleibler(f32sDistribution, f32sDistribution),
|
|
58
|
+
0.0,
|
|
59
|
+
0.01
|
|
60
|
+
);
|
|
61
|
+
assertAlmostEqual(
|
|
62
|
+
simsimd.jensenshannon(f32sDistribution, f32sDistribution),
|
|
63
|
+
0.0,
|
|
64
|
+
0.01
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const u8s = new Uint8Array([1, 2, 3]);
|
|
68
|
+
assertAlmostEqual(simsimd.hamming(u8s, u8s), 0.0, 0.01);
|
|
69
|
+
assertAlmostEqual(simsimd.jaccard(u8s, u8s), 0.0, 0.01);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("Distance from itself JS fallback", () => {
|
|
73
|
+
const f32s = new Float32Array([1.0, 2.0, 3.0]);
|
|
74
|
+
|
|
75
|
+
assertAlmostEqual(fallback.sqeuclidean(f32s, f32s), 0.0, 0.01);
|
|
76
|
+
assertAlmostEqual(fallback.cosine(f32s, f32s), 0.0, 0.01);
|
|
77
|
+
|
|
78
|
+
const arrNormalized = new Float32Array([
|
|
79
|
+
1.0 / Math.sqrt(14),
|
|
80
|
+
2.0 / Math.sqrt(14),
|
|
81
|
+
3.0 / Math.sqrt(14),
|
|
82
|
+
]);
|
|
83
|
+
assertAlmostEqual(fallback.inner(arrNormalized, arrNormalized), 1.0, 0.01);
|
|
84
|
+
|
|
85
|
+
const f32sDistribution = new Float32Array([1.0 / 6, 2.0 / 6, 3.0 / 6]);
|
|
86
|
+
assertAlmostEqual(
|
|
87
|
+
fallback.kullbackleibler(f32sDistribution, f32sDistribution),
|
|
88
|
+
0.0,
|
|
89
|
+
0.01
|
|
90
|
+
);
|
|
91
|
+
assertAlmostEqual(
|
|
92
|
+
fallback.jensenshannon(f32sDistribution, f32sDistribution),
|
|
93
|
+
0.0,
|
|
94
|
+
0.01
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const u8s = new Uint8Array([1, 2, 3]);
|
|
98
|
+
assertAlmostEqual(fallback.hamming(u8s, u8s), 0.0, 0.01);
|
|
99
|
+
assertAlmostEqual(fallback.jaccard(u8s, u8s), 0.0, 0.01);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const f32Array1 = new Float32Array([1.0, 2.0, 3.0]);
|
|
103
|
+
const f32Array2 = new Float32Array([4.0, 5.0, 6.0]);
|
|
104
|
+
|
|
105
|
+
test("Squared Euclidean Distance", () => {
|
|
106
|
+
const result = simsimd.sqeuclidean(f32Array1, f32Array2);
|
|
107
|
+
assertAlmostEqual(result, 27.0, 0.01);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("Inner Distance", () => {
|
|
111
|
+
const result = simsimd.inner(f32Array1, f32Array2);
|
|
112
|
+
assertAlmostEqual(result, 32.0, 0.01);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("Cosine Similarity", () => {
|
|
116
|
+
const result = simsimd.cosine(f32Array1, f32Array2);
|
|
117
|
+
assertAlmostEqual(result, 0.029, 0.01);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("Squared Euclidean Distance JS", () => {
|
|
121
|
+
const result = fallback.sqeuclidean(f32Array1, f32Array2);
|
|
122
|
+
assertAlmostEqual(result, 27.0, 0.01);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("Inner Distance JS", () => {
|
|
126
|
+
const result = fallback.inner(f32Array1, f32Array2);
|
|
127
|
+
assertAlmostEqual(result, 32.0, 0.01);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("Cosine Similarity JS", () => {
|
|
131
|
+
const result = fallback.cosine(f32Array1, f32Array2);
|
|
132
|
+
assertAlmostEqual(result, 0.029, 0.01);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("Squared Euclidean Distance C vs JS", () => {
|
|
136
|
+
const result = simsimd.sqeuclidean(f32Array1, f32Array2);
|
|
137
|
+
const resultjs = fallback.sqeuclidean(f32Array1, f32Array2);
|
|
138
|
+
assertAlmostEqual(resultjs, result, 0.01);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test("Inner Distance C vs JS", () => {
|
|
142
|
+
const result = simsimd.inner(f32Array1, f32Array2);
|
|
143
|
+
const resultjs = fallback.inner(f32Array1, f32Array2);
|
|
144
|
+
assertAlmostEqual(resultjs, result, 0.01);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("Cosine Similarity C vs JS", () => {
|
|
148
|
+
const result = simsimd.cosine(f32Array1, f32Array2);
|
|
149
|
+
const resultjs = fallback.cosine(f32Array1, f32Array2);
|
|
150
|
+
assertAlmostEqual(resultjs, result, 0.01);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("Hamming C vs JS", () => {
|
|
154
|
+
const u8s = new Uint8Array([1, 2, 3]);
|
|
155
|
+
const result = simsimd.hamming(u8s, u8s);
|
|
156
|
+
const resultjs = fallback.hamming(u8s, u8s);
|
|
157
|
+
assertAlmostEqual(resultjs, result, 0.01);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test("Jaccard C vs JS", () => {
|
|
161
|
+
const u8s = new Uint8Array([1, 2, 3]);
|
|
162
|
+
const result = simsimd.jaccard(u8s, u8s);
|
|
163
|
+
const resultjs = fallback.jaccard(u8s, u8s);
|
|
164
|
+
assertAlmostEqual(resultjs, result, 0.01);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("Kullback-Leibler C vs JS", () => {
|
|
168
|
+
const f32sDistribution = new Float32Array([1.0 / 6, 2.0 / 6, 3.0 / 6]);
|
|
169
|
+
const result = simsimd.kullbackleibler(f32sDistribution, f32sDistribution);
|
|
170
|
+
const resultjs = fallback.kullbackleibler(f32sDistribution, f32sDistribution);
|
|
171
|
+
assertAlmostEqual(resultjs, result, 0.01);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("Jensen-Shannon C vs JS", () => {
|
|
175
|
+
const f32sDistribution = new Float32Array([1.0 / 6, 2.0 / 6, 3.0 / 6]);
|
|
176
|
+
const result = simsimd.jensenshannon(f32sDistribution, f32sDistribution);
|
|
177
|
+
const resultjs = fallback.jensenshannon(f32sDistribution, f32sDistribution);
|
|
178
|
+
assertAlmostEqual(resultjs, result, 0.01);
|
|
179
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compileOnSave": false,
|
|
3
|
+
"exclude": [
|
|
4
|
+
"node_modules",
|
|
5
|
+
"dist"
|
|
6
|
+
],
|
|
7
|
+
"include": [
|
|
8
|
+
"node-gyp-build.d.ts",
|
|
9
|
+
"simsimd.ts",
|
|
10
|
+
"fallback.ts"
|
|
11
|
+
],
|
|
12
|
+
"compilerOptions": {
|
|
13
|
+
"allowJs": true,
|
|
14
|
+
"allowSyntheticDefaultImports": true,
|
|
15
|
+
"baseUrl": ".",
|
|
16
|
+
"declaration": true,
|
|
17
|
+
"esModuleInterop": true,
|
|
18
|
+
"inlineSourceMap": false,
|
|
19
|
+
"lib": [
|
|
20
|
+
"esnext"
|
|
21
|
+
],
|
|
22
|
+
"listEmittedFiles": false,
|
|
23
|
+
"listFiles": false,
|
|
24
|
+
"moduleResolution": "node",
|
|
25
|
+
"noFallthroughCasesInSwitch": true,
|
|
26
|
+
"pretty": true,
|
|
27
|
+
"resolveJsonModule": true,
|
|
28
|
+
"rootDir": ".",
|
|
29
|
+
"skipLibCheck": true,
|
|
30
|
+
"strict": true,
|
|
31
|
+
"traceResolution": false,
|
|
32
|
+
"types": [
|
|
33
|
+
"node",
|
|
34
|
+
"./node-gyp-build.d.ts"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
}
|