@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.
- package/README.md +50 -39
- package/dist/browser.js +1 -1
- package/dist/chunks/{context-E6iKaeuJ.js → context-CRbw2Wyo.js} +178 -19
- package/dist/chunks/{context-E6iKaeuJ.js.map → context-CRbw2Wyo.js.map} +1 -1
- package/dist/node.js +1 -1
- package/dist/src/accelerator.d.ts +12 -7
- package/dist/src/accelerator.d.ts.map +1 -1
- package/dist/src/accelerator.js +88 -7
- package/dist/src/accelerator.js.map +1 -1
- package/dist/src/algorithms/components.d.ts +30 -0
- package/dist/src/algorithms/components.d.ts.map +1 -0
- package/dist/src/algorithms/components.js +300 -0
- package/dist/src/algorithms/components.js.map +1 -0
- package/dist/src/algorithms/pagerank.d.ts +39 -0
- package/dist/src/algorithms/pagerank.d.ts.map +1 -0
- package/dist/src/algorithms/pagerank.js +298 -0
- package/dist/src/algorithms/pagerank.js.map +1 -0
- package/dist/src/algorithms/power-iteration.d.ts +109 -0
- package/dist/src/algorithms/power-iteration.d.ts.map +1 -0
- package/dist/src/algorithms/power-iteration.js +206 -0
- package/dist/src/algorithms/power-iteration.js.map +1 -0
- package/dist/src/algorithms/scope.d.ts +26 -0
- package/dist/src/algorithms/scope.d.ts.map +1 -0
- package/dist/src/algorithms/scope.js +41 -0
- package/dist/src/algorithms/scope.js.map +1 -0
- package/dist/src/algorithms/spectral.d.ts +50 -0
- package/dist/src/algorithms/spectral.d.ts.map +1 -0
- package/dist/src/algorithms/spectral.js +247 -0
- package/dist/src/algorithms/spectral.js.map +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernel/dispatch.d.ts +4 -1
- package/dist/src/kernel/dispatch.d.ts.map +1 -1
- package/dist/src/kernel/dispatch.js +12 -5
- package/dist/src/kernel/dispatch.js.map +1 -1
- package/dist/src/kernels.d.ts +20 -4
- package/dist/src/kernels.d.ts.map +1 -1
- package/dist/src/kernels.js +172 -2
- package/dist/src/kernels.js.map +1 -1
- package/dist/src/layouts/seed.d.ts +3 -1
- package/dist/src/layouts/seed.d.ts.map +1 -1
- package/dist/src/layouts/seed.js +3 -1
- package/dist/src/layouts/seed.js.map +1 -1
- package/dist/src/memory/residency.d.ts.map +1 -1
- package/dist/src/memory/residency.js +164 -11
- package/dist/src/memory/residency.js.map +1 -1
- package/dist/src/primitives/core-shape.d.ts +41 -0
- package/dist/src/primitives/core-shape.d.ts.map +1 -0
- package/dist/src/primitives/core-shape.js +89 -0
- package/dist/src/primitives/core-shape.js.map +1 -0
- package/dist/src/primitives/segmented-reduce.d.ts.map +1 -1
- package/dist/src/primitives/segmented-reduce.js +4 -30
- package/dist/src/primitives/segmented-reduce.js.map +1 -1
- package/dist/src/primitives/spmv.d.ts +56 -0
- package/dist/src/primitives/spmv.d.ts.map +1 -0
- package/dist/src/primitives/spmv.js +101 -0
- package/dist/src/primitives/spmv.js.map +1 -0
- package/dist/src/types/accelerator.d.ts +24 -31
- package/dist/src/types/accelerator.d.ts.map +1 -1
- package/dist/src/types/accelerator.js +5 -4
- package/dist/src/types/accelerator.js.map +1 -1
- package/dist/src/types/algorithms.d.ts +74 -0
- package/dist/src/types/algorithms.d.ts.map +1 -0
- package/dist/src/types/algorithms.js +18 -0
- package/dist/src/types/algorithms.js.map +1 -0
- package/dist/src/types/layout.d.ts +2 -2
- package/dist/src/types/layout.d.ts.map +1 -1
- package/dist/src/types/layout.js +1 -1
- package/dist/src/types/options.d.ts +8 -49
- package/dist/src/types/options.d.ts.map +1 -1
- package/dist/src/types/options.js +5 -3
- package/dist/src/types/options.js.map +1 -1
- package/dist/src/wgsl/pr-finalize.wgsl.d.ts +11 -0
- package/dist/src/wgsl/pr-finalize.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/pr-finalize.wgsl.js +36 -0
- package/dist/src/wgsl/pr-finalize.wgsl.js.map +1 -0
- package/dist/src/wgsl/pr-scale.wgsl.d.ts +14 -0
- package/dist/src/wgsl/pr-scale.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/pr-scale.wgsl.js +48 -0
- package/dist/src/wgsl/pr-scale.wgsl.js.map +1 -0
- package/dist/src/wgsl/spmv-pull.wgsl.d.ts +15 -0
- package/dist/src/wgsl/spmv-pull.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/spmv-pull.wgsl.js +47 -0
- package/dist/src/wgsl/spmv-pull.wgsl.js.map +1 -0
- package/dist/src/wgsl/wcc-compress.wgsl.d.ts +9 -0
- package/dist/src/wgsl/wcc-compress.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/wcc-compress.wgsl.js +26 -0
- package/dist/src/wgsl/wcc-compress.wgsl.js.map +1 -0
- package/dist/src/wgsl/wcc-link-edges.wgsl.d.ts +13 -0
- package/dist/src/wgsl/wcc-link-edges.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/wcc-link-edges.wgsl.js +46 -0
- package/dist/src/wgsl/wcc-link-edges.wgsl.js.map +1 -0
- package/dist/src/wgsl/wcc-link-sample.wgsl.d.ts +11 -0
- package/dist/src/wgsl/wcc-link-sample.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/wcc-link-sample.wgsl.js +45 -0
- package/dist/src/wgsl/wcc-link-sample.wgsl.js.map +1 -0
- package/dist/src/wgsl/wcc-sample.wgsl.d.ts +10 -0
- package/dist/src/wgsl/wcc-sample.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/wcc-sample.wgsl.js +18 -0
- package/dist/src/wgsl/wcc-sample.wgsl.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/webgpu-graph-algorithms.js +1550 -29
- package/dist/webgpu-graph-algorithms.js.map +1 -1
- package/package.json +5 -4
- package/src/accelerator.ts +104 -8
- package/src/algorithms/components.ts +348 -0
- package/src/algorithms/pagerank.ts +343 -0
- package/src/algorithms/power-iteration.ts +278 -0
- package/src/algorithms/scope.ts +52 -0
- package/src/algorithms/spectral.ts +300 -0
- package/src/index.ts +20 -1
- package/src/kernel/dispatch.ts +12 -5
- package/src/kernels.ts +206 -5
- package/src/layouts/seed.ts +3 -1
- package/src/memory/residency.ts +200 -11
- package/src/primitives/core-shape.ts +103 -0
- package/src/primitives/segmented-reduce.ts +4 -36
- package/src/primitives/spmv.ts +155 -0
- package/src/types/accelerator.ts +40 -32
- package/src/types/algorithms.ts +83 -0
- package/src/types/layout.ts +2 -2
- package/src/types/options.ts +22 -53
- package/src/wgsl/pr-finalize.wgsl.ts +36 -0
- package/src/wgsl/pr-scale.wgsl.ts +48 -0
- package/src/wgsl/spmv-pull.wgsl.ts +47 -0
- package/src/wgsl/wcc-compress.wgsl.ts +26 -0
- package/src/wgsl/wcc-link-edges.wgsl.ts +46 -0
- package/src/wgsl/wcc-link-sample.wgsl.ts +45 -0
- package/src/wgsl/wcc-sample.wgsl.ts +18 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* The layout half of spec 9.3 and the @graphty/algorithms AlgorithmAccelerator mirror (spec 9.2), plus the
|
|
3
|
+
* package's own accelerator surface (spec 3.3). D27's two halves are now on different footings: at W1b the LAYOUT
|
|
4
|
+
* mirrors became `import type` of the real `@graphty/layout` interfaces, re-exported here so this package's public
|
|
5
|
+
* surface is unchanged; the ALGORITHMS mirrors stay structural until A2/M8a gives them something real to point at.
|
|
6
|
+
* test/types/conformance.test-d.ts is the cross-compile that holds the layout half honest. Types only.
|
|
6
7
|
*/
|
|
7
8
|
export {};
|
|
8
9
|
//# sourceMappingURL=accelerator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accelerator.js","sourceRoot":"","sources":["../../../src/types/accelerator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"accelerator.js","sourceRoot":"","sources":["../../../src/types/accelerator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The result and option records of the P7 algorithms (spec 3.3 lines 815-828, 9.7). The `Gpu*Result` shapes are the
|
|
3
|
+
* design's verbatim; the option records are this package's own, spelled MEMBER FOR MEMBER as the CPU seam spells
|
|
4
|
+
* them so one object literal satisfies both sides (the D27 mirror rule src/types/options.ts followed for the
|
|
5
|
+
* layout options until W1b, when those became `import type` re-exports of `@graphty/layout`'s declarations).
|
|
6
|
+
* Types only: this file imports nothing at runtime.
|
|
7
|
+
*
|
|
8
|
+
* The CPU counterparts, when phase M8a lands them (plan 2026-09-19-webgpu-m8a-algorithms-seam, Task M8a-T8):
|
|
9
|
+
* `PageRankOptions` here is `IndexedPageRankOptions` there (`{ dampingFactor?, maxIterations?, tolerance?,
|
|
10
|
+
* weighted? }`); `HitsOptions`, `EigenvectorOptions` and `KatzOptions` here all correspond to the ONE
|
|
11
|
+
* `HitsOptionsLike` there (`{ maxIterations?, tolerance?, weighted? }`), which is why every one of them carries
|
|
12
|
+
* those three members and `KatzOptions` adds `alpha` / `beta` on top; `ComponentsOptions` has no CPU counterpart at
|
|
13
|
+
* all, because `AlgorithmAccelerator.connectedComponents?(s: GraphSnapshot): Promise<LabelResultLike>` declares no
|
|
14
|
+
* options parameter. `weighted`, never `weight`: that is the member name graph-format design 14.2 fixes at
|
|
15
|
+
* `design/graph-format/graph-format-design.md:3892` and the one M8a ports.
|
|
16
|
+
*/
|
|
17
|
+
import type { F32, U32 } from "@graphty/graph-format";
|
|
18
|
+
/** Spec 3.3 line 815: every score result carries `precision` so a consumer can label GPU scores (Q-24). */
|
|
19
|
+
export interface GpuScoresResult {
|
|
20
|
+
readonly scores: F32;
|
|
21
|
+
readonly iterations: number;
|
|
22
|
+
readonly converged: boolean;
|
|
23
|
+
readonly precision: "f32";
|
|
24
|
+
}
|
|
25
|
+
/** Spec 3.3 line 816: `iterations` is the first iteration whose L1 delta fell below the tolerance (8.2), not the batch boundary. */
|
|
26
|
+
export interface GpuPageRankResult extends GpuScoresResult {
|
|
27
|
+
readonly danglingMass: number;
|
|
28
|
+
}
|
|
29
|
+
/** Spec 3.3 line 817. */
|
|
30
|
+
export interface GpuHitsResult {
|
|
31
|
+
readonly hubs: F32;
|
|
32
|
+
readonly authorities: F32;
|
|
33
|
+
readonly iterations: number;
|
|
34
|
+
readonly converged: boolean;
|
|
35
|
+
readonly precision: "f32";
|
|
36
|
+
}
|
|
37
|
+
/** Spec 3.3 line 818: labels dense 0..count-1 in first-seen order (renumberPartition); groups() is index-aligned. */
|
|
38
|
+
export interface GpuLabelResult {
|
|
39
|
+
readonly labels: U32;
|
|
40
|
+
readonly count: number;
|
|
41
|
+
groups(): U32[];
|
|
42
|
+
}
|
|
43
|
+
/** The CPU seam's IndexedPageRankOptions, member for member (M8a Task M8a-T8; graph-format design 14.2 :3892). */
|
|
44
|
+
export interface PageRankOptions {
|
|
45
|
+
readonly dampingFactor?: number | undefined;
|
|
46
|
+
readonly maxIterations?: number | undefined;
|
|
47
|
+
readonly tolerance?: number | undefined;
|
|
48
|
+
readonly weighted?: boolean | undefined;
|
|
49
|
+
}
|
|
50
|
+
/** The CPU seam's HitsOptionsLike, member for member (M8a Task M8a-T8). */
|
|
51
|
+
export interface HitsOptions {
|
|
52
|
+
readonly maxIterations?: number | undefined;
|
|
53
|
+
readonly tolerance?: number | undefined;
|
|
54
|
+
readonly weighted?: boolean | undefined;
|
|
55
|
+
}
|
|
56
|
+
/** The CPU seam's HitsOptionsLike again: `eigenvectorCentrality` takes that same shape on the CPU side. */
|
|
57
|
+
export interface EigenvectorOptions {
|
|
58
|
+
readonly maxIterations?: number | undefined;
|
|
59
|
+
readonly tolerance?: number | undefined;
|
|
60
|
+
readonly weighted?: boolean | undefined;
|
|
61
|
+
}
|
|
62
|
+
/** HitsOptionsLike plus Katz's own two: `alpha` is the attenuation and `beta` the constant term. */
|
|
63
|
+
export interface KatzOptions {
|
|
64
|
+
readonly alpha?: number | undefined;
|
|
65
|
+
readonly beta?: number | undefined;
|
|
66
|
+
readonly maxIterations?: number | undefined;
|
|
67
|
+
readonly tolerance?: number | undefined;
|
|
68
|
+
readonly weighted?: boolean | undefined;
|
|
69
|
+
}
|
|
70
|
+
/** GPU-only (spec 3.3 line 797: `renumber: true` by default, Q-12); the CPU seam's connectedComponents takes none. */
|
|
71
|
+
export interface ComponentsOptions {
|
|
72
|
+
readonly renumber?: boolean | undefined;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=algorithms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"algorithms.d.ts","sourceRoot":"","sources":["../../../src/types/algorithms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAEtD,2GAA2G;AAC3G,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;CAC7B;AAED,oIAAoI;AACpI,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACtD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CACjC;AAED,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;IACnB,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;CAC7B;AAED,qHAAqH;AACrH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,MAAM,IAAI,GAAG,EAAE,CAAC;CACnB;AAED,kHAAkH;AAClH,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3C;AAED,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3C;AAED,2GAA2G;AAC3G,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3C;AAED,oGAAoG;AACpG,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3C;AAED,sHAAsH;AACtH,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The result and option records of the P7 algorithms (spec 3.3 lines 815-828, 9.7). The `Gpu*Result` shapes are the
|
|
3
|
+
* design's verbatim; the option records are this package's own, spelled MEMBER FOR MEMBER as the CPU seam spells
|
|
4
|
+
* them so one object literal satisfies both sides (the D27 mirror rule src/types/options.ts followed for the
|
|
5
|
+
* layout options until W1b, when those became `import type` re-exports of `@graphty/layout`'s declarations).
|
|
6
|
+
* Types only: this file imports nothing at runtime.
|
|
7
|
+
*
|
|
8
|
+
* The CPU counterparts, when phase M8a lands them (plan 2026-09-19-webgpu-m8a-algorithms-seam, Task M8a-T8):
|
|
9
|
+
* `PageRankOptions` here is `IndexedPageRankOptions` there (`{ dampingFactor?, maxIterations?, tolerance?,
|
|
10
|
+
* weighted? }`); `HitsOptions`, `EigenvectorOptions` and `KatzOptions` here all correspond to the ONE
|
|
11
|
+
* `HitsOptionsLike` there (`{ maxIterations?, tolerance?, weighted? }`), which is why every one of them carries
|
|
12
|
+
* those three members and `KatzOptions` adds `alpha` / `beta` on top; `ComponentsOptions` has no CPU counterpart at
|
|
13
|
+
* all, because `AlgorithmAccelerator.connectedComponents?(s: GraphSnapshot): Promise<LabelResultLike>` declares no
|
|
14
|
+
* options parameter. `weighted`, never `weight`: that is the member name graph-format design 14.2 fixes at
|
|
15
|
+
* `design/graph-format/graph-format-design.md:3892` and the one M8a ports.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=algorithms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"algorithms.js","sourceRoot":"","sources":["../../../src/types/algorithms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The layout-facing public types (spec 3.3, 7.19): the stats records, the GPU simulation interface that extends the
|
|
3
|
-
* design
|
|
3
|
+
* real `@graphty/layout` LayoutSimulation (design 14.3), the run options and the GPU-only tuning knobs. Types only.
|
|
4
4
|
*/
|
|
5
5
|
import type { F32, GraphSnapshot, NodeMask } from "@graphty/graph-format";
|
|
6
6
|
import type { LayoutSimulation } from "./accelerator.js";
|
|
@@ -43,7 +43,7 @@ export interface RunOptions {
|
|
|
43
43
|
readonly batch?: number | undefined;
|
|
44
44
|
readonly signal?: AbortSignal | undefined;
|
|
45
45
|
}
|
|
46
|
-
/** Spec 3.3 GpuLayoutSimulation, verbatim (LayoutSimulation is
|
|
46
|
+
/** Spec 3.3 GpuLayoutSimulation, verbatim (LayoutSimulation is `@graphty/layout`'s, via accelerator.ts). */
|
|
47
47
|
export interface GpuLayoutSimulation<Options, Stats extends LayoutStatsBase> extends LayoutSimulation {
|
|
48
48
|
load(snapshot: GraphSnapshot, positions: F32): void;
|
|
49
49
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/types/layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,wGAAwG;AACxG,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,QAAQ,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,CAAC;IACzC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CACjC;AAED,2CAA2C;AAC3C,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;CACzD;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC7C;AAED,
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/types/layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,wGAAwG;AACxG,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,QAAQ,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,CAAC;IACzC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CACjC;AAED,2CAA2C;AAC3C,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;CACzD;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC7C;AAED,4GAA4G;AAC5G,MAAM,WAAW,mBAAmB,CAAC,OAAO,EAAE,KAAK,SAAS,eAAe,CAAE,SAAQ,gBAAgB;IACjG,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC;IACpD;;;;;;OAMG;IACH,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClE,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,IAAI,CAAC;IACf,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,GAAG,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,WAAW,CAAC,CAAC;CAC/D;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC3D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;CACtD;AAED,8FAA8F;AAC9F,MAAM,WAAW,oBAAoB;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,UAAU,CAAC;CACzC"}
|
package/dist/src/types/layout.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The layout-facing public types (spec 3.3, 7.19): the stats records, the GPU simulation interface that extends the
|
|
3
|
-
* design
|
|
3
|
+
* real `@graphty/layout` LayoutSimulation (design 14.3), the run options and the GPU-only tuning knobs. Types only.
|
|
4
4
|
*/
|
|
5
5
|
export {};
|
|
6
6
|
//# sourceMappingURL=layout.js.map
|
|
@@ -1,54 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The option records of the layouts (spec 9.3, 7.14)
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* The option records of the layouts (spec 9.3, 7.14). The five layout-owned records come from `@graphty/layout` by
|
|
3
|
+
* `import type` and are re-exported here, so a `ForceAtlas2Options` object the element parses is not merely
|
|
4
|
+
* shaped like the one this package takes -- it IS the same declaration (W1b; the D27 mirrors are gone).
|
|
5
|
+
* `ResolvedForceAtlas2Options` below is this package's own and stays local. Types only: nothing here is a runtime
|
|
6
|
+
* import.
|
|
5
7
|
*/
|
|
6
|
-
import type { F32, NodeId
|
|
7
|
-
|
|
8
|
-
export
|
|
9
|
-
readonly dim?: 2 | 3 | undefined;
|
|
10
|
-
readonly scale?: number | undefined;
|
|
11
|
-
readonly center?: ArrayLike<number> | undefined;
|
|
12
|
-
readonly seed?: number | null | undefined;
|
|
13
|
-
}
|
|
14
|
-
/** Spec 9.3 SimulationOptions, mirrored verbatim (layout-owned; the CPU simulations ignore maxInFlight). */
|
|
15
|
-
export interface SimulationOptions {
|
|
16
|
-
readonly settleThreshold?: number | undefined;
|
|
17
|
-
readonly settleWindow?: number | undefined;
|
|
18
|
-
readonly iterationsPerStep?: number | undefined;
|
|
19
|
-
readonly maxInFlight?: number | undefined;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Spec 9.3 ForceAtlas2Options, mirrored verbatim (same names and defaults as
|
|
23
|
-
* layout/src/layouts/force-directed/forceatlas2.ts lines 26-42).
|
|
24
|
-
*/
|
|
25
|
-
export interface ForceAtlas2Options extends CommonLayoutOptions, SimulationOptions {
|
|
26
|
-
readonly maxIter?: number | undefined;
|
|
27
|
-
readonly jitterTolerance?: number | undefined;
|
|
28
|
-
readonly scalingRatio?: number | undefined;
|
|
29
|
-
readonly gravity?: number | undefined;
|
|
30
|
-
readonly strongGravity?: boolean | undefined;
|
|
31
|
-
readonly distributedAction?: boolean | undefined;
|
|
32
|
-
readonly linlog?: boolean | undefined;
|
|
33
|
-
readonly nodeMass?: F32 | string | Readonly<Record<NodeId, number>> | null | undefined;
|
|
34
|
-
readonly nodeSize?: F32 | string | Readonly<Record<NodeId, number>> | null | undefined;
|
|
35
|
-
readonly weight?: boolean | string | null | undefined;
|
|
36
|
-
readonly dissuadeHubs?: boolean | undefined;
|
|
37
|
-
}
|
|
38
|
-
/** Spec 9.3 FruchtermanReingoldOptions, mirrored for the LayoutAccelerator mirror's method signature (P5 implements it). */
|
|
39
|
-
export interface FruchtermanReingoldOptions extends CommonLayoutOptions, SimulationOptions {
|
|
40
|
-
readonly k?: number | null | undefined;
|
|
41
|
-
readonly iterations?: number | undefined;
|
|
42
|
-
readonly fixed?: NodeMask | string | null | undefined;
|
|
43
|
-
}
|
|
44
|
-
/** Spec 9.3 SpringElectricalOptions, mirrored for the LayoutAccelerator mirror's method signature (P5 implements it). */
|
|
45
|
-
export interface SpringElectricalOptions extends CommonLayoutOptions, SimulationOptions {
|
|
46
|
-
readonly springLength?: number | undefined;
|
|
47
|
-
readonly springCoefficient?: number | undefined;
|
|
48
|
-
readonly gravity?: number | undefined;
|
|
49
|
-
readonly dragCoefficient?: number | undefined;
|
|
50
|
-
readonly timeStep?: number | undefined;
|
|
51
|
-
}
|
|
8
|
+
import type { F32, NodeId } from "@graphty/graph-format";
|
|
9
|
+
import type { CommonLayoutOptions, ForceAtlas2Options, FruchtermanReingoldOptions, SimulationOptions, SpringElectricalOptions } from "@graphty/layout";
|
|
10
|
+
export type { CommonLayoutOptions, ForceAtlas2Options, FruchtermanReingoldOptions, SimulationOptions, SpringElectricalOptions, };
|
|
52
11
|
/**
|
|
53
12
|
* The resolved (defaults applied) ForceAtlas2 option record the simulation keeps; every field present.
|
|
54
13
|
* Exported: consumed by src/layouts/forceatlas2.ts (P3-T2, resolveForceAtlas2Options) and the option tests.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/types/options.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/types/options.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EACR,mBAAmB,EACnB,kBAAkB,EAClB,0BAA0B,EAC1B,iBAAiB,EACjB,uBAAuB,EAC1B,MAAM,iBAAiB,CAAC;AAIzB,YAAY,EACR,mBAAmB,EACnB,kBAAkB,EAClB,0BAA0B,EAC1B,iBAAiB,EACjB,uBAAuB,GAC1B,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IAC1E,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IAC1E,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAChC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The option records of the layouts (spec 9.3, 7.14)
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* The option records of the layouts (spec 9.3, 7.14). The five layout-owned records come from `@graphty/layout` by
|
|
3
|
+
* `import type` and are re-exported here, so a `ForceAtlas2Options` object the element parses is not merely
|
|
4
|
+
* shaped like the one this package takes -- it IS the same declaration (W1b; the D27 mirrors are gone).
|
|
5
|
+
* `ResolvedForceAtlas2Options` below is this package's own and stays local. Types only: nothing here is a runtime
|
|
6
|
+
* import.
|
|
5
7
|
*/
|
|
6
8
|
export {};
|
|
7
9
|
//# sourceMappingURL=options.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/types/options.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/types/options.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `pr-finalize` kernel body (spec 8.2 dispatch (b)): ONE workgroup folds the `P.groups` per-workgroup partials
|
|
3
|
+
* into the header at `partials[0]` -- a STORAGE region, never a uniform, read by the next dispatch of the same
|
|
4
|
+
* pass -- and records `firstConverged` the first time the delta falls below `P.convergeThreshold`. NORM_MODE 2
|
|
5
|
+
* stores the square root of the folded norm (the L2 case). The recorded iteration is `P.iteration - 1u` because
|
|
6
|
+
* the delta a scale pass produces at iteration i is `|x(i-1) - x(i-2)|`, the error of iteration i - 1 (PD-9).
|
|
7
|
+
* The body is normative: a sabotage mutation is a textual edit of it, so it is not restyled.
|
|
8
|
+
*/
|
|
9
|
+
/** Entry point `pr_finalize`; override NORM_MODE (2 takes the square root of the folded norm, every other value stores it as folded). */
|
|
10
|
+
export declare const prFinalizeWgsl = "\n@compute @workgroup_size(WG)\nfn pr_finalize(@builtin(local_invocation_id) lid: vec3<u32>) {\n var d = 0.0;\n var e = 0.0;\n var m = 0.0;\n for (var g = lid.x; g < P.groups; g = g + WG) {\n d = d + partials[1u + g].danglingMass;\n e = e + partials[1u + g].delta;\n m = m + partials[1u + g].norm;\n }\n let folded = wg_reduce_vec4(vec4f(d, e, m, 0.0), lid.x, 0u);\n if (lid.x == 0u) {\n partials[0].danglingMass = folded.x;\n partials[0].delta = folded.y;\n var norm = folded.z;\n if (NORM_MODE == 2u) { norm = sqrt(max(0.0, folded.z)); }\n partials[0].norm = norm;\n partials[0].iteration = P.iteration;\n let unset = partials[0].firstConverged == U32_MAX;\n if (P.trackConvergence == 1u && P.iteration >= 2u && folded.y < P.convergeThreshold && unset) {\n partials[0].firstConverged = P.iteration - 1u;\n }\n }\n}\n";
|
|
11
|
+
//# sourceMappingURL=pr-finalize.wgsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-finalize.wgsl.d.ts","sourceRoot":"","sources":["../../../src/wgsl/pr-finalize.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yIAAyI;AACzI,eAAO,MAAM,cAAc,86BAyB1B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `pr-finalize` kernel body (spec 8.2 dispatch (b)): ONE workgroup folds the `P.groups` per-workgroup partials
|
|
3
|
+
* into the header at `partials[0]` -- a STORAGE region, never a uniform, read by the next dispatch of the same
|
|
4
|
+
* pass -- and records `firstConverged` the first time the delta falls below `P.convergeThreshold`. NORM_MODE 2
|
|
5
|
+
* stores the square root of the folded norm (the L2 case). The recorded iteration is `P.iteration - 1u` because
|
|
6
|
+
* the delta a scale pass produces at iteration i is `|x(i-1) - x(i-2)|`, the error of iteration i - 1 (PD-9).
|
|
7
|
+
* The body is normative: a sabotage mutation is a textual edit of it, so it is not restyled.
|
|
8
|
+
*/
|
|
9
|
+
/** Entry point `pr_finalize`; override NORM_MODE (2 takes the square root of the folded norm, every other value stores it as folded). */
|
|
10
|
+
export const prFinalizeWgsl = /* wgsl */ `
|
|
11
|
+
@compute @workgroup_size(WG)
|
|
12
|
+
fn pr_finalize(@builtin(local_invocation_id) lid: vec3<u32>) {
|
|
13
|
+
var d = 0.0;
|
|
14
|
+
var e = 0.0;
|
|
15
|
+
var m = 0.0;
|
|
16
|
+
for (var g = lid.x; g < P.groups; g = g + WG) {
|
|
17
|
+
d = d + partials[1u + g].danglingMass;
|
|
18
|
+
e = e + partials[1u + g].delta;
|
|
19
|
+
m = m + partials[1u + g].norm;
|
|
20
|
+
}
|
|
21
|
+
let folded = wg_reduce_vec4(vec4f(d, e, m, 0.0), lid.x, 0u);
|
|
22
|
+
if (lid.x == 0u) {
|
|
23
|
+
partials[0].danglingMass = folded.x;
|
|
24
|
+
partials[0].delta = folded.y;
|
|
25
|
+
var norm = folded.z;
|
|
26
|
+
if (NORM_MODE == 2u) { norm = sqrt(max(0.0, folded.z)); }
|
|
27
|
+
partials[0].norm = norm;
|
|
28
|
+
partials[0].iteration = P.iteration;
|
|
29
|
+
let unset = partials[0].firstConverged == U32_MAX;
|
|
30
|
+
if (P.trackConvergence == 1u && P.iteration >= 2u && folded.y < P.convergeThreshold && unset) {
|
|
31
|
+
partials[0].firstConverged = P.iteration - 1u;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
//# sourceMappingURL=pr-finalize.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-finalize.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/pr-finalize.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yIAAyI;AACzI,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;CAyBxC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `pr-scale` kernel body (spec 8.2 dispatch (a)): one invocation per node writes `xNorm[u]` and contributes a
|
|
3
|
+
* per-workgroup partial of the dangling mass, the L1 delta `|rankIn - rankPrev|` and, for the spectral modes, the
|
|
4
|
+
* norm term. NORM_MODE selects the divisor: 0 PageRank (`rankIn[u] / outWeightSum[u]`, 0 and a dangling
|
|
5
|
+
* contribution when the sum is not positive); 1 and 2 are NORM PASSES that write no xNorm and only accumulate
|
|
6
|
+
* `abs(x)` (L1) or `x * x` (L2); 3 divides by the scalar `partials[0].norm` the previous dispatch folded; 4 is the
|
|
7
|
+
* identity (Katz). The body is normative: a sabotage mutation is a textual edit of it, so it is not restyled.
|
|
8
|
+
*
|
|
9
|
+
* The guard is named `inRange`, never `active`: `active` is a WGSL reserved word (spec 16.2) and the composer
|
|
10
|
+
* rejects it before a device is touched.
|
|
11
|
+
*/
|
|
12
|
+
/** Entry point `pr_scale`; override NORM_MODE (0 PageRank, 1 L1 norm pass, 2 L2 norm pass, 3 scale by partials[0].norm, 4 identity). */
|
|
13
|
+
export declare const prScaleWgsl = "\n@compute @workgroup_size(WG)\nfn pr_scale(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let u = linear_id(wid, lid.x);\n let inRange = u < P.n;\n var x = 0.0;\n var prev = 0.0;\n if (inRange) { x = rankIn[u]; prev = rankPrev[u]; }\n var dangling = 0.0;\n var delta = 0.0;\n var normTerm = 0.0;\n if (inRange) {\n delta = abs(x - prev);\n if (NORM_MODE == 0u) {\n let divisor = outWeightSum[u];\n if (divisor <= 0.0) { dangling = x; xNorm[u] = 0.0; } else { xNorm[u] = x / divisor; }\n }\n if (NORM_MODE == 1u) { normTerm = abs(x); }\n if (NORM_MODE == 2u) { normTerm = x * x; }\n if (NORM_MODE == 3u) {\n var scale = partials[0].norm;\n if (scale <= 0.0) { scale = 1.0; }\n xNorm[u] = x / scale;\n }\n if (NORM_MODE == 4u) { xNorm[u] = x; }\n }\n let folded = wg_reduce_vec4(vec4f(dangling, delta, normTerm, 0.0), lid.x, 0u);\n if (lid.x == 0u) {\n let slot = 1u + group_id(wid);\n partials[slot].danglingMass = folded.x;\n partials[slot].delta = folded.y;\n partials[slot].norm = folded.z;\n }\n}\n";
|
|
14
|
+
//# sourceMappingURL=pr-scale.wgsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-scale.wgsl.d.ts","sourceRoot":"","sources":["../../../src/wgsl/pr-scale.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wIAAwI;AACxI,eAAO,MAAM,WAAW,2sCAkCvB,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `pr-scale` kernel body (spec 8.2 dispatch (a)): one invocation per node writes `xNorm[u]` and contributes a
|
|
3
|
+
* per-workgroup partial of the dangling mass, the L1 delta `|rankIn - rankPrev|` and, for the spectral modes, the
|
|
4
|
+
* norm term. NORM_MODE selects the divisor: 0 PageRank (`rankIn[u] / outWeightSum[u]`, 0 and a dangling
|
|
5
|
+
* contribution when the sum is not positive); 1 and 2 are NORM PASSES that write no xNorm and only accumulate
|
|
6
|
+
* `abs(x)` (L1) or `x * x` (L2); 3 divides by the scalar `partials[0].norm` the previous dispatch folded; 4 is the
|
|
7
|
+
* identity (Katz). The body is normative: a sabotage mutation is a textual edit of it, so it is not restyled.
|
|
8
|
+
*
|
|
9
|
+
* The guard is named `inRange`, never `active`: `active` is a WGSL reserved word (spec 16.2) and the composer
|
|
10
|
+
* rejects it before a device is touched.
|
|
11
|
+
*/
|
|
12
|
+
/** Entry point `pr_scale`; override NORM_MODE (0 PageRank, 1 L1 norm pass, 2 L2 norm pass, 3 scale by partials[0].norm, 4 identity). */
|
|
13
|
+
export const prScaleWgsl = /* wgsl */ `
|
|
14
|
+
@compute @workgroup_size(WG)
|
|
15
|
+
fn pr_scale(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
|
|
16
|
+
let u = linear_id(wid, lid.x);
|
|
17
|
+
let inRange = u < P.n;
|
|
18
|
+
var x = 0.0;
|
|
19
|
+
var prev = 0.0;
|
|
20
|
+
if (inRange) { x = rankIn[u]; prev = rankPrev[u]; }
|
|
21
|
+
var dangling = 0.0;
|
|
22
|
+
var delta = 0.0;
|
|
23
|
+
var normTerm = 0.0;
|
|
24
|
+
if (inRange) {
|
|
25
|
+
delta = abs(x - prev);
|
|
26
|
+
if (NORM_MODE == 0u) {
|
|
27
|
+
let divisor = outWeightSum[u];
|
|
28
|
+
if (divisor <= 0.0) { dangling = x; xNorm[u] = 0.0; } else { xNorm[u] = x / divisor; }
|
|
29
|
+
}
|
|
30
|
+
if (NORM_MODE == 1u) { normTerm = abs(x); }
|
|
31
|
+
if (NORM_MODE == 2u) { normTerm = x * x; }
|
|
32
|
+
if (NORM_MODE == 3u) {
|
|
33
|
+
var scale = partials[0].norm;
|
|
34
|
+
if (scale <= 0.0) { scale = 1.0; }
|
|
35
|
+
xNorm[u] = x / scale;
|
|
36
|
+
}
|
|
37
|
+
if (NORM_MODE == 4u) { xNorm[u] = x; }
|
|
38
|
+
}
|
|
39
|
+
let folded = wg_reduce_vec4(vec4f(dangling, delta, normTerm, 0.0), lid.x, 0u);
|
|
40
|
+
if (lid.x == 0u) {
|
|
41
|
+
let slot = 1u + group_id(wid);
|
|
42
|
+
partials[slot].danglingMass = folded.x;
|
|
43
|
+
partials[slot].delta = folded.y;
|
|
44
|
+
partials[slot].norm = folded.z;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
//# sourceMappingURL=pr-scale.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-scale.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/pr-scale.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wIAAwI;AACxI,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCrC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `spmv-pull` kernel body (spec 6 row 9, 8.2; PD-1 of the M8b plan): one invocation per row of the REVERSE
|
|
3
|
+
* adjacency, grid-stride over `[0, P.n)`, folding `weight * xNorm[nbr]` over the row's in-arcs in chunks of 64
|
|
4
|
+
* terms (a two-level f32 sum: the chunk absorbs the rounding of 64 terms, the row total the rounding of the chunk
|
|
5
|
+
* count, so a 10,000-arc hub row loses about 200 rounding steps instead of 10,000; Kahan compensation is not used
|
|
6
|
+
* because Metal's shader compiler folds `((acc + term) - acc) - term` to zero whatever hides it) and writing
|
|
7
|
+
* `rankOut[v] = beta * pv + alpha * (sum + danglingMass * pv)`, where `pv` is `personalization[v]` when
|
|
8
|
+
* HAS_PERSONALIZATION and the uniform `P.uniformP` otherwise. PageRank sets alpha to the
|
|
9
|
+
* damping factor, beta to `1 - alpha` and USE_DANGLING; HITS and eigenvector set alpha 1, beta 0, uniformP 0; Katz
|
|
10
|
+
* sets alpha to the attenuation, beta to its constant and uniformP 1. The body is normative: a sabotage mutation
|
|
11
|
+
* (test/helpers/sabotage.ts) is a textual edit of it, so it is not restyled.
|
|
12
|
+
*/
|
|
13
|
+
/** Entry point `spmv_pull`; overrides HAS_PERSONALIZATION and USE_DANGLING plus the standard USE_PERM / HAS_WEIGHTS. */
|
|
14
|
+
export declare const spmvPullWgsl = "\n@compute @workgroup_size(WG)\nfn spmv_pull(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n var dangling = 0.0;\n if (USE_DANGLING) { dangling = partials[0].danglingMass; }\n let first = linear_id(wid, lid.x);\n for (var row = first; row < P.n; row = row + P.stride) {\n let v = select(row, perm[row], USE_PERM);\n let a0 = max(rowPtr[v], P.arcBase);\n let a1 = min(rowPtr[v + 1u], P.arcEnd);\n var acc = 0.0;\n var chunk = 0.0;\n var inChunk = 0u;\n for (var arc = a0; arc < a1; arc = arc + 1u) {\n let nbr = colIdx[arc - P.arcBase]; // `target` is a WGSL reserved word (spec 16.2)\n var weight = 1.0;\n if (HAS_WEIGHTS) { weight = weights[arc - P.arcBase]; }\n // two-level sum: 64 terms into chunk, chunk into acc (see the header; no compensation, no select)\n chunk = chunk + (weight * xNorm[nbr]);\n inChunk = inChunk + 1u;\n if (inChunk == 64u) {\n acc = acc + chunk;\n chunk = 0.0;\n inChunk = 0u;\n }\n }\n acc = acc + chunk;\n var pv = P.uniformP;\n if (HAS_PERSONALIZATION) { pv = personalization[v]; }\n rankOut[v] = (P.beta * pv) + (P.alpha * (acc + (dangling * pv)));\n }\n}\n";
|
|
15
|
+
//# sourceMappingURL=spmv-pull.wgsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spmv-pull.wgsl.d.ts","sourceRoot":"","sources":["../../../src/wgsl/spmv-pull.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wHAAwH;AACxH,eAAO,MAAM,YAAY,s2CAgCxB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `spmv-pull` kernel body (spec 6 row 9, 8.2; PD-1 of the M8b plan): one invocation per row of the REVERSE
|
|
3
|
+
* adjacency, grid-stride over `[0, P.n)`, folding `weight * xNorm[nbr]` over the row's in-arcs in chunks of 64
|
|
4
|
+
* terms (a two-level f32 sum: the chunk absorbs the rounding of 64 terms, the row total the rounding of the chunk
|
|
5
|
+
* count, so a 10,000-arc hub row loses about 200 rounding steps instead of 10,000; Kahan compensation is not used
|
|
6
|
+
* because Metal's shader compiler folds `((acc + term) - acc) - term` to zero whatever hides it) and writing
|
|
7
|
+
* `rankOut[v] = beta * pv + alpha * (sum + danglingMass * pv)`, where `pv` is `personalization[v]` when
|
|
8
|
+
* HAS_PERSONALIZATION and the uniform `P.uniformP` otherwise. PageRank sets alpha to the
|
|
9
|
+
* damping factor, beta to `1 - alpha` and USE_DANGLING; HITS and eigenvector set alpha 1, beta 0, uniformP 0; Katz
|
|
10
|
+
* sets alpha to the attenuation, beta to its constant and uniformP 1. The body is normative: a sabotage mutation
|
|
11
|
+
* (test/helpers/sabotage.ts) is a textual edit of it, so it is not restyled.
|
|
12
|
+
*/
|
|
13
|
+
/** Entry point `spmv_pull`; overrides HAS_PERSONALIZATION and USE_DANGLING plus the standard USE_PERM / HAS_WEIGHTS. */
|
|
14
|
+
export const spmvPullWgsl = /* wgsl */ `
|
|
15
|
+
@compute @workgroup_size(WG)
|
|
16
|
+
fn spmv_pull(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
|
|
17
|
+
var dangling = 0.0;
|
|
18
|
+
if (USE_DANGLING) { dangling = partials[0].danglingMass; }
|
|
19
|
+
let first = linear_id(wid, lid.x);
|
|
20
|
+
for (var row = first; row < P.n; row = row + P.stride) {
|
|
21
|
+
let v = select(row, perm[row], USE_PERM);
|
|
22
|
+
let a0 = max(rowPtr[v], P.arcBase);
|
|
23
|
+
let a1 = min(rowPtr[v + 1u], P.arcEnd);
|
|
24
|
+
var acc = 0.0;
|
|
25
|
+
var chunk = 0.0;
|
|
26
|
+
var inChunk = 0u;
|
|
27
|
+
for (var arc = a0; arc < a1; arc = arc + 1u) {
|
|
28
|
+
let nbr = colIdx[arc - P.arcBase]; // \`target\` is a WGSL reserved word (spec 16.2)
|
|
29
|
+
var weight = 1.0;
|
|
30
|
+
if (HAS_WEIGHTS) { weight = weights[arc - P.arcBase]; }
|
|
31
|
+
// two-level sum: 64 terms into chunk, chunk into acc (see the header; no compensation, no select)
|
|
32
|
+
chunk = chunk + (weight * xNorm[nbr]);
|
|
33
|
+
inChunk = inChunk + 1u;
|
|
34
|
+
if (inChunk == 64u) {
|
|
35
|
+
acc = acc + chunk;
|
|
36
|
+
chunk = 0.0;
|
|
37
|
+
inChunk = 0u;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
acc = acc + chunk;
|
|
41
|
+
var pv = P.uniformP;
|
|
42
|
+
if (HAS_PERSONALIZATION) { pv = personalization[v]; }
|
|
43
|
+
rankOut[v] = (P.beta * pv) + (P.alpha * (acc + (dangling * pv)));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
//# sourceMappingURL=spmv-pull.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spmv-pull.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/spmv-pull.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wHAAwH;AACxH,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCtC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `wcc-compress` kernel body (spec 8.3): pointer jumping to the root, reading through `atomicLoad` on the same
|
|
3
|
+
* `array<atomic<u32>>` because WGSL forbids mixing atomic and plain access to one element. The walk is bounded by
|
|
4
|
+
* `P.maxSteps`; a walk that runs out leaves a shorter path, which the next round finishes. The body is normative:
|
|
5
|
+
* a sabotage mutation is a textual edit of it, so it is not restyled.
|
|
6
|
+
*/
|
|
7
|
+
/** Entry point `wcc_compress`; no overrides. */
|
|
8
|
+
export declare const wccCompressWgsl = "\n@compute @workgroup_size(WG)\nfn wcc_compress(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let first = linear_id(wid, lid.x);\n for (var v = first; v < P.items; v = v + P.stride) {\n var root = atomicLoad(&comp[v]);\n var steps = 0u;\n loop {\n let parent = atomicLoad(&comp[root]);\n if (parent == root) { break; }\n if (steps >= P.maxSteps) { break; }\n steps = steps + 1u;\n root = parent;\n }\n atomicStore(&comp[v], root);\n }\n}\n";
|
|
9
|
+
//# sourceMappingURL=wcc-compress.wgsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wcc-compress.wgsl.d.ts","sourceRoot":"","sources":["../../../src/wgsl/wcc-compress.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gDAAgD;AAChD,eAAO,MAAM,eAAe,0kBAiB3B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `wcc-compress` kernel body (spec 8.3): pointer jumping to the root, reading through `atomicLoad` on the same
|
|
3
|
+
* `array<atomic<u32>>` because WGSL forbids mixing atomic and plain access to one element. The walk is bounded by
|
|
4
|
+
* `P.maxSteps`; a walk that runs out leaves a shorter path, which the next round finishes. The body is normative:
|
|
5
|
+
* a sabotage mutation is a textual edit of it, so it is not restyled.
|
|
6
|
+
*/
|
|
7
|
+
/** Entry point `wcc_compress`; no overrides. */
|
|
8
|
+
export const wccCompressWgsl = /* wgsl */ `
|
|
9
|
+
@compute @workgroup_size(WG)
|
|
10
|
+
fn wcc_compress(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
|
|
11
|
+
let first = linear_id(wid, lid.x);
|
|
12
|
+
for (var v = first; v < P.items; v = v + P.stride) {
|
|
13
|
+
var root = atomicLoad(&comp[v]);
|
|
14
|
+
var steps = 0u;
|
|
15
|
+
loop {
|
|
16
|
+
let parent = atomicLoad(&comp[root]);
|
|
17
|
+
if (parent == root) { break; }
|
|
18
|
+
if (steps >= P.maxSteps) { break; }
|
|
19
|
+
steps = steps + 1u;
|
|
20
|
+
root = parent;
|
|
21
|
+
}
|
|
22
|
+
atomicStore(&comp[v], root);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
//# sourceMappingURL=wcc-compress.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wcc-compress.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/wcc-compress.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;CAiBzC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `wcc-link-edges` kernel body (spec 8.3): the each-edge-once link round of Afforest, correct for directed and
|
|
3
|
+
* undirected input alike because `edgeList()` yields every logical edge once in declared orientation (design 10.1).
|
|
4
|
+
* `link_pair` is the same GAP `Link` transcription as wcc-link-sample (each module is composed alone, so the helper
|
|
5
|
+
* is copied, not shared): all-u32 CAS on `comp`, an `array<atomic<u32>>` because WGSL forbids mixing atomic and
|
|
6
|
+
* plain access to one element, with a bounded retry loop (PD-5) and the changed flag at `P.flagIndex` inside the
|
|
7
|
+
* same array (PD-4). The `P.giant` guard is GAP's "skip the vertices already in the giant component" and is a pure
|
|
8
|
+
* optimisation -- linking two vertices already in one component is a no-op. The body is normative: a sabotage
|
|
9
|
+
* mutation is a textual edit of it, so it is not restyled.
|
|
10
|
+
*/
|
|
11
|
+
/** Entry point `wcc_link_edges`; no overrides. */
|
|
12
|
+
export declare const wccLinkEdgesWgsl = "\nfn link_pair(a: u32, b: u32) {\n var p1 = atomicLoad(&comp[a]);\n var p2 = atomicLoad(&comp[b]);\n var steps = 0u;\n loop {\n if (p1 == p2) { break; }\n if (steps >= P.maxSteps) { atomicStore(&comp[P.flagIndex], 1u); break; }\n steps = steps + 1u;\n let hi = max(p1, p2);\n let lo = min(p1, p2);\n let pHigh = atomicLoad(&comp[hi]);\n if (pHigh == lo) { break; }\n if (pHigh == hi) {\n let swapped = atomicCompareExchangeWeak(&comp[hi], hi, lo);\n if (swapped.exchanged) { atomicStore(&comp[P.flagIndex], 1u); break; }\n }\n p1 = atomicLoad(&comp[atomicLoad(&comp[hi])]);\n p2 = atomicLoad(&comp[lo]);\n }\n}\n\n@compute @workgroup_size(WG)\nfn wcc_link_edges(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let first = linear_id(wid, lid.x);\n for (var e = first; e < P.items; e = e + P.stride) {\n let u = edgeSrc[e];\n let v = edgeDst[e];\n if (u == v) { continue; }\n if (atomicLoad(&comp[u]) == P.giant && atomicLoad(&comp[v]) == P.giant) { continue; }\n link_pair(u, v);\n }\n}\n";
|
|
13
|
+
//# sourceMappingURL=wcc-link-edges.wgsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wcc-link-edges.wgsl.d.ts","sourceRoot":"","sources":["../../../src/wgsl/wcc-link-edges.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,kDAAkD;AAClD,eAAO,MAAM,gBAAgB,uqCAiC5B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `wcc-link-edges` kernel body (spec 8.3): the each-edge-once link round of Afforest, correct for directed and
|
|
3
|
+
* undirected input alike because `edgeList()` yields every logical edge once in declared orientation (design 10.1).
|
|
4
|
+
* `link_pair` is the same GAP `Link` transcription as wcc-link-sample (each module is composed alone, so the helper
|
|
5
|
+
* is copied, not shared): all-u32 CAS on `comp`, an `array<atomic<u32>>` because WGSL forbids mixing atomic and
|
|
6
|
+
* plain access to one element, with a bounded retry loop (PD-5) and the changed flag at `P.flagIndex` inside the
|
|
7
|
+
* same array (PD-4). The `P.giant` guard is GAP's "skip the vertices already in the giant component" and is a pure
|
|
8
|
+
* optimisation -- linking two vertices already in one component is a no-op. The body is normative: a sabotage
|
|
9
|
+
* mutation is a textual edit of it, so it is not restyled.
|
|
10
|
+
*/
|
|
11
|
+
/** Entry point `wcc_link_edges`; no overrides. */
|
|
12
|
+
export const wccLinkEdgesWgsl = /* wgsl */ `
|
|
13
|
+
fn link_pair(a: u32, b: u32) {
|
|
14
|
+
var p1 = atomicLoad(&comp[a]);
|
|
15
|
+
var p2 = atomicLoad(&comp[b]);
|
|
16
|
+
var steps = 0u;
|
|
17
|
+
loop {
|
|
18
|
+
if (p1 == p2) { break; }
|
|
19
|
+
if (steps >= P.maxSteps) { atomicStore(&comp[P.flagIndex], 1u); break; }
|
|
20
|
+
steps = steps + 1u;
|
|
21
|
+
let hi = max(p1, p2);
|
|
22
|
+
let lo = min(p1, p2);
|
|
23
|
+
let pHigh = atomicLoad(&comp[hi]);
|
|
24
|
+
if (pHigh == lo) { break; }
|
|
25
|
+
if (pHigh == hi) {
|
|
26
|
+
let swapped = atomicCompareExchangeWeak(&comp[hi], hi, lo);
|
|
27
|
+
if (swapped.exchanged) { atomicStore(&comp[P.flagIndex], 1u); break; }
|
|
28
|
+
}
|
|
29
|
+
p1 = atomicLoad(&comp[atomicLoad(&comp[hi])]);
|
|
30
|
+
p2 = atomicLoad(&comp[lo]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@compute @workgroup_size(WG)
|
|
35
|
+
fn wcc_link_edges(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
|
|
36
|
+
let first = linear_id(wid, lid.x);
|
|
37
|
+
for (var e = first; e < P.items; e = e + P.stride) {
|
|
38
|
+
let u = edgeSrc[e];
|
|
39
|
+
let v = edgeDst[e];
|
|
40
|
+
if (u == v) { continue; }
|
|
41
|
+
if (atomicLoad(&comp[u]) == P.giant && atomicLoad(&comp[v]) == P.giant) { continue; }
|
|
42
|
+
link_pair(u, v);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
//# sourceMappingURL=wcc-link-edges.wgsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wcc-link-edges.wgsl.js","sourceRoot":"","sources":["../../../src/wgsl/wcc-link-edges.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,kDAAkD;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiC1C,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `wcc-link-sample` kernel body (spec 8.3): one of Afforest's sampled link rounds -- every vertex links its
|
|
3
|
+
* r-th neighbour, `colIdx[rowPtr[v] + P.r]`, when it has one. `link_pair` is GAP's `Link` (gapbs/cc.cc lines
|
|
4
|
+
* 40-150) transcribed for WGSL: all-u32 CAS on `comp`, which is `array<atomic<u32>>` because WGSL forbids mixing
|
|
5
|
+
* atomic and plain access to one element, with a bounded retry loop (PD-5). The changed flag is the word at
|
|
6
|
+
* `P.flagIndex` inside the same array (PD-4). The body is normative: a sabotage mutation is a textual edit of it,
|
|
7
|
+
* so it is not restyled.
|
|
8
|
+
*/
|
|
9
|
+
/** Entry point `wcc_link_sample`; standard USE_PERM / HAS_WEIGHTS only (the body reads neither weights nor a permutation beyond the row select). */
|
|
10
|
+
export declare const wccLinkSampleWgsl = "\nfn link_pair(a: u32, b: u32) {\n var p1 = atomicLoad(&comp[a]);\n var p2 = atomicLoad(&comp[b]);\n var steps = 0u;\n loop {\n if (p1 == p2) { break; }\n if (steps >= P.maxSteps) { atomicStore(&comp[P.flagIndex], 1u); break; }\n steps = steps + 1u;\n let hi = max(p1, p2);\n let lo = min(p1, p2);\n let pHigh = atomicLoad(&comp[hi]);\n if (pHigh == lo) { break; }\n if (pHigh == hi) {\n let swapped = atomicCompareExchangeWeak(&comp[hi], hi, lo);\n if (swapped.exchanged) { atomicStore(&comp[P.flagIndex], 1u); break; }\n }\n p1 = atomicLoad(&comp[atomicLoad(&comp[hi])]);\n p2 = atomicLoad(&comp[lo]);\n }\n}\n\n@compute @workgroup_size(WG)\nfn wcc_link_sample(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let first = linear_id(wid, lid.x);\n for (var row = first; row < P.items; row = row + P.stride) {\n let v = select(row, perm[row], USE_PERM);\n let a0 = rowPtr[v];\n let a1 = rowPtr[v + 1u];\n if (a0 + P.r < a1) {\n link_pair(v, colIdx[a0 + P.r]);\n }\n }\n}\n";
|
|
11
|
+
//# sourceMappingURL=wcc-link-sample.wgsl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wcc-link-sample.wgsl.d.ts","sourceRoot":"","sources":["../../../src/wgsl/wcc-link-sample.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,oJAAoJ;AACpJ,eAAO,MAAM,iBAAiB,kqCAkC7B,CAAC"}
|