@graphty/webgpu-graph-algorithms 0.0.0 → 0.2.1

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 (269) hide show
  1. package/README.md +378 -23
  2. package/dist/browser.d.ts +1 -0
  3. package/dist/browser.js +32 -0
  4. package/dist/browser.js.map +1 -0
  5. package/dist/chunks/context-E6iKaeuJ.js +3136 -0
  6. package/dist/chunks/context-E6iKaeuJ.js.map +1 -0
  7. package/dist/node.d.ts +1 -0
  8. package/dist/node.js +131 -0
  9. package/dist/node.js.map +1 -0
  10. package/dist/src/accelerator.d.ts +26 -0
  11. package/dist/src/accelerator.d.ts.map +1 -0
  12. package/dist/src/accelerator.js +101 -0
  13. package/dist/src/accelerator.js.map +1 -0
  14. package/dist/src/algorithms/degree.d.ts +35 -0
  15. package/dist/src/algorithms/degree.d.ts.map +1 -0
  16. package/dist/src/algorithms/degree.js +119 -0
  17. package/dist/src/algorithms/degree.js.map +1 -0
  18. package/dist/src/browser/index.d.ts +23 -0
  19. package/dist/src/browser/index.d.ts.map +1 -0
  20. package/dist/src/browser/index.js +48 -0
  21. package/dist/src/browser/index.js.map +1 -0
  22. package/dist/src/constants.d.ts +92 -0
  23. package/dist/src/constants.d.ts.map +1 -0
  24. package/dist/src/constants.js +92 -0
  25. package/dist/src/constants.js.map +1 -0
  26. package/dist/src/context.d.ts +84 -0
  27. package/dist/src/context.d.ts.map +1 -0
  28. package/dist/src/context.js +304 -0
  29. package/dist/src/context.js.map +1 -0
  30. package/dist/src/device/acquire.d.ts +57 -0
  31. package/dist/src/device/acquire.d.ts.map +1 -0
  32. package/dist/src/device/acquire.js +232 -0
  33. package/dist/src/device/acquire.js.map +1 -0
  34. package/dist/src/device/caps.d.ts +43 -0
  35. package/dist/src/device/caps.d.ts.map +1 -0
  36. package/dist/src/device/caps.js +104 -0
  37. package/dist/src/device/caps.js.map +1 -0
  38. package/dist/src/device/error-scope.d.ts +75 -0
  39. package/dist/src/device/error-scope.d.ts.map +1 -0
  40. package/dist/src/device/error-scope.js +152 -0
  41. package/dist/src/device/error-scope.js.map +1 -0
  42. package/dist/src/device/lost.d.ts +51 -0
  43. package/dist/src/device/lost.d.ts.map +1 -0
  44. package/dist/src/device/lost.js +130 -0
  45. package/dist/src/device/lost.js.map +1 -0
  46. package/dist/src/device/webgpu-constants.d.ts +31 -0
  47. package/dist/src/device/webgpu-constants.d.ts.map +1 -0
  48. package/dist/src/device/webgpu-constants.js +31 -0
  49. package/dist/src/device/webgpu-constants.js.map +1 -0
  50. package/dist/src/errors.d.ts +56 -0
  51. package/dist/src/errors.d.ts.map +1 -0
  52. package/dist/src/errors.js +57 -0
  53. package/dist/src/errors.js.map +1 -0
  54. package/dist/src/index.d.ts +29 -0
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/index.js +27 -0
  57. package/dist/src/index.js.map +1 -0
  58. package/dist/src/kernel/batch.d.ts +116 -0
  59. package/dist/src/kernel/batch.d.ts.map +1 -0
  60. package/dist/src/kernel/batch.js +335 -0
  61. package/dist/src/kernel/batch.js.map +1 -0
  62. package/dist/src/kernel/dispatch.d.ts +59 -0
  63. package/dist/src/kernel/dispatch.d.ts.map +1 -0
  64. package/dist/src/kernel/dispatch.js +139 -0
  65. package/dist/src/kernel/dispatch.js.map +1 -0
  66. package/dist/src/kernel/kernel.d.ts +84 -0
  67. package/dist/src/kernel/kernel.d.ts.map +1 -0
  68. package/dist/src/kernel/kernel.js +239 -0
  69. package/dist/src/kernel/kernel.js.map +1 -0
  70. package/dist/src/kernel/pipeline-cache.d.ts +90 -0
  71. package/dist/src/kernel/pipeline-cache.d.ts.map +1 -0
  72. package/dist/src/kernel/pipeline-cache.js +251 -0
  73. package/dist/src/kernel/pipeline-cache.js.map +1 -0
  74. package/dist/src/kernel/prelude.d.ts +35 -0
  75. package/dist/src/kernel/prelude.d.ts.map +1 -0
  76. package/dist/src/kernel/prelude.js +211 -0
  77. package/dist/src/kernel/prelude.js.map +1 -0
  78. package/dist/src/kernel/profiler.d.ts +64 -0
  79. package/dist/src/kernel/profiler.d.ts.map +1 -0
  80. package/dist/src/kernel/profiler.js +120 -0
  81. package/dist/src/kernel/profiler.js.map +1 -0
  82. package/dist/src/kernel/struct-block.d.ts +122 -0
  83. package/dist/src/kernel/struct-block.d.ts.map +1 -0
  84. package/dist/src/kernel/struct-block.js +353 -0
  85. package/dist/src/kernel/struct-block.js.map +1 -0
  86. package/dist/src/kernel/uniform-ring.d.ts +70 -0
  87. package/dist/src/kernel/uniform-ring.d.ts.map +1 -0
  88. package/dist/src/kernel/uniform-ring.js +146 -0
  89. package/dist/src/kernel/uniform-ring.js.map +1 -0
  90. package/dist/src/kernel/wgsl.d.ts +88 -0
  91. package/dist/src/kernel/wgsl.d.ts.map +1 -0
  92. package/dist/src/kernel/wgsl.js +390 -0
  93. package/dist/src/kernel/wgsl.js.map +1 -0
  94. package/dist/src/kernels.d.ts +81 -0
  95. package/dist/src/kernels.d.ts.map +1 -0
  96. package/dist/src/kernels.js +417 -0
  97. package/dist/src/kernels.js.map +1 -0
  98. package/dist/src/layouts/force-simulation.d.ts +498 -0
  99. package/dist/src/layouts/force-simulation.d.ts.map +1 -0
  100. package/dist/src/layouts/force-simulation.js +1650 -0
  101. package/dist/src/layouts/force-simulation.js.map +1 -0
  102. package/dist/src/layouts/forceatlas2.d.ts +210 -0
  103. package/dist/src/layouts/forceatlas2.d.ts.map +1 -0
  104. package/dist/src/layouts/forceatlas2.js +759 -0
  105. package/dist/src/layouts/forceatlas2.js.map +1 -0
  106. package/dist/src/layouts/inputs.d.ts +40 -0
  107. package/dist/src/layouts/inputs.d.ts.map +1 -0
  108. package/dist/src/layouts/inputs.js +185 -0
  109. package/dist/src/layouts/inputs.js.map +1 -0
  110. package/dist/src/layouts/repulsion-exact.d.ts +85 -0
  111. package/dist/src/layouts/repulsion-exact.d.ts.map +1 -0
  112. package/dist/src/layouts/repulsion-exact.js +134 -0
  113. package/dist/src/layouts/repulsion-exact.js.map +1 -0
  114. package/dist/src/layouts/seed.d.ts +56 -0
  115. package/dist/src/layouts/seed.d.ts.map +1 -0
  116. package/dist/src/layouts/seed.js +173 -0
  117. package/dist/src/layouts/seed.js.map +1 -0
  118. package/dist/src/memory/buffer-pool.d.ts +73 -0
  119. package/dist/src/memory/buffer-pool.d.ts.map +1 -0
  120. package/dist/src/memory/buffer-pool.js +170 -0
  121. package/dist/src/memory/buffer-pool.js.map +1 -0
  122. package/dist/src/memory/lease.d.ts +53 -0
  123. package/dist/src/memory/lease.d.ts.map +1 -0
  124. package/dist/src/memory/lease.js +85 -0
  125. package/dist/src/memory/lease.js.map +1 -0
  126. package/dist/src/memory/readback.d.ts +143 -0
  127. package/dist/src/memory/readback.d.ts.map +1 -0
  128. package/dist/src/memory/readback.js +375 -0
  129. package/dist/src/memory/readback.js.map +1 -0
  130. package/dist/src/memory/residency.d.ts +83 -0
  131. package/dist/src/memory/residency.d.ts.map +1 -0
  132. package/dist/src/memory/residency.js +573 -0
  133. package/dist/src/memory/residency.js.map +1 -0
  134. package/dist/src/memory/upload-plan.d.ts +101 -0
  135. package/dist/src/memory/upload-plan.d.ts.map +1 -0
  136. package/dist/src/memory/upload-plan.js +265 -0
  137. package/dist/src/memory/upload-plan.js.map +1 -0
  138. package/dist/src/node/index.d.ts +64 -0
  139. package/dist/src/node/index.d.ts.map +1 -0
  140. package/dist/src/node/index.js +183 -0
  141. package/dist/src/node/index.js.map +1 -0
  142. package/dist/src/primitives/reduce.d.ts +57 -0
  143. package/dist/src/primitives/reduce.d.ts.map +1 -0
  144. package/dist/src/primitives/reduce.js +161 -0
  145. package/dist/src/primitives/reduce.js.map +1 -0
  146. package/dist/src/primitives/segmented-reduce.d.ts +38 -0
  147. package/dist/src/primitives/segmented-reduce.d.ts.map +1 -0
  148. package/dist/src/primitives/segmented-reduce.js +211 -0
  149. package/dist/src/primitives/segmented-reduce.js.map +1 -0
  150. package/dist/src/types/accelerator.d.ts +209 -0
  151. package/dist/src/types/accelerator.d.ts.map +1 -0
  152. package/dist/src/types/accelerator.js +8 -0
  153. package/dist/src/types/accelerator.js.map +1 -0
  154. package/dist/src/types/context.d.ts +114 -0
  155. package/dist/src/types/context.d.ts.map +1 -0
  156. package/dist/src/types/context.js +7 -0
  157. package/dist/src/types/context.js.map +1 -0
  158. package/dist/src/types/layout.d.ts +95 -0
  159. package/dist/src/types/layout.d.ts.map +1 -0
  160. package/dist/src/types/layout.js +6 -0
  161. package/dist/src/types/layout.js.map +1 -0
  162. package/dist/src/types/memory.d.ts +22 -0
  163. package/dist/src/types/memory.d.ts.map +1 -0
  164. package/dist/src/types/memory.js +7 -0
  165. package/dist/src/types/memory.js.map +1 -0
  166. package/dist/src/types/options.d.ts +78 -0
  167. package/dist/src/types/options.d.ts.map +1 -0
  168. package/dist/src/types/options.js +7 -0
  169. package/dist/src/types/options.js.map +1 -0
  170. package/dist/src/types/run.d.ts +13 -0
  171. package/dist/src/types/run.d.ts.map +1 -0
  172. package/dist/src/types/run.js +6 -0
  173. package/dist/src/types/run.js.map +1 -0
  174. package/dist/src/wgsl/degree.wgsl.d.ts +10 -0
  175. package/dist/src/wgsl/degree.wgsl.d.ts.map +1 -0
  176. package/dist/src/wgsl/degree.wgsl.js +25 -0
  177. package/dist/src/wgsl/degree.wgsl.js.map +1 -0
  178. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +12 -0
  179. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -0
  180. package/dist/src/wgsl/fa2-attraction.wgsl.js +37 -0
  181. package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -0
  182. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +13 -0
  183. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -0
  184. package/dist/src/wgsl/fa2-integrate.wgsl.js +69 -0
  185. package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -0
  186. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +12 -0
  187. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -0
  188. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +79 -0
  189. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -0
  190. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts +15 -0
  191. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts.map +1 -0
  192. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js +54 -0
  193. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js.map +1 -0
  194. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +14 -0
  195. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -0
  196. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +57 -0
  197. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -0
  198. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts +11 -0
  199. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts.map +1 -0
  200. package/dist/src/wgsl/fa2-to-scene.wgsl.js +19 -0
  201. package/dist/src/wgsl/fa2-to-scene.wgsl.js.map +1 -0
  202. package/dist/src/wgsl/fill.wgsl.d.ts +7 -0
  203. package/dist/src/wgsl/fill.wgsl.d.ts.map +1 -0
  204. package/dist/src/wgsl/fill.wgsl.js +14 -0
  205. package/dist/src/wgsl/fill.wgsl.js.map +1 -0
  206. package/dist/src/wgsl/reduce.wgsl.d.ts +10 -0
  207. package/dist/src/wgsl/reduce.wgsl.d.ts.map +1 -0
  208. package/dist/src/wgsl/reduce.wgsl.js +63 -0
  209. package/dist/src/wgsl/reduce.wgsl.js.map +1 -0
  210. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +13 -0
  211. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -0
  212. package/dist/src/wgsl/segmented-reduce.wgsl.js +35 -0
  213. package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -0
  214. package/dist/tsconfig.build.tsbuildinfo +1 -0
  215. package/dist/webgpu-graph-algorithms.d.ts +1 -0
  216. package/dist/webgpu-graph-algorithms.js +4454 -0
  217. package/dist/webgpu-graph-algorithms.js.map +1 -0
  218. package/package.json +108 -17
  219. package/src/accelerator.ts +117 -0
  220. package/src/algorithms/degree.ts +142 -0
  221. package/src/browser/index.ts +57 -0
  222. package/src/constants.ts +116 -0
  223. package/src/context.ts +399 -0
  224. package/src/device/acquire.ts +256 -0
  225. package/src/device/caps.ts +122 -0
  226. package/src/device/error-scope.ts +171 -0
  227. package/src/device/lost.ts +142 -0
  228. package/src/device/webgpu-constants.ts +44 -0
  229. package/src/errors.ts +94 -0
  230. package/src/index.ts +102 -0
  231. package/src/kernel/batch.ts +427 -0
  232. package/src/kernel/dispatch.ts +162 -0
  233. package/src/kernel/kernel.ts +311 -0
  234. package/src/kernel/pipeline-cache.ts +288 -0
  235. package/src/kernel/prelude.ts +229 -0
  236. package/src/kernel/profiler.ts +148 -0
  237. package/src/kernel/struct-block.ts +439 -0
  238. package/src/kernel/uniform-ring.ts +184 -0
  239. package/src/kernel/wgsl.ts +490 -0
  240. package/src/kernels.ts +511 -0
  241. package/src/layouts/force-simulation.ts +2111 -0
  242. package/src/layouts/forceatlas2.ts +942 -0
  243. package/src/layouts/inputs.ts +252 -0
  244. package/src/layouts/repulsion-exact.ts +183 -0
  245. package/src/layouts/seed.ts +198 -0
  246. package/src/memory/buffer-pool.ts +204 -0
  247. package/src/memory/lease.ts +93 -0
  248. package/src/memory/readback.ts +429 -0
  249. package/src/memory/residency.ts +753 -0
  250. package/src/memory/upload-plan.ts +350 -0
  251. package/src/node/index.ts +230 -0
  252. package/src/primitives/reduce.ts +233 -0
  253. package/src/primitives/segmented-reduce.ts +270 -0
  254. package/src/types/accelerator.ts +236 -0
  255. package/src/types/context.ts +135 -0
  256. package/src/types/layout.ts +103 -0
  257. package/src/types/memory.ts +23 -0
  258. package/src/types/options.ts +84 -0
  259. package/src/types/run.ts +13 -0
  260. package/src/wgsl/degree.wgsl.ts +24 -0
  261. package/src/wgsl/fa2-attraction.wgsl.ts +37 -0
  262. package/src/wgsl/fa2-integrate.wgsl.ts +69 -0
  263. package/src/wgsl/fa2-repulsion-exact.wgsl.ts +78 -0
  264. package/src/wgsl/fa2-speed-finalize.wgsl.ts +53 -0
  265. package/src/wgsl/fa2-stats-finalize.wgsl.ts +57 -0
  266. package/src/wgsl/fa2-to-scene.wgsl.ts +19 -0
  267. package/src/wgsl/fill.wgsl.ts +13 -0
  268. package/src/wgsl/reduce.wgsl.ts +62 -0
  269. package/src/wgsl/segmented-reduce.wgsl.ts +35 -0
@@ -0,0 +1,236 @@
1
+ /**
2
+ * The structural mirrors of @graphty/layout's LayoutSimulation / LayoutAccelerator (spec 9.3) and of
3
+ * the @graphty/algorithms AlgorithmAccelerator (spec 9.2), plus the package's own accelerator surface (spec 3.3).
4
+ * Until W1 these ARE the mirrors (D27): from W1 the mirrors become `import type` of the real packages and
5
+ * test/types/conformance.test-d.ts asserts mutual assignability. Types only.
6
+ */
7
+
8
+ import type { F32, F64, GraphSnapshot, NodeMask, NumericVector, U32 } from "@graphty/graph-format";
9
+
10
+ import type { GpuContext } from "../context.js";
11
+ import type { ForceAtlas2Stats, GpuLayoutSimulation, GpuLayoutTuning } from "./layout.js";
12
+ import type { ForceAtlas2Options, FruchtermanReingoldOptions, SpringElectricalOptions } from "./options.js";
13
+
14
+ // ---- mirrors of @graphty/layout (spec 9.3)
15
+
16
+ /** Design 14.3 LayoutSimulation, verbatim. */
17
+ export interface LayoutSimulation {
18
+ load(snapshot: GraphSnapshot, positions: F32): void;
19
+ step(iterations?: number): void | Promise<void>;
20
+ readonly settled: boolean;
21
+ setFixed(mask: NodeMask): void;
22
+ setPosition(index: number, x: number, y: number, z: number): void;
23
+ dispose(): void;
24
+ }
25
+
26
+ /**
27
+ * Spec 9.3 LayoutAccelerator, verbatim.
28
+ * Exported: published mirror (spec 3.3, D27); re-exported from src/index.ts at P3-T3.
29
+ * @public
30
+ */
31
+ export interface LayoutAccelerator {
32
+ readonly kind: string;
33
+ forceAtlas2?(options?: ForceAtlas2Options): LayoutSimulation;
34
+ fruchtermanReingold?(options?: FruchtermanReingoldOptions): LayoutSimulation;
35
+ springElectrical?(options?: SpringElectricalOptions): LayoutSimulation;
36
+ release?(s: GraphSnapshot): void;
37
+ dispose?(): void;
38
+ }
39
+
40
+ // ---- mirrors of @graphty/algorithms (spec 9.2); the option types named there do not exist before A2, so they are
41
+ // mirrored as empty-extensible records
42
+
43
+ /**
44
+ * Placeholder for the CPU option types the AlgorithmAccelerator methods take before A2 lands (spec 9.2: "the
45
+ * accelerator methods reuse the indexed.* option types").
46
+ * Exported: published mirror (spec 9.2); re-exported from src/index.ts at P3-T3.
47
+ * @public
48
+ */
49
+ export type CpuAlgorithmOptions = Readonly<Record<string, unknown>>;
50
+
51
+ /**
52
+ * Score-shaped result of the CPU package (spec 9.7).
53
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
54
+ * @public
55
+ */
56
+ export interface ScoresResultLike {
57
+ readonly scores: NumericVector;
58
+ readonly iterations: number;
59
+ readonly converged: boolean;
60
+ }
61
+
62
+ /**
63
+ * PageRank result mirror.
64
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
65
+ * @public
66
+ */
67
+ export interface PageRankResultLike extends ScoresResultLike {
68
+ readonly danglingMass?: number | undefined;
69
+ }
70
+
71
+ /**
72
+ * HITS result mirror.
73
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
74
+ * @public
75
+ */
76
+ export interface HitsResultLike {
77
+ readonly hubs: NumericVector;
78
+ readonly authorities: NumericVector;
79
+ readonly iterations: number;
80
+ readonly converged: boolean;
81
+ }
82
+
83
+ /**
84
+ * Label result mirror (components, label propagation).
85
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
86
+ * @public
87
+ */
88
+ export interface LabelResultLike {
89
+ readonly labels: U32;
90
+ readonly count: number;
91
+ groups(): U32[];
92
+ }
93
+
94
+ /**
95
+ * BFS result mirror.
96
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
97
+ * @public
98
+ */
99
+ export interface BfsResultLike {
100
+ readonly depth: U32;
101
+ readonly parent: U32;
102
+ readonly order: U32;
103
+ readonly visitedCount: number;
104
+ }
105
+
106
+ /**
107
+ * SSSP result mirror.
108
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
109
+ * @public
110
+ */
111
+ export interface SsspResultLike {
112
+ readonly dist: NumericVector;
113
+ readonly predArc: U32;
114
+ }
115
+
116
+ /**
117
+ * Bellman-Ford result mirror.
118
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
119
+ * @public
120
+ */
121
+ export interface BellmanFordResultLike extends SsspResultLike {
122
+ readonly hasNegativeCycle: boolean;
123
+ }
124
+
125
+ /**
126
+ * Edge-score result mirror.
127
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
128
+ * @public
129
+ */
130
+ export interface EdgeScoresResultLike {
131
+ readonly scores: NumericVector;
132
+ }
133
+
134
+ /**
135
+ * APSP result mirror.
136
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
137
+ * @public
138
+ */
139
+ export interface ApspResultLike {
140
+ readonly dist: NumericVector;
141
+ readonly n: number;
142
+ }
143
+
144
+ /**
145
+ * k-core result mirror.
146
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
147
+ * @public
148
+ */
149
+ export interface CorenessResultLike {
150
+ readonly coreness: U32;
151
+ }
152
+
153
+ /**
154
+ * Minimum-spanning-tree result mirror.
155
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
156
+ * @public
157
+ */
158
+ export interface MstResultLike {
159
+ readonly edges: U32;
160
+ readonly totalWeight: number;
161
+ }
162
+
163
+ /**
164
+ * Community result mirror (Louvain).
165
+ * Exported: published mirror; re-exported from src/index.ts at P3-T3.
166
+ * @public
167
+ */
168
+ export interface CommunityResultLike extends LabelResultLike {
169
+ readonly modularity: number;
170
+ }
171
+
172
+ /**
173
+ * Spec 9.2 AlgorithmAccelerator, verbatim (every member optional; option types are CpuAlgorithmOptions until A2).
174
+ * Exported: published mirror (spec 9.2, D27); re-exported from src/index.ts at P3-T3.
175
+ * @public
176
+ */
177
+ export interface AlgorithmAccelerator {
178
+ readonly kind: string;
179
+ pageRank?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<PageRankResultLike>;
180
+ personalizedPageRank?(
181
+ s: GraphSnapshot,
182
+ personalization: F32 | F64,
183
+ options?: CpuAlgorithmOptions,
184
+ ): Promise<PageRankResultLike>;
185
+ hits?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<HitsResultLike>;
186
+ eigenvectorCentrality?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<ScoresResultLike>;
187
+ katzCentrality?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<ScoresResultLike>;
188
+ connectedComponents?(s: GraphSnapshot): Promise<LabelResultLike>;
189
+ weaklyConnectedComponents?(s: GraphSnapshot): Promise<LabelResultLike>;
190
+ breadthFirstSearch?(s: GraphSnapshot, source: number, options?: CpuAlgorithmOptions): Promise<BfsResultLike>;
191
+ sssp?(s: GraphSnapshot, source: number, options?: CpuAlgorithmOptions): Promise<SsspResultLike>;
192
+ bellmanFord?(s: GraphSnapshot, source: number, options?: CpuAlgorithmOptions): Promise<BellmanFordResultLike>;
193
+ closenessCentrality?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<ScoresResultLike>;
194
+ betweennessCentrality?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<ScoresResultLike>;
195
+ edgeBetweennessCentrality?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<EdgeScoresResultLike>;
196
+ allPairsShortestPath?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<ApspResultLike>;
197
+ kCoreDecomposition?(s: GraphSnapshot): Promise<CorenessResultLike>;
198
+ triangleCount?(s: GraphSnapshot): Promise<{ readonly perNode: U32; readonly total: number }>;
199
+ labelPropagation?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<LabelResultLike>;
200
+ minimumSpanningTree?(s: GraphSnapshot): Promise<MstResultLike>;
201
+ louvain?(s: GraphSnapshot, options?: CpuAlgorithmOptions): Promise<CommunityResultLike>;
202
+ release?(s: GraphSnapshot): void;
203
+ dispose?(): void;
204
+ }
205
+
206
+ // ---- the package's own accelerator surface (spec 3.3); grows one method per shipped algorithm from P7
207
+
208
+ /**
209
+ * Spec 3.3 AcceleratorOptions, verbatim.
210
+ * Exported: consumed by src/accelerator.ts (P3-T3); re-exported from src/index.ts at P3-T3.
211
+ * @public
212
+ */
213
+ export interface AcceleratorOptions {
214
+ readonly layout?: GpuLayoutTuning | undefined;
215
+ readonly algorithms?:
216
+ | {
217
+ readonly betweenness?:
218
+ { readonly k?: number | undefined; readonly sources?: readonly number[] | undefined } | undefined;
219
+ }
220
+ | undefined;
221
+ }
222
+
223
+ /**
224
+ * The injectable object (spec 3.3); at P3 it carries forceAtlas2, release and dispose -- the algorithm members
225
+ * arrive with P7+.
226
+ * Exported: implemented by src/accelerator.ts (P3-T3); re-exported from src/index.ts at P3-T3.
227
+ * @public
228
+ */
229
+ export interface GpuAccelerator extends AlgorithmAccelerator, LayoutAccelerator {
230
+ readonly kind: "webgpu";
231
+ readonly ctx: GpuContext;
232
+ readonly options: Readonly<AcceleratorOptions>;
233
+ forceAtlas2(options?: ForceAtlas2Options): GpuLayoutSimulation<ForceAtlas2Options, ForceAtlas2Stats>;
234
+ release(s: GraphSnapshot): void;
235
+ dispose(): void;
236
+ }
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Context and capability types (spec 2.2, 3.3; contract 3.3). Types only: the file imports the error class
3
+ * as a type, so every layer may `import type` from it without a value edge (the src/types zone of the
4
+ * package eslint config). P0-T3 wrote AdapterInfoLike and AdapterSummary; P1-T1 completes the file.
5
+ */
6
+
7
+ import type { WebGpuGraphError } from "../errors.js";
8
+
9
+ /** The limits `"raise"` takes from the adapter (spec 2.2); maxComputeWorkgroupsPerDimension is deliberately absent. */
10
+ export type RaisableLimit =
11
+ | "maxBufferSize"
12
+ | "maxStorageBufferBindingSize"
13
+ | "maxStorageBuffersPerShaderStage"
14
+ | "maxComputeWorkgroupStorageSize"
15
+ | "maxComputeInvocationsPerWorkgroup"
16
+ | "maxComputeWorkgroupSizeX";
17
+
18
+ /** How `create()` builds `requiredLimits` (spec 2.2 step 3). */
19
+ export type LimitPolicy = "default" | "raise" | Readonly<Partial<Record<RaisableLimit, number>>>;
20
+
21
+ /** Options of GpuContext.create (spec 2.2). */
22
+ export interface GpuContextOptions {
23
+ /** browser: navigator.gpu; Node: the handle of createNodeGpu(). */
24
+ readonly gpu?: GPU | undefined;
25
+ /** Skips requestAdapter(); the adapter must be UNUSED (spec 2.2 step 1). */
26
+ readonly adapter?: GPUAdapter | undefined;
27
+ /** Adopts a device the caller owns (ownsDevice false). */
28
+ readonly device?: GPUDevice | undefined;
29
+ /** Default "high-performance". */
30
+ readonly powerPreference?: GPUPowerPreference | undefined;
31
+ /** Default false; true -> E_SOFTWARE_ONLY instead of a device on lavapipe / SwiftShader. */
32
+ readonly rejectSoftware?: boolean | undefined;
33
+ /** Default "raise". */
34
+ readonly limits?: LimitPolicy | undefined;
35
+ /** Default ["subgroups", "timestamp-query"]; requested only when the adapter has them. */
36
+ readonly optionalFeatures?: readonly GPUFeatureName[] | undefined;
37
+ /** Default []; a missing one -> E_NO_DEVICE. */
38
+ readonly requiredFeatures?: readonly GPUFeatureName[] | undefined;
39
+ /** The device label and the context label (default "webgpu-graph-algorithms"). */
40
+ readonly label?: string | undefined;
41
+ /** The uncapturederror sink; default: keep the last error and throw it from the next public call (spec 5.7). */
42
+ readonly onError?: ((error: WebGpuGraphError) => void) | undefined;
43
+ /** Default 2: console.warn once when more snapshots than this are resident (spec 4.1). */
44
+ readonly warnUnreleasedSnapshots?: number | undefined;
45
+ /** CONTRACT DECISION: set by the ./browser and ./node entries ("browser" / "node"), never by sniffing globals (spec 2.2 step 4); consumers leave it unset ("unknown"). */
46
+ readonly runtime?: "browser" | "node" | "unknown" | undefined;
47
+ }
48
+
49
+ /** The structural subset of GPUAdapterInfo the package reads (CONTRACT DECISION: structural so tests can fake it without the __brand of @webgpu/types). */
50
+ export interface AdapterInfoLike {
51
+ readonly vendor: string;
52
+ readonly architecture: string;
53
+ readonly device: string;
54
+ readonly description: string;
55
+ readonly isFallbackAdapter?: boolean | undefined;
56
+ readonly subgroupMinSize?: number | undefined;
57
+ readonly subgroupMaxSize?: number | undefined;
58
+ }
59
+
60
+ /** What the app displays or logs about an adapter (spec 2.2). */
61
+ export interface AdapterSummary {
62
+ readonly vendor: string;
63
+ readonly architecture: string;
64
+ readonly device: string;
65
+ readonly description: string;
66
+ readonly software: boolean;
67
+ readonly subgroupMinSize: number;
68
+ readonly subgroupMaxSize: number;
69
+ readonly features: readonly string[];
70
+ readonly limits: Readonly<Record<string, number>>;
71
+ }
72
+
73
+ /** Result of GpuContext.probe (spec 2.2); `adapter` is the UNUSED adapter to pass to create({ adapter }). */
74
+ export interface ProbeResult {
75
+ readonly ok: boolean;
76
+ readonly code: "OK" | "E_NO_WEBGPU" | "E_NO_ADAPTER" | "E_SOFTWARE_ONLY";
77
+ readonly reason: string | null;
78
+ readonly adapter: GPUAdapter | null;
79
+ readonly summary: AdapterSummary | null;
80
+ }
81
+
82
+ /** Options of GpuContext.probe (spec 2.2). `gpu` may be undefined so an app can pass `navigator.gpu` without a guard: undefined -> E_NO_WEBGPU. */
83
+ export interface ProbeOptions {
84
+ readonly gpu: GPU | undefined;
85
+ readonly powerPreference?: GPUPowerPreference | undefined;
86
+ readonly rejectSoftware?: boolean | undefined;
87
+ }
88
+
89
+ /** The limits every planner reads; GPUSupportedLimits is structurally assignable to it (CONTRACT DECISION: planners take PlanCaps so faked tables need no cast). */
90
+ export interface PlanLimits {
91
+ readonly maxBufferSize: number;
92
+ readonly maxStorageBufferBindingSize: number;
93
+ readonly maxStorageBuffersPerShaderStage: number;
94
+ readonly minStorageBufferOffsetAlignment: number;
95
+ readonly minUniformBufferOffsetAlignment: number;
96
+ readonly maxComputeWorkgroupsPerDimension: number;
97
+ readonly maxComputeInvocationsPerWorkgroup: number;
98
+ readonly maxComputeWorkgroupSizeX: number;
99
+ readonly maxComputeWorkgroupStorageSize: number;
100
+ readonly maxUniformBufferBindingSize: number;
101
+ }
102
+
103
+ /** The capability record every planner and kernel reads (spec 3.3). */
104
+ export interface GpuCaps {
105
+ /** device.limits (never adapter.limits, spec 2.2 step 4). */
106
+ readonly limits: GPUSupportedLimits;
107
+ /** device.features. */
108
+ readonly features: ReadonlySet<string>;
109
+ /** navigator.gpu.wgslLanguageFeatures / the Dawn equivalent; informational only (never relied on). */
110
+ readonly wgslFeatures: ReadonlySet<string>;
111
+ /** 0 when the "subgroups" feature is absent from the device. */
112
+ readonly subgroupMinSize: number;
113
+ /** 0 when the "subgroups" feature is absent from the device. */
114
+ readonly subgroupMaxSize: number;
115
+ readonly software: boolean;
116
+ readonly runtime: "browser" | "node" | "unknown";
117
+ readonly vendor: string;
118
+ readonly architecture: string;
119
+ readonly device: string;
120
+ readonly description: string;
121
+ }
122
+
123
+ /** What the pure planners need of GpuCaps: `limits` narrowed to PlanLimits plus the four scalar facts. A GpuCaps IS a PlanCaps. */
124
+ export interface PlanCaps {
125
+ readonly limits: PlanLimits;
126
+ readonly features: ReadonlySet<string>;
127
+ readonly subgroupMinSize: number;
128
+ readonly subgroupMaxSize: number;
129
+ readonly software: boolean;
130
+ }
131
+
132
+ /** Mutable test-build flags on a context (@internal; set by test/setup/gpu.ts from GRAPHTY_GPU_INSPECT, spec 11.9 item 2). */
133
+ export interface GpuDebugFlags {
134
+ inspect: boolean;
135
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * The layout-facing public types (spec 3.3, 7.19): the stats records, the GPU simulation interface that extends the
3
+ * design-14.3 LayoutSimulation mirror, the run options and the GPU-only tuning knobs. Types only.
4
+ */
5
+
6
+ import type { F32, GraphSnapshot, NodeMask } from "@graphty/graph-format";
7
+
8
+ import type { LayoutSimulation } from "./accelerator.js";
9
+
10
+ /** Spec 3.3 LayoutStatsBase, verbatim; the three grid fields are null on the exact tier (P3 always). */
11
+ export interface LayoutStatsBase {
12
+ readonly iteration: number;
13
+ readonly meanDisplacement: number;
14
+ readonly rmsRadius: number;
15
+ readonly layoutRadius: number;
16
+ readonly centroid: readonly [number, number, number];
17
+ readonly repulsionTier: "exact" | "grid";
18
+ readonly maxCellOccupancy: number | null;
19
+ readonly outsideGrid: number | null;
20
+ readonly msPerIteration: number | null;
21
+ }
22
+
23
+ /**
24
+ * One per-iteration trace record of the last completed batch (spec 3.3 ForceAtlas2Stats.trace element).
25
+ * Exported: the element type of ForceAtlas2Stats.trace; re-exported from src/index.ts at P3-T3.
26
+ * @public
27
+ */
28
+ export interface ForceAtlas2TraceRecord {
29
+ readonly swing: number;
30
+ readonly traction: number;
31
+ readonly speed: number;
32
+ readonly speedEfficiency: number;
33
+ readonly meanDisplacement: number;
34
+ readonly settledCount: number;
35
+ }
36
+
37
+ /** Spec 3.3 ForceAtlas2Stats, verbatim. */
38
+ export interface ForceAtlas2Stats extends LayoutStatsBase {
39
+ readonly swing: number;
40
+ readonly traction: number;
41
+ readonly speed: number;
42
+ readonly speedEfficiency: number;
43
+ readonly trace: ReadonlyArray<ForceAtlas2TraceRecord>;
44
+ }
45
+
46
+ /** Options of GpuLayoutSimulation.run (spec 3.3). */
47
+ export interface RunOptions {
48
+ readonly maxIter?: number | undefined;
49
+ readonly batch?: number | undefined;
50
+ readonly signal?: AbortSignal | undefined;
51
+ }
52
+
53
+ /** Spec 3.3 GpuLayoutSimulation, verbatim (LayoutSimulation is the design-14.3 mirror of accelerator.ts). */
54
+ export interface GpuLayoutSimulation<Options, Stats extends LayoutStatsBase> extends LayoutSimulation {
55
+ load(snapshot: GraphSnapshot, positions: F32): void;
56
+ /**
57
+ * Submits k iterations; resolves when their batch has been read back into `positions`. With `maxInFlight`
58
+ * batches in flight the call COALESCES: nothing is queued and the OLDEST pending batch's promise is returned
59
+ * (spec 7.19 item 3).
60
+ * @param iterations - the number of iterations to submit (default `iterationsPerStep`)
61
+ * @returns resolves when the batch carrying them has landed in the owner's array
62
+ */
63
+ step(iterations?: number): Promise<void>;
64
+ readonly settled: boolean;
65
+ setFixed(mask: NodeMask): void;
66
+ setPosition(index: number, x: number, y: number, z: number): void;
67
+ dispose(): void;
68
+ readonly inFlight: number;
69
+ readonly iterationsDone: number;
70
+ readonly stats: Stats;
71
+ flush(): Promise<void>;
72
+ reheat(): void;
73
+ setParams(patch: Partial<Options>): void;
74
+ run(options?: RunOptions): Promise<Stats>;
75
+ inspect?(name: string): Promise<Float32Array | Uint32Array>;
76
+ }
77
+
78
+ /**
79
+ * Spec 3.3 GpuLayoutTuning, verbatim; the grid knobs are accepted and stored in P3 but only `repulsion`,
80
+ * `exactMaxNodes`, `deterministic` and `compat` have an effect (grid tier = P4).
81
+ */
82
+ export interface GpuLayoutTuning {
83
+ readonly repulsion?: "exact" | "grid" | "auto" | undefined;
84
+ readonly exactMaxNodes?: number | undefined;
85
+ readonly nearMax?: number | undefined;
86
+ readonly deterministic?: boolean | undefined;
87
+ readonly gridMax2D?: number | undefined;
88
+ readonly gridMax3D?: number | undefined;
89
+ readonly extentFactor?: number | undefined;
90
+ readonly compat?: "paper" | "networkx" | undefined;
91
+ }
92
+
93
+ /** The resolved tuning record (defaults from constants.ts LAYOUT_TUNING_DEFAULTS applied). */
94
+ export interface ResolvedLayoutTuning {
95
+ readonly repulsion: "exact" | "grid" | "auto";
96
+ readonly exactMaxNodes: number;
97
+ readonly nearMax: number;
98
+ readonly deterministic: boolean;
99
+ readonly gridMax2D: number;
100
+ readonly gridMax3D: number;
101
+ readonly extentFactor: number;
102
+ readonly compat: "paper" | "networkx";
103
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The two types the memory AND the kernel layers share (spec 4.1, 4.2; contract 3.3 CONTRACT DECISION):
3
+ * they live here so src/kernel/kernel.ts never imports src/memory/** for a type and the layer graph has no
4
+ * P1 cycle (test/layers.test.ts). Types only; GPUBuffer is the ambient @webgpu/types global.
5
+ */
6
+
7
+ /** One 64-arc-aligned window of colIdx / weights (spec 4.2). P1-P3 PLAN windows; executing them is P4. */
8
+ export interface ArcWindow {
9
+ readonly start: number;
10
+ readonly end: number;
11
+ readonly rowFirst: number;
12
+ readonly rowLast: number;
13
+ readonly bufferIndex: number;
14
+ readonly offset: number;
15
+ }
16
+
17
+ /** A storage-buffer range (spec 4.1); `window` is non-null only for a binding of one arc window. */
18
+ export interface Binding {
19
+ readonly buffer: GPUBuffer;
20
+ readonly offset: number;
21
+ readonly size: number;
22
+ readonly window: ArcWindow | null;
23
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The option records of the layouts (spec 9.3, 7.14): structural mirrors of @graphty/layout's option types (D27),
3
+ * copied field for field so a `ForceAtlas2Options` object the element parses is accepted here without a cast. Types
4
+ * only: this file imports nothing at runtime.
5
+ */
6
+
7
+ import type { F32, NodeId, NodeMask } from "@graphty/graph-format";
8
+
9
+ /** Design 14.3 CommonLayoutOptions, mirrored verbatim. */
10
+ export interface CommonLayoutOptions {
11
+ readonly dim?: 2 | 3 | undefined;
12
+ readonly scale?: number | undefined;
13
+ readonly center?: ArrayLike<number> | undefined;
14
+ readonly seed?: number | null | undefined;
15
+ }
16
+
17
+ /** Spec 9.3 SimulationOptions, mirrored verbatim (layout-owned; the CPU simulations ignore maxInFlight). */
18
+ export interface SimulationOptions {
19
+ readonly settleThreshold?: number | undefined;
20
+ readonly settleWindow?: number | undefined;
21
+ readonly iterationsPerStep?: number | undefined;
22
+ readonly maxInFlight?: number | undefined;
23
+ }
24
+
25
+ /**
26
+ * Spec 9.3 ForceAtlas2Options, mirrored verbatim (same names and defaults as
27
+ * layout/src/layouts/force-directed/forceatlas2.ts lines 26-42).
28
+ */
29
+ export interface ForceAtlas2Options extends CommonLayoutOptions, SimulationOptions {
30
+ readonly maxIter?: number | undefined;
31
+ readonly jitterTolerance?: number | undefined;
32
+ readonly scalingRatio?: number | undefined;
33
+ readonly gravity?: number | undefined;
34
+ readonly strongGravity?: boolean | undefined;
35
+ readonly distributedAction?: boolean | undefined;
36
+ readonly linlog?: boolean | undefined;
37
+ readonly nodeMass?: F32 | string | Readonly<Record<NodeId, number>> | null | undefined;
38
+ readonly nodeSize?: F32 | string | Readonly<Record<NodeId, number>> | null | undefined;
39
+ readonly weight?: boolean | string | null | undefined;
40
+ readonly dissuadeHubs?: boolean | undefined;
41
+ }
42
+
43
+ /** Spec 9.3 FruchtermanReingoldOptions, mirrored for the LayoutAccelerator mirror's method signature (P5 implements it). */
44
+ export interface FruchtermanReingoldOptions extends CommonLayoutOptions, SimulationOptions {
45
+ readonly k?: number | null | undefined;
46
+ readonly iterations?: number | undefined;
47
+ readonly fixed?: NodeMask | string | null | undefined;
48
+ }
49
+
50
+ /** Spec 9.3 SpringElectricalOptions, mirrored for the LayoutAccelerator mirror's method signature (P5 implements it). */
51
+ export interface SpringElectricalOptions extends CommonLayoutOptions, SimulationOptions {
52
+ readonly springLength?: number | undefined;
53
+ readonly springCoefficient?: number | undefined;
54
+ readonly gravity?: number | undefined;
55
+ readonly dragCoefficient?: number | undefined;
56
+ readonly timeStep?: number | undefined;
57
+ }
58
+
59
+ /**
60
+ * The resolved (defaults applied) ForceAtlas2 option record the simulation keeps; every field present.
61
+ * Exported: consumed by src/layouts/forceatlas2.ts (P3-T2, resolveForceAtlas2Options) and the option tests.
62
+ * @public
63
+ */
64
+ export interface ResolvedForceAtlas2Options {
65
+ readonly maxIter: number;
66
+ readonly jitterTolerance: number;
67
+ readonly scalingRatio: number;
68
+ readonly gravity: number;
69
+ readonly strongGravity: boolean;
70
+ readonly distributedAction: boolean;
71
+ readonly linlog: boolean;
72
+ readonly nodeMass: F32 | string | Readonly<Record<NodeId, number>> | null;
73
+ readonly nodeSize: F32 | string | Readonly<Record<NodeId, number>> | null;
74
+ readonly weight: boolean | string | null;
75
+ readonly dissuadeHubs: boolean;
76
+ readonly dim: 2 | 3;
77
+ readonly scale: number;
78
+ readonly center: readonly [number, number, number];
79
+ readonly seed: number | null;
80
+ readonly settleThreshold: number;
81
+ readonly settleWindow: number;
82
+ readonly iterationsPerStep: number;
83
+ readonly maxInFlight: number;
84
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The run options every algorithm function accepts beside its own (spec 3.3, design 10.7; contract 3.3).
3
+ * Types only.
4
+ */
5
+
6
+ /** Options every algorithm function accepts in addition to its own (spec 3.3, design 10.7). */
7
+ export interface GpuRunOptions {
8
+ /** A preallocated destination of exact length; E_INVALID_ARGUMENT when the length does not match. */
9
+ readonly dest?: Float32Array | Uint32Array | undefined;
10
+ /** Checked between batches; E_ABORTED. */
11
+ readonly signal?: AbortSignal | undefined;
12
+ readonly onProgress?: ((done: number, total: number) => void) | undefined;
13
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The `degree` kernel body (contract 4.5; spec 6 row 3, 11.5): the out-degree of every row of `[P.start, P.end)`
3
+ * through the row-walking gather with the USE_PERM dummy pattern, counting the arcs of the bound window whose
4
+ * neighbour index is a valid node; `P.accumulate == 1` adds into `out[i]` instead of overwriting (the P4 windowed
5
+ * loop). Bindings, overrides and the `RangeParams` block come from the registry entry (src/kernels.ts); WG,
6
+ * USE_PERM and `linear_id` from the prelude. The text is normative: test/helpers/sabotage.ts mutates it textually,
7
+ * so it is copied from the contract and never re-derived or restyled.
8
+ */
9
+ export const degreeWgsl = /* wgsl */ `
10
+ @compute @workgroup_size(WG)
11
+ fn degree(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
12
+ let row = linear_id(wid, lid.x) + P.start;
13
+ if (row >= P.end) { return; }
14
+ let i = select(row, perm[row], USE_PERM);
15
+ let a0 = max(rowPtr[i], P.arcBase);
16
+ let a1 = min(rowPtr[i + 1u], P.arcEnd);
17
+ var d = 0u;
18
+ for (var arc = a0; arc < a1; arc = arc + 1u) {
19
+ let nbr = colIdx[arc - P.arcBase]; // \`target\` is a WGSL reserved word (spec 16.2); never use it as an identifier
20
+ d = d + select(0u, 1u, nbr < P.n);
21
+ }
22
+ out[i] = select(d, out[i] + d, P.accumulate == 1u);
23
+ }
24
+ `;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * K2 of the ForceAtlas2 iteration, `fa2-attraction` (spec 7.5; contract 4.5): the thread-per-row gather of the
3
+ * attraction force over the undirected CSR rows (both arcs present, so the sum is symmetric with no atomics), the
4
+ * linear or linlog law, the optional weights, the distributed-action division by the mass in `pos.w`, written as
5
+ * the FIRST writer of `force` each iteration. P3 ships the thread-per-row tier over `[tierStart, tierEnd)` = `[0, n)`
6
+ * with `USE_PERM = false`; the subgroup / workgroup tiers arrive with P4 (`TIER`).
7
+ *
8
+ * Body only (spec 3.5, D9); normative text (contract 4.5); the K2 sabotage mutations (P3-T5) are textual edits of it.
9
+ */
10
+
11
+ /** The K2 body: entry point `attraction`; an early return is legal here because no barrier follows (spec 3.5 rule 1). */
12
+ export const fa2AttractionWgsl = /* wgsl */ `fn store_force(i: u32, f: vec3f) {
13
+ force[3u * i] = f.x;
14
+ force[3u * i + 1u] = f.y;
15
+ force[3u * i + 2u] = f.z;
16
+ }
17
+
18
+ @compute @workgroup_size(WG)
19
+ fn attraction(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
20
+ let row = linear_id(wid, lid.x) + P.tierStart;
21
+ if (row >= P.tierEnd) { return; } // no barrier follows in this tier (3.5 rule 1)
22
+ let i = select(row, perm[row], USE_PERM);
23
+ let pi = pos[i]; // xyz + mass in one load (D23)
24
+ var f = vec3f(0.0);
25
+ for (var a = rowPtr[i]; a < rowPtr[i + 1u]; a = a + 1u) {
26
+ let j = colIdx[a];
27
+ if (j == i) { continue; } // a self-loop exerts no force
28
+ var w = 1.0;
29
+ if (HAS_WEIGHTS) { w = weights[a]; }
30
+ let d = pos[j].xyz - pi.xyz; // toward j
31
+ let len = max(length(d), FA2_DIST_FLOOR);
32
+ let mag = select(w, w * log(1.0 + len) / len, LINLOG); // linear: |F| = w len; linlog: |F| = w log(1 + len)
33
+ f = f + d * mag;
34
+ }
35
+ if (DISTRIBUTED) { f = f / pi.w; }
36
+ store_force(i, f); // overwrites: attraction is the first writer of force each iteration
37
+ }`;