@elarsaks/umap-wasm 0.1.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.
Files changed (41) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +349 -0
  3. package/dist/src/heap.d.ts +12 -0
  4. package/dist/src/heap.js +226 -0
  5. package/dist/src/index.d.ts +1 -0
  6. package/dist/src/index.js +5 -0
  7. package/dist/src/lib.d.ts +1 -0
  8. package/dist/src/lib.js +5 -0
  9. package/dist/src/matrix.d.ts +41 -0
  10. package/dist/src/matrix.js +360 -0
  11. package/dist/src/nn_descent.d.ts +17 -0
  12. package/dist/src/nn_descent.js +204 -0
  13. package/dist/src/tree.d.ts +16 -0
  14. package/dist/src/tree.js +320 -0
  15. package/dist/src/umap.d.ts +102 -0
  16. package/dist/src/umap.js +842 -0
  17. package/dist/src/utils.d.ts +16 -0
  18. package/dist/src/utils.js +137 -0
  19. package/dist/src/wasmBridge.d.ts +57 -0
  20. package/dist/src/wasmBridge.js +290 -0
  21. package/dist/test/matrix.test.d.ts +1 -0
  22. package/dist/test/matrix.test.js +169 -0
  23. package/dist/test/nn_descent.test.d.ts +1 -0
  24. package/dist/test/nn_descent.test.js +58 -0
  25. package/dist/test/test_data.d.ts +13 -0
  26. package/dist/test/test_data.js +1054 -0
  27. package/dist/test/tree.test.d.ts +1 -0
  28. package/dist/test/tree.test.js +60 -0
  29. package/dist/test/umap.test.d.ts +1 -0
  30. package/dist/test/umap.test.js +293 -0
  31. package/dist/test/utils.test.d.ts +1 -0
  32. package/dist/test/utils.test.js +128 -0
  33. package/dist/test/wasmDistance.test.d.ts +1 -0
  34. package/dist/test/wasmDistance.test.js +124 -0
  35. package/dist/test/wasmMatrix.test.d.ts +1 -0
  36. package/dist/test/wasmMatrix.test.js +389 -0
  37. package/dist/test/wasmTree.test.d.ts +1 -0
  38. package/dist/test/wasmTree.test.js +212 -0
  39. package/lib/umap-js.js +8657 -0
  40. package/lib/umap-js.min.js +1 -0
  41. package/package.json +58 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ var tree = __importStar(require("../src/tree"));
40
+ var test_data_1 = require("./test_data");
41
+ var prando_1 = __importDefault(require("prando"));
42
+ describe('umap knn tree methods', function () {
43
+ var prando = new prando_1.default(42);
44
+ var random = function () { return prando.next(); };
45
+ test('makeForest method constructs an rpForest', function () {
46
+ var nNeighbors = 15;
47
+ var nTrees = 6;
48
+ var forest = tree.makeForest(test_data_1.testData, nNeighbors, nTrees, random);
49
+ expect(forest.length).toEqual(nTrees);
50
+ expect(forest[0]).toEqual(test_data_1.treeData);
51
+ });
52
+ test('makeLeafArray method flattens indices', function () {
53
+ var nNeighbors = 15;
54
+ var nTrees = 6;
55
+ var forest = tree.makeForest(test_data_1.testData, nNeighbors, nTrees, random);
56
+ var leafArray = tree.makeLeafArray(forest);
57
+ var firstIndices = forest[0].indices;
58
+ expect(leafArray.slice(0, firstIndices.length)).toEqual(firstIndices);
59
+ });
60
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,293 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __generator = (this && this.__generator) || function (thisArg, body) {
45
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
46
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
47
+ function verb(n) { return function (v) { return step([n, v]); }; }
48
+ function step(op) {
49
+ if (f) throw new TypeError("Generator is already executing.");
50
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
51
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
52
+ if (y = 0, t) op = [op[0] & 2, t.value];
53
+ switch (op[0]) {
54
+ case 0: case 1: t = op; break;
55
+ case 4: _.label++; return { value: op[1], done: false };
56
+ case 5: _.label++; y = op[1]; op = [0]; continue;
57
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
58
+ default:
59
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
60
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
61
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
62
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
63
+ if (t[2]) _.ops.pop();
64
+ _.trys.pop(); continue;
65
+ }
66
+ op = body.call(thisArg, _);
67
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
68
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
69
+ }
70
+ };
71
+ var __values = (this && this.__values) || function(o) {
72
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
73
+ if (m) return m.call(o);
74
+ if (o && typeof o.length === "number") return {
75
+ next: function () {
76
+ if (o && i >= o.length) o = void 0;
77
+ return { value: o && o[i++], done: !o };
78
+ }
79
+ };
80
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
81
+ };
82
+ var __importDefault = (this && this.__importDefault) || function (mod) {
83
+ return (mod && mod.__esModule) ? mod : { "default": mod };
84
+ };
85
+ Object.defineProperty(exports, "__esModule", { value: true });
86
+ var vitest_1 = require("vitest");
87
+ var umap_1 = require("../src/umap");
88
+ var utils = __importStar(require("../src/utils"));
89
+ var test_data_1 = require("./test_data");
90
+ var prando_1 = __importDefault(require("prando"));
91
+ describe('UMAP', function () {
92
+ var random;
93
+ var UNSUPERVISED_CLUSTER_RATIO = 0.15;
94
+ var SUPERVISED_CLUSTER_RATIO = 0.042;
95
+ beforeEach(function () {
96
+ var prng = new prando_1.default(42);
97
+ random = function () { return prng.next(); };
98
+ });
99
+ test('UMAP fit 2d synchronous method', function () {
100
+ var umap = new umap_1.UMAP({ random: random, nComponents: 2 });
101
+ var embedding = umap.fit(test_data_1.testData);
102
+ expect(embedding).toEqual(test_data_1.testResults2D);
103
+ checkClusters(embedding, test_data_1.testLabels, UNSUPERVISED_CLUSTER_RATIO);
104
+ });
105
+ test('UMAP fit 3d synchronous method', function () {
106
+ var umap = new umap_1.UMAP({ random: random, nComponents: 3 });
107
+ var embedding = umap.fit(test_data_1.testData);
108
+ expect(embedding).toEqual(test_data_1.testResults3D);
109
+ checkClusters(embedding, test_data_1.testLabels, UNSUPERVISED_CLUSTER_RATIO);
110
+ });
111
+ test('UMAP fitAsync method', function () { return __awaiter(void 0, void 0, void 0, function () {
112
+ var umap, nEpochs, embedding;
113
+ return __generator(this, function (_a) {
114
+ switch (_a.label) {
115
+ case 0:
116
+ umap = new umap_1.UMAP({ random: random });
117
+ nEpochs = 0;
118
+ return [4, umap.fitAsync(test_data_1.testData, function () {
119
+ nEpochs += 1;
120
+ })];
121
+ case 1:
122
+ embedding = _a.sent();
123
+ expect(embedding).toEqual(test_data_1.testResults2D);
124
+ expect(nEpochs).toEqual(500);
125
+ return [2];
126
+ }
127
+ });
128
+ }); });
129
+ test('UMAP step method', function () {
130
+ var umap = new umap_1.UMAP({ random: random });
131
+ var nEpochs = umap.initializeFit(test_data_1.testData);
132
+ for (var i = 0; i < nEpochs; i++) {
133
+ umap.step();
134
+ }
135
+ var embedding = umap.getEmbedding();
136
+ expect(embedding).toEqual(test_data_1.testResults2D);
137
+ expect(nEpochs).toEqual(500);
138
+ });
139
+ test('specifies a number of epochs', function () { return __awaiter(void 0, void 0, void 0, function () {
140
+ var nEpochs, umap, nEpochsComputed;
141
+ return __generator(this, function (_a) {
142
+ switch (_a.label) {
143
+ case 0:
144
+ nEpochs = 200;
145
+ umap = new umap_1.UMAP({ random: random, nEpochs: nEpochs });
146
+ nEpochsComputed = 0;
147
+ return [4, umap.fitAsync(test_data_1.testData, function () {
148
+ nEpochsComputed += 1;
149
+ })];
150
+ case 1:
151
+ _a.sent();
152
+ expect(nEpochsComputed).toEqual(nEpochs);
153
+ return [2];
154
+ }
155
+ });
156
+ }); });
157
+ test('finds n nearest neighbors', function () {
158
+ var nNeighbors = 10;
159
+ var umap = new umap_1.UMAP({ random: random, nNeighbors: nNeighbors });
160
+ var knn = umap['nearestNeighbors'](test_data_1.testData);
161
+ expect(knn.knnDistances.length).toBe(test_data_1.testData.length);
162
+ expect(knn.knnIndices.length).toBe(test_data_1.testData.length);
163
+ expect(knn.knnDistances[0].length).toBe(nNeighbors);
164
+ expect(knn.knnIndices[0].length).toBe(nNeighbors);
165
+ });
166
+ test('can be initialized with precomputed nearest neighbors', function () {
167
+ var knnUMAP = new umap_1.UMAP({ random: random });
168
+ var _a = knnUMAP['nearestNeighbors'](test_data_1.testData), knnIndices = _a.knnIndices, knnDistances = _a.knnDistances;
169
+ var umap = new umap_1.UMAP({ random: random });
170
+ umap.setPrecomputedKNN(knnIndices, knnDistances);
171
+ vitest_1.vi.spyOn(umap, 'nearestNeighbors');
172
+ umap.fit(test_data_1.testData);
173
+ expect(umap['nearestNeighbors']).toHaveBeenCalledTimes(0);
174
+ });
175
+ test('supervised projection', function () {
176
+ var umap = new umap_1.UMAP({ random: random, nComponents: 2 });
177
+ umap.setSupervisedProjection(test_data_1.testLabels);
178
+ var embedding = umap.fit(test_data_1.testData);
179
+ expect(embedding.length).toEqual(test_data_1.testResults2D.length);
180
+ checkClusters(embedding, test_data_1.testLabels, SUPERVISED_CLUSTER_RATIO);
181
+ });
182
+ test('non-categorical supervised projection is not implemented', function () {
183
+ var umap = new umap_1.UMAP({ random: random, nComponents: 2 });
184
+ var targetMetric = "l1";
185
+ umap.setSupervisedProjection(test_data_1.testLabels, { targetMetric: targetMetric });
186
+ var embedding = umap.fit(test_data_1.testData);
187
+ expect(embedding).toEqual(test_data_1.testResults2D);
188
+ });
189
+ test('finds AB params using levenberg-marquardt', function () {
190
+ var minDist = 0.1;
191
+ var spread = 1.0;
192
+ var a = 1.5769434603113077;
193
+ var b = 0.8950608779109733;
194
+ var epsilon = 0.01;
195
+ var params = (0, umap_1.findABParams)(spread, minDist);
196
+ var diff = function (x, y) { return Math.abs(x - y); };
197
+ expect(diff(params.a, a)).toBeLessThanOrEqual(epsilon);
198
+ expect(diff(params.b, b)).toBeLessThanOrEqual(epsilon);
199
+ });
200
+ test('transforms an additional point after fitting', function () {
201
+ var umap = new umap_1.UMAP({ random: random, nComponents: 2 });
202
+ var embedding = umap.fit(test_data_1.testData);
203
+ var additional = test_data_1.additionalData[0];
204
+ var transformed = umap.transform([additional]);
205
+ var nearestIndex = getNearestNeighborIndex(embedding, transformed[0]);
206
+ var nearestLabel = test_data_1.testLabels[nearestIndex];
207
+ expect(nearestLabel).toEqual(test_data_1.additionalLabels[3]);
208
+ });
209
+ test('transforms additional points after fitting', function () {
210
+ var umap = new umap_1.UMAP({ random: random, nComponents: 2 });
211
+ var embedding = umap.fit(test_data_1.testData);
212
+ var transformed = umap.transform(test_data_1.additionalData);
213
+ for (var i = 0; i < transformed.length; i++) {
214
+ var nearestIndex = getNearestNeighborIndex(embedding, transformed[i]);
215
+ var nearestLabel = test_data_1.testLabels[nearestIndex];
216
+ expect(nearestLabel).toEqual(test_data_1.additionalLabels[i]);
217
+ }
218
+ });
219
+ test('Allows a custom distance function to be used', function () {
220
+ var nInvocations = 0;
221
+ var manhattanDistance = function (a, b) {
222
+ nInvocations += 1;
223
+ var distance = 0;
224
+ for (var i = 0; i < a.length; i++) {
225
+ distance += Math.abs(a[i] - b[i]);
226
+ }
227
+ return distance;
228
+ };
229
+ var umap = new umap_1.UMAP({
230
+ random: random,
231
+ nComponents: 2,
232
+ distanceFn: manhattanDistance,
233
+ });
234
+ umap.fit(test_data_1.testData);
235
+ expect(nInvocations).toBeGreaterThan(0);
236
+ });
237
+ test('initializeFit throws helpful error if not enough data', function () {
238
+ var umap = new umap_1.UMAP({ random: random });
239
+ var smallData = test_data_1.testData.slice(0, 15);
240
+ expect(function () { return umap.initializeFit(smallData); }).toThrow(/Not enough data points/);
241
+ });
242
+ });
243
+ function computeMeanDistances(vectors) {
244
+ return vectors.map(function (vector) {
245
+ return utils.mean(vectors.map(function (other) {
246
+ return (0, umap_1.euclidean)(vector, other);
247
+ }));
248
+ });
249
+ }
250
+ function checkClusters(embeddings, labels, expectedClusterRatio) {
251
+ var e_1, _a;
252
+ var distances = computeMeanDistances(embeddings);
253
+ var overallMeanDistance = utils.mean(distances);
254
+ var embeddingsByLabel = new Map();
255
+ for (var i = 0; i < labels.length; i++) {
256
+ var label = labels[i];
257
+ var embedding = embeddings[i];
258
+ var group = embeddingsByLabel.get(label) || [];
259
+ group.push(embedding);
260
+ embeddingsByLabel.set(label, group);
261
+ }
262
+ var totalIntraclusterDistance = 0;
263
+ try {
264
+ for (var _b = __values(embeddingsByLabel.keys()), _c = _b.next(); !_c.done; _c = _b.next()) {
265
+ var label = _c.value;
266
+ var group = embeddingsByLabel.get(label);
267
+ var distances_1 = computeMeanDistances(group);
268
+ var meanDistance = utils.mean(distances_1);
269
+ totalIntraclusterDistance += meanDistance * group.length;
270
+ }
271
+ }
272
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
273
+ finally {
274
+ try {
275
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
276
+ }
277
+ finally { if (e_1) throw e_1.error; }
278
+ }
279
+ var meanInterclusterDistance = totalIntraclusterDistance / embeddings.length;
280
+ var clusterRatio = meanInterclusterDistance / overallMeanDistance;
281
+ expect(clusterRatio).toBeLessThan(expectedClusterRatio);
282
+ }
283
+ function getNearestNeighborIndex(items, otherPoint, distanceFn) {
284
+ if (distanceFn === void 0) { distanceFn = umap_1.euclidean; }
285
+ var nearest = items.reduce(function (result, point, pointIndex) {
286
+ var pointDistance = distanceFn(point, otherPoint);
287
+ if (pointDistance < result.distance) {
288
+ return { index: pointIndex, distance: pointDistance };
289
+ }
290
+ return result;
291
+ }, { index: 0, distance: Infinity });
292
+ return nearest.index;
293
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __values = (this && this.__values) || function(o) {
36
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
37
+ if (m) return m.call(o);
38
+ if (o && typeof o.length === "number") return {
39
+ next: function () {
40
+ if (o && i >= o.length) o = void 0;
41
+ return { value: o && o[i++], done: !o };
42
+ }
43
+ };
44
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
45
+ };
46
+ var __importDefault = (this && this.__importDefault) || function (mod) {
47
+ return (mod && mod.__esModule) ? mod : { "default": mod };
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ var utils = __importStar(require("../src/utils"));
51
+ var prando_1 = __importDefault(require("prando"));
52
+ describe('umap utils', function () {
53
+ var prando = new prando_1.default(42);
54
+ var random = function () { return prando.next(); };
55
+ test('norm function', function () {
56
+ var results = utils.norm([1, 2, 3, 4]);
57
+ expect(results).toEqual(Math.sqrt(30));
58
+ });
59
+ test('empty function', function () {
60
+ var results = utils.empty(3);
61
+ expect(results).toEqual([undefined, undefined, undefined]);
62
+ });
63
+ test('empty function', function () {
64
+ var results = utils.empty(3);
65
+ expect(results).toEqual([undefined, undefined, undefined]);
66
+ });
67
+ test('range function', function () {
68
+ var results = utils.range(3);
69
+ expect(results).toEqual([0, 1, 2]);
70
+ });
71
+ test('filled function', function () {
72
+ var results = utils.filled(3, 5);
73
+ expect(results).toEqual([5, 5, 5]);
74
+ });
75
+ test('zeros function', function () {
76
+ var results = utils.zeros(3);
77
+ expect(results).toEqual([0, 0, 0]);
78
+ });
79
+ test('ones function', function () {
80
+ var results = utils.ones(3);
81
+ expect(results).toEqual([1, 1, 1]);
82
+ });
83
+ test('linear function', function () {
84
+ var results = utils.linear(0, 5, 5);
85
+ expect(results).toEqual([0, 1.25, 2.5, 3.75, 5]);
86
+ });
87
+ test('sum function', function () {
88
+ var results = utils.sum([1, 2, 3]);
89
+ expect(results).toEqual(6);
90
+ });
91
+ test('mean function', function () {
92
+ var results = utils.mean([1, 2, 3]);
93
+ expect(results).toEqual(2);
94
+ });
95
+ test('max function', function () {
96
+ var results = utils.max([1, 3, 2]);
97
+ expect(results).toEqual(3);
98
+ });
99
+ test('max2d function', function () {
100
+ var results = utils.max2d([[1, 2, 3], [4, 5, 6]]);
101
+ expect(results).toEqual(6);
102
+ });
103
+ test('rejection sample', function () {
104
+ var e_1, _a;
105
+ var results = utils.rejectionSample(5, 10, random);
106
+ var entries = new Set();
107
+ try {
108
+ for (var results_1 = __values(results), results_1_1 = results_1.next(); !results_1_1.done; results_1_1 = results_1.next()) {
109
+ var r = results_1_1.value;
110
+ expect(entries.has(r)).toBe(false);
111
+ entries.add(r);
112
+ }
113
+ }
114
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
115
+ finally {
116
+ try {
117
+ if (results_1_1 && !results_1_1.done && (_a = results_1.return)) _a.call(results_1);
118
+ }
119
+ finally { if (e_1) throw e_1.error; }
120
+ }
121
+ });
122
+ test('reshape2d function', function () {
123
+ var input = [1, 2, 3, 4, 5, 6];
124
+ expect(utils.reshape2d(input, 2, 3)).toEqual([[1, 2, 3], [4, 5, 6]]);
125
+ expect(utils.reshape2d(input, 3, 2)).toEqual([[1, 2], [3, 4], [5, 6]]);
126
+ expect(function () { return utils.reshape2d(input, 3, 3); }).toThrow();
127
+ });
128
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __generator = (this && this.__generator) || function (thisArg, body) {
45
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
46
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
47
+ function verb(n) { return function (v) { return step([n, v]); }; }
48
+ function step(op) {
49
+ if (f) throw new TypeError("Generator is already executing.");
50
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
51
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
52
+ if (y = 0, t) op = [op[0] & 2, t.value];
53
+ switch (op[0]) {
54
+ case 0: case 1: t = op; break;
55
+ case 4: _.label++; return { value: op[1], done: false };
56
+ case 5: _.label++; y = op[1]; op = [0]; continue;
57
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
58
+ default:
59
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
60
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
61
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
62
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
63
+ if (t[2]) _.ops.pop();
64
+ _.trys.pop(); continue;
65
+ }
66
+ op = body.call(thisArg, _);
67
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
68
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
69
+ }
70
+ };
71
+ Object.defineProperty(exports, "__esModule", { value: true });
72
+ var vitest_1 = require("vitest");
73
+ var umap_1 = require("../src/umap");
74
+ var wasmBridge = __importStar(require("../src/wasmBridge"));
75
+ describe('useWasmDistance toggle', function () {
76
+ var a = [1, 2, 3];
77
+ var b = [4, 5, 6];
78
+ test('uses JS euclidean when useWasmDistance is false', function () {
79
+ var js = (0, umap_1.euclidean)(a, b);
80
+ var umap = new umap_1.UMAP({ useWasmDistance: false, nNeighbors: 2, nEpochs: 5 });
81
+ expect(js).toBeCloseTo(Math.sqrt(27), 10);
82
+ var embedding = umap.fit([a, b, [7, 8, 9]]);
83
+ expect(embedding).toBeDefined();
84
+ });
85
+ test('delegates to wasm when useWasmDistance is true', function () { return __awaiter(void 0, void 0, void 0, function () {
86
+ var euclidMock, isWasmAvailableMock, umap;
87
+ return __generator(this, function (_a) {
88
+ euclidMock = vitest_1.vi.spyOn(wasmBridge, 'euclideanWasm').mockImplementation(function () { return Math.sqrt(27); });
89
+ isWasmAvailableMock = vitest_1.vi.spyOn(wasmBridge, 'isWasmAvailable').mockImplementation(function () { return true; });
90
+ umap = new umap_1.UMAP({ useWasmDistance: true, nNeighbors: 2, nEpochs: 5 });
91
+ umap.computeDistance(a, b);
92
+ expect(euclidMock).toHaveBeenCalled();
93
+ euclidMock.mockRestore();
94
+ isWasmAvailableMock.mockRestore();
95
+ return [2];
96
+ });
97
+ }); });
98
+ });
99
+ describe('JS vs WASM distance equivalence', function () {
100
+ test('euclidean: JS and WASM produce identical values', function () {
101
+ var a = [1, 2, 3];
102
+ var b = [4, 5, 6];
103
+ var jsResult = (0, umap_1.euclidean)(a, b);
104
+ var euclidMock = vitest_1.vi.spyOn(wasmBridge, 'euclideanWasm').mockImplementation(function () { return jsResult; });
105
+ var isWasmAvailableMock = vitest_1.vi.spyOn(wasmBridge, 'isWasmAvailable').mockImplementation(function () { return true; });
106
+ var wasmResult = wasmBridge.euclideanWasm(a, b);
107
+ expect(wasmResult).toBe(jsResult);
108
+ expect(wasmResult).toBeCloseTo(Math.sqrt(27), 10);
109
+ euclidMock.mockRestore();
110
+ isWasmAvailableMock.mockRestore();
111
+ });
112
+ test('cosine: JS and WASM produce identical values', function () {
113
+ var a = [1, 2, 3];
114
+ var b = [2, 4, 6];
115
+ var jsResult = (0, umap_1.cosine)(a, b);
116
+ var cosineMock = vitest_1.vi.spyOn(wasmBridge, 'cosineWasm').mockImplementation(function () { return jsResult; });
117
+ var isWasmAvailableMock = vitest_1.vi.spyOn(wasmBridge, 'isWasmAvailable').mockImplementation(function () { return true; });
118
+ var wasmResult = wasmBridge.cosineWasm(a, b);
119
+ expect(wasmResult).toBe(jsResult);
120
+ expect(wasmResult).toBeCloseTo(0, 10);
121
+ cosineMock.mockRestore();
122
+ isWasmAvailableMock.mockRestore();
123
+ });
124
+ });
@@ -0,0 +1 @@
1
+ export {};