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
package/dist/types.js ADDED
@@ -0,0 +1,11 @@
1
+ export function dtypeOf(a) {
2
+ return a instanceof Float64Array ? 'float64' : 'float32';
3
+ }
4
+ export function constructorFor(dtype) {
5
+ return dtype === 'float64' ? Float64Array : Float32Array;
6
+ }
7
+ /** Machine epsilon for a dtype (numpy finfo(dtype).eps). */
8
+ export function epsFor(dtype) {
9
+ return dtype === 'float64' ? 2.220446049250313e-16 : 1.1920929e-7;
10
+ }
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,OAAO,CAAC,CAAa;IACnC,OAAO,CAAC,YAAY,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAY;IACzC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC;AAC3D,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,MAAM,CAAC,KAAY;IACjC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC;AACpE,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Matrix } from './matrix.js';
2
+ /** Thrown when a method requiring a fitted model is called before fit. */
3
+ export declare class NotFittedError extends Error {
4
+ constructor(estimator: string);
5
+ }
6
+ /** Rejects NaN/Infinity, mirroring sklearn's input validation. */
7
+ export declare function assertAllFinite(x: Matrix, context: string): void;
8
+ /**
9
+ * Rejects fits on fewer than 2 samples. Every variance path divides by
10
+ * n − 1, so a single-sample fit can only produce an all-NaN model. sklearn
11
+ * permits it with a RuntimeWarning; with no warning channel here this is a
12
+ * deliberate, documented deviation. Message text mirrors sklearn's
13
+ * check_array(ensure_min_samples=2).
14
+ */
15
+ export declare function assertMinSamplesForFit(x: Matrix, estimator: string): void;
16
+ export declare function checkFeatureCount(x: Matrix, expected: number, estimator: string): void;
17
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,0EAA0E;AAC1E,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,SAAS,EAAE,MAAM;CAO9B;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAOhE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAOzE;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAMtF"}
@@ -0,0 +1,36 @@
1
+ /** Thrown when a method requiring a fitted model is called before fit. */
2
+ export class NotFittedError extends Error {
3
+ constructor(estimator) {
4
+ super(`This ${estimator} instance is not fitted yet. ` +
5
+ `Call 'fit' with appropriate arguments before using this estimator.`);
6
+ this.name = 'NotFittedError';
7
+ }
8
+ }
9
+ /** Rejects NaN/Infinity, mirroring sklearn's input validation. */
10
+ export function assertAllFinite(x, context) {
11
+ const d = x.data;
12
+ for (let i = 0; i < d.length; i++) {
13
+ if (!Number.isFinite(d[i])) {
14
+ throw new Error(`Input contains ${Number.isNaN(d[i]) ? 'NaN' : 'infinity'} (${context})`);
15
+ }
16
+ }
17
+ }
18
+ /**
19
+ * Rejects fits on fewer than 2 samples. Every variance path divides by
20
+ * n − 1, so a single-sample fit can only produce an all-NaN model. sklearn
21
+ * permits it with a RuntimeWarning; with no warning channel here this is a
22
+ * deliberate, documented deviation. Message text mirrors sklearn's
23
+ * check_array(ensure_min_samples=2).
24
+ */
25
+ export function assertMinSamplesForFit(x, estimator) {
26
+ if (x.rows < 2) {
27
+ throw new Error(`Found array with ${x.rows} sample(s) (shape=(${x.rows}, ${x.cols})) ` +
28
+ `while a minimum of 2 is required by ${estimator}.`);
29
+ }
30
+ }
31
+ export function checkFeatureCount(x, expected, estimator) {
32
+ if (x.cols !== expected) {
33
+ throw new Error(`X has ${x.cols} features, but ${estimator} is expecting ${expected} features as input`);
34
+ }
35
+ }
36
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAEA,0EAA0E;AAC1E,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,SAAiB;QAC3B,KAAK,CACH,QAAQ,SAAS,+BAA+B;YAC9C,oEAAoE,CACvE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,kEAAkE;AAClE,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,OAAe;IACxD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,OAAO,GAAG,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,CAAS,EAAE,SAAiB;IACjE,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,oBAAoB,CAAC,CAAC,IAAI,sBAAsB,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK;YACpE,uCAAuC,SAAS,GAAG,CACtD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,CAAS,EAAE,QAAgB,EAAE,SAAiB;IAC9E,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,SAAS,CAAC,CAAC,IAAI,kBAAkB,SAAS,iBAAiB,QAAQ,oBAAoB,CACxF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * double-single ("ds") encoding: each float64 is carried as an unevaluated
3
+ * sum of two float32 values (hi + lo), preserving ~48 significant bits.
4
+ * WGSL has no f64; the GEMM kernels multiply ds pairs exactly via fma and
5
+ * accumulate in exact integer bins (see kernels.ts).
6
+ *
7
+ * Matrices are prescaled by a power of two before encoding so their
8
+ * magnitude is ~1: power-of-two scaling is exact in f64, keeps every
9
+ * on-device grid in normal f32 range for any normal f64 input, and is
10
+ * undone exactly on the result.
11
+ */
12
+ /** Largest |x|; 0 for an empty or all-zero array. */
13
+ export declare function maxAbs(src: ArrayLike<number>): number;
14
+ /** Power-of-two exponent s with |x|·2^-s ≤ ~1 for |x| ≤ max (0 for max = 0). */
15
+ export declare function prescaleExponent(max: number): number;
16
+ /** Packs values·2^-scaleExp into interleaved (hi, lo) f32 pairs. */
17
+ export declare function encodeDs(src: ArrayLike<number>, scaleExp: number): Float32Array;
18
+ //# sourceMappingURL=df64.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"df64.d.ts","sourceRoot":"","sources":["../../src/webgpu/df64.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,qDAAqD;AACrD,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CASrD;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,oEAAoE;AACpE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAU/E"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * double-single ("ds") encoding: each float64 is carried as an unevaluated
3
+ * sum of two float32 values (hi + lo), preserving ~48 significant bits.
4
+ * WGSL has no f64; the GEMM kernels multiply ds pairs exactly via fma and
5
+ * accumulate in exact integer bins (see kernels.ts).
6
+ *
7
+ * Matrices are prescaled by a power of two before encoding so their
8
+ * magnitude is ~1: power-of-two scaling is exact in f64, keeps every
9
+ * on-device grid in normal f32 range for any normal f64 input, and is
10
+ * undone exactly on the result.
11
+ */
12
+ /** Largest |x|; 0 for an empty or all-zero array. */
13
+ export function maxAbs(src) {
14
+ let m = 0;
15
+ for (let i = 0; i < src.length; i++) {
16
+ const a = Math.abs(src[i]);
17
+ if (a > m) {
18
+ m = a;
19
+ }
20
+ }
21
+ return m;
22
+ }
23
+ /** Power-of-two exponent s with |x|·2^-s ≤ ~1 for |x| ≤ max (0 for max = 0). */
24
+ export function prescaleExponent(max) {
25
+ if (max === 0) {
26
+ return 0;
27
+ }
28
+ return Math.ceil(Math.log2(max));
29
+ }
30
+ /** Packs values·2^-scaleExp into interleaved (hi, lo) f32 pairs. */
31
+ export function encodeDs(src, scaleExp) {
32
+ const scale = 2 ** -scaleExp; // exact for any reasonable exponent
33
+ const out = new Float32Array(src.length * 2);
34
+ for (let i = 0; i < src.length; i++) {
35
+ const x = src[i] * scale; // exact: power-of-two multiply
36
+ const hi = Math.fround(x);
37
+ out[2 * i] = hi;
38
+ out[2 * i + 1] = Math.fround(x - hi);
39
+ }
40
+ return out;
41
+ }
42
+ //# sourceMappingURL=df64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"df64.js","sourceRoot":"","sources":["../../src/webgpu/df64.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,qDAAqD;AACrD,MAAM,UAAU,MAAM,CAAC,GAAsB;IAC3C,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,CAAC,GAAG,CAAC,CAAC;QACR,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACd,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,QAAQ,CAAC,GAAsB,EAAE,QAAgB;IAC/D,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,oCAAoC;IAClE,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,+BAA+B;QACzD,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1B,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAChB,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * WebGPU execution engine: device acquisition with feature detection, ds
3
+ * buffer management, and the exact-binned GEMM dispatch used by the
4
+ * WebGPUPCA frontend (see kernels.ts for the numerical design).
5
+ *
6
+ * The engine verifies at creation time that the kernel actually reaches
7
+ * near-f64 accuracy on the running driver; if the self-check fails,
8
+ * creation reports no engine and callers use the CPU path — numerical
9
+ * equivalence is part of the API contract.
10
+ */
11
+ import type { FloatArray } from '../types.js';
12
+ export interface WebGPUDeviceOptions {
13
+ /** Bring your own device (it will not be destroyed by dispose()). */
14
+ device?: GPUDevice;
15
+ powerPreference?: GPUPowerPreference;
16
+ }
17
+ /** True when a WebGPU implementation is present (browser or runtime flag). */
18
+ export declare function isWebGPUSupported(): boolean;
19
+ /** A device-resident ds matrix (prescaled by 2^-scaleExp). */
20
+ export interface GpuMat {
21
+ readonly buffer: GPUBuffer;
22
+ readonly rows: number;
23
+ readonly cols: number;
24
+ readonly scaleExp: number;
25
+ destroy(): void;
26
+ }
27
+ export declare class GpuEngine {
28
+ readonly device: GPUDevice;
29
+ readonly adapterInfo: string;
30
+ private readonly ownsDevice;
31
+ private readonly pipelines;
32
+ private disposed;
33
+ private relError;
34
+ private constructor();
35
+ /** Achieved |C_gpu − C_cpu| / |C_cpu| in the creation-time GEMM self-check. */
36
+ get measuredRelError(): number;
37
+ /**
38
+ * Human-readable reason for the most recent create() returning null
39
+ * (feature detection, adapter/device failure, or self-check details).
40
+ */
41
+ static lastCreateError: string | null;
42
+ /**
43
+ * Acquires a device and verifies GEMM precision. Returns null when WebGPU
44
+ * is unavailable, the adapter/device request fails, or the precision
45
+ * self-check does not reach near-f64 accuracy.
46
+ */
47
+ static create(options?: WebGPUDeviceOptions): Promise<GpuEngine | null>;
48
+ /** Whether an (rows×cols) ds matrix fits the device's binding limits. */
49
+ canFit(rows: number, cols: number): boolean;
50
+ /** Uploads a matrix to the device, prescaled and ds-encoded. */
51
+ upload(data: FloatArray, rows: number, cols: number): GpuMat;
52
+ /** C = A @ b for a device-resident A and a small CPU panel b (cols×w). */
53
+ mulA(a: GpuMat, b: Float64Array, w: number): Promise<Float64Array>;
54
+ /** C = Aᵀ @ b for a device-resident A and a small CPU panel b (rows×w). */
55
+ mulAT(a: GpuMat, b: Float64Array, w: number): Promise<Float64Array>;
56
+ /** C = bᵀ @ A (w×cols) for a device-resident A and a small CPU panel b (rows×w). */
57
+ mulTA(a: GpuMat, b: Float64Array, w: number): Promise<Float64Array>;
58
+ /** Raw Gram matrix C = AᵀA (cols×cols) of a device-resident A. */
59
+ syrk(a: GpuMat): Promise<Float64Array>;
60
+ /** Projection C = X @ compᵀ (n×k) with both operands device-resident. */
61
+ project(x: GpuMat, comp: GpuMat): Promise<Float64Array>;
62
+ dispose(): void;
63
+ private pipeline;
64
+ /**
65
+ * Runs op(A)·op(B) with exact integer-binned accumulation, splitting the
66
+ * K dimension when it exceeds the per-dispatch overflow bound; chunk
67
+ * results are summed in f64. Returns plain f64 values (rescaled).
68
+ */
69
+ private gemm;
70
+ private dispatchChunk;
71
+ /** Runs a small GEMM whose exact f64 result is computed on the CPU. */
72
+ private precisionSelfCheck;
73
+ }
74
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/webgpu/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,MAAM,WAAW,mBAAmB;IAClC,qEAAqE;IACrE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,eAAe,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED,8DAA8D;AAC9D,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,OAAO,IAAI,IAAI,CAAC;CACjB;AAYD,qBAAa,SAAS;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAc;IAE9B,OAAO;IAMP,+EAA+E;IAC/E,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED;;;OAGG;IACH,MAAM,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE7C;;;;OAIG;WACU,MAAM,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA0DjF,yEAAyE;IACzE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAa3C,gEAAgE;IAChE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAW5D,0EAA0E;IACpE,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IASxE,2EAA2E;IACrE,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IASzE,oFAAoF;IAC9E,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAiBzE,kEAAkE;IAC5D,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI5C,yEAAyE;IACnE,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI7D,OAAO,IAAI,IAAI;IAaf,OAAO,CAAC,QAAQ;IAchB;;;;OAIG;YACW,IAAI;YA0BJ,aAAa;IAuE3B,uEAAuE;YACzD,kBAAkB;CA6CjC"}
@@ -0,0 +1,326 @@
1
+ import { encodeDs, maxAbs, prescaleExponent } from './df64.js';
2
+ import { BIN_LEVELS, gemmShader, MAX_K_PER_DISPATCH, OUT_SLOTS, TILE } from './kernels.js';
3
+ /** True when a WebGPU implementation is present (browser or runtime flag). */
4
+ export function isWebGPUSupported() {
5
+ const nav = globalThis.navigator;
6
+ return typeof nav?.gpu === 'object' && nav.gpu !== null;
7
+ }
8
+ export class GpuEngine {
9
+ device;
10
+ adapterInfo;
11
+ ownsDevice;
12
+ pipelines = new Map();
13
+ disposed = false;
14
+ relError = Number.NaN;
15
+ constructor(device, ownsDevice, adapterInfo) {
16
+ this.device = device;
17
+ this.ownsDevice = ownsDevice;
18
+ this.adapterInfo = adapterInfo;
19
+ }
20
+ /** Achieved |C_gpu − C_cpu| / |C_cpu| in the creation-time GEMM self-check. */
21
+ get measuredRelError() {
22
+ return this.relError;
23
+ }
24
+ /**
25
+ * Human-readable reason for the most recent create() returning null
26
+ * (feature detection, adapter/device failure, or self-check details).
27
+ */
28
+ static lastCreateError = null;
29
+ /**
30
+ * Acquires a device and verifies GEMM precision. Returns null when WebGPU
31
+ * is unavailable, the adapter/device request fails, or the precision
32
+ * self-check does not reach near-f64 accuracy.
33
+ */
34
+ static async create(options = {}) {
35
+ GpuEngine.lastCreateError = null;
36
+ let device = options.device ?? null;
37
+ const ownsDevice = device === null;
38
+ let adapterInfo = 'injected device';
39
+ if (device === null) {
40
+ if (!isWebGPUSupported()) {
41
+ GpuEngine.lastCreateError = 'navigator.gpu is not available';
42
+ return null;
43
+ }
44
+ const gpu = globalThis.navigator.gpu;
45
+ let adapter = null;
46
+ try {
47
+ adapter = await gpu.requestAdapter({
48
+ powerPreference: options.powerPreference ?? 'high-performance',
49
+ });
50
+ }
51
+ catch (err) {
52
+ GpuEngine.lastCreateError = `requestAdapter threw: ${String(err)}`;
53
+ return null;
54
+ }
55
+ if (adapter === null) {
56
+ GpuEngine.lastCreateError = 'requestAdapter returned null';
57
+ return null;
58
+ }
59
+ const info = adapter.info;
60
+ adapterInfo = [info?.vendor, info?.architecture, info?.device, info?.description]
61
+ .filter((s) => typeof s === 'string' && s.length > 0)
62
+ .join(' / ');
63
+ try {
64
+ device = await adapter.requestDevice({
65
+ requiredLimits: {
66
+ maxStorageBufferBindingSize: adapter.limits.maxStorageBufferBindingSize,
67
+ maxBufferSize: adapter.limits.maxBufferSize,
68
+ },
69
+ });
70
+ }
71
+ catch (err) {
72
+ GpuEngine.lastCreateError = `requestDevice failed on "${adapterInfo}": ${String(err)}`;
73
+ return null;
74
+ }
75
+ }
76
+ const engine = new GpuEngine(device, ownsDevice, adapterInfo);
77
+ try {
78
+ engine.relError = await engine.precisionSelfCheck();
79
+ // Plain f32 accumulation would sit around 1e-7; the exact-binned
80
+ // kernel lands near 1e-14.
81
+ if (!(engine.relError < 1e-10)) {
82
+ GpuEngine.lastCreateError = `precision self-check too imprecise on "${adapterInfo}": relErr=${engine.relError.toExponential(2)}`;
83
+ engine.dispose();
84
+ return null;
85
+ }
86
+ return engine;
87
+ }
88
+ catch (err) {
89
+ GpuEngine.lastCreateError = `precision self-check failed on "${adapterInfo}": ${String(err)}`;
90
+ engine.dispose();
91
+ return null;
92
+ }
93
+ }
94
+ /** Whether an (rows×cols) ds matrix fits the device's binding limits. */
95
+ canFit(rows, cols) {
96
+ const dsBytes = rows * cols * 8;
97
+ const outBytes = rows * cols * OUT_SLOTS * 4;
98
+ const lim = this.device.limits;
99
+ const maxDim = Math.max(rows, cols);
100
+ return (dsBytes <= lim.maxStorageBufferBindingSize &&
101
+ outBytes <= lim.maxStorageBufferBindingSize &&
102
+ outBytes <= lim.maxBufferSize &&
103
+ Math.ceil(maxDim / TILE) <= lim.maxComputeWorkgroupsPerDimension);
104
+ }
105
+ /** Uploads a matrix to the device, prescaled and ds-encoded. */
106
+ upload(data, rows, cols) {
107
+ const scaleExp = prescaleExponent(maxAbs(data));
108
+ const ds = encodeDs(data, scaleExp);
109
+ const buffer = this.device.createBuffer({
110
+ size: ds.byteLength,
111
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
112
+ });
113
+ this.device.queue.writeBuffer(buffer, 0, ds);
114
+ return { buffer, rows, cols, scaleExp, destroy: () => buffer.destroy() };
115
+ }
116
+ /** C = A @ b for a device-resident A and a small CPU panel b (cols×w). */
117
+ async mulA(a, b, w) {
118
+ const panel = this.upload(b, a.cols, w);
119
+ try {
120
+ return await this.gemm({ a, b: panel, ta: false, tb: false, m: a.rows, n: w, k: a.cols });
121
+ }
122
+ finally {
123
+ panel.destroy();
124
+ }
125
+ }
126
+ /** C = Aᵀ @ b for a device-resident A and a small CPU panel b (rows×w). */
127
+ async mulAT(a, b, w) {
128
+ const panel = this.upload(b, a.rows, w);
129
+ try {
130
+ return await this.gemm({ a, b: panel, ta: true, tb: false, m: a.cols, n: w, k: a.rows });
131
+ }
132
+ finally {
133
+ panel.destroy();
134
+ }
135
+ }
136
+ /** C = bᵀ @ A (w×cols) for a device-resident A and a small CPU panel b (rows×w). */
137
+ async mulTA(a, b, w) {
138
+ const panel = this.upload(b, a.rows, w);
139
+ try {
140
+ return await this.gemm({
141
+ a: panel,
142
+ b: a,
143
+ ta: true,
144
+ tb: false,
145
+ m: w,
146
+ n: a.cols,
147
+ k: a.rows,
148
+ });
149
+ }
150
+ finally {
151
+ panel.destroy();
152
+ }
153
+ }
154
+ /** Raw Gram matrix C = AᵀA (cols×cols) of a device-resident A. */
155
+ async syrk(a) {
156
+ return this.gemm({ a, b: a, ta: true, tb: false, m: a.cols, n: a.cols, k: a.rows });
157
+ }
158
+ /** Projection C = X @ compᵀ (n×k) with both operands device-resident. */
159
+ async project(x, comp) {
160
+ return this.gemm({ a: x, b: comp, ta: false, tb: true, m: x.rows, n: comp.rows, k: x.cols });
161
+ }
162
+ dispose() {
163
+ if (this.disposed) {
164
+ return;
165
+ }
166
+ this.disposed = true;
167
+ this.pipelines.clear();
168
+ if (this.ownsDevice) {
169
+ this.device.destroy();
170
+ }
171
+ }
172
+ // ------------------------------------------------------------------
173
+ pipeline(ta, tb) {
174
+ const key = `${ta}-${tb}`;
175
+ let p = this.pipelines.get(key);
176
+ if (p === undefined) {
177
+ const module = this.device.createShaderModule({ code: gemmShader(ta, tb) });
178
+ p = this.device.createComputePipeline({
179
+ layout: 'auto',
180
+ compute: { module, entryPoint: 'main' },
181
+ });
182
+ this.pipelines.set(key, p);
183
+ }
184
+ return p;
185
+ }
186
+ /**
187
+ * Runs op(A)·op(B) with exact integer-binned accumulation, splitting the
188
+ * K dimension when it exceeds the per-dispatch overflow bound; chunk
189
+ * results are summed in f64. Returns plain f64 values (rescaled).
190
+ */
191
+ async gemm(spec) {
192
+ const out = new Float64Array(spec.m * spec.n);
193
+ // Grid exponent: prescaled inputs are ≤ 1 in magnitude, so every
194
+ // product term is < 2^1; +2 gives headroom for the bound being lax.
195
+ const e = 2;
196
+ const resultScale = 2 ** (spec.a.scaleExp + spec.b.scaleExp);
197
+ for (let kStart = 0; kStart < spec.k; kStart += MAX_K_PER_DISPATCH) {
198
+ const kCount = Math.min(MAX_K_PER_DISPATCH, spec.k - kStart);
199
+ const bins = await this.dispatchChunk(spec, kStart, kCount, e);
200
+ for (let i = 0; i < out.length; i++) {
201
+ const base = i * OUT_SLOTS;
202
+ let acc = 0;
203
+ for (let lvl = 0; lvl < BIN_LEVELS; lvl++) {
204
+ acc += bins[base + lvl] * 2 ** (e - 13 * (lvl + 1));
205
+ }
206
+ out[i] += acc;
207
+ }
208
+ }
209
+ if (resultScale !== 1) {
210
+ for (let i = 0; i < out.length; i++) {
211
+ out[i] *= resultScale;
212
+ }
213
+ }
214
+ return out;
215
+ }
216
+ async dispatchChunk(spec, kStart, kCount, e) {
217
+ const { device } = this;
218
+ const outBytes = spec.m * spec.n * OUT_SLOTS * 4;
219
+ device.pushErrorScope('out-of-memory');
220
+ device.pushErrorScope('validation');
221
+ const out = device.createBuffer({
222
+ size: outBytes,
223
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
224
+ });
225
+ const staging = device.createBuffer({
226
+ size: outBytes,
227
+ usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
228
+ });
229
+ const dims = device.createBuffer({
230
+ size: 32,
231
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
232
+ });
233
+ const dimsData = new ArrayBuffer(32);
234
+ const u32 = new Uint32Array(dimsData);
235
+ const i32 = new Int32Array(dimsData);
236
+ u32[0] = spec.m;
237
+ u32[1] = spec.n;
238
+ u32[2] = spec.k;
239
+ u32[3] = kStart;
240
+ u32[4] = kCount;
241
+ i32[5] = e;
242
+ device.queue.writeBuffer(dims, 0, dimsData);
243
+ const pipeline = this.pipeline(spec.ta, spec.tb);
244
+ const bind = device.createBindGroup({
245
+ layout: pipeline.getBindGroupLayout(0),
246
+ entries: [
247
+ { binding: 0, resource: { buffer: spec.a.buffer } },
248
+ { binding: 1, resource: { buffer: spec.b.buffer } },
249
+ { binding: 2, resource: { buffer: out } },
250
+ { binding: 3, resource: { buffer: dims } },
251
+ ],
252
+ });
253
+ const encoder = device.createCommandEncoder();
254
+ const pass = encoder.beginComputePass();
255
+ pass.setPipeline(pipeline);
256
+ pass.setBindGroup(0, bind);
257
+ pass.dispatchWorkgroups(Math.ceil(spec.n / TILE), Math.ceil(spec.m / TILE));
258
+ pass.end();
259
+ encoder.copyBufferToBuffer(out, 0, staging, 0, outBytes);
260
+ device.queue.submit([encoder.finish()]);
261
+ try {
262
+ const validationError = await device.popErrorScope();
263
+ const oomError = await device.popErrorScope();
264
+ if (validationError || oomError) {
265
+ throw new Error(`WebGPU GEMM failed: ${(validationError ?? oomError)?.message}`);
266
+ }
267
+ await staging.mapAsync(GPUMapMode.READ);
268
+ const bins = new Int32Array(staging.getMappedRange().slice(0));
269
+ staging.unmap();
270
+ return bins;
271
+ }
272
+ finally {
273
+ out.destroy();
274
+ staging.destroy();
275
+ dims.destroy();
276
+ }
277
+ }
278
+ /** Runs a small GEMM whose exact f64 result is computed on the CPU. */
279
+ async precisionSelfCheck() {
280
+ const m = 33;
281
+ const k = 47;
282
+ const n = 29;
283
+ // Deterministic values with nontrivial low-order bits (exercise the lo
284
+ // halves of the ds encoding and the deep bin levels).
285
+ const a = new Float64Array(m * k);
286
+ const b = new Float64Array(k * n);
287
+ for (let i = 0; i < a.length; i++) {
288
+ a[i] = Math.sin(i + 1) * 3 + 1e-9 * Math.cos(i * 7);
289
+ }
290
+ for (let i = 0; i < b.length; i++) {
291
+ b[i] = Math.cos(i + 2) * 2 + 1e-9 * Math.sin(i * 5);
292
+ }
293
+ const ref = new Float64Array(m * n);
294
+ for (let i = 0; i < m; i++) {
295
+ for (let j = 0; j < n; j++) {
296
+ let acc = 0;
297
+ for (let l = 0; l < k; l++) {
298
+ acc += a[i * k + l] * b[l * n + j];
299
+ }
300
+ ref[i * n + j] = acc;
301
+ }
302
+ }
303
+ const ga = this.upload(a, m, k);
304
+ const gb = this.upload(b, k, n);
305
+ try {
306
+ const got = await this.gemm({ a: ga, b: gb, ta: false, tb: false, m, n, k });
307
+ let refMax = 0;
308
+ for (let i = 0; i < ref.length; i++) {
309
+ refMax = Math.max(refMax, Math.abs(ref[i]));
310
+ }
311
+ let worst = 0;
312
+ for (let i = 0; i < ref.length; i++) {
313
+ // Scale-aware denominator: a near-cancelled reference entry must not
314
+ // spuriously fail the check (its absolute error is what matters).
315
+ const denom = Math.max(Math.abs(ref[i]), 1e-3 * refMax);
316
+ worst = Math.max(worst, Math.abs(got[i] - ref[i]) / denom);
317
+ }
318
+ return worst;
319
+ }
320
+ finally {
321
+ ga.destroy();
322
+ gb.destroy();
323
+ }
324
+ }
325
+ }
326
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/webgpu/engine.ts"],"names":[],"mappings":"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"}