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,90 @@
1
+ import { Matrix, type MatrixInput } from '../matrix.js';
2
+ import type { PCAModel } from '../model.js';
3
+ import { type PCAOptions, type SvdSolver } from '../pca.js';
4
+ import { type FitAsyncOptions } from '../progress.js';
5
+ import type { FloatArray } from '../types.js';
6
+ import { type WebGPUDeviceOptions } from './engine.js';
7
+ export interface WebGPUPCAOptions extends PCAOptions, WebGPUDeviceOptions {
8
+ /**
9
+ * Minimum element count (rows × cols) before the GPU path is used;
10
+ * smaller problems run on the CPU, where they are faster anyway.
11
+ * Default 1<<18 (≈262k elements).
12
+ */
13
+ minGpuElements?: number;
14
+ }
15
+ export declare class WebGPUPCA {
16
+ private cpu;
17
+ private readonly deviceOptions;
18
+ private readonly minGpuElements;
19
+ private enginePromise;
20
+ private engine;
21
+ private backend_;
22
+ private gpuFitting;
23
+ constructor(options?: WebGPUPCAOptions);
24
+ /** True when a WebGPU implementation is present in this environment. */
25
+ static isSupported(): boolean;
26
+ /** 'webgpu' when the last fit/transform used the GPU, else 'cpu'. */
27
+ get backend(): 'webgpu' | 'cpu';
28
+ /** Adapter description of the engine in use, or null on the CPU fallback. */
29
+ get gpuAdapterInfo(): string | null;
30
+ /** Measured df64 GEMM relative error from the device self-check (NaN on CPU). */
31
+ get gpuMeasuredRelError(): number;
32
+ /** Releases GPU resources (does not destroy an injected device). */
33
+ dispose(): void;
34
+ fit(X: MatrixInput, options?: FitAsyncOptions): Promise<this>;
35
+ fitTransform(X: MatrixInput, options?: FitAsyncOptions): Promise<Matrix>;
36
+ /** Concurrent fits on one instance would interleave GPU state; throw early. */
37
+ private guardConcurrentFit;
38
+ /**
39
+ * Validates the input (before any GPU spend or in-place mutation) and
40
+ * decides which backend the fit runs on. Mutates nothing.
41
+ */
42
+ private route;
43
+ /** GPU Gram product + shared CPU covariance_eigh tail. Mutates nothing on failure. */
44
+ private fitGramGpu;
45
+ /**
46
+ * GPU-driven randomized fit: centers on the CPU (respecting copy
47
+ * semantics), keeps X resident on the device, and drives the shared
48
+ * algorithm generator with GPU GEMMs. Returns the (sign-flipped)
49
+ * decomposition for the fitTransform fast path.
50
+ */
51
+ private fitRandomizedGpu;
52
+ /**
53
+ * CPU refit after a GPU failure — unless the input was already mutated,
54
+ * or the "failure" is a cancellation: an abort must reject with the abort
55
+ * error, never silently refit on the CPU.
56
+ */
57
+ private recoverOnGpuError;
58
+ transform(X: MatrixInput): Promise<Matrix>;
59
+ /** CPU delegate (small k×p GEMM; not worth a device round-trip). */
60
+ inverseTransform(X: MatrixInput): Matrix;
61
+ get components(): Matrix;
62
+ get explainedVariance(): FloatArray;
63
+ get explainedVarianceRatio(): FloatArray;
64
+ get singularValues(): FloatArray;
65
+ get mean(): FloatArray;
66
+ get nComponents(): number;
67
+ get nSamples(): number;
68
+ get nFeaturesIn(): number;
69
+ get noiseVariance(): number;
70
+ get whiten(): boolean;
71
+ get resolvedSvdSolver(): Exclude<SvdSolver, 'auto'>;
72
+ getCovariance(): Matrix;
73
+ getPrecision(): Matrix;
74
+ scoreSamples(X: MatrixInput): FloatArray;
75
+ score(X: MatrixInput): number;
76
+ getFeatureNamesOut(): string[];
77
+ /** The fitted model as a plain object — identical to the CPU class's. */
78
+ toModel(): PCAModel;
79
+ /**
80
+ * Rehydrates a fitted WebGPUPCA. `options` supplies the device knobs
81
+ * (powerPreference, injected device, minGpuElements); the PCA options
82
+ * come from the model itself.
83
+ */
84
+ static fromModel(model: PCAModel, options?: WebGPUDeviceOptions & {
85
+ minGpuElements?: number;
86
+ }): WebGPUPCA;
87
+ private ensureEngine;
88
+ private gpuEligible;
89
+ }
90
+ //# sourceMappingURL=gpu-pca.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu-pca.d.ts","sourceRoot":"","sources":["../../src/webgpu/gpu-pca.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,407 @@
1
+ /**
2
+ * WebGPU-accelerated PCA with a numerically-equivalent CPU fallback.
3
+ *
4
+ * The GPU takes over exactly the large-GEMM hotspots — the XᵀX Gram product
5
+ * of covariance_eigh, the power-iteration panel products of the randomized
6
+ * solver (X stays resident on the device across iterations), and large
7
+ * transform projections. Everything else (eigh, panel QR/LU, the small SVD,
8
+ * sign flips, variance bookkeeping, validation) runs through the same code
9
+ * as the CPU `PCA` class via internal bridges, so semantics cannot drift.
10
+ *
11
+ * When WebGPU is unavailable — or the fit is too small to benefit, or the
12
+ * solver is inherently sequential (full, arpack) — fit() delegates to the
13
+ * CPU implementation and produces bit-identical results. When the GPU is
14
+ * used, results match the CPU path within the df64 GEMM accuracy measured
15
+ * by the equivalence test suite (~1e-12 relative on components).
16
+ */
17
+ import { castTo } from '../base.js';
18
+ import { asMatrix, Matrix } from '../matrix.js';
19
+ import { randomizedSvdSteps } from '../numeric/randomized.js';
20
+ import { checkRandomState } from '../numeric/rng.js';
21
+ import { centerInPlace, colMeans } from '../numeric/stats.js';
22
+ import { PCA, resolveSvdSolver, validateNcForSolver, } from '../pca.js';
23
+ import { makeReporter } from '../progress.js';
24
+ import { throwIfAborted } from '../scheduling.js';
25
+ import { assertAllFinite, assertMinSamplesForFit, checkFeatureCount } from '../validation.js';
26
+ import { GpuEngine, isWebGPUSupported } from './engine.js';
27
+ /** Wraps a GPU failure that must not trigger a CPU refit (input was mutated). */
28
+ class GpuFitUnrecoverableError extends Error {
29
+ cause;
30
+ constructor(cause) {
31
+ super('WebGPU fit failed after in-place mutation');
32
+ this.cause = cause;
33
+ }
34
+ }
35
+ export class WebGPUPCA {
36
+ cpu;
37
+ deviceOptions;
38
+ minGpuElements;
39
+ enginePromise = null;
40
+ engine = null;
41
+ backend_ = 'cpu';
42
+ gpuFitting = false;
43
+ constructor(options = {}) {
44
+ const { device, powerPreference, minGpuElements, ...pcaOptions } = options;
45
+ this.cpu = new PCA(pcaOptions);
46
+ this.deviceOptions = { device, powerPreference };
47
+ this.minGpuElements = minGpuElements ?? 1 << 18;
48
+ }
49
+ /** True when a WebGPU implementation is present in this environment. */
50
+ static isSupported() {
51
+ return isWebGPUSupported();
52
+ }
53
+ /** 'webgpu' when the last fit/transform used the GPU, else 'cpu'. */
54
+ get backend() {
55
+ return this.backend_;
56
+ }
57
+ /** Adapter description of the engine in use, or null on the CPU fallback. */
58
+ get gpuAdapterInfo() {
59
+ return this.engine?.adapterInfo ?? null;
60
+ }
61
+ /** Measured df64 GEMM relative error from the device self-check (NaN on CPU). */
62
+ get gpuMeasuredRelError() {
63
+ return this.engine?.measuredRelError ?? Number.NaN;
64
+ }
65
+ /** Releases GPU resources (does not destroy an injected device). */
66
+ dispose() {
67
+ this.engine?.dispose();
68
+ this.engine = null;
69
+ this.enginePromise = null;
70
+ }
71
+ // ------------------------------------------------------------------
72
+ // Fitting
73
+ // ------------------------------------------------------------------
74
+ async fit(X, options = {}) {
75
+ const xm = asMatrix(X);
76
+ this.guardConcurrentFit();
77
+ try {
78
+ const route = await this.route(xm);
79
+ if (route === 'cpu') {
80
+ // The fallback is non-blocking, observable, and abortable too —
81
+ // and still bit-identical to the plain PCA class.
82
+ await this.cpu.fitAsync(xm, options);
83
+ this.backend_ = 'cpu';
84
+ return this;
85
+ }
86
+ try {
87
+ if (route === 'covariance_eigh') {
88
+ await this.fitGramGpu(xm, options);
89
+ }
90
+ else {
91
+ await this.fitRandomizedGpu(xm, options);
92
+ }
93
+ }
94
+ catch (err) {
95
+ await this.recoverOnGpuError(xm, err, options);
96
+ }
97
+ return this;
98
+ }
99
+ finally {
100
+ this.gpuFitting = false;
101
+ }
102
+ }
103
+ async fitTransform(X, options = {}) {
104
+ const xm = asMatrix(X);
105
+ this.guardConcurrentFit();
106
+ try {
107
+ const route = await this.route(xm);
108
+ if (route === 'cpu') {
109
+ this.backend_ = 'cpu';
110
+ return await this.cpu.fitTransformAsync(xm, options);
111
+ }
112
+ if (route === 'covariance_eigh') {
113
+ try {
114
+ await this.fitGramGpu(xm, options);
115
+ }
116
+ catch (err) {
117
+ await this.recoverOnGpuError(xm, err, options);
118
+ }
119
+ // sklearn's fit_transform for covariance_eigh IS transform-after-fit
120
+ // (no U is computed at fit time), so this matches exactly.
121
+ return await this.transform(xm);
122
+ }
123
+ let dec;
124
+ try {
125
+ dec = await this.fitRandomizedGpu(xm, options);
126
+ }
127
+ catch (err) {
128
+ await this.recoverOnGpuError(xm, err, options, 'skipFit');
129
+ return await this.cpu.fitTransformAsync(xm, options);
130
+ }
131
+ // Randomized fast path: X_new = U·S (or U·√(n−1) when whitening),
132
+ // exactly like PCA.fitTransform.
133
+ const n = xm.rows;
134
+ const k = this.cpu.nComponents;
135
+ const out = new Float64Array(n * k);
136
+ const whiten = this.cpu.whiten;
137
+ const f = Math.sqrt(n - 1);
138
+ for (let i = 0; i < n; i++) {
139
+ for (let c = 0; c < k; c++) {
140
+ out[i * k + c] = whiten ? dec.u[i * k + c] * f : dec.u[i * k + c] * dec.s[c];
141
+ }
142
+ }
143
+ return new Matrix(castTo(out, xm.dtype), n, k);
144
+ }
145
+ finally {
146
+ this.gpuFitting = false;
147
+ }
148
+ }
149
+ /** Concurrent fits on one instance would interleave GPU state; throw early. */
150
+ guardConcurrentFit() {
151
+ if (this.gpuFitting) {
152
+ throw new Error('This WebGPUPCA instance is already fitting; concurrent fits on one instance are not supported');
153
+ }
154
+ this.gpuFitting = true;
155
+ }
156
+ /**
157
+ * Validates the input (before any GPU spend or in-place mutation) and
158
+ * decides which backend the fit runs on. Mutates nothing.
159
+ */
160
+ async route(xm) {
161
+ if (xm.rows < 1 || xm.cols < 1) {
162
+ throw new Error(`Found array with shape (${xm.rows}, ${xm.cols}); PCA requires at least 1 sample and 1 feature`);
163
+ }
164
+ assertMinSamplesForFit(xm, 'PCA');
165
+ assertAllFinite(xm, 'PCA.fit');
166
+ const o = this.cpu._resolvedOptions();
167
+ const solver = resolveSvdSolver(xm.rows, xm.cols, o.nComponents, o.svdSolver);
168
+ const engine = await this.ensureEngine();
169
+ if (!this.gpuEligible(engine, xm, solver)) {
170
+ return 'cpu';
171
+ }
172
+ // Fail doomed configurations before uploading anything.
173
+ const nc = o.nComponents === null ? Math.min(xm.rows, xm.cols) : o.nComponents;
174
+ validateNcForSolver(nc, xm.rows, xm.cols, solver);
175
+ return solver;
176
+ }
177
+ /** GPU Gram product + shared CPU covariance_eigh tail. Mutates nothing on failure. */
178
+ async fitGramGpu(xm, options) {
179
+ const eng = this.engine;
180
+ const reporter = makeReporter(options, {
181
+ estimator: 'PCA',
182
+ solver: 'covariance_eigh',
183
+ nRows: xm.rows,
184
+ whiten: this.cpu.whiten,
185
+ });
186
+ throwIfAborted(options.signal);
187
+ const gx = eng.upload(xm.data, xm.rows, xm.cols);
188
+ try {
189
+ reporter?.emit({ phase: 'gram', step: 0, totalSteps: 1 });
190
+ const gram = await eng.syrk(gx);
191
+ reporter?.emit({ phase: 'gram', step: 1, totalSteps: 1 });
192
+ throwIfAborted(options.signal);
193
+ reporter?.emit({ phase: 'decompose', step: 0, totalSteps: null });
194
+ this.cpu._fitGram(xm, gram);
195
+ this.backend_ = 'webgpu';
196
+ if (reporter) {
197
+ this.cpu._emitFinalize(reporter, xm, null, 0, null);
198
+ }
199
+ }
200
+ finally {
201
+ gx.destroy();
202
+ }
203
+ }
204
+ /**
205
+ * GPU-driven randomized fit: centers on the CPU (respecting copy
206
+ * semantics), keeps X resident on the device, and drives the shared
207
+ * algorithm generator with GPU GEMMs. Returns the (sign-flipped)
208
+ * decomposition for the fitTransform fast path.
209
+ */
210
+ async fitRandomizedGpu(xm, options) {
211
+ const eng = this.engine;
212
+ const o = this.cpu._resolvedOptions();
213
+ const n = xm.rows;
214
+ const p = xm.cols;
215
+ const nc = (o.nComponents === null ? Math.min(n, p) : o.nComponents);
216
+ const reporter = makeReporter(options, {
217
+ estimator: 'PCA',
218
+ solver: 'randomized',
219
+ nRows: n,
220
+ whiten: this.cpu.whiten,
221
+ });
222
+ throwIfAborted(options.signal);
223
+ const meanF64 = colMeans(xm.data, n, p);
224
+ const xc = o.copy ? xm.data.slice() : xm.data;
225
+ centerInPlace(xc, n, p, meanF64);
226
+ const gx = eng.upload(xc, n, p);
227
+ try {
228
+ const rng = checkRandomState(o.randomState);
229
+ // The reporter rides the solver's hooks: power-iteration events and
230
+ // snapshot decompositions surface as ordinary GEMM requests below, so
231
+ // X stays device-resident throughout.
232
+ const gen = randomizedSvdSteps(n, p, nc, {
233
+ nOversamples: o.nOversamples,
234
+ nIter: o.iteratedPower,
235
+ powerIterationNormalizer: o.powerIterationNormalizer,
236
+ rng,
237
+ float32Stream: xm.dtype === 'float32',
238
+ hooks: reporter,
239
+ });
240
+ let step = gen.next();
241
+ while (!step.done) {
242
+ throwIfAborted(options.signal);
243
+ const req = step.value;
244
+ const result = req.op === 'mulA'
245
+ ? await eng.mulA(gx, req.b, req.w)
246
+ : req.op === 'mulAT'
247
+ ? await eng.mulAT(gx, req.b, req.w)
248
+ : await eng.mulTA(gx, req.b, req.w);
249
+ step = gen.next(result);
250
+ }
251
+ const dec = step.value;
252
+ this.cpu._fitDecomposed(xm, xc, meanF64, dec);
253
+ this.backend_ = 'webgpu';
254
+ if (reporter) {
255
+ this.cpu._emitFinalize(reporter, xm, dec.u, nc, dec.s);
256
+ }
257
+ return dec;
258
+ }
259
+ catch (err) {
260
+ if (!o.copy) {
261
+ // X was centered in place; a silent CPU retry would re-center the
262
+ // mutated buffer and corrupt the fit. Surface the GPU failure.
263
+ throw new GpuFitUnrecoverableError(err);
264
+ }
265
+ throw err;
266
+ }
267
+ finally {
268
+ gx.destroy();
269
+ }
270
+ }
271
+ /**
272
+ * CPU refit after a GPU failure — unless the input was already mutated,
273
+ * or the "failure" is a cancellation: an abort must reject with the abort
274
+ * error, never silently refit on the CPU.
275
+ */
276
+ async recoverOnGpuError(xm, err, options, mode) {
277
+ if (err instanceof GpuFitUnrecoverableError) {
278
+ throw err.cause;
279
+ }
280
+ if (options.signal?.aborted || err?.name === 'AbortError') {
281
+ throw err;
282
+ }
283
+ this.backend_ = 'cpu';
284
+ if (mode !== 'skipFit') {
285
+ await this.cpu.fitAsync(xm, options);
286
+ }
287
+ }
288
+ // ------------------------------------------------------------------
289
+ // Transforms (GPU projection for large inputs, CPU otherwise)
290
+ // ------------------------------------------------------------------
291
+ async transform(X) {
292
+ const xm = asMatrix(X);
293
+ const engine = this.engine;
294
+ const comp = this.cpu.components; // asserts fitted
295
+ if (engine === null ||
296
+ xm.rows * xm.cols < this.minGpuElements ||
297
+ !engine.canFit(xm.rows, xm.cols) ||
298
+ !engine.canFit(comp.rows, comp.cols)) {
299
+ return this.cpu.transform(xm);
300
+ }
301
+ assertAllFinite(xm, 'PCA.transform');
302
+ checkFeatureCount(xm, this.cpu.nFeaturesIn, 'PCA');
303
+ const gx = engine.upload(xm.data, xm.rows, xm.cols);
304
+ const gc = engine.upload(comp.data, comp.rows, comp.cols);
305
+ try {
306
+ const proj = await engine.project(gx, gc);
307
+ return this.cpu._transformFromProjection(proj, xm.rows, xm.dtype, false);
308
+ }
309
+ catch {
310
+ return this.cpu.transform(xm);
311
+ }
312
+ finally {
313
+ gx.destroy();
314
+ gc.destroy();
315
+ }
316
+ }
317
+ /** CPU delegate (small k×p GEMM; not worth a device round-trip). */
318
+ inverseTransform(X) {
319
+ return this.cpu.inverseTransform(X);
320
+ }
321
+ // ------------------------------------------------------------------
322
+ // Fitted state and CPU-delegated methods
323
+ // ------------------------------------------------------------------
324
+ get components() {
325
+ return this.cpu.components;
326
+ }
327
+ get explainedVariance() {
328
+ return this.cpu.explainedVariance;
329
+ }
330
+ get explainedVarianceRatio() {
331
+ return this.cpu.explainedVarianceRatio;
332
+ }
333
+ get singularValues() {
334
+ return this.cpu.singularValues;
335
+ }
336
+ get mean() {
337
+ return this.cpu.mean;
338
+ }
339
+ get nComponents() {
340
+ return this.cpu.nComponents;
341
+ }
342
+ get nSamples() {
343
+ return this.cpu.nSamples;
344
+ }
345
+ get nFeaturesIn() {
346
+ return this.cpu.nFeaturesIn;
347
+ }
348
+ get noiseVariance() {
349
+ return this.cpu.noiseVariance;
350
+ }
351
+ get whiten() {
352
+ return this.cpu.whiten;
353
+ }
354
+ get resolvedSvdSolver() {
355
+ return this.cpu.resolvedSvdSolver;
356
+ }
357
+ getCovariance() {
358
+ return this.cpu.getCovariance();
359
+ }
360
+ getPrecision() {
361
+ return this.cpu.getPrecision();
362
+ }
363
+ scoreSamples(X) {
364
+ return this.cpu.scoreSamples(X);
365
+ }
366
+ score(X) {
367
+ return this.cpu.score(X);
368
+ }
369
+ getFeatureNamesOut() {
370
+ return this.cpu.getFeatureNamesOut();
371
+ }
372
+ // ------------------------------------------------------------------
373
+ // Model serialization
374
+ // ------------------------------------------------------------------
375
+ /** The fitted model as a plain object — identical to the CPU class's. */
376
+ toModel() {
377
+ return this.cpu.toModel();
378
+ }
379
+ /**
380
+ * Rehydrates a fitted WebGPUPCA. `options` supplies the device knobs
381
+ * (powerPreference, injected device, minGpuElements); the PCA options
382
+ * come from the model itself.
383
+ */
384
+ static fromModel(model, options = {}) {
385
+ const gpu = new WebGPUPCA({ ...model.options, ...options });
386
+ gpu.cpu = PCA.fromModel(model);
387
+ return gpu;
388
+ }
389
+ // ------------------------------------------------------------------
390
+ async ensureEngine() {
391
+ if (this.enginePromise === null) {
392
+ this.enginePromise = GpuEngine.create(this.deviceOptions).then((e) => {
393
+ this.engine = e;
394
+ return e;
395
+ });
396
+ }
397
+ return this.enginePromise;
398
+ }
399
+ gpuEligible(engine, xm, solver) {
400
+ return (engine !== null &&
401
+ (solver === 'covariance_eigh' || solver === 'randomized') &&
402
+ xm.rows * xm.cols >= this.minGpuElements &&
403
+ engine.canFit(xm.rows, xm.cols) &&
404
+ engine.canFit(xm.cols, xm.cols));
405
+ }
406
+ }
407
+ //# sourceMappingURL=gpu-pca.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu-pca.js","sourceRoot":"","sources":["../../src/webgpu/gpu-pca.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `pca-web/webgpu` — WebGPU-accelerated PCA.
3
+ *
4
+ * import { WebGPUPCA, isWebGPUSupported } from 'pca-web/webgpu';
5
+ *
6
+ * TypeScript: the declarations reference the standard WebGPU globals.
7
+ * With `lib: ["dom"]` (TS ≥ 5.9) they resolve natively; Node-only
8
+ * consumers add the types-only package @webgpu/types instead (see README).
9
+ */
10
+ export { asMatrix, Matrix, type MatrixInput } from '../matrix.js';
11
+ export type { PCAModel, PCAModelOptions } from '../model.js';
12
+ export { assertValidModel, modelFromJSON, modelToJSON } from '../model.js';
13
+ export { PCA, type PCAOptions, type PowerIterationNormalizer, type SvdSolver } from '../pca.js';
14
+ export type { FitAsyncOptions, FitObserver, FitPhase, FitSolverId, PCAFitProgress, PCAFitSnapshot, SnapshotOptions, } from '../progress.js';
15
+ export type { AbortSignalLike } from '../scheduling.js';
16
+ export { FitAbortError } from '../scheduling.js';
17
+ export { GpuEngine, isWebGPUSupported, type WebGPUDeviceOptions } from './engine.js';
18
+ export { WebGPUPCA, type WebGPUPCAOptions } from './gpu-pca.js';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webgpu/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAClE,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK,wBAAwB,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAChG,YAAY,EACV,eAAe,EACf,WAAW,EACX,QAAQ,EACR,WAAW,EACX,cAAc,EACd,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `pca-web/webgpu` — WebGPU-accelerated PCA.
3
+ *
4
+ * import { WebGPUPCA, isWebGPUSupported } from 'pca-web/webgpu';
5
+ *
6
+ * TypeScript: the declarations reference the standard WebGPU globals.
7
+ * With `lib: ["dom"]` (TS ≥ 5.9) they resolve natively; Node-only
8
+ * consumers add the types-only package @webgpu/types instead (see README).
9
+ */
10
+ export { asMatrix, Matrix } from '../matrix.js';
11
+ export { assertValidModel, modelFromJSON, modelToJSON } from '../model.js';
12
+ export { PCA } from '../pca.js';
13
+ export { FitAbortError } from '../scheduling.js';
14
+ export { GpuEngine, isWebGPUSupported } from './engine.js';
15
+ export { WebGPUPCA } from './gpu-pca.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webgpu/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAoB,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,GAAG,EAAkE,MAAM,WAAW,CAAC;AAWhG,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAA4B,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,SAAS,EAAyB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * WGSL GEMM kernels with near-f64 accuracy on f32-only hardware.
3
+ *
4
+ * Design constraint discovered empirically (Chrome/Dawn on Metal): the MSL
5
+ * compiler applies fast-math — classic Dekker/Knuth error-free
6
+ * transformations (two_sum, split) are algebraically folded to zero, and
7
+ * multiply-add pairs are contracted into fma, so double-single (df64)
8
+ * accumulation silently degrades to f32. What DOES survive, verified by
9
+ * on-device probes:
10
+ * - fma(a, b, -a*b) computes the exact f32 multiplication error
11
+ * - single float ops are correctly rounded (no cross-op guarantees)
12
+ * - i32 conversions and integer adds are exact and untouched by fast-math
13
+ *
14
+ * So products use fma-exact two_prod, and ACCUMULATION is exact integer
15
+ * binning: every product term is decomposed — exactly, via power-of-two
16
+ * scaling and fma residuals — into 5 levels of 13-bit integers on a fixed
17
+ * per-dispatch grid (exponent E bounds every |a·b| term), accumulated in
18
+ * i32 (no rounding at all), and recombined in float64 on the CPU. The only
19
+ * error is the truncated tail below the last grid level:
20
+ * |error| ≤ K·7·2^(E-65) ≤ maxProduct·2^-45
21
+ * comparable to true f64 accumulation. Inputs are (hi, lo) f32 pairs of the
22
+ * f64 values; the three significant cross products (+ the tiny lo·lo term)
23
+ * feed the binner, preserving ~48 significant bits end to end.
24
+ *
25
+ * One tiled kernel template covers all four op(A)·op(B) transpose variants;
26
+ * only the injected index expressions differ.
27
+ */
28
+ export declare const TILE = 16;
29
+ /**
30
+ * Per-level bin capacity is 2^13; with ≤7 terms per MAC each contributing
31
+ * |n| ≤ 2^13 per level, i32 overflows at K ≈ 2^31/(7·2^13) ≈ 37k. The
32
+ * engine splits the K dimension at this bound and sums chunks in f64.
33
+ */
34
+ export declare const MAX_K_PER_DISPATCH = 30000;
35
+ /** i32 bin levels per output element (13 bits each → 65 bits of grid). */
36
+ export declare const BIN_LEVELS = 5;
37
+ /** i32 slots per output element in the C buffer (BIN_LEVELS padded to 8). */
38
+ export declare const OUT_SLOTS = 8;
39
+ /**
40
+ * Builds the GEMM shader for C(M×N) = op(A)·op(B) over K = [kStart, kStart+kCount).
41
+ *
42
+ * Physical shapes: A is M×K_total when !ta, K_total×M when ta; B is
43
+ * K_total×N when !tb, N×K_total when tb. All row-major, ds-encoded
44
+ * (array<vec2f> of hi/lo pairs). C is array<i32>, OUT_SLOTS per element.
45
+ */
46
+ export declare function gemmShader(ta: boolean, tb: boolean): string;
47
+ //# sourceMappingURL=kernels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kernels.d.ts","sourceRoot":"","sources":["../../src/webgpu/kernels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,IAAI,KAAK,CAAC;AAEvB;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC,0EAA0E;AAC1E,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B,6EAA6E;AAC7E,eAAO,MAAM,SAAS,IAAI,CAAC;AAE3B;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,CAoG3D"}