@graphty/webgpu-graph-algorithms 0.2.1 → 0.4.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 (131) hide show
  1. package/README.md +50 -39
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{context-E6iKaeuJ.js → context-CRbw2Wyo.js} +178 -19
  4. package/dist/chunks/{context-E6iKaeuJ.js.map → context-CRbw2Wyo.js.map} +1 -1
  5. package/dist/node.js +1 -1
  6. package/dist/src/accelerator.d.ts +12 -7
  7. package/dist/src/accelerator.d.ts.map +1 -1
  8. package/dist/src/accelerator.js +88 -7
  9. package/dist/src/accelerator.js.map +1 -1
  10. package/dist/src/algorithms/components.d.ts +30 -0
  11. package/dist/src/algorithms/components.d.ts.map +1 -0
  12. package/dist/src/algorithms/components.js +300 -0
  13. package/dist/src/algorithms/components.js.map +1 -0
  14. package/dist/src/algorithms/pagerank.d.ts +39 -0
  15. package/dist/src/algorithms/pagerank.d.ts.map +1 -0
  16. package/dist/src/algorithms/pagerank.js +298 -0
  17. package/dist/src/algorithms/pagerank.js.map +1 -0
  18. package/dist/src/algorithms/power-iteration.d.ts +109 -0
  19. package/dist/src/algorithms/power-iteration.d.ts.map +1 -0
  20. package/dist/src/algorithms/power-iteration.js +206 -0
  21. package/dist/src/algorithms/power-iteration.js.map +1 -0
  22. package/dist/src/algorithms/scope.d.ts +26 -0
  23. package/dist/src/algorithms/scope.d.ts.map +1 -0
  24. package/dist/src/algorithms/scope.js +41 -0
  25. package/dist/src/algorithms/scope.js.map +1 -0
  26. package/dist/src/algorithms/spectral.d.ts +50 -0
  27. package/dist/src/algorithms/spectral.d.ts.map +1 -0
  28. package/dist/src/algorithms/spectral.js +247 -0
  29. package/dist/src/algorithms/spectral.js.map +1 -0
  30. package/dist/src/index.d.ts +4 -0
  31. package/dist/src/index.d.ts.map +1 -1
  32. package/dist/src/index.js +4 -0
  33. package/dist/src/index.js.map +1 -1
  34. package/dist/src/kernel/dispatch.d.ts +4 -1
  35. package/dist/src/kernel/dispatch.d.ts.map +1 -1
  36. package/dist/src/kernel/dispatch.js +12 -5
  37. package/dist/src/kernel/dispatch.js.map +1 -1
  38. package/dist/src/kernels.d.ts +20 -4
  39. package/dist/src/kernels.d.ts.map +1 -1
  40. package/dist/src/kernels.js +172 -2
  41. package/dist/src/kernels.js.map +1 -1
  42. package/dist/src/layouts/seed.d.ts +3 -1
  43. package/dist/src/layouts/seed.d.ts.map +1 -1
  44. package/dist/src/layouts/seed.js +3 -1
  45. package/dist/src/layouts/seed.js.map +1 -1
  46. package/dist/src/memory/residency.d.ts.map +1 -1
  47. package/dist/src/memory/residency.js +164 -11
  48. package/dist/src/memory/residency.js.map +1 -1
  49. package/dist/src/primitives/core-shape.d.ts +41 -0
  50. package/dist/src/primitives/core-shape.d.ts.map +1 -0
  51. package/dist/src/primitives/core-shape.js +89 -0
  52. package/dist/src/primitives/core-shape.js.map +1 -0
  53. package/dist/src/primitives/segmented-reduce.d.ts.map +1 -1
  54. package/dist/src/primitives/segmented-reduce.js +4 -30
  55. package/dist/src/primitives/segmented-reduce.js.map +1 -1
  56. package/dist/src/primitives/spmv.d.ts +56 -0
  57. package/dist/src/primitives/spmv.d.ts.map +1 -0
  58. package/dist/src/primitives/spmv.js +101 -0
  59. package/dist/src/primitives/spmv.js.map +1 -0
  60. package/dist/src/types/accelerator.d.ts +24 -31
  61. package/dist/src/types/accelerator.d.ts.map +1 -1
  62. package/dist/src/types/accelerator.js +5 -4
  63. package/dist/src/types/accelerator.js.map +1 -1
  64. package/dist/src/types/algorithms.d.ts +74 -0
  65. package/dist/src/types/algorithms.d.ts.map +1 -0
  66. package/dist/src/types/algorithms.js +18 -0
  67. package/dist/src/types/algorithms.js.map +1 -0
  68. package/dist/src/types/layout.d.ts +2 -2
  69. package/dist/src/types/layout.d.ts.map +1 -1
  70. package/dist/src/types/layout.js +1 -1
  71. package/dist/src/types/options.d.ts +8 -49
  72. package/dist/src/types/options.d.ts.map +1 -1
  73. package/dist/src/types/options.js +5 -3
  74. package/dist/src/types/options.js.map +1 -1
  75. package/dist/src/wgsl/pr-finalize.wgsl.d.ts +11 -0
  76. package/dist/src/wgsl/pr-finalize.wgsl.d.ts.map +1 -0
  77. package/dist/src/wgsl/pr-finalize.wgsl.js +36 -0
  78. package/dist/src/wgsl/pr-finalize.wgsl.js.map +1 -0
  79. package/dist/src/wgsl/pr-scale.wgsl.d.ts +14 -0
  80. package/dist/src/wgsl/pr-scale.wgsl.d.ts.map +1 -0
  81. package/dist/src/wgsl/pr-scale.wgsl.js +48 -0
  82. package/dist/src/wgsl/pr-scale.wgsl.js.map +1 -0
  83. package/dist/src/wgsl/spmv-pull.wgsl.d.ts +15 -0
  84. package/dist/src/wgsl/spmv-pull.wgsl.d.ts.map +1 -0
  85. package/dist/src/wgsl/spmv-pull.wgsl.js +47 -0
  86. package/dist/src/wgsl/spmv-pull.wgsl.js.map +1 -0
  87. package/dist/src/wgsl/wcc-compress.wgsl.d.ts +9 -0
  88. package/dist/src/wgsl/wcc-compress.wgsl.d.ts.map +1 -0
  89. package/dist/src/wgsl/wcc-compress.wgsl.js +26 -0
  90. package/dist/src/wgsl/wcc-compress.wgsl.js.map +1 -0
  91. package/dist/src/wgsl/wcc-link-edges.wgsl.d.ts +13 -0
  92. package/dist/src/wgsl/wcc-link-edges.wgsl.d.ts.map +1 -0
  93. package/dist/src/wgsl/wcc-link-edges.wgsl.js +46 -0
  94. package/dist/src/wgsl/wcc-link-edges.wgsl.js.map +1 -0
  95. package/dist/src/wgsl/wcc-link-sample.wgsl.d.ts +11 -0
  96. package/dist/src/wgsl/wcc-link-sample.wgsl.d.ts.map +1 -0
  97. package/dist/src/wgsl/wcc-link-sample.wgsl.js +45 -0
  98. package/dist/src/wgsl/wcc-link-sample.wgsl.js.map +1 -0
  99. package/dist/src/wgsl/wcc-sample.wgsl.d.ts +10 -0
  100. package/dist/src/wgsl/wcc-sample.wgsl.d.ts.map +1 -0
  101. package/dist/src/wgsl/wcc-sample.wgsl.js +18 -0
  102. package/dist/src/wgsl/wcc-sample.wgsl.js.map +1 -0
  103. package/dist/tsconfig.build.tsbuildinfo +1 -1
  104. package/dist/webgpu-graph-algorithms.js +1550 -29
  105. package/dist/webgpu-graph-algorithms.js.map +1 -1
  106. package/package.json +5 -4
  107. package/src/accelerator.ts +104 -8
  108. package/src/algorithms/components.ts +348 -0
  109. package/src/algorithms/pagerank.ts +343 -0
  110. package/src/algorithms/power-iteration.ts +278 -0
  111. package/src/algorithms/scope.ts +52 -0
  112. package/src/algorithms/spectral.ts +300 -0
  113. package/src/index.ts +20 -1
  114. package/src/kernel/dispatch.ts +12 -5
  115. package/src/kernels.ts +206 -5
  116. package/src/layouts/seed.ts +3 -1
  117. package/src/memory/residency.ts +200 -11
  118. package/src/primitives/core-shape.ts +103 -0
  119. package/src/primitives/segmented-reduce.ts +4 -36
  120. package/src/primitives/spmv.ts +155 -0
  121. package/src/types/accelerator.ts +40 -32
  122. package/src/types/algorithms.ts +83 -0
  123. package/src/types/layout.ts +2 -2
  124. package/src/types/options.ts +22 -53
  125. package/src/wgsl/pr-finalize.wgsl.ts +36 -0
  126. package/src/wgsl/pr-scale.wgsl.ts +48 -0
  127. package/src/wgsl/spmv-pull.wgsl.ts +47 -0
  128. package/src/wgsl/wcc-compress.wgsl.ts +26 -0
  129. package/src/wgsl/wcc-link-edges.wgsl.ts +46 -0
  130. package/src/wgsl/wcc-link-sample.wgsl.ts +45 -0
  131. package/src/wgsl/wcc-sample.wgsl.ts +18 -0
@@ -0,0 +1,298 @@
1
+ /**
2
+ * PageRank and personalized PageRank on the device (spec 8.2, 3.3): a pull over the reverse adjacency with the
3
+ * out-weight normaliser folded into `xNorm` by `pr-scale`, the dangling mass and the L1 delta folded by
4
+ * `pr-finalize` into the header at `partials[0]`, and `spmv-pull` writing the next iterate. Iterations run in
5
+ * batches of PR_BATCH per submit, ONE readback per batch (the header and the iterate together), and the device
6
+ * records `firstConverged` the first time the delta falls below `tolerance * n`, so the reported `iterations` is the
7
+ * first converged iteration and not the batch boundary (spec 9.7).
8
+ *
9
+ * PLAN DECISION PD-7: the ping-pong is TWO buffers (`rankA`, `rankB`) alternated through two cached bind groups;
10
+ * one buffer of two aliased halves would bind (each kernel sees the halves in one access mode) but saves nothing.
11
+ * PLAN DECISION PD-8: `outWeightSum` is call scratch from the Lease, one `segmentedReduce` pass per call.
12
+ * PLAN DECISION PD-9: `pr-scale` at iteration i reads x(i-1) and x(i-2), so its delta is the error of iteration
13
+ * i - 1 and `pr-finalize` records `P.iteration - 1`; the ping-pong supplies `rankPrev` for free because it is the
14
+ * buffer this iteration overwrites, and `pr-scale` runs before `spmv-pull` in the same pass.
15
+ */
16
+ import { U32_MAX } from "../constants.js";
17
+ import { isWebGpuGraphError, WebGpuGraphError } from "../errors.js";
18
+ import { CommandBatch } from "../kernel/batch.js";
19
+ import { groupsOf, plan1d } from "../kernel/dispatch.js";
20
+ import { kernelSpec, PR_PARAMS, PR_PARTIAL } from "../kernels.js";
21
+ import { coreOfView } from "../primitives/core-shape.js";
22
+ import { prepareSegmentedReduce } from "../primitives/segmented-reduce.js";
23
+ import { prepareSpmvPull } from "../primitives/spmv.js";
24
+ import { algorithmScope } from "./scope.js";
25
+ /** Iterations per submit (spec 8.2: k = 8). */
26
+ const PR_BATCH = 8;
27
+ /** Params slots of one batch: per iteration one PrParams (shared by pr-scale and pr-finalize) and one SpmvParams, plus the normaliser's RangeParams; a smaller ring wraps onto a slot the same batch still reads. */
28
+ const RING_SLOTS = 2 * PR_BATCH + 1;
29
+ /**
30
+ * Validates `options.dest` for a score result of `n` elements.
31
+ * @param dest - the caller's destination array, if any
32
+ * @param n - the node count
33
+ * @param algorithm - the caller's name, for the message
34
+ * @returns the destination as an F32, or null when none was given
35
+ */
36
+ function checkDest(dest, n, algorithm) {
37
+ if (dest === undefined) {
38
+ return null;
39
+ }
40
+ if (dest instanceof Float32Array && dest.length === n && dest.buffer instanceof ArrayBuffer) {
41
+ return dest;
42
+ }
43
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${algorithm}: dest must be a Float32Array of length ${n} over an ArrayBuffer`, {
44
+ argument: "dest",
45
+ value: `${dest.constructor.name}(${dest.length})`,
46
+ expected: `Float32Array(${n}) over an ArrayBuffer`,
47
+ });
48
+ }
49
+ /**
50
+ * The resident core; a windowed plan (`E_TOO_LARGE { path: "windowed", algorithm: null }`, spec 3.8) is re-thrown
51
+ * with the algorithm name (3.12). Transcribed from degree.ts, whose coreOf is module-private.
52
+ * @param ctx - the context
53
+ * @param s - the snapshot
54
+ * @param algorithm - the caller's name
55
+ * @returns the core binding
56
+ */
57
+ function coreOf(ctx, s, algorithm) {
58
+ try {
59
+ return ctx.residency.core(s);
60
+ }
61
+ catch (error) {
62
+ if (isWebGpuGraphError(error) && error.code === "E_TOO_LARGE" && error.details.path === "windowed") {
63
+ throw new WebGpuGraphError("E_TOO_LARGE", `${algorithm}: the arc arrays need a windowed upload, which P1-P3 plan but do not execute`, { ...error.details, algorithm });
64
+ }
65
+ throw error;
66
+ }
67
+ }
68
+ /**
69
+ * Whole-buffer binding of a scratch buffer over its first `size` bytes.
70
+ * @param buffer - the buffer
71
+ * @param size - the bound byte length
72
+ * @returns the binding
73
+ */
74
+ function bindingOf(buffer, size) {
75
+ return { buffer, offset: 0, size, window: null };
76
+ }
77
+ /**
78
+ * The E_ABORTED error of a signal.
79
+ * @param algorithm - the caller's name
80
+ * @param batchId - the last submitted batch, when one exists
81
+ * @returns the error
82
+ */
83
+ function aborted(algorithm, batchId) {
84
+ return new WebGpuGraphError("E_ABORTED", `${algorithm}: the signal was aborted`, batchId === undefined ? {} : { batchId });
85
+ }
86
+ /**
87
+ * The shared driver: `personalization` is the normalised vector of personalizedPageRank or null for the uniform
88
+ * 1 / n of pageRank.
89
+ * @param ctx - the context
90
+ * @param s - the snapshot
91
+ * @param personalization - the normalised personalization (sum 1), or null
92
+ * @param options - the PageRank and run options
93
+ * @param algorithm - the public name, for messages and labels
94
+ * @returns the result
95
+ */
96
+ async function run(ctx, s, personalization, options, algorithm) {
97
+ ctx.assertReady();
98
+ const n = s.nodeCount;
99
+ const alpha = options?.dampingFactor ?? 0.85;
100
+ const maxIterations = options?.maxIterations ?? 100;
101
+ const tolerance = options?.tolerance ?? 1e-6;
102
+ const useWeights = options?.weighted !== false;
103
+ if (!Number.isInteger(maxIterations) || maxIterations < 1) {
104
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${algorithm}: maxIterations must be a positive integer`, {
105
+ argument: "maxIterations",
106
+ value: maxIterations,
107
+ expected: "a positive integer",
108
+ });
109
+ }
110
+ const dest = checkDest(options?.dest, n, algorithm);
111
+ if (options?.signal?.aborted) {
112
+ throw aborted(algorithm);
113
+ }
114
+ if (n === 0) {
115
+ options?.onProgress?.(maxIterations, maxIterations);
116
+ return { scores: dest ?? new Float32Array(0), iterations: 0, converged: true, danglingMass: 0, precision: "f32" };
117
+ }
118
+ const core = coreOf(ctx, s, algorithm);
119
+ if (s.arcCount === 0) {
120
+ // every node is dangling: the whole mass is redistributed by pv each iteration, so pv is the fixed point
121
+ const scores = dest ?? new Float32Array(n);
122
+ if (personalization === null) {
123
+ scores.fill(1 / n);
124
+ }
125
+ else {
126
+ scores.set(personalization);
127
+ }
128
+ options?.onProgress?.(maxIterations, maxIterations);
129
+ return { scores, iterations: 0, converged: true, danglingMass: 1, precision: "f32" };
130
+ }
131
+ const view = ctx.residency.view(s, "reverse");
132
+ const rev = coreOfView(view, view.scalars.arcCount[0]);
133
+ // weighted: false runs the unweighted algorithm on BOTH sides: the normaliser sums 1 per arc and the pull folds 1
134
+ const weights = useWeights ? undefined : null;
135
+ const weightedCore = useWeights ? core : { ...core, weights: null, hasWeights: false };
136
+ const weightedRev = useWeights ? rev : { ...rev, weights: null, hasWeights: false };
137
+ const scope = algorithmScope(ctx, algorithm, RING_SLOTS);
138
+ let uploaded = null;
139
+ try {
140
+ const bytes = 4 * n;
141
+ const rankA = scope.scratch(bytes, "rankA");
142
+ const rankB = scope.scratch(bytes, "rankB");
143
+ const xNorm = scope.scratch(bytes, "xNorm");
144
+ const outWeightSum = scope.scratch(bytes, "outWeightSum");
145
+ const scalePlan = plan1d(n, ctx.workgroupSize, ctx.caps);
146
+ const groups = groupsOf(scalePlan);
147
+ const partialsBytes = PR_PARTIAL.byteLength * (1 + groups);
148
+ const partials = scope.scratch(partialsBytes, "partials");
149
+ if (personalization !== null) {
150
+ uploaded = ctx.residency.array(personalization, `${algorithm}/personalization`);
151
+ }
152
+ await ctx.allocator.check();
153
+ const normaliser = await prepareSegmentedReduce(scope, weightedCore, {
154
+ op: "sum",
155
+ valueSnippet: "v = weight;",
156
+ tiers: null,
157
+ });
158
+ const pull = await prepareSpmvPull(scope, weightedRev, {
159
+ personalization: personalization !== null,
160
+ dangling: true,
161
+ weights,
162
+ tiers: null,
163
+ });
164
+ const scale = await ctx.pipelines.kernel(kernelSpec("pr-scale", { NORM_MODE: 0 }));
165
+ const finalize = await ctx.pipelines.kernel(kernelSpec("pr-finalize", { NORM_MODE: 0 }));
166
+ const finalizePlan = plan1d(1, ctx.workgroupSize, ctx.caps);
167
+ const { queue } = ctx.device;
168
+ queue.writeBuffer(rankA, 0, new Float32Array(n).fill(1 / n));
169
+ queue.writeBuffer(rankB, 0, new Float32Array(n));
170
+ const header = new ArrayBuffer(PR_PARTIAL.byteLength);
171
+ PR_PARTIAL.write(new DataView(header), { firstConverged: U32_MAX, iteration: 0 });
172
+ queue.writeBuffer(partials, 0, header);
173
+ const rank = [bindingOf(rankA, bytes), bindingOf(rankB, bytes)];
174
+ const xNormBinding = bindingOf(xNorm, bytes);
175
+ const outWeightSumBinding = bindingOf(outWeightSum, bytes);
176
+ const partialsBinding = bindingOf(partials, partialsBytes);
177
+ const coefficients = { alpha, beta: 1 - alpha, uniformP: 1 / n };
178
+ let cur = 0;
179
+ let iterationsRun = 0;
180
+ for (;;) {
181
+ const k = Math.min(PR_BATCH, maxIterations - iterationsRun);
182
+ const batch = new CommandBatch(ctx, algorithm);
183
+ const pass = batch.pass("iterations");
184
+ if (iterationsRun === 0) {
185
+ normaliser.record(pass, weightedCore, outWeightSumBinding);
186
+ }
187
+ for (let i = 0; i < k; i++) {
188
+ const params = scope.params(PR_PARAMS, {
189
+ n,
190
+ groups,
191
+ iteration: iterationsRun + i + 1,
192
+ trackConvergence: 1,
193
+ convergeThreshold: tolerance * n,
194
+ });
195
+ const other = 1 - cur;
196
+ const scaleBound = scale.bind({
197
+ rankIn: rank[cur],
198
+ rankPrev: rank[other],
199
+ outWeightSum: outWeightSumBinding,
200
+ xNorm: xNormBinding,
201
+ partials: partialsBinding,
202
+ P: params.binding,
203
+ });
204
+ scale.dispatch(pass, scaleBound, scalePlan, [params.offset]);
205
+ const finalizeBound = finalize.bind({ partials: partialsBinding, P: params.binding });
206
+ finalize.dispatch(pass, finalizeBound, finalizePlan, [params.offset]);
207
+ pull.record(pass, weightedRev, {
208
+ xNorm: xNormBinding,
209
+ rankOut: rank[other],
210
+ personalization: uploaded?.binding ?? null,
211
+ partials: partialsBinding,
212
+ }, coefficients);
213
+ cur = other;
214
+ }
215
+ batch.endPass();
216
+ const headerRequest = batch.readback(partials, 0, PR_PARTIAL.byteLength);
217
+ const scoresRequest = batch.readback(rank[cur].buffer, 0, bytes);
218
+ scope.flush();
219
+ const submitted = batch.submit();
220
+ const back = await submitted.readback;
221
+ iterationsRun += k;
222
+ ctx.assertReady();
223
+ if (options?.signal?.aborted) {
224
+ throw aborted(algorithm, submitted.id);
225
+ }
226
+ options?.onProgress?.(iterationsRun, maxIterations);
227
+ const folded = PR_PARTIAL.read(new DataView(back), headerRequest.offset);
228
+ const firstConverged = folded.firstConverged;
229
+ const converged = firstConverged !== U32_MAX;
230
+ if (converged || iterationsRun >= maxIterations) {
231
+ const scores = dest ?? new Float32Array(n);
232
+ scores.set(new Float32Array(back, scoresRequest.offset, n));
233
+ if (converged && iterationsRun < maxIterations) {
234
+ options?.onProgress?.(maxIterations, maxIterations);
235
+ }
236
+ return {
237
+ scores,
238
+ iterations: converged ? firstConverged : iterationsRun,
239
+ converged,
240
+ danglingMass: folded.danglingMass,
241
+ precision: "f32",
242
+ };
243
+ }
244
+ }
245
+ }
246
+ finally {
247
+ uploaded?.destroy();
248
+ scope.dispose();
249
+ }
250
+ }
251
+ /**
252
+ * PageRank on the device (spec 3.3, 8.2): NetworkX semantics, f32 scores, `iterations` the first converged
253
+ * iteration (spec 9.7).
254
+ * @param ctx - the context whose device runs the kernels
255
+ * @param s - the snapshot (uploaded through ctx.residency, or found there)
256
+ * @param options - dampingFactor 0.85 / maxIterations 100 / tolerance 1e-6 / weighted true, plus dest / signal / onProgress
257
+ * @returns the scores, iterations, converged, danglingMass and precision
258
+ */
259
+ export function pageRank(ctx, s, options) {
260
+ return run(ctx, s, null, options, "pageRank");
261
+ }
262
+ /**
263
+ * Personalized PageRank on the device (spec 3.3, 8.2): the personalization vector replaces the uniform 1 / n in
264
+ * the teleport and the dangling redistribution; it is normalised to sum 1 on the host.
265
+ * @param ctx - the context whose device runs the kernels
266
+ * @param s - the snapshot (uploaded through ctx.residency, or found there)
267
+ * @param personalization - one finite non-negative mass per node, not all zero
268
+ * @param options - dampingFactor 0.85 / maxIterations 100 / tolerance 1e-6 / weighted true, plus dest / signal / onProgress
269
+ * @returns the scores, iterations, converged, danglingMass and precision
270
+ */
271
+ export async function personalizedPageRank(ctx, s, personalization, options) {
272
+ const n = s.nodeCount;
273
+ const invalid = (value, expected) => new WebGpuGraphError("E_INVALID_ARGUMENT", `personalizedPageRank: personalization must be ${expected}`, {
274
+ argument: "personalization",
275
+ value,
276
+ expected,
277
+ });
278
+ if (!(personalization instanceof Float32Array) || personalization.length !== n) {
279
+ throw invalid(`${personalization.constructor.name}(${personalization.length})`, `a Float32Array of length ${n}`);
280
+ }
281
+ let total = 0;
282
+ for (let v = 0; v < n; v++) {
283
+ const mass = personalization[v];
284
+ if (!Number.isFinite(mass) || mass < 0) {
285
+ throw invalid(mass, "finite and non-negative in every entry");
286
+ }
287
+ total += mass;
288
+ }
289
+ if (n > 0 && !(total > 0)) {
290
+ throw invalid(total, "a vector whose entries sum to a positive number");
291
+ }
292
+ const normalised = new Float32Array(n);
293
+ for (let v = 0; v < n; v++) {
294
+ normalised[v] = personalization[v] / total;
295
+ }
296
+ return run(ctx, s, normalised, options, "personalizedPageRank");
297
+ }
298
+ //# sourceMappingURL=pagerank.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagerank.js","sourceRoot":"","sources":["../../../src/algorithms/pagerank.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * The power-iteration driver HITS, eigenvector centrality and Katz centrality share (spec 8.2 lines 2603-2605; M8b
3
+ * plan PD-10): per iteration `pr-scale` at NORM_MODE 1 | 2 | 4 folds the norm term (and the L1 delta) into the
4
+ * per-workgroup partials, `pr-finalize` folds them into the header at `partials[0]` (the square root for L2) and
5
+ * records `firstConverged`, `pr-scale` at NORM_MODE 3 writes `xNorm[u] = x[u] / partials[0].norm` (skipped at
6
+ * mode 4, the identity, where the first scale pass already wrote `xNorm[u] = x[u]`), and `spmv-pull` writes the
7
+ * next iterate. Four dispatches (three for Katz), all on the device, NO readback inside the batch: the scalar
8
+ * normaliser the host cannot supply without a readback is exactly what stays on the device, so these three batch
9
+ * eight iterations per submit like PageRank does.
10
+ *
11
+ * The ping-pong is TWO buffers alternated through two cached bind groups (PD-7 / DEP-M8B-G), and `rankPrev` is the
12
+ * buffer this iteration overwrites: it still holds x(i-2) when `pr-scale` reads it, because the scale runs before
13
+ * the pull in the same pass (PD-9). With an `alternate` adjacency (HITS, spec 8.2: "alternates two pulls") the
14
+ * iterations pull over `adjacency` and `alternate` in turn, and the ring is THREE buffers so the buffer being
15
+ * overwritten holds x(i-3) -- the previous iterate of the same kind -- and the delta stays meaningful. The batch
16
+ * loop duplicates src/algorithms/pagerank.ts, which its own task owns.
17
+ */
18
+ import { type F32, type GraphSnapshot } from "@graphty/graph-format";
19
+ import { type GpuContext } from "../context.js";
20
+ import { WebGpuGraphError } from "../errors.js";
21
+ import { type CoreBinding } from "../memory/residency.js";
22
+ import { type Binding } from "../types/memory.js";
23
+ /**
24
+ * What one power iteration run needs. `adjacency` is the CoreBinding the pull walks -- the forward core for hubs
25
+ * and eigenvector, coreOfView(view(s, "reverse")) for authorities and Katz (spec 8.2 lines 2603-2606). Exported
26
+ * for runPowerIteration's signature, not imported by name.
27
+ * @public
28
+ */
29
+ export interface PowerIterationConfig {
30
+ /**
31
+ * 1 = L1 (sum) normalise, 2 = L2 normalise, 4 = identity (Katz: no normaliser). Never 0 or 3 here: 0 is
32
+ * PageRank's per-node divisor and 3 is the internal scale pass this driver issues itself.
33
+ */
34
+ readonly normMode: 1 | 2 | 4;
35
+ readonly adjacency: CoreBinding;
36
+ /**
37
+ * Null: every iteration pulls over `adjacency`. Non-null: the odd iterations (1, 3, ...) pull over `adjacency`
38
+ * and the even ones over `alternate`, so x(i) = A_alt * norm(A * norm(x(i-2))) -- one interleaved chain of HITS,
39
+ * whose hubs and authorities are the last iterates of the two chains (forward-first and reverse-first). The
40
+ * ring then has three buffers and `weights` must be null or undefined (each core's own weights).
41
+ */
42
+ readonly alternate: CoreBinding | null;
43
+ readonly alpha: number;
44
+ readonly beta: number;
45
+ readonly uniformP: number;
46
+ readonly maxIterations: number;
47
+ readonly tolerance: number;
48
+ /** undefined takes the adjacency's weights, null runs UNWEIGHTED on a weighted snapshot (T4 Step 4). */
49
+ readonly weights: Binding | null | undefined;
50
+ readonly label: string;
51
+ readonly signal: AbortSignal | undefined;
52
+ readonly onProgress: ((done: number, total: number) => void) | undefined;
53
+ }
54
+ /** The iterate, the device-recorded first converged iteration, and the number of iterations actually run. */
55
+ export interface PowerIterationRun {
56
+ readonly scores: F32;
57
+ /** x(m - 1) on an alternating run: the chain's last iterate of the OTHER kind (hub or authority); null otherwise. */
58
+ readonly previous: F32 | null;
59
+ readonly iterations: number;
60
+ readonly converged: boolean;
61
+ readonly iterationsRun: number;
62
+ }
63
+ /**
64
+ * Validates `options.dest` for a score result of `n` elements.
65
+ * @param dest - the caller's destination array, if any
66
+ * @param n - the node count
67
+ * @param algorithm - the caller's name, for the message
68
+ * @returns the destination as an F32, or null when none was given
69
+ */
70
+ export declare function checkDest(dest: Float32Array | Uint32Array | undefined, n: number, algorithm: string): F32 | null;
71
+ /**
72
+ * The resident core; a windowed plan (`E_TOO_LARGE { path: "windowed", algorithm: null }`, spec 3.8) is re-thrown
73
+ * with the algorithm name (3.12). Transcribed from degree.ts, whose coreOf is module-private.
74
+ * @param ctx - the context
75
+ * @param s - the snapshot
76
+ * @param algorithm - the caller's name
77
+ * @returns the core binding
78
+ */
79
+ export declare function coreOf(ctx: GpuContext, s: GraphSnapshot, algorithm: string): CoreBinding;
80
+ /**
81
+ * The reverse adjacency as the CoreBinding the pull walks (the forward buffers on an undirected snapshot, PD-13).
82
+ * @param ctx - the context
83
+ * @param s - the snapshot (n > 0)
84
+ * @returns the reverse core
85
+ */
86
+ export declare function reverseOf(ctx: GpuContext, s: GraphSnapshot): CoreBinding;
87
+ /**
88
+ * The E_ABORTED error of a signal.
89
+ * @param algorithm - the caller's name
90
+ * @param batchId - the last submitted batch, when one exists
91
+ * @returns the error
92
+ */
93
+ export declare function aborted(algorithm: string, batchId?: number): WebGpuGraphError;
94
+ /**
95
+ * Runs the power iteration of `config` over `n` nodes from x(0) = 1 / n, in batches of eight iterations with ONE
96
+ * readback per batch (the header and the iterate together), stopping at the first batch whose header records a
97
+ * converged iteration or at `maxIterations`. The returned iterate is RAW: the last `spmv-pull` output, which the
98
+ * caller normalises once on the host. The iterate travels with the header in EVERY batch, not once after the loop:
99
+ * whether a batch terminates the run is known only from its header, and a second readback for the iterate would
100
+ * be a second mapAsync (the plan's case 8 counts exactly one). The cost is 4n bytes (8n on an alternating run) of
101
+ * staging per batch of 8 that the loop then discards when it continues -- 40 MB per 8 iterations at 10M nodes;
102
+ * pagerank.ts pays the same.
103
+ * @param ctx - the context
104
+ * @param n - the node count (> 0)
105
+ * @param config - the recurrence, the adjacency and the run options
106
+ * @returns the raw iterate, the first converged iteration, whether it converged and the iterations actually run
107
+ */
108
+ export declare function runPowerIteration(ctx: GpuContext, n: number, config: PowerIterationConfig): Promise<PowerIterationRun>;
109
+ //# sourceMappingURL=power-iteration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"power-iteration.d.ts","sourceRoot":"","sources":["../../../src/algorithms/power-iteration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIpE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAQlD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wGAAwG;IACxG,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC5E;AAED,6GAA6G;AAC7G,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,qHAAqH;IACrH,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAgBhH;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,CAaxF;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,aAAa,GAAG,WAAW,CAGxE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAM7E;AAYD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACnC,GAAG,EAAE,UAAU,EACf,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,oBAAoB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,CAiG5B"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * The power-iteration driver HITS, eigenvector centrality and Katz centrality share (spec 8.2 lines 2603-2605; M8b
3
+ * plan PD-10): per iteration `pr-scale` at NORM_MODE 1 | 2 | 4 folds the norm term (and the L1 delta) into the
4
+ * per-workgroup partials, `pr-finalize` folds them into the header at `partials[0]` (the square root for L2) and
5
+ * records `firstConverged`, `pr-scale` at NORM_MODE 3 writes `xNorm[u] = x[u] / partials[0].norm` (skipped at
6
+ * mode 4, the identity, where the first scale pass already wrote `xNorm[u] = x[u]`), and `spmv-pull` writes the
7
+ * next iterate. Four dispatches (three for Katz), all on the device, NO readback inside the batch: the scalar
8
+ * normaliser the host cannot supply without a readback is exactly what stays on the device, so these three batch
9
+ * eight iterations per submit like PageRank does.
10
+ *
11
+ * The ping-pong is TWO buffers alternated through two cached bind groups (PD-7 / DEP-M8B-G), and `rankPrev` is the
12
+ * buffer this iteration overwrites: it still holds x(i-2) when `pr-scale` reads it, because the scale runs before
13
+ * the pull in the same pass (PD-9). With an `alternate` adjacency (HITS, spec 8.2: "alternates two pulls") the
14
+ * iterations pull over `adjacency` and `alternate` in turn, and the ring is THREE buffers so the buffer being
15
+ * overwritten holds x(i-3) -- the previous iterate of the same kind -- and the delta stays meaningful. The batch
16
+ * loop duplicates src/algorithms/pagerank.ts, which its own task owns.
17
+ */
18
+ import { U32_MAX } from "../constants.js";
19
+ import { isWebGpuGraphError, WebGpuGraphError } from "../errors.js";
20
+ import { CommandBatch } from "../kernel/batch.js";
21
+ import { groupsOf, plan1d } from "../kernel/dispatch.js";
22
+ import { kernelSpec, PR_PARAMS, PR_PARTIAL } from "../kernels.js";
23
+ import { coreOfView } from "../primitives/core-shape.js";
24
+ import { prepareSpmvPull } from "../primitives/spmv.js";
25
+ import { algorithmScope } from "./scope.js";
26
+ /** Iterations per submit (spec 8.2: k = 8). */
27
+ const BATCH = 8;
28
+ /** Params slots of one batch: four blocks per iteration times the batch, plus a margin (the plan's `4 * 8 + 8`). */
29
+ const RING_SLOTS = 4 * BATCH + 8;
30
+ /**
31
+ * Validates `options.dest` for a score result of `n` elements.
32
+ * @param dest - the caller's destination array, if any
33
+ * @param n - the node count
34
+ * @param algorithm - the caller's name, for the message
35
+ * @returns the destination as an F32, or null when none was given
36
+ */
37
+ export function checkDest(dest, n, algorithm) {
38
+ if (dest === undefined) {
39
+ return null;
40
+ }
41
+ if (dest instanceof Float32Array && dest.length === n && dest.buffer instanceof ArrayBuffer) {
42
+ return dest;
43
+ }
44
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${algorithm}: dest must be a Float32Array of length ${n} over an ArrayBuffer`, {
45
+ argument: "dest",
46
+ value: `${dest.constructor.name}(${dest.length})`,
47
+ expected: `Float32Array(${n}) over an ArrayBuffer`,
48
+ });
49
+ }
50
+ /**
51
+ * The resident core; a windowed plan (`E_TOO_LARGE { path: "windowed", algorithm: null }`, spec 3.8) is re-thrown
52
+ * with the algorithm name (3.12). Transcribed from degree.ts, whose coreOf is module-private.
53
+ * @param ctx - the context
54
+ * @param s - the snapshot
55
+ * @param algorithm - the caller's name
56
+ * @returns the core binding
57
+ */
58
+ export function coreOf(ctx, s, algorithm) {
59
+ try {
60
+ return ctx.residency.core(s);
61
+ }
62
+ catch (error) {
63
+ if (isWebGpuGraphError(error) && error.code === "E_TOO_LARGE" && error.details.path === "windowed") {
64
+ throw new WebGpuGraphError("E_TOO_LARGE", `${algorithm}: the arc arrays need a windowed upload, which P1-P3 plan but do not execute`, { ...error.details, algorithm });
65
+ }
66
+ throw error;
67
+ }
68
+ }
69
+ /**
70
+ * The reverse adjacency as the CoreBinding the pull walks (the forward buffers on an undirected snapshot, PD-13).
71
+ * @param ctx - the context
72
+ * @param s - the snapshot (n > 0)
73
+ * @returns the reverse core
74
+ */
75
+ export function reverseOf(ctx, s) {
76
+ const view = ctx.residency.view(s, "reverse");
77
+ return coreOfView(view, view.scalars.arcCount[0]);
78
+ }
79
+ /**
80
+ * The E_ABORTED error of a signal.
81
+ * @param algorithm - the caller's name
82
+ * @param batchId - the last submitted batch, when one exists
83
+ * @returns the error
84
+ */
85
+ export function aborted(algorithm, batchId) {
86
+ return new WebGpuGraphError("E_ABORTED", `${algorithm}: the signal was aborted`, batchId === undefined ? {} : { batchId });
87
+ }
88
+ /**
89
+ * Whole-buffer binding of a scratch buffer over its first `size` bytes.
90
+ * @param buffer - the buffer
91
+ * @param size - the bound byte length
92
+ * @returns the binding
93
+ */
94
+ function whole(buffer, size) {
95
+ return { buffer, offset: 0, size, window: null };
96
+ }
97
+ /**
98
+ * Runs the power iteration of `config` over `n` nodes from x(0) = 1 / n, in batches of eight iterations with ONE
99
+ * readback per batch (the header and the iterate together), stopping at the first batch whose header records a
100
+ * converged iteration or at `maxIterations`. The returned iterate is RAW: the last `spmv-pull` output, which the
101
+ * caller normalises once on the host. The iterate travels with the header in EVERY batch, not once after the loop:
102
+ * whether a batch terminates the run is known only from its header, and a second readback for the iterate would
103
+ * be a second mapAsync (the plan's case 8 counts exactly one). The cost is 4n bytes (8n on an alternating run) of
104
+ * staging per batch of 8 that the loop then discards when it continues -- 40 MB per 8 iterations at 10M nodes;
105
+ * pagerank.ts pays the same.
106
+ * @param ctx - the context
107
+ * @param n - the node count (> 0)
108
+ * @param config - the recurrence, the adjacency and the run options
109
+ * @returns the raw iterate, the first converged iteration, whether it converged and the iterations actually run
110
+ */
111
+ export async function runPowerIteration(ctx, n, config) {
112
+ const scope = algorithmScope(ctx, config.label, RING_SLOTS);
113
+ try {
114
+ const bytes = 4 * n;
115
+ // x(i) lives in ring[i % ring.length]: two buffers for one pull per iteration, three for the alternating pair
116
+ const ring = (config.alternate === null ? ["rankA", "rankB"] : ["rankA", "rankB", "rankC"]).map((label) => whole(scope.scratch(bytes, label), bytes));
117
+ const xNorm = whole(scope.scratch(bytes, "xNorm"), bytes);
118
+ const scalePlan = plan1d(n, ctx.workgroupSize, ctx.caps);
119
+ const groups = groupsOf(scalePlan);
120
+ const partialsBytes = PR_PARTIAL.byteLength * (1 + groups);
121
+ const partialsBuffer = scope.scratch(partialsBytes, "partials");
122
+ const partials = whole(partialsBuffer, partialsBytes);
123
+ await ctx.allocator.check();
124
+ const pullOptions = { personalization: false, dangling: false, weights: config.weights, tiers: null };
125
+ const pulls = [{ core: config.adjacency, pull: await prepareSpmvPull(scope, config.adjacency, pullOptions) }];
126
+ if (config.alternate !== null) {
127
+ pulls.push({ core: config.alternate, pull: await prepareSpmvPull(scope, config.alternate, pullOptions) });
128
+ }
129
+ const scaleNorm = await ctx.pipelines.kernel(kernelSpec("pr-scale", { NORM_MODE: config.normMode }));
130
+ const scaleApply = config.normMode === 4 ? null : await ctx.pipelines.kernel(kernelSpec("pr-scale", { NORM_MODE: 3 }));
131
+ const finalize = await ctx.pipelines.kernel(kernelSpec("pr-finalize", { NORM_MODE: config.normMode }));
132
+ const finalizePlan = plan1d(1, ctx.workgroupSize, ctx.caps);
133
+ const { queue } = ctx.device;
134
+ queue.writeBuffer(ring[0].buffer, 0, new Float32Array(n).fill(1 / n));
135
+ for (const slot of ring.slice(1)) {
136
+ queue.writeBuffer(slot.buffer, 0, new Float32Array(n));
137
+ }
138
+ const header = new ArrayBuffer(PR_PARTIAL.byteLength);
139
+ PR_PARTIAL.write(new DataView(header), { firstConverged: U32_MAX, iteration: 0 });
140
+ queue.writeBuffer(partialsBuffer, 0, header);
141
+ const coefficients = { alpha: config.alpha, beta: config.beta, uniformP: config.uniformP };
142
+ let iterationsRun = 0;
143
+ for (;;) {
144
+ const k = Math.min(BATCH, config.maxIterations - iterationsRun);
145
+ const batch = new CommandBatch(ctx, config.label);
146
+ const pass = batch.pass("iterations");
147
+ for (let i = 0; i < k; i++) {
148
+ const iteration = iterationsRun + i + 1;
149
+ const params = scope.params(PR_PARAMS, {
150
+ n,
151
+ groups,
152
+ iteration,
153
+ trackConvergence: 1,
154
+ convergeThreshold: config.tolerance * n,
155
+ });
156
+ const rankIn = ring[(iteration - 1) % ring.length];
157
+ // the slot the pull overwrites still holds x(iteration - ring.length): that is rankPrev (PD-9)
158
+ const rankOut = ring[iteration % ring.length];
159
+ const { core, pull } = pulls[(iteration - 1) % pulls.length];
160
+ // outWeightSum takes rankIn as its dummy: storage-ro, read only under NORM_MODE 0, never compiled here
161
+ const scaleBindings = { rankIn, rankPrev: rankOut, outWeightSum: rankIn, xNorm, partials, P: params.binding };
162
+ scaleNorm.dispatch(pass, scaleNorm.bind(scaleBindings), scalePlan, [params.offset]);
163
+ finalize.dispatch(pass, finalize.bind({ partials, P: params.binding }), finalizePlan, [params.offset]);
164
+ if (scaleApply !== null) {
165
+ scaleApply.dispatch(pass, scaleApply.bind(scaleBindings), scalePlan, [params.offset]);
166
+ }
167
+ pull.record(pass, core, { xNorm, rankOut, personalization: null, partials }, coefficients);
168
+ }
169
+ batch.endPass();
170
+ const headerRequest = batch.readback(partialsBuffer, 0, PR_PARTIAL.byteLength);
171
+ const scoresRequest = batch.readback(ring[(iterationsRun + k) % ring.length].buffer, 0, bytes);
172
+ // x(m - 1) on an alternating run: the other kind, still intact in the third ring slot
173
+ const previousRequest = config.alternate === null
174
+ ? null
175
+ : batch.readback(ring[(iterationsRun + k - 1) % ring.length].buffer, 0, bytes);
176
+ scope.flush();
177
+ const submitted = batch.submit();
178
+ const back = await submitted.readback; // the ONE mapAsync of the batch (G7 item 5)
179
+ iterationsRun += k;
180
+ ctx.assertReady();
181
+ if (config.signal?.aborted === true) {
182
+ throw aborted(config.label, submitted.id);
183
+ }
184
+ config.onProgress?.(iterationsRun, config.maxIterations);
185
+ const folded = PR_PARTIAL.read(new DataView(back), headerRequest.offset);
186
+ const firstConverged = folded.firstConverged;
187
+ const converged = firstConverged !== U32_MAX;
188
+ if (converged || iterationsRun >= config.maxIterations) {
189
+ if (converged && iterationsRun < config.maxIterations) {
190
+ config.onProgress?.(config.maxIterations, config.maxIterations);
191
+ }
192
+ return {
193
+ scores: new Float32Array(back, scoresRequest.offset, n).slice(),
194
+ previous: previousRequest === null ? null : new Float32Array(back, previousRequest.offset, n).slice(),
195
+ iterations: converged ? firstConverged : iterationsRun,
196
+ converged,
197
+ iterationsRun,
198
+ };
199
+ }
200
+ }
201
+ }
202
+ finally {
203
+ scope.dispose();
204
+ }
205
+ }
206
+ //# sourceMappingURL=power-iteration.js.map