pca-web 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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +421 -0
  3. package/dist/base.d.ts +79 -0
  4. package/dist/base.d.ts.map +1 -0
  5. package/dist/base.js +358 -0
  6. package/dist/base.js.map +1 -0
  7. package/dist/incremental-pca.d.ts +86 -0
  8. package/dist/incremental-pca.d.ts.map +1 -0
  9. package/dist/incremental-pca.js +397 -0
  10. package/dist/incremental-pca.js.map +1 -0
  11. package/dist/index.d.ts +21 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +14 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/matrix.d.ts +44 -0
  16. package/dist/matrix.d.ts.map +1 -0
  17. package/dist/matrix.js +99 -0
  18. package/dist/matrix.js.map +1 -0
  19. package/dist/model.d.ts +86 -0
  20. package/dist/model.d.ts.map +1 -0
  21. package/dist/model.js +132 -0
  22. package/dist/model.js.map +1 -0
  23. package/dist/numeric/blas.d.ts +33 -0
  24. package/dist/numeric/blas.d.ts.map +1 -0
  25. package/dist/numeric/blas.js +130 -0
  26. package/dist/numeric/blas.js.map +1 -0
  27. package/dist/numeric/eigh.d.ts +21 -0
  28. package/dist/numeric/eigh.d.ts.map +1 -0
  29. package/dist/numeric/eigh.js +233 -0
  30. package/dist/numeric/eigh.js.map +1 -0
  31. package/dist/numeric/lanczos.d.ts +31 -0
  32. package/dist/numeric/lanczos.d.ts.map +1 -0
  33. package/dist/numeric/lanczos.js +287 -0
  34. package/dist/numeric/lanczos.js.map +1 -0
  35. package/dist/numeric/lu.d.ts +27 -0
  36. package/dist/numeric/lu.d.ts.map +1 -0
  37. package/dist/numeric/lu.js +149 -0
  38. package/dist/numeric/lu.js.map +1 -0
  39. package/dist/numeric/mle.d.ts +5 -0
  40. package/dist/numeric/mle.d.ts.map +1 -0
  41. package/dist/numeric/mle.js +67 -0
  42. package/dist/numeric/mle.js.map +1 -0
  43. package/dist/numeric/qr.d.ts +15 -0
  44. package/dist/numeric/qr.d.ts.map +1 -0
  45. package/dist/numeric/qr.js +88 -0
  46. package/dist/numeric/qr.js.map +1 -0
  47. package/dist/numeric/randomized.d.ts +54 -0
  48. package/dist/numeric/randomized.d.ts.map +1 -0
  49. package/dist/numeric/randomized.js +130 -0
  50. package/dist/numeric/randomized.js.map +1 -0
  51. package/dist/numeric/rng.d.ts +40 -0
  52. package/dist/numeric/rng.d.ts.map +1 -0
  53. package/dist/numeric/rng.js +127 -0
  54. package/dist/numeric/rng.js.map +1 -0
  55. package/dist/numeric/special.d.ts +2 -0
  56. package/dist/numeric/special.d.ts.map +1 -0
  57. package/dist/numeric/special.js +25 -0
  58. package/dist/numeric/special.js.map +1 -0
  59. package/dist/numeric/stats.d.ts +27 -0
  60. package/dist/numeric/stats.d.ts.map +1 -0
  61. package/dist/numeric/stats.js +110 -0
  62. package/dist/numeric/stats.js.map +1 -0
  63. package/dist/numeric/svd.d.ts +27 -0
  64. package/dist/numeric/svd.d.ts.map +1 -0
  65. package/dist/numeric/svd.js +374 -0
  66. package/dist/numeric/svd.js.map +1 -0
  67. package/dist/numeric/svdflip.d.ts +9 -0
  68. package/dist/numeric/svdflip.d.ts.map +1 -0
  69. package/dist/numeric/svdflip.js +32 -0
  70. package/dist/numeric/svdflip.js.map +1 -0
  71. package/dist/pca.d.ts +170 -0
  72. package/dist/pca.d.ts.map +1 -0
  73. package/dist/pca.js +649 -0
  74. package/dist/pca.js.map +1 -0
  75. package/dist/progress.d.ts +155 -0
  76. package/dist/progress.d.ts.map +1 -0
  77. package/dist/progress.js +173 -0
  78. package/dist/progress.js.map +1 -0
  79. package/dist/scheduling.d.ts +66 -0
  80. package/dist/scheduling.d.ts.map +1 -0
  81. package/dist/scheduling.js +160 -0
  82. package/dist/scheduling.js.map +1 -0
  83. package/dist/types.d.ts +10 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +11 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/validation.d.ts +17 -0
  88. package/dist/validation.d.ts.map +1 -0
  89. package/dist/validation.js +36 -0
  90. package/dist/validation.js.map +1 -0
  91. package/dist/webgpu/df64.d.ts +18 -0
  92. package/dist/webgpu/df64.d.ts.map +1 -0
  93. package/dist/webgpu/df64.js +42 -0
  94. package/dist/webgpu/df64.js.map +1 -0
  95. package/dist/webgpu/engine.d.ts +74 -0
  96. package/dist/webgpu/engine.d.ts.map +1 -0
  97. package/dist/webgpu/engine.js +326 -0
  98. package/dist/webgpu/engine.js.map +1 -0
  99. package/dist/webgpu/gpu-pca.d.ts +90 -0
  100. package/dist/webgpu/gpu-pca.d.ts.map +1 -0
  101. package/dist/webgpu/gpu-pca.js +407 -0
  102. package/dist/webgpu/gpu-pca.js.map +1 -0
  103. package/dist/webgpu/index.d.ts +19 -0
  104. package/dist/webgpu/index.d.ts.map +1 -0
  105. package/dist/webgpu/index.js +16 -0
  106. package/dist/webgpu/index.js.map +1 -0
  107. package/dist/webgpu/kernels.d.ts +47 -0
  108. package/dist/webgpu/kernels.d.ts.map +1 -0
  109. package/dist/webgpu/kernels.js +147 -0
  110. package/dist/webgpu/kernels.js.map +1 -0
  111. package/dist/worker/client.d.ts +174 -0
  112. package/dist/worker/client.d.ts.map +1 -0
  113. package/dist/worker/client.js +482 -0
  114. package/dist/worker/client.js.map +1 -0
  115. package/dist/worker/handler.d.ts +17 -0
  116. package/dist/worker/handler.d.ts.map +1 -0
  117. package/dist/worker/handler.js +404 -0
  118. package/dist/worker/handler.js.map +1 -0
  119. package/dist/worker/protocol.d.ts +192 -0
  120. package/dist/worker/protocol.d.ts.map +1 -0
  121. package/dist/worker/protocol.js +70 -0
  122. package/dist/worker/protocol.js.map +1 -0
  123. package/dist/worker/worker.d.ts +14 -0
  124. package/dist/worker/worker.d.ts.map +1 -0
  125. package/dist/worker/worker.js +20 -0
  126. package/dist/worker/worker.js.map +1 -0
  127. package/package.json +94 -0
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Wire protocol shared by the worker handler (`pca-web/worker`) and the
3
+ * client proxies (`pca-web/client`).
4
+ *
5
+ * Import discipline: this module (and everything the client pulls in) must
6
+ * stay free of solver code — value imports are limited to matrix/types/
7
+ * model/validation; estimator and progress types appear type-only (erased
8
+ * at build time). This is what keeps `pca-web/client` a ~few-KB proxy while
9
+ * `pca-web/worker` carries the estimators.
10
+ */
11
+ import { Matrix } from '../matrix.js';
12
+ export const PCA_WORKER_PROTOCOL_VERSION = 1;
13
+ /** A typed array that owns its entire buffer (safe to clone or transfer). */
14
+ export function tightArray(a) {
15
+ return a.byteOffset === 0 && a.byteLength === a.buffer.byteLength ? a : a.slice();
16
+ }
17
+ /**
18
+ * Encodes a Matrix for the wire. The data is tight-sliced when it is a
19
+ * view — cloning or transferring a subarray view would otherwise serialize
20
+ * (or detach) its entire parent buffer.
21
+ */
22
+ export function matrixToWire(m) {
23
+ return { kind: 'matrix', data: tightArray(m.data), rows: m.rows, cols: m.cols };
24
+ }
25
+ export function wireToMatrix(w) {
26
+ return new Matrix(w.data, w.rows, w.cols);
27
+ }
28
+ export function isWireMatrix(v) {
29
+ return (typeof v === 'object' &&
30
+ v !== null &&
31
+ v.kind === 'matrix' &&
32
+ (v.data instanceof Float64Array ||
33
+ v.data instanceof Float32Array));
34
+ }
35
+ export function toWireError(err) {
36
+ if (err instanceof Error) {
37
+ const wire = { name: err.name || 'Error', message: err.message };
38
+ if (typeof err.stack === 'string') {
39
+ wire.stack = err.stack;
40
+ }
41
+ return wire;
42
+ }
43
+ return { name: 'Error', message: String(err) };
44
+ }
45
+ // ---------------------------------------------------------------------
46
+ // Guards and transfer-list helpers
47
+ // ---------------------------------------------------------------------
48
+ const REQUEST_TAGS = new Set(['create', 'call', 'abort', 'dispose']);
49
+ const RESPONSE_TAGS = new Set(['ready', 'result', 'progress', 'error']);
50
+ export function isWorkerRequest(v) {
51
+ return typeof v === 'object' && v !== null && REQUEST_TAGS.has(v.t);
52
+ }
53
+ export function isWorkerResponse(v) {
54
+ return (typeof v === 'object' && v !== null && RESPONSE_TAGS.has(v.t));
55
+ }
56
+ /** Buffers of a model's typed arrays (all tight by `toModel` contract). */
57
+ export function modelTransferList(model) {
58
+ const buffers = [
59
+ model.components.buffer,
60
+ model.mean.buffer,
61
+ model.explainedVariance.buffer,
62
+ model.explainedVarianceRatio.buffer,
63
+ model.singularValues.buffer,
64
+ ];
65
+ if (model.estimator === 'ipca') {
66
+ buffers.push(model.variance.buffer);
67
+ }
68
+ return buffers;
69
+ }
70
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/worker/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `pca-web/worker` — drop-in worker entry.
3
+ *
4
+ * Spawned directly (`new Worker(new URL('pca-web/worker', import.meta.url),
5
+ * { type: 'module' })` or via a one-line `import 'pca-web/worker'` in your
6
+ * own worker file), it attaches the pca-web protocol to the worker scope.
7
+ * Importing it from a non-worker context is harmless: auto-attach happens
8
+ * only inside a real DedicatedWorkerGlobalScope, so this module doubles as
9
+ * the programmatic entry — `attachPCAWorker(port)` works with any message
10
+ * port, including Node's `worker_threads` `parentPort`.
11
+ */
12
+ export { type AttachPCAWorkerOptions, attachPCAWorker } from './handler.js';
13
+ export * from './protocol.js';
14
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/worker/worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC5E,cAAc,eAAe,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `pca-web/worker` — drop-in worker entry.
3
+ *
4
+ * Spawned directly (`new Worker(new URL('pca-web/worker', import.meta.url),
5
+ * { type: 'module' })` or via a one-line `import 'pca-web/worker'` in your
6
+ * own worker file), it attaches the pca-web protocol to the worker scope.
7
+ * Importing it from a non-worker context is harmless: auto-attach happens
8
+ * only inside a real DedicatedWorkerGlobalScope, so this module doubles as
9
+ * the programmatic entry — `attachPCAWorker(port)` works with any message
10
+ * port, including Node's `worker_threads` `parentPort`.
11
+ */
12
+ import { attachPCAWorker } from './handler.js';
13
+ export { attachPCAWorker } from './handler.js';
14
+ export * from './protocol.js';
15
+ const scope = globalThis;
16
+ if (typeof scope.DedicatedWorkerGlobalScope === 'function' &&
17
+ globalThis instanceof scope.DedicatedWorkerGlobalScope) {
18
+ attachPCAWorker(globalThis);
19
+ }
20
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/worker/worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAA+B,eAAe,EAAE,MAAM,cAAc,CAAC;AAC5E,cAAc,eAAe,CAAC;AAE9B,MAAM,KAAK,GAAG,UAAyE,CAAC;AACxF,IACE,OAAO,KAAK,CAAC,0BAA0B,KAAK,UAAU;IACtD,UAAU,YAAY,KAAK,CAAC,0BAA0B,EACtD,CAAC;IACD,eAAe,CAAC,UAAsC,CAAC,CAAC;AAC1D,CAAC"}
package/package.json ADDED
@@ -0,0 +1,94 @@
1
+ {
2
+ "name": "pca-web",
3
+ "version": "0.1.0",
4
+ "description": "Client-side PCA and IncrementalPCA for the browser and Node.js — a zero-dependency TypeScript reimplementation of scikit-learn's decomposition.PCA with optional WebGPU acceleration.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Jeya Balaji Balasubramanian",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/jeyabbalas/pca-web.git"
11
+ },
12
+ "keywords": [
13
+ "pca",
14
+ "principal-component-analysis",
15
+ "dimensionality-reduction",
16
+ "scikit-learn",
17
+ "machine-learning",
18
+ "webgpu",
19
+ "svd",
20
+ "incremental-pca",
21
+ "browser"
22
+ ],
23
+ "engines": {
24
+ "node": ">=20"
25
+ },
26
+ "sideEffects": [
27
+ "./dist/worker/worker.js",
28
+ "./src/worker/worker.ts"
29
+ ],
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ },
37
+ "./webgpu": {
38
+ "types": "./dist/webgpu/index.d.ts",
39
+ "default": "./dist/webgpu/index.js"
40
+ },
41
+ "./worker": {
42
+ "types": "./dist/worker/worker.d.ts",
43
+ "default": "./dist/worker/worker.js"
44
+ },
45
+ "./client": {
46
+ "types": "./dist/worker/client.d.ts",
47
+ "default": "./dist/worker/client.js"
48
+ }
49
+ },
50
+ "files": [
51
+ "dist",
52
+ "README.md",
53
+ "LICENSE"
54
+ ],
55
+ "workspaces": [
56
+ "examples/demo"
57
+ ],
58
+ "scripts": {
59
+ "prepack": "npm run build",
60
+ "build": "tsc -p tsconfig.build.json",
61
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.tests.json",
62
+ "lint": "biome check .",
63
+ "format": "biome format --write .",
64
+ "test": "vitest run",
65
+ "test:watch": "vitest",
66
+ "test:coverage": "vitest run --coverage",
67
+ "test:browser": "node tests/browser/run.mjs",
68
+ "test:browser:worker": "node tests/browser/run-worker.mjs",
69
+ "bench": "node bench/cpu.mjs",
70
+ "bench:browser": "node bench/browser.mjs",
71
+ "demo:dev": "npm run build && npm -w examples/demo run dev",
72
+ "demo:build": "npm run build && npm -w examples/demo run build",
73
+ "fixtures": ".venv/bin/python python/generate_fixtures.py",
74
+ "demo:data": ".venv/bin/python python/generate_demo_data.py"
75
+ },
76
+ "devDependencies": {
77
+ "@biomejs/biome": "^2.5.2",
78
+ "@types/node": "^24.13.2",
79
+ "@vitest/coverage-v8": "^4.1.10",
80
+ "@webgpu/types": "^0.1.71",
81
+ "esbuild": "^0.28.1",
82
+ "playwright": "^1.61.1",
83
+ "typescript": "^6.0.3",
84
+ "vitest": "^4.1.10"
85
+ },
86
+ "peerDependencies": {
87
+ "@webgpu/types": "*"
88
+ },
89
+ "peerDependenciesMeta": {
90
+ "@webgpu/types": {
91
+ "optional": true
92
+ }
93
+ }
94
+ }