@graphty/webgpu-graph-algorithms 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +45 -36
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{context-E6iKaeuJ.js → context-CRbw2Wyo.js} +178 -19
  4. package/dist/chunks/{context-E6iKaeuJ.js.map → context-CRbw2Wyo.js.map} +1 -1
  5. package/dist/node.js +1 -1
  6. package/dist/src/accelerator.d.ts +9 -6
  7. package/dist/src/accelerator.d.ts.map +1 -1
  8. package/dist/src/accelerator.js +85 -6
  9. package/dist/src/accelerator.js.map +1 -1
  10. package/dist/src/algorithms/components.d.ts +30 -0
  11. package/dist/src/algorithms/components.d.ts.map +1 -0
  12. package/dist/src/algorithms/components.js +300 -0
  13. package/dist/src/algorithms/components.js.map +1 -0
  14. package/dist/src/algorithms/pagerank.d.ts +39 -0
  15. package/dist/src/algorithms/pagerank.d.ts.map +1 -0
  16. package/dist/src/algorithms/pagerank.js +298 -0
  17. package/dist/src/algorithms/pagerank.js.map +1 -0
  18. package/dist/src/algorithms/power-iteration.d.ts +109 -0
  19. package/dist/src/algorithms/power-iteration.d.ts.map +1 -0
  20. package/dist/src/algorithms/power-iteration.js +206 -0
  21. package/dist/src/algorithms/power-iteration.js.map +1 -0
  22. package/dist/src/algorithms/scope.d.ts +26 -0
  23. package/dist/src/algorithms/scope.d.ts.map +1 -0
  24. package/dist/src/algorithms/scope.js +41 -0
  25. package/dist/src/algorithms/scope.js.map +1 -0
  26. package/dist/src/algorithms/spectral.d.ts +50 -0
  27. package/dist/src/algorithms/spectral.d.ts.map +1 -0
  28. package/dist/src/algorithms/spectral.js +247 -0
  29. package/dist/src/algorithms/spectral.js.map +1 -0
  30. package/dist/src/index.d.ts +4 -0
  31. package/dist/src/index.d.ts.map +1 -1
  32. package/dist/src/index.js +4 -0
  33. package/dist/src/index.js.map +1 -1
  34. package/dist/src/kernel/dispatch.d.ts +4 -1
  35. package/dist/src/kernel/dispatch.d.ts.map +1 -1
  36. package/dist/src/kernel/dispatch.js +12 -5
  37. package/dist/src/kernel/dispatch.js.map +1 -1
  38. package/dist/src/kernels.d.ts +20 -4
  39. package/dist/src/kernels.d.ts.map +1 -1
  40. package/dist/src/kernels.js +172 -2
  41. package/dist/src/kernels.js.map +1 -1
  42. package/dist/src/memory/residency.d.ts.map +1 -1
  43. package/dist/src/memory/residency.js +164 -11
  44. package/dist/src/memory/residency.js.map +1 -1
  45. package/dist/src/primitives/core-shape.d.ts +41 -0
  46. package/dist/src/primitives/core-shape.d.ts.map +1 -0
  47. package/dist/src/primitives/core-shape.js +89 -0
  48. package/dist/src/primitives/core-shape.js.map +1 -0
  49. package/dist/src/primitives/segmented-reduce.d.ts.map +1 -1
  50. package/dist/src/primitives/segmented-reduce.js +4 -30
  51. package/dist/src/primitives/segmented-reduce.js.map +1 -1
  52. package/dist/src/primitives/spmv.d.ts +56 -0
  53. package/dist/src/primitives/spmv.d.ts.map +1 -0
  54. package/dist/src/primitives/spmv.js +101 -0
  55. package/dist/src/primitives/spmv.js.map +1 -0
  56. package/dist/src/types/accelerator.d.ts +14 -2
  57. package/dist/src/types/accelerator.d.ts.map +1 -1
  58. package/dist/src/types/algorithms.d.ts +73 -0
  59. package/dist/src/types/algorithms.d.ts.map +1 -0
  60. package/dist/src/types/algorithms.js +17 -0
  61. package/dist/src/types/algorithms.js.map +1 -0
  62. package/dist/src/wgsl/pr-finalize.wgsl.d.ts +11 -0
  63. package/dist/src/wgsl/pr-finalize.wgsl.d.ts.map +1 -0
  64. package/dist/src/wgsl/pr-finalize.wgsl.js +36 -0
  65. package/dist/src/wgsl/pr-finalize.wgsl.js.map +1 -0
  66. package/dist/src/wgsl/pr-scale.wgsl.d.ts +14 -0
  67. package/dist/src/wgsl/pr-scale.wgsl.d.ts.map +1 -0
  68. package/dist/src/wgsl/pr-scale.wgsl.js +48 -0
  69. package/dist/src/wgsl/pr-scale.wgsl.js.map +1 -0
  70. package/dist/src/wgsl/spmv-pull.wgsl.d.ts +15 -0
  71. package/dist/src/wgsl/spmv-pull.wgsl.d.ts.map +1 -0
  72. package/dist/src/wgsl/spmv-pull.wgsl.js +47 -0
  73. package/dist/src/wgsl/spmv-pull.wgsl.js.map +1 -0
  74. package/dist/src/wgsl/wcc-compress.wgsl.d.ts +9 -0
  75. package/dist/src/wgsl/wcc-compress.wgsl.d.ts.map +1 -0
  76. package/dist/src/wgsl/wcc-compress.wgsl.js +26 -0
  77. package/dist/src/wgsl/wcc-compress.wgsl.js.map +1 -0
  78. package/dist/src/wgsl/wcc-link-edges.wgsl.d.ts +13 -0
  79. package/dist/src/wgsl/wcc-link-edges.wgsl.d.ts.map +1 -0
  80. package/dist/src/wgsl/wcc-link-edges.wgsl.js +46 -0
  81. package/dist/src/wgsl/wcc-link-edges.wgsl.js.map +1 -0
  82. package/dist/src/wgsl/wcc-link-sample.wgsl.d.ts +11 -0
  83. package/dist/src/wgsl/wcc-link-sample.wgsl.d.ts.map +1 -0
  84. package/dist/src/wgsl/wcc-link-sample.wgsl.js +45 -0
  85. package/dist/src/wgsl/wcc-link-sample.wgsl.js.map +1 -0
  86. package/dist/src/wgsl/wcc-sample.wgsl.d.ts +10 -0
  87. package/dist/src/wgsl/wcc-sample.wgsl.d.ts.map +1 -0
  88. package/dist/src/wgsl/wcc-sample.wgsl.js +18 -0
  89. package/dist/src/wgsl/wcc-sample.wgsl.js.map +1 -0
  90. package/dist/tsconfig.build.tsbuildinfo +1 -1
  91. package/dist/webgpu-graph-algorithms.js +1550 -29
  92. package/dist/webgpu-graph-algorithms.js.map +1 -1
  93. package/package.json +1 -1
  94. package/src/accelerator.ts +101 -7
  95. package/src/algorithms/components.ts +348 -0
  96. package/src/algorithms/pagerank.ts +343 -0
  97. package/src/algorithms/power-iteration.ts +278 -0
  98. package/src/algorithms/scope.ts +52 -0
  99. package/src/algorithms/spectral.ts +300 -0
  100. package/src/index.ts +18 -0
  101. package/src/kernel/dispatch.ts +12 -5
  102. package/src/kernels.ts +206 -5
  103. package/src/memory/residency.ts +200 -11
  104. package/src/primitives/core-shape.ts +103 -0
  105. package/src/primitives/segmented-reduce.ts +4 -36
  106. package/src/primitives/spmv.ts +155 -0
  107. package/src/types/accelerator.ts +28 -2
  108. package/src/types/algorithms.ts +82 -0
  109. package/src/wgsl/pr-finalize.wgsl.ts +36 -0
  110. package/src/wgsl/pr-scale.wgsl.ts +48 -0
  111. package/src/wgsl/spmv-pull.wgsl.ts +47 -0
  112. package/src/wgsl/wcc-compress.wgsl.ts +26 -0
  113. package/src/wgsl/wcc-link-edges.wgsl.ts +46 -0
  114. package/src/wgsl/wcc-link-sample.wgsl.ts +45 -0
  115. package/src/wgsl/wcc-sample.wgsl.ts +18 -0
@@ -1 +1 @@
1
- {"version":3,"file":"webgpu-graph-algorithms.js","sources":["../src/kernel/dispatch.ts","../src/kernel/struct-block.ts","../src/wgsl/degree.wgsl.ts","../src/wgsl/fa2-attraction.wgsl.ts","../src/wgsl/fa2-integrate.wgsl.ts","../src/wgsl/fa2-repulsion-exact.wgsl.ts","../src/wgsl/fa2-speed-finalize.wgsl.ts","../src/wgsl/fa2-stats-finalize.wgsl.ts","../src/wgsl/fa2-to-scene.wgsl.ts","../src/wgsl/fill.wgsl.ts","../src/wgsl/reduce.wgsl.ts","../src/wgsl/segmented-reduce.wgsl.ts","../src/kernels.ts","../src/algorithms/degree.ts","../src/kernel/batch.ts","../src/kernel/uniform-ring.ts","../src/layouts/seed.ts","../src/layouts/force-simulation.ts","../src/layouts/inputs.ts","../src/layouts/repulsion-exact.ts","../src/layouts/forceatlas2.ts","../src/accelerator.ts"],"sourcesContent":["/**\n * Dispatch planning (spec 5.2; contract 3.9): the 16,776,960 rule. `ceil(items / wg)` workgroups as a 1D dispatch\n * while the count fits one dimension (65,535 groups x 256 = 16,776,960 items, NOT 2^24), else a 2D grid whose\n * kernels linearise their id with the prelude's `linear_id()` and guard `id >= items`. Pure functions with no\n * device: every branch is unit-tested against faked capability tables.\n */\n\nimport { MAX_WORKGROUPS_PER_DIM } from \"../constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type PlanCaps } from \"../types/context.js\";\n\n/** A dispatch shape (spec 5.2). `stride` is the grid-stride step (null for plain 1D / 2D plans). */\nexport interface DispatchPlan {\n readonly x: number;\n readonly y: number;\n readonly z: 1;\n readonly items: number;\n readonly stride: number | null;\n}\n\n/**\n * The per-dimension workgroup limit a plan honours. PLAN DECISION: the minimum of the spec constant and the table's\n * `maxComputeWorkgroupsPerDimension`; the two are asserted equal on a real device at create() (spec 2.2), so every\n * capability table of the tests yields the same plans and a faked table below the constant is still honoured.\n * @param caps - the capability table\n * @returns the limit\n */\nfunction perDimension(caps: PlanCaps): number {\n return Math.min(MAX_WORKGROUPS_PER_DIM, caps.limits.maxComputeWorkgroupsPerDimension);\n}\n\n/**\n * Validates a non-negative integer argument.\n * @param argument - the argument name\n * @param value - the value\n */\nfunction assertCount(argument: string, value: number): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${argument} must be a non-negative integer, got ${value}`, {\n argument,\n value,\n expected: \"a non-negative integer\",\n });\n }\n}\n\n/**\n * Validates a workgroup size: a power of two >= 1 (the reduction trees of 4.3 need it). Arithmetic, no bit tricks.\n * @param wg - the workgroup size\n */\nfunction assertWorkgroupSize(wg: number): void {\n let rest = wg;\n while (Number.isInteger(rest) && rest > 1 && rest % 2 === 0) {\n rest /= 2;\n }\n if (rest !== 1) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `wg must be a power of two, got ${wg}`, {\n argument: \"wg\",\n value: wg,\n expected: \"a power of two >= 1\",\n });\n }\n}\n\n/**\n * The grid of `groups` workgroups: 1D up to the per-dimension limit, else `x = limit`, `y = ceil(groups / limit)`.\n * @param groups - the workgroup count\n * @param items - the item count the plan covers (recorded in the plan)\n * @param caps - the capability table\n * @returns the plan\n */\nfunction grid(groups: number, items: number, caps: PlanCaps): DispatchPlan {\n const limit = perDimension(caps);\n if (groups === 0) {\n return { x: 0, y: 1, z: 1, items, stride: null };\n }\n if (groups <= limit) {\n return { x: groups, y: 1, z: 1, items, stride: null };\n }\n const y = Math.ceil(groups / limit);\n if (y > limit) {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `${groups} workgroups exceed the 2D dispatch limit of ${limit * limit}`,\n {\n needed: groups,\n limit: limit * limit,\n path: \"dispatch\",\n algorithm: null,\n items,\n },\n );\n }\n return { x: limit, y, z: 1, items, stride: null };\n}\n\n/**\n * ceil(items / wg) groups as 1D up to MAX_WORKGROUPS_PER_DIM, else a 2D grid; items 0 -> { x: 0, y: 1 }; y above the limit -> E_TOO_LARGE.\n * @param items - the item count\n * @param wg - the workgroup size (a power of two)\n * @param caps - the capability table\n * @returns the plan\n */\nexport function plan1d(items: number, wg: number, caps: PlanCaps): DispatchPlan {\n assertCount(\"items\", items);\n assertWorkgroupSize(wg);\n return grid(Math.ceil(items / wg), items, caps);\n}\n\n/**\n * The 2D form for a group count (x = MAX_WORKGROUPS_PER_DIM, y = ceil(groups / x)); exported for the indirect finalize kernel's host twin (P4).\n * PLAN DECISION: plan1d's rule applied to a group count (spec 5.4: the finalize kernel uses \"the same rule as\n * plan1d\") -- 1D `{ x: groups, y: 1 }` up to the per-dimension limit and the `x = limit` split only above it, through\n * the same `grid()` as plan1d so the two cannot drift; P4's finalize WGSL mirrors exactly this rule. `items` of the\n * returned plan is `groups` (the caller knows its own wg); groups 0 -> { x: 0, y: 1 }.\n * @param groups - the workgroup count\n * @param caps - the capability table\n * @returns the plan\n */\nexport function plan2d(groups: number, caps: PlanCaps): DispatchPlan {\n assertCount(\"groups\", groups);\n return grid(groups, groups, caps);\n}\n\n/**\n * P7 (spec 5.2): groups = min(groups, maxGroups ?? (caps.software ? 64 : 4096)) with the kernel looping by stride. P1-P3: throws E_UNSUPPORTED { feature: \"planGridStride\" } (lead f).\n * PLAN DECISION: `maxGroups?` is spelled `?: number` rather than the contract's `?: number | undefined` because the\n * root ESLint rule no-duplicate-type-constituents rejects the explicit undefined on an optional parameter (the call\n * signature is identical).\n * @param items - the item count\n * @param wg - the workgroup size\n * @param caps - the capability table\n * @param maxGroups - the group cap\n */\nexport function planGridStride(items: number, wg: number, caps: PlanCaps, maxGroups?: number): DispatchPlan {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"planGridStride lands with the grid-stride kernels of P7 (spec 5.2)\", {\n feature: \"planGridStride\",\n hint: `items ${items}, wg ${wg}, maxGroups ${maxGroups ?? (caps.software ? 64 : 4096)}`,\n });\n}\n\n/**\n * P4 (spec 5.4): the (x, y, 1) args a device-side finalize kernel writes for a count. P1-P3: throws E_UNSUPPORTED { feature: \"planIndirect\" } (lead f).\n * @param count - the device-side count\n * @param wg - the workgroup size\n * @param caps - the capability table\n */\nexport function planIndirect(count: number, wg: number, caps: PlanCaps): DispatchPlan {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"planIndirect lands with the indirect dispatch of P4 (spec 5.4)\", {\n feature: \"planIndirect\",\n hint: `count ${count}, wg ${wg}, limit ${perDimension(caps)}`,\n });\n}\n\n/**\n * The workgroup count of a plan (x * y).\n * @param plan - the plan\n * @returns the count\n */\nexport function groupsOf(plan: DispatchPlan): number {\n return plan.x * plan.y;\n}\n","/**\n * UniformBlock (spec 5.3, D20): one field table generates BOTH the padded WGSL `struct` text spliced into a module\n * and the byte writer / reader the host uses, so the two cannot disagree. The layout is the strict WGSL layout\n * every runtime accepts (Chromium 139 lacks `uniform_buffer_standard_layout`): scalars 4-aligned, vec2 8-aligned,\n * vec4 16-aligned, no vec3, no bool, no arrays, and the total padded to a multiple of 16 (or to `padTo`) through an\n * explicit `@size` on the last member.\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { WGSL_RESERVED_WORDS } from \"./prelude.js\";\n\n/** Field types a block may hold; no vec3 (spec 5.3), no bool (not host-shareable), no arrays. */\nexport type UniformFieldType = \"u32\" | \"i32\" | \"f32\" | \"vec2f\" | \"vec2u\" | \"vec4f\" | \"vec4u\";\n/** One field. */\nexport type UniformField = readonly [name: string, type: UniformFieldType];\n/** The values written into or read from a block: scalars as numbers, vectors as number arrays of the vector's width. */\nexport type UniformValues = Readonly<Record<string, number | readonly number[]>>;\n\n/** The scalar a field is made of. */\ntype ScalarKind = \"u32\" | \"i32\" | \"f32\";\n\n/** Size, alignment and composition of each field type (WGSL 14.4.1). */\ninterface TypeInfo {\n readonly size: number;\n readonly align: number;\n readonly width: number;\n readonly scalar: ScalarKind;\n}\n\nconst TYPE_INFO: Readonly<Record<UniformFieldType, TypeInfo>> = Object.freeze({\n u32: { size: 4, align: 4, width: 1, scalar: \"u32\" },\n i32: { size: 4, align: 4, width: 1, scalar: \"i32\" },\n f32: { size: 4, align: 4, width: 1, scalar: \"f32\" },\n vec2f: { size: 8, align: 8, width: 2, scalar: \"f32\" },\n vec2u: { size: 8, align: 8, width: 2, scalar: \"u32\" },\n vec4f: { size: 16, align: 16, width: 4, scalar: \"f32\" },\n vec4u: { size: 16, align: 16, width: 4, scalar: \"u32\" },\n});\n\n/** One laid-out field. */\ninterface FieldLayout {\n readonly name: string;\n readonly type: UniformFieldType;\n readonly offset: number;\n readonly info: TypeInfo;\n}\n\nconst STRUCT_ALIGN = 16;\nconst IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst U32_LIMIT = 0xffffffff;\nconst I32_MIN = -2147483648;\nconst I32_MAX = 2147483647;\n\n/**\n * Rounds `value` up to the next multiple of `align` (arithmetic, never a bit trick: byte offsets are never operated\n * on bitwise, spec 3.6).\n * @param value - the value to round\n * @param align - the alignment, a positive integer\n * @returns the rounded value\n */\nfunction roundUp(value: number, align: number): number {\n return Math.ceil(value / align) * align;\n}\n\n/**\n * Validates a WGSL identifier for a struct or field name.\n * @param argument - the E_INVALID_ARGUMENT `argument` to report\n * @param name - the identifier\n */\nfunction assertIdentifier(argument: string, name: string): void {\n if (!IDENTIFIER.test(name) || WGSL_RESERVED_WORDS.includes(name)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock: \"${name}\" is not a usable WGSL identifier`, {\n argument,\n value: name,\n expected: \"a WGSL identifier that is not a reserved word\",\n });\n }\n}\n\n/**\n * Validates one scalar component of a value against its scalar kind.\n * @param field - the field name (for the error)\n * @param kind - the scalar kind\n * @param value - the component\n */\nfunction assertScalar(field: string, kind: ScalarKind, value: unknown): asserts value is number {\n if (typeof value !== \"number\") {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock: field \"${field}\" expects a number`, {\n argument: field,\n value,\n expected: kind,\n });\n }\n if (kind === \"u32\" && !(Number.isInteger(value) && value >= 0 && value <= U32_LIMIT)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock: field \"${field}\" is not a u32`, {\n argument: field,\n value,\n expected: \"an integer in [0, 4294967295]\",\n });\n }\n if (kind === \"i32\" && !(Number.isInteger(value) && value >= I32_MIN && value <= I32_MAX)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock: field \"${field}\" is not an i32`, {\n argument: field,\n value,\n expected: \"an integer in [-2147483648, 2147483647]\",\n });\n }\n}\n\n/**\n * Writes one scalar component little-endian.\n * @param view - the target view\n * @param kind - the scalar kind\n * @param offset - the byte offset\n * @param value - the component\n */\nfunction setScalar(view: DataView, kind: ScalarKind, offset: number, value: number): void {\n if (kind === \"u32\") {\n view.setUint32(offset, value, true);\n } else if (kind === \"i32\") {\n view.setInt32(offset, value, true);\n } else {\n view.setFloat32(offset, value, true);\n }\n}\n\n/**\n * Reads one scalar component little-endian.\n * @param view - the source view\n * @param kind - the scalar kind\n * @param offset - the byte offset\n * @returns the component\n */\nfunction getScalar(view: DataView, kind: ScalarKind, offset: number): number {\n if (kind === \"u32\") {\n return view.getUint32(offset, true);\n }\n if (kind === \"i32\") {\n return view.getInt32(offset, true);\n }\n return view.getFloat32(offset, true);\n}\n\n/** A generated struct: the padded WGSL text and the byte writer / reader share one field table, so they cannot disagree (D20). */\nexport class UniformBlock {\n /** The WGSL struct name. */\n readonly name: string;\n /** \"uniform\" (the default) or \"storage\"; both lay out identically, the tag documents the block's address space. */\n readonly layout: \"uniform\" | \"storage\";\n /** The fields in declaration (= byte) order. */\n readonly fields: readonly UniformField[];\n /** The padded byte length (a multiple of 16). */\n readonly byteLength: number;\n /** The `struct <name> { ... }` text with explicit `@size` / `@align` where padding is needed. */\n readonly wgsl: string;\n /** The laid-out fields by name. */\n private readonly table: ReadonlyMap<string, FieldLayout>;\n /** The laid-out fields in order. */\n private readonly laidOut: readonly FieldLayout[];\n\n /**\n * Declares a block; fields are laid out in order with 16-byte alignment for vec4 / the struct, 8 for vec2, 4 for\n * scalars; the total is padded to 16 (uniform, storage) or to `padTo` when given.\n * PLAN DECISION: rejects an empty field list and a struct or field name that is not a WGSL identifier or is a\n * reserved word (spec 3.6: every throwing call leaves state unchanged; a reserved name would be invalid WGSL).\n * PLAN DECISION: optional PARAMETERS (`options?` here, `byteOffset?` of write / read / readField) are spelled\n * `?: T` rather than the contract's `?: T | undefined` because the root ESLint rule\n * no-duplicate-type-constituents rejects the explicit undefined on an optional parameter; every call site is\n * identical, and optional PROPERTIES keep `?: T | undefined`.\n * @param name - the WGSL struct name\n * @param fields - the fields in byte order\n * @param options - the layout tag and the optional padding\n * @param options.layout - \"uniform\" (default) or \"storage\"; the tag documents the address space, the layout is the same\n * @param options.padTo - the byte length to pad to (a multiple of 16 not below the natural size)\n * @returns the block\n */\n static define(\n name: string,\n fields: readonly UniformField[],\n options?: { readonly layout?: \"uniform\" | \"storage\" | undefined; readonly padTo?: number | undefined },\n ): UniformBlock {\n assertIdentifier(\"name\", name);\n if (fields.length === 0) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock ${name}: a block needs at least one field`, {\n argument: \"fields\",\n value: fields.length,\n expected: \">= 1 field\",\n });\n }\n const laidOut: FieldLayout[] = [];\n const table = new Map<string, FieldLayout>();\n let cursor = 0;\n for (const [fieldName, type] of fields) {\n assertIdentifier(\"fields\", fieldName);\n if (table.has(fieldName)) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformBlock ${name}: duplicate field \"${fieldName}\"`,\n {\n argument: \"fields\",\n value: fieldName,\n expected: \"unique field names\",\n },\n );\n }\n const info = TYPE_INFO[type] as TypeInfo | undefined;\n if (info === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock ${name}: unknown field type \"${type}\"`, {\n argument: \"fields\",\n value: type,\n expected: Object.keys(TYPE_INFO).join(\" | \"),\n });\n }\n const offset = roundUp(cursor, info.align);\n const field: FieldLayout = { name: fieldName, type, offset, info };\n laidOut.push(field);\n table.set(fieldName, field);\n cursor = offset + info.size;\n }\n const natural = roundUp(cursor, STRUCT_ALIGN);\n const padTo = options?.padTo;\n if (padTo !== undefined && (!Number.isInteger(padTo) || padTo % STRUCT_ALIGN !== 0 || padTo < natural)) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformBlock ${name}: padTo ${padTo} is not a multiple of 16 >= ${natural}`,\n {\n argument: \"padTo\",\n value: padTo,\n expected: `a multiple of ${STRUCT_ALIGN} not below ${natural}`,\n },\n );\n }\n const byteLength = padTo ?? natural;\n const lines = laidOut.map((field, index) => {\n const last = index === laidOut.length - 1;\n const end = field.offset + field.info.size;\n const size = last && end < byteLength ? `@size(${byteLength - field.offset}) ` : \"\";\n return ` ${size}${field.name}: ${field.type},`;\n });\n const wgsl = `struct ${name} {\\n${lines.join(\"\\n\")}\\n}`;\n return new UniformBlock(name, options?.layout ?? \"uniform\", fields, byteLength, wgsl, laidOut, table);\n }\n\n /**\n * Built by `define()` only.\n * @param name - the struct name\n * @param layout - the address-space tag\n * @param fields - the declared fields\n * @param byteLength - the padded byte length\n * @param wgsl - the struct text\n * @param laidOut - the laid-out fields in order\n * @param table - the laid-out fields by name\n */\n private constructor(\n name: string,\n layout: \"uniform\" | \"storage\",\n fields: readonly UniformField[],\n byteLength: number,\n wgsl: string,\n laidOut: readonly FieldLayout[],\n table: ReadonlyMap<string, FieldLayout>,\n ) {\n this.name = name;\n this.layout = layout;\n this.fields = Object.freeze(fields.map(([fieldName, type]) => Object.freeze([fieldName, type] as const)));\n this.byteLength = byteLength;\n this.wgsl = wgsl;\n this.laidOut = laidOut;\n this.table = table;\n }\n\n /**\n * Byte offset of a field; E_INVALID_ARGUMENT for an unknown field.\n * @param field - the field name\n * @returns the byte offset inside the block\n */\n offsetOf(field: string): number {\n return this.fieldLayout(field).offset;\n }\n\n /**\n * Writes `values` at `byteOffset` (default 0); a missing field is written as 0; an unknown key is\n * E_INVALID_ARGUMENT; a vector of the wrong width is E_INVALID_ARGUMENT. Always little-endian. Every byte of the\n * block's region is written (padding as zero), so a written block is byte-exact.\n * PLAN DECISION: every value is validated first (u32 / vec*u components integers in [0, 2^32 - 1], i32 in\n * [-2^31, 2^31 - 1]) and only then is the region zeroed and written, so a rejected call leaves the view unchanged.\n * @param view - the target view (the region must lie inside it)\n * @param values - the field values\n * @param byteOffset - the region's start inside the view\n */\n write(view: DataView, values: UniformValues, byteOffset?: number): void {\n const base = this.regionStart(view, byteOffset);\n for (const key of Object.keys(values)) {\n if (!this.table.has(key)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock ${this.name}: unknown field \"${key}\"`, {\n argument: \"values\",\n value: key,\n expected: this.laidOut.map((f) => f.name).join(\", \"),\n });\n }\n }\n // validate every value first, so a rejected call leaves the view unchanged (spec 3.6)\n const components: (readonly number[] | null)[] = this.laidOut.map((field) =>\n this.components(field, values[field.name]),\n );\n for (let at = 0; at < this.byteLength; at += 4) {\n view.setUint32(base + at, 0, true);\n }\n this.laidOut.forEach((field, index) => {\n const lanes = components[index];\n if (lanes === null) {\n return;\n }\n lanes.forEach((component, lane) => {\n setScalar(view, field.info.scalar, base + field.offset + 4 * lane, component);\n });\n });\n }\n\n /**\n * The validated components of one field's value: null for an absent field, else `width` numbers.\n * @param field - the laid-out field\n * @param value - the value given for it (undefined when absent)\n * @returns the components or null\n */\n private components(field: FieldLayout, value: number | readonly number[] | undefined): readonly number[] | null {\n if (value === undefined) {\n return null;\n }\n const { scalar, width } = field.info;\n if (width === 1) {\n assertScalar(field.name, scalar, value);\n return [value];\n }\n if (!Array.isArray(value) || value.length !== width) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformBlock ${this.name}: field \"${field.name}\" expects ${width} components`,\n {\n argument: field.name,\n value,\n expected: `an array of ${width} numbers`,\n },\n );\n }\n const lanes: number[] = [];\n for (let lane = 0; lane < width; lane++) {\n const component: unknown = value[lane];\n assertScalar(field.name, scalar, component);\n lanes.push(component);\n }\n return lanes;\n }\n\n /**\n * Reads every field at `byteOffset` (storage mode's reader; also used by tests on uniform blocks).\n * @param view - the source view\n * @param byteOffset - the region's start inside the view\n * @returns the field values (vectors as arrays)\n */\n read(view: DataView, byteOffset?: number): UniformValues {\n const base = this.regionStart(view, byteOffset);\n const out: Record<string, number | readonly number[]> = {};\n for (const field of this.laidOut) {\n out[field.name] = this.decode(view, field, base);\n }\n return out;\n }\n\n /**\n * Reads one field.\n * @param view - the source view\n * @param field - the field name\n * @param byteOffset - the region's start inside the view\n * @returns the value (a number, or an array for a vector)\n */\n readField(view: DataView, field: string, byteOffset?: number): number | readonly number[] {\n const layout = this.fieldLayout(field);\n return this.decode(view, layout, this.regionStart(view, byteOffset));\n }\n\n /**\n * The laid-out field of a name.\n * @param field - the field name\n * @returns the layout\n */\n private fieldLayout(field: string): FieldLayout {\n const layout = this.table.get(field);\n if (layout === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock ${this.name}: unknown field \"${field}\"`, {\n argument: \"field\",\n value: field,\n expected: this.laidOut.map((f) => f.name).join(\", \"),\n });\n }\n return layout;\n }\n\n /**\n * Validates the region `[byteOffset, byteOffset + byteLength)` against the view.\n * @param view - the view\n * @param byteOffset - the requested start (default 0)\n * @returns the start\n */\n private regionStart(view: DataView, byteOffset: number | undefined): number {\n const base = byteOffset ?? 0;\n if (!Number.isInteger(base) || base < 0 || base + this.byteLength > view.byteLength) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformBlock ${this.name}: region [${base}, ${base + this.byteLength}) is outside the view`,\n {\n argument: \"byteOffset\",\n value: base,\n expected: `0 <= byteOffset <= ${view.byteLength - this.byteLength}`,\n },\n );\n }\n return base;\n }\n\n /**\n * Decodes one field from a view.\n * @param view - the source view\n * @param field - the laid-out field\n * @param base - the region start\n * @returns the value\n */\n private decode(view: DataView, field: FieldLayout, base: number): number | readonly number[] {\n const { scalar, width } = field.info;\n if (width === 1) {\n return getScalar(view, scalar, base + field.offset);\n }\n const lanes: number[] = [];\n for (let lane = 0; lane < width; lane++) {\n lanes.push(getScalar(view, scalar, base + field.offset + 4 * lane));\n }\n return lanes;\n }\n}\n","/**\n * The `degree` kernel body (contract 4.5; spec 6 row 3, 11.5): the out-degree of every row of `[P.start, P.end)`\n * through the row-walking gather with the USE_PERM dummy pattern, counting the arcs of the bound window whose\n * neighbour index is a valid node; `P.accumulate == 1` adds into `out[i]` instead of overwriting (the P4 windowed\n * loop). Bindings, overrides and the `RangeParams` block come from the registry entry (src/kernels.ts); WG,\n * USE_PERM and `linear_id` from the prelude. The text is normative: test/helpers/sabotage.ts mutates it textually,\n * so it is copied from the contract and never re-derived or restyled.\n */\nexport const degreeWgsl = /* wgsl */ `\n@compute @workgroup_size(WG)\nfn degree(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let row = linear_id(wid, lid.x) + P.start;\n if (row >= P.end) { return; }\n let i = select(row, perm[row], USE_PERM);\n let a0 = max(rowPtr[i], P.arcBase);\n let a1 = min(rowPtr[i + 1u], P.arcEnd);\n var d = 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); never use it as an identifier\n d = d + select(0u, 1u, nbr < P.n);\n }\n out[i] = select(d, out[i] + d, P.accumulate == 1u);\n}\n`;\n","/**\n * K2 of the ForceAtlas2 iteration, `fa2-attraction` (spec 7.5; contract 4.5): the thread-per-row gather of the\n * attraction force over the undirected CSR rows (both arcs present, so the sum is symmetric with no atomics), the\n * linear or linlog law, the optional weights, the distributed-action division by the mass in `pos.w`, written as\n * the FIRST writer of `force` each iteration. P3 ships the thread-per-row tier over `[tierStart, tierEnd)` = `[0, n)`\n * with `USE_PERM = false`; the subgroup / workgroup tiers arrive with P4 (`TIER`).\n *\n * Body only (spec 3.5, D9); normative text (contract 4.5); the K2 sabotage mutations (P3-T5) are textual edits of it.\n */\n\n/** The K2 body: entry point `attraction`; an early return is legal here because no barrier follows (spec 3.5 rule 1). */\nexport const fa2AttractionWgsl = /* wgsl */ `fn store_force(i: u32, f: vec3f) {\n force[3u * i] = f.x;\n force[3u * i + 1u] = f.y;\n force[3u * i + 2u] = f.z;\n}\n\n@compute @workgroup_size(WG)\nfn attraction(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let row = linear_id(wid, lid.x) + P.tierStart;\n if (row >= P.tierEnd) { return; } // no barrier follows in this tier (3.5 rule 1)\n let i = select(row, perm[row], USE_PERM);\n let pi = pos[i]; // xyz + mass in one load (D23)\n var f = vec3f(0.0);\n for (var a = rowPtr[i]; a < rowPtr[i + 1u]; a = a + 1u) {\n let j = colIdx[a];\n if (j == i) { continue; } // a self-loop exerts no force\n var w = 1.0;\n if (HAS_WEIGHTS) { w = weights[a]; }\n let d = pos[j].xyz - pi.xyz; // toward j\n let len = max(length(d), FA2_DIST_FLOOR);\n let mag = select(w, w * log(1.0 + len) / len, LINLOG); // linear: |F| = w len; linlog: |F| = w log(1 + len)\n f = f + d * mag;\n }\n if (DISTRIBUTED) { f = f / pi.w; }\n store_force(i, f); // overwrites: attraction is the first writer of force each iteration\n}`;\n","/**\n * K5 of the ForceAtlas2 iteration, `fa2-integrate` (spec 7.11; contract 4.5): the per-node speed factor\n * `speed / (1 + sqrt(speed * swing_i))` with the local swing recomputed inline (paper mode `m |F(t) - F(t-1)|`,\n * networkx mode `m |F|`, contract 4.6), the position update with no displacement clamp (D25), z never integrated\n * in 2D (spec 7.13), `oldForce` stored in paper mode for fixed nodes too (spec 7.11), and the partials A\n * (sum p, sum |p - c|^2, min, max with max |p - c|^2 in `max.w`) and C (sum |dp| over free rows, free count) in\n * uniform control flow.\n *\n * Body only (spec 3.5, D9); normative text (contract 4.5); the K5 sabotage mutations (P3-T5) are textual edits of it.\n */\n\n/** The K5 body: entry point `integrate`; calls the reduction helpers (`needs: [\"subgroups\"]`, contract 4.3). */\nexport const fa2IntegrateWgsl = /* wgsl */ `fn load_force(i: u32) -> vec3f { return vec3f(force[3u * i], force[3u * i + 1u], force[3u * i + 2u]); }\nfn load_old(i: u32) -> vec3f { return vec3f(oldForce[3u * i], oldForce[3u * i + 1u], oldForce[3u * i + 2u]); }\nfn store_old(i: u32, f: vec3f) {\n oldForce[3u * i] = f.x;\n oldForce[3u * i + 1u] = f.y;\n oldForce[3u * i + 2u] = f.z;\n}\n\n@compute @workgroup_size(WG)\nfn integrate(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n var dp = vec3f(0.0);\n var p = vec4f(0.0);\n var free = false;\n var valid = false;\n if (i < P.n) {\n valid = true;\n let f = load_force(i);\n p = pos[i];\n var swing_i = p.w * length(f); // SWING_MODE 1: NetworkX's local swinging m |F| (layout.py line 1497)\n if (SWING_MODE == 0u) { swing_i = p.w * length(f - load_old(i)); } // paper: m |F(t) - F(t-1)|, recomputed inline (7.2)\n let factor = S.speed / (1.0 + sqrt(S.speed * swing_i));\n let fixed = mask_bit(fixedMask[i >> 5u], i);\n dp = select(f * factor, vec3f(0.0), fixed); // no clamp on dp (D25)\n if (P.dim == 2u) { dp.z = 0.0; } // 2D never integrates z (7.13)\n p = vec4f(p.xyz + dp, p.w);\n pos[i] = p;\n if (SWING_MODE == 0u) { store_old(i, f); } // fixed nodes too, so a later unpin sees no stale swing (7.11)\n free = !fixed;\n }\n // uniform control flow from here (3.5 rule 1): partials A (sum p, sum |p - c|^2, min, max over valid rows) and C (sum |dp|, free count)\n let c = S.centroid.xyz;\n var sumv = vec4f(0.0);\n var lo = vec4f(F32_MAX);\n var hi = vec4f(-F32_MAX);\n var dl = 0.0;\n var fr = 0u;\n if (valid) {\n let q = p.xyz - c;\n sumv = vec4f(p.xyz, dot(q, q));\n lo = vec4f(p.xyz, 0.0);\n hi = vec4f(p.xyz, dot(q, q)); // max.w carries max |p - c|^2 so K1 can write the exact layoutRadius (spec 3.3)\n }\n if (free) { dl = length(dp); fr = 1u; }\n let tSum = wg_reduce_vec4(sumv, lid.x, 0u);\n let tLo = wg_reduce_vec4(lo, lid.x, 1u);\n let tHi = wg_reduce_vec4(hi, lid.x, 2u);\n let tDl = wg_reduce_f32(dl, lid.x, 0u);\n let tFr = wg_reduce_u32(fr, lid.x, 0u);\n if (lid.x == 0u) {\n let g = group_id(wid);\n partials[g].sum = tSum;\n partials[g].min = tLo;\n partials[g].max = tHi;\n partials[g].dispFree = vec2f(tDl, f32(tFr));\n }\n}`;\n","/**\n * The `fa2-repulsion-exact` kernel body (K3; contract 4.5; spec 7.6, 7.9, 7.10): the tiled all-pairs repulsion\n * `|F| = k m_i m_j / d` with the 0.01 distance floor and the antisymmetric coincident kick, the gravity epilogue\n * (GRAVITY_CENTER 0 = centroid, 1 = origin; STRONG_GRAVITY) added under the `valid` guard, `force += f`, and the\n * swing / traction workgroup reduction in uniform control flow (SWING_MODE 0 = paper: free nodes only against\n * `oldForce`; 1 = NetworkX: positions and forces mixed, every node) whose lane 0 writes\n * `partials[group].swingTraction`. `pos` is `array<vec4f>` with the mass in `.w`; `force` / `oldForce` are stride-3\n * `array<f32>` read through the per-body helpers (4.4 rule 6). Normative text, copied verbatim: the P1-T5 sabotage\n * rows (gravity sign, `k / d2`, the `jj != i` guard, the `.w` mass lane) are textual edits of this string.\n */\nexport const fa2RepulsionExactWgsl = /* wgsl */ `\nvar<workgroup> tile: array<vec4f, WG>; // xyz + mass, 4 KiB at WG = 256\n\nfn load_force(i: u32) -> vec3f { return vec3f(force[3u * i], force[3u * i + 1u], force[3u * i + 2u]); }\nfn store_force(i: u32, f: vec3f) {\n force[3u * i] = f.x;\n force[3u * i + 1u] = f.y;\n force[3u * i + 2u] = f.z;\n}\nfn load_old(i: u32) -> vec3f { return vec3f(oldForce[3u * i], oldForce[3u * i + 1u], oldForce[3u * i + 2u]); }\nfn gravity_force(pi: vec4f) -> vec3f { // spec 7.9: centroid (GRAVITY_CENTER 0) or origin (1); regular or strong\n var q = pi.xyz;\n if (GRAVITY_CENTER == 0u) { q = pi.xyz - S.centroid.xyz; }\n if (STRONG_GRAVITY) { return -P.gravity * pi.w * q; }\n let d = length(q);\n if (d > FA2_DIST_FLOOR) { return -P.gravity * pi.w * q / d; }\n return vec3f(0.0);\n}\n\n@compute @workgroup_size(WG)\nfn repulsion(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n let valid = i < P.n;\n var pi = vec4f(0.0);\n if (valid) { pi = pos[i]; }\n var f = vec3f(0.0);\n let tiles = (P.n + WG - 1u) / WG;\n for (var t = 0u; t < tiles; t = t + 1u) {\n let j = t * WG + lid.x;\n if (j < P.n) { tile[lid.x] = pos[j]; } else { tile[lid.x] = vec4f(0.0); } // guarded fill; mass 0 marks the pad\n workgroupBarrier(); // uniform: every invocation reaches it\n for (var s = 0u; s < WG; s = s + 1u) {\n let o = tile[s];\n let jj = t * WG + s;\n if (o.w > 0.0 && jj != i) { // mass > 0 for every real node, 0 for the pad\n let d = pi.xyz - o.xyz;\n var d2 = dot(d, d);\n if (d2 < FA2_COINCIDENT_SQ) { // coincident: antisymmetric unit kick of magnitude k m_i m_j / 0.01 (7.2)\n f = f + kick_dir(i, jj, P.dim) * (P.scalingRatio * pi.w * o.w / FA2_DIST_FLOOR);\n continue;\n }\n d2 = max(d2, FA2_DIST_FLOOR_SQ); // d >= 0.01\n let k = P.scalingRatio * pi.w * o.w;\n f = f + d * (k / d2); // |F| = k m_i m_j / d along d / d\n }\n }\n workgroupBarrier();\n }\n // epilogue (7.9, 7.10): gravity and force += under the guard, the swing / traction reduction outside it\n var sw = 0.0;\n var tr = 0.0;\n if (valid) {\n f = f + gravity_force(pi);\n let fnew = load_force(i) + f;\n store_force(i, fnew);\n if (SWING_MODE == 1u) { // NetworkX: positions and forces mixed, every node (7.2)\n sw = pi.w * length(pi.xyz - fnew);\n tr = 0.5 * pi.w * length(pi.xyz + fnew);\n } else if (!mask_bit(fixedMask[i >> 5u], i)) { // paper: free nodes only (Gephi ForceAtlas2.java 283-293)\n let fold = load_old(i);\n sw = pi.w * length(fnew - fold);\n tr = 0.5 * pi.w * length(fnew + fold);\n }\n }\n let t = wg_reduce_vec4(vec4f(sw, tr, 0.0, 0.0), lid.x, 0u); // uniform control flow: 256 -> 1\n if (lid.x == 0u) { partials[group_id(wid)].swingTraction = t.xy; }\n}\n`;\n","/**\n * The `fa2-speed-finalize` kernel body (K4; contract 4.5; spec 7.10): ONE workgroup sums `partials[*].swingTraction`\n * sequentially per lane (deterministic), reduces in uniform control flow, then lane 0 runs the line-for-line port\n * of the CPU `estimateFactor` (SWING_MODE 1 accumulates NetworkX's sums across iterations from S.swing / S.traction)\n * and writes `S.speed`, `S.speedEfficiency`, `S.swing`, `S.traction` and the four controller fields of\n * `T[P.iterationIndex]`. `target` is a WGSL reserved word, hence `targetSpeed`. Normative text, copied verbatim:\n * the P1-T5 sabotage rows (`* 0.5` -> `* 0.9`, the 1.3 rise, the swing / traction swap) are textual edits of it.\n * The halving predicate is `swing > 2.0 * tr`, the exact form of the port's `swing / traction > 2` (contract 4.5\n * CONTRACT DECISION K4-1, G3 finding G3-F6): every paper-mode first iteration after load() has oldForce = 0, so\n * traction is EXACTLY half the swing and the predicate sits on its knife edge; a multiplication by 2 and the\n * comparison are exact on every device, while WGSL grants f32 division 2.5 ULP and Dawn on NVIDIA returns 2 + 1 ulp\n * for 2.2% of the inputs x / (x / 2) (tmp/p3-fix/div-probe.mjs), which took the branch the CPU reference never takes.\n */\nexport const fa2SpeedFinalizeWgsl = /* wgsl */ `\n@compute @workgroup_size(WG)\nfn speed_finalize(@builtin(local_invocation_id) lid: vec3<u32>) {\n let groups = (P.n + WG - 1u) / WG;\n var st = vec2f(0.0);\n for (var g = lid.x; g < groups; g = g + WG) { st = st + partials[g].swingTraction; } // sequential per lane: deterministic\n let t = wg_reduce_vec4(vec4f(st, 0.0, 0.0), lid.x, 0u);\n if (lid.x == 0u) {\n var swing = t.x;\n var traction = t.y;\n if (SWING_MODE == 1u) { swing = S.swing + t.x; traction = S.traction + t.y; } // NetworkX accumulates across iterations from 1\n let n = f32(P.n);\n let optJitter = 0.05 * sqrt(n);\n let minJitter = sqrt(optJitter);\n let maxJitter = 10.0;\n let tr = max(traction, 1.0e-30); // guards the division only (7.10)\n let other = min(maxJitter, optJitter * traction / (n * n));\n var jitter = P.jitterTolerance * max(minJitter, other);\n var eff = S.speedEfficiency;\n if (swing > 2.0 * tr) { // swing / traction > 2 in the exact form (contract 4.5 CONTRACT DECISION K4-1: 2 x is exact, a WGSL f32 division is not)\n if (eff > 0.05) { eff = eff * 0.5; } // the CPU's conditional multiply (7.2)\n jitter = max(jitter, P.jitterTolerance);\n }\n let targetSpeed = select(jitter * eff * traction / swing, 1.0e30, swing == 0.0); // +Inf in the port; 1e30 gives the same min() below (\\`target\\` is reserved)\n if (swing > jitter * traction) {\n if (eff > 0.05) { eff = eff * 0.7; }\n } else if (S.speed < 1000.0) {\n eff = eff * 1.3;\n }\n S.speed = S.speed + min(targetSpeed - S.speed, 0.5 * S.speed);\n S.speedEfficiency = eff;\n S.swing = swing;\n S.traction = traction;\n T[P.iterationIndex].swing = swing;\n T[P.iterationIndex].traction = traction;\n T[P.iterationIndex].speed = S.speed;\n T[P.iterationIndex].speedEfficiency = eff;\n }\n}\n`;\n","/**\n * K1 of the ForceAtlas2 iteration, `fa2-stats-finalize` (spec 7.4; contract 4.5): one workgroup folds the partials\n * the previous integrate (K5) wrote into the state block -- centroid, RMS radius, layout radius (max |p - c|, the\n * exact spec 3.3 value from `partials.max.w`), bounding box, mean displacement over free nodes (0 when every node\n * is fixed), the settle counter -- increments the iteration counter and writes the K1 half of the trace record.\n * On the first iteration after load() (`FA2_FLAG_FIRST`) it folds nothing and keeps the host-written state.\n *\n * This file holds the kernel BODY only (spec 3.5, D9): no bind-group lines and no `override` lines -- the composer\n * emits them from the registry entry in src/kernels.ts (contract 3.10.1). The text is normative (contract 4.5) and\n * is the target of the K1 sabotage mutations (test/helpers/sabotage.ts, P3-T5); amend the contract before editing.\n */\n\n/** The K1 body: entry point `stats_finalize`; calls the reduction helpers (`needs: [\"subgroups\"]`, contract 4.3). */\nexport const fa2StatsFinalizeWgsl = /* wgsl */ `// K1: folds the previous integrate's partials into the state block (spec 7.4); one workgroup\n@compute @workgroup_size(WG)\nfn stats_finalize(@builtin(local_invocation_id) lid: vec3<u32>) {\n let groups = (P.n + WG - 1u) / WG;\n let fold = (P.flags & FA2_FLAG_FIRST) == 0u; // the first iteration after load() keeps the host-written state\n var sum = vec4f(0.0);\n var lo = vec4f(F32_MAX);\n var hi = vec4f(-F32_MAX);\n var disp = 0.0;\n var free = 0u;\n if (fold) {\n for (var g = lid.x; g < groups; g = g + WG) { // sequential per lane in index order: deterministic\n let q = partials[g];\n sum = sum + q.sum;\n lo = min(lo, q.min);\n hi = max(hi, q.max);\n disp = disp + q.dispFree.x;\n free = free + u32(q.dispFree.y);\n }\n }\n let tSum = wg_reduce_vec4(sum, lid.x, 0u);\n let tLo = wg_reduce_vec4(lo, lid.x, 1u);\n let tHi = wg_reduce_vec4(hi, lid.x, 2u);\n let tDisp = wg_reduce_f32(disp, lid.x, 0u);\n let tFree = wg_reduce_u32(free, lid.x, 0u);\n if (lid.x == 0u) {\n if (fold) {\n let n = f32(P.n);\n let c = tSum.xyz / n;\n S.centroid = vec4f(c, 0.0);\n S.rmsRadius = sqrt(max(tSum.w, 0.0) / n); // RMS radius about the previous centroid (7.17)\n S.min = vec4f(tLo.xyz, 0.0);\n S.max = vec4f(tHi.xyz, 0.0);\n S.radius = sqrt(max(tHi.w, 0.0)); // max |p - centroid| about the same previous centroid as rmsRadius (K5 puts |q|^2 in max.w)\n let meanDisp = select(tDisp / f32(tFree), 0.0, tFree == 0u); // all-fixed: 0, never NaN (7.4)\n S.meanDisplacement = meanDisp;\n S.settledCount = select(0u, S.settledCount + 1u, meanDisp <= P.settleThreshold * S.rmsRadius);\n }\n S.iteration = S.iteration + 1u;\n T[P.iterationIndex].meanDisplacement = S.meanDisplacement;\n T[P.iterationIndex].settledCount = S.settledCount;\n T[P.iterationIndex].iteration = S.iteration;\n }\n}`;\n","/**\n * The per-batch `fa2-to-scene` kernel (spec 7.13, 7.18; contract 4.5): unpacks the vec4f layout-unit positions into\n * the stride-3 scene array the staging copy reads back, applying `scale` and `center`; in 2D the third component is\n * `center.z` on every readback whatever z the device holds.\n *\n * Body only (spec 3.5, D9); normative text (contract 4.5); exempt from the sabotage matrix (SABOTAGE_EXEMPT: a wrong\n * toScene fails the exact-equality position tests directly).\n */\n\n/** The toScene body: entry point `to_scene`; an early return is legal here because no barrier follows (spec 3.5 rule 1). */\nexport const fa2ToSceneWgsl = /* wgsl */ `@compute @workgroup_size(WG)\nfn to_scene(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n if (i >= P.n) { return; }\n let s = pos[i].xyz * P.scale + P.center.xyz;\n scene[3u * i] = s.x;\n scene[3u * i + 1u] = s.y;\n scene[3u * i + 2u] = select(s.z, P.center.z, P.dim == 2u); // 2D writes z = center.z on every readback (7.13)\n}`;\n","/**\n * The `fill` kernel body (contract 4.5): `dst[i] = P.value` (mode 0) or `i + P.value` (mode 1, iota) for every\n * `i < P.count`, `i` from the prelude's `linear_id` so a 2D dispatch covers counts above MAX_1D_ITEMS. The 17M-item\n * linear_id test of spec 5.2 / 11.5 is mode 1 over 16,776,961 words. Normative text, copied verbatim.\n */\nexport const fillWgsl = /* wgsl */ `\n@compute @workgroup_size(WG)\nfn fill(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n if (i >= P.count) { return; }\n dst[i] = select(P.value, i + P.value, P.mode == 1u);\n}\n`;\n","/**\n * The `reduce` kernel body (contract 4.5; spec 6 row 1): one level of the 2-3 level reduction. Overrides: OP\n * 0 sum / 1 min / 2 max, DTYPE 0 f32 / 1 u32 / 2 vec4f (four words per element, loaded through bitcast from the\n * u32 storage view), FINAL true for the one-workgroup level that folds the partials sequentially per lane in\n * index order (deterministic) and writes one element at `out[P.outOffset]`; the level-1 form writes\n * `out[P.outOffset + group]`. Calls the prelude's `wg_reduce_*` helpers (needs: [\"subgroups\"]) in uniform\n * control flow: DTYPE is a pipeline constant, so the branch on it is uniform. Normative text, copied verbatim.\n */\nexport const reduceWgsl = /* wgsl */ `\n// DTYPE 0 = f32, 1 = u32, 2 = vec4f (4 words per element); OP 0 = sum, 1 = min, 2 = max; FINAL = the one-workgroup level\nfn identity_f() -> f32 { if (OP == 1u) { return F32_MAX; } if (OP == 2u) { return -F32_MAX; } return 0.0; }\nfn identity_u() -> u32 { if (OP == 1u) { return U32_MAX; } return 0u; } // U32_MAX from the prelude: the literal is forbidden in bodies (4.1)\nfn comb_f(a: f32, b: f32) -> f32 { if (OP == 1u) { return min(a, b); } if (OP == 2u) { return max(a, b); } return a + b; }\nfn comb_u(a: u32, b: u32) -> u32 { if (OP == 1u) { return min(a, b); } if (OP == 2u) { return max(a, b); } return a + b; }\nfn comb_v(a: vec4f, b: vec4f) -> vec4f { if (OP == 1u) { return min(a, b); } if (OP == 2u) { return max(a, b); } return a + b; }\nfn load_f(i: u32) -> f32 { return bitcast<f32>(src[i]); }\nfn load_v(i: u32) -> vec4f {\n return vec4f(bitcast<f32>(src[4u * i]), bitcast<f32>(src[4u * i + 1u]), bitcast<f32>(src[4u * i + 2u]), bitcast<f32>(src[4u * i + 3u]));\n}\nfn store_f(i: u32, v: f32) { out[i] = bitcast<u32>(v); }\nfn store_v(i: u32, v: vec4f) {\n out[4u * i] = bitcast<u32>(v.x);\n out[4u * i + 1u] = bitcast<u32>(v.y);\n out[4u * i + 2u] = bitcast<u32>(v.z);\n out[4u * i + 3u] = bitcast<u32>(v.w);\n}\n\n@compute @workgroup_size(WG)\nfn reduce(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n var accF = identity_f();\n var accU = identity_u();\n var accV = vec4f(identity_f());\n if (FINAL) {\n for (var i = lid.x; i < P.count; i = i + WG) { // sequential per lane in index order: deterministic\n if (DTYPE == 0u) { accF = comb_f(accF, load_f(i)); }\n else if (DTYPE == 1u) { accU = comb_u(accU, src[i]); }\n else { accV = comb_v(accV, load_v(i)); }\n }\n } else {\n let i = linear_id(wid, lid.x);\n if (i < P.count) {\n if (DTYPE == 0u) { accF = load_f(i); }\n else if (DTYPE == 1u) { accU = src[i]; }\n else { accV = load_v(i); }\n }\n }\n // uniform control flow: the workgroup reduction of the selected dtype (DTYPE is a pipeline constant, so the branch is uniform)\n var tF = 0.0;\n var tU = 0u;\n var tV = vec4f(0.0);\n if (DTYPE == 0u) { tF = wg_reduce_f32(accF, lid.x, OP); }\n else if (DTYPE == 1u) { tU = wg_reduce_u32(accU, lid.x, OP); }\n else { tV = wg_reduce_vec4(accV, lid.x, OP); }\n if (lid.x == 0u) {\n let g = select(group_id(wid), 0u, FINAL);\n let o = P.outOffset + g;\n if (DTYPE == 0u) { store_f(o, tF); }\n else if (DTYPE == 1u) { out[o] = tU; }\n else { store_v(o, tV); }\n }\n}\n`;\n","/**\n * The `segmented-reduce` kernel body (spec 6 row 3; contract 4.5), TIER 0 = thread-per-row: one invocation per row\n * of [P.start, P.end) folds the VALUE snippet over the row's arcs inside the bound window [P.arcBase, P.arcEnd) and\n * writes out[i] as f32; a row with no arcs gets the identity element (0 for sum, F32_MAX for min, -F32_MAX for\n * max). The mid / high degree tiers (TIER 1 / 2 over degreeOrder()) land at P4. The body is normative: a sabotage\n * mutation (test/helpers/sabotage.ts) is a textual edit of it, so it is not restyled.\n */\n\n/**\n * Entry point `segmented_reduce`; overrides OP (0 sum, 1 min, 2 max) and TIER (0); snippet slot VALUE: statements\n * assigning `v` from `row`, `arc`, `nbr`, `weight` (`target` is a WGSL reserved word, hence `nbr`).\n */\nexport const segmentedReduceWgsl = /* wgsl */ `\nfn identity() -> f32 { if (OP == 1u) { return F32_MAX; } if (OP == 2u) { return -F32_MAX; } return 0.0; }\nfn comb(a: f32, b: f32) -> f32 { if (OP == 1u) { return min(a, b); } if (OP == 2u) { return max(a, b); } return a + b; }\n\n@compute @workgroup_size(WG)\nfn segmented_reduce(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let row = linear_id(wid, lid.x) + P.start;\n if (row >= P.end) { return; }\n let i = select(row, perm[row], USE_PERM);\n let a0 = max(rowPtr[i], P.arcBase);\n let a1 = min(rowPtr[i + 1u], P.arcEnd);\n var acc = identity();\n for (var arc = a0; arc < a1; arc = arc + 1u) {\n let nbr = colIdx[arc - P.arcBase]; // the neighbour index (\\`target\\` is a WGSL reserved word)\n var weight = 1.0;\n if (HAS_WEIGHTS) { weight = weights[arc - P.arcBase]; }\n var v = 0.0;\n //@@VALUE@@\n acc = comb(acc, v);\n }\n out[i] = select(acc, comb(out[i], acc), P.accumulate == 1u);\n}\n`;\n","/**\n * THE kernel registry (spec 3.5; contract 3.10): every WGSL module the package compiles, keyed by id, with the\n * binding table, the override declarations, the generated uniform / storage blocks and the feature needs from\n * which src/kernel/wgsl.ts emits the bind declarations and src/kernel/pipeline-cache.ts derives the explicit\n * bind-group layouts. A variant cannot exist without an entry here: the compile tests, the bind-group-budget\n * test and PipelineCache.warm() iterate this table. P1-T4 lands degree, reduce, fill, fa2-repulsion-exact (K3)\n * and fa2-speed-finalize (K4) together with every generated block of contract 3.10.2; P2-T2 lands\n * segmented-reduce; P3-T2 adds fa2-stats-finalize (K1), fa2-attraction (K2), fa2-integrate (K5) and\n * fa2-to-scene. This file is the only importer of src/wgsl/** (spec 3.2; test/layers.test.ts).\n */\n\nimport { STATE_HEADER_BYTES } from \"./constants.js\";\nimport { WebGpuGraphError } from \"./errors.js\";\nimport { UniformBlock } from \"./kernel/struct-block.js\";\nimport { type BindingDecl, type OverrideDecl, type WgslModuleSpec } from \"./kernel/wgsl.js\";\nimport { type CoreBinding } from \"./memory/residency.js\";\nimport { type Binding } from \"./types/memory.js\";\nimport { degreeWgsl } from \"./wgsl/degree.wgsl.js\";\nimport { fa2AttractionWgsl } from \"./wgsl/fa2-attraction.wgsl.js\";\nimport { fa2IntegrateWgsl } from \"./wgsl/fa2-integrate.wgsl.js\";\nimport { fa2RepulsionExactWgsl } from \"./wgsl/fa2-repulsion-exact.wgsl.js\";\nimport { fa2SpeedFinalizeWgsl } from \"./wgsl/fa2-speed-finalize.wgsl.js\";\nimport { fa2StatsFinalizeWgsl } from \"./wgsl/fa2-stats-finalize.wgsl.js\";\nimport { fa2ToSceneWgsl } from \"./wgsl/fa2-to-scene.wgsl.js\";\nimport { fillWgsl } from \"./wgsl/fill.wgsl.js\";\nimport { reduceWgsl } from \"./wgsl/reduce.wgsl.js\";\nimport { segmentedReduceWgsl } from \"./wgsl/segmented-reduce.wgsl.js\";\n\n/** Every module id of P1-P3 (P4+ ids are appended, never renamed). */\nexport type KernelId =\n | \"degree\"\n | \"reduce\"\n | \"fill\"\n | \"segmented-reduce\"\n | \"fa2-stats-finalize\"\n | \"fa2-attraction\"\n | \"fa2-repulsion-exact\"\n | \"fa2-speed-finalize\"\n | \"fa2-integrate\"\n | \"fa2-to-scene\";\n\n/** One registry entry: everything of a WgslModuleSpec except the per-variant overrides and snippets. */\nexport interface KernelEntry {\n readonly id: KernelId;\n readonly body: string;\n readonly entryPoint: string;\n readonly bindings: readonly BindingDecl[];\n readonly overrideDecls: readonly OverrideDecl[];\n readonly uniforms: readonly UniformBlock[];\n /** [\"subgroups\"] when the body calls a reduction helper (the twin axis), else []. */\n readonly needs: readonly \"subgroups\"[];\n /** The snippet marker names the body carries (segmented-reduce: [\"VALUE\"]). */\n readonly snippetSlots: readonly string[];\n /** The phase the entry landed in (documentation and the compile-matrix filter). */\n readonly phase: \"P1\" | \"P2\" | \"P3\";\n}\n\n// ---- the generated blocks (spec 5.3; contract 3.10.2): field order = byte order, offsets in the JSDoc\n\n/** `RangeParams` (uniform, 32 B): rows `[start, end)` @0 / @4 of the dispatch, the bound arc window `[arcBase, arcEnd)` @8 / @12 (0 and arcCount when not windowed), `accumulate` @16 (1 combines into `out[i]` instead of overwriting: the P4 windowed loop), `n` @20 (the node count that bounds neighbour indices), `pad0` @24, `pad1` @28. */\nexport const RANGE_PARAMS: UniformBlock = UniformBlock.define(\"RangeParams\", [\n [\"start\", \"u32\"],\n [\"end\", \"u32\"],\n [\"arcBase\", \"u32\"],\n [\"arcEnd\", \"u32\"],\n [\"accumulate\", \"u32\"],\n [\"n\", \"u32\"],\n [\"pad0\", \"u32\"],\n [\"pad1\", \"u32\"],\n]);\n\n/** `ReduceParams` (uniform, 16 B): `count` @0 elements of the level, `outOffset` @4 (the element index the level writes at), `level` @8, `pad0` @12. */\nexport const REDUCE_PARAMS: UniformBlock = UniformBlock.define(\"ReduceParams\", [\n [\"count\", \"u32\"],\n [\"outOffset\", \"u32\"],\n [\"level\", \"u32\"],\n [\"pad0\", \"u32\"],\n]);\n\n/** `FillParams` (uniform, 16 B): `count` @0 words, `value` @4, `mode` @8 (0 = the constant `value`, 1 = iota `i + value`), `pad0` @12. */\nexport const FILL_PARAMS: UniformBlock = UniformBlock.define(\"FillParams\", [\n [\"count\", \"u32\"],\n [\"value\", \"u32\"],\n [\"mode\", \"u32\"],\n [\"pad0\", \"u32\"],\n]);\n\n/** `Fa2Params` (uniform, 96 B; spec 7.3): the per-iteration ForceAtlas2 parameters -- `n` @0, `dim` @4, `flags` @8 (bit 0 = FA2_FLAG_FIRST), `tierStart` @12, `tierEnd` @16, `iterationIndex` @20, `seed` @24, `nearMax` @28, `scalingRatio` @32, `gravity` @36, `jitterTolerance` @40, `scale` @44, `center` @48 (xyz, w 0), `settleThreshold` @64, `extentFactor` @68, `gridMax` @72, `levels` @76, `pad` @80 (reserved for the P4 GridSpec). */\nexport const FA2_PARAMS: UniformBlock = UniformBlock.define(\"Fa2Params\", [\n [\"n\", \"u32\"],\n [\"dim\", \"u32\"],\n [\"flags\", \"u32\"],\n [\"tierStart\", \"u32\"],\n [\"tierEnd\", \"u32\"],\n [\"iterationIndex\", \"u32\"],\n [\"seed\", \"u32\"],\n [\"nearMax\", \"u32\"],\n [\"scalingRatio\", \"f32\"],\n [\"gravity\", \"f32\"],\n [\"jitterTolerance\", \"f32\"],\n [\"scale\", \"f32\"],\n [\"center\", \"vec4f\"],\n [\"settleThreshold\", \"f32\"],\n [\"extentFactor\", \"f32\"],\n [\"gridMax\", \"u32\"],\n [\"levels\", \"u32\"],\n [\"pad\", \"vec4f\"],\n]);\n\n/** `Fa2State` (storage, padded to STATE_HEADER_BYTES = 256; spec 7.3): the device-resident controller state the finalize kernels write and the host reads back for stats -- `speed` @0, `speedEfficiency` @4, `swing` @8, `traction` @12, `centroid` @16, `rmsRadius` @32, `radius` @36, `meanDisplacement` @40, `iteration` @44, `min` @48, `max` @64, `gridMin` @80 (P4), `eps` @96 (P4), `settledCount` @100, `outsideGrid` @104 (P4), `maxCellOccupancy` @108 (P4), `reserved0` .. `reserved8` @112 .. @240. */\nexport const FA2_STATE: UniformBlock = UniformBlock.define(\n \"Fa2State\",\n [\n [\"speed\", \"f32\"],\n [\"speedEfficiency\", \"f32\"],\n [\"swing\", \"f32\"],\n [\"traction\", \"f32\"],\n [\"centroid\", \"vec4f\"],\n [\"rmsRadius\", \"f32\"],\n [\"radius\", \"f32\"],\n [\"meanDisplacement\", \"f32\"],\n [\"iteration\", \"u32\"],\n [\"min\", \"vec4f\"],\n [\"max\", \"vec4f\"],\n [\"gridMin\", \"vec4f\"],\n [\"eps\", \"f32\"],\n [\"settledCount\", \"u32\"],\n [\"outsideGrid\", \"u32\"],\n [\"maxCellOccupancy\", \"u32\"],\n [\"reserved0\", \"vec4f\"],\n [\"reserved1\", \"vec4f\"],\n [\"reserved2\", \"vec4f\"],\n [\"reserved3\", \"vec4f\"],\n [\"reserved4\", \"vec4f\"],\n [\"reserved5\", \"vec4f\"],\n [\"reserved6\", \"vec4f\"],\n [\"reserved7\", \"vec4f\"],\n [\"reserved8\", \"vec4f\"],\n ],\n { layout: \"storage\", padTo: STATE_HEADER_BYTES },\n);\n\n/** `Fa2Trace` (storage record, 32 B; spec 7.3): one per-iteration trace record -- `swing` @0, `traction` @4, `speed` @8, `speedEfficiency` @12 (written by K4), `meanDisplacement` @16, `settledCount` @20, `iteration` @24 (written by K1), `pad0` @28; the trace region is `array<Fa2Trace>` at byte offset STATE_HEADER_BYTES of the state buffer. */\nexport const FA2_TRACE: UniformBlock = UniformBlock.define(\n \"Fa2Trace\",\n [\n [\"swing\", \"f32\"],\n [\"traction\", \"f32\"],\n [\"speed\", \"f32\"],\n [\"speedEfficiency\", \"f32\"],\n [\"meanDisplacement\", \"f32\"],\n [\"settledCount\", \"u32\"],\n [\"iteration\", \"u32\"],\n [\"pad0\", \"u32\"],\n ],\n { layout: \"storage\" },\n);\n\n/** `Fa2Partial` (storage record, 64 B; spec 7.3): one per-workgroup partial -- `sum` @0 (xyz = sum of positions, w = sum of |p - centroid|^2), `min` @16, `max` @32 (w = max of |p - centroid|^2, the exact layoutRadius source), written by K5; `swingTraction` @48 (written by K3's epilogue); `dispFree` @56 (x = sum |dp| over free rows, y = the free count as an f32 <= 256, written by K5). */\nexport const FA2_PARTIAL: UniformBlock = UniformBlock.define(\n \"Fa2Partial\",\n [\n [\"sum\", \"vec4f\"],\n [\"min\", \"vec4f\"],\n [\"max\", \"vec4f\"],\n [\"swingTraction\", \"vec2f\"],\n [\"dispFree\", \"vec2f\"],\n ],\n { layout: \"storage\" },\n);\n\n// ---- the entries (contract 3.10.1; group 0 = graph, 1 = state, 2 = params, 3 = cold)\n\n/**\n * One binding declaration of contract 3.9, so the tables below read like the rows of 3.10.1.\n * @param group - the bind group (0 graph, 1 state, 2 params, 3 cold)\n * @param binding - the slot inside the group\n * @param name - the WGSL variable name (also the KernelBindings key)\n * @param kind - \"storage\" (read_write), \"storage-ro\" (read) or \"uniform\"\n * @param wgslType - the element / struct type text\n * @returns the declaration\n */\nfunction decl(\n group: 0 | 1 | 2 | 3,\n binding: number,\n name: string,\n kind: BindingDecl[\"kind\"],\n wgslType: string,\n): BindingDecl {\n return { group, binding, name, kind, wgslType };\n}\n\n/** The four group-0 graph slots of every row-walking kernel (spec 3.5): rowPtr, colIdx, weights | dummy, perm | dummy -- all read-only, so the dummies never alias a writable slot (3.10.1). */\nconst GRAPH_SLOTS: readonly BindingDecl[] = [\n decl(0, 0, \"rowPtr\", \"storage-ro\", \"array<u32>\"),\n decl(0, 1, \"colIdx\", \"storage-ro\", \"array<u32>\"),\n decl(0, 2, \"weights\", \"storage-ro\", \"array<f32>\"),\n decl(0, 3, \"perm\", \"storage-ro\", \"array<u32>\"),\n];\n\n/** `degree` (3.10.1): 5 storage bindings; only the standard USE_PERM / HAS_WEIGHTS overrides. */\nconst DEGREE: KernelEntry = {\n id: \"degree\",\n body: degreeWgsl,\n entryPoint: \"degree\",\n bindings: GRAPH_SLOTS.concat(decl(1, 0, \"out\", \"storage\", \"array<u32>\"), decl(2, 0, \"P\", \"uniform\", \"RangeParams\")),\n overrideDecls: [],\n uniforms: [RANGE_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `reduce` (3.10.1): the multi-level reduction; OP 0 sum / 1 min / 2 max, DTYPE 0 f32 / 1 u32 / 2 vec4f, FINAL for the one-workgroup level; 2 storage bindings; calls the reduction helpers. */\nconst REDUCE: KernelEntry = {\n id: \"reduce\",\n body: reduceWgsl,\n entryPoint: \"reduce\",\n bindings: [\n decl(1, 0, \"src\", \"storage-ro\", \"array<u32>\"),\n decl(1, 1, \"out\", \"storage\", \"array<u32>\"),\n decl(2, 0, \"P\", \"uniform\", \"ReduceParams\"),\n ],\n overrideDecls: [\n { name: \"OP\", type: \"u32\", default: 0 },\n { name: \"DTYPE\", type: \"u32\", default: 0 },\n { name: \"FINAL\", type: \"bool\", default: false },\n ],\n uniforms: [REDUCE_PARAMS],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `fill` (3.10.1): dst[i] = value (mode 0) or i + value (mode 1) over `count` words; 1 storage binding. */\nconst FILL: KernelEntry = {\n id: \"fill\",\n body: fillWgsl,\n entryPoint: \"fill\",\n bindings: [decl(1, 0, \"dst\", \"storage\", \"array<u32>\"), decl(2, 0, \"P\", \"uniform\", \"FillParams\")],\n overrideDecls: [],\n uniforms: [FILL_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `segmented-reduce` (3.10.1): the per-row fold of the VALUE snippet over the CSR rows; OP 0 sum / 1 min / 2 max, TIER 0 (thread-per-row; the degreeOrder tiers land at P4) plus the standard USE_PERM / HAS_WEIGHTS; 5 storage bindings; one snippet slot. */\nconst SEGMENTED_REDUCE: KernelEntry = {\n id: \"segmented-reduce\",\n body: segmentedReduceWgsl,\n entryPoint: \"segmented_reduce\",\n bindings: GRAPH_SLOTS.concat(decl(1, 0, \"out\", \"storage\", \"array<f32>\"), decl(2, 0, \"P\", \"uniform\", \"RangeParams\")),\n overrideDecls: [\n { name: \"OP\", type: \"u32\", default: 0 },\n { name: \"TIER\", type: \"u32\", default: 0 },\n ],\n uniforms: [RANGE_PARAMS],\n needs: [],\n snippetSlots: [\"VALUE\"],\n phase: \"P2\",\n};\n\n/** `fa2-stats-finalize` (K1, 3.10.1): the one-workgroup fold of the previous integrate's partials into the state block and the K1 half of the trace record; 3 storage bindings; calls the reduction helpers. */\nconst FA2_STATS_FINALIZE: KernelEntry = {\n id: \"fa2-stats-finalize\",\n body: fa2StatsFinalizeWgsl,\n entryPoint: \"stats_finalize\",\n bindings: [\n decl(1, 0, \"partials\", \"storage-ro\", \"array<Fa2Partial>\"),\n decl(1, 1, \"S\", \"storage\", \"Fa2State\"),\n decl(1, 2, \"T\", \"storage\", \"array<Fa2Trace>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [],\n uniforms: [FA2_PARAMS, FA2_STATE, FA2_TRACE, FA2_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P3\",\n};\n\n/** `fa2-attraction` (K2, 3.10.1): the thread-per-row attraction gather over the CSR rows (the first writer of `force` each iteration); LINLOG / DISTRIBUTED / TIER 0 plus the standard USE_PERM / HAS_WEIGHTS; 6 storage bindings. */\nconst FA2_ATTRACTION: KernelEntry = {\n id: \"fa2-attraction\",\n body: fa2AttractionWgsl,\n entryPoint: \"attraction\",\n bindings: GRAPH_SLOTS.concat(\n decl(1, 0, \"pos\", \"storage-ro\", \"array<vec4f>\"),\n decl(1, 1, \"force\", \"storage\", \"array<f32>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ),\n overrideDecls: [\n { name: \"LINLOG\", type: \"bool\", default: false },\n { name: \"DISTRIBUTED\", type: \"bool\", default: false },\n { name: \"TIER\", type: \"u32\", default: 0 },\n ],\n uniforms: [FA2_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P3\",\n};\n\n/** `fa2-repulsion-exact` (K3, 3.10.1): the tiled all-pairs repulsion with the gravity and swing / traction epilogue; 6 storage bindings (`oldForce` read-only: it only calls load_old); calls the reduction helpers. */\nconst FA2_REPULSION_EXACT: KernelEntry = {\n id: \"fa2-repulsion-exact\",\n body: fa2RepulsionExactWgsl,\n entryPoint: \"repulsion\",\n bindings: [\n decl(1, 0, \"pos\", \"storage-ro\", \"array<vec4f>\"),\n decl(1, 1, \"S\", \"storage\", \"Fa2State\"),\n decl(1, 2, \"force\", \"storage\", \"array<f32>\"),\n decl(1, 3, \"oldForce\", \"storage-ro\", \"array<f32>\"),\n decl(1, 4, \"fixedMask\", \"storage-ro\", \"array<u32>\"),\n decl(1, 5, \"partials\", \"storage\", \"array<Fa2Partial>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [\n { name: \"SWING_MODE\", type: \"u32\", default: 0 },\n { name: \"STRONG_GRAVITY\", type: \"bool\", default: false },\n { name: \"GRAVITY_CENTER\", type: \"u32\", default: 0 },\n ],\n uniforms: [FA2_PARAMS, FA2_STATE, FA2_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `fa2-speed-finalize` (K4, 3.10.1): the one-workgroup partials fold and estimateFactor; 3 storage bindings; calls the reduction helpers. */\nconst FA2_SPEED_FINALIZE: KernelEntry = {\n id: \"fa2-speed-finalize\",\n body: fa2SpeedFinalizeWgsl,\n entryPoint: \"speed_finalize\",\n bindings: [\n decl(1, 0, \"partials\", \"storage-ro\", \"array<Fa2Partial>\"),\n decl(1, 1, \"S\", \"storage\", \"Fa2State\"),\n decl(1, 2, \"T\", \"storage\", \"array<Fa2Trace>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [{ name: \"SWING_MODE\", type: \"u32\", default: 0 }],\n uniforms: [FA2_PARAMS, FA2_STATE, FA2_TRACE, FA2_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `fa2-integrate` (K5, 3.10.1): the per-node speed factor and position update (no clamp, D25), `oldForce` stored in SWING_MODE 0, and the partials A / C of the next K1; 6 storage bindings; calls the reduction helpers. */\nconst FA2_INTEGRATE: KernelEntry = {\n id: \"fa2-integrate\",\n body: fa2IntegrateWgsl,\n entryPoint: \"integrate\",\n bindings: [\n decl(1, 0, \"force\", \"storage-ro\", \"array<f32>\"),\n decl(1, 1, \"oldForce\", \"storage\", \"array<f32>\"),\n decl(1, 2, \"fixedMask\", \"storage-ro\", \"array<u32>\"),\n decl(1, 3, \"S\", \"storage\", \"Fa2State\"),\n decl(1, 4, \"pos\", \"storage\", \"array<vec4f>\"),\n decl(1, 5, \"partials\", \"storage\", \"array<Fa2Partial>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [{ name: \"SWING_MODE\", type: \"u32\", default: 0 }],\n uniforms: [FA2_PARAMS, FA2_STATE, FA2_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P3\",\n};\n\n/** `fa2-to-scene` (3.10.1): the per-batch unpack of the vec4f layout positions into the stride-3 scene array with `scale` / `center` applied (z = center.z in 2D); 2 storage bindings. */\nconst FA2_TO_SCENE: KernelEntry = {\n id: \"fa2-to-scene\",\n body: fa2ToSceneWgsl,\n entryPoint: \"to_scene\",\n bindings: [\n decl(1, 0, \"pos\", \"storage-ro\", \"array<vec4f>\"),\n decl(1, 1, \"scene\", \"storage\", \"array<f32>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [],\n uniforms: [FA2_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P3\",\n};\n\n/**\n * The entries by id, in dispatch order. PLAN DECISION: `KernelId` is declared in full (contract 3.10) while the\n * entries landed phase by phase, so the table is built as a Partial record and exported below through the\n * contract's `Readonly<Record<KernelId, KernelEntry>>` type by one assertion; the runtime membership check of\n * `entryOf` is the E_INVALID_ARGUMENT the contract documents for a JS caller's unknown id. P1-T4 landed the five\n * P1 entries, P2-T2 `\"segmented-reduce\"`, and P3-T2 `\"fa2-stats-finalize\"`, `\"fa2-attraction\"`, `\"fa2-integrate\"`\n * and `\"fa2-to-scene\"`, so every member of `KernelId` is present and the assertion is exact.\n */\nconst REGISTRY: Readonly<Partial<Record<KernelId, KernelEntry>>> = Object.freeze({\n degree: DEGREE,\n reduce: REDUCE,\n fill: FILL,\n \"segmented-reduce\": SEGMENTED_REDUCE,\n \"fa2-stats-finalize\": FA2_STATS_FINALIZE,\n \"fa2-attraction\": FA2_ATTRACTION,\n \"fa2-repulsion-exact\": FA2_REPULSION_EXACT,\n \"fa2-speed-finalize\": FA2_SPEED_FINALIZE,\n \"fa2-integrate\": FA2_INTEGRATE,\n \"fa2-to-scene\": FA2_TO_SCENE,\n});\n\n/** THE registry (spec 3.5): every entry, keyed by id. */\nexport const KERNELS: Readonly<Record<KernelId, KernelEntry>> = REGISTRY as Readonly<Record<KernelId, KernelEntry>>;\n\n/** The bodies installed by setKernelBodyOverride (the sabotage seam of spec 11.9 item 1), by id. */\nconst bodyOverrides = new Map<KernelId, string>();\n\n/**\n * The entry of an id, or E_INVALID_ARGUMENT for an id that is not (yet) registered.\n * @param id - the module id\n * @returns the entry\n */\nfunction entryOf(id: KernelId): KernelEntry {\n const entry = REGISTRY[id];\n if (entry === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `unknown kernel id \"${id}\"`, {\n argument: \"id\",\n value: id,\n expected: Object.keys(REGISTRY),\n });\n }\n return entry;\n}\n\n/**\n * A WgslModuleSpec for a variant: the entry plus the overrides / snippets given; unknown override names are\n * rejected at compose time. A body override installed by setKernelBodyOverride is used instead of the entry's\n * body.\n * @param id - the module id\n * @param overrides - the override values of this variant (the five standard names and the entry's overrideDecls)\n * @param snippets - the texts substituted at the body's `//@@NAME@@` markers\n * @returns the spec the PipelineCache compiles\n */\nexport function kernelSpec(\n id: KernelId,\n overrides?: Readonly<Record<string, number | boolean>>,\n snippets?: Readonly<Record<string, string>>,\n): WgslModuleSpec {\n const entry = entryOf(id);\n return {\n id: entry.id,\n body: bodyOverrides.get(id) ?? entry.body,\n bindings: entry.bindings,\n overrideDecls: entry.overrideDecls,\n overrides: overrides ?? {},\n needs: entry.needs,\n uniforms: entry.uniforms,\n snippets,\n };\n}\n\n/**\n * The sabotage seam (spec 11.9 item 1): replaces an entry's body for specs created afterwards (null restores).\n * Tests use a FRESH context per mutation because the pipeline key does not include the body.\n * @internal\n * @param id - the module id\n * @param body - the replacement body, or null to restore the normative one\n */\nexport function setKernelBodyOverride(id: KernelId, body: string | null): void {\n entryOf(id);\n if (body === null) {\n bodyOverrides.delete(id);\n } else {\n bodyOverrides.set(id, body);\n }\n}\n\n/**\n * The group-0 graph bindings of a core with the dummy rules applied (spec 3.5, 4.1): colIdx <- rowPtr when null,\n * weights <- colIdx ?? rowPtr when null, perm <- rowPtr when null. `weights` is the binding to use in the weights\n * slot: omitted -> core.weights (degree, segmented-reduce); a layout passes its RESOLVED weights\n * (ModelResources.weights, 3.13), null meaning \"attract with 1.0\" even on a weighted snapshot.\n * @param core - the resident core arrays of a snapshot\n * @param perm - the degreeOrder row permutation, or null (rowPtr is bound as the dummy)\n * @param weights - the weights binding to use; undefined takes the core's, null binds the colIdx dummy\n * @returns the four bindings in slot order\n */\nexport function graphBindings(\n core: CoreBinding,\n perm: Binding | null,\n weights?: Binding | null,\n): Readonly<Record<\"rowPtr\" | \"colIdx\" | \"weights\" | \"perm\", Binding>> {\n const colIdx = core.colIdx ?? core.rowPtr;\n const resolved = weights === undefined ? core.weights : weights;\n return {\n rowPtr: core.rowPtr,\n colIdx,\n weights: resolved ?? colIdx,\n perm: perm ?? core.rowPtr,\n };\n}\n\n/**\n * The override values graphBindings implies: USE_PERM = perm !== null, HAS_WEIGHTS = (weights === undefined ?\n * core.weights : weights) !== null.\n * @param core - the resident core arrays of a snapshot\n * @param perm - the row permutation binding, or null\n * @param weights - the weights binding to use; undefined takes the core's, null means \"unweighted\"\n * @returns the two standard override values of the variant\n */\nexport function graphOverrides(\n core: CoreBinding,\n perm: Binding | null,\n weights?: Binding | null,\n): Readonly<{ USE_PERM: boolean; HAS_WEIGHTS: boolean }> {\n const resolved = weights === undefined ? core.weights : weights;\n return { USE_PERM: perm !== null, HAS_WEIGHTS: resolved !== null };\n}\n","/**\n * `degree(ctx, s)` -- the walking-skeleton algorithm, kept public as a diagnostic (spec 3.3, 11.5): the out-degree of\n * every node computed on the device by the row-walking `degree` kernel (4.5) over the resident core of the snapshot,\n * with the group-0 dummy-binding pattern of spec 3.5 (`colIdx` in the `weights` slot when the snapshot is unweighted,\n * `rowPtr` in the `perm` slot because P1-P3 pass no row permutation, so `USE_PERM` is false). The result equals\n * `snapshot.outDegree()`; the point of the kernel is to prove the upload, bind, dispatch and readback path end to end\n * on every adapter (bitwise identical across adapters, spec 11.5), not to be faster than the CPU (the README says\n * so).\n *\n * Contract (3.12): `ctx.assertReady()` first; `nodeCount === 0` returns an empty `Uint32Array` (or `dest`) with no\n * GPU work (spec 5.6: there is no work, which is not a fallback); an already-aborted `signal` is `E_ABORTED` before\n * any work; `dest` must be a `Uint32Array` of length n over an `ArrayBuffer`; a windowed core is `E_TOO_LARGE\n * { path: \"windowed\", algorithm: \"degree\" }` until P4 executes windows -- `residency.core()` (3.8) throws that error\n * itself with `algorithm: null` before it would ever return a windowed `CoreBinding`, so `degree` catches it and\n * re-throws the same error with `algorithm: \"degree\"` (the 3.12 detail) instead of testing `core.plan`, which never\n * observes \"windowed\" in P1-P3; `arcCount === 0` skips the dispatch (only `rowPtr` is resident)\n * and the result is zeros; otherwise ONE dispatch over rows [0, n) with `accumulate = 0` (every row is written, so no\n * fill precedes it), a readback into the result, `onProgress(1, 1)`, and the scratch returned in a finally. Two runs\n * are bitwise identical (spec 11.9 item 4).\n */\n\nimport { type GraphSnapshot, type U32 } from \"@graphty/graph-format\";\n\nimport { type GpuContext } from \"../context.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { isWebGpuGraphError, WebGpuGraphError } from \"../errors.js\";\nimport { plan1d } from \"../kernel/dispatch.js\";\nimport { graphBindings, graphOverrides, kernelSpec, RANGE_PARAMS } from \"../kernels.js\";\nimport { type CoreBinding } from \"../memory/residency.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type GpuRunOptions } from \"../types/run.js\";\n\n/**\n * Validates `options.dest` for a result of `n` elements.\n * @param dest - the caller's destination array, if any\n * @param n - the node count\n * @returns the destination as a U32, or null when none was given\n */\nfunction checkDest(dest: Float32Array | Uint32Array | undefined, n: number): U32 | null {\n if (dest === undefined) {\n return null;\n }\n if (dest instanceof Uint32Array && dest.length === n && dest.buffer instanceof ArrayBuffer) {\n return dest as U32;\n }\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `degree: dest must be a Uint32Array of length ${n} over an ArrayBuffer`,\n {\n argument: \"dest\",\n value: `${dest.constructor.name}(${dest.length})`,\n expected: `Uint32Array(${n}) over an ArrayBuffer`,\n },\n );\n}\n\n/**\n * Uploads (or finds) the core through the residency; a windowed plan, which the residency reports as `E_TOO_LARGE\n * { path: \"windowed\", algorithm: null }` (3.8), is re-thrown with `algorithm: \"degree\"` (3.12) and its other details\n * (`needed`, `limit`, `path`) kept. Every other error passes through untouched.\n * @param ctx - the context whose residency holds the core\n * @param s - the snapshot\n * @returns the resident core binding (arena or perArray)\n */\nfunction coreOf(ctx: GpuContext, s: GraphSnapshot): CoreBinding {\n try {\n return ctx.residency.core(s);\n } catch (error: unknown) {\n if (isWebGpuGraphError(error) && error.code === \"E_TOO_LARGE\" && error.details.path === \"windowed\") {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n \"degree: the arc arrays need a windowed upload, which P1-P3 plan but do not execute\",\n { ...error.details, algorithm: \"degree\" },\n );\n }\n throw error;\n }\n}\n\n/**\n * The walking-skeleton kernel, kept public as a diagnostic (spec 3.3): out-degree per node through the row-walking\n * gather with the USE_PERM dummy pattern; equals snapshot.outDegree().\n * @param ctx - the context whose device runs the kernel\n * @param s - the snapshot (uploaded through ctx.residency, or found there)\n * @param options - dest / signal / onProgress (spec 3.3). PLAN DECISION: spelled `?: GpuRunOptions` rather than the\n * contract's `?: GpuRunOptions | undefined` because the root ESLint rule no-duplicate-type-constituents rejects the\n * explicit undefined on an optional parameter (the call signature is identical; P1-T3 made the same choice).\n * @returns the out-degree of every node, index-aligned (`dest` itself when given)\n */\nexport async function degree(ctx: GpuContext, s: GraphSnapshot, options?: GpuRunOptions): Promise<U32> {\n ctx.assertReady();\n const n = s.nodeCount;\n const dest = checkDest(options?.dest, n);\n if (options?.signal?.aborted) {\n throw new WebGpuGraphError(\"E_ABORTED\", \"degree: the signal was aborted before any work started\", {});\n }\n if (n === 0) {\n options?.onProgress?.(1, 1);\n return dest ?? new Uint32Array(0);\n }\n const core = coreOf(ctx, s);\n if (s.arcCount === 0) {\n const zeros = dest ?? new Uint32Array(n);\n zeros.fill(0);\n options?.onProgress?.(1, 1);\n return zeros;\n }\n const byteLength = n * 4;\n const out = ctx.pool.acquire(\n byteLength,\n BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST,\n \"degree/out\",\n );\n const params = ctx.pool.acquire(\n RANGE_PARAMS.byteLength,\n BufferUsage.UNIFORM | BufferUsage.COPY_DST,\n \"degree/params\",\n );\n try {\n await ctx.allocator.check();\n const kernel = await ctx.pipelines.kernel(kernelSpec(\"degree\", graphOverrides(core, null)));\n const bytes = new ArrayBuffer(RANGE_PARAMS.byteLength);\n RANGE_PARAMS.write(new DataView(bytes), { start: 0, end: n, arcBase: 0, arcEnd: s.arcCount, accumulate: 0, n });\n ctx.device.queue.writeBuffer(params, 0, bytes);\n const outBinding: Binding = { buffer: out, offset: 0, size: byteLength, window: null };\n const paramsBinding: Binding = { buffer: params, offset: 0, size: RANGE_PARAMS.byteLength, window: null };\n const bound = kernel.bind({ ...graphBindings(core, null), out: outBinding, P: paramsBinding });\n const encoder = ctx.device.createCommandEncoder({ label: \"degree\" });\n const pass = encoder.beginComputePass({ label: \"degree\" });\n kernel.dispatch(pass, bound, plan1d(n, ctx.workgroupSize, ctx.caps), [0]);\n pass.end();\n ctx.device.queue.submit([encoder.finish()]);\n ctx.assertReady();\n const result = await ctx.readback.read(out, byteLength, dest ?? undefined);\n ctx.assertReady();\n options?.onProgress?.(1, 1);\n return dest ?? new Uint32Array(result);\n } finally {\n ctx.pool.release(params);\n ctx.pool.release(out);\n }\n}\n","/**\n * The CommandBatch of spec 5.8: one GPUCommandEncoder, one compute pass per \"phase\" (a pass may hold\n * many dispatches; dispatches inside a pass are ordered), the staging copies of every readback\n * request at the end, and ONE queue.submit. The batch borrows one slot of the Readback ring for its\n * lifetime (spec 4.4) and returns it when its readback settles -- resolved, discarded or rejected --\n * so the ring never grows because of a slot left pending. mapAsync on that slot is the completion\n * signal; a batch never calls onSubmittedWorkDone.\n *\n * Errors (spec 5.7): under Dawn-node an uncapturederror is delivered SYNCHRONOUSLY inside the API\n * call that fails, so an error pending in the context's slot when submit() runs belongs to this batch\n * and rejects ITS OWN readback (an invalid command buffer is a no-op submit; the staging bytes would be\n * stale). In browsers delivery is asynchronous: the batch takes the slot again after its map completes,\n * and whatever arrives later is thrown by the context's next public call. Device loss is raced against\n * the map, so a readback rejects E_DEVICE_LOST whether the runtime rejects, resolves or never settles\n * the pending map of a destroyed buffer; the slot goes back only once the map has settled (or the grace\n * ran out), because a staging buffer is never unmapped while its map is pending (readback.ts).\n */\n\nimport type { AllocationTracker } from \"../device/error-scope.js\";\nimport { deviceLostError } from \"../device/lost.js\";\nimport { isWebGpuGraphError, WebGpuGraphError } from \"../errors.js\";\nimport type { Readback, StagingSlot } from \"../memory/readback.js\";\nimport type { Binding } from \"../types/memory.js\";\nimport type { Profiler } from \"./profiler.js\";\n\n/** How long a batch waits for the context's loss fan-out after its map rejected with a foreign error (a destroyed buffer rejects before device.lost settles), and for the runtime to settle a pending map after the loss won the race. */\nconst LOSS_GRACE_MS = 2000;\n\n/**\n * Resolves when the promise settles either way, or after the grace (a runtime that never settles a pending map).\n * @param pending - the promise\n * @param graceMs - the ceiling\n */\nasync function settled(pending: Promise<unknown>, graceMs: number): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const grace = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, graceMs);\n });\n await Promise.race([\n pending.then(\n () => undefined,\n () => undefined,\n ),\n grace,\n ]);\n clearTimeout(timer);\n}\n\n/**\n * A plain message for a thrown value (the house pattern of graph-io's report.ts).\n * @param error - whatever the runtime rejected with\n * @returns the Error message, the string itself, or a typeof note\n */\nfunction messageOf(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === \"string\") {\n return error;\n }\n return `non-error thrown (${typeof error})`;\n}\n\n/** What a CommandBatch needs of its owner (GpuContext satisfies it structurally; kernel/ never imports context.ts). */\nexport interface BatchHost {\n readonly device: GPUDevice;\n readonly readback: Readback;\n readonly profiler: Profiler | null;\n readonly allocator: AllocationTracker;\n assertReady(): void;\n takePendingError(): WebGpuGraphError | null;\n nextBatchId(): number;\n /** Registers a device-loss listener and returns the unregister function (GpuContext.onLost, contract 3.5): the batch races its map against loss. PLAN DECISION 1: an amendment to contract 3.9, which declares the seven members above. */\n onLost(listener: (info: GPUDeviceLostInfo) => void): () => void;\n}\n\n/** A readback scheduled into the batch's staging slot: `offset` is the slot-relative byte offset the caller reads at. */\nexport interface ReadbackRequest {\n readonly src: GPUBuffer;\n readonly srcOffset: number;\n readonly byteLength: number;\n readonly offset: number;\n}\n\n/** What submit() returns (spec 5.8). `readback` resolves with the mapped bytes COPIED out (one ArrayBuffer holding every request at its offset) after allocator.check(); it rejects with E_VALIDATION { batchId } when the pending-error slot held an error right after submit and with E_DEVICE_LOST after loss; a discarded batch resolves an empty ArrayBuffer (see discard()). */\nexport interface SubmittedBatch {\n readonly id: number;\n readonly generation: number;\n readonly readback: Promise<ArrayBuffer>;\n /** Marks the batch stale: its readback still awaits mapAsync (so the slot is returned) but resolves with an empty ArrayBuffer and the caller ignores it (spec 7.19 item 6). */\n discard(): void;\n}\n\n/** The discard flag shared by a handle and its readback. */\ninterface DiscardState {\n discarded: boolean;\n}\n\n/** Records dispatches / copies into one encoder and submits once (spec 5.8). */\nexport class CommandBatch {\n readonly id: number;\n readonly generation: number;\n readonly label: string;\n private readonly host: BatchHost;\n private readonly encoder: GPUCommandEncoder;\n private readonly requests: ReadbackRequest[] = [];\n private openPass: GPUComputePassEncoder | null = null;\n private dispatchCount = 0;\n private stagingBytes = 0;\n private slot: StagingSlot | null = null;\n private submitted = false;\n\n /**\n * Creates the encoder; the id comes from host.nextBatchId().\n * @param host - the owner (the GpuContext)\n * @param label - names the encoder, its passes and the E_VALIDATION details\n * @param generation - the simulation generation the batch carries (default 0)\n */\n constructor(host: BatchHost, label: string, generation?: number) {\n this.host = host;\n this.id = host.nextBatchId();\n this.generation = generation ?? 0;\n this.label = label;\n this.encoder = host.device.createCommandEncoder({ label: `batch/${label}#${this.id}` });\n }\n\n /**\n * Dispatch count recorded so far (tests bound it).\n * @returns the number of dispatchWorkgroups / dispatchWorkgroupsIndirect calls on this batch's passes\n */\n get dispatches(): number {\n return this.dispatchCount;\n }\n\n /**\n * Begins a compute pass (ending the previous one); with a profiler present the pass carries timestampWrites and\n * `label` names it in Profiler.resolveInto / timings.\n * @param label - the pass name\n * @returns the pass encoder kernels dispatch into\n */\n pass(label: string): GPUComputePassEncoder {\n this.assertOpen(\"pass\");\n this.endPass();\n const descriptor: GPUComputePassDescriptor = { label: `batch/${this.label}#${this.id}/${label}` };\n const timestampWrites = this.host.profiler?.beginPass(label);\n if (timestampWrites !== undefined) {\n descriptor.timestampWrites = timestampWrites;\n }\n const pass = this.encoder.beginComputePass(descriptor);\n this.countDispatches(pass);\n this.openPass = pass;\n return pass;\n }\n\n /** Ends the open pass, if any. */\n endPass(): void {\n if (this.openPass !== null) {\n this.openPass.end();\n this.openPass = null;\n }\n }\n\n /**\n * copyBufferToBuffer between two bindings (after endPass).\n * @param src - the source range\n * @param dst - the destination range\n * @param byteLength - a positive multiple of 4 no larger than either binding\n */\n copy(src: Binding, dst: Binding, byteLength: number): void {\n this.assertOpen(\"copy\");\n this.checkByteLength(byteLength);\n if (byteLength > src.size || byteLength > dst.size) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `copy of ${byteLength} bytes exceeds a binding (src ${src.size}, dst ${dst.size})`,\n {\n argument: \"byteLength\",\n value: byteLength,\n expected: `<= ${Math.min(src.size, dst.size)}`,\n },\n );\n }\n this.endPass();\n this.encoder.copyBufferToBuffer(src.buffer, src.offset, dst.buffer, dst.offset, byteLength);\n }\n\n /**\n * Schedules a copy of `byteLength` bytes from `src` into the borrowed staging slot; the slot is borrowed at the\n * first request and re-borrowed larger when the sum of requests outgrows it (nothing is recorded before submit).\n * @param src - the source buffer\n * @param srcOffset - a non-negative multiple of 4\n * @param byteLength - a positive multiple of 4 with srcOffset + byteLength <= src.size\n * @returns the request; `offset` is where the caller reads inside the readback bytes\n */\n readback(src: GPUBuffer, srcOffset: number, byteLength: number): ReadbackRequest {\n this.assertOpen(\"readback\");\n this.checkByteLength(byteLength);\n if (!Number.isInteger(srcOffset) || srcOffset < 0 || srcOffset % 4 !== 0 || srcOffset + byteLength > src.size) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `readback of [${srcOffset}, ${srcOffset + byteLength}) is outside the ${src.size}-byte source or not 4-aligned`,\n {\n argument: \"srcOffset\",\n value: srcOffset,\n expected: `a multiple of 4 with srcOffset + byteLength <= ${src.size}`,\n },\n );\n }\n const request: ReadbackRequest = { src, srcOffset, byteLength, offset: this.stagingBytes };\n this.requests.push(request);\n this.stagingBytes += byteLength;\n this.ensureSlot(this.stagingBytes);\n return request;\n }\n\n /**\n * Records `resolveQuerySet` after ending the open pass; used by Profiler.resolveInto only.\n * @internal\n * @param querySet - the timestamp query set\n * @param firstQuery - first query index\n * @param queryCount - number of queries\n * @param destination - a QUERY_RESOLVE | COPY_SRC buffer written at offset 0\n */\n resolveQuerySet(querySet: GPUQuerySet, firstQuery: number, queryCount: number, destination: GPUBuffer): void {\n this.assertOpen(\"resolveQuerySet\");\n this.endPass();\n this.encoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, 0);\n }\n\n /**\n * Ends passes, records the staging copies, submits, checks the pending-error slot (spec 5.7), returns the handle.\n * A batch can be submitted once; submit() after device loss throws E_DEVICE_LOST.\n * @returns the submitted-batch handle\n */\n submit(): SubmittedBatch {\n this.assertOpen(\"submit\");\n this.submitted = true;\n this.endPass();\n const { slot } = this;\n const pendingBefore = this.host.takePendingError();\n try {\n this.host.assertReady();\n } catch (error) {\n this.releaseSlot();\n throw error;\n }\n if (slot !== null) {\n for (const request of this.requests) {\n this.encoder.copyBufferToBuffer(\n request.src,\n request.srcOffset,\n slot.buffer,\n request.offset,\n request.byteLength,\n );\n }\n }\n const commandBuffer = this.encoder.finish({ label: `batch/${this.label}#${this.id}` });\n this.host.device.queue.submit([commandBuffer]);\n // the slot is drained a second time so a finish() / submit() error raised by a command buffer the first error\n // already invalidated never leaks to the next public call; the FIRST error is the one reported\n const pendingAfter = this.host.takePendingError();\n const pending = pendingBefore ?? pendingAfter;\n const state: DiscardState = { discarded: false };\n const readback = pending === null ? this.awaitReadback(slot, state) : this.rejectReadback(pending);\n return {\n id: this.id,\n generation: this.generation,\n readback,\n discard: (): void => {\n state.discarded = true;\n },\n };\n }\n\n private rejectReadback(pending: WebGpuGraphError): Promise<ArrayBuffer> {\n this.releaseSlot();\n return Promise.reject(this.attribute(pending));\n }\n\n private async awaitReadback(slot: StagingSlot | null, state: DiscardState): Promise<ArrayBuffer> {\n if (slot === null) {\n await this.host.allocator.check();\n return new ArrayBuffer(0);\n }\n const total = this.stagingBytes;\n let unregister: () => void = (): void => undefined;\n const lost = new Promise<never>((_resolve, reject) => {\n unregister = this.host.onLost((info) => {\n reject(deviceLostError(info));\n });\n });\n void lost.catch(() => undefined);\n const mapped = this.host.readback.mapSlot(slot, total);\n void mapped.catch(() => undefined);\n let bytes: ArrayBuffer;\n try {\n await Promise.race([mapped, lost]);\n this.host.assertReady();\n bytes = state.discarded ? new ArrayBuffer(0) : slot.buffer.getMappedRange(0, total).slice(0);\n } catch (error) {\n // the loss may have won the race: let the runtime settle the map before the slot is unmapped and returned\n await settled(mapped, LOSS_GRACE_MS);\n this.releaseSlot();\n throw await this.classify(error, lost);\n } finally {\n unregister();\n }\n this.releaseSlot();\n await this.host.allocator.check();\n return bytes;\n }\n\n private async classify(error: unknown, lost: Promise<never>): Promise<WebGpuGraphError> {\n if (isWebGpuGraphError(error)) {\n return error.code === \"E_DEVICE_LOST\" || error.code === \"E_DISPOSED\" ? error : this.attribute(error);\n }\n try {\n this.host.assertReady();\n } catch (state) {\n if (isWebGpuGraphError(state)) {\n return state.code === \"E_DEVICE_LOST\" || state.code === \"E_DISPOSED\" ? state : this.attribute(state);\n }\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const grace = new Promise<null>((resolve) => {\n timer = setTimeout(() => {\n resolve(null);\n }, LOSS_GRACE_MS);\n });\n const late = await Promise.race([\n lost.then(\n () => null,\n (reason: unknown) => reason,\n ),\n grace,\n ]);\n clearTimeout(timer);\n if (isWebGpuGraphError(late)) {\n return late;\n }\n const message = messageOf(error);\n return new WebGpuGraphError(\n \"E_VALIDATION\",\n `mapAsync failed for batch ${this.id} \"${this.label}\": ${message}`,\n {\n label: this.label,\n message,\n batchId: this.id,\n },\n );\n }\n\n private attribute(error: WebGpuGraphError): WebGpuGraphError {\n return new WebGpuGraphError(error.code, `${error.message} (delivered to batch ${this.id} \"${this.label}\")`, {\n ...error.details,\n batchId: this.id,\n batchLabel: this.label,\n });\n }\n\n private ensureSlot(byteLength: number): void {\n if (this.slot !== null && this.slot.capacity >= byteLength) {\n return;\n }\n this.releaseSlot();\n this.slot = this.host.readback.borrowSlot(byteLength);\n }\n\n private releaseSlot(): void {\n if (this.slot === null) {\n return;\n }\n const { slot } = this;\n this.slot = null;\n try {\n this.host.readback.returnSlot(slot);\n } catch (error) {\n if (!isWebGpuGraphError(error) || error.code !== \"E_DISPOSED\") {\n throw error;\n }\n }\n }\n\n private countDispatches(pass: GPUComputePassEncoder): void {\n const direct = pass.dispatchWorkgroups.bind(pass);\n const indirect = pass.dispatchWorkgroupsIndirect.bind(pass);\n pass.dispatchWorkgroups = (x: number, y?: number, z?: number): undefined => {\n this.dispatchCount += 1;\n direct(x, y, z);\n return undefined;\n };\n pass.dispatchWorkgroupsIndirect = (buffer: GPUBuffer, offset: number): undefined => {\n this.dispatchCount += 1;\n indirect(buffer, offset);\n return undefined;\n };\n }\n\n private assertOpen(operation: string): void {\n if (this.submitted) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${operation}() after submit() on batch ${this.id} \"${this.label}\"`,\n {\n argument: operation,\n value: this.id,\n expected: \"a batch that has not been submitted\",\n },\n );\n }\n }\n\n private checkByteLength(byteLength: number): void {\n if (!Number.isInteger(byteLength) || byteLength <= 0 || byteLength % 4 !== 0) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `byteLength ${byteLength} is not a positive multiple of 4`,\n {\n argument: \"byteLength\",\n value: byteLength,\n expected: \"a positive multiple of 4\",\n },\n );\n }\n }\n}\n","/**\n * The UniformRing of spec 5.3: one UNIFORM buffer holding UNIFORM_SLOT_BYTES-stride slots for the\n * per-iteration params of a batch. A batch reserves k contiguous slots, writes their values into the\n * host shadow, flushes them with ONE queue.writeBuffer and records k dispatches that select their slot\n * through a dynamic offset -- no per-iteration writeBuffer and no host round trip. The stride is 256\n * because minUniformBufferOffsetAlignment is 256 on every runtime the package targets (the Dawn-node\n * ADAPTER advertises 64, which the package never requests; spec 2.6).\n */\n\nimport { UNIFORM_SLOT_BYTES } from \"../constants.js\";\nimport type { AllocationTracker } from \"../device/error-scope.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport type { Binding } from \"../types/memory.js\";\nimport type { UniformBlock, UniformValues } from \"./struct-block.js\";\n\n/** One UNIFORM buffer with UNIFORM_SLOT_BYTES-stride slots for the per-iteration params of a batch (spec 5.3). */\nexport class UniformRing {\n /** Number of slots. */\n readonly slots: number;\n private readonly device: GPUDevice;\n private readonly allocator: AllocationTracker;\n private readonly buffer: GPUBuffer;\n private readonly label: string;\n private readonly shadow: ArrayBuffer;\n private readonly view: DataView;\n private next = 0;\n private dirtyLo = -1;\n private dirtyHi = -1;\n private destroyed = false;\n\n /**\n * Creates the ring buffer (`slots x UNIFORM_SLOT_BYTES` bytes, UNIFORM | COPY_DST) through the allocator.\n * @param device - the device the buffer belongs to\n * @param allocator - the context's OOM-scoped allocator (the buffer is destroyed through it)\n * @param slots - number of slots; E_INVALID_ARGUMENT unless a positive integer\n * @param label - the buffer label\n */\n constructor(device: GPUDevice, allocator: AllocationTracker, slots: number, label: string) {\n if (!Number.isInteger(slots) || slots < 1) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformRing \"${label}\": slots must be a positive integer, got ${slots}`,\n {\n argument: \"slots\",\n value: slots,\n expected: \"an integer >= 1\",\n },\n );\n }\n this.device = device;\n this.allocator = allocator;\n this.slots = slots;\n this.label = label;\n this.shadow = new ArrayBuffer(slots * UNIFORM_SLOT_BYTES);\n this.view = new DataView(this.shadow);\n this.buffer = allocator.createBuffer({\n label,\n size: slots * UNIFORM_SLOT_BYTES,\n usage: BufferUsage.UNIFORM | BufferUsage.COPY_DST,\n });\n }\n\n /**\n * The whole-buffer binding a kernel binds once (size = the block's byteLength; the slot is the dynamic offset).\n * @param block - the params block the kernel declares for this binding\n * @returns the binding at offset 0 of the ring buffer\n */\n binding(block: UniformBlock): Binding {\n this.assertLive();\n this.assertFits(block);\n return { buffer: this.buffer, offset: 0, size: block.byteLength, window: null };\n }\n\n /**\n * Byte offset of a slot (the dynamic offset a dispatch passes for it).\n * @param slot - a slot index in [0, slots)\n * @returns slot x UNIFORM_SLOT_BYTES\n */\n offsetOf(slot: number): number {\n this.checkSlot(slot);\n return slot * UNIFORM_SLOT_BYTES;\n }\n\n /**\n * Reserves `count` contiguous slots for a batch, wrapping to 0 when the tail is too short; E_INVALID_ARGUMENT when count > slots.\n * @param count - slots needed, in [1, slots]\n * @returns the first slot of the reservation\n */\n reserve(count: number): number {\n this.assertLive();\n if (!Number.isInteger(count) || count < 1 || count > this.slots) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformRing \"${this.label}\": cannot reserve ${count} of ${this.slots} slots`,\n {\n argument: \"count\",\n value: count,\n expected: `an integer in [1, ${this.slots}]`,\n },\n );\n }\n if (this.next + count > this.slots) {\n this.next = 0;\n }\n const first = this.next;\n this.next += count;\n return first;\n }\n\n /**\n * Writes one block's values into a slot of the host shadow; `flush()` sends the dirty range with one writeBuffer.\n * @param slot - the slot to fill\n * @param block - the block whose layout the bytes follow\n * @param values - the field values (a missing field is written as 0 by the block)\n */\n write(slot: number, block: UniformBlock, values: UniformValues): void {\n this.checkSlot(slot);\n this.assertFits(block);\n block.write(this.view, values, slot * UNIFORM_SLOT_BYTES);\n if (this.dirtyLo < 0 || slot < this.dirtyLo) {\n this.dirtyLo = slot;\n }\n if (slot > this.dirtyHi) {\n this.dirtyHi = slot;\n }\n }\n\n /**\n * queue.writeBuffer of the dirty slots (called by the batch driver before submit): one call covering\n * [lowest dirty slot, highest dirty slot]; nothing when no slot is dirty.\n */\n flush(): void {\n this.assertLive();\n if (this.dirtyLo < 0) {\n return;\n }\n const begin = this.dirtyLo * UNIFORM_SLOT_BYTES;\n const end = (this.dirtyHi + 1) * UNIFORM_SLOT_BYTES;\n this.device.queue.writeBuffer(this.buffer, begin, this.shadow, begin, end - begin);\n this.dirtyLo = -1;\n this.dirtyHi = -1;\n }\n\n /** Destroys the buffer (through the allocator); idempotent. */\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n this.allocator.destroy(this.buffer);\n }\n\n private assertLive(): void {\n if (this.destroyed) {\n throw new WebGpuGraphError(\"E_DISPOSED\", `UniformRing \"${this.label}\" is destroyed`, { label: this.label });\n }\n }\n\n private checkSlot(slot: number): void {\n this.assertLive();\n if (!Number.isInteger(slot) || slot < 0 || slot >= this.slots) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformRing \"${this.label}\": slot ${slot} is outside [0, ${this.slots})`,\n {\n argument: \"slot\",\n value: slot,\n expected: `an integer in [0, ${this.slots})`,\n },\n );\n }\n }\n\n private assertFits(block: UniformBlock): void {\n if (block.byteLength > UNIFORM_SLOT_BYTES) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformRing \"${this.label}\": block ${block.name} is ${block.byteLength} bytes, a slot holds ${UNIFORM_SLOT_BYTES}`,\n { argument: \"block\", value: block.name, expected: `byteLength <= ${UNIFORM_SLOT_BYTES}` },\n );\n }\n }\n}\n","/**\n * The CPU port's random number generator, bit for bit, and the NaN-row seeding both paths share (spec 7.2 \"Initial\n * positions\", 9.3 seedPositions, 7.14 `pos`, 7.19 topology change): a seed gives the same start on the CPU and the\n * GPU because both write the same f32 values in index order. The package carries its own copy of the LCG for its\n * whole life (D27: it cannot import @graphty/layout); W1 cross-tests it against the real RandomNumberGenerator.\n */\n\nimport type { F32, GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { WebGpuGraphError } from \"../errors.js\";\n\n/** The CPU port's LCG constants (layout/src/utils/random.ts): m = 2^35 - 31, a = 185852, c = 1. */\nexport const LCG_M = 34359738337;\n/** The multiplier a of the port's LCG. */\nexport const LCG_A = 185852;\n/** The increment c of the port's LCG. */\nexport const LCG_C = 1;\n\n/**\n * The port's RandomNumberGenerator, bit for bit: `seed || Math.floor(Math.random() * 1000000)` (seed 0 / null =\n * unseeded, the quirk preserved), state = seed % m, next = (a * state + c) % m, value = state / m. The product\n * a * state stays below 2^53 (a < 2^18, state < 2^35), so every step is exact in f64, as it is in the port.\n */\nexport class Lcg {\n /** The seed actually used (a random one when unseeded). */\n readonly seed: number;\n\n private state: number;\n\n /**\n * Creates the generator; a seed of 0, -0, NaN or null means unseeded (the port's `seed || random` quirk).\n * @param seed - the seed, or null for a random seed\n */\n constructor(seed: number | null) {\n this.seed = seed === null || seed === 0 || Number.isNaN(seed) ? Math.floor(Math.random() * 1000000) : seed;\n this.state = this.seed % LCG_M;\n }\n\n /**\n * Next value in [0, 1).\n * @returns state / m after one LCG step\n */\n next(): number {\n this.state = (LCG_A * this.state + LCG_C) % LCG_M;\n return this.state / LCG_M;\n }\n}\n\n/**\n * The three center components of a CommonLayoutOptions.center (missing components are 0).\n * @param center - the caller's center, or null\n * @returns [x, y, z]; E_INVALID_ARGUMENT when a component is not finite\n */\nfunction resolveCenter(center: ArrayLike<number> | null): [number, number, number] {\n const out: [number, number, number] = [0, 0, 0];\n if (center === null) {\n return out;\n }\n for (let axis = 0; axis < 3 && axis < center.length; axis++) {\n const v = center[axis];\n if (!Number.isFinite(v)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `center[${axis}] is not finite`, {\n argument: \"center\",\n value: v,\n expected: \"finite components\",\n });\n }\n out[axis] = v;\n }\n return out;\n}\n\n/**\n * Seeds the unseeded rows of the owner's stride-3 SCENE array in index order (spec 9.3 seedPositions, 7.14 `pos`,\n * 7.19 topology change): a row is unseeded when any of its `dim` components is not finite; every such component\n * draws one LCG value; when NO row is fully finite the draw is uniform in [-1, 1) layout units per axis (`range:\n * \"fa2\"`; `\"fr\"` is [0, 1)), otherwise uniform inside the [min, max] box of the finite components per axis,\n * converted to layout units (an axis with no finite value falls back to the range box); the value is written as\n * `v * scale + center[axis]`, which for scale 1 / center 0 is bit-identical to the port's `u * 2 - 1` (resp. `u`);\n * in 2D the third component of a seeded row is written as center[2]. Finite components are never changed and a\n * fully finite row is never touched. No random number is drawn when nothing needs seeding.\n * PLAN DECISION 12 (P3-T1): the box is taken over every finite COMPONENT (the port's rule), not over the fully\n * finite ROWS only; the two differ only when a partially finite row's finite axis lies outside the fully finite\n * rows' box (pinned by test/layouts/seed.test.ts). PLAN DECISION 13: a 2D row whose x and y are finite is seeded\n * whatever its z holds.\n * @param s - the snapshot (nodeCount rows)\n * @param positions - the owner's stride-3 scene-unit array, length 3 * nodeCount, modified in place\n * @param seed - the LCG seed (0 / null = unseeded, the port's quirk)\n * @param dim - 2 or 3\n * @param scale - the scene scale (> 0)\n * @param center - the scene center, or null for the origin\n * @param range - \"fa2\" for [-1, 1), \"fr\" for [0, 1)\n */\nexport function seedPositions(\n s: GraphSnapshot,\n positions: F32,\n seed: number | null,\n dim: 2 | 3,\n scale: number,\n center: ArrayLike<number> | null,\n range: \"fa2\" | \"fr\",\n): void {\n const n = s.nodeCount;\n if (dim !== 2 && dim !== 3) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `dim must be 2 or 3, got ${String(dim)}`, {\n argument: \"dim\",\n value: dim,\n expected: \"2 or 3\",\n });\n }\n if (positions.length !== 3 * n) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `positions has ${positions.length} entries, expected ${3 * n}`,\n {\n argument: \"positions\",\n value: positions.length,\n expected: 3 * n,\n },\n );\n }\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `scale must be a finite number > 0, got ${scale}`, {\n argument: \"scale\",\n value: scale,\n expected: \"a finite number > 0\",\n });\n }\n const c = resolveCenter(center);\n\n // classify the rows and collect the per-axis box of the finite components (scene units)\n const lo = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY];\n const hi = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY];\n let finiteRows = 0;\n let unseededRows = 0;\n for (let i = 0; i < n; i++) {\n let finite = true;\n for (let axis = 0; axis < dim; axis++) {\n const v = positions[3 * i + axis];\n if (Number.isFinite(v)) {\n if (v < lo[axis]) {\n lo[axis] = v;\n }\n if (v > hi[axis]) {\n hi[axis] = v;\n }\n } else {\n finite = false;\n }\n }\n if (finite) {\n finiteRows++;\n } else {\n unseededRows++;\n }\n }\n if (unseededRows === 0) {\n return;\n }\n\n // the per-axis draw box in layout units\n const rangeLo = range === \"fr\" ? 0 : -1;\n const rangeHi = 1;\n const boxLo = [rangeLo, rangeLo, rangeLo];\n const boxHi = [rangeHi, rangeHi, rangeHi];\n if (finiteRows > 0) {\n for (let axis = 0; axis < dim; axis++) {\n if (Number.isFinite(lo[axis]) && Number.isFinite(hi[axis])) {\n boxLo[axis] = (lo[axis] - c[axis]) / scale;\n boxHi[axis] = (hi[axis] - c[axis]) / scale;\n }\n }\n }\n\n const rng = new Lcg(seed);\n for (let i = 0; i < n; i++) {\n let unseeded = false;\n for (let axis = 0; axis < dim; axis++) {\n if (!Number.isFinite(positions[3 * i + axis])) {\n unseeded = true;\n }\n }\n if (!unseeded) {\n continue;\n }\n for (let axis = 0; axis < dim; axis++) {\n const at = 3 * i + axis;\n if (!Number.isFinite(positions[at])) {\n const u = rng.next();\n const v = boxLo[axis] + u * (boxHi[axis] - boxLo[axis]);\n positions[at] = v * scale + c[axis];\n }\n }\n if (dim === 2) {\n positions[3 * i + 2] = c[2];\n }\n }\n}\n","/**\n * The shared layout state machine (spec 7.19): the buffers every model shares (positions, scenePositions, fixed,\n * partials, state + trace), the in-flight batches and their readbacks, the settle window, the fixed mask and the\n * setPosition override list (spec 7.12), the trace and the batch driver; consumes a ForceModel by composition (the\n * per-model kernel sequence, buffers, overrides, per-iteration params, controller hooks and stats decoding).\n * Positions are layout units on the device and scene units in the owner's array (spec 7.18): load() repacks\n * (scene - center) / scale into vec4f with the mass in .w (D23); the model's toScene stage, recorded once per batch\n * on the last iteration (PLAN DECISION 2), writes p * scale + center back into scenePositions.\n */\n\nimport { type F32, type GraphSnapshot, makeMask, maskTest, type NodeMask, type U32 } from \"@graphty/graph-format\";\n\nimport {\n FA2_DEFAULTS,\n FA2_FLAG_FIRST,\n MAX_1D_ITEMS,\n MAX_ITERATIONS_PER_STEP,\n PARTIAL_BYTES,\n STATE_HEADER_BYTES,\n UNIFORM_SLOT_BYTES,\n} from \"../constants.js\";\nimport { type GpuContext } from \"../context.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { hasErrorCode, WebGpuGraphError } from \"../errors.js\";\nimport { CommandBatch, type ReadbackRequest, type SubmittedBatch } from \"../kernel/batch.js\";\nimport { type PipelineCache } from \"../kernel/pipeline-cache.js\";\nimport { type UniformBlock, type UniformFieldType, type UniformValues } from \"../kernel/struct-block.js\";\nimport { UniformRing } from \"../kernel/uniform-ring.js\";\nimport { type WgslModuleSpec } from \"../kernel/wgsl.js\";\nimport { graphOverrides } from \"../kernels.js\";\nimport { type ArrayBinding, type CoreBinding } from \"../memory/residency.js\";\nimport { type PlanCaps } from \"../types/context.js\";\nimport {\n type GpuLayoutSimulation,\n type LayoutStatsBase,\n type ResolvedLayoutTuning,\n type RunOptions,\n} from \"../types/layout.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type CommonLayoutOptions, type SimulationOptions } from \"../types/options.js\";\nimport { type ResolvedWeights } from \"./inputs.js\";\nimport { seedPositions } from \"./seed.js\";\n\n// ============================================================ the model hook interface (contract 3.13)\n\n/** A model-owned buffer beyond the shared set (spec 7.19: oldForce, velocity, the grid tier's). */\nexport interface BufferSpec {\n readonly name: string;\n readonly byteLength: number;\n readonly usage: number;\n readonly zero: boolean;\n}\n\n/** Host writes into the state header collected between submits (spec 7.19 onLoad / onReheat / onSetParams). */\nexport interface StateWriter {\n /** Queues a field write (flushed by one writeBuffer before the next submit; also applied to the host shadow immediately). */\n set(field: string, value: number | readonly number[]): void;\n /** The host shadow of a field (last known value). */\n get(field: string): number | readonly number[];\n}\n\n/** What a model gets at bind time (after load() / a resize): the graph, the shared and model buffers, the ring, the cache. */\nexport interface ModelResources {\n readonly device: GPUDevice;\n readonly caps: PlanCaps;\n readonly pipelines: PipelineCache;\n readonly core: CoreBinding;\n readonly perm: Binding | null;\n /**\n * The RESOLVED weights binding (model.inputs(): source \"arcs\" -> core.weights (null on an unweighted snapshot),\n * \"column\" -> the registered ArrayBinding's binding, \"none\" -> null); group 0 is built as\n * graphBindings(core, perm, weights) (3.10).\n */\n readonly weights: Binding | null;\n readonly n: number;\n readonly dim: 2 | 3;\n readonly tier: \"exact\" | \"grid\";\n readonly ring: UniformRing;\n /** A shared or model-owned buffer by name: \"positions\", \"scenePositions\", \"fixed\", \"partials\", \"state\", \"trace\", plus every BufferSpec name. */\n buffer(name: string): Binding;\n}\n\n/** The per-load inputs a model resolves from the snapshot and its options (mass into the `.w` lane; weights into the group-0 slot). */\nexport interface ModelInputs {\n readonly mass: F32;\n readonly weights: ResolvedWeights;\n}\n\n/**\n * Spec 7.19 ForceModel (kind, buffers, overrides, paramsFor, recordIteration, onLoad, onReheat, onSetParams,\n * readStats) with SEVEN additions (CONTRACT DECISION, each with its reason): `stages` (the kernel stage names for\n * debugRunStages / inspect, spec 11.9 item 2); `params` (the model's uniform block, which must declare the shared\n * field names n, dim, flags, iterationIndex, seed, scale, center, settleThreshold, so the simulation can write\n * them); `state` and `trace` (the model's generated Fa2State / Fa2Trace blocks, so the simulation allocates,\n * initialises and decodes the state buffer through the model's own layouts, D20); `specs` (the module specs of an\n * override set, for warm() and the compile matrix); `bind` (the model compiles and binds after load(), when the\n * buffers exist); `inputs` (mass and weight resolution need the model's option names -- nodeMass / weight are\n * ForceAtlas2Options, not CommonLayoutOptions -- so the simulation calls it at load() and derives USE_PERM /\n * HAS_WEIGHTS from ModelResources, 3.10); and the optional `upTo` argument of `recordIteration` (truncates the\n * sequence after a stage, for debugRunStages / inspect). PLAN DECISION 4: the state block must declare centroid,\n * min, max (vec4f), rmsRadius, radius, meanDisplacement (f32), iteration, settledCount (u32) and fit in\n * STATE_HEADER_BYTES; the params block must declare the eight shared names with center a vec4f and fit in\n * UNIFORM_SLOT_BYTES. PLAN DECISION 6: paramsFor receives the GLOBAL iteration index; the shared fields win.\n * PLAN DECISION 2: recordIteration with `upTo` undefined records EVERY stage (toScene included); `upTo = <stage>`\n * stops after that stage.\n */\nexport interface ForceModel<Options, Stats extends LayoutStatsBase> {\n readonly kind: \"forceatlas2\" | \"fruchtermanReingold\" | \"springElectrical\";\n readonly stages: readonly string[];\n readonly params: UniformBlock;\n readonly state: UniformBlock;\n readonly trace: UniformBlock;\n buffers(n: number, dim: 2 | 3): readonly BufferSpec[];\n /** Called at load() before the upload: FA2 = { mass: resolveNodeMass(s, nodeMass), weights: resolveWeights(s, weight) }. */\n inputs(s: GraphSnapshot, options: Options): ModelInputs;\n /** The model's OWN override set; the simulation merges USE_PERM / HAS_WEIGHTS from graphOverrides(core, perm, resources.weights) before specs() / bind(). */\n overrides(options: Options): Readonly<Record<string, number | boolean>>;\n specs(overrides: Readonly<Record<string, number | boolean>>, subgroups: boolean): readonly WgslModuleSpec[];\n bind(resources: ModelResources, overrides: Readonly<Record<string, number | boolean>>): Promise<void>;\n paramsFor(iteration: number, options: Options): UniformValues;\n recordIteration(batch: CommandBatch, slot: number, tier: \"exact\" | \"grid\", upTo?: string): void;\n onLoad(state: StateWriter): void;\n onReheat(state: StateWriter): void;\n onSetParams(patch: Partial<Options>, state: StateWriter): void;\n readStats(state: DataView, trace: DataView): Stats;\n}\n\n// ============================================================ module-private helpers\n\n/** The shared params fields (name, width) every model params block must declare (PLAN DECISION 4). */\nconst SHARED_PARAM_FIELDS: readonly (readonly [string, number])[] = [\n [\"n\", 1],\n [\"dim\", 1],\n [\"flags\", 1],\n [\"iterationIndex\", 1],\n [\"seed\", 1],\n [\"scale\", 1],\n [\"center\", 4],\n [\"settleThreshold\", 1],\n];\n\n/** The state fields (name, width) the simulation writes at load() and reads after every batch (PLAN DECISION 4). */\nconst SHARED_STATE_FIELDS: readonly (readonly [string, number])[] = [\n [\"centroid\", 4],\n [\"min\", 4],\n [\"max\", 4],\n [\"rmsRadius\", 1],\n [\"radius\", 1],\n [\"meanDisplacement\", 1],\n [\"iteration\", 1],\n [\"settledCount\", 1],\n];\n\n/** The names of the shared buffers a BufferSpec may not reuse. */\nconst SHARED_BUFFER_NAMES: readonly string[] = [\"positions\", \"scenePositions\", \"fixed\", \"partials\", \"state\", \"trace\"];\n\n/** The per-batch epilogue stage: iterations 0..k-2 stop after the stage that precedes it (PLAN DECISION 2). */\nconst EPILOGUE_STAGE = \"toScene\";\n\nlet simulationCounter = 0;\n\n/**\n * An E_INVALID_ARGUMENT with the documented details shape.\n * @param argument - the argument name\n * @param value - the offending value\n * @param expected - what was expected\n * @param message - the message\n * @returns the error\n */\nfunction invalidArgument(argument: string, value: unknown, expected: unknown, message: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", message, { argument, value, expected });\n}\n\n/**\n * The E_DISPOSED of a simulation.\n * @param label - the simulation label\n * @returns the error\n */\nfunction disposedError(label: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_DISPOSED\", `${label} is disposed`, { label });\n}\n\n/**\n * Coerces a caught value to an Error for Promise rejections.\n * @param err - the caught value\n * @returns the value when it is an Error, else a wrapping Error\n */\nfunction asError(err: unknown): Error {\n if (err instanceof Error) {\n return err;\n }\n return new Error(typeof err === \"string\" ? err : \"unknown error\");\n}\n\n/**\n * Reads a field of an option record the generic type does not name (maxIter, iterations, nodeSize).\n * @param record - the options or patch\n * @param key - the field name\n * @returns the value, or undefined\n */\nfunction optionField(record: object, key: string): unknown {\n return (record as Record<string, unknown>)[key];\n}\n\n/**\n * The number of scalars of a uniform field type.\n * @param type - the field type\n * @returns 1, 2 or 4\n */\nfunction fieldWidth(type: UniformFieldType): number {\n switch (type) {\n case \"u32\":\n case \"i32\":\n case \"f32\":\n return 1;\n case \"vec2f\":\n case \"vec2u\":\n return 2;\n case \"vec4f\":\n case \"vec4u\":\n return 4;\n default:\n throw invalidArgument(\"type\", type, \"a UniformFieldType\", \"unknown uniform field type\");\n }\n}\n\n/**\n * The type of a block field, or null when the block does not declare it.\n * @param block - the block\n * @param field - the field name\n * @returns the type or null\n */\nfunction fieldTypeOrNull(block: UniformBlock, field: string): UniformFieldType | null {\n for (const [name, type] of block.fields) {\n if (name === field) {\n return type;\n }\n }\n return null;\n}\n\n/**\n * The type of a block field.\n * @param block - the block\n * @param field - the field name\n * @returns the type; E_INVALID_ARGUMENT when the block does not declare the field\n */\nfunction fieldTypeOf(block: UniformBlock, field: string): UniformFieldType {\n const type = fieldTypeOrNull(block, field);\n if (type === null) {\n throw invalidArgument(\n \"field\",\n field,\n block.fields.map((f) => f[0]),\n `block ${block.name} has no field ${field}`,\n );\n }\n return type;\n}\n\n/**\n * Asserts a block declares every (name, width) pair (PLAN DECISION 4).\n * @param block - the block\n * @param required - the required fields\n * @param what - \"model.params\" or \"model.state\", for the error\n */\nfunction requireFields(block: UniformBlock, required: readonly (readonly [string, number])[], what: string): void {\n for (const [field, width] of required) {\n const type = fieldTypeOrNull(block, field);\n if (type === null) {\n throw invalidArgument(\n what,\n field,\n required.map((r) => r[0]),\n `${what} block ${block.name} must declare ${field}`,\n );\n }\n if (fieldWidth(type) !== width) {\n throw invalidArgument(\n what,\n field,\n `a field of width ${width}`,\n `${what}.${field} must have width ${width}`,\n );\n }\n }\n}\n\n/**\n * A stable string of an override record, for the law-change comparison of setParams.\n * @param record - the overrides\n * @returns the JSON of the sorted entries\n */\nfunction stableKey(record: Readonly<Record<string, number | boolean>>): string {\n return JSON.stringify(\n Object.keys(record)\n .sort()\n .map((k) => [k, record[k]]),\n );\n}\n\n/**\n * The stats record with msPerIteration filled by the simulation (PLAN DECISION 3).\n * @param stats - the model's record\n * @param msPerIteration - the measured value\n * @returns the record\n */\nfunction withMs<S extends LayoutStatsBase>(stats: S, msPerIteration: number | null): S {\n return { ...stats, msPerIteration };\n}\n\n/**\n * True for a SharedArrayBuffer (the package never writes into one, spec 5.7).\n * @param buffer - the backing buffer\n * @returns true when shared\n */\nfunction isSharedBuffer(buffer: ArrayBufferLike): boolean {\n return typeof SharedArrayBuffer !== \"undefined\" && buffer instanceof SharedArrayBuffer;\n}\n\n/**\n * The validated scale of an option record (FA2_DEFAULTS.scale when absent).\n * @param options - the options\n * @returns the scale\n */\nfunction scaleOf(options: CommonLayoutOptions): number {\n const scale = options.scale ?? FA2_DEFAULTS.scale;\n if (!Number.isFinite(scale) || scale <= 0) {\n throw invalidArgument(\"scale\", scale, \"a finite number > 0\", `scale must be a finite number > 0, got ${scale}`);\n }\n return scale;\n}\n\n/**\n * The validated center of an option record (missing components are 0).\n * @param options - the options\n * @returns [x, y, z]\n */\nfunction centerOf(options: CommonLayoutOptions): [number, number, number] {\n const out: [number, number, number] = [0, 0, 0];\n const { center } = options;\n if (center === undefined) {\n return out;\n }\n for (let axis = 0; axis < 3 && axis < center.length; axis++) {\n const v = center[axis];\n if (!Number.isFinite(v)) {\n throw invalidArgument(\"center\", v, \"finite components\", `center[${axis}] is not finite`);\n }\n out[axis] = v;\n }\n return out;\n}\n\n/**\n * The repulsion tier of a node count under a tuning (PLAN DECISION 11).\n * @param tuning - the resolved tuning\n * @param n - the node count\n * @returns \"exact\" or \"grid\"\n */\nfunction tierFor(tuning: ResolvedLayoutTuning, n: number): \"exact\" | \"grid\" {\n if (tuning.repulsion === \"exact\") {\n return \"exact\";\n }\n if (tuning.repulsion === \"grid\") {\n return \"grid\";\n }\n return n <= tuning.exactMaxNodes ? \"exact\" : \"grid\";\n}\n\n/**\n * A whole-buffer binding.\n * @param buffer - the buffer\n * @param size - its byte length\n * @returns the binding\n */\nfunction wholeBinding(buffer: GPUBuffer, size: number): Binding {\n return { buffer, offset: 0, size, window: null };\n}\n\n/**\n * The host side of the state header (PLAN DECISION 5): a shadow of every field, a queue of the fields set since\n * the last flush, and the byte image the queued fields are copied from.\n */\nclass HeaderWriter implements StateWriter {\n private readonly block: UniformBlock;\n private readonly shadow = new Map<string, number | readonly number[]>();\n private readonly queued = new Map<string, number | readonly number[]>();\n\n /**\n * Creates a writer over a model's state block with every field 0.\n * @param block - the model's state block\n */\n constructor(block: UniformBlock) {\n this.block = block;\n this.reset();\n }\n\n /**\n * Queues a field write and applies it to the shadow.\n * @param field - the field name (E_INVALID_ARGUMENT when the block lacks it or the width differs)\n * @param value - a number for a scalar field, an array of the vector's width otherwise\n */\n set(field: string, value: number | readonly number[]): void {\n const width = fieldWidth(fieldTypeOf(this.block, field));\n const ok = width === 1 ? typeof value === \"number\" : typeof value !== \"number\" && value.length === width;\n if (!ok) {\n throw invalidArgument(\n \"value\",\n value,\n `a value of width ${width}`,\n `state field ${field} takes a value of width ${width}`,\n );\n }\n this.shadow.set(field, value);\n this.queued.set(field, value);\n }\n\n /**\n * The host shadow of a field: the last value set, or the last landed header's value.\n * @param field - the field name\n * @returns the value\n */\n get(field: string): number | readonly number[] {\n const value = this.shadow.get(field);\n if (value === undefined) {\n throw invalidArgument(\n \"field\",\n field,\n this.block.fields.map((f) => f[0]),\n `state block has no field ${field}`,\n );\n }\n return value;\n }\n\n /** Every field back to 0 and the queue cleared (load()). */\n reset(): void {\n this.shadow.clear();\n this.queued.clear();\n const zero = this.block.read(new DataView(new ArrayBuffer(this.block.byteLength)));\n for (const [name, value] of Object.entries(zero)) {\n this.shadow.set(name, value);\n }\n }\n\n /**\n * The byte image of the shadow (the block's own writer, D20).\n * @returns block.byteLength bytes\n */\n headerBytes(): ArrayBuffer {\n const bytes = new ArrayBuffer(this.block.byteLength);\n this.block.write(new DataView(bytes), Object.fromEntries(this.shadow));\n return bytes;\n }\n\n /**\n * Refreshes the shadow from a landed header; a field set since the last flush keeps its queued value.\n * @param view - the landed header\n */\n absorb(view: DataView): void {\n for (const [name, value] of Object.entries(this.block.read(view))) {\n if (!this.queued.has(name)) {\n this.shadow.set(name, value);\n }\n }\n }\n\n /**\n * The fields set since the last flush; clears the queue.\n * @returns the field names\n */\n takeQueued(): string[] {\n const fields = [...this.queued.keys()];\n this.queued.clear();\n return fields;\n }\n\n /** Drops the queue (after load() wrote the whole header). */\n clearQueued(): void {\n this.queued.clear();\n }\n}\n\n/** One batch from the step() call that created it until its readback settled (PLAN DECISION 7). */\ninterface PendingBatch {\n readonly k: number;\n readonly generation: number;\n readonly promise: Promise<void>;\n readonly resolve: () => void;\n readonly reject: (error: Error) => void;\n id: number;\n submitted: SubmittedBatch | null;\n stale: boolean;\n startedAt: number;\n sceneOffset: number;\n stateOffset: number;\n profile: ReadbackRequest | null;\n}\n\n/**\n * A pending record whose promise the simulation settles.\n * @param k - iterations of the batch\n * @param generation - the generation at the step() call\n * @returns the record\n */\nfunction createPending(k: number, generation: number): PendingBatch {\n let resolveFn: () => void = () => undefined;\n let rejectFn: (error: Error) => void = () => undefined;\n const promise = new Promise<void>((resolve, reject) => {\n resolveFn = resolve;\n rejectFn = reject;\n });\n return {\n k,\n generation,\n promise,\n resolve: () => {\n resolveFn();\n },\n reject: (error: Error) => {\n rejectFn(error);\n },\n id: 0,\n submitted: null,\n stale: false,\n startedAt: 0,\n sceneOffset: 0,\n stateOffset: 0,\n profile: null,\n };\n}\n\n/** The simulation's buffers of one load() (spec 7.3) plus the name -> Binding map the model and inspect() read. */\ninterface SimulationBuffers {\n readonly positions: GPUBuffer;\n readonly scene: GPUBuffer;\n readonly fixed: GPUBuffer;\n readonly partials: GPUBuffer;\n readonly state: GPUBuffer;\n readonly model: ReadonlyMap<string, { readonly buffer: GPUBuffer; readonly spec: BufferSpec }>;\n readonly bindings: ReadonlyMap<string, Binding>;\n readonly traceRegionBytes: number;\n}\n\n/** The registered expanded weight column of the current load (re-expanded only when column.version changed). */\ninterface WeightsUpload {\n readonly serial: number;\n readonly column: object;\n readonly version: number;\n readonly data: F32;\n readonly upload: ArrayBinding;\n}\n\n// ============================================================ the simulation\n\n/**\n * The shared layout state machine (spec 7.19): buffers, in-flight batches, readback, settle window, fixed mask,\n * setPosition overrides, trace, batch driver; consumes a ForceModel by composition.\n */\nexport class ForceSimulation<\n Options extends CommonLayoutOptions & SimulationOptions,\n Stats extends LayoutStatsBase,\n> implements GpuLayoutSimulation<Options, Stats> {\n readonly ctx: GpuContext;\n readonly model: ForceModel<Options, Stats>;\n readonly tuning: ResolvedLayoutTuning;\n /**\n * The uniform ring, sized (maxInFlight + 1) x MAX_ITERATIONS_PER_STEP slots at construction (CONTRACT DECISION:\n * reserve() wraps to 0 when the tail is short, so maxInFlight batches of up to MAX_ITERATIONS_PER_STEP slots\n * plus one wasted tail always fit without a slot being rewritten while a submitted batch still reads it; hence\n * setParams cannot change maxInFlight, 3.13 forceatlas2.ts).\n * @internal\n */\n readonly ring: UniformRing;\n /**\n * Present when ctx.debug.inspect is true: reads back any named buffer (a shared name, a BufferSpec name,\n * \"force\", \"state\", \"trace\") after the last submitted kernel; resolves a Float32Array except for \"fixed\",\n * \"trace\" (raw words) which resolve Uint32Array.\n */\n inspect?: (name: string) => Promise<Float32Array | Uint32Array>;\n /**\n * Present when ctx.debug.inspect is true: records ONE iteration truncated after stage `upTo` (a model stage\n * name), submits, awaits it (no readback into positions, no stats update).\n * @internal\n */\n debugRunStages?: (upTo: string) => Promise<void>;\n\n private readonly resolveOptions: (patch: Partial<Options>, current: Options) => Options;\n private readonly maxInFlight: number;\n private readonly label: string;\n private readonly traceBytes: number;\n private readonly writer: HeaderWriter;\n private readonly overrideList = new Map<number, number>();\n private readonly pending: PendingBatch[] = [];\n private readonly unregisterLost: () => void;\n private optionsValue: Options;\n private stateValue: \"created\" | \"loaded\" | \"disposed\" = \"created\";\n private generationValue = 0;\n private tierValue: \"exact\" | \"grid\";\n private dimValue: 2 | 3;\n private snapshot: GraphSnapshot | null = null;\n private serial: number | null = null;\n private owner: F32 | null = null;\n private n = 0;\n private scale = 1;\n private center: [number, number, number] = [0, 0, 0];\n private buffers: SimulationBuffers | null = null;\n private core: CoreBinding | null = null;\n private resources: ModelResources | null = null;\n private weightsUpload: WeightsUpload | null = null;\n private ready: Promise<void> = Promise.resolve();\n private submitChain: Promise<void> = Promise.resolve();\n private fixedWords: U32 = new Uint32Array(0);\n private fixedDirty = false;\n private iterationsSubmitted = 0;\n private iterationsDoneValue = 0;\n private settledCountValue = 0;\n private settledValue = false;\n private firstPending = true;\n private statsValue: Stats | null = null;\n private lastSubmittedBatchIdValue = 0;\n /** The id of the last batch submitted BEFORE the most recent reheat() (PLAN DECISION 21); 0 = none. */\n private reheatedAfterBatchId = 0;\n private coalescedValue = 0;\n private torndown = false;\n\n /**\n * Creates a simulation over a context and a model (state \"created\"; load() makes it \"loaded\").\n * @param ctx - the context (ready)\n * @param model - the force model\n * @param options - the option record (defaults applied by the caller's factory)\n * @param tuning - the resolved GPU tuning\n * @param resolve - how setParams merges a patch into the current record\n */\n constructor(\n ctx: GpuContext,\n model: ForceModel<Options, Stats>,\n options: Options,\n tuning: ResolvedLayoutTuning,\n resolve: (patch: Partial<Options>, current: Options) => Options,\n ) {\n ctx.assertReady();\n requireFields(model.params, SHARED_PARAM_FIELDS, \"model.params\");\n requireFields(model.state, SHARED_STATE_FIELDS, \"model.state\");\n if (model.params.byteLength > UNIFORM_SLOT_BYTES) {\n throw invalidArgument(\n \"model.params\",\n model.params.byteLength,\n `<= ${UNIFORM_SLOT_BYTES} bytes`,\n \"the params block must fit one ring slot\",\n );\n }\n if (model.state.byteLength > STATE_HEADER_BYTES) {\n throw invalidArgument(\n \"model.state\",\n model.state.byteLength,\n `<= ${STATE_HEADER_BYTES} bytes`,\n \"the state block must fit the state header\",\n );\n }\n if (model.stages.length === 0) {\n throw invalidArgument(\n \"model.stages\",\n model.stages,\n \"at least one stage name\",\n \"a model declares its stages\",\n );\n }\n const maxInFlight = options.maxInFlight ?? FA2_DEFAULTS.maxInFlight;\n if (!Number.isInteger(maxInFlight) || maxInFlight < 1) {\n throw invalidArgument(\n \"maxInFlight\",\n maxInFlight,\n \"an integer >= 1\",\n `maxInFlight must be an integer >= 1, got ${maxInFlight}`,\n );\n }\n const dim = options.dim ?? FA2_DEFAULTS.dim;\n if (dim !== 2 && dim !== 3) {\n throw invalidArgument(\"dim\", dim, \"2 or 3\", `dim must be 2 or 3, got ${String(dim)}`);\n }\n // scale and center are validated now so a bad option never reaches load()\n scaleOf(options);\n centerOf(options);\n simulationCounter++;\n this.ctx = ctx;\n this.model = model;\n this.tuning = tuning;\n this.resolveOptions = resolve;\n this.optionsValue = options;\n this.maxInFlight = maxInFlight;\n this.dimValue = dim;\n this.tierValue = tuning.repulsion === \"grid\" ? \"grid\" : \"exact\";\n this.label = `${model.kind}#${simulationCounter}`;\n this.traceBytes = model.trace.byteLength;\n this.writer = new HeaderWriter(model.state);\n this.ring = new UniformRing(\n ctx.device,\n ctx.allocator,\n (maxInFlight + 1) * MAX_ITERATIONS_PER_STEP,\n `${this.label}/ring`,\n );\n this.unregisterLost = ctx.onLost((info) => {\n this.onDeviceLost(info);\n });\n if (ctx.debug.inspect) {\n this.inspect = (name: string): Promise<Float32Array | Uint32Array> => this.inspectBuffer(name);\n this.debugRunStages = (upTo: string): Promise<void> => this.runStages(upTo);\n }\n }\n\n // ---------------------------------------------------------------- read-only state\n\n /**\n * \"created\" | \"loaded\" | \"disposed\".\n * @returns the state\n */\n get state(): \"created\" | \"loaded\" | \"disposed\" {\n return this.stateValue;\n }\n\n /**\n * The current options record (defaults applied).\n * @returns the record\n */\n get options(): Options {\n return this.optionsValue;\n }\n\n /**\n * The repulsion tier of the current load (\"exact\" until P4 lifts the grid tier).\n * @returns the tier\n */\n get tier(): \"exact\" | \"grid\" {\n return this.tierValue;\n }\n\n /**\n * The generation counter bumped by every load() (stale readbacks are discarded).\n * @internal\n * @returns the generation\n */\n get generation(): number {\n return this.generationValue;\n }\n\n /**\n * Nodes of the current load (0 before load()).\n * @returns the node count\n */\n get nodeCount(): number {\n return this.n;\n }\n\n /**\n * 2 or 3, fixed at construction (setParams({ dim }) is rejected, spec 7.13).\n * @returns the dimension\n */\n get dim(): 2 | 3 {\n return this.dimValue;\n }\n\n /**\n * iterationsDone >= the budget OR settledCount >= settleWindow of the last completed batch (spec 7.17); true for an empty graph.\n * @returns whether the layout is settled\n */\n get settled(): boolean {\n return this.settledValue;\n }\n\n /**\n * Batches created by step() and not yet landed (PLAN DECISION 7: counted from the step() call).\n * @returns the count\n */\n get inFlight(): number {\n return this.pending.length;\n }\n\n /**\n * Iterations landed since load() or the last reheat().\n * @returns the count\n */\n get iterationsDone(): number {\n return this.iterationsDoneValue;\n }\n\n /**\n * The stats of the last completed batch; before one lands, the host-written header decoded through the model\n * with an empty trace and msPerIteration null.\n * @returns the stats\n */\n get stats(): Stats {\n if (this.statsValue !== null) {\n return this.statsValue;\n }\n const header = new DataView(this.writer.headerBytes());\n const trace = new DataView(new ArrayBuffer(0));\n return withMs(this.model.readStats(header, trace), null);\n }\n\n /**\n * The override list (spec 7.12): rows whose readback is skipped while a batch older than the write is in flight.\n * @internal\n * @returns row -> lastSubmittedBatchId at the write\n */\n get overrides(): ReadonlyMap<number, number> {\n return this.overrideList;\n }\n\n /**\n * The last submitted batch id.\n * @internal\n * @returns the id (0 before any submit)\n */\n get lastSubmittedBatchId(): number {\n return this.lastSubmittedBatchIdValue;\n }\n\n /**\n * Number of step() calls that returned an existing batch's promise instead of submitting (spec 7.19 item 3;\n * read by test/helpers/frame-loop.ts).\n * @internal\n * @returns the count\n */\n get coalesced(): number {\n return this.coalescedValue;\n }\n\n // ---------------------------------------------------------------- load\n\n /**\n * Uploads the snapshot's core, seeds the NaN rows of `positions`, repacks it into layout-unit vec4f with the\n * mass in .w, writes the initial state, starts the model's compile + bind and enters \"loaded\" (spec 7.19; a\n * load() during flight bumps the generation and discards the in-flight batches). Order of the checks (PLAN\n * DECISION 16): E_DISPOSED, the context's assertReady, E_SNAPSHOT (directed), E_TOO_LARGE (nodeCount), the\n * positions array, the tuning, then the core upload and model.inputs() BEFORE any state is touched.\n * PLAN DECISION 10: nodeCount 0 loads with no GPU work at all. PLAN DECISION 11: the tier is resolved here\n * and \"grid\" is E_UNSUPPORTED until P4. PLAN DECISION 17: a same-size load() keeps the buffers and re-zeroes\n * partials, the trace region and every `zero: true` model buffer.\n * @param snapshot - an undirected snapshot\n * @param positions - the owner's stride-3 scene-unit array (NaN rows are seeded in place)\n */\n load(snapshot: GraphSnapshot, positions: F32): void {\n this.assertNotDisposed();\n this.ctx.assertReady();\n if (snapshot.directed) {\n throw new WebGpuGraphError(\n \"E_SNAPSHOT\",\n \"a layout needs an undirected snapshot: pass toUndirected().snapshot\",\n {\n reason: \"directed\",\n serial: snapshot.serial,\n },\n );\n }\n const n = snapshot.nodeCount;\n if (n > MAX_1D_ITEMS) {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `${n} nodes exceed ${MAX_1D_ITEMS} (the third partials level is P4)`,\n {\n needed: n,\n limit: MAX_1D_ITEMS,\n path: \"partials\",\n algorithm: this.model.kind,\n },\n );\n }\n if (positions.length !== 3 * n) {\n throw invalidArgument(\n \"positions\",\n positions.length,\n 3 * n,\n `positions has ${positions.length} entries, expected ${3 * n}`,\n );\n }\n if (isSharedBuffer(positions.buffer)) {\n throw invalidArgument(\n \"positions\",\n \"SharedArrayBuffer\",\n \"an ArrayBuffer-backed Float32Array\",\n \"positions must not be backed by a SharedArrayBuffer\",\n );\n }\n const scale = scaleOf(this.optionsValue);\n const center = centerOf(this.optionsValue);\n const tier = tierFor(this.tuning, n);\n if (tier === \"grid\") {\n throw new WebGpuGraphError(\n \"E_UNSUPPORTED\",\n `the grid repulsion tier lands at P4 (n = ${n}, exactMaxNodes = ${this.tuning.exactMaxNodes})`,\n {\n feature: \"repulsion.grid\",\n hint: 'pass repulsion: \"exact\" or raise exactMaxNodes',\n },\n );\n }\n const positionsBytes = 16 * n;\n if (positionsBytes > this.ctx.caps.limits.maxBufferSize) {\n throw new WebGpuGraphError(\"E_TOO_LARGE\", `${positionsBytes} bytes of positions exceed maxBufferSize`, {\n needed: positionsBytes,\n limit: this.ctx.caps.limits.maxBufferSize,\n path: \"positions\",\n algorithm: this.model.kind,\n });\n }\n let core: CoreBinding | null = null;\n let inputs: ModelInputs | null = null;\n if (n > 0) {\n core = this.ctx.residency.core(snapshot);\n if (core.plan === \"windowed\") {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n \"a windowed core cannot be walked by the layout kernels until P4\",\n {\n needed: snapshot.arcCount,\n limit: this.ctx.caps.limits.maxStorageBufferBindingSize,\n path: \"windowed\",\n algorithm: this.model.kind,\n },\n );\n }\n inputs = this.model.inputs(snapshot, this.optionsValue);\n if (inputs.mass.length !== n) {\n throw invalidArgument(\n \"nodeMass\",\n inputs.mass.length,\n n,\n `the model resolved ${inputs.mass.length} masses for ${n} nodes`,\n );\n }\n }\n\n // ---- every check passed: mutate\n this.generationValue++;\n this.discardPending();\n const resized = this.buffers === null || n !== this.n || snapshot.serial !== this.serial;\n this.snapshot = snapshot;\n this.serial = snapshot.serial;\n this.owner = positions;\n this.n = n;\n this.tierValue = tier;\n this.scale = scale;\n this.center = center;\n this.core = core;\n this.iterationsSubmitted = 0;\n this.iterationsDoneValue = 0;\n this.settledCountValue = 0;\n this.firstPending = true;\n this.statsValue = null;\n this.writer.reset();\n if (resized) {\n this.destroyBuffers();\n this.overrideList.clear();\n this.fixedWords = makeMask(n);\n this.fixedDirty = false;\n }\n if (n === 0 || core === null || inputs === null) {\n // PLAN DECISION 10: an empty graph loads with no GPU work\n this.weightsUpload = null;\n this.resources = null;\n // keep the chain (PLAN DECISION 20): a bind of the previous load may still be running and the next\n // non-empty load() must start its bind after it; its outcome is irrelevant here\n this.ready = this.ready.catch(() => undefined);\n this.settledValue = true;\n this.stateValue = \"loaded\";\n return;\n }\n const buffers = resized ? this.allocate(n) : this.requireBuffers();\n if (!resized) {\n this.clearKept(buffers);\n }\n this.buffers = buffers;\n const range = this.model.kind === \"fruchtermanReingold\" ? \"fr\" : \"fa2\";\n seedPositions(snapshot, positions, this.optionsValue.seed ?? null, this.dimValue, scale, center, range);\n this.uploadPositions(buffers, positions, inputs.mass);\n const weights = this.resolveWeightsBinding(snapshot, core, inputs.weights);\n const overrides = { ...this.model.overrides(this.optionsValue), ...graphOverrides(core, null, weights) };\n const resources = this.makeResources(core, weights, buffers);\n this.resources = resources;\n this.startBind(resources, overrides);\n this.settledValue = false;\n this.stateValue = \"loaded\";\n }\n\n // ---------------------------------------------------------------- step and the batch driver\n\n /**\n * Submits k iterations (spec 7.19 items 1-6): \"created\" -> E_NOT_LOADED; \"disposed\" -> E_DISPOSED; a released\n * snapshot -> E_RELEASED; k outside [1, MAX_ITERATIONS_PER_STEP] -> E_INVALID_ARGUMENT; settled -> resolves at\n * once; inFlight >= maxInFlight -> the OLDEST pending batch's promise (coalesced); else the batch is queued on\n * the submit chain (after the bind promise and allocator.check()) and its promise resolves when its readback\n * landed in the owner's array. The same promise object is returned for every coalesced call. PLAN DECISION 7:\n * the batch counts in `inFlight` from this call, not from its submission.\n * @param iterations - k (default options.iterationsPerStep, default 1)\n * @returns resolves when the batch landed (or was discarded); rejects E_VALIDATION / E_DEVICE_LOST / E_OUT_OF_MEMORY / E_SHADER_COMPILE\n */\n step(iterations?: number): Promise<void> {\n if (this.stateValue === \"created\") {\n return Promise.reject(\n new WebGpuGraphError(\"E_NOT_LOADED\", `${this.label}: load() first`, { state: \"created\" }),\n );\n }\n if (this.stateValue === \"disposed\") {\n return Promise.reject(disposedError(this.label));\n }\n try {\n this.ctx.assertReady();\n } catch (err) {\n return Promise.reject(asError(err));\n }\n const { snapshot } = this;\n if (snapshot !== null && this.ctx.residency.isReleased(snapshot.serial)) {\n return Promise.reject(\n new WebGpuGraphError(\n \"E_RELEASED\",\n `snapshot ${snapshot.serial} was released while ${this.label} used it`,\n {\n serial: snapshot.serial,\n },\n ),\n );\n }\n const k = iterations ?? this.optionsValue.iterationsPerStep ?? FA2_DEFAULTS.iterationsPerStep;\n if (!Number.isInteger(k) || k < 1 || k > MAX_ITERATIONS_PER_STEP) {\n return Promise.reject(\n invalidArgument(\n \"iterations\",\n k,\n `an integer in [1, ${MAX_ITERATIONS_PER_STEP}]`,\n `step(${k}): iterations must be an integer in [1, ${MAX_ITERATIONS_PER_STEP}]`,\n ),\n );\n }\n if (this.settledValue || this.n === 0) {\n return Promise.resolve();\n }\n if (this.pending.length >= this.maxInFlight) {\n this.coalescedValue++;\n return this.pending[0].promise;\n }\n const record = createPending(k, this.generationValue);\n this.pending.push(record);\n this.submitChain = this.submitChain.then(() => this.submitBatch(record));\n return record.promise;\n }\n\n /**\n * Resolves when nothing is in flight (every pending batch landed or was discarded).\n * @returns the promise\n */\n async flush(): Promise<void> {\n while (this.pending.length > 0) {\n await Promise.allSettled(this.pending.map((r) => r.promise));\n }\n }\n\n /**\n * Node batch driver: loops step(batch) until settled, the budget (`maxIter ?? options.maxIter`, PLAN DECISION\n * 1) is reached or the signal aborts (E_ABORTED; the batch in flight at the abort is discarded, spec 5.7 / Q-15).\n * @param options - maxIter, batch (default 8), signal\n * @returns the stats of the last completed batch\n */\n async run(options?: RunOptions): Promise<Stats> {\n this.assertNotDisposed();\n const batch = options?.batch ?? 8;\n if (!Number.isInteger(batch) || batch < 1 || batch > MAX_ITERATIONS_PER_STEP) {\n throw invalidArgument(\n \"batch\",\n batch,\n `an integer in [1, ${MAX_ITERATIONS_PER_STEP}]`,\n \"run(): batch must be an integer in [1, MAX_ITERATIONS_PER_STEP]\",\n );\n }\n const budget = options?.maxIter ?? this.iterationBudget();\n if (Number.isNaN(budget) || budget < 0) {\n throw invalidArgument(\"maxIter\", budget, \"a number >= 0\", \"run(): maxIter must be >= 0\");\n }\n const signal = options?.signal;\n const onAbort = (): void => {\n this.discardPending();\n };\n if (signal !== undefined) {\n if (signal.aborted) {\n throw this.abortedError();\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n try {\n while (!this.settled && this.iterationsDoneValue < budget) {\n if (signal?.aborted === true) {\n throw this.abortedError();\n }\n const k = Math.min(batch, budget - this.iterationsDoneValue);\n await this.step(k);\n }\n if (signal?.aborted === true) {\n throw this.abortedError();\n }\n return this.stats;\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n // ---------------------------------------------------------------- pins, drags, reheat, params\n\n /**\n * Copies the mask words (spec 7.12): E_INVALID_ARGUMENT when shorter than ceil(n / 32); the buffer is marked\n * dirty and re-uploaded before the next submit; reheat() iff some bit went 1 -> 0 (an unpin). PLAN DECISION\n * 18: the comparison is bit by bit below n (bits at or above n never count as an unpin).\n * @param mask - the NodeMask (LSB-first words)\n */\n setFixed(mask: NodeMask): void {\n this.assertLoaded();\n const { n } = this;\n const words = Math.ceil(n / 32);\n if (mask.length < words) {\n throw invalidArgument(\n \"mask\",\n mask.length,\n words,\n `setFixed: the mask has ${mask.length} words, ${words} needed for ${n} nodes`,\n );\n }\n let unpinned = false;\n for (let w = 0; w < words && !unpinned; w++) {\n if (this.fixedWords[w] === mask[w]) {\n continue;\n }\n const last = Math.min(n, w * 32 + 32);\n for (let i = w * 32; i < last; i++) {\n if (maskTest(this.fixedWords, i) && !maskTest(mask, i)) {\n unpinned = true;\n break;\n }\n }\n }\n this.fixedWords.set(mask.subarray(0, words));\n this.fixedDirty = true;\n if (unpinned) {\n this.reheat();\n }\n }\n\n /**\n * Writes a scene-unit position (spec 7.12): into the owner's array at once, into the device (layout units, z 0\n * in 2D, 12 bytes at 16 i, queue-ordered before the next submit), into the override list keyed by the last\n * submitted batch id, then reheat(). PLAN DECISION 18: non-finite coordinates are E_INVALID_ARGUMENT.\n * @param index - the node index (< n)\n * @param x - scene x\n * @param y - scene y\n * @param z - scene z (ignored on the device in 2D)\n */\n setPosition(index: number, x: number, y: number, z: number): void {\n this.assertLoaded();\n const { n } = this;\n if (!Number.isInteger(index) || index < 0 || index >= n) {\n throw invalidArgument(\n \"index\",\n index,\n `an integer in [0, ${n})`,\n `setPosition(${index}): index out of range`,\n );\n }\n if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)) {\n throw invalidArgument(\n \"position\",\n [x, y, z],\n \"finite coordinates\",\n \"setPosition: coordinates must be finite\",\n );\n }\n const { owner, buffers } = this;\n if (owner === null || buffers === null) {\n throw new WebGpuGraphError(\"E_NOT_LOADED\", `${this.label}: load() first`, { state: this.stateValue });\n }\n owner[3 * index] = x;\n owner[3 * index + 1] = y;\n owner[3 * index + 2] = z;\n const [cx, cy, cz] = this.center;\n const layout = new Float32Array([\n (x - cx) / this.scale,\n (y - cy) / this.scale,\n this.dimValue === 2 ? 0 : (z - cz) / this.scale,\n ]);\n this.ctx.device.queue.writeBuffer(buffers.positions, 16 * index, layout);\n this.overrideList.set(index, this.lastSubmittedBatchIdValue);\n this.reheat();\n }\n\n /**\n * iterationsDone = 0, settledCount = 0 (a queued state write), model.onReheat(writer); nothing else (D8: the\n * speed controller keeps its state). `settled` is recomputed at once (PLAN DECISION 8). Allowed before load().\n * PLAN DECISION 21: the id of the last batch submitted so far is remembered; a batch with that id or an older\n * one was computed from the pre-reheat counter, so its landed settledCount is taken as 0 (see onLanded) and a\n * drag or unpin can never leave the simulation settled through a batch that was already in flight.\n */\n reheat(): void {\n this.assertNotDisposed();\n this.iterationsDoneValue = 0;\n this.settledCountValue = 0;\n this.reheatedAfterBatchId = this.lastSubmittedBatchIdValue;\n this.writer.set(\"settledCount\", 0);\n this.model.onReheat(this.writer);\n this.settledValue = this.computeSettled();\n }\n\n /**\n * Live tuning (spec 3.3, 7.17): `dim` differing from the current -> E_INVALID_ARGUMENT; `maxInFlight` differing\n * -> E_INVALID_ARGUMENT (the ring is sized by it); a non-null `nodeSize` -> E_UNSUPPORTED; the record is\n * replaced through `resolve(patch, current)`; a change of the model's override set (a force LAW) recompiles\n * and re-binds; scale / center changes reach the next batch through the shared params of every slot (the\n * model's toScene reads them); then model.onSetParams(patch, writer) and reheat().\n * @param patch - the fields to change\n */\n setParams(patch: Partial<Options>): void {\n this.assertNotDisposed();\n const current = this.optionsValue;\n const { dim, maxInFlight } = patch;\n if (dim !== undefined && dim !== this.dimValue) {\n throw invalidArgument(\n \"dim\",\n dim,\n this.dimValue,\n \"dim is fixed at construction; graphty-element re-creates the engine on a view-mode switch (spec 7.13)\",\n );\n }\n if (maxInFlight !== undefined && maxInFlight !== this.maxInFlight) {\n throw invalidArgument(\n \"maxInFlight\",\n maxInFlight,\n this.maxInFlight,\n \"maxInFlight is fixed at construction (the uniform ring is sized by it)\",\n );\n }\n const nodeSize = optionField(patch, \"nodeSize\");\n if (nodeSize !== undefined && nodeSize !== null) {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"nodeSize (adjustSizes) is deferred (spec 7.14)\", {\n option: \"nodeSize\",\n hint: \"leave nodeSize null; the size correction ships in a later slice\",\n });\n }\n const next = this.resolveOptions(patch, current);\n const scale = scaleOf(next);\n const center = centerOf(next);\n const before = stableKey(this.model.overrides(current));\n const after = stableKey(this.model.overrides(next));\n this.optionsValue = next;\n this.scale = scale;\n this.center = center;\n const { resources, core } = this;\n if (this.stateValue === \"loaded\" && resources !== null && core !== null && before !== after) {\n const overrides = { ...this.model.overrides(next), ...graphOverrides(core, null, resources.weights) };\n this.startBind(resources, overrides);\n }\n this.model.onSetParams(patch, this.writer);\n this.reheat();\n }\n\n // ---------------------------------------------------------------- dispose and device loss\n\n /**\n * Discards in-flight batches (their promises resolve), destroys every simulation buffer and the ring, trims\n * the pool, unregisters the loss listener; state \"disposed\"; idempotent.\n */\n dispose(): void {\n if (this.stateValue === \"disposed\") {\n return;\n }\n this.stateValue = \"disposed\";\n this.teardown();\n }\n\n // ---------------------------------------------------------------- private: the batch driver\n\n /**\n * The serialised submission of one pending batch: awaits the bind / warm promise and allocator.check(), then\n * records and submits unless the record went stale meanwhile; wires the readback handlers. A record that went\n * stale while waiting (a load() or dispose() superseded it) RESOLVES even when the wait rejected (PLAN\n * DECISION 8: the rejection belongs to the superseded generation -- a bind that failed E_SHADER_COMPILE, or\n * the ring's E_DISPOSED after dispose() tore it down under a running bind).\n * @param record - the pending batch\n */\n private async submitBatch(record: PendingBatch): Promise<void> {\n try {\n await this.ready;\n await this.ctx.allocator.check();\n } catch (err) {\n this.finish(record);\n if (this.isStale(record)) {\n record.resolve();\n return;\n }\n if (hasErrorCode(err, \"E_OUT_OF_MEMORY\")) {\n this.outOfMemory();\n }\n record.reject(asError(err));\n return;\n }\n if (this.isStale(record)) {\n this.finish(record);\n record.resolve();\n return;\n }\n let submitted: SubmittedBatch;\n try {\n submitted = this.recordAndSubmit(record);\n } catch (err) {\n this.finish(record);\n record.reject(asError(err));\n return;\n }\n submitted.readback.then(\n (bytes) => {\n this.onLanded(record, bytes);\n },\n (err: unknown) => {\n this.onFailed(record, err);\n },\n );\n }\n\n /**\n * Flushes the host writes, fills k ring slots, records k iterations (only the last one runs the model's toScene\n * epilogue, PLAN DECISION 2) + the two readbacks into one CommandBatch and submits it (spec 7.19 items 4-5).\n * @param record - the pending batch\n * @returns the submitted batch\n */\n private recordAndSubmit(record: PendingBatch): SubmittedBatch {\n const buffers = this.requireBuffers();\n const { k } = record;\n const { device } = this.ctx;\n if (this.fixedDirty) {\n device.queue.writeBuffer(buffers.fixed, 0, this.fixedWords);\n this.fixedDirty = false;\n }\n this.flushStateWrites(buffers.state);\n const first = this.ring.reserve(k);\n for (let i = 0; i < k; i++) {\n const flags = i === 0 && this.firstPending ? FA2_FLAG_FIRST : 0;\n this.ring.write(first + i, this.model.params, this.paramsForSlot(this.iterationsSubmitted + i, i, flags));\n }\n this.ring.flush();\n const batch = new CommandBatch(this.ctx, `${this.label}/batch`, this.generationValue);\n const beforeEpilogue = this.lastIterationStage();\n for (let i = 0; i < k; i++) {\n // the last iteration records every stage (toScene included); the others stop before the epilogue\n this.model.recordIteration(batch, first + i, this.tierValue, i === k - 1 ? undefined : beforeEpilogue);\n }\n batch.endPass();\n const scene = batch.readback(buffers.scene, 0, 12 * this.n);\n const state = batch.readback(buffers.state, 0, STATE_HEADER_BYTES + k * this.traceBytes);\n const { profiler } = this.ctx;\n const profile = profiler === null ? null : profiler.resolveInto(batch);\n const submitted = batch.submit();\n record.submitted = submitted;\n record.id = submitted.id;\n record.sceneOffset = scene.offset;\n record.stateOffset = state.offset;\n record.profile = profile;\n record.startedAt = performance.now();\n this.lastSubmittedBatchIdValue = submitted.id;\n this.iterationsSubmitted += k;\n this.firstPending = false;\n return submitted;\n }\n\n /**\n * A landed readback (spec 7.19 item 6): stale -> discard; else the scene bytes go into the owner's array row by\n * row (skipping overridden rows, clearing overrides older than this batch), the header refreshes the shadow,\n * the stats are decoded through the model (msPerIteration from the profiler or the wall time, PLAN DECISION 3),\n * iterationsDone += k and settled is recomputed -- with the landed settledCount taken as 0 when the batch was\n * submitted before the last reheat() (PLAN DECISION 21; the header is still absorbed and the stats decoded).\n * @param record - the pending batch\n * @param bytes - the batch's readback bytes\n */\n private onLanded(record: PendingBatch, bytes: ArrayBuffer): void {\n this.finish(record);\n const { owner } = this;\n if (this.isStale(record) || owner === null) {\n record.resolve();\n return;\n }\n try {\n const { k } = record;\n const { n } = this;\n const needed = Math.max(\n record.sceneOffset + 12 * n,\n record.stateOffset + STATE_HEADER_BYTES + k * this.traceBytes,\n );\n if (bytes.byteLength < needed) {\n // a discarded readback resolves with an empty buffer\n record.resolve();\n return;\n }\n this.copyScene(owner, bytes, record);\n const header = new DataView(bytes, record.stateOffset, STATE_HEADER_BYTES);\n const trace = new DataView(bytes, record.stateOffset + STATE_HEADER_BYTES, k * this.traceBytes);\n this.writer.absorb(header);\n const settledCount = this.model.state.readField(header, \"settledCount\");\n if (typeof settledCount !== \"number\") {\n throw invalidArgument(\"settledCount\", settledCount, \"a scalar\", \"settledCount must be a scalar field\");\n }\n const ms = this.batchMilliseconds(record, bytes);\n this.statsValue = withMs(this.model.readStats(header, trace), ms / k);\n this.iterationsDoneValue += k;\n // PLAN DECISION 21: a batch in flight at reheat() carries the pre-reheat settle counter\n this.settledCountValue = record.id <= this.reheatedAfterBatchId ? 0 : settledCount;\n this.settledValue = this.computeSettled();\n record.resolve();\n } catch (err) {\n record.reject(asError(err));\n }\n }\n\n /**\n * A failed readback: a discarded batch's E_ABORTED resolves (PLAN DECISION 8); a lost device rejects\n * E_DEVICE_LOST; everything else (E_VALIDATION, E_DISPOSED) rejects as is.\n * @param record - the pending batch\n * @param err - the rejection\n */\n private onFailed(record: PendingBatch, err: unknown): void {\n this.finish(record);\n if (hasErrorCode(err, \"E_ABORTED\") && this.isStale(record)) {\n record.resolve();\n return;\n }\n if (this.ctx.state === \"lost\" && !hasErrorCode(err, \"E_DEVICE_LOST\")) {\n record.reject(\n new WebGpuGraphError(\"E_DEVICE_LOST\", \"the device was lost while the batch was in flight\", {\n reason: \"unknown\",\n message: asError(err).message,\n }),\n );\n return;\n }\n record.reject(asError(err));\n }\n\n /**\n * Copies the scene bytes of a landed batch into the owner's array, honouring the override list (spec 7.12).\n * @param owner - the owner's array\n * @param bytes - the readback\n * @param record - the batch\n */\n private copyScene(owner: F32, bytes: ArrayBuffer, record: PendingBatch): void {\n const { n } = this;\n const scene = new Float32Array(bytes, record.sceneOffset, 3 * n);\n if (this.overrideList.size === 0) {\n owner.set(scene);\n return;\n }\n for (let i = 0; i < n; i++) {\n const after = this.overrideList.get(i);\n if (after !== undefined && after >= record.id) {\n continue;\n }\n owner[3 * i] = scene[3 * i];\n owner[3 * i + 1] = scene[3 * i + 1];\n owner[3 * i + 2] = scene[3 * i + 2];\n }\n for (const [i, after] of this.overrideList) {\n if (after < record.id) {\n this.overrideList.delete(i);\n }\n }\n }\n\n /**\n * The batch's duration in milliseconds: the profiler's pass timings summed when present, else wall time.\n * @param record - the batch\n * @param bytes - its readback (the profiler's resolve lands in it)\n * @returns milliseconds\n */\n private batchMilliseconds(record: PendingBatch, bytes: ArrayBuffer): number {\n const { profiler } = this.ctx;\n if (profiler !== null && record.profile !== null) {\n const timings = profiler.timings(bytes, record.profile);\n if (timings.length > 0) {\n let ns = 0;\n for (const timing of timings) {\n ns += timing.ns;\n }\n return ns / 1e6;\n }\n }\n return performance.now() - record.startedAt;\n }\n\n /**\n * Whether a record belongs to an earlier generation, was discarded, or the simulation left \"loaded\".\n * @param record - the batch\n * @returns true when its readback must be ignored\n */\n private isStale(record: PendingBatch): boolean {\n return record.stale || this.stateValue !== \"loaded\" || record.generation !== this.generationValue;\n }\n\n /**\n * Removes a record from the pending list (idempotent).\n * @param record - the batch\n */\n private finish(record: PendingBatch): void {\n const at = this.pending.indexOf(record);\n if (at >= 0) {\n this.pending.splice(at, 1);\n }\n }\n\n /** Marks every pending batch stale and discards the submitted ones (their readbacks resolve empty or E_ABORTED). */\n private discardPending(): void {\n for (const record of this.pending) {\n record.stale = true;\n record.submitted?.discard();\n }\n }\n\n /** An OOM surfaced by allocator.check(): every simulation buffer is destroyed and the state returns to \"created\". */\n private outOfMemory(): void {\n this.discardPending();\n this.destroyBuffers();\n this.ctx.allocator.reset();\n this.settledValue = false;\n this.stateValue = \"created\";\n }\n\n /**\n * The E_ABORTED of run().\n * @returns the error\n */\n private abortedError(): WebGpuGraphError {\n return new WebGpuGraphError(\"E_ABORTED\", `${this.label}: run() aborted by the signal`, {\n batchId: this.lastSubmittedBatchIdValue,\n });\n }\n\n // ---------------------------------------------------------------- private: params, state writes, toScene\n\n /**\n * The uniform values of one iteration slot: the model's values with the shared fields on top (PLAN DECISION 6).\n * @param global - the global iteration index (iterationsSubmitted + i)\n * @param index - the slot index within the batch (the trace slot)\n * @param flags - FA2_FLAG_FIRST for the first iteration after load(), else 0\n * @returns the values\n */\n private paramsForSlot(global: number, index: number, flags: number): UniformValues {\n const [cx, cy, cz] = this.center;\n const shared: UniformValues = {\n n: this.n,\n dim: this.dimValue,\n flags,\n iterationIndex: index,\n seed: this.seedU32(),\n scale: this.scale,\n center: [cx, cy, cz, 0],\n settleThreshold: this.settleThreshold(),\n };\n return { ...this.model.paramsFor(global, this.optionsValue), ...shared };\n }\n\n /**\n * The option seed as a u32 (0 when unseeded), the near-field hash seed of P4.\n * @returns the seed\n */\n private seedU32(): number {\n const { seed } = this.optionsValue;\n if (seed === null || seed === undefined || !Number.isFinite(seed)) {\n return 0;\n }\n return Math.floor(Math.abs(seed)) % 4294967296;\n }\n\n /**\n * Writes the queued state fields, each as one writeBuffer of its own byte range (PLAN DECISION 5).\n * @param state - the state buffer\n */\n private flushStateWrites(state: GPUBuffer): void {\n const fields = this.writer.takeQueued();\n if (fields.length === 0) {\n return;\n }\n const bytes = this.writer.headerBytes();\n const block = this.model.state;\n for (const field of fields) {\n const offset = block.offsetOf(field);\n const size = 4 * fieldWidth(fieldTypeOf(block, field));\n this.ctx.device.queue.writeBuffer(state, offset, bytes, offset, size);\n }\n }\n\n /**\n * The stage that precedes the toScene epilogue in model.stages (the `upTo` of every iteration but the last), or\n * undefined when the model has no epilogue or lists it first (every iteration then records every stage).\n * @returns the stage name or undefined\n */\n private lastIterationStage(): string | undefined {\n const at = this.model.stages.indexOf(EPILOGUE_STAGE);\n if (at <= 0) {\n return undefined;\n }\n return this.model.stages[at - 1];\n }\n\n /**\n * The settle threshold of the current options (FA2_DEFAULTS when absent).\n * @returns the threshold\n */\n private settleThreshold(): number {\n return this.optionsValue.settleThreshold ?? FA2_DEFAULTS.settleThreshold;\n }\n\n /**\n * The settle window of the current options (FA2_DEFAULTS when absent).\n * @returns the window\n */\n private settleWindow(): number {\n return this.optionsValue.settleWindow ?? FA2_DEFAULTS.settleWindow;\n }\n\n /**\n * The iteration budget (PLAN DECISION 1): options.maxIter, else options.iterations, else no budget.\n * @returns the budget\n */\n private iterationBudget(): number {\n const maxIter = optionField(this.optionsValue, \"maxIter\");\n if (typeof maxIter === \"number\") {\n return maxIter;\n }\n const iterations = optionField(this.optionsValue, \"iterations\");\n if (typeof iterations === \"number\") {\n return iterations;\n }\n return Number.POSITIVE_INFINITY;\n }\n\n /**\n * The settle rule of spec 7.17 over the counters of the last completed batch.\n * @returns whether the layout is settled\n */\n private computeSettled(): boolean {\n if (this.stateValue !== \"loaded\") {\n return false;\n }\n return (\n this.n === 0 ||\n this.iterationsDoneValue >= this.iterationBudget() ||\n this.settledCountValue >= this.settleWindow()\n );\n }\n\n // ---------------------------------------------------------------- private: buffers, upload, bind\n\n /**\n * Allocates the shared buffers (spec 7.3 sizes) and the model's BufferSpecs through the allocator (every buffer\n * labelled); a `zero: true` spec must carry COPY_DST so it can be re-zeroed when kept across loads (PLAN\n * DECISION 17). The state buffer is STATE_HEADER_BYTES + MAX_ITERATIONS_PER_STEP x model.trace.byteLength:\n * contract 3.13 writes TRACE_RECORD_BYTES (32, the FA2 record) for the last factor; the model's block is the\n * same number for FA2 and is what the simulation decodes the trace with, so it is the general rule (PLAN\n * DECISION 4) and the constant is not imported here.\n * @param n - the node count (> 0)\n * @returns the buffers and the name -> Binding map\n */\n private allocate(n: number): SimulationBuffers {\n const { allocator } = this.ctx;\n const { label } = this;\n const groups = Math.ceil(n / this.ctx.workgroupSize);\n const traceRegionBytes = MAX_ITERATIONS_PER_STEP * this.traceBytes;\n const storageRw = BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST;\n const positions = allocator.createBuffer({ label: `${label}/positions`, size: 16 * n, usage: storageRw });\n const scene = allocator.createBuffer({\n label: `${label}/scenePositions`,\n size: 12 * n,\n usage: BufferUsage.STORAGE | BufferUsage.COPY_SRC,\n });\n const fixed = allocator.createBuffer({\n label: `${label}/fixed`,\n size: 4 * Math.ceil(n / 32),\n usage: storageRw,\n });\n const partials = allocator.createBuffer({\n label: `${label}/partials`,\n size: PARTIAL_BYTES * groups,\n usage: storageRw,\n });\n const state = allocator.createBuffer({\n label: `${label}/state`,\n size: STATE_HEADER_BYTES + traceRegionBytes,\n usage: storageRw,\n });\n const bindings = new Map<string, Binding>();\n bindings.set(\"positions\", wholeBinding(positions, 16 * n));\n bindings.set(\"scenePositions\", wholeBinding(scene, 12 * n));\n bindings.set(\"fixed\", wholeBinding(fixed, 4 * Math.ceil(n / 32)));\n bindings.set(\"partials\", wholeBinding(partials, PARTIAL_BYTES * groups));\n bindings.set(\"state\", { buffer: state, offset: 0, size: STATE_HEADER_BYTES, window: null });\n bindings.set(\"trace\", { buffer: state, offset: STATE_HEADER_BYTES, size: traceRegionBytes, window: null });\n const model = new Map<string, { readonly buffer: GPUBuffer; readonly spec: BufferSpec }>();\n for (const spec of this.model.buffers(n, this.dimValue)) {\n if (SHARED_BUFFER_NAMES.includes(spec.name) || bindings.has(spec.name)) {\n throw invalidArgument(\n \"BufferSpec.name\",\n spec.name,\n \"a name no other buffer uses\",\n `BufferSpec \"${spec.name}\" reuses a buffer name`,\n );\n }\n if (!Number.isInteger(spec.byteLength) || spec.byteLength <= 0 || spec.byteLength % 4 !== 0) {\n throw invalidArgument(\n \"BufferSpec.byteLength\",\n spec.byteLength,\n \"a positive multiple of 4\",\n `BufferSpec \"${spec.name}\" has byteLength ${spec.byteLength}`,\n );\n }\n if (spec.zero && (spec.usage & BufferUsage.COPY_DST) === 0) {\n throw invalidArgument(\n \"BufferSpec.usage\",\n spec.usage,\n \"COPY_DST on a zero: true spec\",\n `BufferSpec \"${spec.name}\" is zero: true but lacks COPY_DST`,\n );\n }\n const buffer = allocator.createBuffer({\n label: `${label}/${spec.name}`,\n size: spec.byteLength,\n usage: spec.usage,\n });\n model.set(spec.name, { buffer, spec });\n bindings.set(spec.name, wholeBinding(buffer, spec.byteLength));\n }\n return { positions, scene, fixed, partials, state, model, bindings, traceRegionBytes };\n }\n\n /**\n * Re-zeroes the buffers a same-size load() keeps: partials, the trace region and every `zero: true` model buffer.\n * @param buffers - the kept buffers\n */\n private clearKept(buffers: SimulationBuffers): void {\n const { device } = this.ctx;\n const encoder = device.createCommandEncoder({ label: `${this.label}/clear` });\n encoder.clearBuffer(buffers.partials);\n encoder.clearBuffer(buffers.state, STATE_HEADER_BYTES, buffers.traceRegionBytes);\n for (const { buffer, spec } of buffers.model.values()) {\n if (spec.zero) {\n encoder.clearBuffer(buffer);\n }\n }\n device.queue.submit([encoder.finish()]);\n }\n\n /**\n * Destroys every simulation buffer through the allocator (the ring lives on until dispose()). While batches are\n * still in flight the destruction is DEFERRED until their readbacks have settled: the GPU may still be copying\n * out of `scene` / `state` and Dawn's Metal backend (dawn-node 0.4.0 on macOS) has taken the worker process\n * down when a buffer with pending work was destroyed (the Vulkan backends defer internally). The simulation\n * drops its references at once either way, so nothing here is reachable afterwards.\n */\n private destroyBuffers(): void {\n const { buffers } = this;\n if (buffers === null) {\n return;\n }\n this.buffers = null;\n this.resources = null;\n const doomed = [buffers.positions, buffers.scene, buffers.fixed, buffers.partials, buffers.state];\n for (const { buffer } of buffers.model.values()) {\n doomed.push(buffer);\n }\n this.afterInFlight(() => {\n const { allocator } = this.ctx;\n for (const buffer of doomed) {\n allocator.destroy(buffer);\n }\n });\n }\n\n /**\n * Runs `action` now when no submitted batch is in flight, otherwise once every in-flight readback has settled\n * (resolved, discarded or rejected -- the staging slot is returned and the GPU work is done either way).\n * @param action - the destruction to run\n */\n private afterInFlight(action: () => void): void {\n const waits: Promise<unknown>[] = [];\n for (const record of this.pending) {\n if (record.submitted !== null) {\n waits.push(record.submitted.readback.catch(() => undefined));\n }\n }\n if (waits.length === 0) {\n action();\n return;\n }\n void Promise.all(waits).then(action, action);\n }\n\n /**\n * The buffers of the current load.\n * @returns the buffers; E_NOT_LOADED when there are none\n */\n private requireBuffers(): SimulationBuffers {\n const { buffers } = this;\n if (buffers === null) {\n throw new WebGpuGraphError(\"E_NOT_LOADED\", `${this.label}: load() first`, { state: this.stateValue });\n }\n return buffers;\n }\n\n /**\n * Repacks the seeded scene array into layout-unit vec4f (mass in .w, z = 0 in 2D), uploads it, and writes the\n * initial centroid / bbox / rmsRadius / radius (f64 over the f32 values uploaded) with iteration 0,\n * settledCount 0, meanDisplacement 0 into the state header, then model.onLoad(writer) and one whole-header\n * writeBuffer (spec 7.4, 7.17, 7.18).\n * @param buffers - the buffers\n * @param positions - the seeded owner array\n * @param mass - the resolved masses\n */\n private uploadPositions(buffers: SimulationBuffers, positions: F32, mass: F32): void {\n const { n, scale } = this;\n const [cx, cy, cz] = this.center;\n const packed = new Float32Array(4 * n);\n for (let i = 0; i < n; i++) {\n packed[4 * i] = (positions[3 * i] - cx) / scale;\n packed[4 * i + 1] = (positions[3 * i + 1] - cy) / scale;\n packed[4 * i + 2] = this.dimValue === 2 ? 0 : (positions[3 * i + 2] - cz) / scale;\n packed[4 * i + 3] = mass[i];\n }\n this.ctx.device.queue.writeBuffer(buffers.positions, 0, packed);\n let sx = 0;\n let sy = 0;\n let sz = 0;\n const lo = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY];\n const hi = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY];\n for (let i = 0; i < n; i++) {\n const x = packed[4 * i];\n const y = packed[4 * i + 1];\n const z = packed[4 * i + 2];\n sx += x;\n sy += y;\n sz += z;\n lo[0] = Math.min(lo[0], x);\n lo[1] = Math.min(lo[1], y);\n lo[2] = Math.min(lo[2], z);\n hi[0] = Math.max(hi[0], x);\n hi[1] = Math.max(hi[1], y);\n hi[2] = Math.max(hi[2], z);\n }\n const mx = sx / n;\n const my = sy / n;\n const mz = sz / n;\n let sumSq = 0;\n let maxSq = 0;\n for (let i = 0; i < n; i++) {\n const dx = packed[4 * i] - mx;\n const dy = packed[4 * i + 1] - my;\n const dz = packed[4 * i + 2] - mz;\n const q = dx * dx + dy * dy + dz * dz;\n sumSq += q;\n maxSq = Math.max(maxSq, q);\n }\n const { writer } = this;\n writer.set(\"iteration\", 0);\n writer.set(\"settledCount\", 0);\n writer.set(\"meanDisplacement\", 0);\n writer.set(\"centroid\", [mx, my, mz, 0]);\n writer.set(\"min\", [lo[0], lo[1], lo[2], 0]);\n writer.set(\"max\", [hi[0], hi[1], hi[2], 0]);\n writer.set(\"rmsRadius\", Math.sqrt(sumSq / n));\n writer.set(\"radius\", Math.sqrt(maxSq));\n this.model.onLoad(writer);\n this.ctx.device.queue.writeBuffer(buffers.state, 0, writer.headerBytes());\n writer.clearQueued();\n }\n\n /**\n * The weights binding of a load (3.10): \"arcs\" -> core.weights, \"none\" -> null, \"column\" -> the expanded array\n * registered with residency.array(expanded, \"weights\", snapshot), the previous array object reused when the\n * column and its version are unchanged (so the upload cache finds it).\n * @param snapshot - the snapshot\n * @param core - its core\n * @param resolved - model.inputs().weights\n * @returns the binding for the group-0 weights slot, or null\n */\n private resolveWeightsBinding(\n snapshot: GraphSnapshot,\n core: CoreBinding,\n resolved: ResolvedWeights,\n ): Binding | null {\n if (resolved.source === \"arcs\") {\n this.weightsUpload = null;\n return core.weights;\n }\n if (resolved.source === \"none\" || resolved.data === null || resolved.column === null) {\n this.weightsUpload = null;\n return null;\n }\n const previous = this.weightsUpload;\n const reusable =\n previous !== null &&\n previous.serial === snapshot.serial &&\n previous.column === resolved.column &&\n previous.version === resolved.column.version &&\n previous.data.length === resolved.data.length;\n const data = reusable && previous !== null ? previous.data : resolved.data;\n const upload = this.ctx.residency.array(data, \"weights\", snapshot);\n this.weightsUpload = {\n serial: snapshot.serial,\n column: resolved.column,\n version: resolved.column.version,\n data,\n upload,\n };\n return upload.binding;\n }\n\n /**\n * The ModelResources of a load.\n * @param core - the core\n * @param weights - the resolved weights binding\n * @param buffers - the buffers\n * @returns the resources\n */\n private makeResources(core: CoreBinding, weights: Binding | null, buffers: SimulationBuffers): ModelResources {\n const { bindings } = buffers;\n return {\n device: this.ctx.device,\n caps: this.ctx.caps,\n pipelines: this.ctx.pipelines,\n core,\n perm: null,\n weights,\n n: this.n,\n dim: this.dimValue,\n tier: this.tierValue,\n ring: this.ring,\n buffer: (name: string): Binding => {\n const binding = bindings.get(name);\n if (binding === undefined) {\n throw invalidArgument(\"name\", name, [...bindings.keys()], `no simulation buffer named \"${name}\"`);\n }\n return binding;\n },\n };\n }\n\n /**\n * Chains the compile + bind promise the next step() awaits on the PREVIOUS one (PLAN DECISION 20: binds are\n * serialised on `ready` for load() and setParams() alike, so a superseded load()'s bind either fails its\n * generation check before model.bind() or completes before its successor's bind starts -- it can never bind\n * the model to destroyed buffers AFTER the new bind finished). The previous promise's rejection is swallowed by\n * the chain (it belonged to the superseded generation); this promise's rejection is kept for the next step()\n * (the derived catch only silences the unhandled-rejection warning).\n * @param resources - the resources\n * @param overrides - the merged override set\n */\n private startBind(resources: ModelResources, overrides: Readonly<Record<string, number | boolean>>): void {\n const generation = this.generationValue;\n const run = (): Promise<void> => this.compileAndBind(resources, overrides, generation);\n const promise = this.ready.catch(() => undefined).then(run);\n void promise.catch(() => undefined);\n this.ready = promise;\n }\n\n /**\n * warm(model.specs()) then model.bind(); the await re-checks that the load is current before binding.\n * @param resources - the resources\n * @param overrides - the merged override set\n * @param generation - the generation the bind belongs to\n */\n private async compileAndBind(\n resources: ModelResources,\n overrides: Readonly<Record<string, number | boolean>>,\n generation: number,\n ): Promise<void> {\n const subgroups = this.ctx.caps.features.has(\"subgroups\");\n await this.ctx.pipelines.warm(this.model.specs(overrides, subgroups));\n if (this.stateValue !== \"loaded\" || generation !== this.generationValue) {\n return;\n }\n await this.model.bind(resources, overrides);\n }\n\n // ---------------------------------------------------------------- private: inspect and debug runs\n\n /**\n * inspect(name): flush, read the named buffer back, Uint32Array for \"fixed\" and \"trace\", Float32Array otherwise.\n * @param name - a shared or BufferSpec name\n * @returns the words\n */\n private async inspectBuffer(name: string): Promise<Float32Array | Uint32Array> {\n this.assertLoaded();\n const { buffers } = this;\n const binding = buffers?.bindings.get(name);\n if (buffers === null || binding === undefined) {\n throw invalidArgument(\n \"name\",\n name,\n buffers === null ? [] : [...buffers.bindings.keys()],\n `inspect(\"${name}\"): no such buffer`,\n );\n }\n await this.flush();\n const bytes = await this.ctx.readback.read(binding.buffer, binding.size, undefined, binding.offset);\n return name === \"fixed\" || name === \"trace\" ? new Uint32Array(bytes) : new Float32Array(bytes);\n }\n\n /**\n * debugRunStages(upTo): one iteration truncated after a stage, submitted alone after flush(), awaited through\n * a header readback; never advances the counters or the FA2_FLAG_FIRST flag (PLAN DECISION 9).\n * @param upTo - a model stage name\n */\n private async runStages(upTo: string): Promise<void> {\n this.assertLoaded();\n if (!this.model.stages.includes(upTo)) {\n throw invalidArgument(\n \"upTo\",\n upTo,\n [...this.model.stages],\n `debugRunStages(\"${upTo}\"): not a stage of ${this.model.kind}`,\n );\n }\n if (this.n === 0) {\n return;\n }\n await this.flush();\n await this.ready;\n await this.ctx.allocator.check();\n this.assertLoaded();\n const buffers = this.requireBuffers();\n const { device } = this.ctx;\n if (this.fixedDirty) {\n device.queue.writeBuffer(buffers.fixed, 0, this.fixedWords);\n this.fixedDirty = false;\n }\n this.flushStateWrites(buffers.state);\n const slot = this.ring.reserve(1);\n this.ring.write(\n slot,\n this.model.params,\n this.paramsForSlot(this.iterationsSubmitted, 0, this.firstPending ? FA2_FLAG_FIRST : 0),\n );\n this.ring.flush();\n const batch = new CommandBatch(this.ctx, `${this.label}/debug`, this.generationValue);\n this.model.recordIteration(batch, slot, this.tierValue, upTo);\n batch.endPass();\n batch.readback(buffers.state, 0, STATE_HEADER_BYTES);\n const submitted = batch.submit();\n this.lastSubmittedBatchIdValue = submitted.id;\n await submitted.readback;\n }\n\n // ---------------------------------------------------------------- private: lifecycle\n\n /**\n * Device loss (spec 5.7): every pending promise rejects E_DEVICE_LOST, the simulation is disposed.\n * @param info - the loss info\n */\n private onDeviceLost(info: GPUDeviceLostInfo): void {\n if (this.stateValue === \"disposed\") {\n return;\n }\n const error = new WebGpuGraphError(\"E_DEVICE_LOST\", `device lost (${info.reason}): ${info.message}`, {\n reason: info.reason,\n message: info.message,\n });\n const pending = this.pending.splice(0);\n this.stateValue = \"disposed\";\n for (const record of pending) {\n record.stale = true;\n record.reject(error);\n }\n this.teardown();\n }\n\n /** Releases everything once: pending batches discarded, buffers and ring destroyed, pool trimmed, listener unregistered. */\n private teardown(): void {\n if (this.torndown) {\n return;\n }\n this.torndown = true;\n this.discardPending();\n this.destroyBuffers();\n this.afterInFlight(() => {\n this.ring.destroy();\n });\n if (this.ctx.state === \"ready\") {\n this.ctx.pool.trim();\n }\n this.unregisterLost();\n this.core = null;\n this.snapshot = null;\n this.owner = null;\n this.weightsUpload = null;\n }\n\n /** E_DISPOSED after dispose() or device loss. */\n private assertNotDisposed(): void {\n if (this.stateValue === \"disposed\") {\n throw disposedError(this.label);\n }\n }\n\n /** E_NOT_LOADED before load(), E_DISPOSED after dispose(). */\n private assertLoaded(): void {\n if (this.stateValue === \"created\") {\n throw new WebGpuGraphError(\"E_NOT_LOADED\", `${this.label}: load() first`, { state: \"created\" });\n }\n this.assertNotDisposed();\n }\n}\n","/**\n * nodeMass and weight resolution from graph-format primitives only (spec 7.14, 7.5; D28, Q-30): the role-\"mass\"\n * node column first, then outDegree() + 1; weights from the arc array, from a named edge column expanded to arcs\n * with expandEdges, or none. The Record form of nodeMass is rejected with the hint of spec 7.14 (graphty-element\n * writes its nodeMass config as the role column once at engine creation, so both simulations find it the same way\n * and this package parses no ids).\n */\n\nimport { type Column, expandEdges, type F32, type GraphSnapshot, type NodeId } from \"@graphty/graph-format\";\n\nimport { WebGpuGraphError } from \"../errors.js\";\n\n/** The message of spec 7.14 for the Record form of nodeMass. */\nconst NODE_MASS_HINT =\n \"write a role 'mass' node column (nodes.set(name, vec, { role: 'mass', replaceRole: true })) or pass a \" +\n \"Float32Array; @graphty/layout's resolveNodeVector does this on the CPU path\";\n\n/**\n * An E_INVALID_ARGUMENT with the documented details shape.\n * @param argument - the option name\n * @param value - the offending value\n * @param expected - what was expected\n * @param message - the message\n * @returns the error\n */\nfunction invalid(argument: string, value: unknown, expected: unknown, message: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", message, { argument, value, expected });\n}\n\n/**\n * Asserts every mass is finite and > 0 (spec 7.14: a mass of 0 would divide the distributed action by zero).\n * @param mass - the masses\n * @param source - what the masses came from, for the message\n */\nfunction checkMass(mass: ArrayLike<number>, source: string): void {\n for (let i = 0; i < mass.length; i++) {\n const v = mass[i];\n if (!Number.isFinite(v) || v <= 0) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${source}: mass[${i}] = ${v} is not a finite number > 0`,\n {\n argument: \"nodeMass\",\n value: v,\n index: i,\n expected: \"finite masses > 0\",\n },\n );\n }\n }\n}\n\n/**\n * outDegree()[i] + 1 for every node (spec 7.2 \"Mass\" row; one O(n) loop over the cached view).\n * @param s - the snapshot\n * @returns a fresh F32 of nodeCount masses\n */\nfunction degreePlusOne(s: GraphSnapshot): F32 {\n const n = s.nodeCount;\n const degree = s.outDegree();\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n out[i] = degree[i] + 1;\n }\n return out;\n}\n\n/**\n * The masses of a node column: f32 as is, f64 / u32 / i32 through gpuView (f64 = the cached f32 copy; u32 / i32\n * converted to a fresh F32), u8 through column.data; every other dtype is E_INVALID_ARGUMENT (PLAN DECISION 14).\n * @param s - the snapshot (the column belongs to s.nodes)\n * @param column - the node column\n * @returns nodeCount masses\n */\nfunction massFromColumn(s: GraphSnapshot, column: Column): F32 {\n const { name } = column.meta;\n if (column.meta.components !== 1) {\n throw invalid(\n \"nodeMass\",\n name,\n \"a one-component numeric node column\",\n `node column \"${name}\" has ${column.meta.components} components; a mass column has one`,\n );\n }\n let values: ArrayLike<number>;\n switch (column.dtype) {\n case \"f32\":\n case \"f64\": {\n const view = s.nodes.gpuView(name);\n const out = view instanceof Float32Array ? view : new Float32Array(view);\n checkMass(out, `node column \"${name}\"`);\n return out;\n }\n case \"u32\":\n case \"i32\":\n values = s.nodes.gpuView(name);\n break;\n case \"u8\":\n values = column.data;\n break;\n default:\n throw invalid(\n \"nodeMass\",\n name,\n \"a numeric node column (f32, f64, u32, i32, u8)\",\n `node column \"${name}\" is ${column.dtype}, not numeric`,\n );\n }\n const out = new Float32Array(s.nodeCount);\n for (let i = 0; i < out.length; i++) {\n out[i] = values[i];\n }\n checkMass(out, `node column \"${name}\"`);\n return out;\n}\n\n/**\n * nodeMass resolution by ROLE (spec 7.14): null -> the role-\"mass\" node column when present (any numeric dtype\n * through gpuView, converted to a fresh F32 when not f32), else outDegree()[i] + 1; an F32 of length n -> as is;\n * a column NAME -> nodes.get(name) (numeric); a Record -> E_UNSUPPORTED with the spec's message. Always returns n\n * values, every one finite and > 0.\n * @param s - the snapshot\n * @param spec - the ForceAtlas2Options.nodeMass value\n * @returns nodeCount masses (the caller's array when an F32 was given)\n */\nexport function resolveNodeMass(\n s: GraphSnapshot,\n spec: F32 | string | Readonly<Record<NodeId, number>> | null | undefined,\n): F32 {\n const n = s.nodeCount;\n if (spec === null || spec === undefined) {\n const column = s.nodes.byRole(\"mass\");\n if (column === null) {\n return degreePlusOne(s);\n }\n return massFromColumn(s, column);\n }\n if (spec instanceof Float32Array) {\n if (spec.length !== n) {\n throw invalid(\"nodeMass\", spec.length, `${n} values`, `nodeMass has ${spec.length} values, expected ${n}`);\n }\n checkMass(spec, \"nodeMass\");\n return spec;\n }\n if (typeof spec === \"string\") {\n const column = s.nodes.get(spec);\n if (column === null) {\n throw invalid(\n \"nodeMass\",\n spec,\n \"an existing numeric node column\",\n `nodeMass names node column \"${spec}\", which the snapshot does not hold`,\n );\n }\n return massFromColumn(s, column);\n }\n if (ArrayBuffer.isView(spec)) {\n throw invalid(\n \"nodeMass\",\n \"typed array\",\n \"a Float32Array\",\n \"nodeMass must be a Float32Array, a column name or null\",\n );\n }\n throw new WebGpuGraphError(\n \"E_UNSUPPORTED\",\n `nodeMass as a Record is not supported on the GPU path: ${NODE_MASS_HINT}`,\n {\n option: \"nodeMass\",\n hint: NODE_MASS_HINT,\n },\n );\n}\n\n/** What resolveWeights found. */\nexport interface ResolvedWeights {\n readonly data: F32 | null;\n readonly source: \"arcs\" | \"column\" | \"none\";\n readonly column: Column | null;\n}\n\n/**\n * Weight resolution (spec 7.5, 7.14): true -> { data: s.weights, source: \"arcs\" } (data null when unweighted ->\n * ones); a string -> a name `s.edges` does not hold is E_INVALID_ARGUMENT (spec 7.14's nodeMass rule applied to\n * weight too), else `column = s.edges.get(name)`, then by `column.dtype`: f32 / f64 / u32 / i32 ->\n * expandEdges(s, s.edges.gpuView(name)) (f64 arrives as gpuView's cached f32 copy; u32 / i32 are converted to a\n * fresh F32; `Column.data` is NOT used because it is U8 for u8 / bool and absent for string / list / json), string /\n * list / json -> the gpuView E_GPU_INELIGIBLE pass-through, u8 / bool / dict -> E_INVALID_ARGUMENT (gpuView returns\n * packed words, not per-edge values); source \"column\", `column` kept for the version check; false / null /\n * undefined -> none. A named column must have one component (PLAN DECISION 15); the weight values are never\n * inspected.\n * @param s - the snapshot\n * @param spec - the ForceAtlas2Options.weight value\n * @returns the resolved weights\n */\nexport function resolveWeights(s: GraphSnapshot, spec: boolean | string | null | undefined): ResolvedWeights {\n if (spec === true) {\n return { data: s.weights, source: \"arcs\", column: null };\n }\n if (spec === false || spec === null || spec === undefined) {\n return { data: null, source: \"none\", column: null };\n }\n if (typeof spec !== \"string\") {\n throw invalid(\n \"weight\",\n spec,\n \"true, false, null or an edge column name\",\n \"weight must be true, false, null or an edge column name\",\n );\n }\n const column = s.edges.get(spec);\n if (column === null) {\n throw invalid(\n \"weight\",\n spec,\n \"an existing numeric edge column\",\n `weight names edge column \"${spec}\", which the snapshot does not hold`,\n );\n }\n if (column.meta.components !== 1) {\n throw invalid(\n \"weight\",\n spec,\n \"a one-component numeric edge column\",\n `edge column \"${spec}\" has ${column.meta.components} components; a weight column has one`,\n );\n }\n switch (column.dtype) {\n case \"f32\":\n case \"f64\":\n case \"u32\":\n case \"i32\": {\n const view = s.edges.gpuView(spec);\n const expanded = expandEdges(s, view);\n const data = expanded instanceof Float32Array ? expanded : new Float32Array(expanded);\n return { data, source: \"column\", column };\n }\n case \"string\":\n case \"list\":\n case \"json\":\n // gpuView throws the GraphFormatError E_GPU_INELIGIBLE, which passes through unchanged (D12)\n s.edges.gpuView(spec);\n throw invalid(\"weight\", spec, \"a numeric edge column\", `edge column \"${spec}\" is ${column.dtype}`);\n default:\n throw invalid(\n \"weight\",\n spec,\n \"an f32 / f64 / u32 / i32 edge column\",\n `edge column \"${spec}\" is ${column.dtype}: its gpuView is packed words, not per-edge values`,\n );\n }\n}\n","/**\n * The exact-tier repulsion stage of ForceAtlas2 (spec 7.6, 7.9, 7.10; contract 3.13): K3, the tiled all-pairs\n * repulsion with the gravity term and the swing / traction epilogue, followed by K4, the one-workgroup speed finalize\n * that folds the per-workgroup partials and runs estimateFactor on the device (D15). P1 ships the stage driven over a\n * pass the caller opens (the tests); P3-T2 records it from ForceAtlas2Model.recordIteration without changing these\n * declarations. Both kernels come from the registry (src/kernels.ts) through the pipeline cache, so a distinct\n * override set is a distinct pipeline and the subgroup twin is selected by the device's features (spec 5.1, D16).\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type DispatchPlan, plan1d } from \"../kernel/dispatch.js\";\nimport { type BoundKernel, type Kernel } from \"../kernel/kernel.js\";\nimport { type PipelineCache } from \"../kernel/pipeline-cache.js\";\nimport { type WgslModuleSpec } from \"../kernel/wgsl.js\";\nimport { kernelSpec } from \"../kernels.js\";\nimport { type PlanCaps } from \"../types/context.js\";\nimport { type Binding } from \"../types/memory.js\";\n\n/** The buffers the exact-tier repulsion stage binds (all in layout units; spec 7.3). */\nexport interface RepulsionExactResources {\n readonly pos: Binding;\n readonly state: Binding;\n readonly trace: Binding;\n readonly force: Binding;\n readonly oldForce: Binding;\n readonly fixedMask: Binding;\n readonly partials: Binding;\n readonly params: Binding;\n}\n\n/** The overrides K3 / K4 compile with. */\nexport interface RepulsionExactOverrides {\n readonly SWING_MODE: 0 | 1;\n readonly STRONG_GRAVITY: boolean;\n readonly GRAVITY_CENTER: 0 | 1;\n}\n\n/** K3 (tiled all-pairs repulsion + gravity + the swing / traction epilogue) followed by K4 (the one-workgroup speed finalize) (spec 7.6, 7.10). */\nexport class RepulsionExact {\n /** The overrides both kernels were compiled with (a frozen copy of the argument of create()). */\n readonly overrides: RepulsionExactOverrides;\n\n private readonly caps: PlanCaps;\n private readonly repulsion: Kernel;\n private readonly speedFinalize: Kernel;\n /** Exactly one workgroup of K4 (spec 7.4: \"1 workgroup\"). */\n private readonly finalizePlan: DispatchPlan;\n private boundRepulsion: BoundKernel | null = null;\n private boundSpeedFinalize: BoundKernel | null = null;\n\n /**\n * Holds the two compiled kernels; create() is the only caller.\n * @param repulsion - the K3 kernel\n * @param speedFinalize - the K4 kernel\n * @param caps - the device caps the dispatch planner reads\n * @param overrides - the override set both kernels were compiled with\n */\n private constructor(repulsion: Kernel, speedFinalize: Kernel, caps: PlanCaps, overrides: RepulsionExactOverrides) {\n this.repulsion = repulsion;\n this.speedFinalize = speedFinalize;\n this.caps = caps;\n this.overrides = Object.freeze({\n SWING_MODE: overrides.SWING_MODE,\n STRONG_GRAVITY: overrides.STRONG_GRAVITY,\n GRAVITY_CENTER: overrides.GRAVITY_CENTER,\n });\n this.finalizePlan = plan1d(speedFinalize.workgroupSize, speedFinalize.workgroupSize, caps);\n }\n\n /**\n * Compiles both kernels through the cache (the twin is selected by caps.features).\n * @param pipelines - the context's pipeline cache\n * @param caps - the device caps the dispatch planner reads\n * @param overrides - the SWING_MODE / STRONG_GRAVITY / GRAVITY_CENTER set of this stage\n * @returns the stage, ready for bind()\n */\n static async create(\n pipelines: PipelineCache,\n caps: PlanCaps,\n overrides: RepulsionExactOverrides,\n ): Promise<RepulsionExact> {\n const [repulsionSpec, finalizeSpec] = RepulsionExact.specs(overrides);\n // Sequential on purpose: PipelineCache.get runs createComputePipelineAsync inside a validation scope, and error\n // scopes form one stack per device, so two interleaved compilations would pop each other's scope.\n const repulsion = await pipelines.kernel(repulsionSpec);\n const speedFinalize = await pipelines.kernel(finalizeSpec);\n return new RepulsionExact(repulsion, speedFinalize, caps, overrides);\n }\n\n /**\n * The two specs (for warm() and the compile matrix).\n * @param overrides - the override set of the stage\n * @returns the K3 spec then the K4 spec\n */\n static specs(overrides: RepulsionExactOverrides): readonly [WgslModuleSpec, WgslModuleSpec] {\n return [\n kernelSpec(\"fa2-repulsion-exact\", {\n SWING_MODE: overrides.SWING_MODE,\n STRONG_GRAVITY: overrides.STRONG_GRAVITY,\n GRAVITY_CENTER: overrides.GRAVITY_CENTER,\n }),\n kernelSpec(\"fa2-speed-finalize\", { SWING_MODE: overrides.SWING_MODE }),\n ];\n }\n\n /**\n * Creates the bind groups once per load(): K3 takes pos, state (S), force, oldForce, fixedMask, partials and the\n * params slot; K4 takes partials, state (S), trace (T) and the params slot (the 3.10.1 binding names). The state\n * header and the trace region are two disjoint ranges of one buffer, which Kernel.bind() accepts (no writable alias).\n * @param resources - the buffers of spec 7.3\n */\n bind(resources: RepulsionExactResources): void {\n this.boundRepulsion = this.repulsion.bind({\n pos: resources.pos,\n S: resources.state,\n force: resources.force,\n oldForce: resources.oldForce,\n fixedMask: resources.fixedMask,\n partials: resources.partials,\n P: resources.params,\n });\n this.boundSpeedFinalize = this.speedFinalize.bind({\n partials: resources.partials,\n S: resources.state,\n T: resources.trace,\n P: resources.params,\n });\n }\n\n /**\n * Records K3 (plan1d(n)) then K4 (1 workgroup) with the params slot's dynamic offset.\n * @param pass - the open compute pass of the batch\n * @param n - the node count (rows [0, n) of pos / force)\n * @param paramsOffset - the dynamic offset of this iteration's Fa2Params slot in the uniform ring\n */\n record(pass: GPUComputePassEncoder, n: number, paramsOffset: number): void {\n this.recordRepulsion(pass, n, paramsOffset);\n this.recordSpeedFinalize(pass, paramsOffset);\n }\n\n /**\n * Records K3 only (the inspect() stage split, spec 11.9 item 2).\n * @param pass - the open compute pass\n * @param n - the node count\n * @param paramsOffset - the dynamic offset of the Fa2Params slot\n * @internal\n */\n recordRepulsion(pass: GPUComputePassEncoder, n: number, paramsOffset: number): void {\n const bound = this.bound(this.boundRepulsion, \"recordRepulsion\");\n const plan = plan1d(n, this.repulsion.workgroupSize, this.caps);\n this.repulsion.dispatch(pass, bound, plan, [paramsOffset]);\n }\n\n /**\n * Records K4 only.\n * @param pass - the open compute pass\n * @param paramsOffset - the dynamic offset of the Fa2Params slot\n * @internal\n */\n recordSpeedFinalize(pass: GPUComputePassEncoder, paramsOffset: number): void {\n const bound = this.bound(this.boundSpeedFinalize, \"recordSpeedFinalize\");\n this.speedFinalize.dispatch(pass, bound, this.finalizePlan, [paramsOffset]);\n }\n\n /**\n * The bound kernel of a method, or E_NOT_LOADED when bind() has not run.\n * @param bound - the cached BoundKernel, null before bind()\n * @param method - the caller's name for the message\n * @returns the bound kernel\n */\n private bound(bound: BoundKernel | null, method: string): BoundKernel {\n if (bound === null) {\n throw new WebGpuGraphError(\n \"E_NOT_LOADED\",\n `RepulsionExact.${method}(): bind() has not been called for this stage`,\n {\n state: \"unbound\",\n },\n );\n }\n return bound;\n }\n}\n","/**\n * ForceAtlas2 on the exact repulsion tier (spec 7.1-7.18; contract 3.13): the ForceModel that ForceSimulation\n * drives -- the K1 K2 K3 K4 K5 sequence per iteration and toScene per batch (spec 7.4), the override set of the option\n * record (spec 7.2 with the 4.6 NetworkX corrections), the per-iteration Fa2Params values, the controller resets of\n * spec 7.17 and the stats decoder -- plus the two option resolvers and `createForceAtlas2`. Positions are vec4f\n * (xyz + mass) in layout units on the device (D23, 7.18); the speed controller runs on the device (D15); no\n * displacement clamp (D25); K2 runs the thread-per-row tier over [0, n) with USE_PERM false (P3, spec 7.5).\n *\n * Model decisions this file fixes (the plan of P3-T2 lists the reasons): recordIteration with no `upTo` records every\n * stage including toScene; the K1-K5 dispatches of every iteration of one batch share ONE compute pass (opened by the\n * batch's first recordIteration and remembered by batch id) and toScene runs in a second pass that ends it (contract\n * 4.4); the fill kernel takes its FillParams from a model-owned 256-byte uniform buffer (\"fillParams\"); the first\n * iteration after every load() zeroes oldForce with a fill (paper mode); `repulsion: \"grid\"` is E_UNSUPPORTED at\n * load() for any n and `\"auto\"` above exactMaxNodes.\n */\n\nimport { type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport {\n FA2_DEFAULTS,\n LAYOUT_TUNING_DEFAULTS,\n MAX_ITERATIONS_PER_STEP,\n TRACE_RECORD_BYTES,\n UNIFORM_SLOT_BYTES,\n} from \"../constants.js\";\nimport { type GpuContext } from \"../context.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type CommandBatch } from \"../kernel/batch.js\";\nimport { type DispatchPlan, plan1d } from \"../kernel/dispatch.js\";\nimport { type BoundKernel, type Kernel } from \"../kernel/kernel.js\";\nimport { type UniformBlock, type UniformValues } from \"../kernel/struct-block.js\";\nimport { type WgslModuleSpec } from \"../kernel/wgsl.js\";\nimport { FA2_PARAMS, FA2_STATE, FA2_TRACE, FILL_PARAMS, graphBindings, kernelSpec } from \"../kernels.js\";\nimport {\n type ForceAtlas2Stats,\n type ForceAtlas2TraceRecord,\n type GpuLayoutSimulation,\n type GpuLayoutTuning,\n type ResolvedLayoutTuning,\n} from \"../types/layout.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type ForceAtlas2Options, type ResolvedForceAtlas2Options } from \"../types/options.js\";\nimport {\n type BufferSpec,\n type ForceModel,\n ForceSimulation,\n type ModelInputs,\n type ModelResources,\n type StateWriter,\n} from \"./force-simulation.js\";\nimport { resolveNodeMass, resolveWeights } from \"./inputs.js\";\nimport { RepulsionExact, type RepulsionExactOverrides } from \"./repulsion-exact.js\";\n\n// ============================================================ constants and small helpers\n\n/** An override record as the kernel layer takes it. */\ntype Overrides = Readonly<Record<string, number | boolean>>;\n\n/** The stage names of one iteration in dispatch order plus the per-batch toScene (spec 7.4; contract 3.13). */\nconst FA2_STAGES = [\"K1\", \"K2\", \"K3\", \"K4\", \"K5\", \"toScene\"] as const;\n\n/** Bytes of the stride-3 f32 force arrays per node. */\nconst FORCE_BYTES_PER_NODE = 12;\n\n/** The name of the model-owned FillParams buffer (a BufferSpec, reached through ModelResources.buffer). */\nconst FILL_PARAMS_BUFFER = \"fillParams\";\n\n/** The one-workgroup dispatch of K1 (spec 7.4). */\nconst ONE_WORKGROUP: DispatchPlan = { x: 1, y: 1, z: 1, items: 1, stride: null };\n\n/** Every override K2 accepts, with its default (contract 3.10.1 plus the two standard graph overrides). */\nconst K2_DEFAULTS: Overrides = { LINLOG: false, DISTRIBUTED: false, TIER: 0, USE_PERM: false, HAS_WEIGHTS: false };\n\n/** Every override K5 accepts, with its default. */\nconst K5_DEFAULTS: Overrides = { SWING_MODE: 0 };\n\n/** 2^32, the modulus of the u32 seed word (computed with `%`, never a bitwise operator). */\nconst U32_MODULUS = 4294967296;\n\n/** The resolved record with no option given: FA2_DEFAULTS plus the null / origin defaults of spec 7.14. */\nconst DEFAULT_RESOLVED: ResolvedForceAtlas2Options = Object.freeze<ResolvedForceAtlas2Options>({\n ...FA2_DEFAULTS,\n nodeMass: null,\n nodeSize: null,\n weight: null,\n center: [0, 0, 0],\n seed: null,\n});\n\n/**\n * A short, safe rendering of an argument value for error messages (never String() on an object).\n * @param value - the value\n * @returns the rendering\n */\nfunction describeValue(value: unknown): string {\n if (value === null) {\n return \"null\";\n }\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"string\") {\n return String(value);\n }\n if (typeof value === \"undefined\") {\n return \"undefined\";\n }\n if (typeof value === \"object\" && \"length\" in value && typeof value.length === \"number\") {\n return `[${value.length} values]`;\n }\n return typeof value;\n}\n\n/**\n * The E_INVALID_ARGUMENT error of an option check (contract 3.1: { argument, value, expected }).\n * @param argument - the option name\n * @param value - the value given\n * @param expected - what was expected\n * @returns the error (not thrown here)\n */\nfunction invalid(argument: string, value: unknown, expected: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${argument} must be ${expected}; got ${describeValue(value)}`, {\n argument,\n value,\n expected,\n });\n}\n\n/**\n * A numeric option: the given value when defined, else the fallback; validated by `check` (the value is checked as\n * `unknown` so a JS caller's string or object is E_INVALID_ARGUMENT too).\n * @param name - the option name\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @param check - the range predicate over a finite number\n * @param expected - the range in words (the error message)\n * @returns the value\n */\nfunction pickNumber(\n name: string,\n given: number | undefined,\n fallback: number,\n check: (value: number) => boolean,\n expected: string,\n): number {\n const value: unknown = given === undefined ? fallback : given;\n if (typeof value !== \"number\" || !Number.isFinite(value) || !check(value)) {\n throw invalid(name, value, expected);\n }\n return value;\n}\n\n/**\n * A boolean option: the given value when defined, else the fallback; a non-boolean is E_INVALID_ARGUMENT.\n * @param name - the option name\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @returns the value\n */\nfunction pickBoolean(name: string, given: boolean | undefined, fallback: boolean): boolean {\n const value: unknown = given === undefined ? fallback : given;\n if (typeof value !== \"boolean\") {\n throw invalid(name, value, \"a boolean\");\n }\n return value;\n}\n\n/**\n * The layout dimension: 2 or 3.\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @returns 2 or 3\n */\nfunction pickDim(given: 2 | 3 | undefined, fallback: 2 | 3): 2 | 3 {\n const value: unknown = given === undefined ? fallback : given;\n if (value !== 2 && value !== 3) {\n throw invalid(\"dim\", value, \"2 or 3\");\n }\n return value;\n}\n\n/**\n * The scene-unit center: an array-like of 2 (z = 0) or 3 finite numbers.\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @returns the three components\n */\nfunction pickCenter(\n given: ArrayLike<number> | undefined,\n fallback: readonly [number, number, number],\n): readonly [number, number, number] {\n if (given === undefined) {\n return fallback;\n }\n const expected = \"an array of 2 or 3 finite numbers\";\n const value: unknown = given;\n if (typeof value !== \"object\" || value === null || !(\"length\" in value)) {\n throw invalid(\"center\", given, expected);\n }\n const { length } = value;\n if (length !== 2 && length !== 3) {\n throw invalid(\"center\", given, expected);\n }\n const x: unknown = given[0];\n const y: unknown = given[1];\n const z: unknown = length === 3 ? given[2] : 0;\n if (\n typeof x !== \"number\" ||\n typeof y !== \"number\" ||\n typeof z !== \"number\" ||\n !Number.isFinite(x) ||\n !Number.isFinite(y) ||\n !Number.isFinite(z)\n ) {\n throw invalid(\"center\", given, expected);\n }\n return [x, y, z];\n}\n\n/**\n * The seed: a finite number, or null (unseeded; 0 keeps the port's \"0 = unseeded\" quirk through the Lcg).\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @returns the seed or null\n */\nfunction pickSeed(given: number | null | undefined, fallback: number | null): number | null {\n if (given === undefined) {\n return fallback;\n }\n const value: unknown = given;\n if (value !== null && (typeof value !== \"number\" || !Number.isFinite(value))) {\n throw invalid(\"seed\", given, \"a finite number or null\");\n }\n return value;\n}\n\n/**\n * Integer >= 1.\n * @param value - a finite number\n * @returns whether it is a positive integer\n */\nfunction isPositiveInteger(value: number): boolean {\n return Number.isInteger(value) && value >= 1;\n}\n\n/**\n * The u32 word written into Fa2Params.seed: 0 for null, else floor(|seed|) mod 2^32.\n * @param seed - the resolved seed\n * @returns the u32 value\n */\nfunction seedWord(seed: number | null): number {\n if (seed === null) {\n return 0;\n }\n return Math.floor(Math.abs(seed)) % U32_MODULUS;\n}\n\n/**\n * A scalar field of a block's read() result.\n * @param values - the values read\n * @param name - the field name\n * @returns the number\n */\nfunction scalar(values: UniformValues, name: string): number {\n const value = values[name];\n if (typeof value !== \"number\") {\n throw invalid(name, value, \"a scalar field\");\n }\n return value;\n}\n\n/**\n * A vector field of a block's read() result.\n * @param values - the values read\n * @param name - the field name\n * @returns the components\n */\nfunction vector(values: UniformValues, name: string): readonly number[] {\n const value = values[name];\n if (typeof value === \"number\") {\n throw invalid(name, value, \"a vector field\");\n }\n return value;\n}\n\n/**\n * The override record a kernel gets: its defaults overlaid with the values present in the merged set (contract 3.9:\n * a name a spec does not declare is rejected at compose time, so nothing else is passed through).\n * @param merged - the merged override set of the model (plus USE_PERM / HAS_WEIGHTS from the simulation)\n * @param defaults - the kernel's accepted names with their defaults\n * @returns the kernel's override record, every accepted name explicit\n */\nfunction subset(merged: Overrides, defaults: Overrides): Overrides {\n const out: Record<string, number | boolean> = {};\n for (const name of Object.keys(defaults)) {\n out[name] = name in merged ? merged[name] : defaults[name];\n }\n return out;\n}\n\n/**\n * The K3 / K4 override values of a merged set (typed for RepulsionExact).\n * @param merged - the merged override set\n * @returns the three K3 / K4 overrides\n */\nfunction repulsionOverrides(merged: Overrides): RepulsionExactOverrides {\n return {\n SWING_MODE: merged.SWING_MODE === 1 ? 1 : 0,\n STRONG_GRAVITY: merged.STRONG_GRAVITY === true,\n GRAVITY_CENTER: merged.GRAVITY_CENTER === 1 ? 1 : 0,\n };\n}\n\n// ============================================================ the resolvers\n\n/**\n * Applies FA2_DEFAULTS to the option record; validates ranges (spec 7.14; contract 3.13). With `previous` the record\n * is a PATCH over it (an absent or explicitly undefined field keeps the previous value) and `maxInFlight` may not\n * change (the uniform ring is sized by it at construction). `nodeSize` is E_UNSUPPORTED { option: \"nodeSize\" } (the\n * adjustSizes correction is deferred); `dissuadeHubs` is kept and ignored, exactly like the CPU.\n * @param options - the caller's options (or a setParams patch)\n * @param previous - the current resolved record when resolving a patch\n * @returns the frozen resolved record\n */\nexport function resolveForceAtlas2Options(\n options: ForceAtlas2Options | undefined,\n previous?: ResolvedForceAtlas2Options,\n): ResolvedForceAtlas2Options {\n const o: ForceAtlas2Options = options ?? {};\n const base = previous ?? DEFAULT_RESOLVED;\n if (previous !== undefined && o.maxInFlight !== undefined && o.maxInFlight !== previous.maxInFlight) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `maxInFlight cannot change after creation (the uniform ring is sized by it): got ${describeValue(o.maxInFlight)}, current ${previous.maxInFlight}`,\n { argument: \"maxInFlight\", value: o.maxInFlight, expected: previous.maxInFlight },\n );\n }\n const nodeSize = o.nodeSize === undefined ? base.nodeSize : o.nodeSize;\n if (nodeSize !== null) {\n throw new WebGpuGraphError(\n \"E_UNSUPPORTED\",\n \"nodeSize (the adjustSizes correction) is not supported by the GPU ForceAtlas2 yet (spec 7.14)\",\n { option: \"nodeSize\", hint: \"pass nodeSize: null; the size-aware repulsion is deferred (spec 7.2, Q-25)\" },\n );\n }\n const resolved: ResolvedForceAtlas2Options = {\n maxIter: pickNumber(\"maxIter\", o.maxIter, base.maxIter, isPositiveInteger, \"an integer >= 1\"),\n jitterTolerance: pickNumber(\"jitterTolerance\", o.jitterTolerance, base.jitterTolerance, (v) => v > 0, \"> 0\"),\n scalingRatio: pickNumber(\"scalingRatio\", o.scalingRatio, base.scalingRatio, (v) => v > 0, \"> 0\"),\n gravity: pickNumber(\"gravity\", o.gravity, base.gravity, (v) => v >= 0, \">= 0\"),\n strongGravity: pickBoolean(\"strongGravity\", o.strongGravity, base.strongGravity),\n distributedAction: pickBoolean(\"distributedAction\", o.distributedAction, base.distributedAction),\n linlog: pickBoolean(\"linlog\", o.linlog, base.linlog),\n nodeMass: o.nodeMass === undefined ? base.nodeMass : o.nodeMass,\n nodeSize,\n weight: o.weight === undefined ? base.weight : o.weight,\n dissuadeHubs: pickBoolean(\"dissuadeHubs\", o.dissuadeHubs, base.dissuadeHubs),\n dim: pickDim(o.dim, base.dim),\n scale: pickNumber(\"scale\", o.scale, base.scale, (v) => v > 0, \"> 0\"),\n center: pickCenter(o.center, base.center),\n seed: pickSeed(o.seed, base.seed),\n settleThreshold: pickNumber(\"settleThreshold\", o.settleThreshold, base.settleThreshold, (v) => v >= 0, \">= 0\"),\n settleWindow: pickNumber(\n \"settleWindow\",\n o.settleWindow,\n base.settleWindow,\n isPositiveInteger,\n \"an integer >= 1\",\n ),\n iterationsPerStep: pickNumber(\n \"iterationsPerStep\",\n o.iterationsPerStep,\n base.iterationsPerStep,\n (v) => isPositiveInteger(v) && v <= MAX_ITERATIONS_PER_STEP,\n `an integer in [1, ${MAX_ITERATIONS_PER_STEP}]`,\n ),\n maxInFlight: pickNumber(\"maxInFlight\", o.maxInFlight, base.maxInFlight, isPositiveInteger, \"an integer >= 1\"),\n };\n return Object.freeze(resolved);\n}\n\n/**\n * Applies LAYOUT_TUNING_DEFAULTS (spec 7.14); the grid knobs are validated and stored but only `repulsion`,\n * `exactMaxNodes`, `deterministic` and `compat` have an effect in P3 (contract 3.3).\n * @param tuning - the GPU-only knobs given (any object carrying them, e.g. the createForceAtlas2 options)\n * @returns the frozen resolved tuning\n */\nexport function resolveLayoutTuning(tuning: GpuLayoutTuning | undefined): ResolvedLayoutTuning {\n const t: GpuLayoutTuning = tuning ?? {};\n const repulsion: unknown = t.repulsion ?? LAYOUT_TUNING_DEFAULTS.repulsion;\n if (repulsion !== \"exact\" && repulsion !== \"grid\" && repulsion !== \"auto\") {\n throw invalid(\"repulsion\", repulsion, '\"exact\", \"grid\" or \"auto\"');\n }\n const compat: unknown = t.compat ?? LAYOUT_TUNING_DEFAULTS.compat;\n if (compat !== \"paper\" && compat !== \"networkx\") {\n throw invalid(\"compat\", compat, '\"paper\" or \"networkx\"');\n }\n const resolved: ResolvedLayoutTuning = {\n repulsion,\n exactMaxNodes: pickNumber(\n \"exactMaxNodes\",\n t.exactMaxNodes,\n LAYOUT_TUNING_DEFAULTS.exactMaxNodes,\n isPositiveInteger,\n \"an integer >= 1\",\n ),\n nearMax: pickNumber(\"nearMax\", t.nearMax, LAYOUT_TUNING_DEFAULTS.nearMax, isPositiveInteger, \"an integer >= 1\"),\n deterministic: pickBoolean(\"deterministic\", t.deterministic, LAYOUT_TUNING_DEFAULTS.deterministic),\n gridMax2D: pickNumber(\n \"gridMax2D\",\n t.gridMax2D,\n LAYOUT_TUNING_DEFAULTS.gridMax2D,\n isPositiveInteger,\n \"an integer >= 1\",\n ),\n gridMax3D: pickNumber(\n \"gridMax3D\",\n t.gridMax3D,\n LAYOUT_TUNING_DEFAULTS.gridMax3D,\n isPositiveInteger,\n \"an integer >= 1\",\n ),\n extentFactor: pickNumber(\n \"extentFactor\",\n t.extentFactor,\n LAYOUT_TUNING_DEFAULTS.extentFactor,\n (v) => v > 0,\n \"> 0\",\n ),\n compat,\n };\n return Object.freeze(resolved);\n}\n\n// ============================================================ the model\n\n/** Everything bind() produced for one load(): the kernels, their bind groups and the dispatch plans of this n. */\ninterface BoundModel {\n readonly n: number;\n /** plan1d(n): K2, K5, toScene (every kernel compiles with the same device-derived WG). */\n readonly plan: DispatchPlan;\n /** plan1d(3n): the fills of force / oldForce (3 words per node). */\n readonly fillPlan: DispatchPlan;\n readonly k1: Kernel;\n readonly k1Bound: BoundKernel;\n readonly k2: Kernel;\n /** null when arcCount === 0 (K2 is not recorded; the fill below zeroes force instead, spec 7.5). */\n readonly k2Bound: BoundKernel | null;\n readonly repulsion: RepulsionExact;\n readonly k5: Kernel;\n readonly k5Bound: BoundKernel;\n readonly toScene: Kernel;\n readonly toSceneBound: BoundKernel;\n readonly fill: Kernel;\n /** The fill of `force` (arcCount === 0 only). */\n readonly fillForceBound: BoundKernel | null;\n /** The fill of `oldForce` on the first iteration after load() (paper mode only). */\n readonly fillOldBound: BoundKernel | null;\n}\n\n/** The ForceAtlas2 model (spec 7.4: K1 K2 K3 K4 K5 per iteration; toScene once per batch). Stages: [\"K1\", \"K2\", \"K3\", \"K4\", \"K5\", \"toScene\"]. */\nexport class ForceAtlas2Model implements ForceModel<ForceAtlas2Options, ForceAtlas2Stats> {\n /** The model kind of spec 7.19. */\n readonly kind = \"forceatlas2\";\n /** The stage names in dispatch order (the `upTo` vocabulary of recordIteration and debugRunStages). */\n readonly stages: readonly [\"K1\", \"K2\", \"K3\", \"K4\", \"K5\", \"toScene\"] = FA2_STAGES;\n /** Fa2Params: the per-iteration uniform block (the simulation writes the shared fields into it). */\n readonly params: UniformBlock = FA2_PARAMS;\n /** Fa2State: the state header block (the simulation allocates and initialises it through this layout). */\n readonly state: UniformBlock = FA2_STATE;\n /** Fa2Trace: one record per iteration of a batch. */\n readonly trace: UniformBlock = FA2_TRACE;\n /** The resolved GPU-only tuning this model was created with. */\n readonly tuning: ResolvedLayoutTuning;\n\n /**\n * The option record the model holds: the constructor's record, replaced by onSetParams() ONLY. The query hooks\n * (inputs, overrides, paramsFor) never assign it: the simulation calls overrides(next) BEFORE onSetParams(patch)\n * (3.13 setParams: the recompile decision precedes the controller reset), so a hook that tracked the record would\n * hide every law change from onSetParams (PLAN DECISION 12).\n */\n private current: ResolvedForceAtlas2Options;\n /** The resources of the last bind(), or null before the first. */\n private resources: ModelResources | null = null;\n /** The kernels and bind groups of the last bind(), or null before it (and for n === 0). */\n private bound: BoundModel | null = null;\n /** Armed by onLoad(): the next recordIteration zeroes oldForce first (paper mode). */\n private resetOldForce = false;\n /**\n * The K1-K5 compute pass of the batch being recorded, keyed by CommandBatch.id (unique per batch): every\n * recordIteration of one batch dispatches into it (ONE pass per batch, contract 4.4); null between batches and\n * after the toScene pass ended it (PLAN DECISION 2).\n */\n private openPass: { readonly id: number; readonly pass: GPUComputePassEncoder } | null = null;\n\n /**\n * Creates the model for one simulation.\n * @param tuning - the resolved GPU-only tuning (compat selects SWING_MODE / GRAVITY_CENTER; repulsion and\n * exactMaxNodes the tier rule)\n * @param resolved - the resolved option record at creation\n */\n constructor(tuning: ResolvedLayoutTuning, resolved: ResolvedForceAtlas2Options) {\n this.tuning = tuning;\n this.current = resolved;\n }\n\n /**\n * The SWING_MODE of this model: 1 in networkx mode (accumulated, position-mixed sums; m|F| local swing), else 0.\n * @returns 0 or 1\n */\n private get swingMode(): 0 | 1 {\n return this.tuning.compat === \"networkx\" ? 1 : 0;\n }\n\n /**\n * force 12n and oldForce 12n (zeroed) in BOTH swing modes (3.10.1: a writable slot is never aliased; mode 1 leaves\n * oldForce unread and unwritten), plus the 256-byte FillParams uniform buffer the fill dispatches read. n = 0\n * reports one node's worth of bytes so no zero-length buffer is ever created (spec 3.6).\n * @param n - the node count\n * @param _dim - the layout dimension (the force arrays are stride 3 in both)\n * @returns the three model-owned buffer specs\n */\n buffers(n: number, _dim: 2 | 3): readonly BufferSpec[] {\n const bytes = Math.max(1, n) * FORCE_BYTES_PER_NODE;\n const usage = BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST;\n return [\n { name: \"force\", byteLength: bytes, usage, zero: true },\n { name: \"oldForce\", byteLength: bytes, usage, zero: true },\n {\n name: FILL_PARAMS_BUFFER,\n byteLength: UNIFORM_SLOT_BYTES,\n usage: BufferUsage.UNIFORM | BufferUsage.COPY_DST,\n zero: false,\n },\n ];\n }\n\n /**\n * { mass: resolveNodeMass(s, resolved.nodeMass), weights: resolveWeights(s, resolved.weight) } (3.13 inputs.ts),\n * after the tier rule of spec 7.8 / lead f: `repulsion: \"grid\"` is E_UNSUPPORTED { feature: \"repulsion.grid\" }\n * for any n and `\"auto\"` when n > exactMaxNodes (the grid tier lands in P4); `\"exact\"` always runs.\n * @param s - the snapshot being loaded\n * @param options - the simulation's current option record\n * @returns the per-load inputs\n */\n inputs(s: GraphSnapshot, options: ForceAtlas2Options): ModelInputs {\n const resolved = resolveForceAtlas2Options(options, this.current);\n const { repulsion, exactMaxNodes } = this.tuning;\n const n = s.nodeCount;\n if (repulsion === \"grid\" || (repulsion === \"auto\" && n > exactMaxNodes)) {\n throw new WebGpuGraphError(\n \"E_UNSUPPORTED\",\n repulsion === \"grid\"\n ? 'repulsion: \"grid\" is not available yet (the grid tier lands in P4)'\n : `the graph has ${n} nodes, above exactMaxNodes ${exactMaxNodes}, and the grid tier lands in P4`,\n {\n feature: \"repulsion.grid\",\n hint: 'pass repulsion: \"exact\" (or raise exactMaxNodes) to run the exact tier at this size',\n },\n );\n }\n return { mass: resolveNodeMass(s, resolved.nodeMass), weights: resolveWeights(s, resolved.weight) };\n }\n\n /**\n * { LINLOG, DISTRIBUTED, TIER: 0, SWING_MODE: compat === \"networkx\" ? 1 : 0, STRONG_GRAVITY, GRAVITY_CENTER:\n * compat === \"networkx\" ? 1 : 0 }; USE_PERM / HAS_WEIGHTS are merged in by the simulation from ModelResources\n * (3.10, never from core.hasWeights). A pure query: the simulation calls it with the current AND the next record\n * inside setParams() to decide the recompile, so it never touches the model's record (PLAN DECISION 12).\n * @param options - an option record (the simulation's current one, or the next one of a setParams patch)\n * @returns the model's own override set\n */\n overrides(options: ForceAtlas2Options): Overrides {\n const resolved = resolveForceAtlas2Options(options, this.current);\n const mode = this.swingMode;\n return {\n LINLOG: resolved.linlog,\n DISTRIBUTED: resolved.distributedAction,\n TIER: 0,\n SWING_MODE: mode,\n STRONG_GRAVITY: resolved.strongGravity,\n GRAVITY_CENTER: mode,\n };\n }\n\n /**\n * The seven module specs of an override set in dispatch order -- K1, K2, K3, K4, K5, toScene, fill -- each with\n * only the override names its entry declares (K2 also USE_PERM / HAS_WEIGHTS), for warm() and the compile matrix.\n * @param overrides - the merged override set (the model's plus USE_PERM / HAS_WEIGHTS)\n * @param _subgroups - accepted for the ForceModel interface and unused: every reducing FA2 body carries\n * needs: [\"subgroups\"] in its registry entry and the composer picks the twin from caps.features (contract 4.3)\n * @returns the specs\n */\n specs(overrides: Overrides, _subgroups: boolean): readonly WgslModuleSpec[] {\n const [repulsionSpec, speedSpec] = RepulsionExact.specs(repulsionOverrides(overrides));\n return [\n kernelSpec(\"fa2-stats-finalize\"),\n kernelSpec(\"fa2-attraction\", subset(overrides, K2_DEFAULTS)),\n repulsionSpec,\n speedSpec,\n kernelSpec(\"fa2-integrate\", subset(overrides, K5_DEFAULTS)),\n kernelSpec(\"fa2-to-scene\"),\n kernelSpec(\"fill\"),\n ];\n }\n\n /**\n * Compiles (through the cache) and binds every kernel against the buffers of this load(): K1, K2 (or the fill of\n * force when arcCount === 0), K3 + K4 through RepulsionExact, K5, toScene, and the fill of oldForce; writes the\n * FillParams { count: 3n, value: 0, mode: 0 } into the model's uniform buffer. With n === 0 nothing is bound.\n * @param resources - the graph, the shared and model buffers, the ring and the cache\n * @param overrides - the merged override set\n */\n async bind(resources: ModelResources, overrides: Overrides): Promise<void> {\n this.dropBound();\n this.resources = resources;\n const { n, pipelines, caps, core, perm, ring, device } = resources;\n if (n === 0) {\n return;\n }\n const [k1, k2, k5, toScene, fill] = await Promise.all([\n pipelines.kernel(kernelSpec(\"fa2-stats-finalize\")),\n pipelines.kernel(kernelSpec(\"fa2-attraction\", subset(overrides, K2_DEFAULTS))),\n pipelines.kernel(kernelSpec(\"fa2-integrate\", subset(overrides, K5_DEFAULTS))),\n pipelines.kernel(kernelSpec(\"fa2-to-scene\")),\n pipelines.kernel(kernelSpec(\"fill\")),\n ]);\n const repulsion = await RepulsionExact.create(pipelines, caps, repulsionOverrides(overrides));\n if (this.resources !== resources) {\n // a newer bind() superseded this one while the pipelines compiled; its own bind groups stand\n return;\n }\n const pos = resources.buffer(\"positions\");\n const scene = resources.buffer(\"scenePositions\");\n const fixed = resources.buffer(\"fixed\");\n const partials = resources.buffer(\"partials\");\n const state = resources.buffer(\"state\");\n const trace = resources.buffer(\"trace\");\n const force = resources.buffer(\"force\");\n const oldForce = resources.buffer(\"oldForce\");\n const fillParamsBuffer = resources.buffer(FILL_PARAMS_BUFFER);\n const params = ring.binding(FA2_PARAMS);\n const fillParams: Binding = {\n buffer: fillParamsBuffer.buffer,\n offset: fillParamsBuffer.offset,\n size: FILL_PARAMS.byteLength,\n window: null,\n };\n const fillBytes = new ArrayBuffer(FILL_PARAMS.byteLength);\n FILL_PARAMS.write(new DataView(fillBytes), { count: 3 * n, value: 0, mode: 0 });\n device.queue.writeBuffer(fillParamsBuffer.buffer, fillParamsBuffer.offset, fillBytes);\n const hasArcs = core.colIdx !== null;\n repulsion.bind({ pos, state, trace, force, oldForce, fixedMask: fixed, partials, params });\n const wg = k1.workgroupSize;\n this.bound = {\n n,\n plan: plan1d(n, wg, caps),\n fillPlan: plan1d(3 * n, wg, caps),\n k1,\n k1Bound: k1.bind({ partials, S: state, T: trace, P: params }),\n k2,\n k2Bound: hasArcs\n ? k2.bind({ ...graphBindings(core, perm, resources.weights), pos, force, P: params })\n : null,\n repulsion,\n k5,\n k5Bound: k5.bind({ force, oldForce, fixedMask: fixed, S: state, pos, partials, P: params }),\n toScene,\n toSceneBound: toScene.bind({ pos, scene, P: params }),\n fill,\n fillForceBound: hasArcs ? null : fill.bind({ dst: force, P: fillParams }),\n fillOldBound: this.swingMode === 0 ? fill.bind({ dst: oldForce, P: fillParams }) : null,\n };\n }\n\n /**\n * The Fa2Params values of one iteration (the simulation overwrites the shared fields n, dim, flags,\n * iterationIndex, seed, scale, center and settleThreshold with the same values plus the flags).\n * @param iteration - the trace slot of the iteration inside its batch\n * @param options - the simulation's current option record\n * @returns the uniform values\n */\n paramsFor(iteration: number, options: ForceAtlas2Options): UniformValues {\n const { n } = this.requireResources();\n const resolved = resolveForceAtlas2Options(options, this.current);\n const { nearMax, extentFactor } = this.tuning;\n return {\n n,\n dim: resolved.dim,\n flags: 0,\n tierStart: 0,\n tierEnd: n,\n iterationIndex: iteration,\n seed: seedWord(resolved.seed),\n nearMax,\n scalingRatio: resolved.scalingRatio,\n gravity: resolved.gravity,\n jitterTolerance: resolved.jitterTolerance,\n scale: resolved.scale,\n center: [resolved.center[0], resolved.center[1], resolved.center[2], 0],\n settleThreshold: resolved.settleThreshold,\n extentFactor,\n gridMax: 0,\n levels: 0,\n pad: [0, 0, 0, 0],\n };\n }\n\n /**\n * Records one iteration into the batch: K1, K2 (or the fill of force when arcCount === 0), K3, K4, K5 in the\n * batch's ONE K1-K5 compute pass (opened by the first call of a batch and reused by every later call with the\n * same batch.id, PLAN DECISION 2), then toScene in a second pass that ends it, stopping after stage `upTo` when\n * given (spec 7.4; debugRunStages / inspect, spec 11.9 item 2). The simulation passes \"K5\" for iterations\n * 0..k-2 and undefined for the last, so toScene runs once per batch. The first call after load() zeroes\n * oldForce before K1 (paper mode). With n === 0 nothing is recorded (PLAN DECISION 9); a call before bind()\n * completed is E_NOT_LOADED (never a silent no-op).\n * @param batch - the batch being recorded\n * @param slot - the UniformRing slot holding this iteration's Fa2Params\n * @param tier - \"exact\" (the grid tier is E_UNSUPPORTED until P4; the simulation never passes \"grid\")\n * @param upTo - a stage name to stop after; undefined records every stage including toScene\n */\n recordIteration(batch: CommandBatch, slot: number, tier: \"exact\" | \"grid\", upTo?: string): void {\n if (tier === \"grid\") {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"the grid repulsion tier lands in P4\", {\n feature: \"repulsion.grid\",\n hint: 'pass repulsion: \"exact\"',\n });\n }\n const resources = this.requireResources();\n const stop = upTo === undefined ? FA2_STAGES.length - 1 : this.stageIndex(upTo);\n const { bound } = this;\n if (bound === null) {\n if (resources.n === 0) {\n return;\n }\n throw new WebGpuGraphError(\n \"E_NOT_LOADED\",\n \"the ForceAtlas2 model is not bound (bind() has not completed)\",\n {\n state: \"loaded\",\n },\n );\n }\n const offset = resources.ring.offsetOf(slot);\n const pass = this.openPass !== null && this.openPass.id === batch.id ? this.openPass.pass : batch.pass(\"fa2\");\n this.openPass = { id: batch.id, pass };\n if (this.resetOldForce) {\n this.resetOldForce = false;\n if (bound.fillOldBound !== null) {\n bound.fill.dispatch(pass, bound.fillOldBound, bound.fillPlan, [0]);\n }\n }\n bound.k1.dispatch(pass, bound.k1Bound, ONE_WORKGROUP, [offset]);\n if (stop < 1) {\n return;\n }\n if (bound.k2Bound !== null) {\n bound.k2.dispatch(pass, bound.k2Bound, bound.plan, [offset]);\n } else if (bound.fillForceBound !== null) {\n bound.fill.dispatch(pass, bound.fillForceBound, bound.fillPlan, [0]);\n }\n if (stop < 2) {\n return;\n }\n bound.repulsion.recordRepulsion(pass, bound.n, offset);\n if (stop < 3) {\n return;\n }\n bound.repulsion.recordSpeedFinalize(pass, offset);\n if (stop < 4) {\n return;\n }\n bound.k5.dispatch(pass, bound.k5Bound, bound.plan, [offset]);\n if (stop < 5) {\n return;\n }\n // the second pass ends the K1-K5 pass; the batch is complete after toScene, so nothing reuses it\n this.openPass = null;\n const scenePass = batch.pass(\"fa2-to-scene\");\n bound.toScene.dispatch(scenePass, bound.toSceneBound, bound.plan, [offset]);\n }\n\n /**\n * speed = 1, speedEfficiency = 1, swing = 1, traction = 1 (mode 1 accumulates from 1; mode 0 overwrites them each\n * iteration, the initial value is irrelevant); arms the oldForce reset of the next recordIteration.\n * @param state - the state writer of the simulation\n */\n onLoad(state: StateWriter): void {\n state.set(\"speed\", 1);\n state.set(\"speedEfficiency\", 1);\n state.set(\"swing\", 1);\n state.set(\"traction\", 1);\n this.resetOldForce = true;\n }\n\n /**\n * Mode 0: nothing (D8). Mode 1 (networkx): swing = traction = 1 (spec 7.2 \"load() and reheat() reset them to 1\").\n * @param state - the state writer of the simulation\n */\n onReheat(state: StateWriter): void {\n if (this.swingMode === 1) {\n state.set(\"swing\", 1);\n state.set(\"traction\", 1);\n }\n }\n\n /**\n * Resets speed / speedEfficiency to 1 only when linlog, strongGravity or distributedAction changed (spec 7.17);\n * a numeric tweak leaves the controller alone. The patch is validated by the same resolver the simulation uses\n * and applied over the record of the constructor / the previous onSetParams -- the only place `current` moves\n * (PLAN DECISION 12), so the comparison sees the record from BEFORE this setParams even though the simulation\n * already queried overrides(next).\n * @param patch - the setParams patch\n * @param state - the state writer of the simulation\n */\n onSetParams(patch: Partial<ForceAtlas2Options>, state: StateWriter): void {\n const next = resolveForceAtlas2Options(patch, this.current);\n const lawChanged =\n next.linlog !== this.current.linlog ||\n next.strongGravity !== this.current.strongGravity ||\n next.distributedAction !== this.current.distributedAction;\n this.current = next;\n if (lawChanged) {\n state.set(\"speed\", 1);\n state.set(\"speedEfficiency\", 1);\n }\n }\n\n /**\n * Decodes the state header and the k trace records of a completed batch (k = trace.byteLength / 32) into\n * ForceAtlas2Stats: the exact tier with null grid fields; msPerIteration null (the simulation owns the clock).\n * @param state - a DataView over the 256-byte state header\n * @param trace - a DataView over the k Fa2Trace records of the batch\n * @returns the stats\n */\n readStats(state: DataView, trace: DataView): ForceAtlas2Stats {\n const header = FA2_STATE.read(state);\n const centroid = vector(header, \"centroid\");\n const records: ForceAtlas2TraceRecord[] = [];\n const count = Math.floor(trace.byteLength / TRACE_RECORD_BYTES);\n for (let i = 0; i < count; i++) {\n const record = FA2_TRACE.read(trace, i * TRACE_RECORD_BYTES);\n records.push({\n swing: scalar(record, \"swing\"),\n traction: scalar(record, \"traction\"),\n speed: scalar(record, \"speed\"),\n speedEfficiency: scalar(record, \"speedEfficiency\"),\n meanDisplacement: scalar(record, \"meanDisplacement\"),\n settledCount: scalar(record, \"settledCount\"),\n });\n }\n return {\n iteration: scalar(header, \"iteration\"),\n meanDisplacement: scalar(header, \"meanDisplacement\"),\n rmsRadius: scalar(header, \"rmsRadius\"),\n layoutRadius: scalar(header, \"radius\"),\n centroid: [centroid[0], centroid[1], centroid[2]],\n repulsionTier: \"exact\",\n maxCellOccupancy: null,\n outsideGrid: null,\n msPerIteration: null,\n swing: scalar(header, \"swing\"),\n traction: scalar(header, \"traction\"),\n speed: scalar(header, \"speed\"),\n speedEfficiency: scalar(header, \"speedEfficiency\"),\n trace: records,\n };\n }\n\n /**\n * The resources of the last bind(), or E_NOT_LOADED before it.\n * @returns the resources\n */\n private requireResources(): ModelResources {\n if (this.resources === null) {\n throw new WebGpuGraphError(\"E_NOT_LOADED\", \"the ForceAtlas2 model has not been bound (load() first)\", {\n state: \"created\",\n });\n }\n return this.resources;\n }\n\n /**\n * The index of a stage name in FA2_STAGES, or E_INVALID_ARGUMENT.\n * @param upTo - the stage name\n * @returns its index\n */\n private stageIndex(upTo: string): number {\n for (let i = 0; i < FA2_STAGES.length; i++) {\n if (FA2_STAGES[i] === upTo) {\n return i;\n }\n }\n throw invalid(\"upTo\", upTo, FA2_STAGES.join(\" | \"));\n }\n\n /**\n * Drops the bind groups of the previous bind() (the buffers changed) so the cached kernels do not accumulate stale\n * groups across reloads; K3 / K4 live inside RepulsionExact and keep the P1-T6 behaviour. Also forgets the pass\n * of a batch recorded before the rebind.\n */\n private dropBound(): void {\n this.openPass = null;\n const { bound } = this;\n if (bound === null) {\n return;\n }\n for (const kernel of [bound.k1, bound.k2, bound.k5, bound.toScene, bound.fill]) {\n kernel.invalidate();\n }\n this.bound = null;\n }\n}\n\n// ============================================================ the factory\n\n/**\n * The resolve callback of the simulation's setParams: the patch over the current record, re-validated (the current\n * record is re-resolved first so the callback is typed without a cast).\n * @param patch - the setParams patch\n * @param current - the simulation's current option record\n * @returns the new record\n */\nfunction resolvePatch(patch: Partial<ForceAtlas2Options>, current: ForceAtlas2Options): ForceAtlas2Options {\n return resolveForceAtlas2Options(patch, resolveForceAtlas2Options(current));\n}\n\n/**\n * Spec 3.3 createForceAtlas2, verbatim: a GpuLayoutSimulation running ForceAtlas2 on the exact repulsion tier with\n * the option defaults of spec 7.14 and the GPU-only tuning of GpuLayoutTuning (contract 3.13 \"Contracts\").\n * @param ctx - the context (E_DISPOSED / E_DEVICE_LOST through assertReady)\n * @param options - the ForceAtlas2 options and the GPU-only tuning knobs in one record\n * @returns the simulation in state \"created\"; load() next\n */\nexport function createForceAtlas2(\n ctx: GpuContext,\n options?: ForceAtlas2Options & GpuLayoutTuning,\n): GpuLayoutSimulation<ForceAtlas2Options, ForceAtlas2Stats> {\n ctx.assertReady();\n const resolved = resolveForceAtlas2Options(options);\n const tuning = resolveLayoutTuning(options);\n const model = new ForceAtlas2Model(tuning, resolved);\n return new ForceSimulation<ForceAtlas2Options, ForceAtlas2Stats>(ctx, model, resolved, tuning, resolvePatch);\n}\n","/**\n * createAccelerator (spec 3.3, 9; contract 3.14): the injectable object that satisfies the CPU packages'\n * AlgorithmAccelerator and LayoutAccelerator interfaces STRUCTURALLY (spec 9.2, 9.3; the mirrors of\n * src/types/accelerator.ts until W1, D27). At P3 it carries `forceAtlas2`, `release` and `dispose` and nothing\n * else: the CPU-side dispatchers (`accelerated()`, `createSimulation()`) test `acc.pageRank !== undefined` and\n * route to the CPU when the member is absent (spec 2.4 row \"method missing\"), so a method the GPU does not\n * implement must not exist here -- never a throwing stub. The algorithm members arrive one per shipped algorithm\n * from P7; `fruchtermanReingold` / `springElectrical` with P5.\n */\n\nimport { type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { type GpuContext } from \"./context.js\";\nimport { createForceAtlas2 } from \"./layouts/forceatlas2.js\";\nimport { type AcceleratorOptions, type GpuAccelerator } from \"./types/accelerator.js\";\nimport { type ForceAtlas2Stats, type GpuLayoutSimulation, type GpuLayoutTuning } from \"./types/layout.js\";\nimport { type ForceAtlas2Options } from \"./types/options.js\";\n\n/** The `algorithms` record of AcceleratorOptions (spec 3.3), named for the copy helpers. */\ntype AlgorithmDefaults = NonNullable<AcceleratorOptions[\"algorithms\"]>;\n\n/** The `algorithms.betweenness` record of AcceleratorOptions (spec 3.3: the `k` / `sources` defaults until A2). */\ntype BetweennessDefaults = NonNullable<AlgorithmDefaults[\"betweenness\"]>;\n\n/**\n * Frozen copy of the betweenness defaults; `sources` is copied into a fresh frozen array so a later mutation of\n * the caller's list is never seen by the accelerator.\n * @param defaults - the caller's record\n * @returns the frozen copy\n */\nfunction copyBetweenness(defaults: BetweennessDefaults): BetweennessDefaults {\n const copy: { k?: number | undefined; sources?: readonly number[] | undefined } = { ...defaults };\n if (defaults.sources !== undefined) {\n copy.sources = Object.freeze([...defaults.sources]);\n }\n return Object.freeze(copy);\n}\n\n/**\n * Frozen copy of the algorithms record, one level deeper for `betweenness`.\n * @param algorithms - the caller's record\n * @returns the frozen copy\n */\nfunction copyAlgorithms(algorithms: AlgorithmDefaults): AlgorithmDefaults {\n const copy: { betweenness?: BetweennessDefaults | undefined } = { ...algorithms };\n if (algorithms.betweenness !== undefined) {\n copy.betweenness = copyBetweenness(algorithms.betweenness);\n }\n return Object.freeze(copy);\n}\n\n/**\n * The frozen deep copy of the accelerator options (spec 3.3 GpuAccelerator.options: \"the tuning defaults given\n * to createAccelerator; frozen\"; contract 3.14): the record, its `layout` tuning, its `algorithms` record, the\n * `betweenness` record and the `sources` list are each fresh frozen objects, so neither the caller's later edits\n * nor a consumer's writes can change what the accelerator's simulations inherit.\n * @param options - the caller's options, or undefined\n * @returns the frozen copy (an empty frozen record when nothing was given)\n */\nfunction freezeOptions(options: AcceleratorOptions | undefined): Readonly<AcceleratorOptions> {\n if (options === undefined) {\n return Object.freeze({});\n }\n const copy: { layout?: GpuLayoutTuning | undefined; algorithms?: AlgorithmDefaults | undefined } = { ...options };\n if (options.layout !== undefined) {\n copy.layout = Object.freeze({ ...options.layout });\n }\n if (options.algorithms !== undefined) {\n copy.algorithms = copyAlgorithms(options.algorithms);\n }\n return Object.freeze(copy);\n}\n\n/**\n * Spec 3.3 createAccelerator, verbatim: the object implementing AlgorithmAccelerator & LayoutAccelerator\n * structurally; at P3 it carries forceAtlas2, release and dispose. One per call (the app creates one and injects\n * it, spec 2.4); `kind` is \"webgpu\"; `options` is a frozen deep copy; `forceAtlas2(o)` is\n * `createForceAtlas2(ctx, { ...o, ...options.layout })`, so the GPU tuning given here wins over anything the\n * CPU-typed option object carries (spec 3.3: tuning never comes from the caller of the accelerator method);\n * `release(s)` is `ctx.release(s)`; `dispose()` is `ctx.dispose()`.\n * @param ctx - the context every simulation the accelerator creates runs on\n * @param options - GPU-only defaults inherited by every simulation (`layout`) and, from P9, the algorithm defaults\n * @returns the injectable accelerator\n * @throws E_DISPOSED / E_DEVICE_LOST from `ctx.assertReady()` (here and inside `forceAtlas2()`); `forceAtlas2()`\n * also throws what createForceAtlas2 throws (E_UNSUPPORTED for `nodeSize`, E_INVALID_ARGUMENT for a bad range)\n */\nexport function createAccelerator(ctx: GpuContext, options?: AcceleratorOptions): GpuAccelerator {\n ctx.assertReady();\n const frozen = freezeOptions(options);\n return {\n kind: \"webgpu\",\n ctx,\n options: frozen,\n /**\n * The ForceAtlas2 simulation with this accelerator's layout tuning (spec 3.3; contract 3.14).\n * @param o - the CPU option type (spec 9.3 ForceAtlas2Options); GPU tuning keys come from `options.layout`\n * @returns a fresh simulation in state \"created\"\n */\n forceAtlas2(o?: ForceAtlas2Options): GpuLayoutSimulation<ForceAtlas2Options, ForceAtlas2Stats> {\n ctx.assertReady();\n return createForceAtlas2(ctx, { ...o, ...frozen.layout });\n },\n /**\n * Destroys every device buffer recorded for the snapshot (spec 4.5); delegates to ctx.release.\n * @param s - the snapshot the app is done with\n */\n release(s: GraphSnapshot): void {\n ctx.release(s);\n },\n /**\n * Disposes the context (spec 2.8); delegates to ctx.dispose, idempotent.\n */\n dispose(): void {\n ctx.dispose();\n },\n };\n}\n"],"names":["f","scalar","k","invalid","degree","out"],"mappings":"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AA;AAAA;AAAA;ACFpC,MAAM;AAAA;AAAA,EAAmC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACGzC,MAAM;AAAA;AAAA,EAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAxC,MAAM;AAAA;AAAA,EAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACHxC,MAAM;AAAA;AAAA,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACLlC,MAAM;AAAA;AAAA,EAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACG5B,MAAM;AAAA;AAAA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACI9B,MAAM;AAAA;AAAA,EAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACgDvC,MAAM,eAA6B,aAAa,OAAO,eAAe;AAAA,EACzE,CAAC,SAAS,KAAK;AAAA,EACf,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,WAAW,KAAK;AAAA,EACjB,CAAC,UAAU,KAAK;AAAA,EAChB,CAAC,cAAc,KAAK;AAAA,EACpB,CAAC,KAAK,KAAK;AAAA,EACX,CAAC,QAAQ,KAAK;AAAA,EACd,CAAC,QAAQ,KAAK;AAClB,CAAC;AAGM,MAAM,gBAA8B,aAAa,OAAO,gBAAgB;AAAA,EAC3E,CAAC,SAAS,KAAK;AAAA,EACf,CAAC,aAAa,KAAK;AAAA,EACnB,CAAC,SAAS,KAAK;AAAA,EACf,CAAC,QAAQ,KAAK;AAClB,CAAC;AAGM,MAAM,cAA4B,aAAa,OAAO,cAAc;AAAA,EACvE,CAAC,SAAS,KAAK;AAAA,EACf,CAAC,SAAS,KAAK;AAAA,EACf,CAAC,QAAQ,KAAK;AAAA,EACd,CAAC,QAAQ,KAAK;AAClB,CAAC;AAGM,MAAM,aAA2B,aAAa,OAAO,aAAa;AAAA,EACrE,CAAC,KAAK,KAAK;AAAA,EACX,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,SAAS,KAAK;AAAA,EACf,CAAC,aAAa,KAAK;AAAA,EACnB,CAAC,WAAW,KAAK;AAAA,EACjB,CAAC,kBAAkB,KAAK;AAAA,EACxB,CAAC,QAAQ,KAAK;AAAA,EACd,CAAC,WAAW,KAAK;AAAA,EACjB,CAAC,gBAAgB,KAAK;AAAA,EACtB,CAAC,WAAW,KAAK;AAAA,EACjB,CAAC,mBAAmB,KAAK;AAAA,EACzB,CAAC,SAAS,KAAK;AAAA,EACf,CAAC,UAAU,OAAO;AAAA,EAClB,CAAC,mBAAmB,KAAK;AAAA,EACzB,CAAC,gBAAgB,KAAK;AAAA,EACtB,CAAC,WAAW,KAAK;AAAA,EACjB,CAAC,UAAU,KAAK;AAAA,EAChB,CAAC,OAAO,OAAO;AACnB,CAAC;AAGM,MAAM,YAA0B,aAAa;AAAA,EAChD;AAAA,EACA;AAAA,IACI,CAAC,SAAS,KAAK;AAAA,IACf,CAAC,mBAAmB,KAAK;AAAA,IACzB,CAAC,SAAS,KAAK;AAAA,IACf,CAAC,YAAY,KAAK;AAAA,IAClB,CAAC,YAAY,OAAO;AAAA,IACpB,CAAC,aAAa,KAAK;AAAA,IACnB,CAAC,UAAU,KAAK;AAAA,IAChB,CAAC,oBAAoB,KAAK;AAAA,IAC1B,CAAC,aAAa,KAAK;AAAA,IACnB,CAAC,OAAO,OAAO;AAAA,IACf,CAAC,OAAO,OAAO;AAAA,IACf,CAAC,WAAW,OAAO;AAAA,IACnB,CAAC,OAAO,KAAK;AAAA,IACb,CAAC,gBAAgB,KAAK;AAAA,IACtB,CAAC,eAAe,KAAK;AAAA,IACrB,CAAC,oBAAoB,KAAK;AAAA,IAC1B,CAAC,aAAa,OAAO;AAAA,IACrB,CAAC,aAAa,OAAO;AAAA,IACrB,CAAC,aAAa,OAAO;AAAA,IACrB,CAAC,aAAa,OAAO;AAAA,IACrB,CAAC,aAAa,OAAO;AAAA,IACrB,CAAC,aAAa,OAAO;AAAA,IACrB,CAAC,aAAa,OAAO;AAAA,IACrB,CAAC,aAAa,OAAO;AAAA,IACrB,CAAC,aAAa,OAAO;AAAA,EAAA;AAAA,EAEzB,EAAE,QAAQ,WAAW,OAAO,mBAAA;AAChC;AAGO,MAAM,YAA0B,aAAa;AAAA,EAChD;AAAA,EACA;AAAA,IACI,CAAC,SAAS,KAAK;AAAA,IACf,CAAC,YAAY,KAAK;AAAA,IAClB,CAAC,SAAS,KAAK;AAAA,IACf,CAAC,mBAAmB,KAAK;AAAA,IACzB,CAAC,oBAAoB,KAAK;AAAA,IAC1B,CAAC,gBAAgB,KAAK;AAAA,IACtB,CAAC,aAAa,KAAK;AAAA,IACnB,CAAC,QAAQ,KAAK;AAAA,EAAA;AAAA,EAElB,EAAE,QAAQ,UAAA;AACd;AAGO,MAAM,cAA4B,aAAa;AAAA,EAClD;AAAA,EACA;AAAA,IACI,CAAC,OAAO,OAAO;AAAA,IACf,CAAC,OAAO,OAAO;AAAA,IACf,CAAC,OAAO,OAAO;AAAA,IACf,CAAC,iBAAiB,OAAO;AAAA,IACzB,CAAC,YAAY,OAAO;AAAA,EAAA;AAAA,EAExB,EAAE,QAAQ,UAAA;AACd;AAaA,SAAS,KACL,OACA,SACA,MACA,MACA,UACW;AACX,SAAO,EAAE,OAAO,SAAS,MAAM,MAAM,SAAA;AACzC;AAGA,MAAM,cAAsC;AAAA,EACxC,KAAK,GAAG,GAAG,UAAU,cAAc,YAAY;AAAA,EAC/C,KAAK,GAAG,GAAG,UAAU,cAAc,YAAY;AAAA,EAC/C,KAAK,GAAG,GAAG,WAAW,cAAc,YAAY;AAAA,EAChD,KAAK,GAAG,GAAG,QAAQ,cAAc,YAAY;AACjD;AAGA,MAAM,SAAsB;AAAA,EACxB,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU,YAAY,OAAO,KAAK,GAAG,GAAG,OAAO,WAAW,YAAY,GAAG,KAAK,GAAG,GAAG,KAAK,WAAW,aAAa,CAAC;AAAA,EAClH,eAAe,CAAA;AAAA,EACf,UAAU,CAAC,YAAY;AAAA,EACvB,OAAO,CAAA;AAAA,EACP,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAGA,MAAM,SAAsB;AAAA,EACxB,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU;AAAA,IACN,KAAK,GAAG,GAAG,OAAO,cAAc,YAAY;AAAA,IAC5C,KAAK,GAAG,GAAG,OAAO,WAAW,YAAY;AAAA,IACzC,KAAK,GAAG,GAAG,KAAK,WAAW,cAAc;AAAA,EAAA;AAAA,EAE7C,eAAe;AAAA,IACX,EAAE,MAAM,MAAM,MAAM,OAAO,SAAS,EAAA;AAAA,IACpC,EAAE,MAAM,SAAS,MAAM,OAAO,SAAS,EAAA;AAAA,IACvC,EAAE,MAAM,SAAS,MAAM,QAAQ,SAAS,MAAA;AAAA,EAAM;AAAA,EAElD,UAAU,CAAC,aAAa;AAAA,EACxB,OAAO,CAAC,WAAW;AAAA,EACnB,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAGA,MAAM,OAAoB;AAAA,EACtB,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU,CAAC,KAAK,GAAG,GAAG,OAAO,WAAW,YAAY,GAAG,KAAK,GAAG,GAAG,KAAK,WAAW,YAAY,CAAC;AAAA,EAC/F,eAAe,CAAA;AAAA,EACf,UAAU,CAAC,WAAW;AAAA,EACtB,OAAO,CAAA;AAAA,EACP,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAGA,MAAM,mBAAgC;AAAA,EAClC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU,YAAY,OAAO,KAAK,GAAG,GAAG,OAAO,WAAW,YAAY,GAAG,KAAK,GAAG,GAAG,KAAK,WAAW,aAAa,CAAC;AAAA,EAClH,eAAe;AAAA,IACX,EAAE,MAAM,MAAM,MAAM,OAAO,SAAS,EAAA;AAAA,IACpC,EAAE,MAAM,QAAQ,MAAM,OAAO,SAAS,EAAA;AAAA,EAAE;AAAA,EAE5C,UAAU,CAAC,YAAY;AAAA,EACvB,OAAO,CAAA;AAAA,EACP,cAAc,CAAC,OAAO;AAAA,EACtB,OAAO;AACX;AAGA,MAAM,qBAAkC;AAAA,EACpC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU;AAAA,IACN,KAAK,GAAG,GAAG,YAAY,cAAc,mBAAmB;AAAA,IACxD,KAAK,GAAG,GAAG,KAAK,WAAW,UAAU;AAAA,IACrC,KAAK,GAAG,GAAG,KAAK,WAAW,iBAAiB;AAAA,IAC5C,KAAK,GAAG,GAAG,KAAK,WAAW,WAAW;AAAA,EAAA;AAAA,EAE1C,eAAe,CAAA;AAAA,EACf,UAAU,CAAC,YAAY,WAAW,WAAW,WAAW;AAAA,EACxD,OAAO,CAAC,WAAW;AAAA,EACnB,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAGA,MAAM,iBAA8B;AAAA,EAChC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU,YAAY;AAAA,IAClB,KAAK,GAAG,GAAG,OAAO,cAAc,cAAc;AAAA,IAC9C,KAAK,GAAG,GAAG,SAAS,WAAW,YAAY;AAAA,IAC3C,KAAK,GAAG,GAAG,KAAK,WAAW,WAAW;AAAA,EAAA;AAAA,EAE1C,eAAe;AAAA,IACX,EAAE,MAAM,UAAU,MAAM,QAAQ,SAAS,MAAA;AAAA,IACzC,EAAE,MAAM,eAAe,MAAM,QAAQ,SAAS,MAAA;AAAA,IAC9C,EAAE,MAAM,QAAQ,MAAM,OAAO,SAAS,EAAA;AAAA,EAAE;AAAA,EAE5C,UAAU,CAAC,UAAU;AAAA,EACrB,OAAO,CAAA;AAAA,EACP,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAGA,MAAM,sBAAmC;AAAA,EACrC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU;AAAA,IACN,KAAK,GAAG,GAAG,OAAO,cAAc,cAAc;AAAA,IAC9C,KAAK,GAAG,GAAG,KAAK,WAAW,UAAU;AAAA,IACrC,KAAK,GAAG,GAAG,SAAS,WAAW,YAAY;AAAA,IAC3C,KAAK,GAAG,GAAG,YAAY,cAAc,YAAY;AAAA,IACjD,KAAK,GAAG,GAAG,aAAa,cAAc,YAAY;AAAA,IAClD,KAAK,GAAG,GAAG,YAAY,WAAW,mBAAmB;AAAA,IACrD,KAAK,GAAG,GAAG,KAAK,WAAW,WAAW;AAAA,EAAA;AAAA,EAE1C,eAAe;AAAA,IACX,EAAE,MAAM,cAAc,MAAM,OAAO,SAAS,EAAA;AAAA,IAC5C,EAAE,MAAM,kBAAkB,MAAM,QAAQ,SAAS,MAAA;AAAA,IACjD,EAAE,MAAM,kBAAkB,MAAM,OAAO,SAAS,EAAA;AAAA,EAAE;AAAA,EAEtD,UAAU,CAAC,YAAY,WAAW,WAAW;AAAA,EAC7C,OAAO,CAAC,WAAW;AAAA,EACnB,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAGA,MAAM,qBAAkC;AAAA,EACpC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU;AAAA,IACN,KAAK,GAAG,GAAG,YAAY,cAAc,mBAAmB;AAAA,IACxD,KAAK,GAAG,GAAG,KAAK,WAAW,UAAU;AAAA,IACrC,KAAK,GAAG,GAAG,KAAK,WAAW,iBAAiB;AAAA,IAC5C,KAAK,GAAG,GAAG,KAAK,WAAW,WAAW;AAAA,EAAA;AAAA,EAE1C,eAAe,CAAC,EAAE,MAAM,cAAc,MAAM,OAAO,SAAS,GAAG;AAAA,EAC/D,UAAU,CAAC,YAAY,WAAW,WAAW,WAAW;AAAA,EACxD,OAAO,CAAC,WAAW;AAAA,EACnB,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAGA,MAAM,gBAA6B;AAAA,EAC/B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU;AAAA,IACN,KAAK,GAAG,GAAG,SAAS,cAAc,YAAY;AAAA,IAC9C,KAAK,GAAG,GAAG,YAAY,WAAW,YAAY;AAAA,IAC9C,KAAK,GAAG,GAAG,aAAa,cAAc,YAAY;AAAA,IAClD,KAAK,GAAG,GAAG,KAAK,WAAW,UAAU;AAAA,IACrC,KAAK,GAAG,GAAG,OAAO,WAAW,cAAc;AAAA,IAC3C,KAAK,GAAG,GAAG,YAAY,WAAW,mBAAmB;AAAA,IACrD,KAAK,GAAG,GAAG,KAAK,WAAW,WAAW;AAAA,EAAA;AAAA,EAE1C,eAAe,CAAC,EAAE,MAAM,cAAc,MAAM,OAAO,SAAS,GAAG;AAAA,EAC/D,UAAU,CAAC,YAAY,WAAW,WAAW;AAAA,EAC7C,OAAO,CAAC,WAAW;AAAA,EACnB,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAGA,MAAM,eAA4B;AAAA,EAC9B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU;AAAA,IACN,KAAK,GAAG,GAAG,OAAO,cAAc,cAAc;AAAA,IAC9C,KAAK,GAAG,GAAG,SAAS,WAAW,YAAY;AAAA,IAC3C,KAAK,GAAG,GAAG,KAAK,WAAW,WAAW;AAAA,EAAA;AAAA,EAE1C,eAAe,CAAA;AAAA,EACf,UAAU,CAAC,UAAU;AAAA,EACrB,OAAO,CAAA;AAAA,EACP,cAAc,CAAA;AAAA,EACd,OAAO;AACX;AAUA,MAAM,WAA6D,OAAO,OAAO;AAAA,EAC7E,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,gBAAgB;AACpB,CAAC;AAMD,MAAM,oCAAoB,IAAA;AAO1B,SAAS,QAAQ,IAA2B;AACxC,QAAM,QAAQ,SAAS,EAAE;AACzB,MAAI,UAAU,QAAW;AACrB,UAAM,IAAI,iBAAiB,sBAAsB,sBAAsB,EAAE,KAAK;AAAA,MAC1E,UAAU;AAAA,MACV,OAAO;AAAA,MACP,UAAU,OAAO,KAAK,QAAQ;AAAA,IAAA,CACjC;AAAA,EACL;AACA,SAAO;AACX;AAWO,SAAS,WACZ,IACA,WACA,UACc;AACd,QAAM,QAAQ,QAAQ,EAAE;AACxB,SAAO;AAAA,IACH,IAAI,MAAM;AAAA,IACV,MAAM,cAAc,IAAI,EAAE,KAAK,MAAM;AAAA,IACrC,UAAU,MAAM;AAAA,IAChB,eAAe,MAAM;AAAA,IACrB,WAAW,aAAa,CAAA;AAAA,IACxB,OAAO,MAAM;AAAA,IACb,UAAU,MAAM;AAAA,IAChB;AAAA,EAAA;AAER;AA4BO,SAAS,cACZ,MACA,MACA,SACmE;AACnE,QAAM,SAAS,KAAK,UAAU,KAAK;AACnC,QAAM,WAAW,YAAY,SAAY,KAAK,UAAU;AACxD,SAAO;AAAA,IACH,QAAQ,KAAK;AAAA,IACb;AAAA,IACA,SAAS,YAAY;AAAA,IACrB,MAAM,QAAQ,KAAK;AAAA,EAAA;AAE3B;AAUO,SAAS,eACZ,MACA,MACA,SACqD;AACrD,QAAM,WAAW,YAAY,SAAY,KAAK,UAAU;AACxD,SAAO,EAAE,UAAU,SAAS,MAAM,aAAa,aAAa,KAAA;AAChE;ACxdA,SAAS,UAAU,MAA8C,GAAuB;AACpF,MAAI,SAAS,QAAW;AACpB,WAAO;AAAA,EACX;AACA,MAAI,gBAAgB,eAAe,KAAK,WAAW,KAAK,KAAK,kBAAkB,aAAa;AACxF,WAAO;AAAA,EACX;AACA,QAAM,IAAI;AAAA,IACN;AAAA,IACA,gDAAgD,CAAC;AAAA,IACjD;AAAA,MACI,UAAU;AAAA,MACV,OAAO,GAAG,KAAK,YAAY,IAAI,IAAI,KAAK,MAAM;AAAA,MAC9C,UAAU,eAAe,CAAC;AAAA,IAAA;AAAA,EAC9B;AAER;AAUA,SAAS,OAAO,KAAiB,GAA+B;AAC5D,MAAI;AACA,WAAO,IAAI,UAAU,KAAK,CAAC;AAAA,EAC/B,SAAS,OAAgB;AACrB,QAAI,mBAAmB,KAAK,KAAK,MAAM,SAAS,iBAAiB,MAAM,QAAQ,SAAS,YAAY;AAChG,YAAM,IAAI;AAAA,QACN;AAAA,QACA;AAAA,QACA,EAAE,GAAG,MAAM,SAAS,WAAW,SAAA;AAAA,MAAS;AAAA,IAEhD;AACA,UAAM;AAAA,EACV;AACJ;AAYA,eAAsB,OAAO,KAAiB,GAAkB,SAAuC;AACnG,MAAI,YAAA;AACJ,QAAM,IAAI,EAAE;AACZ,QAAM,OAAO,UAAU,SAAS,MAAM,CAAC;AACvC,MAAI,SAAS,QAAQ,SAAS;AAC1B,UAAM,IAAI,iBAAiB,aAAa,0DAA0D,CAAA,CAAE;AAAA,EACxG;AACA,MAAI,MAAM,GAAG;AACT,aAAS,aAAa,GAAG,CAAC;AAC1B,WAAO,QAAQ,IAAI,YAAY,CAAC;AAAA,EACpC;AACA,QAAM,OAAO,OAAO,KAAK,CAAC;AAC1B,MAAI,EAAE,aAAa,GAAG;AAClB,UAAM,QAAQ,QAAQ,IAAI,YAAY,CAAC;AACvC,UAAM,KAAK,CAAC;AACZ,aAAS,aAAa,GAAG,CAAC;AAC1B,WAAO;AAAA,EACX;AACA,QAAM,aAAa,IAAI;AACvB,QAAM,MAAM,IAAI,KAAK;AAAA,IACjB;AAAA,IACA,YAAY,UAAU,YAAY,WAAW,YAAY;AAAA,IACzD;AAAA,EAAA;AAEJ,QAAM,SAAS,IAAI,KAAK;AAAA,IACpB,aAAa;AAAA,IACb,YAAY,UAAU,YAAY;AAAA,IAClC;AAAA,EAAA;AAEJ,MAAI;AACA,UAAM,IAAI,UAAU,MAAA;AACpB,UAAM,SAAS,MAAM,IAAI,UAAU,OAAO,WAAW,UAAU,eAAe,MAAM,IAAI,CAAC,CAAC;AAC1F,UAAM,QAAQ,IAAI,YAAY,aAAa,UAAU;AACrD,iBAAa,MAAM,IAAI,SAAS,KAAK,GAAG,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,EAAE,UAAU,YAAY,GAAG,GAAG;AAC9G,QAAI,OAAO,MAAM,YAAY,QAAQ,GAAG,KAAK;AAC7C,UAAM,aAAsB,EAAE,QAAQ,KAAK,QAAQ,GAAG,MAAM,YAAY,QAAQ,KAAA;AAChF,UAAM,gBAAyB,EAAE,QAAQ,QAAQ,QAAQ,GAAG,MAAM,aAAa,YAAY,QAAQ,KAAA;AACnG,UAAM,QAAQ,OAAO,KAAK,EAAE,GAAG,cAAc,MAAM,IAAI,GAAG,KAAK,YAAY,GAAG,eAAe;AAC7F,UAAM,UAAU,IAAI,OAAO,qBAAqB,EAAE,OAAO,UAAU;AACnE,UAAM,OAAO,QAAQ,iBAAiB,EAAE,OAAO,UAAU;AACzD,WAAO,SAAS,MAAM,OAAO,OAAO,GAAG,IAAI,eAAe,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;AACxE,SAAK,IAAA;AACL,QAAI,OAAO,MAAM,OAAO,CAAC,QAAQ,OAAA,CAAQ,CAAC;AAC1C,QAAI,YAAA;AACJ,UAAM,SAAS,MAAM,IAAI,SAAS,KAAK,KAAK,YAAY,QAAQ,MAAS;AACzE,QAAI,YAAA;AACJ,aAAS,aAAa,GAAG,CAAC;AAC1B,WAAO,QAAQ,IAAI,YAAY,MAAM;AAAA,EACzC,UAAA;AACI,QAAI,KAAK,QAAQ,MAAM;AACvB,QAAI,KAAK,QAAQ,GAAG;AAAA,EACxB;AACJ;ACnHA,MAAM,gBAAgB;AAOtB,eAAe,QAAQ,SAA2B,SAAgC;AAC9E,MAAI;AACJ,QAAM,QAAQ,IAAI,QAAc,CAAC,YAAY;AACzC,YAAQ,WAAW,SAAS,OAAO;AAAA,EACvC,CAAC;AACD,QAAM,QAAQ,KAAK;AAAA,IACf,QAAQ;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,IAAA;AAAA,IAEV;AAAA,EAAA,CACH;AACD,eAAa,KAAK;AACtB;AAOA,SAAS,UAAU,OAAwB;AACvC,MAAI,iBAAiB,OAAO;AACxB,WAAO,MAAM;AAAA,EACjB;AACA,MAAI,OAAO,UAAU,UAAU;AAC3B,WAAO;AAAA,EACX;AACA,SAAO,qBAAqB,OAAO,KAAK;AAC5C;AAsCO,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBtB,YAAY,MAAiB,OAAe,YAAqB;AAbjE,SAAiB,WAA8B,CAAA;AAC/C,SAAQ,WAAyC;AACjD,SAAQ,gBAAgB;AACxB,SAAQ,eAAe;AACvB,SAAQ,OAA2B;AACnC,SAAQ,YAAY;AAShB,SAAK,OAAO;AACZ,SAAK,KAAK,KAAK,YAAA;AACf,SAAK,aAAa,cAAc;AAChC,SAAK,QAAQ;AACb,SAAK,UAAU,KAAK,OAAO,qBAAqB,EAAE,OAAO,SAAS,KAAK,IAAI,KAAK,EAAE,GAAA,CAAI;AAAA,EAC1F;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,aAAqB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAK,OAAsC;AACvC,SAAK,WAAW,MAAM;AACtB,SAAK,QAAA;AACL,UAAM,aAAuC,EAAE,OAAO,SAAS,KAAK,KAAK,IAAI,KAAK,EAAE,IAAI,KAAK,GAAA;AAC7F,UAAM,kBAAkB,KAAK,KAAK,UAAU,UAAU,KAAK;AAC3D,QAAI,oBAAoB,QAAW;AAC/B,iBAAW,kBAAkB;AAAA,IACjC;AACA,UAAM,OAAO,KAAK,QAAQ,iBAAiB,UAAU;AACrD,SAAK,gBAAgB,IAAI;AACzB,SAAK,WAAW;AAChB,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,UAAgB;AACZ,QAAI,KAAK,aAAa,MAAM;AACxB,WAAK,SAAS,IAAA;AACd,WAAK,WAAW;AAAA,IACpB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAK,KAAc,KAAc,YAA0B;AACvD,SAAK,WAAW,MAAM;AACtB,SAAK,gBAAgB,UAAU;AAC/B,QAAI,aAAa,IAAI,QAAQ,aAAa,IAAI,MAAM;AAChD,YAAM,IAAI;AAAA,QACN;AAAA,QACA,WAAW,UAAU,iCAAiC,IAAI,IAAI,SAAS,IAAI,IAAI;AAAA,QAC/E;AAAA,UACI,UAAU;AAAA,UACV,OAAO;AAAA,UACP,UAAU,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,QAAA;AAAA,MAChD;AAAA,IAER;AACA,SAAK,QAAA;AACL,SAAK,QAAQ,mBAAmB,IAAI,QAAQ,IAAI,QAAQ,IAAI,QAAQ,IAAI,QAAQ,UAAU;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAAS,KAAgB,WAAmB,YAAqC;AAC7E,SAAK,WAAW,UAAU;AAC1B,SAAK,gBAAgB,UAAU;AAC/B,QAAI,CAAC,OAAO,UAAU,SAAS,KAAK,YAAY,KAAK,YAAY,MAAM,KAAK,YAAY,aAAa,IAAI,MAAM;AAC3G,YAAM,IAAI;AAAA,QACN;AAAA,QACA,gBAAgB,SAAS,KAAK,YAAY,UAAU,oBAAoB,IAAI,IAAI;AAAA,QAChF;AAAA,UACI,UAAU;AAAA,UACV,OAAO;AAAA,UACP,UAAU,kDAAkD,IAAI,IAAI;AAAA,QAAA;AAAA,MACxE;AAAA,IAER;AACA,UAAM,UAA2B,EAAE,KAAK,WAAW,YAAY,QAAQ,KAAK,aAAA;AAC5E,SAAK,SAAS,KAAK,OAAO;AAC1B,SAAK,gBAAgB;AACrB,SAAK,WAAW,KAAK,YAAY;AACjC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,gBAAgB,UAAuB,YAAoB,YAAoB,aAA8B;AACzG,SAAK,WAAW,iBAAiB;AACjC,SAAK,QAAA;AACL,SAAK,QAAQ,gBAAgB,UAAU,YAAY,YAAY,aAAa,CAAC;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAyB;AACrB,SAAK,WAAW,QAAQ;AACxB,SAAK,YAAY;AACjB,SAAK,QAAA;AACL,UAAM,EAAE,SAAS;AACjB,UAAM,gBAAgB,KAAK,KAAK,iBAAA;AAChC,QAAI;AACA,WAAK,KAAK,YAAA;AAAA,IACd,SAAS,OAAO;AACZ,WAAK,YAAA;AACL,YAAM;AAAA,IACV;AACA,QAAI,SAAS,MAAM;AACf,iBAAW,WAAW,KAAK,UAAU;AACjC,aAAK,QAAQ;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,KAAK;AAAA,UACL,QAAQ;AAAA,UACR,QAAQ;AAAA,QAAA;AAAA,MAEhB;AAAA,IACJ;AACA,UAAM,gBAAgB,KAAK,QAAQ,OAAO,EAAE,OAAO,SAAS,KAAK,KAAK,IAAI,KAAK,EAAE,IAAI;AACrF,SAAK,KAAK,OAAO,MAAM,OAAO,CAAC,aAAa,CAAC;AAG7C,UAAM,eAAe,KAAK,KAAK,iBAAA;AAC/B,UAAM,UAAU,iBAAiB;AACjC,UAAM,QAAsB,EAAE,WAAW,MAAA;AACzC,UAAM,WAAW,YAAY,OAAO,KAAK,cAAc,MAAM,KAAK,IAAI,KAAK,eAAe,OAAO;AACjG,WAAO;AAAA,MACH,IAAI,KAAK;AAAA,MACT,YAAY,KAAK;AAAA,MACjB;AAAA,MACA,SAAS,MAAY;AACjB,cAAM,YAAY;AAAA,MACtB;AAAA,IAAA;AAAA,EAER;AAAA,EAEQ,eAAe,SAAiD;AACpE,SAAK,YAAA;AACL,WAAO,QAAQ,OAAO,KAAK,UAAU,OAAO,CAAC;AAAA,EACjD;AAAA,EAEA,MAAc,cAAc,MAA0B,OAA2C;AAC7F,QAAI,SAAS,MAAM;AACf,YAAM,KAAK,KAAK,UAAU,MAAA;AAC1B,aAAO,IAAI,YAAY,CAAC;AAAA,IAC5B;AACA,UAAM,QAAQ,KAAK;AACnB,QAAI,aAAyB,MAAY;AACzC,UAAM,OAAO,IAAI,QAAe,CAAC,UAAU,WAAW;AAClD,mBAAa,KAAK,KAAK,OAAO,CAAC,SAAS;AACpC,eAAO,gBAAgB,IAAI,CAAC;AAAA,MAChC,CAAC;AAAA,IACL,CAAC;AACD,SAAK,KAAK,MAAM,MAAM,MAAS;AAC/B,UAAM,SAAS,KAAK,KAAK,SAAS,QAAQ,MAAM,KAAK;AACrD,SAAK,OAAO,MAAM,MAAM,MAAS;AACjC,QAAI;AACJ,QAAI;AACA,YAAM,QAAQ,KAAK,CAAC,QAAQ,IAAI,CAAC;AACjC,WAAK,KAAK,YAAA;AACV,cAAQ,MAAM,YAAY,IAAI,YAAY,CAAC,IAAI,KAAK,OAAO,eAAe,GAAG,KAAK,EAAE,MAAM,CAAC;AAAA,IAC/F,SAAS,OAAO;AAEZ,YAAM,QAAQ,QAAQ,aAAa;AACnC,WAAK,YAAA;AACL,YAAM,MAAM,KAAK,SAAS,OAAO,IAAI;AAAA,IACzC,UAAA;AACI,iBAAA;AAAA,IACJ;AACA,SAAK,YAAA;AACL,UAAM,KAAK,KAAK,UAAU,MAAA;AAC1B,WAAO;AAAA,EACX;AAAA,EAEA,MAAc,SAAS,OAAgB,MAAiD;AACpF,QAAI,mBAAmB,KAAK,GAAG;AAC3B,aAAO,MAAM,SAAS,mBAAmB,MAAM,SAAS,eAAe,QAAQ,KAAK,UAAU,KAAK;AAAA,IACvG;AACA,QAAI;AACA,WAAK,KAAK,YAAA;AAAA,IACd,SAAS,OAAO;AACZ,UAAI,mBAAmB,KAAK,GAAG;AAC3B,eAAO,MAAM,SAAS,mBAAmB,MAAM,SAAS,eAAe,QAAQ,KAAK,UAAU,KAAK;AAAA,MACvG;AAAA,IACJ;AACA,QAAI;AACJ,UAAM,QAAQ,IAAI,QAAc,CAAC,YAAY;AACzC,cAAQ,WAAW,MAAM;AACrB,gBAAQ,IAAI;AAAA,MAChB,GAAG,aAAa;AAAA,IACpB,CAAC;AACD,UAAM,OAAO,MAAM,QAAQ,KAAK;AAAA,MAC5B,KAAK;AAAA,QACD,MAAM;AAAA,QACN,CAAC,WAAoB;AAAA,MAAA;AAAA,MAEzB;AAAA,IAAA,CACH;AACD,iBAAa,KAAK;AAClB,QAAI,mBAAmB,IAAI,GAAG;AAC1B,aAAO;AAAA,IACX;AACA,UAAM,UAAU,UAAU,KAAK;AAC/B,WAAO,IAAI;AAAA,MACP;AAAA,MACA,6BAA6B,KAAK,EAAE,KAAK,KAAK,KAAK,MAAM,OAAO;AAAA,MAChE;AAAA,QACI,OAAO,KAAK;AAAA,QACZ;AAAA,QACA,SAAS,KAAK;AAAA,MAAA;AAAA,IAClB;AAAA,EAER;AAAA,EAEQ,UAAU,OAA2C;AACzD,WAAO,IAAI,iBAAiB,MAAM,MAAM,GAAG,MAAM,OAAO,wBAAwB,KAAK,EAAE,KAAK,KAAK,KAAK,MAAM;AAAA,MACxG,GAAG,MAAM;AAAA,MACT,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,IAAA,CACpB;AAAA,EACL;AAAA,EAEQ,WAAW,YAA0B;AACzC,QAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,YAAY,YAAY;AACxD;AAAA,IACJ;AACA,SAAK,YAAA;AACL,SAAK,OAAO,KAAK,KAAK,SAAS,WAAW,UAAU;AAAA,EACxD;AAAA,EAEQ,cAAoB;AACxB,QAAI,KAAK,SAAS,MAAM;AACpB;AAAA,IACJ;AACA,UAAM,EAAE,SAAS;AACjB,SAAK,OAAO;AACZ,QAAI;AACA,WAAK,KAAK,SAAS,WAAW,IAAI;AAAA,IACtC,SAAS,OAAO;AACZ,UAAI,CAAC,mBAAmB,KAAK,KAAK,MAAM,SAAS,cAAc;AAC3D,cAAM;AAAA,MACV;AAAA,IACJ;AAAA,EACJ;AAAA,EAEQ,gBAAgB,MAAmC;AACvD,UAAM,SAAS,KAAK,mBAAmB,KAAK,IAAI;AAChD,UAAM,WAAW,KAAK,2BAA2B,KAAK,IAAI;AAC1D,SAAK,qBAAqB,CAAC,GAAW,GAAY,MAA0B;AACxE,WAAK,iBAAiB;AACtB,aAAO,GAAG,GAAG,CAAC;AACd,aAAO;AAAA,IACX;AACA,SAAK,6BAA6B,CAAC,QAAmB,WAA8B;AAChF,WAAK,iBAAiB;AACtB,eAAS,QAAQ,MAAM;AACvB,aAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEQ,WAAW,WAAyB;AACxC,QAAI,KAAK,WAAW;AAChB,YAAM,IAAI;AAAA,QACN;AAAA,QACA,GAAG,SAAS,8BAA8B,KAAK,EAAE,KAAK,KAAK,KAAK;AAAA,QAChE;AAAA,UACI,UAAU;AAAA,UACV,OAAO,KAAK;AAAA,UACZ,UAAU;AAAA,QAAA;AAAA,MACd;AAAA,IAER;AAAA,EACJ;AAAA,EAEQ,gBAAgB,YAA0B;AAC9C,QAAI,CAAC,OAAO,UAAU,UAAU,KAAK,cAAc,KAAK,aAAa,MAAM,GAAG;AAC1E,YAAM,IAAI;AAAA,QACN;AAAA,QACA,cAAc,UAAU;AAAA,QACxB;AAAA,UACI,UAAU;AAAA,UACV,OAAO;AAAA,UACP,UAAU;AAAA,QAAA;AAAA,MACd;AAAA,IAER;AAAA,EACJ;AACJ;ACzZO,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBrB,YAAY,QAAmB,WAA8B,OAAe,OAAe;AAZ3F,SAAQ,OAAO;AACf,SAAQ,UAAU;AAClB,SAAQ,UAAU;AAClB,SAAQ,YAAY;AAUhB,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACvC,YAAM,IAAI;AAAA,QACN;AAAA,QACA,gBAAgB,KAAK,4CAA4C,KAAK;AAAA,QACtE;AAAA,UACI,UAAU;AAAA,UACV,OAAO;AAAA,UACP,UAAU;AAAA,QAAA;AAAA,MACd;AAAA,IAER;AACA,SAAK,SAAS;AACd,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,QAAQ;AACb,SAAK,SAAS,IAAI,YAAY,QAAQ,kBAAkB;AACxD,SAAK,OAAO,IAAI,SAAS,KAAK,MAAM;AACpC,SAAK,SAAS,UAAU,aAAa;AAAA,MACjC;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,OAAO,YAAY,UAAU,YAAY;AAAA,IAAA,CAC5C;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,OAA8B;AAClC,SAAK,WAAA;AACL,SAAK,WAAW,KAAK;AACrB,WAAO,EAAE,QAAQ,KAAK,QAAQ,QAAQ,GAAG,MAAM,MAAM,YAAY,QAAQ,KAAA;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,MAAsB;AAC3B,SAAK,UAAU,IAAI;AACnB,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,OAAuB;AAC3B,SAAK,WAAA;AACL,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,KAAK,OAAO;AAC7D,YAAM,IAAI;AAAA,QACN;AAAA,QACA,gBAAgB,KAAK,KAAK,qBAAqB,KAAK,OAAO,KAAK,KAAK;AAAA,QACrE;AAAA,UACI,UAAU;AAAA,UACV,OAAO;AAAA,UACP,UAAU,qBAAqB,KAAK,KAAK;AAAA,QAAA;AAAA,MAC7C;AAAA,IAER;AACA,QAAI,KAAK,OAAO,QAAQ,KAAK,OAAO;AAChC,WAAK,OAAO;AAAA,IAChB;AACA,UAAM,QAAQ,KAAK;AACnB,SAAK,QAAQ;AACb,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAc,OAAqB,QAA6B;AAClE,SAAK,UAAU,IAAI;AACnB,SAAK,WAAW,KAAK;AACrB,UAAM,MAAM,KAAK,MAAM,QAAQ,OAAO,kBAAkB;AACxD,QAAI,KAAK,UAAU,KAAK,OAAO,KAAK,SAAS;AACzC,WAAK,UAAU;AAAA,IACnB;AACA,QAAI,OAAO,KAAK,SAAS;AACrB,WAAK,UAAU;AAAA,IACnB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AACV,SAAK,WAAA;AACL,QAAI,KAAK,UAAU,GAAG;AAClB;AAAA,IACJ;AACA,UAAM,QAAQ,KAAK,UAAU;AAC7B,UAAM,OAAO,KAAK,UAAU,KAAK;AACjC,SAAK,OAAO,MAAM,YAAY,KAAK,QAAQ,OAAO,KAAK,QAAQ,OAAO,MAAM,KAAK;AACjF,SAAK,UAAU;AACf,SAAK,UAAU;AAAA,EACnB;AAAA;AAAA,EAGA,UAAgB;AACZ,QAAI,KAAK,WAAW;AAChB;AAAA,IACJ;AACA,SAAK,YAAY;AACjB,SAAK,UAAU,QAAQ,KAAK,MAAM;AAAA,EACtC;AAAA,EAEQ,aAAmB;AACvB,QAAI,KAAK,WAAW;AAChB,YAAM,IAAI,iBAAiB,cAAc,gBAAgB,KAAK,KAAK,kBAAkB,EAAE,OAAO,KAAK,MAAA,CAAO;AAAA,IAC9G;AAAA,EACJ;AAAA,EAEQ,UAAU,MAAoB;AAClC,SAAK,WAAA;AACL,QAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,QAAQ,KAAK,OAAO;AAC3D,YAAM,IAAI;AAAA,QACN;AAAA,QACA,gBAAgB,KAAK,KAAK,WAAW,IAAI,mBAAmB,KAAK,KAAK;AAAA,QACtE;AAAA,UACI,UAAU;AAAA,UACV,OAAO;AAAA,UACP,UAAU,qBAAqB,KAAK,KAAK;AAAA,QAAA;AAAA,MAC7C;AAAA,IAER;AAAA,EACJ;AAAA,EAEQ,WAAW,OAA2B;AAC1C,QAAI,MAAM,aAAa,oBAAoB;AACvC,YAAM,IAAI;AAAA,QACN;AAAA,QACA,gBAAgB,KAAK,KAAK,YAAY,MAAM,IAAI,OAAO,MAAM,UAAU,wBAAwB,kBAAkB;AAAA,QACjH,EAAE,UAAU,SAAS,OAAO,MAAM,MAAM,UAAU,iBAAiB,kBAAkB,GAAA;AAAA,MAAG;AAAA,IAEhG;AAAA,EACJ;AACJ;AC3KO,MAAM,QAAQ;AAEd,MAAM,QAAQ;AAEd,MAAM,QAAQ;AAOd,MAAM,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAUb,YAAY,MAAqB;AAC7B,SAAK,OAAO,SAAS,QAAQ,SAAS,KAAK,OAAO,MAAM,IAAI,IAAI,KAAK,MAAM,KAAK,OAAA,IAAW,GAAO,IAAI;AACtG,SAAK,QAAQ,KAAK,OAAO;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe;AACX,SAAK,SAAS,QAAQ,KAAK,QAAQ,SAAS;AAC5C,WAAO,KAAK,QAAQ;AAAA,EACxB;AACJ;AAOA,SAAS,cAAc,QAA4D;AAC/E,QAAM,MAAgC,CAAC,GAAG,GAAG,CAAC;AAC9C,MAAI,WAAW,MAAM;AACjB,WAAO;AAAA,EACX;AACA,WAAS,OAAO,GAAG,OAAO,KAAK,OAAO,OAAO,QAAQ,QAAQ;AACzD,UAAM,IAAI,OAAO,IAAI;AACrB,QAAI,CAAC,OAAO,SAAS,CAAC,GAAG;AACrB,YAAM,IAAI,iBAAiB,sBAAsB,UAAU,IAAI,mBAAmB;AAAA,QAC9E,UAAU;AAAA,QACV,OAAO;AAAA,QACP,UAAU;AAAA,MAAA,CACb;AAAA,IACL;AACA,QAAI,IAAI,IAAI;AAAA,EAChB;AACA,SAAO;AACX;AAuBO,SAAS,cACZ,GACA,WACA,MACA,KACA,OACA,QACA,OACI;AACJ,QAAM,IAAI,EAAE;AACZ,MAAI,QAAQ,KAAK,QAAQ,GAAG;AACxB,UAAM,IAAI,iBAAiB,sBAAsB,2BAA2B,OAAO,GAAG,CAAC,IAAI;AAAA,MACvF,UAAU;AAAA,MACV,OAAO;AAAA,MACP,UAAU;AAAA,IAAA,CACb;AAAA,EACL;AACA,MAAI,UAAU,WAAW,IAAI,GAAG;AAC5B,UAAM,IAAI;AAAA,MACN;AAAA,MACA,iBAAiB,UAAU,MAAM,sBAAsB,IAAI,CAAC;AAAA,MAC5D;AAAA,QACI,UAAU;AAAA,QACV,OAAO,UAAU;AAAA,QACjB,UAAU,IAAI;AAAA,MAAA;AAAA,IAClB;AAAA,EAER;AACA,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG;AACvC,UAAM,IAAI,iBAAiB,sBAAsB,0CAA0C,KAAK,IAAI;AAAA,MAChG,UAAU;AAAA,MACV,OAAO;AAAA,MACP,UAAU;AAAA,IAAA,CACb;AAAA,EACL;AACA,QAAM,IAAI,cAAc,MAAM;AAG9B,QAAM,KAAK,CAAC,OAAO,mBAAmB,OAAO,mBAAmB,OAAO,iBAAiB;AACxF,QAAM,KAAK,CAAC,OAAO,mBAAmB,OAAO,mBAAmB,OAAO,iBAAiB;AACxF,MAAI,aAAa;AACjB,MAAI,eAAe;AACnB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,QAAI,SAAS;AACb,aAAS,OAAO,GAAG,OAAO,KAAK,QAAQ;AACnC,YAAM,IAAI,UAAU,IAAI,IAAI,IAAI;AAChC,UAAI,OAAO,SAAS,CAAC,GAAG;AACpB,YAAI,IAAI,GAAG,IAAI,GAAG;AACd,aAAG,IAAI,IAAI;AAAA,QACf;AACA,YAAI,IAAI,GAAG,IAAI,GAAG;AACd,aAAG,IAAI,IAAI;AAAA,QACf;AAAA,MACJ,OAAO;AACH,iBAAS;AAAA,MACb;AAAA,IACJ;AACA,QAAI,QAAQ;AACR;AAAA,IACJ,OAAO;AACH;AAAA,IACJ;AAAA,EACJ;AACA,MAAI,iBAAiB,GAAG;AACpB;AAAA,EACJ;AAGA,QAAM,UAAU,UAAU,OAAO,IAAI;AACrC,QAAM,UAAU;AAChB,QAAM,QAAQ,CAAC,SAAS,SAAS,OAAO;AACxC,QAAM,QAAQ,CAAC,SAAS,SAAS,OAAO;AACxC,MAAI,aAAa,GAAG;AAChB,aAAS,OAAO,GAAG,OAAO,KAAK,QAAQ;AACnC,UAAI,OAAO,SAAS,GAAG,IAAI,CAAC,KAAK,OAAO,SAAS,GAAG,IAAI,CAAC,GAAG;AACxD,cAAM,IAAI,KAAK,GAAG,IAAI,IAAI,EAAE,IAAI,KAAK;AACrC,cAAM,IAAI,KAAK,GAAG,IAAI,IAAI,EAAE,IAAI,KAAK;AAAA,MACzC;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,MAAM,IAAI,IAAI,IAAI;AACxB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,QAAI,WAAW;AACf,aAAS,OAAO,GAAG,OAAO,KAAK,QAAQ;AACnC,UAAI,CAAC,OAAO,SAAS,UAAU,IAAI,IAAI,IAAI,CAAC,GAAG;AAC3C,mBAAW;AAAA,MACf;AAAA,IACJ;AACA,QAAI,CAAC,UAAU;AACX;AAAA,IACJ;AACA,aAAS,OAAO,GAAG,OAAO,KAAK,QAAQ;AACnC,YAAM,KAAK,IAAI,IAAI;AACnB,UAAI,CAAC,OAAO,SAAS,UAAU,EAAE,CAAC,GAAG;AACjC,cAAM,IAAI,IAAI,KAAA;AACd,cAAM,IAAI,MAAM,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI;AACrD,kBAAU,EAAE,IAAI,IAAI,QAAQ,EAAE,IAAI;AAAA,MACtC;AAAA,IACJ;AACA,QAAI,QAAQ,GAAG;AACX,gBAAU,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;AAAA,IAC9B;AAAA,EACJ;AACJ;ACnEA,MAAM,sBAA8D;AAAA,EAChE,CAAC,KAAK,CAAC;AAAA,EACP,CAAC,OAAO,CAAC;AAAA,EACT,CAAC,SAAS,CAAC;AAAA,EACX,CAAC,kBAAkB,CAAC;AAAA,EACpB,CAAC,QAAQ,CAAC;AAAA,EACV,CAAC,SAAS,CAAC;AAAA,EACX,CAAC,UAAU,CAAC;AAAA,EACZ,CAAC,mBAAmB,CAAC;AACzB;AAGA,MAAM,sBAA8D;AAAA,EAChE,CAAC,YAAY,CAAC;AAAA,EACd,CAAC,OAAO,CAAC;AAAA,EACT,CAAC,OAAO,CAAC;AAAA,EACT,CAAC,aAAa,CAAC;AAAA,EACf,CAAC,UAAU,CAAC;AAAA,EACZ,CAAC,oBAAoB,CAAC;AAAA,EACtB,CAAC,aAAa,CAAC;AAAA,EACf,CAAC,gBAAgB,CAAC;AACtB;AAGA,MAAM,sBAAyC,CAAC,aAAa,kBAAkB,SAAS,YAAY,SAAS,OAAO;AAGpH,MAAM,iBAAiB;AAEvB,IAAI,oBAAoB;AAUxB,SAAS,gBAAgB,UAAkB,OAAgB,UAAmB,SAAmC;AAC7G,SAAO,IAAI,iBAAiB,sBAAsB,SAAS,EAAE,UAAU,OAAO,UAAU;AAC5F;AAOA,SAAS,cAAc,OAAiC;AACpD,SAAO,IAAI,iBAAiB,cAAc,GAAG,KAAK,gBAAgB,EAAE,OAAO;AAC/E;AAOA,SAAS,QAAQ,KAAqB;AAClC,MAAI,eAAe,OAAO;AACtB,WAAO;AAAA,EACX;AACA,SAAO,IAAI,MAAM,OAAO,QAAQ,WAAW,MAAM,eAAe;AACpE;AAQA,SAAS,YAAY,QAAgB,KAAsB;AACvD,SAAQ,OAAmC,GAAG;AAClD;AAOA,SAAS,WAAW,MAAgC;AAChD,UAAQ,MAAA;AAAA,IACJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AACD,aAAO;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AACD,aAAO;AAAA,IACX;AACI,YAAM,gBAAgB,QAAQ,MAAM,sBAAsB,4BAA4B;AAAA,EAAA;AAElG;AAQA,SAAS,gBAAgB,OAAqB,OAAwC;AAClF,aAAW,CAAC,MAAM,IAAI,KAAK,MAAM,QAAQ;AACrC,QAAI,SAAS,OAAO;AAChB,aAAO;AAAA,IACX;AAAA,EACJ;AACA,SAAO;AACX;AAQA,SAAS,YAAY,OAAqB,OAAiC;AACvE,QAAM,OAAO,gBAAgB,OAAO,KAAK;AACzC,MAAI,SAAS,MAAM;AACf,UAAM;AAAA,MACF;AAAA,MACA;AAAA,MACA,MAAM,OAAO,IAAI,CAACD,OAAMA,GAAE,CAAC,CAAC;AAAA,MAC5B,SAAS,MAAM,IAAI,iBAAiB,KAAK;AAAA,IAAA;AAAA,EAEjD;AACA,SAAO;AACX;AAQA,SAAS,cAAc,OAAqB,UAAkD,MAAoB;AAC9G,aAAW,CAAC,OAAO,KAAK,KAAK,UAAU;AACnC,UAAM,OAAO,gBAAgB,OAAO,KAAK;AACzC,QAAI,SAAS,MAAM;AACf,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAAA,QACxB,GAAG,IAAI,UAAU,MAAM,IAAI,iBAAiB,KAAK;AAAA,MAAA;AAAA,IAEzD;AACA,QAAI,WAAW,IAAI,MAAM,OAAO;AAC5B,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,oBAAoB,KAAK;AAAA,QACzB,GAAG,IAAI,IAAI,KAAK,oBAAoB,KAAK;AAAA,MAAA;AAAA,IAEjD;AAAA,EACJ;AACJ;AAOA,SAAS,UAAU,QAA4D;AAC3E,SAAO,KAAK;AAAA,IACR,OAAO,KAAK,MAAM,EACb,OACA,IAAI,CAACE,OAAM,CAACA,IAAG,OAAOA,EAAC,CAAC,CAAC;AAAA,EAAA;AAEtC;AAQA,SAAS,OAAkC,OAAU,gBAAkC;AACnF,SAAO,EAAE,GAAG,OAAO,eAAA;AACvB;AAOA,SAAS,eAAe,QAAkC;AACtD,SAAO,OAAO,sBAAsB,eAAe,kBAAkB;AACzE;AAOA,SAAS,QAAQ,SAAsC;AACnD,QAAM,QAAQ,QAAQ,SAAS,aAAa;AAC5C,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG;AACvC,UAAM,gBAAgB,SAAS,OAAO,uBAAuB,0CAA0C,KAAK,EAAE;AAAA,EAClH;AACA,SAAO;AACX;AAOA,SAAS,SAAS,SAAwD;AACtE,QAAM,MAAgC,CAAC,GAAG,GAAG,CAAC;AAC9C,QAAM,EAAE,WAAW;AACnB,MAAI,WAAW,QAAW;AACtB,WAAO;AAAA,EACX;AACA,WAAS,OAAO,GAAG,OAAO,KAAK,OAAO,OAAO,QAAQ,QAAQ;AACzD,UAAM,IAAI,OAAO,IAAI;AACrB,QAAI,CAAC,OAAO,SAAS,CAAC,GAAG;AACrB,YAAM,gBAAgB,UAAU,GAAG,qBAAqB,UAAU,IAAI,iBAAiB;AAAA,IAC3F;AACA,QAAI,IAAI,IAAI;AAAA,EAChB;AACA,SAAO;AACX;AAQA,SAAS,QAAQ,QAA8B,GAA6B;AACxE,MAAI,OAAO,cAAc,SAAS;AAC9B,WAAO;AAAA,EACX;AACA,MAAI,OAAO,cAAc,QAAQ;AAC7B,WAAO;AAAA,EACX;AACA,SAAO,KAAK,OAAO,gBAAgB,UAAU;AACjD;AAQA,SAAS,aAAa,QAAmB,MAAuB;AAC5D,SAAO,EAAE,QAAQ,QAAQ,GAAG,MAAM,QAAQ,KAAA;AAC9C;AAMA,MAAM,aAAoC;AAAA;AAAA;AAAA;AAAA;AAAA,EAStC,YAAY,OAAqB;AAPjC,SAAiB,6BAAa,IAAA;AAC9B,SAAiB,6BAAa,IAAA;AAO1B,SAAK,QAAQ;AACb,SAAK,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,OAAe,OAAyC;AACxD,UAAM,QAAQ,WAAW,YAAY,KAAK,OAAO,KAAK,CAAC;AACvD,UAAM,KAAK,UAAU,IAAI,OAAO,UAAU,WAAW,OAAO,UAAU,YAAY,MAAM,WAAW;AACnG,QAAI,CAAC,IAAI;AACL,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,oBAAoB,KAAK;AAAA,QACzB,eAAe,KAAK,2BAA2B,KAAK;AAAA,MAAA;AAAA,IAE5D;AACA,SAAK,OAAO,IAAI,OAAO,KAAK;AAC5B,SAAK,OAAO,IAAI,OAAO,KAAK;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,OAA2C;AAC3C,UAAM,QAAQ,KAAK,OAAO,IAAI,KAAK;AACnC,QAAI,UAAU,QAAW;AACrB,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,KAAK,MAAM,OAAO,IAAI,CAACF,OAAMA,GAAE,CAAC,CAAC;AAAA,QACjC,4BAA4B,KAAK;AAAA,MAAA;AAAA,IAEzC;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,QAAc;AACV,SAAK,OAAO,MAAA;AACZ,SAAK,OAAO,MAAA;AACZ,UAAM,OAAO,KAAK,MAAM,KAAK,IAAI,SAAS,IAAI,YAAY,KAAK,MAAM,UAAU,CAAC,CAAC;AACjF,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC9C,WAAK,OAAO,IAAI,MAAM,KAAK;AAAA,IAC/B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAA2B;AACvB,UAAM,QAAQ,IAAI,YAAY,KAAK,MAAM,UAAU;AACnD,SAAK,MAAM,MAAM,IAAI,SAAS,KAAK,GAAG,OAAO,YAAY,KAAK,MAAM,CAAC;AACrE,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,MAAsB;AACzB,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG;AAC/D,UAAI,CAAC,KAAK,OAAO,IAAI,IAAI,GAAG;AACxB,aAAK,OAAO,IAAI,MAAM,KAAK;AAAA,MAC/B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAuB;AACnB,UAAM,SAAS,CAAC,GAAG,KAAK,OAAO,MAAM;AACrC,SAAK,OAAO,MAAA;AACZ,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,cAAoB;AAChB,SAAK,OAAO,MAAA;AAAA,EAChB;AACJ;AAwBA,SAAS,cAAcE,IAAW,YAAkC;AAChE,MAAI,YAAwB,MAAM;AAClC,MAAI,WAAmC,MAAM;AAC7C,QAAM,UAAU,IAAI,QAAc,CAAC,SAAS,WAAW;AACnD,gBAAY;AACZ,eAAW;AAAA,EACf,CAAC;AACD,SAAO;AAAA,IACH,GAAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,MAAM;AACX,gBAAA;AAAA,IACJ;AAAA,IACA,QAAQ,CAAC,UAAiB;AACtB,eAAS,KAAK;AAAA,IAClB;AAAA,IACA,IAAI;AAAA,IACJ,WAAW;AAAA,IACX,OAAO;AAAA,IACP,WAAW;AAAA,IACX,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,EAAA;AAEjB;AA6BO,MAAM,gBAGoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwE7C,YACI,KACA,OACA,SACA,QACA,SACF;AAhDF,SAAiB,mCAAmB,IAAA;AACpC,SAAiB,UAA0B,CAAA;AAG3C,SAAQ,aAAgD;AACxD,SAAQ,kBAAkB;AAG1B,SAAQ,WAAiC;AACzC,SAAQ,SAAwB;AAChC,SAAQ,QAAoB;AAC5B,SAAQ,IAAI;AACZ,SAAQ,QAAQ;AAChB,SAAQ,SAAmC,CAAC,GAAG,GAAG,CAAC;AACnD,SAAQ,UAAoC;AAC5C,SAAQ,OAA2B;AACnC,SAAQ,YAAmC;AAC3C,SAAQ,gBAAsC;AAC9C,SAAQ,QAAuB,QAAQ,QAAA;AACvC,SAAQ,cAA6B,QAAQ,QAAA;AAC7C,SAAQ,aAAkB,IAAI,YAAY,CAAC;AAC3C,SAAQ,aAAa;AACrB,SAAQ,sBAAsB;AAC9B,SAAQ,sBAAsB;AAC9B,SAAQ,oBAAoB;AAC5B,SAAQ,eAAe;AACvB,SAAQ,eAAe;AACvB,SAAQ,aAA2B;AACnC,SAAQ,4BAA4B;AAEpC,SAAQ,uBAAuB;AAC/B,SAAQ,iBAAiB;AACzB,SAAQ,WAAW;AAiBf,QAAI,YAAA;AACJ,kBAAc,MAAM,QAAQ,qBAAqB,cAAc;AAC/D,kBAAc,MAAM,OAAO,qBAAqB,aAAa;AAC7D,QAAI,MAAM,OAAO,aAAa,oBAAoB;AAC9C,YAAM;AAAA,QACF;AAAA,QACA,MAAM,OAAO;AAAA,QACb,MAAM,kBAAkB;AAAA,QACxB;AAAA,MAAA;AAAA,IAER;AACA,QAAI,MAAM,MAAM,aAAa,oBAAoB;AAC7C,YAAM;AAAA,QACF;AAAA,QACA,MAAM,MAAM;AAAA,QACZ,MAAM,kBAAkB;AAAA,QACxB;AAAA,MAAA;AAAA,IAER;AACA,QAAI,MAAM,OAAO,WAAW,GAAG;AAC3B,YAAM;AAAA,QACF;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,IAER;AACA,UAAM,cAAc,QAAQ,eAAe,aAAa;AACxD,QAAI,CAAC,OAAO,UAAU,WAAW,KAAK,cAAc,GAAG;AACnD,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA,4CAA4C,WAAW;AAAA,MAAA;AAAA,IAE/D;AACA,UAAM,MAAM,QAAQ,OAAO,aAAa;AACxC,QAAI,QAAQ,KAAK,QAAQ,GAAG;AACxB,YAAM,gBAAgB,OAAO,KAAK,UAAU,2BAA2B,OAAO,GAAG,CAAC,EAAE;AAAA,IACxF;AAEA,YAAQ,OAAO;AACf,aAAS,OAAO;AAChB;AACA,SAAK,MAAM;AACX,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,SAAK,iBAAiB;AACtB,SAAK,eAAe;AACpB,SAAK,cAAc;AACnB,SAAK,WAAW;AAChB,SAAK,YAAY,OAAO,cAAc,SAAS,SAAS;AACxD,SAAK,QAAQ,GAAG,MAAM,IAAI,IAAI,iBAAiB;AAC/C,SAAK,aAAa,MAAM,MAAM;AAC9B,SAAK,SAAS,IAAI,aAAa,MAAM,KAAK;AAC1C,SAAK,OAAO,IAAI;AAAA,MACZ,IAAI;AAAA,MACJ,IAAI;AAAA,OACH,cAAc,KAAK;AAAA,MACpB,GAAG,KAAK,KAAK;AAAA,IAAA;AAEjB,SAAK,iBAAiB,IAAI,OAAO,CAAC,SAAS;AACvC,WAAK,aAAa,IAAI;AAAA,IAC1B,CAAC;AACD,QAAI,IAAI,MAAM,SAAS;AACnB,WAAK,UAAU,CAAC,SAAsD,KAAK,cAAc,IAAI;AAC7F,WAAK,iBAAiB,CAAC,SAAgC,KAAK,UAAU,IAAI;AAAA,IAC9E;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,QAA2C;AAC3C,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,UAAmB;AACnB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,OAAyB;AACzB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,aAAqB;AACrB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAAoB;AACpB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,MAAa;AACb,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,UAAmB;AACnB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,WAAmB;AACnB,WAAO,KAAK,QAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,iBAAyB;AACzB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,QAAe;AACf,QAAI,KAAK,eAAe,MAAM;AAC1B,aAAO,KAAK;AAAA,IAChB;AACA,UAAM,SAAS,IAAI,SAAS,KAAK,OAAO,aAAa;AACrD,UAAM,QAAQ,IAAI,SAAS,IAAI,YAAY,CAAC,CAAC;AAC7C,WAAO,OAAO,KAAK,MAAM,UAAU,QAAQ,KAAK,GAAG,IAAI;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,YAAyC;AACzC,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,uBAA+B;AAC/B,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,YAAoB;AACpB,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,KAAK,UAAyB,WAAsB;AAChD,SAAK,kBAAA;AACL,SAAK,IAAI,YAAA;AACT,QAAI,SAAS,UAAU;AACnB,YAAM,IAAI;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,UACI,QAAQ;AAAA,UACR,QAAQ,SAAS;AAAA,QAAA;AAAA,MACrB;AAAA,IAER;AACA,UAAM,IAAI,SAAS;AACnB,QAAI,IAAI,cAAc;AAClB,YAAM,IAAI;AAAA,QACN;AAAA,QACA,GAAG,CAAC,iBAAiB,YAAY;AAAA,QACjC;AAAA,UACI,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,MAAM;AAAA,UACN,WAAW,KAAK,MAAM;AAAA,QAAA;AAAA,MAC1B;AAAA,IAER;AACA,QAAI,UAAU,WAAW,IAAI,GAAG;AAC5B,YAAM;AAAA,QACF;AAAA,QACA,UAAU;AAAA,QACV,IAAI;AAAA,QACJ,iBAAiB,UAAU,MAAM,sBAAsB,IAAI,CAAC;AAAA,MAAA;AAAA,IAEpE;AACA,QAAI,eAAe,UAAU,MAAM,GAAG;AAClC,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAER;AACA,UAAM,QAAQ,QAAQ,KAAK,YAAY;AACvC,UAAM,SAAS,SAAS,KAAK,YAAY;AACzC,UAAM,OAAO,QAAQ,KAAK,QAAQ,CAAC;AACnC,QAAI,SAAS,QAAQ;AACjB,YAAM,IAAI;AAAA,QACN;AAAA,QACA,4CAA4C,CAAC,qBAAqB,KAAK,OAAO,aAAa;AAAA,QAC3F;AAAA,UACI,SAAS;AAAA,UACT,MAAM;AAAA,QAAA;AAAA,MACV;AAAA,IAER;AACA,UAAM,iBAAiB,KAAK;AAC5B,QAAI,iBAAiB,KAAK,IAAI,KAAK,OAAO,eAAe;AACrD,YAAM,IAAI,iBAAiB,eAAe,GAAG,cAAc,4CAA4C;AAAA,QACnG,QAAQ;AAAA,QACR,OAAO,KAAK,IAAI,KAAK,OAAO;AAAA,QAC5B,MAAM;AAAA,QACN,WAAW,KAAK,MAAM;AAAA,MAAA,CACzB;AAAA,IACL;AACA,QAAI,OAA2B;AAC/B,QAAI,SAA6B;AACjC,QAAI,IAAI,GAAG;AACP,aAAO,KAAK,IAAI,UAAU,KAAK,QAAQ;AACvC,UAAI,KAAK,SAAS,YAAY;AAC1B,cAAM,IAAI;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,YACI,QAAQ,SAAS;AAAA,YACjB,OAAO,KAAK,IAAI,KAAK,OAAO;AAAA,YAC5B,MAAM;AAAA,YACN,WAAW,KAAK,MAAM;AAAA,UAAA;AAAA,QAC1B;AAAA,MAER;AACA,eAAS,KAAK,MAAM,OAAO,UAAU,KAAK,YAAY;AACtD,UAAI,OAAO,KAAK,WAAW,GAAG;AAC1B,cAAM;AAAA,UACF;AAAA,UACA,OAAO,KAAK;AAAA,UACZ;AAAA,UACA,sBAAsB,OAAO,KAAK,MAAM,eAAe,CAAC;AAAA,QAAA;AAAA,MAEhE;AAAA,IACJ;AAGA,SAAK;AACL,SAAK,eAAA;AACL,UAAM,UAAU,KAAK,YAAY,QAAQ,MAAM,KAAK,KAAK,SAAS,WAAW,KAAK;AAClF,SAAK,WAAW;AAChB,SAAK,SAAS,SAAS;AACvB,SAAK,QAAQ;AACb,SAAK,IAAI;AACT,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,sBAAsB;AAC3B,SAAK,sBAAsB;AAC3B,SAAK,oBAAoB;AACzB,SAAK,eAAe;AACpB,SAAK,aAAa;AAClB,SAAK,OAAO,MAAA;AACZ,QAAI,SAAS;AACT,WAAK,eAAA;AACL,WAAK,aAAa,MAAA;AAClB,WAAK,aAAa,SAAS,CAAC;AAC5B,WAAK,aAAa;AAAA,IACtB;AACA,QAAI,MAAM,KAAK,SAAS,QAAQ,WAAW,MAAM;AAE7C,WAAK,gBAAgB;AACrB,WAAK,YAAY;AAGjB,WAAK,QAAQ,KAAK,MAAM,MAAM,MAAM,MAAS;AAC7C,WAAK,eAAe;AACpB,WAAK,aAAa;AAClB;AAAA,IACJ;AACA,UAAM,UAAU,UAAU,KAAK,SAAS,CAAC,IAAI,KAAK,eAAA;AAClD,QAAI,CAAC,SAAS;AACV,WAAK,UAAU,OAAO;AAAA,IAC1B;AACA,SAAK,UAAU;AACf,UAAM,QAAQ,KAAK,MAAM,SAAS,wBAAwB,OAAO;AACjE,kBAAc,UAAU,WAAW,KAAK,aAAa,QAAQ,MAAM,KAAK,UAAU,OAAO,QAAQ,KAAK;AACtG,SAAK,gBAAgB,SAAS,WAAW,OAAO,IAAI;AACpD,UAAM,UAAU,KAAK,sBAAsB,UAAU,MAAM,OAAO,OAAO;AACzE,UAAM,YAAY,EAAE,GAAG,KAAK,MAAM,UAAU,KAAK,YAAY,GAAG,GAAG,eAAe,MAAM,MAAM,OAAO,EAAA;AACrG,UAAM,YAAY,KAAK,cAAc,MAAM,SAAS,OAAO;AAC3D,SAAK,YAAY;AACjB,SAAK,UAAU,WAAW,SAAS;AACnC,SAAK,eAAe;AACpB,SAAK,aAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,KAAK,YAAoC;AACrC,QAAI,KAAK,eAAe,WAAW;AAC/B,aAAO,QAAQ;AAAA,QACX,IAAI,iBAAiB,gBAAgB,GAAG,KAAK,KAAK,kBAAkB,EAAE,OAAO,UAAA,CAAW;AAAA,MAAA;AAAA,IAEhG;AACA,QAAI,KAAK,eAAe,YAAY;AAChC,aAAO,QAAQ,OAAO,cAAc,KAAK,KAAK,CAAC;AAAA,IACnD;AACA,QAAI;AACA,WAAK,IAAI,YAAA;AAAA,IACb,SAAS,KAAK;AACV,aAAO,QAAQ,OAAO,QAAQ,GAAG,CAAC;AAAA,IACtC;AACA,UAAM,EAAE,aAAa;AACrB,QAAI,aAAa,QAAQ,KAAK,IAAI,UAAU,WAAW,SAAS,MAAM,GAAG;AACrE,aAAO,QAAQ;AAAA,QACX,IAAI;AAAA,UACA;AAAA,UACA,YAAY,SAAS,MAAM,uBAAuB,KAAK,KAAK;AAAA,UAC5D;AAAA,YACI,QAAQ,SAAS;AAAA,UAAA;AAAA,QACrB;AAAA,MACJ;AAAA,IAER;AACA,UAAMA,KAAI,cAAc,KAAK,aAAa,qBAAqB,aAAa;AAC5E,QAAI,CAAC,OAAO,UAAUA,EAAC,KAAKA,KAAI,KAAKA,KAAI,yBAAyB;AAC9D,aAAO,QAAQ;AAAA,QACX;AAAA,UACI;AAAA,UACAA;AAAA,UACA,qBAAqB,uBAAuB;AAAA,UAC5C,QAAQA,EAAC,2CAA2C,uBAAuB;AAAA,QAAA;AAAA,MAC/E;AAAA,IAER;AACA,QAAI,KAAK,gBAAgB,KAAK,MAAM,GAAG;AACnC,aAAO,QAAQ,QAAA;AAAA,IACnB;AACA,QAAI,KAAK,QAAQ,UAAU,KAAK,aAAa;AACzC,WAAK;AACL,aAAO,KAAK,QAAQ,CAAC,EAAE;AAAA,IAC3B;AACA,UAAM,SAAS,cAAcA,IAAG,KAAK,eAAe;AACpD,SAAK,QAAQ,KAAK,MAAM;AACxB,SAAK,cAAc,KAAK,YAAY,KAAK,MAAM,KAAK,YAAY,MAAM,CAAC;AACvE,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAuB;AACzB,WAAO,KAAK,QAAQ,SAAS,GAAG;AAC5B,YAAM,QAAQ,WAAW,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,IAC/D;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,SAAsC;AAC5C,SAAK,kBAAA;AACL,UAAM,QAAQ,SAAS,SAAS;AAChC,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,yBAAyB;AAC1E,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,qBAAqB,uBAAuB;AAAA,QAC5C;AAAA,MAAA;AAAA,IAER;AACA,UAAM,SAAS,SAAS,WAAW,KAAK,gBAAA;AACxC,QAAI,OAAO,MAAM,MAAM,KAAK,SAAS,GAAG;AACpC,YAAM,gBAAgB,WAAW,QAAQ,iBAAiB,6BAA6B;AAAA,IAC3F;AACA,UAAM,SAAS,SAAS;AACxB,UAAM,UAAU,MAAY;AACxB,WAAK,eAAA;AAAA,IACT;AACA,QAAI,WAAW,QAAW;AACtB,UAAI,OAAO,SAAS;AAChB,cAAM,KAAK,aAAA;AAAA,MACf;AACA,aAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM;AAAA,IAC5D;AACA,QAAI;AACA,aAAO,CAAC,KAAK,WAAW,KAAK,sBAAsB,QAAQ;AACvD,YAAI,QAAQ,YAAY,MAAM;AAC1B,gBAAM,KAAK,aAAA;AAAA,QACf;AACA,cAAMA,KAAI,KAAK,IAAI,OAAO,SAAS,KAAK,mBAAmB;AAC3D,cAAM,KAAK,KAAKA,EAAC;AAAA,MACrB;AACA,UAAI,QAAQ,YAAY,MAAM;AAC1B,cAAM,KAAK,aAAA;AAAA,MACf;AACA,aAAO,KAAK;AAAA,IAChB,UAAA;AACI,cAAQ,oBAAoB,SAAS,OAAO;AAAA,IAChD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAAS,MAAsB;AAC3B,SAAK,aAAA;AACL,UAAM,EAAE,MAAM;AACd,UAAM,QAAQ,KAAK,KAAK,IAAI,EAAE;AAC9B,QAAI,KAAK,SAAS,OAAO;AACrB,YAAM;AAAA,QACF;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,0BAA0B,KAAK,MAAM,WAAW,KAAK,eAAe,CAAC;AAAA,MAAA;AAAA,IAE7E;AACA,QAAI,WAAW;AACf,aAAS,IAAI,GAAG,IAAI,SAAS,CAAC,UAAU,KAAK;AACzC,UAAI,KAAK,WAAW,CAAC,MAAM,KAAK,CAAC,GAAG;AAChC;AAAA,MACJ;AACA,YAAM,OAAO,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE;AACpC,eAAS,IAAI,IAAI,IAAI,IAAI,MAAM,KAAK;AAChC,YAAI,SAAS,KAAK,YAAY,CAAC,KAAK,CAAC,SAAS,MAAM,CAAC,GAAG;AACpD,qBAAW;AACX;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AACA,SAAK,WAAW,IAAI,KAAK,SAAS,GAAG,KAAK,CAAC;AAC3C,SAAK,aAAa;AAClB,QAAI,UAAU;AACV,WAAK,OAAA;AAAA,IACT;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,YAAY,OAAe,GAAW,GAAW,GAAiB;AAC9D,SAAK,aAAA;AACL,UAAM,EAAE,MAAM;AACd,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,SAAS,GAAG;AACrD,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,qBAAqB,CAAC;AAAA,QACtB,eAAe,KAAK;AAAA,MAAA;AAAA,IAE5B;AACA,QAAI,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,GAAG;AACnE,YAAM;AAAA,QACF;AAAA,QACA,CAAC,GAAG,GAAG,CAAC;AAAA,QACR;AAAA,QACA;AAAA,MAAA;AAAA,IAER;AACA,UAAM,EAAE,OAAO,QAAA,IAAY;AAC3B,QAAI,UAAU,QAAQ,YAAY,MAAM;AACpC,YAAM,IAAI,iBAAiB,gBAAgB,GAAG,KAAK,KAAK,kBAAkB,EAAE,OAAO,KAAK,WAAA,CAAY;AAAA,IACxG;AACA,UAAM,IAAI,KAAK,IAAI;AACnB,UAAM,IAAI,QAAQ,CAAC,IAAI;AACvB,UAAM,IAAI,QAAQ,CAAC,IAAI;AACvB,UAAM,CAAC,IAAI,IAAI,EAAE,IAAI,KAAK;AAC1B,UAAM,SAAS,IAAI,aAAa;AAAA,OAC3B,IAAI,MAAM,KAAK;AAAA,OACf,IAAI,MAAM,KAAK;AAAA,MAChB,KAAK,aAAa,IAAI,KAAK,IAAI,MAAM,KAAK;AAAA,IAAA,CAC7C;AACD,SAAK,IAAI,OAAO,MAAM,YAAY,QAAQ,WAAW,KAAK,OAAO,MAAM;AACvE,SAAK,aAAa,IAAI,OAAO,KAAK,yBAAyB;AAC3D,SAAK,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAe;AACX,SAAK,kBAAA;AACL,SAAK,sBAAsB;AAC3B,SAAK,oBAAoB;AACzB,SAAK,uBAAuB,KAAK;AACjC,SAAK,OAAO,IAAI,gBAAgB,CAAC;AACjC,SAAK,MAAM,SAAS,KAAK,MAAM;AAC/B,SAAK,eAAe,KAAK,eAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UAAU,OAA+B;AACrC,SAAK,kBAAA;AACL,UAAM,UAAU,KAAK;AACrB,UAAM,EAAE,KAAK,YAAA,IAAgB;AAC7B,QAAI,QAAQ,UAAa,QAAQ,KAAK,UAAU;AAC5C,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MAAA;AAAA,IAER;AACA,QAAI,gBAAgB,UAAa,gBAAgB,KAAK,aAAa;AAC/D,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MAAA;AAAA,IAER;AACA,UAAM,WAAW,YAAY,OAAO,UAAU;AAC9C,QAAI,aAAa,UAAa,aAAa,MAAM;AAC7C,YAAM,IAAI,iBAAiB,iBAAiB,kDAAkD;AAAA,QAC1F,QAAQ;AAAA,QACR,MAAM;AAAA,MAAA,CACT;AAAA,IACL;AACA,UAAM,OAAO,KAAK,eAAe,OAAO,OAAO;AAC/C,UAAM,QAAQ,QAAQ,IAAI;AAC1B,UAAM,SAAS,SAAS,IAAI;AAC5B,UAAM,SAAS,UAAU,KAAK,MAAM,UAAU,OAAO,CAAC;AACtD,UAAM,QAAQ,UAAU,KAAK,MAAM,UAAU,IAAI,CAAC;AAClD,SAAK,eAAe;AACpB,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,UAAM,EAAE,WAAW,KAAA,IAAS;AAC5B,QAAI,KAAK,eAAe,YAAY,cAAc,QAAQ,SAAS,QAAQ,WAAW,OAAO;AACzF,YAAM,YAAY,EAAE,GAAG,KAAK,MAAM,UAAU,IAAI,GAAG,GAAG,eAAe,MAAM,MAAM,UAAU,OAAO,EAAA;AAClG,WAAK,UAAU,WAAW,SAAS;AAAA,IACvC;AACA,SAAK,MAAM,YAAY,OAAO,KAAK,MAAM;AACzC,SAAK,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAgB;AACZ,QAAI,KAAK,eAAe,YAAY;AAChC;AAAA,IACJ;AACA,SAAK,aAAa;AAClB,SAAK,SAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,YAAY,QAAqC;AAC3D,QAAI;AACA,YAAM,KAAK;AACX,YAAM,KAAK,IAAI,UAAU,MAAA;AAAA,IAC7B,SAAS,KAAK;AACV,WAAK,OAAO,MAAM;AAClB,UAAI,KAAK,QAAQ,MAAM,GAAG;AACtB,eAAO,QAAA;AACP;AAAA,MACJ;AACA,UAAI,aAAa,KAAK,iBAAiB,GAAG;AACtC,aAAK,YAAA;AAAA,MACT;AACA,aAAO,OAAO,QAAQ,GAAG,CAAC;AAC1B;AAAA,IACJ;AACA,QAAI,KAAK,QAAQ,MAAM,GAAG;AACtB,WAAK,OAAO,MAAM;AAClB,aAAO,QAAA;AACP;AAAA,IACJ;AACA,QAAI;AACJ,QAAI;AACA,kBAAY,KAAK,gBAAgB,MAAM;AAAA,IAC3C,SAAS,KAAK;AACV,WAAK,OAAO,MAAM;AAClB,aAAO,OAAO,QAAQ,GAAG,CAAC;AAC1B;AAAA,IACJ;AACA,cAAU,SAAS;AAAA,MACf,CAAC,UAAU;AACP,aAAK,SAAS,QAAQ,KAAK;AAAA,MAC/B;AAAA,MACA,CAAC,QAAiB;AACd,aAAK,SAAS,QAAQ,GAAG;AAAA,MAC7B;AAAA,IAAA;AAAA,EAER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,gBAAgB,QAAsC;AAC1D,UAAM,UAAU,KAAK,eAAA;AACrB,UAAM,EAAE,GAAAA,OAAM;AACd,UAAM,EAAE,WAAW,KAAK;AACxB,QAAI,KAAK,YAAY;AACjB,aAAO,MAAM,YAAY,QAAQ,OAAO,GAAG,KAAK,UAAU;AAC1D,WAAK,aAAa;AAAA,IACtB;AACA,SAAK,iBAAiB,QAAQ,KAAK;AACnC,UAAM,QAAQ,KAAK,KAAK,QAAQA,EAAC;AACjC,aAAS,IAAI,GAAG,IAAIA,IAAG,KAAK;AACxB,YAAM,QAAQ,MAAM,KAAK,KAAK,eAAe,iBAAiB;AAC9D,WAAK,KAAK,MAAM,QAAQ,GAAG,KAAK,MAAM,QAAQ,KAAK,cAAc,KAAK,sBAAsB,GAAG,GAAG,KAAK,CAAC;AAAA,IAC5G;AACA,SAAK,KAAK,MAAA;AACV,UAAM,QAAQ,IAAI,aAAa,KAAK,KAAK,GAAG,KAAK,KAAK,UAAU,KAAK,eAAe;AACpF,UAAM,iBAAiB,KAAK,mBAAA;AAC5B,aAAS,IAAI,GAAG,IAAIA,IAAG,KAAK;AAExB,WAAK,MAAM,gBAAgB,OAAO,QAAQ,GAAG,KAAK,WAAW,MAAMA,KAAI,IAAI,SAAY,cAAc;AAAA,IACzG;AACA,UAAM,QAAA;AACN,UAAM,QAAQ,MAAM,SAAS,QAAQ,OAAO,GAAG,KAAK,KAAK,CAAC;AAC1D,UAAM,QAAQ,MAAM,SAAS,QAAQ,OAAO,GAAG,qBAAqBA,KAAI,KAAK,UAAU;AACvF,UAAM,EAAE,aAAa,KAAK;AAC1B,UAAM,UAAU,aAAa,OAAO,OAAO,SAAS,YAAY,KAAK;AACrE,UAAM,YAAY,MAAM,OAAA;AACxB,WAAO,YAAY;AACnB,WAAO,KAAK,UAAU;AACtB,WAAO,cAAc,MAAM;AAC3B,WAAO,cAAc,MAAM;AAC3B,WAAO,UAAU;AACjB,WAAO,YAAY,YAAY,IAAA;AAC/B,SAAK,4BAA4B,UAAU;AAC3C,SAAK,uBAAuBA;AAC5B,SAAK,eAAe;AACpB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,SAAS,QAAsB,OAA0B;AAC7D,SAAK,OAAO,MAAM;AAClB,UAAM,EAAE,UAAU;AAClB,QAAI,KAAK,QAAQ,MAAM,KAAK,UAAU,MAAM;AACxC,aAAO,QAAA;AACP;AAAA,IACJ;AACA,QAAI;AACA,YAAM,EAAE,GAAAA,OAAM;AACd,YAAM,EAAE,MAAM;AACd,YAAM,SAAS,KAAK;AAAA,QAChB,OAAO,cAAc,KAAK;AAAA,QAC1B,OAAO,cAAc,qBAAqBA,KAAI,KAAK;AAAA,MAAA;AAEvD,UAAI,MAAM,aAAa,QAAQ;AAE3B,eAAO,QAAA;AACP;AAAA,MACJ;AACA,WAAK,UAAU,OAAO,OAAO,MAAM;AACnC,YAAM,SAAS,IAAI,SAAS,OAAO,OAAO,aAAa,kBAAkB;AACzE,YAAM,QAAQ,IAAI,SAAS,OAAO,OAAO,cAAc,oBAAoBA,KAAI,KAAK,UAAU;AAC9F,WAAK,OAAO,OAAO,MAAM;AACzB,YAAM,eAAe,KAAK,MAAM,MAAM,UAAU,QAAQ,cAAc;AACtE,UAAI,OAAO,iBAAiB,UAAU;AAClC,cAAM,gBAAgB,gBAAgB,cAAc,YAAY,qCAAqC;AAAA,MACzG;AACA,YAAM,KAAK,KAAK,kBAAkB,QAAQ,KAAK;AAC/C,WAAK,aAAa,OAAO,KAAK,MAAM,UAAU,QAAQ,KAAK,GAAG,KAAKA,EAAC;AACpE,WAAK,uBAAuBA;AAE5B,WAAK,oBAAoB,OAAO,MAAM,KAAK,uBAAuB,IAAI;AACtE,WAAK,eAAe,KAAK,eAAA;AACzB,aAAO,QAAA;AAAA,IACX,SAAS,KAAK;AACV,aAAO,OAAO,QAAQ,GAAG,CAAC;AAAA,IAC9B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,SAAS,QAAsB,KAAoB;AACvD,SAAK,OAAO,MAAM;AAClB,QAAI,aAAa,KAAK,WAAW,KAAK,KAAK,QAAQ,MAAM,GAAG;AACxD,aAAO,QAAA;AACP;AAAA,IACJ;AACA,QAAI,KAAK,IAAI,UAAU,UAAU,CAAC,aAAa,KAAK,eAAe,GAAG;AAClE,aAAO;AAAA,QACH,IAAI,iBAAiB,iBAAiB,qDAAqD;AAAA,UACvF,QAAQ;AAAA,UACR,SAAS,QAAQ,GAAG,EAAE;AAAA,QAAA,CACzB;AAAA,MAAA;AAEL;AAAA,IACJ;AACA,WAAO,OAAO,QAAQ,GAAG,CAAC;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,UAAU,OAAY,OAAoB,QAA4B;AAC1E,UAAM,EAAE,MAAM;AACd,UAAM,QAAQ,IAAI,aAAa,OAAO,OAAO,aAAa,IAAI,CAAC;AAC/D,QAAI,KAAK,aAAa,SAAS,GAAG;AAC9B,YAAM,IAAI,KAAK;AACf;AAAA,IACJ;AACA,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,YAAM,QAAQ,KAAK,aAAa,IAAI,CAAC;AACrC,UAAI,UAAU,UAAa,SAAS,OAAO,IAAI;AAC3C;AAAA,MACJ;AACA,YAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC;AAC1B,YAAM,IAAI,IAAI,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC;AAClC,YAAM,IAAI,IAAI,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,IACtC;AACA,eAAW,CAAC,GAAG,KAAK,KAAK,KAAK,cAAc;AACxC,UAAI,QAAQ,OAAO,IAAI;AACnB,aAAK,aAAa,OAAO,CAAC;AAAA,MAC9B;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,kBAAkB,QAAsB,OAA4B;AACxE,UAAM,EAAE,aAAa,KAAK;AAC1B,QAAI,aAAa,QAAQ,OAAO,YAAY,MAAM;AAC9C,YAAM,UAAU,SAAS,QAAQ,OAAO,OAAO,OAAO;AACtD,UAAI,QAAQ,SAAS,GAAG;AACpB,YAAI,KAAK;AACT,mBAAW,UAAU,SAAS;AAC1B,gBAAM,OAAO;AAAA,QACjB;AACA,eAAO,KAAK;AAAA,MAChB;AAAA,IACJ;AACA,WAAO,YAAY,QAAQ,OAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,QAAQ,QAA+B;AAC3C,WAAO,OAAO,SAAS,KAAK,eAAe,YAAY,OAAO,eAAe,KAAK;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,OAAO,QAA4B;AACvC,UAAM,KAAK,KAAK,QAAQ,QAAQ,MAAM;AACtC,QAAI,MAAM,GAAG;AACT,WAAK,QAAQ,OAAO,IAAI,CAAC;AAAA,IAC7B;AAAA,EACJ;AAAA;AAAA,EAGQ,iBAAuB;AAC3B,eAAW,UAAU,KAAK,SAAS;AAC/B,aAAO,QAAQ;AACf,aAAO,WAAW,QAAA;AAAA,IACtB;AAAA,EACJ;AAAA;AAAA,EAGQ,cAAoB;AACxB,SAAK,eAAA;AACL,SAAK,eAAA;AACL,SAAK,IAAI,UAAU,MAAA;AACnB,SAAK,eAAe;AACpB,SAAK,aAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAiC;AACrC,WAAO,IAAI,iBAAiB,aAAa,GAAG,KAAK,KAAK,iCAAiC;AAAA,MACnF,SAAS,KAAK;AAAA,IAAA,CACjB;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,cAAc,QAAgB,OAAe,OAA8B;AAC/E,UAAM,CAAC,IAAI,IAAI,EAAE,IAAI,KAAK;AAC1B,UAAM,SAAwB;AAAA,MAC1B,GAAG,KAAK;AAAA,MACR,KAAK,KAAK;AAAA,MACV;AAAA,MACA,gBAAgB;AAAA,MAChB,MAAM,KAAK,QAAA;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC;AAAA,MACtB,iBAAiB,KAAK,gBAAA;AAAA,IAAgB;AAE1C,WAAO,EAAE,GAAG,KAAK,MAAM,UAAU,QAAQ,KAAK,YAAY,GAAG,GAAG,OAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAkB;AACtB,UAAM,EAAE,SAAS,KAAK;AACtB,QAAI,SAAS,QAAQ,SAAS,UAAa,CAAC,OAAO,SAAS,IAAI,GAAG;AAC/D,aAAO;AAAA,IACX;AACA,WAAO,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,OAAwB;AAC7C,UAAM,SAAS,KAAK,OAAO,WAAA;AAC3B,QAAI,OAAO,WAAW,GAAG;AACrB;AAAA,IACJ;AACA,UAAM,QAAQ,KAAK,OAAO,YAAA;AAC1B,UAAM,QAAQ,KAAK,MAAM;AACzB,eAAW,SAAS,QAAQ;AACxB,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,YAAM,OAAO,IAAI,WAAW,YAAY,OAAO,KAAK,CAAC;AACrD,WAAK,IAAI,OAAO,MAAM,YAAY,OAAO,QAAQ,OAAO,QAAQ,IAAI;AAAA,IACxE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAAyC;AAC7C,UAAM,KAAK,KAAK,MAAM,OAAO,QAAQ,cAAc;AACnD,QAAI,MAAM,GAAG;AACT,aAAO;AAAA,IACX;AACA,WAAO,KAAK,MAAM,OAAO,KAAK,CAAC;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,kBAA0B;AAC9B,WAAO,KAAK,aAAa,mBAAmB,aAAa;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAuB;AAC3B,WAAO,KAAK,aAAa,gBAAgB,aAAa;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,kBAA0B;AAC9B,UAAM,UAAU,YAAY,KAAK,cAAc,SAAS;AACxD,QAAI,OAAO,YAAY,UAAU;AAC7B,aAAO;AAAA,IACX;AACA,UAAM,aAAa,YAAY,KAAK,cAAc,YAAY;AAC9D,QAAI,OAAO,eAAe,UAAU;AAChC,aAAO;AAAA,IACX;AACA,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAA0B;AAC9B,QAAI,KAAK,eAAe,UAAU;AAC9B,aAAO;AAAA,IACX;AACA,WACI,KAAK,MAAM,KACX,KAAK,uBAAuB,KAAK,gBAAA,KACjC,KAAK,qBAAqB,KAAK,aAAA;AAAA,EAEvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,SAAS,GAA8B;AAC3C,UAAM,EAAE,cAAc,KAAK;AAC3B,UAAM,EAAE,UAAU;AAClB,UAAM,SAAS,KAAK,KAAK,IAAI,KAAK,IAAI,aAAa;AACnD,UAAM,mBAAmB,0BAA0B,KAAK;AACxD,UAAM,YAAY,YAAY,UAAU,YAAY,WAAW,YAAY;AAC3E,UAAM,YAAY,UAAU,aAAa,EAAE,OAAO,GAAG,KAAK,cAAc,MAAM,KAAK,GAAG,OAAO,WAAW;AACxG,UAAM,QAAQ,UAAU,aAAa;AAAA,MACjC,OAAO,GAAG,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,MACX,OAAO,YAAY,UAAU,YAAY;AAAA,IAAA,CAC5C;AACD,UAAM,QAAQ,UAAU,aAAa;AAAA,MACjC,OAAO,GAAG,KAAK;AAAA,MACf,MAAM,IAAI,KAAK,KAAK,IAAI,EAAE;AAAA,MAC1B,OAAO;AAAA,IAAA,CACV;AACD,UAAM,WAAW,UAAU,aAAa;AAAA,MACpC,OAAO,GAAG,KAAK;AAAA,MACf,MAAM,gBAAgB;AAAA,MACtB,OAAO;AAAA,IAAA,CACV;AACD,UAAM,QAAQ,UAAU,aAAa;AAAA,MACjC,OAAO,GAAG,KAAK;AAAA,MACf,MAAM,qBAAqB;AAAA,MAC3B,OAAO;AAAA,IAAA,CACV;AACD,UAAM,+BAAe,IAAA;AACrB,aAAS,IAAI,aAAa,aAAa,WAAW,KAAK,CAAC,CAAC;AACzD,aAAS,IAAI,kBAAkB,aAAa,OAAO,KAAK,CAAC,CAAC;AAC1D,aAAS,IAAI,SAAS,aAAa,OAAO,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC;AAChE,aAAS,IAAI,YAAY,aAAa,UAAU,gBAAgB,MAAM,CAAC;AACvE,aAAS,IAAI,SAAS,EAAE,QAAQ,OAAO,QAAQ,GAAG,MAAM,oBAAoB,QAAQ,KAAA,CAAM;AAC1F,aAAS,IAAI,SAAS,EAAE,QAAQ,OAAO,QAAQ,oBAAoB,MAAM,kBAAkB,QAAQ,KAAA,CAAM;AACzG,UAAM,4BAAY,IAAA;AAClB,eAAW,QAAQ,KAAK,MAAM,QAAQ,GAAG,KAAK,QAAQ,GAAG;AACrD,UAAI,oBAAoB,SAAS,KAAK,IAAI,KAAK,SAAS,IAAI,KAAK,IAAI,GAAG;AACpE,cAAM;AAAA,UACF;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA,eAAe,KAAK,IAAI;AAAA,QAAA;AAAA,MAEhC;AACA,UAAI,CAAC,OAAO,UAAU,KAAK,UAAU,KAAK,KAAK,cAAc,KAAK,KAAK,aAAa,MAAM,GAAG;AACzF,cAAM;AAAA,UACF;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA,eAAe,KAAK,IAAI,oBAAoB,KAAK,UAAU;AAAA,QAAA;AAAA,MAEnE;AACA,UAAI,KAAK,SAAS,KAAK,QAAQ,YAAY,cAAc,GAAG;AACxD,cAAM;AAAA,UACF;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA,eAAe,KAAK,IAAI;AAAA,QAAA;AAAA,MAEhC;AACA,YAAM,SAAS,UAAU,aAAa;AAAA,QAClC,OAAO,GAAG,KAAK,IAAI,KAAK,IAAI;AAAA,QAC5B,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,MAAA,CACf;AACD,YAAM,IAAI,KAAK,MAAM,EAAE,QAAQ,MAAM;AACrC,eAAS,IAAI,KAAK,MAAM,aAAa,QAAQ,KAAK,UAAU,CAAC;AAAA,IACjE;AACA,WAAO,EAAE,WAAW,OAAO,OAAO,UAAU,OAAO,OAAO,UAAU,iBAAA;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAU,SAAkC;AAChD,UAAM,EAAE,WAAW,KAAK;AACxB,UAAM,UAAU,OAAO,qBAAqB,EAAE,OAAO,GAAG,KAAK,KAAK,UAAU;AAC5E,YAAQ,YAAY,QAAQ,QAAQ;AACpC,YAAQ,YAAY,QAAQ,OAAO,oBAAoB,QAAQ,gBAAgB;AAC/E,eAAW,EAAE,QAAQ,KAAA,KAAU,QAAQ,MAAM,UAAU;AACnD,UAAI,KAAK,MAAM;AACX,gBAAQ,YAAY,MAAM;AAAA,MAC9B;AAAA,IACJ;AACA,WAAO,MAAM,OAAO,CAAC,QAAQ,OAAA,CAAQ,CAAC;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,iBAAuB;AAC3B,UAAM,EAAE,YAAY;AACpB,QAAI,YAAY,MAAM;AAClB;AAAA,IACJ;AACA,SAAK,UAAU;AACf,SAAK,YAAY;AACjB,UAAM,SAAS,CAAC,QAAQ,WAAW,QAAQ,OAAO,QAAQ,OAAO,QAAQ,UAAU,QAAQ,KAAK;AAChG,eAAW,EAAE,OAAA,KAAY,QAAQ,MAAM,UAAU;AAC7C,aAAO,KAAK,MAAM;AAAA,IACtB;AACA,SAAK,cAAc,MAAM;AACrB,YAAM,EAAE,cAAc,KAAK;AAC3B,iBAAW,UAAU,QAAQ;AACzB,kBAAU,QAAQ,MAAM;AAAA,MAC5B;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,cAAc,QAA0B;AAC5C,UAAM,QAA4B,CAAA;AAClC,eAAW,UAAU,KAAK,SAAS;AAC/B,UAAI,OAAO,cAAc,MAAM;AAC3B,cAAM,KAAK,OAAO,UAAU,SAAS,MAAM,MAAM,MAAS,CAAC;AAAA,MAC/D;AAAA,IACJ;AACA,QAAI,MAAM,WAAW,GAAG;AACpB,aAAA;AACA;AAAA,IACJ;AACA,SAAK,QAAQ,IAAI,KAAK,EAAE,KAAK,QAAQ,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAoC;AACxC,UAAM,EAAE,YAAY;AACpB,QAAI,YAAY,MAAM;AAClB,YAAM,IAAI,iBAAiB,gBAAgB,GAAG,KAAK,KAAK,kBAAkB,EAAE,OAAO,KAAK,WAAA,CAAY;AAAA,IACxG;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,gBAAgB,SAA4B,WAAgB,MAAiB;AACjF,UAAM,EAAE,GAAG,MAAA,IAAU;AACrB,UAAM,CAAC,IAAI,IAAI,EAAE,IAAI,KAAK;AAC1B,UAAM,SAAS,IAAI,aAAa,IAAI,CAAC;AACrC,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,aAAO,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,IAAI,MAAM;AAC1C,aAAO,IAAI,IAAI,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,MAAM;AAClD,aAAO,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,MAAM;AAC5E,aAAO,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;AAAA,IAC9B;AACA,SAAK,IAAI,OAAO,MAAM,YAAY,QAAQ,WAAW,GAAG,MAAM;AAC9D,QAAI,KAAK;AACT,QAAI,KAAK;AACT,QAAI,KAAK;AACT,UAAM,KAAK,CAAC,OAAO,mBAAmB,OAAO,mBAAmB,OAAO,iBAAiB;AACxF,UAAM,KAAK,CAAC,OAAO,mBAAmB,OAAO,mBAAmB,OAAO,iBAAiB;AACxF,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,YAAM,IAAI,OAAO,IAAI,CAAC;AACtB,YAAM,IAAI,OAAO,IAAI,IAAI,CAAC;AAC1B,YAAM,IAAI,OAAO,IAAI,IAAI,CAAC;AAC1B,YAAM;AACN,YAAM;AACN,YAAM;AACN,SAAG,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AACzB,SAAG,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AACzB,SAAG,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AACzB,SAAG,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AACzB,SAAG,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AACzB,SAAG,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AAAA,IAC7B;AACA,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,KAAK;AAChB,QAAI,QAAQ;AACZ,QAAI,QAAQ;AACZ,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,YAAM,KAAK,OAAO,IAAI,CAAC,IAAI;AAC3B,YAAM,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI;AAC/B,YAAM,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI;AAC/B,YAAM,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK;AACnC,eAAS;AACT,cAAQ,KAAK,IAAI,OAAO,CAAC;AAAA,IAC7B;AACA,UAAM,EAAE,WAAW;AACnB,WAAO,IAAI,aAAa,CAAC;AACzB,WAAO,IAAI,gBAAgB,CAAC;AAC5B,WAAO,IAAI,oBAAoB,CAAC;AAChC,WAAO,IAAI,YAAY,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;AACtC,WAAO,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1C,WAAO,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1C,WAAO,IAAI,aAAa,KAAK,KAAK,QAAQ,CAAC,CAAC;AAC5C,WAAO,IAAI,UAAU,KAAK,KAAK,KAAK,CAAC;AACrC,SAAK,MAAM,OAAO,MAAM;AACxB,SAAK,IAAI,OAAO,MAAM,YAAY,QAAQ,OAAO,GAAG,OAAO,aAAa;AACxE,WAAO,YAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,sBACJ,UACA,MACA,UACc;AACd,QAAI,SAAS,WAAW,QAAQ;AAC5B,WAAK,gBAAgB;AACrB,aAAO,KAAK;AAAA,IAChB;AACA,QAAI,SAAS,WAAW,UAAU,SAAS,SAAS,QAAQ,SAAS,WAAW,MAAM;AAClF,WAAK,gBAAgB;AACrB,aAAO;AAAA,IACX;AACA,UAAM,WAAW,KAAK;AACtB,UAAM,WACF,aAAa,QACb,SAAS,WAAW,SAAS,UAC7B,SAAS,WAAW,SAAS,UAC7B,SAAS,YAAY,SAAS,OAAO,WACrC,SAAS,KAAK,WAAW,SAAS,KAAK;AAC3C,UAAM,OAAO,YAAY,aAAa,OAAO,SAAS,OAAO,SAAS;AACtE,UAAM,SAAS,KAAK,IAAI,UAAU,MAAM,MAAM,WAAW,QAAQ;AACjE,SAAK,gBAAgB;AAAA,MACjB,QAAQ,SAAS;AAAA,MACjB,QAAQ,SAAS;AAAA,MACjB,SAAS,SAAS,OAAO;AAAA,MACzB;AAAA,MACA;AAAA,IAAA;AAEJ,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,cAAc,MAAmB,SAAyB,SAA4C;AAC1G,UAAM,EAAE,aAAa;AACrB,WAAO;AAAA,MACH,QAAQ,KAAK,IAAI;AAAA,MACjB,MAAM,KAAK,IAAI;AAAA,MACf,WAAW,KAAK,IAAI;AAAA,MACpB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,GAAG,KAAK;AAAA,MACR,KAAK,KAAK;AAAA,MACV,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,QAAQ,CAAC,SAA0B;AAC/B,cAAM,UAAU,SAAS,IAAI,IAAI;AACjC,YAAI,YAAY,QAAW;AACvB,gBAAM,gBAAgB,QAAQ,MAAM,CAAC,GAAG,SAAS,KAAA,CAAM,GAAG,+BAA+B,IAAI,GAAG;AAAA,QACpG;AACA,eAAO;AAAA,MACX;AAAA,IAAA;AAAA,EAER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,UAAU,WAA2B,WAA6D;AACtG,UAAM,aAAa,KAAK;AACxB,UAAM,MAAM,MAAqB,KAAK,eAAe,WAAW,WAAW,UAAU;AACrF,UAAM,UAAU,KAAK,MAAM,MAAM,MAAM,MAAS,EAAE,KAAK,GAAG;AAC1D,SAAK,QAAQ,MAAM,MAAM,MAAS;AAClC,SAAK,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,eACV,WACA,WACA,YACa;AACb,UAAM,YAAY,KAAK,IAAI,KAAK,SAAS,IAAI,WAAW;AACxD,UAAM,KAAK,IAAI,UAAU,KAAK,KAAK,MAAM,MAAM,WAAW,SAAS,CAAC;AACpE,QAAI,KAAK,eAAe,YAAY,eAAe,KAAK,iBAAiB;AACrE;AAAA,IACJ;AACA,UAAM,KAAK,MAAM,KAAK,WAAW,SAAS;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,cAAc,MAAmD;AAC3E,SAAK,aAAA;AACL,UAAM,EAAE,YAAY;AACpB,UAAM,UAAU,SAAS,SAAS,IAAI,IAAI;AAC1C,QAAI,YAAY,QAAQ,YAAY,QAAW;AAC3C,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,YAAY,OAAO,KAAK,CAAC,GAAG,QAAQ,SAAS,MAAM;AAAA,QACnD,YAAY,IAAI;AAAA,MAAA;AAAA,IAExB;AACA,UAAM,KAAK,MAAA;AACX,UAAM,QAAQ,MAAM,KAAK,IAAI,SAAS,KAAK,QAAQ,QAAQ,QAAQ,MAAM,QAAW,QAAQ,MAAM;AAClG,WAAO,SAAS,WAAW,SAAS,UAAU,IAAI,YAAY,KAAK,IAAI,IAAI,aAAa,KAAK;AAAA,EACjG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,UAAU,MAA6B;AACjD,SAAK,aAAA;AACL,QAAI,CAAC,KAAK,MAAM,OAAO,SAAS,IAAI,GAAG;AACnC,YAAM;AAAA,QACF;AAAA,QACA;AAAA,QACA,CAAC,GAAG,KAAK,MAAM,MAAM;AAAA,QACrB,mBAAmB,IAAI,sBAAsB,KAAK,MAAM,IAAI;AAAA,MAAA;AAAA,IAEpE;AACA,QAAI,KAAK,MAAM,GAAG;AACd;AAAA,IACJ;AACA,UAAM,KAAK,MAAA;AACX,UAAM,KAAK;AACX,UAAM,KAAK,IAAI,UAAU,MAAA;AACzB,SAAK,aAAA;AACL,UAAM,UAAU,KAAK,eAAA;AACrB,UAAM,EAAE,WAAW,KAAK;AACxB,QAAI,KAAK,YAAY;AACjB,aAAO,MAAM,YAAY,QAAQ,OAAO,GAAG,KAAK,UAAU;AAC1D,WAAK,aAAa;AAAA,IACtB;AACA,SAAK,iBAAiB,QAAQ,KAAK;AACnC,UAAM,OAAO,KAAK,KAAK,QAAQ,CAAC;AAChC,SAAK,KAAK;AAAA,MACN;AAAA,MACA,KAAK,MAAM;AAAA,MACX,KAAK,cAAc,KAAK,qBAAqB,GAAG,KAAK,eAAe,iBAAiB,CAAC;AAAA,IAAA;AAE1F,SAAK,KAAK,MAAA;AACV,UAAM,QAAQ,IAAI,aAAa,KAAK,KAAK,GAAG,KAAK,KAAK,UAAU,KAAK,eAAe;AACpF,SAAK,MAAM,gBAAgB,OAAO,MAAM,KAAK,WAAW,IAAI;AAC5D,UAAM,QAAA;AACN,UAAM,SAAS,QAAQ,OAAO,GAAG,kBAAkB;AACnD,UAAM,YAAY,MAAM,OAAA;AACxB,SAAK,4BAA4B,UAAU;AAC3C,UAAM,UAAU;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,aAAa,MAA+B;AAChD,QAAI,KAAK,eAAe,YAAY;AAChC;AAAA,IACJ;AACA,UAAM,QAAQ,IAAI,iBAAiB,iBAAiB,gBAAgB,KAAK,MAAM,MAAM,KAAK,OAAO,IAAI;AAAA,MACjG,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,IAAA,CACjB;AACD,UAAM,UAAU,KAAK,QAAQ,OAAO,CAAC;AACrC,SAAK,aAAa;AAClB,eAAW,UAAU,SAAS;AAC1B,aAAO,QAAQ;AACf,aAAO,OAAO,KAAK;AAAA,IACvB;AACA,SAAK,SAAA;AAAA,EACT;AAAA;AAAA,EAGQ,WAAiB;AACrB,QAAI,KAAK,UAAU;AACf;AAAA,IACJ;AACA,SAAK,WAAW;AAChB,SAAK,eAAA;AACL,SAAK,eAAA;AACL,SAAK,cAAc,MAAM;AACrB,WAAK,KAAK,QAAA;AAAA,IACd,CAAC;AACD,QAAI,KAAK,IAAI,UAAU,SAAS;AAC5B,WAAK,IAAI,KAAK,KAAA;AAAA,IAClB;AACA,SAAK,eAAA;AACL,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,QAAQ;AACb,SAAK,gBAAgB;AAAA,EACzB;AAAA;AAAA,EAGQ,oBAA0B;AAC9B,QAAI,KAAK,eAAe,YAAY;AAChC,YAAM,cAAc,KAAK,KAAK;AAAA,IAClC;AAAA,EACJ;AAAA;AAAA,EAGQ,eAAqB;AACzB,QAAI,KAAK,eAAe,WAAW;AAC/B,YAAM,IAAI,iBAAiB,gBAAgB,GAAG,KAAK,KAAK,kBAAkB,EAAE,OAAO,WAAW;AAAA,IAClG;AACA,SAAK,kBAAA;AAAA,EACT;AACJ;ACjjEA,MAAM,iBACF;AAWJ,SAASC,UAAQ,UAAkB,OAAgB,UAAmB,SAAmC;AACrG,SAAO,IAAI,iBAAiB,sBAAsB,SAAS,EAAE,UAAU,OAAO,UAAU;AAC5F;AAOA,SAAS,UAAU,MAAyB,QAAsB;AAC9D,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AAClC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,CAAC,OAAO,SAAS,CAAC,KAAK,KAAK,GAAG;AAC/B,YAAM,IAAI;AAAA,QACN;AAAA,QACA,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;AAAA,QAC5B;AAAA,UACI,UAAU;AAAA,UACV,OAAO;AAAA,UACP,OAAO;AAAA,UACP,UAAU;AAAA,QAAA;AAAA,MACd;AAAA,IAER;AAAA,EACJ;AACJ;AAOA,SAAS,cAAc,GAAuB;AAC1C,QAAM,IAAI,EAAE;AACZ,QAAMC,UAAS,EAAE,UAAA;AACjB,QAAM,MAAM,IAAI,aAAa,CAAC;AAC9B,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,QAAI,CAAC,IAAIA,QAAO,CAAC,IAAI;AAAA,EACzB;AACA,SAAO;AACX;AASA,SAAS,eAAe,GAAkB,QAAqB;AAC3D,QAAM,EAAE,SAAS,OAAO;AACxB,MAAI,OAAO,KAAK,eAAe,GAAG;AAC9B,UAAMD;AAAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,IAAI,SAAS,OAAO,KAAK,UAAU;AAAA,IAAA;AAAA,EAE3D;AACA,MAAI;AACJ,UAAQ,OAAO,OAAA;AAAA,IACX,KAAK;AAAA,IACL,KAAK,OAAO;AACR,YAAM,OAAO,EAAE,MAAM,QAAQ,IAAI;AACjC,YAAME,OAAM,gBAAgB,eAAe,OAAO,IAAI,aAAa,IAAI;AACvE,gBAAUA,MAAK,gBAAgB,IAAI,GAAG;AACtC,aAAOA;AAAAA,IACX;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AACD,eAAS,EAAE,MAAM,QAAQ,IAAI;AAC7B;AAAA,IACJ,KAAK;AACD,eAAS,OAAO;AAChB;AAAA,IACJ;AACI,YAAMF;AAAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB,IAAI,QAAQ,OAAO,KAAK;AAAA,MAAA;AAAA,EAC5C;AAER,QAAM,MAAM,IAAI,aAAa,EAAE,SAAS;AACxC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACjC,QAAI,CAAC,IAAI,OAAO,CAAC;AAAA,EACrB;AACA,YAAU,KAAK,gBAAgB,IAAI,GAAG;AACtC,SAAO;AACX;AAWO,SAAS,gBACZ,GACA,MACG;AACH,QAAM,IAAI,EAAE;AACZ,MAAI,SAAS,QAAQ,SAAS,QAAW;AACrC,UAAM,SAAS,EAAE,MAAM,OAAO,MAAM;AACpC,QAAI,WAAW,MAAM;AACjB,aAAO,cAAc,CAAC;AAAA,IAC1B;AACA,WAAO,eAAe,GAAG,MAAM;AAAA,EACnC;AACA,MAAI,gBAAgB,cAAc;AAC9B,QAAI,KAAK,WAAW,GAAG;AACnB,YAAMA,UAAQ,YAAY,KAAK,QAAQ,GAAG,CAAC,WAAW,gBAAgB,KAAK,MAAM,qBAAqB,CAAC,EAAE;AAAA,IAC7G;AACA,cAAU,MAAM,UAAU;AAC1B,WAAO;AAAA,EACX;AACA,MAAI,OAAO,SAAS,UAAU;AAC1B,UAAM,SAAS,EAAE,MAAM,IAAI,IAAI;AAC/B,QAAI,WAAW,MAAM;AACjB,YAAMA;AAAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA,+BAA+B,IAAI;AAAA,MAAA;AAAA,IAE3C;AACA,WAAO,eAAe,GAAG,MAAM;AAAA,EACnC;AACA,MAAI,YAAY,OAAO,IAAI,GAAG;AAC1B,UAAMA;AAAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAER;AACA,QAAM,IAAI;AAAA,IACN;AAAA,IACA,0DAA0D,cAAc;AAAA,IACxE;AAAA,MACI,QAAQ;AAAA,MACR,MAAM;AAAA,IAAA;AAAA,EACV;AAER;AAuBO,SAAS,eAAe,GAAkB,MAA4D;AACzG,MAAI,SAAS,MAAM;AACf,WAAO,EAAE,MAAM,EAAE,SAAS,QAAQ,QAAQ,QAAQ,KAAA;AAAA,EACtD;AACA,MAAI,SAAS,SAAS,SAAS,QAAQ,SAAS,QAAW;AACvD,WAAO,EAAE,MAAM,MAAM,QAAQ,QAAQ,QAAQ,KAAA;AAAA,EACjD;AACA,MAAI,OAAO,SAAS,UAAU;AAC1B,UAAMA;AAAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAER;AACA,QAAM,SAAS,EAAE,MAAM,IAAI,IAAI;AAC/B,MAAI,WAAW,MAAM;AACjB,UAAMA;AAAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA,6BAA6B,IAAI;AAAA,IAAA;AAAA,EAEzC;AACA,MAAI,OAAO,KAAK,eAAe,GAAG;AAC9B,UAAMA;AAAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,IAAI,SAAS,OAAO,KAAK,UAAU;AAAA,IAAA;AAAA,EAE3D;AACA,UAAQ,OAAO,OAAA;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,OAAO;AACR,YAAM,OAAO,EAAE,MAAM,QAAQ,IAAI;AACjC,YAAM,WAAW,YAAY,GAAG,IAAI;AACpC,YAAM,OAAO,oBAAoB,eAAe,WAAW,IAAI,aAAa,QAAQ;AACpF,aAAO,EAAE,MAAM,QAAQ,UAAU,OAAA;AAAA,IACrC;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAED,QAAE,MAAM,QAAQ,IAAI;AACpB,YAAMA,UAAQ,UAAU,MAAM,yBAAyB,gBAAgB,IAAI,QAAQ,OAAO,KAAK,EAAE;AAAA,IACrG;AACI,YAAMA;AAAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB,IAAI,QAAQ,OAAO,KAAK;AAAA,MAAA;AAAA,EAC5C;AAEZ;ACrNO,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBhB,YAAY,WAAmB,eAAuB,MAAgB,WAAoC;AAVlH,SAAQ,iBAAqC;AAC7C,SAAQ,qBAAyC;AAU7C,SAAK,YAAY;AACjB,SAAK,gBAAgB;AACrB,SAAK,OAAO;AACZ,SAAK,YAAY,OAAO,OAAO;AAAA,MAC3B,YAAY,UAAU;AAAA,MACtB,gBAAgB,UAAU;AAAA,MAC1B,gBAAgB,UAAU;AAAA,IAAA,CAC7B;AACD,SAAK,eAAe,OAAO,cAAc,eAAe,cAAc,eAAe,IAAI;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAa,OACT,WACA,MACA,WACuB;AACvB,UAAM,CAAC,eAAe,YAAY,IAAI,eAAe,MAAM,SAAS;AAGpE,UAAM,YAAY,MAAM,UAAU,OAAO,aAAa;AACtD,UAAM,gBAAgB,MAAM,UAAU,OAAO,YAAY;AACzD,WAAO,IAAI,eAAe,WAAW,eAAe,MAAM,SAAS;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,MAAM,WAA+E;AACxF,WAAO;AAAA,MACH,WAAW,uBAAuB;AAAA,QAC9B,YAAY,UAAU;AAAA,QACtB,gBAAgB,UAAU;AAAA,QAC1B,gBAAgB,UAAU;AAAA,MAAA,CAC7B;AAAA,MACD,WAAW,sBAAsB,EAAE,YAAY,UAAU,YAAY;AAAA,IAAA;AAAA,EAE7E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAK,WAA0C;AAC3C,SAAK,iBAAiB,KAAK,UAAU,KAAK;AAAA,MACtC,KAAK,UAAU;AAAA,MACf,GAAG,UAAU;AAAA,MACb,OAAO,UAAU;AAAA,MACjB,UAAU,UAAU;AAAA,MACpB,WAAW,UAAU;AAAA,MACrB,UAAU,UAAU;AAAA,MACpB,GAAG,UAAU;AAAA,IAAA,CAChB;AACD,SAAK,qBAAqB,KAAK,cAAc,KAAK;AAAA,MAC9C,UAAU,UAAU;AAAA,MACpB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IAAA,CAChB;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,MAA6B,GAAW,cAA4B;AACvE,SAAK,gBAAgB,MAAM,GAAG,YAAY;AAC1C,SAAK,oBAAoB,MAAM,YAAY;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,gBAAgB,MAA6B,GAAW,cAA4B;AAChF,UAAM,QAAQ,KAAK,MAAM,KAAK,gBAAgB,iBAAiB;AAC/D,UAAM,OAAO,OAAO,GAAG,KAAK,UAAU,eAAe,KAAK,IAAI;AAC9D,SAAK,UAAU,SAAS,MAAM,OAAO,MAAM,CAAC,YAAY,CAAC;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,MAA6B,cAA4B;AACzE,UAAM,QAAQ,KAAK,MAAM,KAAK,oBAAoB,qBAAqB;AACvE,SAAK,cAAc,SAAS,MAAM,OAAO,KAAK,cAAc,CAAC,YAAY,CAAC;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,MAAM,OAA2B,QAA6B;AAClE,QAAI,UAAU,MAAM;AAChB,YAAM,IAAI;AAAA,QACN;AAAA,QACA,kBAAkB,MAAM;AAAA,QACxB;AAAA,UACI,OAAO;AAAA,QAAA;AAAA,MACX;AAAA,IAER;AACA,WAAO;AAAA,EACX;AACJ;AC1HA,MAAM,aAAa,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,SAAS;AAG3D,MAAM,uBAAuB;AAG7B,MAAM,qBAAqB;AAG3B,MAAM,gBAA8B,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,KAAA;AAG1E,MAAM,cAAyB,EAAE,QAAQ,OAAO,aAAa,OAAO,MAAM,GAAG,UAAU,OAAO,aAAa,MAAA;AAG3G,MAAM,cAAyB,EAAE,YAAY,EAAA;AAG7C,MAAM,cAAc;AAGpB,MAAM,mBAA+C,OAAO,OAAmC;AAAA,EAC3F,GAAG;AAAA,EACH,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ,CAAC,GAAG,GAAG,CAAC;AAAA,EAChB,MAAM;AACV,CAAC;AAOD,SAAS,cAAc,OAAwB;AAC3C,MAAI,UAAU,MAAM;AAChB,WAAO;AAAA,EACX;AACA,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,aAAa,OAAO,UAAU,UAAU;AACtF,WAAO,OAAO,KAAK;AAAA,EACvB;AACA,MAAI,OAAO,UAAU,aAAa;AAC9B,WAAO;AAAA,EACX;AACA,MAAI,OAAO,UAAU,YAAY,YAAY,SAAS,OAAO,MAAM,WAAW,UAAU;AACpF,WAAO,IAAI,MAAM,MAAM;AAAA,EAC3B;AACA,SAAO,OAAO;AAClB;AASA,SAAS,QAAQ,UAAkB,OAAgB,UAAoC;AACnF,SAAO,IAAI,iBAAiB,sBAAsB,GAAG,QAAQ,YAAY,QAAQ,SAAS,cAAc,KAAK,CAAC,IAAI;AAAA,IAC9G;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACH;AACL;AAYA,SAAS,WACL,MACA,OACA,UACA,OACA,UACM;AACN,QAAM,QAAiB,UAAU,SAAY,WAAW;AACxD,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,MAAM,KAAK,GAAG;AACvE,UAAM,QAAQ,MAAM,OAAO,QAAQ;AAAA,EACvC;AACA,SAAO;AACX;AASA,SAAS,YAAY,MAAc,OAA4B,UAA4B;AACvF,QAAM,QAAiB,UAAU,SAAY,WAAW;AACxD,MAAI,OAAO,UAAU,WAAW;AAC5B,UAAM,QAAQ,MAAM,OAAO,WAAW;AAAA,EAC1C;AACA,SAAO;AACX;AAQA,SAAS,QAAQ,OAA0B,UAAwB;AAC/D,QAAM,QAAiB,UAAU,SAAY,WAAW;AACxD,MAAI,UAAU,KAAK,UAAU,GAAG;AAC5B,UAAM,QAAQ,OAAO,OAAO,QAAQ;AAAA,EACxC;AACA,SAAO;AACX;AAQA,SAAS,WACL,OACA,UACiC;AACjC,MAAI,UAAU,QAAW;AACrB,WAAO;AAAA,EACX;AACA,QAAM,WAAW;AACjB,QAAM,QAAiB;AACvB,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,YAAY,QAAQ;AACrE,UAAM,QAAQ,UAAU,OAAO,QAAQ;AAAA,EAC3C;AACA,QAAM,EAAE,WAAW;AACnB,MAAI,WAAW,KAAK,WAAW,GAAG;AAC9B,UAAM,QAAQ,UAAU,OAAO,QAAQ;AAAA,EAC3C;AACA,QAAM,IAAa,MAAM,CAAC;AAC1B,QAAM,IAAa,MAAM,CAAC;AAC1B,QAAM,IAAa,WAAW,IAAI,MAAM,CAAC,IAAI;AAC7C,MACI,OAAO,MAAM,YACb,OAAO,MAAM,YACb,OAAO,MAAM,YACb,CAAC,OAAO,SAAS,CAAC,KAClB,CAAC,OAAO,SAAS,CAAC,KAClB,CAAC,OAAO,SAAS,CAAC,GACpB;AACE,UAAM,QAAQ,UAAU,OAAO,QAAQ;AAAA,EAC3C;AACA,SAAO,CAAC,GAAG,GAAG,CAAC;AACnB;AAQA,SAAS,SAAS,OAAkC,UAAwC;AACxF,MAAI,UAAU,QAAW;AACrB,WAAO;AAAA,EACX;AACA,QAAM,QAAiB;AACvB,MAAI,UAAU,SAAS,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,IAAI;AAC1E,UAAM,QAAQ,QAAQ,OAAO,yBAAyB;AAAA,EAC1D;AACA,SAAO;AACX;AAOA,SAAS,kBAAkB,OAAwB;AAC/C,SAAO,OAAO,UAAU,KAAK,KAAK,SAAS;AAC/C;AAOA,SAAS,SAAS,MAA6B;AAC3C,MAAI,SAAS,MAAM;AACf,WAAO;AAAA,EACX;AACA,SAAO,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI;AACxC;AAQA,SAAS,OAAO,QAAuB,MAAsB;AACzD,QAAM,QAAQ,OAAO,IAAI;AACzB,MAAI,OAAO,UAAU,UAAU;AAC3B,UAAM,QAAQ,MAAM,OAAO,gBAAgB;AAAA,EAC/C;AACA,SAAO;AACX;AAQA,SAAS,OAAO,QAAuB,MAAiC;AACpE,QAAM,QAAQ,OAAO,IAAI;AACzB,MAAI,OAAO,UAAU,UAAU;AAC3B,UAAM,QAAQ,MAAM,OAAO,gBAAgB;AAAA,EAC/C;AACA,SAAO;AACX;AASA,SAAS,OAAO,QAAmB,UAAgC;AAC/D,QAAM,MAAwC,CAAA;AAC9C,aAAW,QAAQ,OAAO,KAAK,QAAQ,GAAG;AACtC,QAAI,IAAI,IAAI,QAAQ,SAAS,OAAO,IAAI,IAAI,SAAS,IAAI;AAAA,EAC7D;AACA,SAAO;AACX;AAOA,SAAS,mBAAmB,QAA4C;AACpE,SAAO;AAAA,IACH,YAAY,OAAO,eAAe,IAAI,IAAI;AAAA,IAC1C,gBAAgB,OAAO,mBAAmB;AAAA,IAC1C,gBAAgB,OAAO,mBAAmB,IAAI,IAAI;AAAA,EAAA;AAE1D;AAaO,SAAS,0BACZ,SACA,UAC0B;AAC1B,QAAM,IAAwB,WAAW,CAAA;AACzC,QAAM,OAAO,YAAY;AACzB,MAAI,aAAa,UAAa,EAAE,gBAAgB,UAAa,EAAE,gBAAgB,SAAS,aAAa;AACjG,UAAM,IAAI;AAAA,MACN;AAAA,MACA,mFAAmF,cAAc,EAAE,WAAW,CAAC,aAAa,SAAS,WAAW;AAAA,MAChJ,EAAE,UAAU,eAAe,OAAO,EAAE,aAAa,UAAU,SAAS,YAAA;AAAA,IAAY;AAAA,EAExF;AACA,QAAM,WAAW,EAAE,aAAa,SAAY,KAAK,WAAW,EAAE;AAC9D,MAAI,aAAa,MAAM;AACnB,UAAM,IAAI;AAAA,MACN;AAAA,MACA;AAAA,MACA,EAAE,QAAQ,YAAY,MAAM,6EAAA;AAAA,IAA6E;AAAA,EAEjH;AACA,QAAM,WAAuC;AAAA,IACzC,SAAS,WAAW,WAAW,EAAE,SAAS,KAAK,SAAS,mBAAmB,iBAAiB;AAAA,IAC5F,iBAAiB,WAAW,mBAAmB,EAAE,iBAAiB,KAAK,iBAAiB,CAAC,MAAM,IAAI,GAAG,KAAK;AAAA,IAC3G,cAAc,WAAW,gBAAgB,EAAE,cAAc,KAAK,cAAc,CAAC,MAAM,IAAI,GAAG,KAAK;AAAA,IAC/F,SAAS,WAAW,WAAW,EAAE,SAAS,KAAK,SAAS,CAAC,MAAM,KAAK,GAAG,MAAM;AAAA,IAC7E,eAAe,YAAY,iBAAiB,EAAE,eAAe,KAAK,aAAa;AAAA,IAC/E,mBAAmB,YAAY,qBAAqB,EAAE,mBAAmB,KAAK,iBAAiB;AAAA,IAC/F,QAAQ,YAAY,UAAU,EAAE,QAAQ,KAAK,MAAM;AAAA,IACnD,UAAU,EAAE,aAAa,SAAY,KAAK,WAAW,EAAE;AAAA,IACvD;AAAA,IACA,QAAQ,EAAE,WAAW,SAAY,KAAK,SAAS,EAAE;AAAA,IACjD,cAAc,YAAY,gBAAgB,EAAE,cAAc,KAAK,YAAY;AAAA,IAC3E,KAAK,QAAQ,EAAE,KAAK,KAAK,GAAG;AAAA,IAC5B,OAAO,WAAW,SAAS,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,IAAI,GAAG,KAAK;AAAA,IACnE,QAAQ,WAAW,EAAE,QAAQ,KAAK,MAAM;AAAA,IACxC,MAAM,SAAS,EAAE,MAAM,KAAK,IAAI;AAAA,IAChC,iBAAiB,WAAW,mBAAmB,EAAE,iBAAiB,KAAK,iBAAiB,CAAC,MAAM,KAAK,GAAG,MAAM;AAAA,IAC7G,cAAc;AAAA,MACV;AAAA,MACA,EAAE;AAAA,MACF,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IAAA;AAAA,IAEJ,mBAAmB;AAAA,MACf;AAAA,MACA,EAAE;AAAA,MACF,KAAK;AAAA,MACL,CAAC,MAAM,kBAAkB,CAAC,KAAK,KAAK;AAAA,MACpC,qBAAqB,uBAAuB;AAAA,IAAA;AAAA,IAEhD,aAAa,WAAW,eAAe,EAAE,aAAa,KAAK,aAAa,mBAAmB,iBAAiB;AAAA,EAAA;AAEhH,SAAO,OAAO,OAAO,QAAQ;AACjC;AAQO,SAAS,oBAAoB,QAA2D;AAC3F,QAAM,IAAqB,UAAU,CAAA;AACrC,QAAM,YAAqB,EAAE,aAAa,uBAAuB;AACjE,MAAI,cAAc,WAAW,cAAc,UAAU,cAAc,QAAQ;AACvE,UAAM,QAAQ,aAAa,WAAW,2BAA2B;AAAA,EACrE;AACA,QAAM,SAAkB,EAAE,UAAU,uBAAuB;AAC3D,MAAI,WAAW,WAAW,WAAW,YAAY;AAC7C,UAAM,QAAQ,UAAU,QAAQ,uBAAuB;AAAA,EAC3D;AACA,QAAM,WAAiC;AAAA,IACnC;AAAA,IACA,eAAe;AAAA,MACX;AAAA,MACA,EAAE;AAAA,MACF,uBAAuB;AAAA,MACvB;AAAA,MACA;AAAA,IAAA;AAAA,IAEJ,SAAS,WAAW,WAAW,EAAE,SAAS,uBAAuB,SAAS,mBAAmB,iBAAiB;AAAA,IAC9G,eAAe,YAAY,iBAAiB,EAAE,eAAe,uBAAuB,aAAa;AAAA,IACjG,WAAW;AAAA,MACP;AAAA,MACA,EAAE;AAAA,MACF,uBAAuB;AAAA,MACvB;AAAA,MACA;AAAA,IAAA;AAAA,IAEJ,WAAW;AAAA,MACP;AAAA,MACA,EAAE;AAAA,MACF,uBAAuB;AAAA,MACvB;AAAA,MACA;AAAA,IAAA;AAAA,IAEJ,cAAc;AAAA,MACV;AAAA,MACA,EAAE;AAAA,MACF,uBAAuB;AAAA,MACvB,CAAC,MAAM,IAAI;AAAA,MACX;AAAA,IAAA;AAAA,IAEJ;AAAA,EAAA;AAEJ,SAAO,OAAO,OAAO,QAAQ;AACjC;AA6BO,MAAM,iBAA6E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCtF,YAAY,QAA8B,UAAsC;AAtChF,SAAS,OAAO;AAEhB,SAAS,SAA6D;AAEtE,SAAS,SAAuB;AAEhC,SAAS,QAAsB;AAE/B,SAAS,QAAsB;AAY/B,SAAQ,YAAmC;AAE3C,SAAQ,QAA2B;AAEnC,SAAQ,gBAAgB;AAMxB,SAAQ,WAAiF;AASrF,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAY,YAAmB;AAC3B,WAAO,KAAK,OAAO,WAAW,aAAa,IAAI;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAQ,GAAW,MAAoC;AACnD,UAAM,QAAQ,KAAK,IAAI,GAAG,CAAC,IAAI;AAC/B,UAAM,QAAQ,YAAY,UAAU,YAAY,WAAW,YAAY;AACvE,WAAO;AAAA,MACH,EAAE,MAAM,SAAS,YAAY,OAAO,OAAO,MAAM,KAAA;AAAA,MACjD,EAAE,MAAM,YAAY,YAAY,OAAO,OAAO,MAAM,KAAA;AAAA,MACpD;AAAA,QACI,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO,YAAY,UAAU,YAAY;AAAA,QACzC,MAAM;AAAA,MAAA;AAAA,IACV;AAAA,EAER;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,GAAkB,SAA0C;AAC/D,UAAM,WAAW,0BAA0B,SAAS,KAAK,OAAO;AAChE,UAAM,EAAE,WAAW,cAAA,IAAkB,KAAK;AAC1C,UAAM,IAAI,EAAE;AACZ,QAAI,cAAc,UAAW,cAAc,UAAU,IAAI,eAAgB;AACrE,YAAM,IAAI;AAAA,QACN;AAAA,QACA,cAAc,SACR,uEACA,iBAAiB,CAAC,+BAA+B,aAAa;AAAA,QACpE;AAAA,UACI,SAAS;AAAA,UACT,MAAM;AAAA,QAAA;AAAA,MACV;AAAA,IAER;AACA,WAAO,EAAE,MAAM,gBAAgB,GAAG,SAAS,QAAQ,GAAG,SAAS,eAAe,GAAG,SAAS,MAAM,EAAA;AAAA,EACpG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UAAU,SAAwC;AAC9C,UAAM,WAAW,0BAA0B,SAAS,KAAK,OAAO;AAChE,UAAM,OAAO,KAAK;AAClB,WAAO;AAAA,MACH,QAAQ,SAAS;AAAA,MACjB,aAAa,SAAS;AAAA,MACtB,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,gBAAgB,SAAS;AAAA,MACzB,gBAAgB;AAAA,IAAA;AAAA,EAExB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,WAAsB,YAAgD;AACxE,UAAM,CAAC,eAAe,SAAS,IAAI,eAAe,MAAM,mBAAmB,SAAS,CAAC;AACrF,WAAO;AAAA,MACH,WAAW,oBAAoB;AAAA,MAC/B,WAAW,kBAAkB,OAAO,WAAW,WAAW,CAAC;AAAA,MAC3D;AAAA,MACA;AAAA,MACA,WAAW,iBAAiB,OAAO,WAAW,WAAW,CAAC;AAAA,MAC1D,WAAW,cAAc;AAAA,MACzB,WAAW,MAAM;AAAA,IAAA;AAAA,EAEzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAK,WAA2B,WAAqC;AACvE,SAAK,UAAA;AACL,SAAK,YAAY;AACjB,UAAM,EAAE,GAAG,WAAW,MAAM,MAAM,MAAM,MAAM,WAAW;AACzD,QAAI,MAAM,GAAG;AACT;AAAA,IACJ;AACA,UAAM,CAAC,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,MAAM,QAAQ,IAAI;AAAA,MAClD,UAAU,OAAO,WAAW,oBAAoB,CAAC;AAAA,MACjD,UAAU,OAAO,WAAW,kBAAkB,OAAO,WAAW,WAAW,CAAC,CAAC;AAAA,MAC7E,UAAU,OAAO,WAAW,iBAAiB,OAAO,WAAW,WAAW,CAAC,CAAC;AAAA,MAC5E,UAAU,OAAO,WAAW,cAAc,CAAC;AAAA,MAC3C,UAAU,OAAO,WAAW,MAAM,CAAC;AAAA,IAAA,CACtC;AACD,UAAM,YAAY,MAAM,eAAe,OAAO,WAAW,MAAM,mBAAmB,SAAS,CAAC;AAC5F,QAAI,KAAK,cAAc,WAAW;AAE9B;AAAA,IACJ;AACA,UAAM,MAAM,UAAU,OAAO,WAAW;AACxC,UAAM,QAAQ,UAAU,OAAO,gBAAgB;AAC/C,UAAM,QAAQ,UAAU,OAAO,OAAO;AACtC,UAAM,WAAW,UAAU,OAAO,UAAU;AAC5C,UAAM,QAAQ,UAAU,OAAO,OAAO;AACtC,UAAM,QAAQ,UAAU,OAAO,OAAO;AACtC,UAAM,QAAQ,UAAU,OAAO,OAAO;AACtC,UAAM,WAAW,UAAU,OAAO,UAAU;AAC5C,UAAM,mBAAmB,UAAU,OAAO,kBAAkB;AAC5D,UAAM,SAAS,KAAK,QAAQ,UAAU;AACtC,UAAM,aAAsB;AAAA,MACxB,QAAQ,iBAAiB;AAAA,MACzB,QAAQ,iBAAiB;AAAA,MACzB,MAAM,YAAY;AAAA,MAClB,QAAQ;AAAA,IAAA;AAEZ,UAAM,YAAY,IAAI,YAAY,YAAY,UAAU;AACxD,gBAAY,MAAM,IAAI,SAAS,SAAS,GAAG,EAAE,OAAO,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG;AAC9E,WAAO,MAAM,YAAY,iBAAiB,QAAQ,iBAAiB,QAAQ,SAAS;AACpF,UAAM,UAAU,KAAK,WAAW;AAChC,cAAU,KAAK,EAAE,KAAK,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,UAAU,OAAA,CAAQ;AACzF,UAAM,KAAK,GAAG;AACd,SAAK,QAAQ;AAAA,MACT;AAAA,MACA,MAAM,OAAO,GAAG,IAAI,IAAI;AAAA,MACxB,UAAU,OAAO,IAAI,GAAG,IAAI,IAAI;AAAA,MAChC;AAAA,MACA,SAAS,GAAG,KAAK,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,OAAA,CAAQ;AAAA,MAC5D;AAAA,MACA,SAAS,UACH,GAAG,KAAK,EAAE,GAAG,cAAc,MAAM,MAAM,UAAU,OAAO,GAAG,KAAK,OAAO,GAAG,OAAA,CAAQ,IAClF;AAAA,MACN;AAAA,MACA;AAAA,MACA,SAAS,GAAG,KAAK,EAAE,OAAO,UAAU,WAAW,OAAO,GAAG,OAAO,KAAK,UAAU,GAAG,QAAQ;AAAA,MAC1F;AAAA,MACA,cAAc,QAAQ,KAAK,EAAE,KAAK,OAAO,GAAG,QAAQ;AAAA,MACpD;AAAA,MACA,gBAAgB,UAAU,OAAO,KAAK,KAAK,EAAE,KAAK,OAAO,GAAG,YAAY;AAAA,MACxE,cAAc,KAAK,cAAc,IAAI,KAAK,KAAK,EAAE,KAAK,UAAU,GAAG,WAAA,CAAY,IAAI;AAAA,IAAA;AAAA,EAE3F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,WAAmB,SAA4C;AACrE,UAAM,EAAE,EAAA,IAAM,KAAK,iBAAA;AACnB,UAAM,WAAW,0BAA0B,SAAS,KAAK,OAAO;AAChE,UAAM,EAAE,SAAS,aAAA,IAAiB,KAAK;AACvC,WAAO;AAAA,MACH;AAAA,MACA,KAAK,SAAS;AAAA,MACd,OAAO;AAAA,MACP,WAAW;AAAA,MACX,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,MAAM,SAAS,SAAS,IAAI;AAAA,MAC5B;AAAA,MACA,cAAc,SAAS;AAAA,MACvB,SAAS,SAAS;AAAA,MAClB,iBAAiB,SAAS;AAAA,MAC1B,OAAO,SAAS;AAAA,MAChB,QAAQ,CAAC,SAAS,OAAO,CAAC,GAAG,SAAS,OAAO,CAAC,GAAG,SAAS,OAAO,CAAC,GAAG,CAAC;AAAA,MACtE,iBAAiB,SAAS;AAAA,MAC1B;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;AAAA,IAAA;AAAA,EAExB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,gBAAgB,OAAqB,MAAc,MAAwB,MAAqB;AAC5F,QAAI,SAAS,QAAQ;AACjB,YAAM,IAAI,iBAAiB,iBAAiB,uCAAuC;AAAA,QAC/E,SAAS;AAAA,QACT,MAAM;AAAA,MAAA,CACT;AAAA,IACL;AACA,UAAM,YAAY,KAAK,iBAAA;AACvB,UAAM,OAAO,SAAS,SAAY,WAAW,SAAS,IAAI,KAAK,WAAW,IAAI;AAC9E,UAAM,EAAE,UAAU;AAClB,QAAI,UAAU,MAAM;AAChB,UAAI,UAAU,MAAM,GAAG;AACnB;AAAA,MACJ;AACA,YAAM,IAAI;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,UACI,OAAO;AAAA,QAAA;AAAA,MACX;AAAA,IAER;AACA,UAAM,SAAS,UAAU,KAAK,SAAS,IAAI;AAC3C,UAAM,OAAO,KAAK,aAAa,QAAQ,KAAK,SAAS,OAAO,MAAM,KAAK,KAAK,SAAS,OAAO,MAAM,KAAK,KAAK;AAC5G,SAAK,WAAW,EAAE,IAAI,MAAM,IAAI,KAAA;AAChC,QAAI,KAAK,eAAe;AACpB,WAAK,gBAAgB;AACrB,UAAI,MAAM,iBAAiB,MAAM;AAC7B,cAAM,KAAK,SAAS,MAAM,MAAM,cAAc,MAAM,UAAU,CAAC,CAAC,CAAC;AAAA,MACrE;AAAA,IACJ;AACA,UAAM,GAAG,SAAS,MAAM,MAAM,SAAS,eAAe,CAAC,MAAM,CAAC;AAC9D,QAAI,OAAO,GAAG;AACV;AAAA,IACJ;AACA,QAAI,MAAM,YAAY,MAAM;AACxB,YAAM,GAAG,SAAS,MAAM,MAAM,SAAS,MAAM,MAAM,CAAC,MAAM,CAAC;AAAA,IAC/D,WAAW,MAAM,mBAAmB,MAAM;AACtC,YAAM,KAAK,SAAS,MAAM,MAAM,gBAAgB,MAAM,UAAU,CAAC,CAAC,CAAC;AAAA,IACvE;AACA,QAAI,OAAO,GAAG;AACV;AAAA,IACJ;AACA,UAAM,UAAU,gBAAgB,MAAM,MAAM,GAAG,MAAM;AACrD,QAAI,OAAO,GAAG;AACV;AAAA,IACJ;AACA,UAAM,UAAU,oBAAoB,MAAM,MAAM;AAChD,QAAI,OAAO,GAAG;AACV;AAAA,IACJ;AACA,UAAM,GAAG,SAAS,MAAM,MAAM,SAAS,MAAM,MAAM,CAAC,MAAM,CAAC;AAC3D,QAAI,OAAO,GAAG;AACV;AAAA,IACJ;AAEA,SAAK,WAAW;AAChB,UAAM,YAAY,MAAM,KAAK,cAAc;AAC3C,UAAM,QAAQ,SAAS,WAAW,MAAM,cAAc,MAAM,MAAM,CAAC,MAAM,CAAC;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,OAA0B;AAC7B,UAAM,IAAI,SAAS,CAAC;AACpB,UAAM,IAAI,mBAAmB,CAAC;AAC9B,UAAM,IAAI,SAAS,CAAC;AACpB,UAAM,IAAI,YAAY,CAAC;AACvB,SAAK,gBAAgB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,OAA0B;AAC/B,QAAI,KAAK,cAAc,GAAG;AACtB,YAAM,IAAI,SAAS,CAAC;AACpB,YAAM,IAAI,YAAY,CAAC;AAAA,IAC3B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,YAAY,OAAoC,OAA0B;AACtE,UAAM,OAAO,0BAA0B,OAAO,KAAK,OAAO;AAC1D,UAAM,aACF,KAAK,WAAW,KAAK,QAAQ,UAC7B,KAAK,kBAAkB,KAAK,QAAQ,iBACpC,KAAK,sBAAsB,KAAK,QAAQ;AAC5C,SAAK,UAAU;AACf,QAAI,YAAY;AACZ,YAAM,IAAI,SAAS,CAAC;AACpB,YAAM,IAAI,mBAAmB,CAAC;AAAA,IAClC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,OAAiB,OAAmC;AAC1D,UAAM,SAAS,UAAU,KAAK,KAAK;AACnC,UAAM,WAAW,OAAO,QAAQ,UAAU;AAC1C,UAAM,UAAoC,CAAA;AAC1C,UAAM,QAAQ,KAAK,MAAM,MAAM,aAAa,kBAAkB;AAC9D,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC5B,YAAM,SAAS,UAAU,KAAK,OAAO,IAAI,kBAAkB;AAC3D,cAAQ,KAAK;AAAA,QACT,OAAO,OAAO,QAAQ,OAAO;AAAA,QAC7B,UAAU,OAAO,QAAQ,UAAU;AAAA,QACnC,OAAO,OAAO,QAAQ,OAAO;AAAA,QAC7B,iBAAiB,OAAO,QAAQ,iBAAiB;AAAA,QACjD,kBAAkB,OAAO,QAAQ,kBAAkB;AAAA,QACnD,cAAc,OAAO,QAAQ,cAAc;AAAA,MAAA,CAC9C;AAAA,IACL;AACA,WAAO;AAAA,MACH,WAAW,OAAO,QAAQ,WAAW;AAAA,MACrC,kBAAkB,OAAO,QAAQ,kBAAkB;AAAA,MACnD,WAAW,OAAO,QAAQ,WAAW;AAAA,MACrC,cAAc,OAAO,QAAQ,QAAQ;AAAA,MACrC,UAAU,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;AAAA,MAChD,eAAe;AAAA,MACf,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,OAAO,OAAO,QAAQ,OAAO;AAAA,MAC7B,UAAU,OAAO,QAAQ,UAAU;AAAA,MACnC,OAAO,OAAO,QAAQ,OAAO;AAAA,MAC7B,iBAAiB,OAAO,QAAQ,iBAAiB;AAAA,MACjD,OAAO;AAAA,IAAA;AAAA,EAEf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmC;AACvC,QAAI,KAAK,cAAc,MAAM;AACzB,YAAM,IAAI,iBAAiB,gBAAgB,2DAA2D;AAAA,QAClG,OAAO;AAAA,MAAA,CACV;AAAA,IACL;AACA,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,WAAW,MAAsB;AACrC,aAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AACxC,UAAI,WAAW,CAAC,MAAM,MAAM;AACxB,eAAO;AAAA,MACX;AAAA,IACJ;AACA,UAAM,QAAQ,QAAQ,MAAM,WAAW,KAAK,KAAK,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAkB;AACtB,SAAK,WAAW;AAChB,UAAM,EAAE,UAAU;AAClB,QAAI,UAAU,MAAM;AAChB;AAAA,IACJ;AACA,eAAW,UAAU,CAAC,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,SAAS,MAAM,IAAI,GAAG;AAC5E,aAAO,WAAA;AAAA,IACX;AACA,SAAK,QAAQ;AAAA,EACjB;AACJ;AAWA,SAAS,aAAa,OAAoC,SAAiD;AACvG,SAAO,0BAA0B,OAAO,0BAA0B,OAAO,CAAC;AAC9E;AASO,SAAS,kBACZ,KACA,SACyD;AACzD,MAAI,YAAA;AACJ,QAAM,WAAW,0BAA0B,OAAO;AAClD,QAAM,SAAS,oBAAoB,OAAO;AAC1C,QAAM,QAAQ,IAAI,iBAAiB,QAAQ,QAAQ;AACnD,SAAO,IAAI,gBAAsD,KAAK,OAAO,UAAU,QAAQ,YAAY;AAC/G;AC/4BA,SAAS,gBAAgB,UAAoD;AACzE,QAAM,OAA4E,EAAE,GAAG,SAAA;AACvF,MAAI,SAAS,YAAY,QAAW;AAChC,SAAK,UAAU,OAAO,OAAO,CAAC,GAAG,SAAS,OAAO,CAAC;AAAA,EACtD;AACA,SAAO,OAAO,OAAO,IAAI;AAC7B;AAOA,SAAS,eAAe,YAAkD;AACtE,QAAM,OAA0D,EAAE,GAAG,WAAA;AACrE,MAAI,WAAW,gBAAgB,QAAW;AACtC,SAAK,cAAc,gBAAgB,WAAW,WAAW;AAAA,EAC7D;AACA,SAAO,OAAO,OAAO,IAAI;AAC7B;AAUA,SAAS,cAAc,SAAuE;AAC1F,MAAI,YAAY,QAAW;AACvB,WAAO,OAAO,OAAO,EAAE;AAAA,EAC3B;AACA,QAAM,OAA6F,EAAE,GAAG,QAAA;AACxG,MAAI,QAAQ,WAAW,QAAW;AAC9B,SAAK,SAAS,OAAO,OAAO,EAAE,GAAG,QAAQ,QAAQ;AAAA,EACrD;AACA,MAAI,QAAQ,eAAe,QAAW;AAClC,SAAK,aAAa,eAAe,QAAQ,UAAU;AAAA,EACvD;AACA,SAAO,OAAO,OAAO,IAAI;AAC7B;AAeO,SAAS,kBAAkB,KAAiB,SAA8C;AAC7F,MAAI,YAAA;AACJ,QAAM,SAAS,cAAc,OAAO;AACpC,SAAO;AAAA,IACH,MAAM;AAAA,IACN;AAAA,IACA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMT,YAAY,GAAmF;AAC3F,UAAI,YAAA;AACJ,aAAO,kBAAkB,KAAK,EAAE,GAAG,GAAG,GAAG,OAAO,QAAQ;AAAA,IAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,QAAQ,GAAwB;AAC5B,UAAI,QAAQ,CAAC;AAAA,IACjB;AAAA;AAAA;AAAA;AAAA,IAIA,UAAgB;AACZ,UAAI,QAAA;AAAA,IACR;AAAA,EAAA;AAER;"}
1
+ {"version":3,"file":"webgpu-graph-algorithms.js","sources":["../src/kernel/dispatch.ts","../src/kernel/struct-block.ts","../src/wgsl/degree.wgsl.ts","../src/wgsl/fa2-attraction.wgsl.ts","../src/wgsl/fa2-integrate.wgsl.ts","../src/wgsl/fa2-repulsion-exact.wgsl.ts","../src/wgsl/fa2-speed-finalize.wgsl.ts","../src/wgsl/fa2-stats-finalize.wgsl.ts","../src/wgsl/fa2-to-scene.wgsl.ts","../src/wgsl/fill.wgsl.ts","../src/wgsl/pr-finalize.wgsl.ts","../src/wgsl/pr-scale.wgsl.ts","../src/wgsl/reduce.wgsl.ts","../src/wgsl/segmented-reduce.wgsl.ts","../src/wgsl/spmv-pull.wgsl.ts","../src/wgsl/wcc-compress.wgsl.ts","../src/wgsl/wcc-link-edges.wgsl.ts","../src/wgsl/wcc-link-sample.wgsl.ts","../src/wgsl/wcc-sample.wgsl.ts","../src/kernels.ts","../src/algorithms/degree.ts","../src/kernel/batch.ts","../src/kernel/uniform-ring.ts","../src/algorithms/scope.ts","../src/algorithms/components.ts","../src/primitives/core-shape.ts","../src/primitives/segmented-reduce.ts","../src/primitives/spmv.ts","../src/algorithms/pagerank.ts","../src/algorithms/power-iteration.ts","../src/algorithms/spectral.ts","../src/layouts/seed.ts","../src/layouts/force-simulation.ts","../src/layouts/inputs.ts","../src/layouts/repulsion-exact.ts","../src/layouts/forceatlas2.ts","../src/accelerator.ts"],"sourcesContent":["/**\n * Dispatch planning (spec 5.2; contract 3.9): the 16,776,960 rule. `ceil(items / wg)` workgroups as a 1D dispatch\n * while the count fits one dimension (65,535 groups x 256 = 16,776,960 items, NOT 2^24), else a 2D grid whose\n * kernels linearise their id with the prelude's `linear_id()` and guard `id >= items`. Pure functions with no\n * device: every branch is unit-tested against faked capability tables.\n */\n\nimport { MAX_WORKGROUPS_PER_DIM } from \"../constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type PlanCaps } from \"../types/context.js\";\n\n/** A dispatch shape (spec 5.2). `stride` is the grid-stride step (null for plain 1D / 2D plans). */\nexport interface DispatchPlan {\n readonly x: number;\n readonly y: number;\n readonly z: 1;\n readonly items: number;\n readonly stride: number | null;\n}\n\n/**\n * The per-dimension workgroup limit a plan honours. PLAN DECISION: the minimum of the spec constant and the table's\n * `maxComputeWorkgroupsPerDimension`; the two are asserted equal on a real device at create() (spec 2.2), so every\n * capability table of the tests yields the same plans and a faked table below the constant is still honoured.\n * @param caps - the capability table\n * @returns the limit\n */\nfunction perDimension(caps: PlanCaps): number {\n return Math.min(MAX_WORKGROUPS_PER_DIM, caps.limits.maxComputeWorkgroupsPerDimension);\n}\n\n/**\n * Validates a non-negative integer argument.\n * @param argument - the argument name\n * @param value - the value\n */\nfunction assertCount(argument: string, value: number): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${argument} must be a non-negative integer, got ${value}`, {\n argument,\n value,\n expected: \"a non-negative integer\",\n });\n }\n}\n\n/**\n * Validates a workgroup size: a power of two >= 1 (the reduction trees of 4.3 need it). Arithmetic, no bit tricks.\n * @param wg - the workgroup size\n */\nfunction assertWorkgroupSize(wg: number): void {\n let rest = wg;\n while (Number.isInteger(rest) && rest > 1 && rest % 2 === 0) {\n rest /= 2;\n }\n if (rest !== 1) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `wg must be a power of two, got ${wg}`, {\n argument: \"wg\",\n value: wg,\n expected: \"a power of two >= 1\",\n });\n }\n}\n\n/**\n * The grid of `groups` workgroups: 1D up to the per-dimension limit, else `x = limit`, `y = ceil(groups / limit)`.\n * @param groups - the workgroup count\n * @param items - the item count the plan covers (recorded in the plan)\n * @param caps - the capability table\n * @returns the plan\n */\nfunction grid(groups: number, items: number, caps: PlanCaps): DispatchPlan {\n const limit = perDimension(caps);\n if (groups === 0) {\n return { x: 0, y: 1, z: 1, items, stride: null };\n }\n if (groups <= limit) {\n return { x: groups, y: 1, z: 1, items, stride: null };\n }\n const y = Math.ceil(groups / limit);\n if (y > limit) {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `${groups} workgroups exceed the 2D dispatch limit of ${limit * limit}`,\n {\n needed: groups,\n limit: limit * limit,\n path: \"dispatch\",\n algorithm: null,\n items,\n },\n );\n }\n return { x: limit, y, z: 1, items, stride: null };\n}\n\n/**\n * ceil(items / wg) groups as 1D up to MAX_WORKGROUPS_PER_DIM, else a 2D grid; items 0 -> { x: 0, y: 1 }; y above the limit -> E_TOO_LARGE.\n * @param items - the item count\n * @param wg - the workgroup size (a power of two)\n * @param caps - the capability table\n * @returns the plan\n */\nexport function plan1d(items: number, wg: number, caps: PlanCaps): DispatchPlan {\n assertCount(\"items\", items);\n assertWorkgroupSize(wg);\n return grid(Math.ceil(items / wg), items, caps);\n}\n\n/**\n * The 2D form for a group count (x = MAX_WORKGROUPS_PER_DIM, y = ceil(groups / x)); exported for the indirect finalize kernel's host twin (P4).\n * PLAN DECISION: plan1d's rule applied to a group count (spec 5.4: the finalize kernel uses \"the same rule as\n * plan1d\") -- 1D `{ x: groups, y: 1 }` up to the per-dimension limit and the `x = limit` split only above it, through\n * the same `grid()` as plan1d so the two cannot drift; P4's finalize WGSL mirrors exactly this rule. `items` of the\n * returned plan is `groups` (the caller knows its own wg); groups 0 -> { x: 0, y: 1 }.\n * @param groups - the workgroup count\n * @param caps - the capability table\n * @returns the plan\n */\nexport function plan2d(groups: number, caps: PlanCaps): DispatchPlan {\n assertCount(\"groups\", groups);\n return grid(groups, groups, caps);\n}\n\n/**\n * P7 (spec 5.2): groups = min(ceil(items / wg), maxGroups ?? (caps.software ? 64 : 4096), the per-dimension limit) with the kernel looping by `stride = groups * wg`; items 0 -> { x: 0, stride: null }.\n * The cap is the ONE performance default in src/ that may read `caps.software` (spec 2.4, 5.2): a grid-stride map is\n * order-independent, so the result never depends on it and the same body serves both adapters.\n * PLAN DECISION: `maxGroups?` is spelled `?: number` rather than the contract's `?: number | undefined` because the\n * root ESLint rule no-duplicate-type-constituents rejects the explicit undefined on an optional parameter (the call\n * signature is identical).\n * @param items - the item count\n * @param wg - the workgroup size\n * @param caps - the capability table\n * @param maxGroups - the group cap\n * @returns the plan\n */\nexport function planGridStride(items: number, wg: number, caps: PlanCaps, maxGroups?: number): DispatchPlan {\n assertCount(\"items\", items);\n assertWorkgroupSize(wg);\n if (items === 0) {\n return { x: 0, y: 1, z: 1, items, stride: null };\n }\n const cap = Math.min(maxGroups ?? (caps.software ? 64 : 4096), perDimension(caps));\n const groups = Math.min(Math.ceil(items / wg), cap);\n return { x: groups, y: 1, z: 1, items, stride: groups * wg };\n}\n\n/**\n * P4 (spec 5.4): the (x, y, 1) args a device-side finalize kernel writes for a count. P1-P3: throws E_UNSUPPORTED { feature: \"planIndirect\" } (lead f).\n * @param count - the device-side count\n * @param wg - the workgroup size\n * @param caps - the capability table\n */\nexport function planIndirect(count: number, wg: number, caps: PlanCaps): DispatchPlan {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"planIndirect lands with the indirect dispatch of P4 (spec 5.4)\", {\n feature: \"planIndirect\",\n hint: `count ${count}, wg ${wg}, limit ${perDimension(caps)}`,\n });\n}\n\n/**\n * The workgroup count of a plan (x * y).\n * @param plan - the plan\n * @returns the count\n */\nexport function groupsOf(plan: DispatchPlan): number {\n return plan.x * plan.y;\n}\n","/**\n * UniformBlock (spec 5.3, D20): one field table generates BOTH the padded WGSL `struct` text spliced into a module\n * and the byte writer / reader the host uses, so the two cannot disagree. The layout is the strict WGSL layout\n * every runtime accepts (Chromium 139 lacks `uniform_buffer_standard_layout`): scalars 4-aligned, vec2 8-aligned,\n * vec4 16-aligned, no vec3, no bool, no arrays, and the total padded to a multiple of 16 (or to `padTo`) through an\n * explicit `@size` on the last member.\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { WGSL_RESERVED_WORDS } from \"./prelude.js\";\n\n/** Field types a block may hold; no vec3 (spec 5.3), no bool (not host-shareable), no arrays. */\nexport type UniformFieldType = \"u32\" | \"i32\" | \"f32\" | \"vec2f\" | \"vec2u\" | \"vec4f\" | \"vec4u\";\n/** One field. */\nexport type UniformField = readonly [name: string, type: UniformFieldType];\n/** The values written into or read from a block: scalars as numbers, vectors as number arrays of the vector's width. */\nexport type UniformValues = Readonly<Record<string, number | readonly number[]>>;\n\n/** The scalar a field is made of. */\ntype ScalarKind = \"u32\" | \"i32\" | \"f32\";\n\n/** Size, alignment and composition of each field type (WGSL 14.4.1). */\ninterface TypeInfo {\n readonly size: number;\n readonly align: number;\n readonly width: number;\n readonly scalar: ScalarKind;\n}\n\nconst TYPE_INFO: Readonly<Record<UniformFieldType, TypeInfo>> = Object.freeze({\n u32: { size: 4, align: 4, width: 1, scalar: \"u32\" },\n i32: { size: 4, align: 4, width: 1, scalar: \"i32\" },\n f32: { size: 4, align: 4, width: 1, scalar: \"f32\" },\n vec2f: { size: 8, align: 8, width: 2, scalar: \"f32\" },\n vec2u: { size: 8, align: 8, width: 2, scalar: \"u32\" },\n vec4f: { size: 16, align: 16, width: 4, scalar: \"f32\" },\n vec4u: { size: 16, align: 16, width: 4, scalar: \"u32\" },\n});\n\n/** One laid-out field. */\ninterface FieldLayout {\n readonly name: string;\n readonly type: UniformFieldType;\n readonly offset: number;\n readonly info: TypeInfo;\n}\n\nconst STRUCT_ALIGN = 16;\nconst IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst U32_LIMIT = 0xffffffff;\nconst I32_MIN = -2147483648;\nconst I32_MAX = 2147483647;\n\n/**\n * Rounds `value` up to the next multiple of `align` (arithmetic, never a bit trick: byte offsets are never operated\n * on bitwise, spec 3.6).\n * @param value - the value to round\n * @param align - the alignment, a positive integer\n * @returns the rounded value\n */\nfunction roundUp(value: number, align: number): number {\n return Math.ceil(value / align) * align;\n}\n\n/**\n * Validates a WGSL identifier for a struct or field name.\n * @param argument - the E_INVALID_ARGUMENT `argument` to report\n * @param name - the identifier\n */\nfunction assertIdentifier(argument: string, name: string): void {\n if (!IDENTIFIER.test(name) || WGSL_RESERVED_WORDS.includes(name)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock: \"${name}\" is not a usable WGSL identifier`, {\n argument,\n value: name,\n expected: \"a WGSL identifier that is not a reserved word\",\n });\n }\n}\n\n/**\n * Validates one scalar component of a value against its scalar kind.\n * @param field - the field name (for the error)\n * @param kind - the scalar kind\n * @param value - the component\n */\nfunction assertScalar(field: string, kind: ScalarKind, value: unknown): asserts value is number {\n if (typeof value !== \"number\") {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock: field \"${field}\" expects a number`, {\n argument: field,\n value,\n expected: kind,\n });\n }\n if (kind === \"u32\" && !(Number.isInteger(value) && value >= 0 && value <= U32_LIMIT)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock: field \"${field}\" is not a u32`, {\n argument: field,\n value,\n expected: \"an integer in [0, 4294967295]\",\n });\n }\n if (kind === \"i32\" && !(Number.isInteger(value) && value >= I32_MIN && value <= I32_MAX)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock: field \"${field}\" is not an i32`, {\n argument: field,\n value,\n expected: \"an integer in [-2147483648, 2147483647]\",\n });\n }\n}\n\n/**\n * Writes one scalar component little-endian.\n * @param view - the target view\n * @param kind - the scalar kind\n * @param offset - the byte offset\n * @param value - the component\n */\nfunction setScalar(view: DataView, kind: ScalarKind, offset: number, value: number): void {\n if (kind === \"u32\") {\n view.setUint32(offset, value, true);\n } else if (kind === \"i32\") {\n view.setInt32(offset, value, true);\n } else {\n view.setFloat32(offset, value, true);\n }\n}\n\n/**\n * Reads one scalar component little-endian.\n * @param view - the source view\n * @param kind - the scalar kind\n * @param offset - the byte offset\n * @returns the component\n */\nfunction getScalar(view: DataView, kind: ScalarKind, offset: number): number {\n if (kind === \"u32\") {\n return view.getUint32(offset, true);\n }\n if (kind === \"i32\") {\n return view.getInt32(offset, true);\n }\n return view.getFloat32(offset, true);\n}\n\n/** A generated struct: the padded WGSL text and the byte writer / reader share one field table, so they cannot disagree (D20). */\nexport class UniformBlock {\n /** The WGSL struct name. */\n readonly name: string;\n /** \"uniform\" (the default) or \"storage\"; both lay out identically, the tag documents the block's address space. */\n readonly layout: \"uniform\" | \"storage\";\n /** The fields in declaration (= byte) order. */\n readonly fields: readonly UniformField[];\n /** The padded byte length (a multiple of 16). */\n readonly byteLength: number;\n /** The `struct <name> { ... }` text with explicit `@size` / `@align` where padding is needed. */\n readonly wgsl: string;\n /** The laid-out fields by name. */\n private readonly table: ReadonlyMap<string, FieldLayout>;\n /** The laid-out fields in order. */\n private readonly laidOut: readonly FieldLayout[];\n\n /**\n * Declares a block; fields are laid out in order with 16-byte alignment for vec4 / the struct, 8 for vec2, 4 for\n * scalars; the total is padded to 16 (uniform, storage) or to `padTo` when given.\n * PLAN DECISION: rejects an empty field list and a struct or field name that is not a WGSL identifier or is a\n * reserved word (spec 3.6: every throwing call leaves state unchanged; a reserved name would be invalid WGSL).\n * PLAN DECISION: optional PARAMETERS (`options?` here, `byteOffset?` of write / read / readField) are spelled\n * `?: T` rather than the contract's `?: T | undefined` because the root ESLint rule\n * no-duplicate-type-constituents rejects the explicit undefined on an optional parameter; every call site is\n * identical, and optional PROPERTIES keep `?: T | undefined`.\n * @param name - the WGSL struct name\n * @param fields - the fields in byte order\n * @param options - the layout tag and the optional padding\n * @param options.layout - \"uniform\" (default) or \"storage\"; the tag documents the address space, the layout is the same\n * @param options.padTo - the byte length to pad to (a multiple of 16 not below the natural size)\n * @returns the block\n */\n static define(\n name: string,\n fields: readonly UniformField[],\n options?: { readonly layout?: \"uniform\" | \"storage\" | undefined; readonly padTo?: number | undefined },\n ): UniformBlock {\n assertIdentifier(\"name\", name);\n if (fields.length === 0) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock ${name}: a block needs at least one field`, {\n argument: \"fields\",\n value: fields.length,\n expected: \">= 1 field\",\n });\n }\n const laidOut: FieldLayout[] = [];\n const table = new Map<string, FieldLayout>();\n let cursor = 0;\n for (const [fieldName, type] of fields) {\n assertIdentifier(\"fields\", fieldName);\n if (table.has(fieldName)) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformBlock ${name}: duplicate field \"${fieldName}\"`,\n {\n argument: \"fields\",\n value: fieldName,\n expected: \"unique field names\",\n },\n );\n }\n const info = TYPE_INFO[type] as TypeInfo | undefined;\n if (info === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock ${name}: unknown field type \"${type}\"`, {\n argument: \"fields\",\n value: type,\n expected: Object.keys(TYPE_INFO).join(\" | \"),\n });\n }\n const offset = roundUp(cursor, info.align);\n const field: FieldLayout = { name: fieldName, type, offset, info };\n laidOut.push(field);\n table.set(fieldName, field);\n cursor = offset + info.size;\n }\n const natural = roundUp(cursor, STRUCT_ALIGN);\n const padTo = options?.padTo;\n if (padTo !== undefined && (!Number.isInteger(padTo) || padTo % STRUCT_ALIGN !== 0 || padTo < natural)) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformBlock ${name}: padTo ${padTo} is not a multiple of 16 >= ${natural}`,\n {\n argument: \"padTo\",\n value: padTo,\n expected: `a multiple of ${STRUCT_ALIGN} not below ${natural}`,\n },\n );\n }\n const byteLength = padTo ?? natural;\n const lines = laidOut.map((field, index) => {\n const last = index === laidOut.length - 1;\n const end = field.offset + field.info.size;\n const size = last && end < byteLength ? `@size(${byteLength - field.offset}) ` : \"\";\n return ` ${size}${field.name}: ${field.type},`;\n });\n const wgsl = `struct ${name} {\\n${lines.join(\"\\n\")}\\n}`;\n return new UniformBlock(name, options?.layout ?? \"uniform\", fields, byteLength, wgsl, laidOut, table);\n }\n\n /**\n * Built by `define()` only.\n * @param name - the struct name\n * @param layout - the address-space tag\n * @param fields - the declared fields\n * @param byteLength - the padded byte length\n * @param wgsl - the struct text\n * @param laidOut - the laid-out fields in order\n * @param table - the laid-out fields by name\n */\n private constructor(\n name: string,\n layout: \"uniform\" | \"storage\",\n fields: readonly UniformField[],\n byteLength: number,\n wgsl: string,\n laidOut: readonly FieldLayout[],\n table: ReadonlyMap<string, FieldLayout>,\n ) {\n this.name = name;\n this.layout = layout;\n this.fields = Object.freeze(fields.map(([fieldName, type]) => Object.freeze([fieldName, type] as const)));\n this.byteLength = byteLength;\n this.wgsl = wgsl;\n this.laidOut = laidOut;\n this.table = table;\n }\n\n /**\n * Byte offset of a field; E_INVALID_ARGUMENT for an unknown field.\n * @param field - the field name\n * @returns the byte offset inside the block\n */\n offsetOf(field: string): number {\n return this.fieldLayout(field).offset;\n }\n\n /**\n * Writes `values` at `byteOffset` (default 0); a missing field is written as 0; an unknown key is\n * E_INVALID_ARGUMENT; a vector of the wrong width is E_INVALID_ARGUMENT. Always little-endian. Every byte of the\n * block's region is written (padding as zero), so a written block is byte-exact.\n * PLAN DECISION: every value is validated first (u32 / vec*u components integers in [0, 2^32 - 1], i32 in\n * [-2^31, 2^31 - 1]) and only then is the region zeroed and written, so a rejected call leaves the view unchanged.\n * @param view - the target view (the region must lie inside it)\n * @param values - the field values\n * @param byteOffset - the region's start inside the view\n */\n write(view: DataView, values: UniformValues, byteOffset?: number): void {\n const base = this.regionStart(view, byteOffset);\n for (const key of Object.keys(values)) {\n if (!this.table.has(key)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock ${this.name}: unknown field \"${key}\"`, {\n argument: \"values\",\n value: key,\n expected: this.laidOut.map((f) => f.name).join(\", \"),\n });\n }\n }\n // validate every value first, so a rejected call leaves the view unchanged (spec 3.6)\n const components: (readonly number[] | null)[] = this.laidOut.map((field) =>\n this.components(field, values[field.name]),\n );\n for (let at = 0; at < this.byteLength; at += 4) {\n view.setUint32(base + at, 0, true);\n }\n this.laidOut.forEach((field, index) => {\n const lanes = components[index];\n if (lanes === null) {\n return;\n }\n lanes.forEach((component, lane) => {\n setScalar(view, field.info.scalar, base + field.offset + 4 * lane, component);\n });\n });\n }\n\n /**\n * The validated components of one field's value: null for an absent field, else `width` numbers.\n * @param field - the laid-out field\n * @param value - the value given for it (undefined when absent)\n * @returns the components or null\n */\n private components(field: FieldLayout, value: number | readonly number[] | undefined): readonly number[] | null {\n if (value === undefined) {\n return null;\n }\n const { scalar, width } = field.info;\n if (width === 1) {\n assertScalar(field.name, scalar, value);\n return [value];\n }\n if (!Array.isArray(value) || value.length !== width) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformBlock ${this.name}: field \"${field.name}\" expects ${width} components`,\n {\n argument: field.name,\n value,\n expected: `an array of ${width} numbers`,\n },\n );\n }\n const lanes: number[] = [];\n for (let lane = 0; lane < width; lane++) {\n const component: unknown = value[lane];\n assertScalar(field.name, scalar, component);\n lanes.push(component);\n }\n return lanes;\n }\n\n /**\n * Reads every field at `byteOffset` (storage mode's reader; also used by tests on uniform blocks).\n * @param view - the source view\n * @param byteOffset - the region's start inside the view\n * @returns the field values (vectors as arrays)\n */\n read(view: DataView, byteOffset?: number): UniformValues {\n const base = this.regionStart(view, byteOffset);\n const out: Record<string, number | readonly number[]> = {};\n for (const field of this.laidOut) {\n out[field.name] = this.decode(view, field, base);\n }\n return out;\n }\n\n /**\n * Reads one field.\n * @param view - the source view\n * @param field - the field name\n * @param byteOffset - the region's start inside the view\n * @returns the value (a number, or an array for a vector)\n */\n readField(view: DataView, field: string, byteOffset?: number): number | readonly number[] {\n const layout = this.fieldLayout(field);\n return this.decode(view, layout, this.regionStart(view, byteOffset));\n }\n\n /**\n * The laid-out field of a name.\n * @param field - the field name\n * @returns the layout\n */\n private fieldLayout(field: string): FieldLayout {\n const layout = this.table.get(field);\n if (layout === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `UniformBlock ${this.name}: unknown field \"${field}\"`, {\n argument: \"field\",\n value: field,\n expected: this.laidOut.map((f) => f.name).join(\", \"),\n });\n }\n return layout;\n }\n\n /**\n * Validates the region `[byteOffset, byteOffset + byteLength)` against the view.\n * @param view - the view\n * @param byteOffset - the requested start (default 0)\n * @returns the start\n */\n private regionStart(view: DataView, byteOffset: number | undefined): number {\n const base = byteOffset ?? 0;\n if (!Number.isInteger(base) || base < 0 || base + this.byteLength > view.byteLength) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformBlock ${this.name}: region [${base}, ${base + this.byteLength}) is outside the view`,\n {\n argument: \"byteOffset\",\n value: base,\n expected: `0 <= byteOffset <= ${view.byteLength - this.byteLength}`,\n },\n );\n }\n return base;\n }\n\n /**\n * Decodes one field from a view.\n * @param view - the source view\n * @param field - the laid-out field\n * @param base - the region start\n * @returns the value\n */\n private decode(view: DataView, field: FieldLayout, base: number): number | readonly number[] {\n const { scalar, width } = field.info;\n if (width === 1) {\n return getScalar(view, scalar, base + field.offset);\n }\n const lanes: number[] = [];\n for (let lane = 0; lane < width; lane++) {\n lanes.push(getScalar(view, scalar, base + field.offset + 4 * lane));\n }\n return lanes;\n }\n}\n","/**\n * The `degree` kernel body (contract 4.5; spec 6 row 3, 11.5): the out-degree of every row of `[P.start, P.end)`\n * through the row-walking gather with the USE_PERM dummy pattern, counting the arcs of the bound window whose\n * neighbour index is a valid node; `P.accumulate == 1` adds into `out[i]` instead of overwriting (the P4 windowed\n * loop). Bindings, overrides and the `RangeParams` block come from the registry entry (src/kernels.ts); WG,\n * USE_PERM and `linear_id` from the prelude. The text is normative: test/helpers/sabotage.ts mutates it textually,\n * so it is copied from the contract and never re-derived or restyled.\n */\nexport const degreeWgsl = /* wgsl */ `\n@compute @workgroup_size(WG)\nfn degree(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let row = linear_id(wid, lid.x) + P.start;\n if (row >= P.end) { return; }\n let i = select(row, perm[row], USE_PERM);\n let a0 = max(rowPtr[i], P.arcBase);\n let a1 = min(rowPtr[i + 1u], P.arcEnd);\n var d = 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); never use it as an identifier\n d = d + select(0u, 1u, nbr < P.n);\n }\n out[i] = select(d, out[i] + d, P.accumulate == 1u);\n}\n`;\n","/**\n * K2 of the ForceAtlas2 iteration, `fa2-attraction` (spec 7.5; contract 4.5): the thread-per-row gather of the\n * attraction force over the undirected CSR rows (both arcs present, so the sum is symmetric with no atomics), the\n * linear or linlog law, the optional weights, the distributed-action division by the mass in `pos.w`, written as\n * the FIRST writer of `force` each iteration. P3 ships the thread-per-row tier over `[tierStart, tierEnd)` = `[0, n)`\n * with `USE_PERM = false`; the subgroup / workgroup tiers arrive with P4 (`TIER`).\n *\n * Body only (spec 3.5, D9); normative text (contract 4.5); the K2 sabotage mutations (P3-T5) are textual edits of it.\n */\n\n/** The K2 body: entry point `attraction`; an early return is legal here because no barrier follows (spec 3.5 rule 1). */\nexport const fa2AttractionWgsl = /* wgsl */ `fn store_force(i: u32, f: vec3f) {\n force[3u * i] = f.x;\n force[3u * i + 1u] = f.y;\n force[3u * i + 2u] = f.z;\n}\n\n@compute @workgroup_size(WG)\nfn attraction(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let row = linear_id(wid, lid.x) + P.tierStart;\n if (row >= P.tierEnd) { return; } // no barrier follows in this tier (3.5 rule 1)\n let i = select(row, perm[row], USE_PERM);\n let pi = pos[i]; // xyz + mass in one load (D23)\n var f = vec3f(0.0);\n for (var a = rowPtr[i]; a < rowPtr[i + 1u]; a = a + 1u) {\n let j = colIdx[a];\n if (j == i) { continue; } // a self-loop exerts no force\n var w = 1.0;\n if (HAS_WEIGHTS) { w = weights[a]; }\n let d = pos[j].xyz - pi.xyz; // toward j\n let len = max(length(d), FA2_DIST_FLOOR);\n let mag = select(w, w * log(1.0 + len) / len, LINLOG); // linear: |F| = w len; linlog: |F| = w log(1 + len)\n f = f + d * mag;\n }\n if (DISTRIBUTED) { f = f / pi.w; }\n store_force(i, f); // overwrites: attraction is the first writer of force each iteration\n}`;\n","/**\n * K5 of the ForceAtlas2 iteration, `fa2-integrate` (spec 7.11; contract 4.5): the per-node speed factor\n * `speed / (1 + sqrt(speed * swing_i))` with the local swing recomputed inline (paper mode `m |F(t) - F(t-1)|`,\n * networkx mode `m |F|`, contract 4.6), the position update with no displacement clamp (D25), z never integrated\n * in 2D (spec 7.13), `oldForce` stored in paper mode for fixed nodes too (spec 7.11), and the partials A\n * (sum p, sum |p - c|^2, min, max with max |p - c|^2 in `max.w`) and C (sum |dp| over free rows, free count) in\n * uniform control flow.\n *\n * Body only (spec 3.5, D9); normative text (contract 4.5); the K5 sabotage mutations (P3-T5) are textual edits of it.\n */\n\n/** The K5 body: entry point `integrate`; calls the reduction helpers (`needs: [\"subgroups\"]`, contract 4.3). */\nexport const fa2IntegrateWgsl = /* wgsl */ `fn load_force(i: u32) -> vec3f { return vec3f(force[3u * i], force[3u * i + 1u], force[3u * i + 2u]); }\nfn load_old(i: u32) -> vec3f { return vec3f(oldForce[3u * i], oldForce[3u * i + 1u], oldForce[3u * i + 2u]); }\nfn store_old(i: u32, f: vec3f) {\n oldForce[3u * i] = f.x;\n oldForce[3u * i + 1u] = f.y;\n oldForce[3u * i + 2u] = f.z;\n}\n\n@compute @workgroup_size(WG)\nfn integrate(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n var dp = vec3f(0.0);\n var p = vec4f(0.0);\n var free = false;\n var valid = false;\n if (i < P.n) {\n valid = true;\n let f = load_force(i);\n p = pos[i];\n var swing_i = p.w * length(f); // SWING_MODE 1: NetworkX's local swinging m |F| (layout.py line 1497)\n if (SWING_MODE == 0u) { swing_i = p.w * length(f - load_old(i)); } // paper: m |F(t) - F(t-1)|, recomputed inline (7.2)\n let factor = S.speed / (1.0 + sqrt(S.speed * swing_i));\n let fixed = mask_bit(fixedMask[i >> 5u], i);\n dp = select(f * factor, vec3f(0.0), fixed); // no clamp on dp (D25)\n if (P.dim == 2u) { dp.z = 0.0; } // 2D never integrates z (7.13)\n p = vec4f(p.xyz + dp, p.w);\n pos[i] = p;\n if (SWING_MODE == 0u) { store_old(i, f); } // fixed nodes too, so a later unpin sees no stale swing (7.11)\n free = !fixed;\n }\n // uniform control flow from here (3.5 rule 1): partials A (sum p, sum |p - c|^2, min, max over valid rows) and C (sum |dp|, free count)\n let c = S.centroid.xyz;\n var sumv = vec4f(0.0);\n var lo = vec4f(F32_MAX);\n var hi = vec4f(-F32_MAX);\n var dl = 0.0;\n var fr = 0u;\n if (valid) {\n let q = p.xyz - c;\n sumv = vec4f(p.xyz, dot(q, q));\n lo = vec4f(p.xyz, 0.0);\n hi = vec4f(p.xyz, dot(q, q)); // max.w carries max |p - c|^2 so K1 can write the exact layoutRadius (spec 3.3)\n }\n if (free) { dl = length(dp); fr = 1u; }\n let tSum = wg_reduce_vec4(sumv, lid.x, 0u);\n let tLo = wg_reduce_vec4(lo, lid.x, 1u);\n let tHi = wg_reduce_vec4(hi, lid.x, 2u);\n let tDl = wg_reduce_f32(dl, lid.x, 0u);\n let tFr = wg_reduce_u32(fr, lid.x, 0u);\n if (lid.x == 0u) {\n let g = group_id(wid);\n partials[g].sum = tSum;\n partials[g].min = tLo;\n partials[g].max = tHi;\n partials[g].dispFree = vec2f(tDl, f32(tFr));\n }\n}`;\n","/**\n * The `fa2-repulsion-exact` kernel body (K3; contract 4.5; spec 7.6, 7.9, 7.10): the tiled all-pairs repulsion\n * `|F| = k m_i m_j / d` with the 0.01 distance floor and the antisymmetric coincident kick, the gravity epilogue\n * (GRAVITY_CENTER 0 = centroid, 1 = origin; STRONG_GRAVITY) added under the `valid` guard, `force += f`, and the\n * swing / traction workgroup reduction in uniform control flow (SWING_MODE 0 = paper: free nodes only against\n * `oldForce`; 1 = NetworkX: positions and forces mixed, every node) whose lane 0 writes\n * `partials[group].swingTraction`. `pos` is `array<vec4f>` with the mass in `.w`; `force` / `oldForce` are stride-3\n * `array<f32>` read through the per-body helpers (4.4 rule 6). Normative text, copied verbatim: the P1-T5 sabotage\n * rows (gravity sign, `k / d2`, the `jj != i` guard, the `.w` mass lane) are textual edits of this string.\n */\nexport const fa2RepulsionExactWgsl = /* wgsl */ `\nvar<workgroup> tile: array<vec4f, WG>; // xyz + mass, 4 KiB at WG = 256\n\nfn load_force(i: u32) -> vec3f { return vec3f(force[3u * i], force[3u * i + 1u], force[3u * i + 2u]); }\nfn store_force(i: u32, f: vec3f) {\n force[3u * i] = f.x;\n force[3u * i + 1u] = f.y;\n force[3u * i + 2u] = f.z;\n}\nfn load_old(i: u32) -> vec3f { return vec3f(oldForce[3u * i], oldForce[3u * i + 1u], oldForce[3u * i + 2u]); }\nfn gravity_force(pi: vec4f) -> vec3f { // spec 7.9: centroid (GRAVITY_CENTER 0) or origin (1); regular or strong\n var q = pi.xyz;\n if (GRAVITY_CENTER == 0u) { q = pi.xyz - S.centroid.xyz; }\n if (STRONG_GRAVITY) { return -P.gravity * pi.w * q; }\n let d = length(q);\n if (d > FA2_DIST_FLOOR) { return -P.gravity * pi.w * q / d; }\n return vec3f(0.0);\n}\n\n@compute @workgroup_size(WG)\nfn repulsion(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n let valid = i < P.n;\n var pi = vec4f(0.0);\n if (valid) { pi = pos[i]; }\n var f = vec3f(0.0);\n let tiles = (P.n + WG - 1u) / WG;\n for (var t = 0u; t < tiles; t = t + 1u) {\n let j = t * WG + lid.x;\n if (j < P.n) { tile[lid.x] = pos[j]; } else { tile[lid.x] = vec4f(0.0); } // guarded fill; mass 0 marks the pad\n workgroupBarrier(); // uniform: every invocation reaches it\n for (var s = 0u; s < WG; s = s + 1u) {\n let o = tile[s];\n let jj = t * WG + s;\n if (o.w > 0.0 && jj != i) { // mass > 0 for every real node, 0 for the pad\n let d = pi.xyz - o.xyz;\n var d2 = dot(d, d);\n if (d2 < FA2_COINCIDENT_SQ) { // coincident: antisymmetric unit kick of magnitude k m_i m_j / 0.01 (7.2)\n f = f + kick_dir(i, jj, P.dim) * (P.scalingRatio * pi.w * o.w / FA2_DIST_FLOOR);\n continue;\n }\n d2 = max(d2, FA2_DIST_FLOOR_SQ); // d >= 0.01\n let k = P.scalingRatio * pi.w * o.w;\n f = f + d * (k / d2); // |F| = k m_i m_j / d along d / d\n }\n }\n workgroupBarrier();\n }\n // epilogue (7.9, 7.10): gravity and force += under the guard, the swing / traction reduction outside it\n var sw = 0.0;\n var tr = 0.0;\n if (valid) {\n f = f + gravity_force(pi);\n let fnew = load_force(i) + f;\n store_force(i, fnew);\n if (SWING_MODE == 1u) { // NetworkX: positions and forces mixed, every node (7.2)\n sw = pi.w * length(pi.xyz - fnew);\n tr = 0.5 * pi.w * length(pi.xyz + fnew);\n } else if (!mask_bit(fixedMask[i >> 5u], i)) { // paper: free nodes only (Gephi ForceAtlas2.java 283-293)\n let fold = load_old(i);\n sw = pi.w * length(fnew - fold);\n tr = 0.5 * pi.w * length(fnew + fold);\n }\n }\n let t = wg_reduce_vec4(vec4f(sw, tr, 0.0, 0.0), lid.x, 0u); // uniform control flow: 256 -> 1\n if (lid.x == 0u) { partials[group_id(wid)].swingTraction = t.xy; }\n}\n`;\n","/**\n * The `fa2-speed-finalize` kernel body (K4; contract 4.5; spec 7.10): ONE workgroup sums `partials[*].swingTraction`\n * sequentially per lane (deterministic), reduces in uniform control flow, then lane 0 runs the line-for-line port\n * of the CPU `estimateFactor` (SWING_MODE 1 accumulates NetworkX's sums across iterations from S.swing / S.traction)\n * and writes `S.speed`, `S.speedEfficiency`, `S.swing`, `S.traction` and the four controller fields of\n * `T[P.iterationIndex]`. `target` is a WGSL reserved word, hence `targetSpeed`. Normative text, copied verbatim:\n * the P1-T5 sabotage rows (`* 0.5` -> `* 0.9`, the 1.3 rise, the swing / traction swap) are textual edits of it.\n * The halving predicate is `swing > 2.0 * tr`, the exact form of the port's `swing / traction > 2` (contract 4.5\n * CONTRACT DECISION K4-1, G3 finding G3-F6): every paper-mode first iteration after load() has oldForce = 0, so\n * traction is EXACTLY half the swing and the predicate sits on its knife edge; a multiplication by 2 and the\n * comparison are exact on every device, while WGSL grants f32 division 2.5 ULP and Dawn on NVIDIA returns 2 + 1 ulp\n * for 2.2% of the inputs x / (x / 2) (tmp/p3-fix/div-probe.mjs), which took the branch the CPU reference never takes.\n */\nexport const fa2SpeedFinalizeWgsl = /* wgsl */ `\n@compute @workgroup_size(WG)\nfn speed_finalize(@builtin(local_invocation_id) lid: vec3<u32>) {\n let groups = (P.n + WG - 1u) / WG;\n var st = vec2f(0.0);\n for (var g = lid.x; g < groups; g = g + WG) { st = st + partials[g].swingTraction; } // sequential per lane: deterministic\n let t = wg_reduce_vec4(vec4f(st, 0.0, 0.0), lid.x, 0u);\n if (lid.x == 0u) {\n var swing = t.x;\n var traction = t.y;\n if (SWING_MODE == 1u) { swing = S.swing + t.x; traction = S.traction + t.y; } // NetworkX accumulates across iterations from 1\n let n = f32(P.n);\n let optJitter = 0.05 * sqrt(n);\n let minJitter = sqrt(optJitter);\n let maxJitter = 10.0;\n let tr = max(traction, 1.0e-30); // guards the division only (7.10)\n let other = min(maxJitter, optJitter * traction / (n * n));\n var jitter = P.jitterTolerance * max(minJitter, other);\n var eff = S.speedEfficiency;\n if (swing > 2.0 * tr) { // swing / traction > 2 in the exact form (contract 4.5 CONTRACT DECISION K4-1: 2 x is exact, a WGSL f32 division is not)\n if (eff > 0.05) { eff = eff * 0.5; } // the CPU's conditional multiply (7.2)\n jitter = max(jitter, P.jitterTolerance);\n }\n let targetSpeed = select(jitter * eff * traction / swing, 1.0e30, swing == 0.0); // +Inf in the port; 1e30 gives the same min() below (\\`target\\` is reserved)\n if (swing > jitter * traction) {\n if (eff > 0.05) { eff = eff * 0.7; }\n } else if (S.speed < 1000.0) {\n eff = eff * 1.3;\n }\n S.speed = S.speed + min(targetSpeed - S.speed, 0.5 * S.speed);\n S.speedEfficiency = eff;\n S.swing = swing;\n S.traction = traction;\n T[P.iterationIndex].swing = swing;\n T[P.iterationIndex].traction = traction;\n T[P.iterationIndex].speed = S.speed;\n T[P.iterationIndex].speedEfficiency = eff;\n }\n}\n`;\n","/**\n * K1 of the ForceAtlas2 iteration, `fa2-stats-finalize` (spec 7.4; contract 4.5): one workgroup folds the partials\n * the previous integrate (K5) wrote into the state block -- centroid, RMS radius, layout radius (max |p - c|, the\n * exact spec 3.3 value from `partials.max.w`), bounding box, mean displacement over free nodes (0 when every node\n * is fixed), the settle counter -- increments the iteration counter and writes the K1 half of the trace record.\n * On the first iteration after load() (`FA2_FLAG_FIRST`) it folds nothing and keeps the host-written state.\n *\n * This file holds the kernel BODY only (spec 3.5, D9): no bind-group lines and no `override` lines -- the composer\n * emits them from the registry entry in src/kernels.ts (contract 3.10.1). The text is normative (contract 4.5) and\n * is the target of the K1 sabotage mutations (test/helpers/sabotage.ts, P3-T5); amend the contract before editing.\n */\n\n/** The K1 body: entry point `stats_finalize`; calls the reduction helpers (`needs: [\"subgroups\"]`, contract 4.3). */\nexport const fa2StatsFinalizeWgsl = /* wgsl */ `// K1: folds the previous integrate's partials into the state block (spec 7.4); one workgroup\n@compute @workgroup_size(WG)\nfn stats_finalize(@builtin(local_invocation_id) lid: vec3<u32>) {\n let groups = (P.n + WG - 1u) / WG;\n let fold = (P.flags & FA2_FLAG_FIRST) == 0u; // the first iteration after load() keeps the host-written state\n var sum = vec4f(0.0);\n var lo = vec4f(F32_MAX);\n var hi = vec4f(-F32_MAX);\n var disp = 0.0;\n var free = 0u;\n if (fold) {\n for (var g = lid.x; g < groups; g = g + WG) { // sequential per lane in index order: deterministic\n let q = partials[g];\n sum = sum + q.sum;\n lo = min(lo, q.min);\n hi = max(hi, q.max);\n disp = disp + q.dispFree.x;\n free = free + u32(q.dispFree.y);\n }\n }\n let tSum = wg_reduce_vec4(sum, lid.x, 0u);\n let tLo = wg_reduce_vec4(lo, lid.x, 1u);\n let tHi = wg_reduce_vec4(hi, lid.x, 2u);\n let tDisp = wg_reduce_f32(disp, lid.x, 0u);\n let tFree = wg_reduce_u32(free, lid.x, 0u);\n if (lid.x == 0u) {\n if (fold) {\n let n = f32(P.n);\n let c = tSum.xyz / n;\n S.centroid = vec4f(c, 0.0);\n S.rmsRadius = sqrt(max(tSum.w, 0.0) / n); // RMS radius about the previous centroid (7.17)\n S.min = vec4f(tLo.xyz, 0.0);\n S.max = vec4f(tHi.xyz, 0.0);\n S.radius = sqrt(max(tHi.w, 0.0)); // max |p - centroid| about the same previous centroid as rmsRadius (K5 puts |q|^2 in max.w)\n let meanDisp = select(tDisp / f32(tFree), 0.0, tFree == 0u); // all-fixed: 0, never NaN (7.4)\n S.meanDisplacement = meanDisp;\n S.settledCount = select(0u, S.settledCount + 1u, meanDisp <= P.settleThreshold * S.rmsRadius);\n }\n S.iteration = S.iteration + 1u;\n T[P.iterationIndex].meanDisplacement = S.meanDisplacement;\n T[P.iterationIndex].settledCount = S.settledCount;\n T[P.iterationIndex].iteration = S.iteration;\n }\n}`;\n","/**\n * The per-batch `fa2-to-scene` kernel (spec 7.13, 7.18; contract 4.5): unpacks the vec4f layout-unit positions into\n * the stride-3 scene array the staging copy reads back, applying `scale` and `center`; in 2D the third component is\n * `center.z` on every readback whatever z the device holds.\n *\n * Body only (spec 3.5, D9); normative text (contract 4.5); exempt from the sabotage matrix (SABOTAGE_EXEMPT: a wrong\n * toScene fails the exact-equality position tests directly).\n */\n\n/** The toScene body: entry point `to_scene`; an early return is legal here because no barrier follows (spec 3.5 rule 1). */\nexport const fa2ToSceneWgsl = /* wgsl */ `@compute @workgroup_size(WG)\nfn to_scene(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n if (i >= P.n) { return; }\n let s = pos[i].xyz * P.scale + P.center.xyz;\n scene[3u * i] = s.x;\n scene[3u * i + 1u] = s.y;\n scene[3u * i + 2u] = select(s.z, P.center.z, P.dim == 2u); // 2D writes z = center.z on every readback (7.13)\n}`;\n","/**\n * The `fill` kernel body (contract 4.5): `dst[i] = P.value` (mode 0) or `i + P.value` (mode 1, iota) for every\n * `i < P.count`, `i` from the prelude's `linear_id` so a 2D dispatch covers counts above MAX_1D_ITEMS. The 17M-item\n * linear_id test of spec 5.2 / 11.5 is mode 1 over 16,776,961 words. Normative text, copied verbatim.\n */\nexport const fillWgsl = /* wgsl */ `\n@compute @workgroup_size(WG)\nfn fill(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n if (i >= P.count) { return; }\n dst[i] = select(P.value, i + P.value, P.mode == 1u);\n}\n`;\n","/**\n * The `pr-finalize` kernel body (spec 8.2 dispatch (b)): ONE workgroup folds the `P.groups` per-workgroup partials\n * into the header at `partials[0]` -- a STORAGE region, never a uniform, read by the next dispatch of the same\n * pass -- and records `firstConverged` the first time the delta falls below `P.convergeThreshold`. NORM_MODE 2\n * stores the square root of the folded norm (the L2 case). The recorded iteration is `P.iteration - 1u` because\n * the delta a scale pass produces at iteration i is `|x(i-1) - x(i-2)|`, the error of iteration i - 1 (PD-9).\n * The body is normative: a sabotage mutation is a textual edit of it, so it is not restyled.\n */\n\n/** Entry point `pr_finalize`; override NORM_MODE (2 takes the square root of the folded norm, every other value stores it as folded). */\nexport const prFinalizeWgsl = /* wgsl */ `\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`;\n","/**\n * The `pr-scale` kernel body (spec 8.2 dispatch (a)): one invocation per node writes `xNorm[u]` and contributes a\n * per-workgroup partial of the dangling mass, the L1 delta `|rankIn - rankPrev|` and, for the spectral modes, the\n * norm term. NORM_MODE selects the divisor: 0 PageRank (`rankIn[u] / outWeightSum[u]`, 0 and a dangling\n * contribution when the sum is not positive); 1 and 2 are NORM PASSES that write no xNorm and only accumulate\n * `abs(x)` (L1) or `x * x` (L2); 3 divides by the scalar `partials[0].norm` the previous dispatch folded; 4 is the\n * identity (Katz). The body is normative: a sabotage mutation is a textual edit of it, so it is not restyled.\n *\n * The guard is named `inRange`, never `active`: `active` is a WGSL reserved word (spec 16.2) and the composer\n * rejects it before a device is touched.\n */\n\n/** 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). */\nexport const prScaleWgsl = /* wgsl */ `\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`;\n","/**\n * The `reduce` kernel body (contract 4.5; spec 6 row 1): one level of the 2-3 level reduction. Overrides: OP\n * 0 sum / 1 min / 2 max, DTYPE 0 f32 / 1 u32 / 2 vec4f (four words per element, loaded through bitcast from the\n * u32 storage view), FINAL true for the one-workgroup level that folds the partials sequentially per lane in\n * index order (deterministic) and writes one element at `out[P.outOffset]`; the level-1 form writes\n * `out[P.outOffset + group]`. Calls the prelude's `wg_reduce_*` helpers (needs: [\"subgroups\"]) in uniform\n * control flow: DTYPE is a pipeline constant, so the branch on it is uniform. Normative text, copied verbatim.\n */\nexport const reduceWgsl = /* wgsl */ `\n// DTYPE 0 = f32, 1 = u32, 2 = vec4f (4 words per element); OP 0 = sum, 1 = min, 2 = max; FINAL = the one-workgroup level\nfn identity_f() -> f32 { if (OP == 1u) { return F32_MAX; } if (OP == 2u) { return -F32_MAX; } return 0.0; }\nfn identity_u() -> u32 { if (OP == 1u) { return U32_MAX; } return 0u; } // U32_MAX from the prelude: the literal is forbidden in bodies (4.1)\nfn comb_f(a: f32, b: f32) -> f32 { if (OP == 1u) { return min(a, b); } if (OP == 2u) { return max(a, b); } return a + b; }\nfn comb_u(a: u32, b: u32) -> u32 { if (OP == 1u) { return min(a, b); } if (OP == 2u) { return max(a, b); } return a + b; }\nfn comb_v(a: vec4f, b: vec4f) -> vec4f { if (OP == 1u) { return min(a, b); } if (OP == 2u) { return max(a, b); } return a + b; }\nfn load_f(i: u32) -> f32 { return bitcast<f32>(src[i]); }\nfn load_v(i: u32) -> vec4f {\n return vec4f(bitcast<f32>(src[4u * i]), bitcast<f32>(src[4u * i + 1u]), bitcast<f32>(src[4u * i + 2u]), bitcast<f32>(src[4u * i + 3u]));\n}\nfn store_f(i: u32, v: f32) { out[i] = bitcast<u32>(v); }\nfn store_v(i: u32, v: vec4f) {\n out[4u * i] = bitcast<u32>(v.x);\n out[4u * i + 1u] = bitcast<u32>(v.y);\n out[4u * i + 2u] = bitcast<u32>(v.z);\n out[4u * i + 3u] = bitcast<u32>(v.w);\n}\n\n@compute @workgroup_size(WG)\nfn reduce(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n var accF = identity_f();\n var accU = identity_u();\n var accV = vec4f(identity_f());\n if (FINAL) {\n for (var i = lid.x; i < P.count; i = i + WG) { // sequential per lane in index order: deterministic\n if (DTYPE == 0u) { accF = comb_f(accF, load_f(i)); }\n else if (DTYPE == 1u) { accU = comb_u(accU, src[i]); }\n else { accV = comb_v(accV, load_v(i)); }\n }\n } else {\n let i = linear_id(wid, lid.x);\n if (i < P.count) {\n if (DTYPE == 0u) { accF = load_f(i); }\n else if (DTYPE == 1u) { accU = src[i]; }\n else { accV = load_v(i); }\n }\n }\n // uniform control flow: the workgroup reduction of the selected dtype (DTYPE is a pipeline constant, so the branch is uniform)\n var tF = 0.0;\n var tU = 0u;\n var tV = vec4f(0.0);\n if (DTYPE == 0u) { tF = wg_reduce_f32(accF, lid.x, OP); }\n else if (DTYPE == 1u) { tU = wg_reduce_u32(accU, lid.x, OP); }\n else { tV = wg_reduce_vec4(accV, lid.x, OP); }\n if (lid.x == 0u) {\n let g = select(group_id(wid), 0u, FINAL);\n let o = P.outOffset + g;\n if (DTYPE == 0u) { store_f(o, tF); }\n else if (DTYPE == 1u) { out[o] = tU; }\n else { store_v(o, tV); }\n }\n}\n`;\n","/**\n * The `segmented-reduce` kernel body (spec 6 row 3; contract 4.5), TIER 0 = thread-per-row: one invocation per row\n * of [P.start, P.end) folds the VALUE snippet over the row's arcs inside the bound window [P.arcBase, P.arcEnd) and\n * writes out[i] as f32; a row with no arcs gets the identity element (0 for sum, F32_MAX for min, -F32_MAX for\n * max). The mid / high degree tiers (TIER 1 / 2 over degreeOrder()) land at P4. The body is normative: a sabotage\n * mutation (test/helpers/sabotage.ts) is a textual edit of it, so it is not restyled.\n */\n\n/**\n * Entry point `segmented_reduce`; overrides OP (0 sum, 1 min, 2 max) and TIER (0); snippet slot VALUE: statements\n * assigning `v` from `row`, `arc`, `nbr`, `weight` (`target` is a WGSL reserved word, hence `nbr`).\n */\nexport const segmentedReduceWgsl = /* wgsl */ `\nfn identity() -> f32 { if (OP == 1u) { return F32_MAX; } if (OP == 2u) { return -F32_MAX; } return 0.0; }\nfn comb(a: f32, b: f32) -> f32 { if (OP == 1u) { return min(a, b); } if (OP == 2u) { return max(a, b); } return a + b; }\n\n@compute @workgroup_size(WG)\nfn segmented_reduce(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let row = linear_id(wid, lid.x) + P.start;\n if (row >= P.end) { return; }\n let i = select(row, perm[row], USE_PERM);\n let a0 = max(rowPtr[i], P.arcBase);\n let a1 = min(rowPtr[i + 1u], P.arcEnd);\n var acc = identity();\n for (var arc = a0; arc < a1; arc = arc + 1u) {\n let nbr = colIdx[arc - P.arcBase]; // the neighbour index (\\`target\\` is a WGSL reserved word)\n var weight = 1.0;\n if (HAS_WEIGHTS) { weight = weights[arc - P.arcBase]; }\n var v = 0.0;\n //@@VALUE@@\n acc = comb(acc, v);\n }\n out[i] = select(acc, comb(out[i], acc), P.accumulate == 1u);\n}\n`;\n","/**\n * The `spmv-pull` kernel body (spec 6 row 9, 8.2; PD-1 of the M8b plan): one invocation per row of the REVERSE\n * adjacency, grid-stride over `[0, P.n)`, folding `weight * xNorm[nbr]` over the row's in-arcs in chunks of 64\n * terms (a two-level f32 sum: the chunk absorbs the rounding of 64 terms, the row total the rounding of the chunk\n * count, so a 10,000-arc hub row loses about 200 rounding steps instead of 10,000; Kahan compensation is not used\n * because Metal's shader compiler folds `((acc + term) - acc) - term` to zero whatever hides it) and writing\n * `rankOut[v] = beta * pv + alpha * (sum + danglingMass * pv)`, where `pv` is `personalization[v]` when\n * HAS_PERSONALIZATION and the uniform `P.uniformP` otherwise. PageRank sets alpha to the\n * damping factor, beta to `1 - alpha` and USE_DANGLING; HITS and eigenvector set alpha 1, beta 0, uniformP 0; Katz\n * sets alpha to the attenuation, beta to its constant and uniformP 1. The body is normative: a sabotage mutation\n * (test/helpers/sabotage.ts) is a textual edit of it, so it is not restyled.\n */\n\n/** Entry point `spmv_pull`; overrides HAS_PERSONALIZATION and USE_DANGLING plus the standard USE_PERM / HAS_WEIGHTS. */\nexport const spmvPullWgsl = /* wgsl */ `\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`;\n","/**\n * The `wcc-compress` kernel body (spec 8.3): pointer jumping to the root, reading through `atomicLoad` on the same\n * `array<atomic<u32>>` because WGSL forbids mixing atomic and plain access to one element. The walk is bounded by\n * `P.maxSteps`; a walk that runs out leaves a shorter path, which the next round finishes. The body is normative:\n * a sabotage mutation is a textual edit of it, so it is not restyled.\n */\n\n/** Entry point `wcc_compress`; no overrides. */\nexport const wccCompressWgsl = /* wgsl */ `\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`;\n","/**\n * The `wcc-link-edges` kernel body (spec 8.3): the each-edge-once link round of Afforest, correct for directed and\n * undirected input alike because `edgeList()` yields every logical edge once in declared orientation (design 10.1).\n * `link_pair` is the same GAP `Link` transcription as wcc-link-sample (each module is composed alone, so the helper\n * is copied, not shared): all-u32 CAS on `comp`, an `array<atomic<u32>>` because WGSL forbids mixing atomic and\n * plain access to one element, with a bounded retry loop (PD-5) and the changed flag at `P.flagIndex` inside the\n * same array (PD-4). The `P.giant` guard is GAP's \"skip the vertices already in the giant component\" and is a pure\n * optimisation -- linking two vertices already in one component is a no-op. The body is normative: a sabotage\n * mutation is a textual edit of it, so it is not restyled.\n */\n\n/** Entry point `wcc_link_edges`; no overrides. */\nexport const wccLinkEdgesWgsl = /* wgsl */ `\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`;\n","/**\n * The `wcc-link-sample` kernel body (spec 8.3): one of Afforest's sampled link rounds -- every vertex links its\n * r-th neighbour, `colIdx[rowPtr[v] + P.r]`, when it has one. `link_pair` is GAP's `Link` (gapbs/cc.cc lines\n * 40-150) transcribed for WGSL: all-u32 CAS on `comp`, which is `array<atomic<u32>>` because WGSL forbids mixing\n * atomic and plain access to one element, with a bounded retry loop (PD-5). The changed flag is the word at\n * `P.flagIndex` inside the same array (PD-4). The body is normative: a sabotage mutation is a textual edit of it,\n * so it is not restyled.\n */\n\n/** Entry point `wcc_link_sample`; standard USE_PERM / HAS_WEIGHTS only (the body reads neither weights nor a permutation beyond the row select). */\nexport const wccLinkSampleWgsl = /* wgsl */ `\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`;\n","/**\n * The `wcc-sample` kernel body (spec 8.3 \"a 1,024-entry histogram readback to find the giant component\"): writes\n * the component label of `P.items` pseudo-randomly chosen vertices into `hist`, which the host reads back and takes\n * the mode of (PD-12: GAP's SampleFrequentElement counts on the host too, and a device histogram over component\n * ids would return a bucket, not an id). The sampler uses the prelude's `lowbias32` and `%`, never a bitwise\n * operator on an index.\n */\n\n/** Entry point `wcc_sample`; no overrides. */\nexport const wccSampleWgsl = /* wgsl */ `\n@compute @workgroup_size(WG)\nfn wcc_sample(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let i = linear_id(wid, lid.x);\n if (i >= P.items) { return; }\n let v = lowbias32(i + P.r) % P.n;\n hist[i] = atomicLoad(&comp[v]);\n}\n`;\n","/**\n * THE kernel registry (spec 3.5; contract 3.10): every WGSL module the package compiles, keyed by id, with the\n * binding table, the override declarations, the generated uniform / storage blocks and the feature needs from\n * which src/kernel/wgsl.ts emits the bind declarations and src/kernel/pipeline-cache.ts derives the explicit\n * bind-group layouts. A variant cannot exist without an entry here: the compile tests, the bind-group-budget\n * test and PipelineCache.warm() iterate this table. P1-T4 lands degree, reduce, fill, fa2-repulsion-exact (K3)\n * and fa2-speed-finalize (K4) together with every generated block of contract 3.10.2; P2-T2 lands\n * segmented-reduce; P3-T2 adds fa2-stats-finalize (K1), fa2-attraction (K2), fa2-integrate (K5) and\n * fa2-to-scene; M8b-T3 adds the seven P7 entries: spmv-pull, pr-scale, pr-finalize, wcc-link-sample,\n * wcc-link-edges, wcc-compress and wcc-sample. This file is the only importer of src/wgsl/** (spec 3.2;\n * test/layers.test.ts).\n */\n\nimport { STATE_HEADER_BYTES } from \"./constants.js\";\nimport { WebGpuGraphError } from \"./errors.js\";\nimport { UniformBlock } from \"./kernel/struct-block.js\";\nimport { type BindingDecl, type OverrideDecl, type WgslModuleSpec } from \"./kernel/wgsl.js\";\nimport { type CoreBinding } from \"./memory/residency.js\";\nimport { type Binding } from \"./types/memory.js\";\nimport { degreeWgsl } from \"./wgsl/degree.wgsl.js\";\nimport { fa2AttractionWgsl } from \"./wgsl/fa2-attraction.wgsl.js\";\nimport { fa2IntegrateWgsl } from \"./wgsl/fa2-integrate.wgsl.js\";\nimport { fa2RepulsionExactWgsl } from \"./wgsl/fa2-repulsion-exact.wgsl.js\";\nimport { fa2SpeedFinalizeWgsl } from \"./wgsl/fa2-speed-finalize.wgsl.js\";\nimport { fa2StatsFinalizeWgsl } from \"./wgsl/fa2-stats-finalize.wgsl.js\";\nimport { fa2ToSceneWgsl } from \"./wgsl/fa2-to-scene.wgsl.js\";\nimport { fillWgsl } from \"./wgsl/fill.wgsl.js\";\nimport { prFinalizeWgsl } from \"./wgsl/pr-finalize.wgsl.js\";\nimport { prScaleWgsl } from \"./wgsl/pr-scale.wgsl.js\";\nimport { reduceWgsl } from \"./wgsl/reduce.wgsl.js\";\nimport { segmentedReduceWgsl } from \"./wgsl/segmented-reduce.wgsl.js\";\nimport { spmvPullWgsl } from \"./wgsl/spmv-pull.wgsl.js\";\nimport { wccCompressWgsl } from \"./wgsl/wcc-compress.wgsl.js\";\nimport { wccLinkEdgesWgsl } from \"./wgsl/wcc-link-edges.wgsl.js\";\nimport { wccLinkSampleWgsl } from \"./wgsl/wcc-link-sample.wgsl.js\";\nimport { wccSampleWgsl } from \"./wgsl/wcc-sample.wgsl.js\";\n\n/** Every module id of P1-P3 and P7 (later ids are appended, never renamed). */\nexport type KernelId =\n | \"degree\"\n | \"reduce\"\n | \"fill\"\n | \"segmented-reduce\"\n | \"fa2-stats-finalize\"\n | \"fa2-attraction\"\n | \"fa2-repulsion-exact\"\n | \"fa2-speed-finalize\"\n | \"fa2-integrate\"\n | \"fa2-to-scene\"\n | \"spmv-pull\"\n | \"pr-scale\"\n | \"pr-finalize\"\n | \"wcc-link-sample\"\n | \"wcc-link-edges\"\n | \"wcc-compress\"\n | \"wcc-sample\";\n\n/** One registry entry: everything of a WgslModuleSpec except the per-variant overrides and snippets. */\nexport interface KernelEntry {\n readonly id: KernelId;\n readonly body: string;\n readonly entryPoint: string;\n readonly bindings: readonly BindingDecl[];\n readonly overrideDecls: readonly OverrideDecl[];\n readonly uniforms: readonly UniformBlock[];\n /** [\"subgroups\"] when the body calls a reduction helper (the twin axis), else []. */\n readonly needs: readonly \"subgroups\"[];\n /** The snippet marker names the body carries (segmented-reduce: [\"VALUE\"]). */\n readonly snippetSlots: readonly string[];\n /** The phase the entry landed in (documentation and the compile-matrix filter). */\n readonly phase: \"P1\" | \"P2\" | \"P3\" | \"P7\";\n}\n\n// ---- the generated blocks (spec 5.3; contract 3.10.2): field order = byte order, offsets in the JSDoc\n\n/** `RangeParams` (uniform, 32 B): rows `[start, end)` @0 / @4 of the dispatch, the bound arc window `[arcBase, arcEnd)` @8 / @12 (0 and arcCount when not windowed), `accumulate` @16 (1 combines into `out[i]` instead of overwriting: the P4 windowed loop), `n` @20 (the node count that bounds neighbour indices), `pad0` @24, `pad1` @28. */\nexport const RANGE_PARAMS: UniformBlock = UniformBlock.define(\"RangeParams\", [\n [\"start\", \"u32\"],\n [\"end\", \"u32\"],\n [\"arcBase\", \"u32\"],\n [\"arcEnd\", \"u32\"],\n [\"accumulate\", \"u32\"],\n [\"n\", \"u32\"],\n [\"pad0\", \"u32\"],\n [\"pad1\", \"u32\"],\n]);\n\n/** `ReduceParams` (uniform, 16 B): `count` @0 elements of the level, `outOffset` @4 (the element index the level writes at), `level` @8, `pad0` @12. */\nexport const REDUCE_PARAMS: UniformBlock = UniformBlock.define(\"ReduceParams\", [\n [\"count\", \"u32\"],\n [\"outOffset\", \"u32\"],\n [\"level\", \"u32\"],\n [\"pad0\", \"u32\"],\n]);\n\n/** `FillParams` (uniform, 16 B): `count` @0 words, `value` @4, `mode` @8 (0 = the constant `value`, 1 = iota `i + value`), `pad0` @12. */\nexport const FILL_PARAMS: UniformBlock = UniformBlock.define(\"FillParams\", [\n [\"count\", \"u32\"],\n [\"value\", \"u32\"],\n [\"mode\", \"u32\"],\n [\"pad0\", \"u32\"],\n]);\n\n/** `Fa2Params` (uniform, 96 B; spec 7.3): the per-iteration ForceAtlas2 parameters -- `n` @0, `dim` @4, `flags` @8 (bit 0 = FA2_FLAG_FIRST), `tierStart` @12, `tierEnd` @16, `iterationIndex` @20, `seed` @24, `nearMax` @28, `scalingRatio` @32, `gravity` @36, `jitterTolerance` @40, `scale` @44, `center` @48 (xyz, w 0), `settleThreshold` @64, `extentFactor` @68, `gridMax` @72, `levels` @76, `pad` @80 (reserved for the P4 GridSpec). */\nexport const FA2_PARAMS: UniformBlock = UniformBlock.define(\"Fa2Params\", [\n [\"n\", \"u32\"],\n [\"dim\", \"u32\"],\n [\"flags\", \"u32\"],\n [\"tierStart\", \"u32\"],\n [\"tierEnd\", \"u32\"],\n [\"iterationIndex\", \"u32\"],\n [\"seed\", \"u32\"],\n [\"nearMax\", \"u32\"],\n [\"scalingRatio\", \"f32\"],\n [\"gravity\", \"f32\"],\n [\"jitterTolerance\", \"f32\"],\n [\"scale\", \"f32\"],\n [\"center\", \"vec4f\"],\n [\"settleThreshold\", \"f32\"],\n [\"extentFactor\", \"f32\"],\n [\"gridMax\", \"u32\"],\n [\"levels\", \"u32\"],\n [\"pad\", \"vec4f\"],\n]);\n\n/** `Fa2State` (storage, padded to STATE_HEADER_BYTES = 256; spec 7.3): the device-resident controller state the finalize kernels write and the host reads back for stats -- `speed` @0, `speedEfficiency` @4, `swing` @8, `traction` @12, `centroid` @16, `rmsRadius` @32, `radius` @36, `meanDisplacement` @40, `iteration` @44, `min` @48, `max` @64, `gridMin` @80 (P4), `eps` @96 (P4), `settledCount` @100, `outsideGrid` @104 (P4), `maxCellOccupancy` @108 (P4), `reserved0` .. `reserved8` @112 .. @240. */\nexport const FA2_STATE: UniformBlock = UniformBlock.define(\n \"Fa2State\",\n [\n [\"speed\", \"f32\"],\n [\"speedEfficiency\", \"f32\"],\n [\"swing\", \"f32\"],\n [\"traction\", \"f32\"],\n [\"centroid\", \"vec4f\"],\n [\"rmsRadius\", \"f32\"],\n [\"radius\", \"f32\"],\n [\"meanDisplacement\", \"f32\"],\n [\"iteration\", \"u32\"],\n [\"min\", \"vec4f\"],\n [\"max\", \"vec4f\"],\n [\"gridMin\", \"vec4f\"],\n [\"eps\", \"f32\"],\n [\"settledCount\", \"u32\"],\n [\"outsideGrid\", \"u32\"],\n [\"maxCellOccupancy\", \"u32\"],\n [\"reserved0\", \"vec4f\"],\n [\"reserved1\", \"vec4f\"],\n [\"reserved2\", \"vec4f\"],\n [\"reserved3\", \"vec4f\"],\n [\"reserved4\", \"vec4f\"],\n [\"reserved5\", \"vec4f\"],\n [\"reserved6\", \"vec4f\"],\n [\"reserved7\", \"vec4f\"],\n [\"reserved8\", \"vec4f\"],\n ],\n { layout: \"storage\", padTo: STATE_HEADER_BYTES },\n);\n\n/** `Fa2Trace` (storage record, 32 B; spec 7.3): one per-iteration trace record -- `swing` @0, `traction` @4, `speed` @8, `speedEfficiency` @12 (written by K4), `meanDisplacement` @16, `settledCount` @20, `iteration` @24 (written by K1), `pad0` @28; the trace region is `array<Fa2Trace>` at byte offset STATE_HEADER_BYTES of the state buffer. */\nexport const FA2_TRACE: UniformBlock = UniformBlock.define(\n \"Fa2Trace\",\n [\n [\"swing\", \"f32\"],\n [\"traction\", \"f32\"],\n [\"speed\", \"f32\"],\n [\"speedEfficiency\", \"f32\"],\n [\"meanDisplacement\", \"f32\"],\n [\"settledCount\", \"u32\"],\n [\"iteration\", \"u32\"],\n [\"pad0\", \"u32\"],\n ],\n { layout: \"storage\" },\n);\n\n/** `Fa2Partial` (storage record, 64 B; spec 7.3): one per-workgroup partial -- `sum` @0 (xyz = sum of positions, w = sum of |p - centroid|^2), `min` @16, `max` @32 (w = max of |p - centroid|^2, the exact layoutRadius source), written by K5; `swingTraction` @48 (written by K3's epilogue); `dispFree` @56 (x = sum |dp| over free rows, y = the free count as an f32 <= 256, written by K5). */\nexport const FA2_PARTIAL: UniformBlock = UniformBlock.define(\n \"Fa2Partial\",\n [\n [\"sum\", \"vec4f\"],\n [\"min\", \"vec4f\"],\n [\"max\", \"vec4f\"],\n [\"swingTraction\", \"vec2f\"],\n [\"dispFree\", \"vec2f\"],\n ],\n { layout: \"storage\" },\n);\n\n/** `SpmvParams` (uniform, 32 B; spec 8.2): `n` @0 rows of the pull, the bound arc window `[arcBase, arcEnd)` @4 / @8 (0 and arcCount when not windowed), the grid-stride step `stride` @12, `alpha` @16, `beta` @20 (the `1 - alpha` term), `uniformP` @24 (the uniform personalization mass `1 / n`, 0 for a pure SpMV), `pad0` @28. */\nexport const SPMV_PARAMS: UniformBlock = UniformBlock.define(\"SpmvParams\", [\n [\"n\", \"u32\"],\n [\"arcBase\", \"u32\"],\n [\"arcEnd\", \"u32\"],\n [\"stride\", \"u32\"],\n [\"alpha\", \"f32\"],\n [\"beta\", \"f32\"],\n [\"uniformP\", \"f32\"],\n [\"pad0\", \"u32\"],\n]);\n\n/** `PrParams` (uniform, 32 B; spec 8.2): `n` @0, `groups` @4 (the per-workgroup partial count the finalize folds), `iteration` @8 (1-based), `trackConvergence` @12 (1 records firstConverged), `convergeThreshold` @16 (`tolerance * n`, the design's `delta < tol * n`), `pad0` @20, `pad1` @24, `pad2` @28. */\nexport const PR_PARAMS: UniformBlock = UniformBlock.define(\"PrParams\", [\n [\"n\", \"u32\"],\n [\"groups\", \"u32\"],\n [\"iteration\", \"u32\"],\n [\"trackConvergence\", \"u32\"],\n [\"convergeThreshold\", \"f32\"],\n [\"pad0\", \"u32\"],\n [\"pad1\", \"u32\"],\n [\"pad2\", \"u32\"],\n]);\n\n/**\n * `PrPartial` (storage record, 32 B; spec 8.2). Element 0 is the HEADER, whose first 16 bytes are exactly the four\n * fields the design names -- `danglingMass` @0, `delta` @4, `firstConvergedIteration` @8, `iteration` @12 -- plus\n * `norm` @16, which M8b adds so HITS / eigenvector / Katz keep their normaliser on the device (PD-10). Element\n * `1 + g` is workgroup g's partial: it uses `danglingMass`, `delta` and `norm` as three sums and leaves the two u32\n * fields zero.\n */\nexport const PR_PARTIAL: UniformBlock = UniformBlock.define(\n \"PrPartial\",\n [\n [\"danglingMass\", \"f32\"],\n [\"delta\", \"f32\"],\n [\"firstConverged\", \"u32\"],\n [\"iteration\", \"u32\"],\n [\"norm\", \"f32\"],\n [\"pad0\", \"f32\"],\n [\"pad1\", \"f32\"],\n [\"pad2\", \"f32\"],\n ],\n { layout: \"storage\" },\n);\n\n/** `WccParams` (uniform, 32 B; spec 8.3): `n` @0, `items` @4 (rows for a sample round, edges for an edge round, 1024 for the sampler), `stride` @8, `r` @12 (the neighbour index of the sampled round, and the sampler's seed), `flagIndex` @16 (the changed word inside `comp`, PD-4), `giant` @20 (`U32_MAX` before the sample), `maxSteps` @24, `pad0` @28. */\nexport const WCC_PARAMS: UniformBlock = UniformBlock.define(\"WccParams\", [\n [\"n\", \"u32\"],\n [\"items\", \"u32\"],\n [\"stride\", \"u32\"],\n [\"r\", \"u32\"],\n [\"flagIndex\", \"u32\"],\n [\"giant\", \"u32\"],\n [\"maxSteps\", \"u32\"],\n [\"pad0\", \"u32\"],\n]);\n\n// ---- the entries (contract 3.10.1; group 0 = graph, 1 = state, 2 = params, 3 = cold)\n\n/**\n * One binding declaration of contract 3.9, so the tables below read like the rows of 3.10.1.\n * @param group - the bind group (0 graph, 1 state, 2 params, 3 cold)\n * @param binding - the slot inside the group\n * @param name - the WGSL variable name (also the KernelBindings key)\n * @param kind - \"storage\" (read_write), \"storage-ro\" (read) or \"uniform\"\n * @param wgslType - the element / struct type text\n * @returns the declaration\n */\nfunction decl(\n group: 0 | 1 | 2 | 3,\n binding: number,\n name: string,\n kind: BindingDecl[\"kind\"],\n wgslType: string,\n): BindingDecl {\n return { group, binding, name, kind, wgslType };\n}\n\n/** The four group-0 graph slots of every row-walking kernel (spec 3.5): rowPtr, colIdx, weights | dummy, perm | dummy -- all read-only, so the dummies never alias a writable slot (3.10.1). */\nconst GRAPH_SLOTS: readonly BindingDecl[] = [\n decl(0, 0, \"rowPtr\", \"storage-ro\", \"array<u32>\"),\n decl(0, 1, \"colIdx\", \"storage-ro\", \"array<u32>\"),\n decl(0, 2, \"weights\", \"storage-ro\", \"array<f32>\"),\n decl(0, 3, \"perm\", \"storage-ro\", \"array<u32>\"),\n];\n\n/** `degree` (3.10.1): 5 storage bindings; only the standard USE_PERM / HAS_WEIGHTS overrides. */\nconst DEGREE: KernelEntry = {\n id: \"degree\",\n body: degreeWgsl,\n entryPoint: \"degree\",\n bindings: GRAPH_SLOTS.concat(decl(1, 0, \"out\", \"storage\", \"array<u32>\"), decl(2, 0, \"P\", \"uniform\", \"RangeParams\")),\n overrideDecls: [],\n uniforms: [RANGE_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `reduce` (3.10.1): the multi-level reduction; OP 0 sum / 1 min / 2 max, DTYPE 0 f32 / 1 u32 / 2 vec4f, FINAL for the one-workgroup level; 2 storage bindings; calls the reduction helpers. */\nconst REDUCE: KernelEntry = {\n id: \"reduce\",\n body: reduceWgsl,\n entryPoint: \"reduce\",\n bindings: [\n decl(1, 0, \"src\", \"storage-ro\", \"array<u32>\"),\n decl(1, 1, \"out\", \"storage\", \"array<u32>\"),\n decl(2, 0, \"P\", \"uniform\", \"ReduceParams\"),\n ],\n overrideDecls: [\n { name: \"OP\", type: \"u32\", default: 0 },\n { name: \"DTYPE\", type: \"u32\", default: 0 },\n { name: \"FINAL\", type: \"bool\", default: false },\n ],\n uniforms: [REDUCE_PARAMS],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `fill` (3.10.1): dst[i] = value (mode 0) or i + value (mode 1) over `count` words; 1 storage binding. */\nconst FILL: KernelEntry = {\n id: \"fill\",\n body: fillWgsl,\n entryPoint: \"fill\",\n bindings: [decl(1, 0, \"dst\", \"storage\", \"array<u32>\"), decl(2, 0, \"P\", \"uniform\", \"FillParams\")],\n overrideDecls: [],\n uniforms: [FILL_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `segmented-reduce` (3.10.1): the per-row fold of the VALUE snippet over the CSR rows; OP 0 sum / 1 min / 2 max, TIER 0 (thread-per-row; the degreeOrder tiers land at P4) plus the standard USE_PERM / HAS_WEIGHTS; 5 storage bindings; one snippet slot. */\nconst SEGMENTED_REDUCE: KernelEntry = {\n id: \"segmented-reduce\",\n body: segmentedReduceWgsl,\n entryPoint: \"segmented_reduce\",\n bindings: GRAPH_SLOTS.concat(decl(1, 0, \"out\", \"storage\", \"array<f32>\"), decl(2, 0, \"P\", \"uniform\", \"RangeParams\")),\n overrideDecls: [\n { name: \"OP\", type: \"u32\", default: 0 },\n { name: \"TIER\", type: \"u32\", default: 0 },\n ],\n uniforms: [RANGE_PARAMS],\n needs: [],\n snippetSlots: [\"VALUE\"],\n phase: \"P2\",\n};\n\n/** `fa2-stats-finalize` (K1, 3.10.1): the one-workgroup fold of the previous integrate's partials into the state block and the K1 half of the trace record; 3 storage bindings; calls the reduction helpers. */\nconst FA2_STATS_FINALIZE: KernelEntry = {\n id: \"fa2-stats-finalize\",\n body: fa2StatsFinalizeWgsl,\n entryPoint: \"stats_finalize\",\n bindings: [\n decl(1, 0, \"partials\", \"storage-ro\", \"array<Fa2Partial>\"),\n decl(1, 1, \"S\", \"storage\", \"Fa2State\"),\n decl(1, 2, \"T\", \"storage\", \"array<Fa2Trace>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [],\n uniforms: [FA2_PARAMS, FA2_STATE, FA2_TRACE, FA2_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P3\",\n};\n\n/** `fa2-attraction` (K2, 3.10.1): the thread-per-row attraction gather over the CSR rows (the first writer of `force` each iteration); LINLOG / DISTRIBUTED / TIER 0 plus the standard USE_PERM / HAS_WEIGHTS; 6 storage bindings. */\nconst FA2_ATTRACTION: KernelEntry = {\n id: \"fa2-attraction\",\n body: fa2AttractionWgsl,\n entryPoint: \"attraction\",\n bindings: GRAPH_SLOTS.concat(\n decl(1, 0, \"pos\", \"storage-ro\", \"array<vec4f>\"),\n decl(1, 1, \"force\", \"storage\", \"array<f32>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ),\n overrideDecls: [\n { name: \"LINLOG\", type: \"bool\", default: false },\n { name: \"DISTRIBUTED\", type: \"bool\", default: false },\n { name: \"TIER\", type: \"u32\", default: 0 },\n ],\n uniforms: [FA2_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P3\",\n};\n\n/** `fa2-repulsion-exact` (K3, 3.10.1): the tiled all-pairs repulsion with the gravity and swing / traction epilogue; 6 storage bindings (`oldForce` read-only: it only calls load_old); calls the reduction helpers. */\nconst FA2_REPULSION_EXACT: KernelEntry = {\n id: \"fa2-repulsion-exact\",\n body: fa2RepulsionExactWgsl,\n entryPoint: \"repulsion\",\n bindings: [\n decl(1, 0, \"pos\", \"storage-ro\", \"array<vec4f>\"),\n decl(1, 1, \"S\", \"storage\", \"Fa2State\"),\n decl(1, 2, \"force\", \"storage\", \"array<f32>\"),\n decl(1, 3, \"oldForce\", \"storage-ro\", \"array<f32>\"),\n decl(1, 4, \"fixedMask\", \"storage-ro\", \"array<u32>\"),\n decl(1, 5, \"partials\", \"storage\", \"array<Fa2Partial>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [\n { name: \"SWING_MODE\", type: \"u32\", default: 0 },\n { name: \"STRONG_GRAVITY\", type: \"bool\", default: false },\n { name: \"GRAVITY_CENTER\", type: \"u32\", default: 0 },\n ],\n uniforms: [FA2_PARAMS, FA2_STATE, FA2_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `fa2-speed-finalize` (K4, 3.10.1): the one-workgroup partials fold and estimateFactor; 3 storage bindings; calls the reduction helpers. */\nconst FA2_SPEED_FINALIZE: KernelEntry = {\n id: \"fa2-speed-finalize\",\n body: fa2SpeedFinalizeWgsl,\n entryPoint: \"speed_finalize\",\n bindings: [\n decl(1, 0, \"partials\", \"storage-ro\", \"array<Fa2Partial>\"),\n decl(1, 1, \"S\", \"storage\", \"Fa2State\"),\n decl(1, 2, \"T\", \"storage\", \"array<Fa2Trace>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [{ name: \"SWING_MODE\", type: \"u32\", default: 0 }],\n uniforms: [FA2_PARAMS, FA2_STATE, FA2_TRACE, FA2_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P1\",\n};\n\n/** `fa2-integrate` (K5, 3.10.1): the per-node speed factor and position update (no clamp, D25), `oldForce` stored in SWING_MODE 0, and the partials A / C of the next K1; 6 storage bindings; calls the reduction helpers. */\nconst FA2_INTEGRATE: KernelEntry = {\n id: \"fa2-integrate\",\n body: fa2IntegrateWgsl,\n entryPoint: \"integrate\",\n bindings: [\n decl(1, 0, \"force\", \"storage-ro\", \"array<f32>\"),\n decl(1, 1, \"oldForce\", \"storage\", \"array<f32>\"),\n decl(1, 2, \"fixedMask\", \"storage-ro\", \"array<u32>\"),\n decl(1, 3, \"S\", \"storage\", \"Fa2State\"),\n decl(1, 4, \"pos\", \"storage\", \"array<vec4f>\"),\n decl(1, 5, \"partials\", \"storage\", \"array<Fa2Partial>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [{ name: \"SWING_MODE\", type: \"u32\", default: 0 }],\n uniforms: [FA2_PARAMS, FA2_STATE, FA2_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P3\",\n};\n\n/** `fa2-to-scene` (3.10.1): the per-batch unpack of the vec4f layout positions into the stride-3 scene array with `scale` / `center` applied (z = center.z in 2D); 2 storage bindings. */\nconst FA2_TO_SCENE: KernelEntry = {\n id: \"fa2-to-scene\",\n body: fa2ToSceneWgsl,\n entryPoint: \"to_scene\",\n bindings: [\n decl(1, 0, \"pos\", \"storage-ro\", \"array<vec4f>\"),\n decl(1, 1, \"scene\", \"storage\", \"array<f32>\"),\n decl(2, 0, \"P\", \"uniform\", \"Fa2Params\"),\n ],\n overrideDecls: [],\n uniforms: [FA2_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P3\",\n};\n\n/** `spmv-pull` (spec 8.10): the grid-stride pull SpMV over the reverse adjacency; HAS_PERSONALIZATION / USE_DANGLING plus the standard USE_PERM / HAS_WEIGHTS; 8 storage bindings (the design's count). */\nconst SPMV_PULL: KernelEntry = {\n id: \"spmv-pull\",\n body: spmvPullWgsl,\n entryPoint: \"spmv_pull\",\n bindings: GRAPH_SLOTS.concat(\n decl(1, 0, \"xNorm\", \"storage-ro\", \"array<f32>\"),\n decl(1, 1, \"rankOut\", \"storage\", \"array<f32>\"),\n decl(1, 2, \"personalization\", \"storage-ro\", \"array<f32>\"),\n decl(1, 3, \"partials\", \"storage-ro\", \"array<PrPartial>\"),\n decl(2, 0, \"P\", \"uniform\", \"SpmvParams\"),\n ),\n overrideDecls: [\n { name: \"HAS_PERSONALIZATION\", type: \"bool\", default: false },\n { name: \"USE_DANGLING\", type: \"bool\", default: false },\n ],\n uniforms: [SPMV_PARAMS, PR_PARTIAL],\n needs: [],\n snippetSlots: [],\n phase: \"P7\",\n};\n\n/** `pr-scale` (spec 8.2 dispatch (a), 8.10): the per-node normaliser and the per-workgroup partials; NORM_MODE 0 PageRank / 1 L1 pass / 2 L2 pass / 3 scale / 4 identity; 5 storage bindings; calls the reduction helpers. */\nconst PR_SCALE: KernelEntry = {\n id: \"pr-scale\",\n body: prScaleWgsl,\n entryPoint: \"pr_scale\",\n bindings: [\n decl(1, 0, \"rankIn\", \"storage-ro\", \"array<f32>\"),\n decl(1, 1, \"rankPrev\", \"storage-ro\", \"array<f32>\"),\n decl(1, 2, \"outWeightSum\", \"storage-ro\", \"array<f32>\"),\n decl(1, 3, \"xNorm\", \"storage\", \"array<f32>\"),\n decl(1, 4, \"partials\", \"storage\", \"array<PrPartial>\"),\n decl(2, 0, \"P\", \"uniform\", \"PrParams\"),\n ],\n overrideDecls: [{ name: \"NORM_MODE\", type: \"u32\", default: 0 }],\n uniforms: [PR_PARAMS, PR_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P7\",\n};\n\n/** `pr-finalize` (spec 8.2 dispatch (b), 8.10): the one-workgroup fold of the partials into the header at partials[0] and the firstConverged record; NORM_MODE 2 takes the square root; 1 storage binding; calls the reduction helpers. */\nconst PR_FINALIZE: KernelEntry = {\n id: \"pr-finalize\",\n body: prFinalizeWgsl,\n entryPoint: \"pr_finalize\",\n bindings: [decl(1, 0, \"partials\", \"storage\", \"array<PrPartial>\"), decl(2, 0, \"P\", \"uniform\", \"PrParams\")],\n overrideDecls: [{ name: \"NORM_MODE\", type: \"u32\", default: 0 }],\n uniforms: [PR_PARAMS, PR_PARTIAL],\n needs: [\"subgroups\"],\n snippetSlots: [],\n phase: \"P7\",\n};\n\n/** `wcc-link-sample` (spec 8.3): Afforest's sampled link round over the CSR rows (every vertex links its r-th neighbour); the standard USE_PERM / HAS_WEIGHTS only; 5 storage bindings (the four graph slots and the atomic `comp`, whose word at P.flagIndex is the changed flag, PD-4). */\nconst WCC_LINK_SAMPLE: KernelEntry = {\n id: \"wcc-link-sample\",\n body: wccLinkSampleWgsl,\n entryPoint: \"wcc_link_sample\",\n bindings: GRAPH_SLOTS.concat(\n decl(1, 0, \"comp\", \"storage\", \"array<atomic<u32>>\"),\n decl(2, 0, \"P\", \"uniform\", \"WccParams\"),\n ),\n overrideDecls: [],\n uniforms: [WCC_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P7\",\n};\n\n/** `wcc-link-edges` (spec 8.3, 8.10): Afforest's each-edge-once link round over the edge list; no overrides; 3 storage bindings (the design's count: edgeSrc, edgeDst and the atomic `comp` carrying the changed flag). */\nconst WCC_LINK_EDGES: KernelEntry = {\n id: \"wcc-link-edges\",\n body: wccLinkEdgesWgsl,\n entryPoint: \"wcc_link_edges\",\n bindings: [\n decl(1, 0, \"edgeSrc\", \"storage-ro\", \"array<u32>\"),\n decl(1, 1, \"edgeDst\", \"storage-ro\", \"array<u32>\"),\n decl(1, 2, \"comp\", \"storage\", \"array<atomic<u32>>\"),\n decl(2, 0, \"P\", \"uniform\", \"WccParams\"),\n ],\n overrideDecls: [],\n uniforms: [WCC_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P7\",\n};\n\n/** `wcc-compress` (spec 8.3, 8.10): Afforest's bounded pointer-jumping compress; no overrides; 1 storage binding. */\nconst WCC_COMPRESS: KernelEntry = {\n id: \"wcc-compress\",\n body: wccCompressWgsl,\n entryPoint: \"wcc_compress\",\n bindings: [decl(1, 0, \"comp\", \"storage\", \"array<atomic<u32>>\"), decl(2, 0, \"P\", \"uniform\", \"WccParams\")],\n overrideDecls: [],\n uniforms: [WCC_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P7\",\n};\n\n/** `wcc-sample` (spec 8.3, 8.10): the component-label sample of P.items pseudo-random vertices the host takes the mode of (PD-12); no overrides; 2 storage bindings. */\nconst WCC_SAMPLE: KernelEntry = {\n id: \"wcc-sample\",\n body: wccSampleWgsl,\n entryPoint: \"wcc_sample\",\n bindings: [\n decl(1, 0, \"comp\", \"storage\", \"array<atomic<u32>>\"),\n decl(1, 1, \"hist\", \"storage\", \"array<u32>\"),\n decl(2, 0, \"P\", \"uniform\", \"WccParams\"),\n ],\n overrideDecls: [],\n uniforms: [WCC_PARAMS],\n needs: [],\n snippetSlots: [],\n phase: \"P7\",\n};\n\n/**\n * The entries by id, in dispatch order. PLAN DECISION: `KernelId` is declared in full (contract 3.10) while the\n * entries landed phase by phase, so the table is built as a Partial record and exported below through the\n * contract's `Readonly<Record<KernelId, KernelEntry>>` type by one assertion; the runtime membership check of\n * `entryOf` is the E_INVALID_ARGUMENT the contract documents for a JS caller's unknown id. P1-T4 landed the five\n * P1 entries, P2-T2 `\"segmented-reduce\"`, and P3-T2 `\"fa2-stats-finalize\"`, `\"fa2-attraction\"`, `\"fa2-integrate\"`\n * and `\"fa2-to-scene\"`; M8b-T3 landed the seven P7 entries, so every member of `KernelId` is present and the\n * assertion is exact.\n */\nconst REGISTRY: Readonly<Partial<Record<KernelId, KernelEntry>>> = Object.freeze({\n degree: DEGREE,\n reduce: REDUCE,\n fill: FILL,\n \"segmented-reduce\": SEGMENTED_REDUCE,\n \"fa2-stats-finalize\": FA2_STATS_FINALIZE,\n \"fa2-attraction\": FA2_ATTRACTION,\n \"fa2-repulsion-exact\": FA2_REPULSION_EXACT,\n \"fa2-speed-finalize\": FA2_SPEED_FINALIZE,\n \"fa2-integrate\": FA2_INTEGRATE,\n \"fa2-to-scene\": FA2_TO_SCENE,\n \"spmv-pull\": SPMV_PULL,\n \"pr-scale\": PR_SCALE,\n \"pr-finalize\": PR_FINALIZE,\n \"wcc-link-sample\": WCC_LINK_SAMPLE,\n \"wcc-link-edges\": WCC_LINK_EDGES,\n \"wcc-compress\": WCC_COMPRESS,\n \"wcc-sample\": WCC_SAMPLE,\n});\n\n/** THE registry (spec 3.5): every entry, keyed by id. */\nexport const KERNELS: Readonly<Record<KernelId, KernelEntry>> = REGISTRY as Readonly<Record<KernelId, KernelEntry>>;\n\n/** The bodies installed by setKernelBodyOverride (the sabotage seam of spec 11.9 item 1), by id. */\nconst bodyOverrides = new Map<KernelId, string>();\n\n/**\n * The entry of an id, or E_INVALID_ARGUMENT for an id that is not (yet) registered.\n * @param id - the module id\n * @returns the entry\n */\nfunction entryOf(id: KernelId): KernelEntry {\n const entry = REGISTRY[id];\n if (entry === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `unknown kernel id \"${id}\"`, {\n argument: \"id\",\n value: id,\n expected: Object.keys(REGISTRY),\n });\n }\n return entry;\n}\n\n/**\n * A WgslModuleSpec for a variant: the entry plus the overrides / snippets given; unknown override names are\n * rejected at compose time. A body override installed by setKernelBodyOverride is used instead of the entry's\n * body.\n * @param id - the module id\n * @param overrides - the override values of this variant (the five standard names and the entry's overrideDecls)\n * @param snippets - the texts substituted at the body's `//@@NAME@@` markers\n * @returns the spec the PipelineCache compiles\n */\nexport function kernelSpec(\n id: KernelId,\n overrides?: Readonly<Record<string, number | boolean>>,\n snippets?: Readonly<Record<string, string>>,\n): WgslModuleSpec {\n const entry = entryOf(id);\n return {\n id: entry.id,\n body: bodyOverrides.get(id) ?? entry.body,\n bindings: entry.bindings,\n overrideDecls: entry.overrideDecls,\n overrides: overrides ?? {},\n needs: entry.needs,\n uniforms: entry.uniforms,\n snippets,\n };\n}\n\n/**\n * The sabotage seam (spec 11.9 item 1): replaces an entry's body for specs created afterwards (null restores).\n * Tests use a FRESH context per mutation because the pipeline key does not include the body.\n * @internal\n * @param id - the module id\n * @param body - the replacement body, or null to restore the normative one\n */\nexport function setKernelBodyOverride(id: KernelId, body: string | null): void {\n entryOf(id);\n if (body === null) {\n bodyOverrides.delete(id);\n } else {\n bodyOverrides.set(id, body);\n }\n}\n\n/**\n * The group-0 graph bindings of a core with the dummy rules applied (spec 3.5, 4.1): colIdx <- rowPtr when null,\n * weights <- colIdx ?? rowPtr when null, perm <- rowPtr when null. `weights` is the binding to use in the weights\n * slot: omitted -> core.weights (degree, segmented-reduce); a layout passes its RESOLVED weights\n * (ModelResources.weights, 3.13), null meaning \"attract with 1.0\" even on a weighted snapshot.\n * @param core - the resident core arrays of a snapshot\n * @param perm - the degreeOrder row permutation, or null (rowPtr is bound as the dummy)\n * @param weights - the weights binding to use; undefined takes the core's, null binds the colIdx dummy\n * @returns the four bindings in slot order\n */\nexport function graphBindings(\n core: CoreBinding,\n perm: Binding | null,\n weights?: Binding | null,\n): Readonly<Record<\"rowPtr\" | \"colIdx\" | \"weights\" | \"perm\", Binding>> {\n const colIdx = core.colIdx ?? core.rowPtr;\n const resolved = weights === undefined ? core.weights : weights;\n return {\n rowPtr: core.rowPtr,\n colIdx,\n weights: resolved ?? colIdx,\n perm: perm ?? core.rowPtr,\n };\n}\n\n/**\n * The override values graphBindings implies: USE_PERM = perm !== null, HAS_WEIGHTS = (weights === undefined ?\n * core.weights : weights) !== null.\n * @param core - the resident core arrays of a snapshot\n * @param perm - the row permutation binding, or null\n * @param weights - the weights binding to use; undefined takes the core's, null means \"unweighted\"\n * @returns the two standard override values of the variant\n */\nexport function graphOverrides(\n core: CoreBinding,\n perm: Binding | null,\n weights?: Binding | null,\n): Readonly<{ USE_PERM: boolean; HAS_WEIGHTS: boolean }> {\n const resolved = weights === undefined ? core.weights : weights;\n return { USE_PERM: perm !== null, HAS_WEIGHTS: resolved !== null };\n}\n","/**\n * `degree(ctx, s)` -- the walking-skeleton algorithm, kept public as a diagnostic (spec 3.3, 11.5): the out-degree of\n * every node computed on the device by the row-walking `degree` kernel (4.5) over the resident core of the snapshot,\n * with the group-0 dummy-binding pattern of spec 3.5 (`colIdx` in the `weights` slot when the snapshot is unweighted,\n * `rowPtr` in the `perm` slot because P1-P3 pass no row permutation, so `USE_PERM` is false). The result equals\n * `snapshot.outDegree()`; the point of the kernel is to prove the upload, bind, dispatch and readback path end to end\n * on every adapter (bitwise identical across adapters, spec 11.5), not to be faster than the CPU (the README says\n * so).\n *\n * Contract (3.12): `ctx.assertReady()` first; `nodeCount === 0` returns an empty `Uint32Array` (or `dest`) with no\n * GPU work (spec 5.6: there is no work, which is not a fallback); an already-aborted `signal` is `E_ABORTED` before\n * any work; `dest` must be a `Uint32Array` of length n over an `ArrayBuffer`; a windowed core is `E_TOO_LARGE\n * { path: \"windowed\", algorithm: \"degree\" }` until P4 executes windows -- `residency.core()` (3.8) throws that error\n * itself with `algorithm: null` before it would ever return a windowed `CoreBinding`, so `degree` catches it and\n * re-throws the same error with `algorithm: \"degree\"` (the 3.12 detail) instead of testing `core.plan`, which never\n * observes \"windowed\" in P1-P3; `arcCount === 0` skips the dispatch (only `rowPtr` is resident)\n * and the result is zeros; otherwise ONE dispatch over rows [0, n) with `accumulate = 0` (every row is written, so no\n * fill precedes it), a readback into the result, `onProgress(1, 1)`, and the scratch returned in a finally. Two runs\n * are bitwise identical (spec 11.9 item 4).\n */\n\nimport { type GraphSnapshot, type U32 } from \"@graphty/graph-format\";\n\nimport { type GpuContext } from \"../context.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { isWebGpuGraphError, WebGpuGraphError } from \"../errors.js\";\nimport { plan1d } from \"../kernel/dispatch.js\";\nimport { graphBindings, graphOverrides, kernelSpec, RANGE_PARAMS } from \"../kernels.js\";\nimport { type CoreBinding } from \"../memory/residency.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type GpuRunOptions } from \"../types/run.js\";\n\n/**\n * Validates `options.dest` for a result of `n` elements.\n * @param dest - the caller's destination array, if any\n * @param n - the node count\n * @returns the destination as a U32, or null when none was given\n */\nfunction checkDest(dest: Float32Array | Uint32Array | undefined, n: number): U32 | null {\n if (dest === undefined) {\n return null;\n }\n if (dest instanceof Uint32Array && dest.length === n && dest.buffer instanceof ArrayBuffer) {\n return dest as U32;\n }\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `degree: dest must be a Uint32Array of length ${n} over an ArrayBuffer`,\n {\n argument: \"dest\",\n value: `${dest.constructor.name}(${dest.length})`,\n expected: `Uint32Array(${n}) over an ArrayBuffer`,\n },\n );\n}\n\n/**\n * Uploads (or finds) the core through the residency; a windowed plan, which the residency reports as `E_TOO_LARGE\n * { path: \"windowed\", algorithm: null }` (3.8), is re-thrown with `algorithm: \"degree\"` (3.12) and its other details\n * (`needed`, `limit`, `path`) kept. Every other error passes through untouched.\n * @param ctx - the context whose residency holds the core\n * @param s - the snapshot\n * @returns the resident core binding (arena or perArray)\n */\nfunction coreOf(ctx: GpuContext, s: GraphSnapshot): CoreBinding {\n try {\n return ctx.residency.core(s);\n } catch (error: unknown) {\n if (isWebGpuGraphError(error) && error.code === \"E_TOO_LARGE\" && error.details.path === \"windowed\") {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n \"degree: the arc arrays need a windowed upload, which P1-P3 plan but do not execute\",\n { ...error.details, algorithm: \"degree\" },\n );\n }\n throw error;\n }\n}\n\n/**\n * The walking-skeleton kernel, kept public as a diagnostic (spec 3.3): out-degree per node through the row-walking\n * gather with the USE_PERM dummy pattern; equals snapshot.outDegree().\n * @param ctx - the context whose device runs the kernel\n * @param s - the snapshot (uploaded through ctx.residency, or found there)\n * @param options - dest / signal / onProgress (spec 3.3). PLAN DECISION: spelled `?: GpuRunOptions` rather than the\n * contract's `?: GpuRunOptions | undefined` because the root ESLint rule no-duplicate-type-constituents rejects the\n * explicit undefined on an optional parameter (the call signature is identical; P1-T3 made the same choice).\n * @returns the out-degree of every node, index-aligned (`dest` itself when given)\n */\nexport async function degree(ctx: GpuContext, s: GraphSnapshot, options?: GpuRunOptions): Promise<U32> {\n ctx.assertReady();\n const n = s.nodeCount;\n const dest = checkDest(options?.dest, n);\n if (options?.signal?.aborted) {\n throw new WebGpuGraphError(\"E_ABORTED\", \"degree: the signal was aborted before any work started\", {});\n }\n if (n === 0) {\n options?.onProgress?.(1, 1);\n return dest ?? new Uint32Array(0);\n }\n const core = coreOf(ctx, s);\n if (s.arcCount === 0) {\n const zeros = dest ?? new Uint32Array(n);\n zeros.fill(0);\n options?.onProgress?.(1, 1);\n return zeros;\n }\n const byteLength = n * 4;\n const out = ctx.pool.acquire(\n byteLength,\n BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST,\n \"degree/out\",\n );\n const params = ctx.pool.acquire(\n RANGE_PARAMS.byteLength,\n BufferUsage.UNIFORM | BufferUsage.COPY_DST,\n \"degree/params\",\n );\n try {\n await ctx.allocator.check();\n const kernel = await ctx.pipelines.kernel(kernelSpec(\"degree\", graphOverrides(core, null)));\n const bytes = new ArrayBuffer(RANGE_PARAMS.byteLength);\n RANGE_PARAMS.write(new DataView(bytes), { start: 0, end: n, arcBase: 0, arcEnd: s.arcCount, accumulate: 0, n });\n ctx.device.queue.writeBuffer(params, 0, bytes);\n const outBinding: Binding = { buffer: out, offset: 0, size: byteLength, window: null };\n const paramsBinding: Binding = { buffer: params, offset: 0, size: RANGE_PARAMS.byteLength, window: null };\n const bound = kernel.bind({ ...graphBindings(core, null), out: outBinding, P: paramsBinding });\n const encoder = ctx.device.createCommandEncoder({ label: \"degree\" });\n const pass = encoder.beginComputePass({ label: \"degree\" });\n kernel.dispatch(pass, bound, plan1d(n, ctx.workgroupSize, ctx.caps), [0]);\n pass.end();\n ctx.device.queue.submit([encoder.finish()]);\n ctx.assertReady();\n const result = await ctx.readback.read(out, byteLength, dest ?? undefined);\n ctx.assertReady();\n options?.onProgress?.(1, 1);\n return dest ?? new Uint32Array(result);\n } finally {\n ctx.pool.release(params);\n ctx.pool.release(out);\n }\n}\n","/**\n * The CommandBatch of spec 5.8: one GPUCommandEncoder, one compute pass per \"phase\" (a pass may hold\n * many dispatches; dispatches inside a pass are ordered), the staging copies of every readback\n * request at the end, and ONE queue.submit. The batch borrows one slot of the Readback ring for its\n * lifetime (spec 4.4) and returns it when its readback settles -- resolved, discarded or rejected --\n * so the ring never grows because of a slot left pending. mapAsync on that slot is the completion\n * signal; a batch never calls onSubmittedWorkDone.\n *\n * Errors (spec 5.7): under Dawn-node an uncapturederror is delivered SYNCHRONOUSLY inside the API\n * call that fails, so an error pending in the context's slot when submit() runs belongs to this batch\n * and rejects ITS OWN readback (an invalid command buffer is a no-op submit; the staging bytes would be\n * stale). In browsers delivery is asynchronous: the batch takes the slot again after its map completes,\n * and whatever arrives later is thrown by the context's next public call. Device loss is raced against\n * the map, so a readback rejects E_DEVICE_LOST whether the runtime rejects, resolves or never settles\n * the pending map of a destroyed buffer; the slot goes back only once the map has settled (or the grace\n * ran out), because a staging buffer is never unmapped while its map is pending (readback.ts).\n */\n\nimport type { AllocationTracker } from \"../device/error-scope.js\";\nimport { deviceLostError } from \"../device/lost.js\";\nimport { isWebGpuGraphError, WebGpuGraphError } from \"../errors.js\";\nimport type { Readback, StagingSlot } from \"../memory/readback.js\";\nimport type { Binding } from \"../types/memory.js\";\nimport type { Profiler } from \"./profiler.js\";\n\n/** How long a batch waits for the context's loss fan-out after its map rejected with a foreign error (a destroyed buffer rejects before device.lost settles), and for the runtime to settle a pending map after the loss won the race. */\nconst LOSS_GRACE_MS = 2000;\n\n/**\n * Resolves when the promise settles either way, or after the grace (a runtime that never settles a pending map).\n * @param pending - the promise\n * @param graceMs - the ceiling\n */\nasync function settled(pending: Promise<unknown>, graceMs: number): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const grace = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, graceMs);\n });\n await Promise.race([\n pending.then(\n () => undefined,\n () => undefined,\n ),\n grace,\n ]);\n clearTimeout(timer);\n}\n\n/**\n * A plain message for a thrown value (the house pattern of graph-io's report.ts).\n * @param error - whatever the runtime rejected with\n * @returns the Error message, the string itself, or a typeof note\n */\nfunction messageOf(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === \"string\") {\n return error;\n }\n return `non-error thrown (${typeof error})`;\n}\n\n/** What a CommandBatch needs of its owner (GpuContext satisfies it structurally; kernel/ never imports context.ts). */\nexport interface BatchHost {\n readonly device: GPUDevice;\n readonly readback: Readback;\n readonly profiler: Profiler | null;\n readonly allocator: AllocationTracker;\n assertReady(): void;\n takePendingError(): WebGpuGraphError | null;\n nextBatchId(): number;\n /** Registers a device-loss listener and returns the unregister function (GpuContext.onLost, contract 3.5): the batch races its map against loss. PLAN DECISION 1: an amendment to contract 3.9, which declares the seven members above. */\n onLost(listener: (info: GPUDeviceLostInfo) => void): () => void;\n}\n\n/** A readback scheduled into the batch's staging slot: `offset` is the slot-relative byte offset the caller reads at. */\nexport interface ReadbackRequest {\n readonly src: GPUBuffer;\n readonly srcOffset: number;\n readonly byteLength: number;\n readonly offset: number;\n}\n\n/** What submit() returns (spec 5.8). `readback` resolves with the mapped bytes COPIED out (one ArrayBuffer holding every request at its offset) after allocator.check(); it rejects with E_VALIDATION { batchId } when the pending-error slot held an error right after submit and with E_DEVICE_LOST after loss; a discarded batch resolves an empty ArrayBuffer (see discard()). */\nexport interface SubmittedBatch {\n readonly id: number;\n readonly generation: number;\n readonly readback: Promise<ArrayBuffer>;\n /** Marks the batch stale: its readback still awaits mapAsync (so the slot is returned) but resolves with an empty ArrayBuffer and the caller ignores it (spec 7.19 item 6). */\n discard(): void;\n}\n\n/** The discard flag shared by a handle and its readback. */\ninterface DiscardState {\n discarded: boolean;\n}\n\n/** Records dispatches / copies into one encoder and submits once (spec 5.8). */\nexport class CommandBatch {\n readonly id: number;\n readonly generation: number;\n readonly label: string;\n private readonly host: BatchHost;\n private readonly encoder: GPUCommandEncoder;\n private readonly requests: ReadbackRequest[] = [];\n private openPass: GPUComputePassEncoder | null = null;\n private dispatchCount = 0;\n private stagingBytes = 0;\n private slot: StagingSlot | null = null;\n private submitted = false;\n\n /**\n * Creates the encoder; the id comes from host.nextBatchId().\n * @param host - the owner (the GpuContext)\n * @param label - names the encoder, its passes and the E_VALIDATION details\n * @param generation - the simulation generation the batch carries (default 0)\n */\n constructor(host: BatchHost, label: string, generation?: number) {\n this.host = host;\n this.id = host.nextBatchId();\n this.generation = generation ?? 0;\n this.label = label;\n this.encoder = host.device.createCommandEncoder({ label: `batch/${label}#${this.id}` });\n }\n\n /**\n * Dispatch count recorded so far (tests bound it).\n * @returns the number of dispatchWorkgroups / dispatchWorkgroupsIndirect calls on this batch's passes\n */\n get dispatches(): number {\n return this.dispatchCount;\n }\n\n /**\n * Begins a compute pass (ending the previous one); with a profiler present the pass carries timestampWrites and\n * `label` names it in Profiler.resolveInto / timings.\n * @param label - the pass name\n * @returns the pass encoder kernels dispatch into\n */\n pass(label: string): GPUComputePassEncoder {\n this.assertOpen(\"pass\");\n this.endPass();\n const descriptor: GPUComputePassDescriptor = { label: `batch/${this.label}#${this.id}/${label}` };\n const timestampWrites = this.host.profiler?.beginPass(label);\n if (timestampWrites !== undefined) {\n descriptor.timestampWrites = timestampWrites;\n }\n const pass = this.encoder.beginComputePass(descriptor);\n this.countDispatches(pass);\n this.openPass = pass;\n return pass;\n }\n\n /** Ends the open pass, if any. */\n endPass(): void {\n if (this.openPass !== null) {\n this.openPass.end();\n this.openPass = null;\n }\n }\n\n /**\n * copyBufferToBuffer between two bindings (after endPass).\n * @param src - the source range\n * @param dst - the destination range\n * @param byteLength - a positive multiple of 4 no larger than either binding\n */\n copy(src: Binding, dst: Binding, byteLength: number): void {\n this.assertOpen(\"copy\");\n this.checkByteLength(byteLength);\n if (byteLength > src.size || byteLength > dst.size) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `copy of ${byteLength} bytes exceeds a binding (src ${src.size}, dst ${dst.size})`,\n {\n argument: \"byteLength\",\n value: byteLength,\n expected: `<= ${Math.min(src.size, dst.size)}`,\n },\n );\n }\n this.endPass();\n this.encoder.copyBufferToBuffer(src.buffer, src.offset, dst.buffer, dst.offset, byteLength);\n }\n\n /**\n * Schedules a copy of `byteLength` bytes from `src` into the borrowed staging slot; the slot is borrowed at the\n * first request and re-borrowed larger when the sum of requests outgrows it (nothing is recorded before submit).\n * @param src - the source buffer\n * @param srcOffset - a non-negative multiple of 4\n * @param byteLength - a positive multiple of 4 with srcOffset + byteLength <= src.size\n * @returns the request; `offset` is where the caller reads inside the readback bytes\n */\n readback(src: GPUBuffer, srcOffset: number, byteLength: number): ReadbackRequest {\n this.assertOpen(\"readback\");\n this.checkByteLength(byteLength);\n if (!Number.isInteger(srcOffset) || srcOffset < 0 || srcOffset % 4 !== 0 || srcOffset + byteLength > src.size) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `readback of [${srcOffset}, ${srcOffset + byteLength}) is outside the ${src.size}-byte source or not 4-aligned`,\n {\n argument: \"srcOffset\",\n value: srcOffset,\n expected: `a multiple of 4 with srcOffset + byteLength <= ${src.size}`,\n },\n );\n }\n const request: ReadbackRequest = { src, srcOffset, byteLength, offset: this.stagingBytes };\n this.requests.push(request);\n this.stagingBytes += byteLength;\n this.ensureSlot(this.stagingBytes);\n return request;\n }\n\n /**\n * Records `resolveQuerySet` after ending the open pass; used by Profiler.resolveInto only.\n * @internal\n * @param querySet - the timestamp query set\n * @param firstQuery - first query index\n * @param queryCount - number of queries\n * @param destination - a QUERY_RESOLVE | COPY_SRC buffer written at offset 0\n */\n resolveQuerySet(querySet: GPUQuerySet, firstQuery: number, queryCount: number, destination: GPUBuffer): void {\n this.assertOpen(\"resolveQuerySet\");\n this.endPass();\n this.encoder.resolveQuerySet(querySet, firstQuery, queryCount, destination, 0);\n }\n\n /**\n * Ends passes, records the staging copies, submits, checks the pending-error slot (spec 5.7), returns the handle.\n * A batch can be submitted once; submit() after device loss throws E_DEVICE_LOST.\n * @returns the submitted-batch handle\n */\n submit(): SubmittedBatch {\n this.assertOpen(\"submit\");\n this.submitted = true;\n this.endPass();\n const { slot } = this;\n const pendingBefore = this.host.takePendingError();\n try {\n this.host.assertReady();\n } catch (error) {\n this.releaseSlot();\n throw error;\n }\n if (slot !== null) {\n for (const request of this.requests) {\n this.encoder.copyBufferToBuffer(\n request.src,\n request.srcOffset,\n slot.buffer,\n request.offset,\n request.byteLength,\n );\n }\n }\n const commandBuffer = this.encoder.finish({ label: `batch/${this.label}#${this.id}` });\n this.host.device.queue.submit([commandBuffer]);\n // the slot is drained a second time so a finish() / submit() error raised by a command buffer the first error\n // already invalidated never leaks to the next public call; the FIRST error is the one reported\n const pendingAfter = this.host.takePendingError();\n const pending = pendingBefore ?? pendingAfter;\n const state: DiscardState = { discarded: false };\n const readback = pending === null ? this.awaitReadback(slot, state) : this.rejectReadback(pending);\n return {\n id: this.id,\n generation: this.generation,\n readback,\n discard: (): void => {\n state.discarded = true;\n },\n };\n }\n\n private rejectReadback(pending: WebGpuGraphError): Promise<ArrayBuffer> {\n this.releaseSlot();\n return Promise.reject(this.attribute(pending));\n }\n\n private async awaitReadback(slot: StagingSlot | null, state: DiscardState): Promise<ArrayBuffer> {\n if (slot === null) {\n await this.host.allocator.check();\n return new ArrayBuffer(0);\n }\n const total = this.stagingBytes;\n let unregister: () => void = (): void => undefined;\n const lost = new Promise<never>((_resolve, reject) => {\n unregister = this.host.onLost((info) => {\n reject(deviceLostError(info));\n });\n });\n void lost.catch(() => undefined);\n const mapped = this.host.readback.mapSlot(slot, total);\n void mapped.catch(() => undefined);\n let bytes: ArrayBuffer;\n try {\n await Promise.race([mapped, lost]);\n this.host.assertReady();\n bytes = state.discarded ? new ArrayBuffer(0) : slot.buffer.getMappedRange(0, total).slice(0);\n } catch (error) {\n // the loss may have won the race: let the runtime settle the map before the slot is unmapped and returned\n await settled(mapped, LOSS_GRACE_MS);\n this.releaseSlot();\n throw await this.classify(error, lost);\n } finally {\n unregister();\n }\n this.releaseSlot();\n await this.host.allocator.check();\n return bytes;\n }\n\n private async classify(error: unknown, lost: Promise<never>): Promise<WebGpuGraphError> {\n if (isWebGpuGraphError(error)) {\n return error.code === \"E_DEVICE_LOST\" || error.code === \"E_DISPOSED\" ? error : this.attribute(error);\n }\n try {\n this.host.assertReady();\n } catch (state) {\n if (isWebGpuGraphError(state)) {\n return state.code === \"E_DEVICE_LOST\" || state.code === \"E_DISPOSED\" ? state : this.attribute(state);\n }\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const grace = new Promise<null>((resolve) => {\n timer = setTimeout(() => {\n resolve(null);\n }, LOSS_GRACE_MS);\n });\n const late = await Promise.race([\n lost.then(\n () => null,\n (reason: unknown) => reason,\n ),\n grace,\n ]);\n clearTimeout(timer);\n if (isWebGpuGraphError(late)) {\n return late;\n }\n const message = messageOf(error);\n return new WebGpuGraphError(\n \"E_VALIDATION\",\n `mapAsync failed for batch ${this.id} \"${this.label}\": ${message}`,\n {\n label: this.label,\n message,\n batchId: this.id,\n },\n );\n }\n\n private attribute(error: WebGpuGraphError): WebGpuGraphError {\n return new WebGpuGraphError(error.code, `${error.message} (delivered to batch ${this.id} \"${this.label}\")`, {\n ...error.details,\n batchId: this.id,\n batchLabel: this.label,\n });\n }\n\n private ensureSlot(byteLength: number): void {\n if (this.slot !== null && this.slot.capacity >= byteLength) {\n return;\n }\n this.releaseSlot();\n this.slot = this.host.readback.borrowSlot(byteLength);\n }\n\n private releaseSlot(): void {\n if (this.slot === null) {\n return;\n }\n const { slot } = this;\n this.slot = null;\n try {\n this.host.readback.returnSlot(slot);\n } catch (error) {\n if (!isWebGpuGraphError(error) || error.code !== \"E_DISPOSED\") {\n throw error;\n }\n }\n }\n\n private countDispatches(pass: GPUComputePassEncoder): void {\n const direct = pass.dispatchWorkgroups.bind(pass);\n const indirect = pass.dispatchWorkgroupsIndirect.bind(pass);\n pass.dispatchWorkgroups = (x: number, y?: number, z?: number): undefined => {\n this.dispatchCount += 1;\n direct(x, y, z);\n return undefined;\n };\n pass.dispatchWorkgroupsIndirect = (buffer: GPUBuffer, offset: number): undefined => {\n this.dispatchCount += 1;\n indirect(buffer, offset);\n return undefined;\n };\n }\n\n private assertOpen(operation: string): void {\n if (this.submitted) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${operation}() after submit() on batch ${this.id} \"${this.label}\"`,\n {\n argument: operation,\n value: this.id,\n expected: \"a batch that has not been submitted\",\n },\n );\n }\n }\n\n private checkByteLength(byteLength: number): void {\n if (!Number.isInteger(byteLength) || byteLength <= 0 || byteLength % 4 !== 0) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `byteLength ${byteLength} is not a positive multiple of 4`,\n {\n argument: \"byteLength\",\n value: byteLength,\n expected: \"a positive multiple of 4\",\n },\n );\n }\n }\n}\n","/**\n * The UniformRing of spec 5.3: one UNIFORM buffer holding UNIFORM_SLOT_BYTES-stride slots for the\n * per-iteration params of a batch. A batch reserves k contiguous slots, writes their values into the\n * host shadow, flushes them with ONE queue.writeBuffer and records k dispatches that select their slot\n * through a dynamic offset -- no per-iteration writeBuffer and no host round trip. The stride is 256\n * because minUniformBufferOffsetAlignment is 256 on every runtime the package targets (the Dawn-node\n * ADAPTER advertises 64, which the package never requests; spec 2.6).\n */\n\nimport { UNIFORM_SLOT_BYTES } from \"../constants.js\";\nimport type { AllocationTracker } from \"../device/error-scope.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport type { Binding } from \"../types/memory.js\";\nimport type { UniformBlock, UniformValues } from \"./struct-block.js\";\n\n/** One UNIFORM buffer with UNIFORM_SLOT_BYTES-stride slots for the per-iteration params of a batch (spec 5.3). */\nexport class UniformRing {\n /** Number of slots. */\n readonly slots: number;\n private readonly device: GPUDevice;\n private readonly allocator: AllocationTracker;\n private readonly buffer: GPUBuffer;\n private readonly label: string;\n private readonly shadow: ArrayBuffer;\n private readonly view: DataView;\n private next = 0;\n private dirtyLo = -1;\n private dirtyHi = -1;\n private destroyed = false;\n\n /**\n * Creates the ring buffer (`slots x UNIFORM_SLOT_BYTES` bytes, UNIFORM | COPY_DST) through the allocator.\n * @param device - the device the buffer belongs to\n * @param allocator - the context's OOM-scoped allocator (the buffer is destroyed through it)\n * @param slots - number of slots; E_INVALID_ARGUMENT unless a positive integer\n * @param label - the buffer label\n */\n constructor(device: GPUDevice, allocator: AllocationTracker, slots: number, label: string) {\n if (!Number.isInteger(slots) || slots < 1) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformRing \"${label}\": slots must be a positive integer, got ${slots}`,\n {\n argument: \"slots\",\n value: slots,\n expected: \"an integer >= 1\",\n },\n );\n }\n this.device = device;\n this.allocator = allocator;\n this.slots = slots;\n this.label = label;\n this.shadow = new ArrayBuffer(slots * UNIFORM_SLOT_BYTES);\n this.view = new DataView(this.shadow);\n this.buffer = allocator.createBuffer({\n label,\n size: slots * UNIFORM_SLOT_BYTES,\n usage: BufferUsage.UNIFORM | BufferUsage.COPY_DST,\n });\n }\n\n /**\n * The whole-buffer binding a kernel binds once (size = the block's byteLength; the slot is the dynamic offset).\n * @param block - the params block the kernel declares for this binding\n * @returns the binding at offset 0 of the ring buffer\n */\n binding(block: UniformBlock): Binding {\n this.assertLive();\n this.assertFits(block);\n return { buffer: this.buffer, offset: 0, size: block.byteLength, window: null };\n }\n\n /**\n * Byte offset of a slot (the dynamic offset a dispatch passes for it).\n * @param slot - a slot index in [0, slots)\n * @returns slot x UNIFORM_SLOT_BYTES\n */\n offsetOf(slot: number): number {\n this.checkSlot(slot);\n return slot * UNIFORM_SLOT_BYTES;\n }\n\n /**\n * Reserves `count` contiguous slots for a batch, wrapping to 0 when the tail is too short; E_INVALID_ARGUMENT when count > slots.\n * @param count - slots needed, in [1, slots]\n * @returns the first slot of the reservation\n */\n reserve(count: number): number {\n this.assertLive();\n if (!Number.isInteger(count) || count < 1 || count > this.slots) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformRing \"${this.label}\": cannot reserve ${count} of ${this.slots} slots`,\n {\n argument: \"count\",\n value: count,\n expected: `an integer in [1, ${this.slots}]`,\n },\n );\n }\n if (this.next + count > this.slots) {\n this.next = 0;\n }\n const first = this.next;\n this.next += count;\n return first;\n }\n\n /**\n * Writes one block's values into a slot of the host shadow; `flush()` sends the dirty range with one writeBuffer.\n * @param slot - the slot to fill\n * @param block - the block whose layout the bytes follow\n * @param values - the field values (a missing field is written as 0 by the block)\n */\n write(slot: number, block: UniformBlock, values: UniformValues): void {\n this.checkSlot(slot);\n this.assertFits(block);\n block.write(this.view, values, slot * UNIFORM_SLOT_BYTES);\n if (this.dirtyLo < 0 || slot < this.dirtyLo) {\n this.dirtyLo = slot;\n }\n if (slot > this.dirtyHi) {\n this.dirtyHi = slot;\n }\n }\n\n /**\n * queue.writeBuffer of the dirty slots (called by the batch driver before submit): one call covering\n * [lowest dirty slot, highest dirty slot]; nothing when no slot is dirty.\n */\n flush(): void {\n this.assertLive();\n if (this.dirtyLo < 0) {\n return;\n }\n const begin = this.dirtyLo * UNIFORM_SLOT_BYTES;\n const end = (this.dirtyHi + 1) * UNIFORM_SLOT_BYTES;\n this.device.queue.writeBuffer(this.buffer, begin, this.shadow, begin, end - begin);\n this.dirtyLo = -1;\n this.dirtyHi = -1;\n }\n\n /** Destroys the buffer (through the allocator); idempotent. */\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n this.allocator.destroy(this.buffer);\n }\n\n private assertLive(): void {\n if (this.destroyed) {\n throw new WebGpuGraphError(\"E_DISPOSED\", `UniformRing \"${this.label}\" is destroyed`, { label: this.label });\n }\n }\n\n private checkSlot(slot: number): void {\n this.assertLive();\n if (!Number.isInteger(slot) || slot < 0 || slot >= this.slots) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformRing \"${this.label}\": slot ${slot} is outside [0, ${this.slots})`,\n {\n argument: \"slot\",\n value: slot,\n expected: `an integer in [0, ${this.slots})`,\n },\n );\n }\n }\n\n private assertFits(block: UniformBlock): void {\n if (block.byteLength > UNIFORM_SLOT_BYTES) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `UniformRing \"${this.label}\": block ${block.name} is ${block.byteLength} bytes, a slot holds ${UNIFORM_SLOT_BYTES}`,\n { argument: \"block\", value: block.name, expected: `byteLength <= ${UNIFORM_SLOT_BYTES}` },\n );\n }\n }\n}\n","/**\n * The ReduceScope an algorithm driver hands the primitives (contract 3.11), built over a GpuContext: `scratch` comes\n * from ONE Lease (released by `dispose()` in the algorithm's `finally`, spec 4.4) and `params` from a UniformRing\n * slot, so a batch of k iterations writes k parameter blocks into one buffer and dispatches with dynamic offsets\n * instead of allocating a uniform buffer per dispatch (spec 5.3). The src/ twin of the tests' testReduceScope\n * (test/helpers/segmented-reduce.ts). `slots` sizes the ring for the LARGEST batch the caller records: reserve()\n * wraps, so a ring too small silently reuses a slot another dispatch of the same batch still reads.\n */\n\nimport { type GpuContext } from \"../context.js\";\nimport { UniformRing } from \"../kernel/uniform-ring.js\";\nimport { type ReduceScope } from \"../primitives/reduce.js\";\n\n/** A ReduceScope over a context plus the two lifecycle calls an algorithm makes: flush() before submit, dispose() in its finally. */\nexport interface AlgorithmScope extends ReduceScope {\n /** queue.writeBuffer of the params slots written since the last flush (called before the batch is submitted). */\n flush(): void;\n /** Destroys the ring and releases every scratch buffer of the lease; idempotent. */\n dispose(): void;\n}\n\n/**\n * The scope of one algorithm call.\n * @param ctx - the context\n * @param label - the label prefix of the ring and every scratch buffer\n * @param slots - the params slots of the ring: at least the parameter blocks of the largest batch recorded\n * @returns the scope\n */\nexport function algorithmScope(ctx: GpuContext, label: string, slots: number): AlgorithmScope {\n const lease = ctx.pool.lease();\n const ring = new UniformRing(ctx.device, ctx.allocator, slots, `${label}/ring`);\n return {\n device: ctx.device,\n caps: ctx.caps,\n pipelines: ctx.pipelines,\n pool: ctx.pool,\n workgroupSize: ctx.workgroupSize,\n scratch: (byteLength, scratchLabel) => lease.storage(byteLength, `${label}/${scratchLabel}`),\n params(block, values) {\n const slot = ring.reserve(1);\n ring.write(slot, block, values);\n return { binding: ring.binding(block), offset: ring.offsetOf(slot) };\n },\n flush: () => {\n ring.flush();\n },\n dispose(): void {\n ring.destroy();\n lease.release();\n },\n };\n}\n","/**\n * Weakly connected components on the device (spec 8.3, 3.3): Afforest from GAP's cc.cc, step for step. `comp[v] = v`\n * by `fill` mode 1; two sampled link rounds over the r-th out-neighbour of every row plus a compress (one batch, no\n * readback); a 1,024-vertex label sample the host takes the mode of, which is the giant component (PD-12); then\n * each-edge-once link rounds over `edgeList()` -- correct for directed and undirected input alike, which is what\n * makes the partition the WEAK one -- in batches of four `link + compress` pairs, ONE readback of the changed flag per\n * batch, until the flag stays 0; a final compress; readback; `renumberPartition` on the host in first-seen order so\n * the labels are IDENTICAL to the CPU's (spec 9.7), or the raw roots when `renumber: false`.\n *\n * PLAN DECISION PD-4: the changed flag is the word at `comp[n]`, so the link kernels bind three buffers (design 8.10).\n * PLAN DECISION PD-11: `E_PARTITION` is NOT a pass-through. The kernels only ever store a value read out of `comp`,\n * which `fill` seeded with `v < n`, so no label can be `INVALID_INDEX`; the host verifies every label is `< n` before\n * `renumberPartition` sees it and raises `E_VALIDATION { label: \"connectedComponents/labels\" }` if that ever fails --\n * it would mean a GPU bug, which no caller could act on as `E_PARTITION`.\n * DEP-M8B-C: no `dedupe` primitive; Afforest's link is idempotent, so a repeated edge is a no-op.\n */\n\nimport { type GraphSnapshot, renumberPartition, type U32 } from \"@graphty/graph-format\";\n\nimport { U32_MAX } from \"../constants.js\";\nimport { type GpuContext } from \"../context.js\";\nimport { isWebGpuGraphError, WebGpuGraphError } from \"../errors.js\";\nimport { CommandBatch } from \"../kernel/batch.js\";\nimport { plan1d, planGridStride } from \"../kernel/dispatch.js\";\nimport { FILL_PARAMS, graphBindings, graphOverrides, kernelSpec, WCC_PARAMS } from \"../kernels.js\";\nimport { type CoreBinding } from \"../memory/residency.js\";\nimport { type ComponentsOptions, type GpuLabelResult } from \"../types/algorithms.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type GpuRunOptions } from \"../types/run.js\";\nimport { algorithmScope } from \"./scope.js\";\n\nconst ALGORITHM = \"connectedComponents\";\n/** Link rounds between two reads of the changed flag (design 8.3: \"checked every 4 rounds\"). */\nconst ROUNDS_PER_BATCH = 4;\n/** The edge-round cap; the flag not settling by then is a hard error, never a fallback. */\nconst MAX_WCC_ROUNDS = 64;\n/** The sampled vertices the giant component is found from (design 8.3). */\nconst SAMPLE_SIZE = 1024;\n/** The bound of a CAS retry loop and of a compress walk (PD-5). */\nconst MAX_STEPS = 1024;\n/** Params slots of the largest batch: four link + four compress blocks; the setup batch uses fill + 2 links + compress. */\nconst RING_SLOTS = 2 * ROUNDS_PER_BATCH;\n\n/**\n * Validates `options.dest` for a label result of `n` elements.\n * @param dest - the caller's destination array, if any\n * @param n - the node count\n * @returns the destination as a U32, or null when none was given\n */\nfunction checkDest(dest: Float32Array | Uint32Array | undefined, n: number): U32 | null {\n if (dest === undefined) {\n return null;\n }\n if (dest instanceof Uint32Array && dest.length === n && dest.buffer instanceof ArrayBuffer) {\n return dest as U32;\n }\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${ALGORITHM}: dest must be a Uint32Array of length ${n} over an ArrayBuffer`,\n {\n argument: \"dest\",\n value: `${dest.constructor.name}(${dest.length})`,\n expected: `Uint32Array(${n}) over an ArrayBuffer`,\n },\n );\n}\n\n/**\n * The resident core; a windowed plan (`E_TOO_LARGE { path: \"windowed\", algorithm: null }`, spec 3.8) is re-thrown\n * with the algorithm name (3.12). Transcribed from degree.ts, whose coreOf is module-private.\n * @param ctx - the context\n * @param s - the snapshot\n * @returns the core binding\n */\nfunction coreOf(ctx: GpuContext, s: GraphSnapshot): CoreBinding {\n try {\n return ctx.residency.core(s);\n } catch (error: unknown) {\n if (isWebGpuGraphError(error) && error.code === \"E_TOO_LARGE\" && error.details.path === \"windowed\") {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `${ALGORITHM}: the arc arrays need a windowed upload, which P1-P3 plan but do not execute`,\n { ...error.details, algorithm: ALGORITHM },\n );\n }\n throw error;\n }\n}\n\n/**\n * Whole-buffer binding of a scratch buffer over its first `size` bytes.\n * @param buffer - the buffer\n * @param size - the bound byte length\n * @returns the binding\n */\nfunction bindingOf(buffer: GPUBuffer, size: number): Binding {\n return { buffer, offset: 0, size, window: null };\n}\n\n/**\n * The result object over a label array whose labels are all `< n`: `count` blocks, `groups()` built lazily once in\n * first-seen label order (which for renumbered labels is index order).\n * @param labels - the labels\n * @param count - the block count\n * @returns the result\n */\nfunction labelResult(labels: U32, count: number): GpuLabelResult {\n let groups: U32[] | null = null;\n return {\n labels,\n count,\n groups(): U32[] {\n if (groups !== null) {\n return groups;\n }\n const n = labels.length;\n const dense = new Uint32Array(n).fill(U32_MAX);\n const sizes = new Uint32Array(count);\n let next = 0;\n for (let v = 0; v < n; v++) {\n let k = dense[labels[v]];\n if (k === U32_MAX) {\n k = next++;\n dense[labels[v]] = k;\n }\n sizes[k]++;\n }\n const built: U32[] = Array.from(sizes, (size) => new Uint32Array(size));\n const filled = new Uint32Array(count);\n for (let v = 0; v < n; v++) {\n const k = dense[labels[v]];\n built[k][filled[k]++] = v;\n }\n groups = built;\n return built;\n },\n };\n}\n\n/**\n * The mode of the sampled labels (GAP's SampleFrequentElement, counted on the host; PD-12).\n * @param sample - the sampled labels\n * @returns the most frequent label\n */\nfunction modeOf(sample: Uint32Array): number {\n const counts = new Map<number, number>();\n let best = sample[0];\n let bestCount = 0;\n for (const label of sample) {\n const c = (counts.get(label) ?? 0) + 1;\n counts.set(label, c);\n if (c > bestCount) {\n best = label;\n bestCount = c;\n }\n }\n return best;\n}\n\n/**\n * Verifies every label is a node index (so `renumberPartition` can never see `INVALID_INDEX`, PD-11) and counts the\n * distinct roots.\n * @param raw - the labels the device produced\n * @returns the number of distinct labels\n */\nfunction checkLabels(raw: U32): number {\n const n = raw.length;\n const seen = new Uint8Array(n);\n let count = 0;\n for (let v = 0; v < n; v++) {\n const label = raw[v];\n if (label >= n) {\n throw new WebGpuGraphError(\"E_VALIDATION\", `${ALGORITHM}: labels[${v}] = ${label} is not a node index`, {\n label: `${ALGORITHM}/labels`,\n message: `the device produced a label outside [0, ${n})`,\n });\n }\n if (seen[label] === 0) {\n seen[label] = 1;\n count++;\n }\n }\n return count;\n}\n\n/**\n * Weakly connected components on the device (spec 3.3, 8.3): Afforest over the resident core and the edge list;\n * labels dense in first-seen order (`renumber: true`, the default) or the raw roots (`renumber: false`).\n * @param ctx - the context whose device runs the kernels\n * @param s - the snapshot (uploaded through ctx.residency, or found there)\n * @param options - renumber (default true), plus dest / signal / onProgress\n * @returns the labels, the component count and groups()\n */\nexport async function connectedComponents(\n ctx: GpuContext,\n s: GraphSnapshot,\n options?: ComponentsOptions & GpuRunOptions,\n): Promise<GpuLabelResult> {\n ctx.assertReady();\n const n = s.nodeCount;\n const renumber = options?.renumber !== false;\n const dest = checkDest(options?.dest, n);\n if (options?.signal?.aborted) {\n throw new WebGpuGraphError(\"E_ABORTED\", `${ALGORITHM}: the signal was aborted before any work started`, {});\n }\n if (n === 0) {\n options?.onProgress?.(1, 1);\n return labelResult(dest ?? new Uint32Array(0), 0);\n }\n const core = coreOf(ctx, s);\n if (s.arcCount === 0) {\n // every node is its own block, and the identity is already first-seen dense: renumbered and raw agree\n const labels = dest ?? new Uint32Array(n);\n for (let v = 0; v < n; v++) {\n labels[v] = v;\n }\n options?.onProgress?.(1, 1);\n return labelResult(labels, n);\n }\n const edges = ctx.residency.view(s, \"edgeList\");\n const edgeCount = edges.scalars.edgeCount[0];\n const scope = algorithmScope(ctx, ALGORITHM, RING_SLOTS);\n try {\n const compBytes = 4 * (n + 1);\n const comp = scope.scratch(compBytes, \"comp\");\n const items = Math.min(SAMPLE_SIZE, n);\n const hist = scope.scratch(4 * items, \"hist\");\n await ctx.allocator.check();\n const fill = await ctx.pipelines.kernel(kernelSpec(\"fill\", {}));\n const linkSample = await ctx.pipelines.kernel(kernelSpec(\"wcc-link-sample\", graphOverrides(core, null)));\n const linkEdges = await ctx.pipelines.kernel(kernelSpec(\"wcc-link-edges\", {}));\n const compress = await ctx.pipelines.kernel(kernelSpec(\"wcc-compress\", {}));\n const sample = await ctx.pipelines.kernel(kernelSpec(\"wcc-sample\", {}));\n const { queue } = ctx.device;\n const compBinding = bindingOf(comp, compBytes);\n const histBinding = bindingOf(hist, 4 * items);\n const rowPlan = planGridStride(n, ctx.workgroupSize, ctx.caps);\n const edgePlan = planGridStride(edgeCount, ctx.workgroupSize, ctx.caps);\n const flagIndex = n;\n const zero = new Uint32Array(1);\n const wccParams = (fields: {\n items: number;\n stride: number;\n r: number;\n giant: number;\n }): { binding: Binding; offset: number } =>\n scope.params(WCC_PARAMS, { n, ...fields, flagIndex, maxSteps: MAX_STEPS, pad0: 0 });\n const recordCompress = (pass: GPUComputePassEncoder): void => {\n const params = wccParams({ items: n, stride: rowPlan.stride ?? n, r: 0, giant: U32_MAX });\n compress.dispatch(pass, compress.bind({ comp: compBinding, P: params.binding }), rowPlan, [params.offset]);\n };\n const submit = (batch: CommandBatch): ReturnType<CommandBatch[\"submit\"]> => {\n scope.flush();\n return batch.submit();\n };\n\n // batch 1: comp[v] = v, the flag cleared, two sampled link rounds over the r-th out-neighbour, one compress\n queue.writeBuffer(comp, 4 * flagIndex, zero);\n const setup = new CommandBatch(ctx, `${ALGORITHM}/setup`);\n let pass = setup.pass(\"sample-rounds\");\n const fillParams = scope.params(FILL_PARAMS, { count: n, value: 0, mode: 1, pad0: 0 });\n fill.dispatch(\n pass,\n fill.bind({ dst: bindingOf(comp, 4 * n), P: fillParams.binding }),\n plan1d(n, ctx.workgroupSize, ctx.caps),\n [fillParams.offset],\n );\n const graph = graphBindings(core, null);\n for (let r = 0; r < 2; r++) {\n const params = wccParams({ items: n, stride: rowPlan.stride ?? n, r, giant: U32_MAX });\n const bound = linkSample.bind({ ...graph, comp: compBinding, P: params.binding });\n linkSample.dispatch(pass, bound, rowPlan, [params.offset]);\n }\n recordCompress(pass);\n setup.endPass();\n await submit(setup).readback;\n ctx.assertReady();\n\n // batch 2: the label sample, whose mode is the giant component\n const sampler = new CommandBatch(ctx, `${ALGORITHM}/sample`);\n pass = sampler.pass(\"sample\");\n const sampleParams = wccParams({ items, stride: 0, r: 0, giant: U32_MAX });\n sample.dispatch(\n pass,\n sample.bind({ comp: compBinding, hist: histBinding, P: sampleParams.binding }),\n plan1d(items, ctx.workgroupSize, ctx.caps),\n [sampleParams.offset],\n );\n sampler.endPass();\n const histRequest = sampler.readback(hist, 0, 4 * items);\n const histBytes = await submit(sampler).readback;\n ctx.assertReady();\n const giant = modeOf(new Uint32Array(histBytes, histRequest.offset, items));\n\n // the edge rounds: four (link + compress) per batch, one readback of the changed flag per batch\n const edgeBindings = { edgeSrc: edges.bindings.src, edgeDst: edges.bindings.dst, comp: compBinding };\n let rounds = 0;\n for (;;) {\n queue.writeBuffer(comp, 4 * flagIndex, zero);\n const batch = new CommandBatch(ctx, `${ALGORITHM}/rounds`);\n pass = batch.pass(\"edge-rounds\");\n for (let i = 0; i < ROUNDS_PER_BATCH; i++) {\n const params = wccParams({ items: edgeCount, stride: edgePlan.stride ?? edgeCount, r: 0, giant });\n const bound = linkEdges.bind({ ...edgeBindings, P: params.binding });\n linkEdges.dispatch(pass, bound, edgePlan, [params.offset]);\n recordCompress(pass);\n }\n batch.endPass();\n const flagRequest = batch.readback(comp, 4 * flagIndex, 4);\n const submitted = submit(batch);\n const back = await submitted.readback;\n rounds += ROUNDS_PER_BATCH;\n ctx.assertReady();\n if (options?.signal?.aborted) {\n throw new WebGpuGraphError(\"E_ABORTED\", `${ALGORITHM}: the signal was aborted`, { batchId: submitted.id });\n }\n if (new Uint32Array(back, flagRequest.offset, 1)[0] === 0) {\n break;\n }\n if (rounds >= MAX_WCC_ROUNDS) {\n throw new WebGpuGraphError(\n \"E_VALIDATION\",\n `${ALGORITHM}: the changed flag never settled in ${MAX_WCC_ROUNDS} rounds`,\n { label: ALGORITHM, message: `the changed flag never settled in ${MAX_WCC_ROUNDS} rounds` },\n );\n }\n }\n\n // the final compress, then the labels\n const final = new CommandBatch(ctx, `${ALGORITHM}/final`);\n recordCompress(final.pass(\"compress\"));\n final.endPass();\n await submit(final).readback;\n ctx.assertReady();\n const raw = !renumber && dest !== null ? dest : new Uint32Array(n);\n await ctx.readback.read(comp, 4 * n, raw);\n ctx.assertReady();\n const distinct = checkLabels(raw);\n options?.onProgress?.(1, 1);\n if (!renumber) {\n return labelResult(raw, distinct);\n }\n const { labels, count } = renumberPartition(raw, dest ?? undefined);\n return labelResult(labels, count);\n } finally {\n scope.dispose();\n }\n}\n","/**\n * The shape helpers every core-walking primitive shares (spec 4.1): the row count and the arc count a CoreBinding\n * implies, the windowed rejection of P4, and the ViewBinding -> CoreBinding adapter the P7 pull kernels need.\n * Moved out of segmented-reduce.ts by M8b-T4 so spmv.ts can use them without duplicating them; the `primitive`\n * argument keeps each caller's error details byte-identical to what they were when the helpers were private.\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type CoreBinding, type ViewBinding } from \"../memory/residency.js\";\nimport { type Binding } from \"../types/memory.js\";\n\n/**\n * The row count of a core from its rowPtr binding (4(n + 1) bytes).\n * @param core - the core\n * @param primitive - the caller's name, used in the message and the detail\n * @returns n\n */\nexport function rowCountOf(core: CoreBinding, primitive: string): number {\n const bytes = core.rowPtr.size;\n if (bytes < 4 || bytes % 4 !== 0) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${primitive}: a rowPtr binding of ${bytes} bytes is not 4(n + 1)`,\n {\n argument: \"core.rowPtr\",\n value: bytes,\n expected: \"a positive multiple of 4\",\n },\n );\n }\n return bytes / 4 - 1;\n}\n\n/**\n * The arc count a core implies: the colIdx binding is 4 bytes per arc, and a null colIdx is an arc-less snapshot.\n * @param core - the core\n * @returns the arc count\n */\nexport function arcCountOf(core: CoreBinding): number {\n return core.colIdx === null ? 0 : core.colIdx.size / 4;\n}\n\n/**\n * Rejects a windowed core (executed at P4).\n * @param core - the core\n * @param primitive - the caller's name, used in the message and the feature detail\n */\nexport function assertNotWindowed(core: CoreBinding, primitive: string): void {\n if (core.plan === \"windowed\" || core.windows !== null) {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", `${primitive}: windowed cores are executed at P4`, {\n feature: `${primitive}.windowed`,\n });\n }\n}\n\n/**\n * The CoreBinding shape of a residency VIEW (spec 4.3). residency.view() returns a ViewBinding -- a name -> Binding\n * record -- while graphBindings / graphOverrides and every core-walking primitive read rowPtr / colIdx / weights as\n * top-level fields (src/kernels.ts graphBindings / graphOverrides). This is the only adapter between the two in the\n * package. `plan` is \"perArray\" because views always upload per array (spec 4.3 lines 1182-1186) and `windows` is\n * null because a view is never windowed, which is what makes assertNotWindowed pass for a view. `serial` is -1: a\n * view is not a core and no caller of this function reads serial (nothing in src/primitives or src/algorithms\n * reads CoreBinding.serial).\n * @param v - the view binding, from residency.view(s, \"reverse\") or view(s, \"edgeList\")\n * @param arcCount - the arc count of the view, from v.scalars.arcCount[0]; it must agree with the colIdx binding,\n * which is what record() derives the arc window from (E_INVALID_ARGUMENT { argument: \"arcCount\" } otherwise)\n * @returns the equivalent CoreBinding\n */\nexport function coreOfView(v: ViewBinding, arcCount: number): CoreBinding {\n const { rowPtr }: { readonly rowPtr?: Binding | undefined } = v.bindings;\n if (rowPtr === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `the ${v.view} view has no rowPtr binding`, {\n argument: \"view\",\n value: v.view,\n expected: \"a view with a rowPtr binding (reverse)\",\n });\n }\n const colIdx = v.bindings.colIdx ?? null;\n const weights = v.bindings.weights ?? null;\n const bound = colIdx === null ? 0 : colIdx.size / 4;\n if (bound !== arcCount) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `the ${v.view} view binds ${bound} arcs but its arcCount scalar says ${arcCount}`,\n {\n argument: \"arcCount\",\n value: arcCount,\n expected: bound,\n },\n );\n }\n return Object.freeze({\n serial: -1,\n plan: \"perArray\" as const,\n rowPtr,\n colIdx,\n weights,\n arcToEdge: null,\n edgeToArc: null,\n windows: null,\n hasWeights: weights !== null,\n });\n}\n","/**\n * The segmented (per-row) reduction primitive of spec 6 row 3 in its thread-per-row tier (P2-P3): one invocation per\n * CSR row folds the caller's VALUE snippet over the row's arcs into `out[row]` (f32), a row with no arcs receiving\n * the identity element. The degree tiers of degreeOrder() (subgroup-per-row for the mid tier, workgroup-per-row for\n * the high tier) land at P4; until then `tiers !== null` is E_UNSUPPORTED and USE_PERM is always false (the perm\n * slot carries the rowPtr dummy of graphBindings). The row and arc counts come from the core's binding sizes: the\n * residency binds every array at its exact byte length (contract 3.8), so rowPtr is 4(n + 1) bytes and colIdx\n * 4 x arcCount.\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { plan1d } from \"../kernel/dispatch.js\";\nimport { type Kernel } from \"../kernel/kernel.js\";\nimport { graphBindings, graphOverrides, kernelSpec, RANGE_PARAMS } from \"../kernels.js\";\nimport { type CoreBinding } from \"../memory/residency.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { assertNotWindowed, rowCountOf } from \"./core-shape.js\";\nimport { type ReduceOp, type ReduceScope } from \"./reduce.js\";\n\n/** The degree tiers of degreeOrder(): the permutation binding and the CPU-side segmentOffsets [0, hiEnd, midEnd, lowEnd, n]. */\nexport interface DegreeTiers {\n readonly perm: Binding;\n readonly segmentOffsets: readonly [number, number, number, number, number];\n}\n\n/** Options of segmentedReduce. `valueSnippet` is the Gunrock-style functor: WGSL statements assigning `v` from (row, arc, nbr, weight) (4.5; `nbr` because `target` is a WGSL reserved word). */\nexport interface SegmentedReduceOptions {\n readonly op: ReduceOp;\n readonly valueSnippet: string;\n readonly tiers: DegreeTiers | null;\n readonly accumulate?: boolean | undefined;\n}\n\n/** A prepared segmented reduce (P2-P3: the thread-per-row tier only; `tiers !== null` -> E_UNSUPPORTED { feature: \"segmentedReduce.tiers\" } until P4). */\nexport interface SegmentedReducePlanner {\n /** Records one dispatch over rows [0, n) (tiers null) writing out[i] (f32) per row; a row with no arcs gets the identity element. */\n record(pass: GPUComputePassEncoder, core: CoreBinding, out: Binding): void;\n}\n\n/** The identifiers a VALUE snippet may name (contract 3.11, 4.5); every other identifier is rejected textually before compose. */\nconst VALUE_SNIPPET_VOCABULARY: ReadonlySet<string> = new Set([\"row\", \"arc\", \"nbr\", \"weight\", \"v\"]);\n\n/**\n * The WGSL words a snippet statement may use that are not identifiers: the statement keywords (never the flow\n * keywords `return` / `break` / `continue`, which would leave the fold), the scalar type constructors and the\n * builtin math functions a value expression may call (a bounded list; a binding, a uniform or a module function such\n * as `identity` / `comb` / `linear_id` is NOT in it and is rejected as an identifier).\n */\nconst VALUE_SNIPPET_WGSL_WORDS: ReadonlySet<string> = new Set([\n \"if\",\n \"else\",\n \"let\",\n \"var\",\n \"const\",\n \"true\",\n \"false\",\n \"f32\",\n \"u32\",\n \"i32\",\n \"bool\",\n \"abs\",\n \"ceil\",\n \"clamp\",\n \"exp\",\n \"exp2\",\n \"floor\",\n \"fract\",\n \"inverseSqrt\",\n \"log\",\n \"log2\",\n \"max\",\n \"min\",\n \"mix\",\n \"pow\",\n \"round\",\n \"select\",\n \"sign\",\n \"sqrt\",\n \"step\",\n \"trunc\",\n]);\n\n/**\n * The OP override value of an operator (the body's `OP == 1u` / `OP == 2u` tests, contract 4.5).\n * @param op - the operator\n * @returns 0 for sum, 1 for min, 2 for max\n */\nfunction opCode(op: ReduceOp): number {\n switch (op) {\n case \"sum\":\n return 0;\n case \"min\":\n return 1;\n case \"max\":\n return 2;\n default:\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `segmentedReduce: unknown op ${String(op)}`, {\n argument: \"op\",\n value: op,\n expected: \"sum | min | max\",\n });\n }\n}\n\n/**\n * WGSL comments removed (a comment may mention `target` or any other word).\n * @param text - WGSL text\n * @returns the text with block and line comments replaced by spaces\n */\nfunction stripComments(text: string): string {\n return text.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/\\/\\/[^\\n]*/g, \" \");\n}\n\n/**\n * The textual vocabulary check of contract 3.11: the snippet must assign `v` (`=`, `+=`, `-=`, `*=` or `/=`) and its\n * identifiers may be only row, arc, nbr, weight and v; numeric literals and the WGSL words of\n * VALUE_SNIPPET_WGSL_WORDS are not identifiers and pass; anything else -- a binding, a uniform, a module function,\n * a locally declared name, a flow keyword, a reserved word such as `target` -- is E_SHADER_COMPILE { stage:\n * \"compose\", slot: \"VALUE\", identifier } on every device, before any shader is created.\n * @param snippet - the VALUE snippet text\n */\nfunction validateValueSnippet(snippet: string): void {\n const code = stripComments(snippet);\n if (!/\\bv\\s*[-+*/]?=(?!=)/.test(code)) {\n throw new WebGpuGraphError(\"E_SHADER_COMPILE\", \"segmentedReduce: the VALUE snippet never assigns v\", {\n id: \"segmented-reduce\",\n stage: \"compose\",\n slot: \"VALUE\",\n });\n }\n const tokens = code.match(/[A-Za-z_][A-Za-z0-9_]*|[0-9][0-9A-Za-z_.]*/g) ?? [];\n for (const token of tokens) {\n if (/^[0-9]/.test(token) || VALUE_SNIPPET_VOCABULARY.has(token) || VALUE_SNIPPET_WGSL_WORDS.has(token)) {\n continue;\n }\n throw new WebGpuGraphError(\n \"E_SHADER_COMPILE\",\n `segmentedReduce: the VALUE snippet names \"${token}\"; the only identifiers allowed are row, arc, nbr, weight and v`,\n { id: \"segmented-reduce\", stage: \"compose\", slot: \"VALUE\", identifier: token },\n );\n }\n}\n\n/** The thread-per-row planner: ONE `segmented-reduce` dispatch with TIER 0 over every row. */\nclass ThreadPerRowPlanner implements SegmentedReducePlanner {\n private readonly scope: ReduceScope;\n private readonly kernel: Kernel;\n private readonly hasWeights: boolean;\n private readonly accumulate: boolean;\n\n /**\n * Wraps a compiled thread-per-row pipeline with the pattern it was compiled for.\n * @param scope - the scope the pipeline was prepared in\n * @param kernel - the compiled kernel\n * @param hasWeights - the HAS_WEIGHTS the pipeline was compiled with\n * @param accumulate - whether record() combines into out instead of overwriting\n */\n constructor(scope: ReduceScope, kernel: Kernel, hasWeights: boolean, accumulate: boolean) {\n this.scope = scope;\n this.kernel = kernel;\n this.hasWeights = hasWeights;\n this.accumulate = accumulate;\n }\n\n /**\n * Records the dispatch: rows [0, n), arcs [0, arcCount), plan1d(n); nothing for n = 0 (no zero-length binding is\n * ever created).\n * @param pass - the pass to record into\n * @param core - a core with the SAME weights pattern as the one prepared (any snapshot)\n * @param out - at least 4n bytes of f32\n */\n record(pass: GPUComputePassEncoder, core: CoreBinding, out: Binding): void {\n assertNotWindowed(core, \"segmentedReduce\");\n if ((core.weights !== null) !== this.hasWeights) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n \"segmentedReduce: the core's weights pattern differs from the one prepared\",\n {\n argument: \"core\",\n value: core.weights !== null,\n expected: this.hasWeights,\n },\n );\n }\n const n = rowCountOf(core, \"segmentedReduce\");\n if (n === 0) {\n return;\n }\n const arcCount = core.colIdx === null ? 0 : core.colIdx.size / 4;\n if (out.size < 4 * n) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `segmentedReduce: out holds ${out.size} bytes, ${4 * n} needed`,\n {\n argument: \"out\",\n value: out.size,\n expected: `>= ${4 * n}`,\n },\n );\n }\n const params = this.scope.params(RANGE_PARAMS, {\n start: 0,\n end: n,\n arcBase: 0,\n arcEnd: arcCount,\n accumulate: this.accumulate ? 1 : 0,\n n,\n });\n const bound = this.kernel.bind({ ...graphBindings(core, null), out, P: params.binding });\n this.kernel.dispatch(pass, bound, plan1d(n, this.scope.workgroupSize, this.scope.caps), [params.offset]);\n }\n}\n\n/**\n * Prepares the thread-per-row pipeline for a snapshot's dummy pattern (USE_PERM, HAS_WEIGHTS) and snippet.\n * @param scope - the reduce scope (pipelines, pool, params writer)\n * @param core - the core whose weights pattern selects HAS_WEIGHTS (USE_PERM is false: no tiers at P2)\n * @param options - operator, snippet, tiers (must be null), accumulate\n * @returns the planner\n */\nexport async function prepareSegmentedReduce(\n scope: ReduceScope,\n core: CoreBinding,\n options: SegmentedReduceOptions,\n): Promise<SegmentedReducePlanner> {\n if (options.tiers !== null) {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"segmentedReduce: the degree tiers land at P4; pass tiers: null\", {\n feature: \"segmentedReduce.tiers\",\n });\n }\n assertNotWindowed(core, \"segmentedReduce\");\n const op = opCode(options.op);\n validateValueSnippet(options.valueSnippet);\n const overrides = { ...graphOverrides(core, null), OP: op, TIER: 0 };\n const spec = kernelSpec(\"segmented-reduce\", overrides, { VALUE: options.valueSnippet });\n const kernel = await scope.pipelines.kernel(spec);\n return new ThreadPerRowPlanner(scope, kernel, core.weights !== null, options.accumulate === true);\n}\n","/**\n * The pull SpMV primitive of spec 6 row 9 / 8.2 in its thread-per-row tier (P7; M8b plan PD-1 / PD-2): one\n * grid-stride dispatch of the `spmv-pull` module over the rows of a REVERSE adjacency, each invocation folding\n * `weight * xNorm[nbr]` over its row's in-arcs (Kahan-compensated, f32) and writing\n * `rankOut[v] = beta * pv + alpha * (sum + danglingMass * pv)`, where `pv` is `personalization[v]` under\n * HAS_PERSONALIZATION and the uniform `P.uniformP` otherwise, and `danglingMass` is `partials[0].danglingMass`\n * under USE_DANGLING. PageRank sets alpha to the damping, beta to 1 - alpha and USE_DANGLING; HITS and eigenvector\n * set alpha 1, beta 0, uniformP 0; Katz sets alpha to the attenuation, beta to its constant and uniformP 1.\n *\n * It is its own registry entry rather than a `segmentedReduce` VALUE snippet (PD-1): the snippet vocabulary is\n * `row, arc, nbr, weight, v` and cannot read `xNorm[nbr]`, and the design's binding table gives the kernel eight\n * storage bindings of its own. The in-degree tiers of `reverseDegreeOrder()` land at P4 (PD-2): `tiers !== null` is\n * E_UNSUPPORTED and USE_PERM is always false (the perm slot carries the rowPtr dummy of graphBindings). The row and\n * arc counts come from the core's binding sizes exactly as segmentedReduce derives them.\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { planGridStride } from \"../kernel/dispatch.js\";\nimport { type Kernel } from \"../kernel/kernel.js\";\nimport { graphBindings, graphOverrides, kernelSpec, SPMV_PARAMS } from \"../kernels.js\";\nimport { type CoreBinding } from \"../memory/residency.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { arcCountOf, assertNotWindowed, rowCountOf } from \"./core-shape.js\";\nimport { type ReduceScope } from \"./reduce.js\";\nimport { type DegreeTiers } from \"./segmented-reduce.js\";\n\n/** The group-1 bindings of one pull: the pre-scaled input, the output, the personalization (null binds xNorm as the dummy) and the PrPartial block whose header carries danglingMass. */\nexport interface SpmvResources {\n readonly xNorm: Binding;\n readonly rankOut: Binding;\n readonly personalization: Binding | null;\n readonly partials: Binding;\n}\n\n/** The scalar coefficients of one pull (SpmvParams alpha / beta / uniformP). */\nexport interface SpmvCoefficients {\n readonly alpha: number;\n readonly beta: number;\n readonly uniformP: number;\n}\n\n/** Options of prepareSpmvPull: the two variant flags, the weights binding and the tiers (must be null at P7). */\nexport interface SpmvPullOptions {\n readonly personalization: boolean;\n readonly dangling: boolean;\n /** The weights binding to fold with: `undefined` takes the core's, `null` runs UNWEIGHTED on a weighted core. */\n readonly weights?: Binding | null | undefined;\n readonly tiers: DegreeTiers | null;\n}\n\n/** A prepared pull: records ONE grid-stride dispatch over the rows of a reverse core into a pass. */\nexport interface SpmvPullPlanner {\n /** Records the dispatch over rows [0, n) of `rev` writing rankOut[v] (f32) per row; nothing for n = 0. */\n record(pass: GPUComputePassEncoder, rev: CoreBinding, resources: SpmvResources, coefficients: SpmvCoefficients): void;\n /** Dispatches the last record() issued (1, or 0 for n = 0). */\n readonly lastDispatches: number;\n}\n\n/** The thread-per-row planner: ONE `spmv-pull` dispatch, grid-stride over every row. */\nclass SpmvPullPlannerImpl implements SpmvPullPlanner {\n private readonly scope: ReduceScope;\n private readonly kernel: Kernel;\n private readonly weights: Binding | null | undefined;\n private dispatches = 0;\n\n /**\n * Wraps a compiled pipeline with the weights choice it was compiled for.\n * @param scope - the scope the pipeline was prepared in\n * @param kernel - the compiled kernel\n * @param weights - the weights option the pipeline's HAS_WEIGHTS was derived from; record() binds the same way\n */\n constructor(scope: ReduceScope, kernel: Kernel, weights: Binding | null | undefined) {\n this.scope = scope;\n this.kernel = kernel;\n this.weights = weights;\n }\n\n /**\n * Dispatches the last record() issued.\n * @returns 1, or 0 when the last record covered no rows\n */\n get lastDispatches(): number {\n return this.dispatches;\n }\n\n /**\n * Records the dispatch: rows [0, n), arcs [0, arcCount), planGridStride(n); nothing for n = 0 (no zero-length\n * binding is ever created). `personalization ?? xNorm` follows the group-0 dummy rule: both slots are\n * storage-ro, so the aliasing check of Kernel.bind does not fire, and HAS_PERSONALIZATION false never reads it.\n * @param pass - the pass to record into\n * @param rev - the reverse core (any snapshot with the weights pattern the planner was prepared for)\n * @param resources - xNorm, rankOut, personalization, partials\n * @param coefficients - alpha, beta, uniformP\n */\n record(\n pass: GPUComputePassEncoder,\n rev: CoreBinding,\n resources: SpmvResources,\n coefficients: SpmvCoefficients,\n ): void {\n const n = rowCountOf(rev, \"spmvPull\");\n const plan = planGridStride(n, this.scope.workgroupSize, this.scope.caps);\n if (plan.x === 0) {\n this.dispatches = 0;\n return;\n }\n const params = this.scope.params(SPMV_PARAMS, {\n n,\n arcBase: 0,\n arcEnd: arcCountOf(rev),\n stride: plan.stride ?? n,\n alpha: coefficients.alpha,\n beta: coefficients.beta,\n uniformP: coefficients.uniformP,\n pad0: 0,\n });\n const bound = this.kernel.bind({\n ...graphBindings(rev, null, this.weights),\n xNorm: resources.xNorm,\n rankOut: resources.rankOut,\n personalization: resources.personalization ?? resources.xNorm,\n partials: resources.partials,\n P: params.binding,\n });\n this.kernel.dispatch(pass, bound, plan, [params.offset]);\n this.dispatches = 1;\n }\n}\n\n/**\n * Prepares the thread-per-row pull pipeline for a reverse core's weights pattern and the two variant flags.\n * @param scope - the reduce scope (pipelines, params writer)\n * @param rev - the reverse core whose weights pattern selects HAS_WEIGHTS (USE_PERM is false: no tiers at P7)\n * @param options - personalization, dangling, weights, tiers (must be null)\n * @returns the planner\n */\nexport async function prepareSpmvPull(\n scope: ReduceScope,\n rev: CoreBinding,\n options: SpmvPullOptions,\n): Promise<SpmvPullPlanner> {\n if (options.tiers !== null) {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"spmvPull: the in-degree tiers land at P4; pass tiers: null\", {\n feature: \"spmvPull.tiers\",\n });\n }\n assertNotWindowed(rev, \"spmvPull\");\n const spec = kernelSpec(\"spmv-pull\", {\n ...graphOverrides(rev, null, options.weights),\n HAS_PERSONALIZATION: options.personalization,\n USE_DANGLING: options.dangling,\n });\n const kernel = await scope.pipelines.kernel(spec);\n return new SpmvPullPlannerImpl(scope, kernel, options.weights);\n}\n","/**\n * PageRank and personalized PageRank on the device (spec 8.2, 3.3): a pull over the reverse adjacency with the\n * out-weight normaliser folded into `xNorm` by `pr-scale`, the dangling mass and the L1 delta folded by\n * `pr-finalize` into the header at `partials[0]`, and `spmv-pull` writing the next iterate. Iterations run in\n * batches of PR_BATCH per submit, ONE readback per batch (the header and the iterate together), and the device\n * records `firstConverged` the first time the delta falls below `tolerance * n`, so the reported `iterations` is the\n * first converged iteration and not the batch boundary (spec 9.7).\n *\n * PLAN DECISION PD-7: the ping-pong is TWO buffers (`rankA`, `rankB`) alternated through two cached bind groups;\n * one buffer of two aliased halves would bind (each kernel sees the halves in one access mode) but saves nothing.\n * PLAN DECISION PD-8: `outWeightSum` is call scratch from the Lease, one `segmentedReduce` pass per call.\n * PLAN DECISION PD-9: `pr-scale` at iteration i reads x(i-1) and x(i-2), so its delta is the error of iteration\n * i - 1 and `pr-finalize` records `P.iteration - 1`; the ping-pong supplies `rankPrev` for free because it is the\n * buffer this iteration overwrites, and `pr-scale` runs before `spmv-pull` in the same pass.\n */\n\nimport { type F32, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { U32_MAX } from \"../constants.js\";\nimport { type GpuContext } from \"../context.js\";\nimport { isWebGpuGraphError, WebGpuGraphError } from \"../errors.js\";\nimport { CommandBatch } from \"../kernel/batch.js\";\nimport { groupsOf, plan1d } from \"../kernel/dispatch.js\";\nimport { kernelSpec, PR_PARAMS, PR_PARTIAL } from \"../kernels.js\";\nimport { type ArrayBinding, type CoreBinding } from \"../memory/residency.js\";\nimport { coreOfView } from \"../primitives/core-shape.js\";\nimport { prepareSegmentedReduce } from \"../primitives/segmented-reduce.js\";\nimport { prepareSpmvPull } from \"../primitives/spmv.js\";\nimport { type GpuPageRankResult, type PageRankOptions } from \"../types/algorithms.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type GpuRunOptions } from \"../types/run.js\";\nimport { algorithmScope } from \"./scope.js\";\n\n/** Iterations per submit (spec 8.2: k = 8). */\nconst PR_BATCH = 8;\n/** Params slots of one batch: per iteration one PrParams (shared by pr-scale and pr-finalize) and one SpmvParams, plus the normaliser's RangeParams; a smaller ring wraps onto a slot the same batch still reads. */\nconst RING_SLOTS = 2 * PR_BATCH + 1;\n\n/**\n * Validates `options.dest` for a score result of `n` elements.\n * @param dest - the caller's destination array, if any\n * @param n - the node count\n * @param algorithm - the caller's name, for the message\n * @returns the destination as an F32, or null when none was given\n */\nfunction checkDest(dest: Float32Array | Uint32Array | undefined, n: number, algorithm: string): F32 | null {\n if (dest === undefined) {\n return null;\n }\n if (dest instanceof Float32Array && dest.length === n && dest.buffer instanceof ArrayBuffer) {\n return dest as F32;\n }\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${algorithm}: dest must be a Float32Array of length ${n} over an ArrayBuffer`,\n {\n argument: \"dest\",\n value: `${dest.constructor.name}(${dest.length})`,\n expected: `Float32Array(${n}) over an ArrayBuffer`,\n },\n );\n}\n\n/**\n * The resident core; a windowed plan (`E_TOO_LARGE { path: \"windowed\", algorithm: null }`, spec 3.8) is re-thrown\n * with the algorithm name (3.12). Transcribed from degree.ts, whose coreOf is module-private.\n * @param ctx - the context\n * @param s - the snapshot\n * @param algorithm - the caller's name\n * @returns the core binding\n */\nfunction coreOf(ctx: GpuContext, s: GraphSnapshot, algorithm: string): CoreBinding {\n try {\n return ctx.residency.core(s);\n } catch (error: unknown) {\n if (isWebGpuGraphError(error) && error.code === \"E_TOO_LARGE\" && error.details.path === \"windowed\") {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `${algorithm}: the arc arrays need a windowed upload, which P1-P3 plan but do not execute`,\n { ...error.details, algorithm },\n );\n }\n throw error;\n }\n}\n\n/**\n * Whole-buffer binding of a scratch buffer over its first `size` bytes.\n * @param buffer - the buffer\n * @param size - the bound byte length\n * @returns the binding\n */\nfunction bindingOf(buffer: GPUBuffer, size: number): Binding {\n return { buffer, offset: 0, size, window: null };\n}\n\n/**\n * The E_ABORTED error of a signal.\n * @param algorithm - the caller's name\n * @param batchId - the last submitted batch, when one exists\n * @returns the error\n */\nfunction aborted(algorithm: string, batchId?: number): WebGpuGraphError {\n return new WebGpuGraphError(\n \"E_ABORTED\",\n `${algorithm}: the signal was aborted`,\n batchId === undefined ? {} : { batchId },\n );\n}\n\n/**\n * The shared driver: `personalization` is the normalised vector of personalizedPageRank or null for the uniform\n * 1 / n of pageRank.\n * @param ctx - the context\n * @param s - the snapshot\n * @param personalization - the normalised personalization (sum 1), or null\n * @param options - the PageRank and run options\n * @param algorithm - the public name, for messages and labels\n * @returns the result\n */\nasync function run(\n ctx: GpuContext,\n s: GraphSnapshot,\n personalization: F32 | null,\n options: (PageRankOptions & GpuRunOptions) | undefined,\n algorithm: string,\n): Promise<GpuPageRankResult> {\n ctx.assertReady();\n const n = s.nodeCount;\n const alpha = options?.dampingFactor ?? 0.85;\n const maxIterations = options?.maxIterations ?? 100;\n const tolerance = options?.tolerance ?? 1e-6;\n const useWeights = options?.weighted !== false;\n if (!Number.isInteger(maxIterations) || maxIterations < 1) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${algorithm}: maxIterations must be a positive integer`, {\n argument: \"maxIterations\",\n value: maxIterations,\n expected: \"a positive integer\",\n });\n }\n const dest = checkDest(options?.dest, n, algorithm);\n if (options?.signal?.aborted) {\n throw aborted(algorithm);\n }\n if (n === 0) {\n options?.onProgress?.(maxIterations, maxIterations);\n return { scores: dest ?? new Float32Array(0), iterations: 0, converged: true, danglingMass: 0, precision: \"f32\" };\n }\n const core = coreOf(ctx, s, algorithm);\n if (s.arcCount === 0) {\n // every node is dangling: the whole mass is redistributed by pv each iteration, so pv is the fixed point\n const scores = dest ?? new Float32Array(n);\n if (personalization === null) {\n scores.fill(1 / n);\n } else {\n scores.set(personalization);\n }\n options?.onProgress?.(maxIterations, maxIterations);\n return { scores, iterations: 0, converged: true, danglingMass: 1, precision: \"f32\" };\n }\n const view = ctx.residency.view(s, \"reverse\");\n const rev = coreOfView(view, view.scalars.arcCount[0]);\n // weighted: false runs the unweighted algorithm on BOTH sides: the normaliser sums 1 per arc and the pull folds 1\n const weights: Binding | null | undefined = useWeights ? undefined : null;\n const weightedCore: CoreBinding = useWeights ? core : { ...core, weights: null, hasWeights: false };\n const weightedRev: CoreBinding = useWeights ? rev : { ...rev, weights: null, hasWeights: false };\n const scope = algorithmScope(ctx, algorithm, RING_SLOTS);\n let uploaded: ArrayBinding | null = null;\n try {\n const bytes = 4 * n;\n const rankA = scope.scratch(bytes, \"rankA\");\n const rankB = scope.scratch(bytes, \"rankB\");\n const xNorm = scope.scratch(bytes, \"xNorm\");\n const outWeightSum = scope.scratch(bytes, \"outWeightSum\");\n const scalePlan = plan1d(n, ctx.workgroupSize, ctx.caps);\n const groups = groupsOf(scalePlan);\n const partialsBytes = PR_PARTIAL.byteLength * (1 + groups);\n const partials = scope.scratch(partialsBytes, \"partials\");\n if (personalization !== null) {\n uploaded = ctx.residency.array(personalization, `${algorithm}/personalization`);\n }\n await ctx.allocator.check();\n const normaliser = await prepareSegmentedReduce(scope, weightedCore, {\n op: \"sum\",\n valueSnippet: \"v = weight;\",\n tiers: null,\n });\n const pull = await prepareSpmvPull(scope, weightedRev, {\n personalization: personalization !== null,\n dangling: true,\n weights,\n tiers: null,\n });\n const scale = await ctx.pipelines.kernel(kernelSpec(\"pr-scale\", { NORM_MODE: 0 }));\n const finalize = await ctx.pipelines.kernel(kernelSpec(\"pr-finalize\", { NORM_MODE: 0 }));\n const finalizePlan = plan1d(1, ctx.workgroupSize, ctx.caps);\n const { queue } = ctx.device;\n queue.writeBuffer(rankA, 0, new Float32Array(n).fill(1 / n));\n queue.writeBuffer(rankB, 0, new Float32Array(n));\n const header = new ArrayBuffer(PR_PARTIAL.byteLength);\n PR_PARTIAL.write(new DataView(header), { firstConverged: U32_MAX, iteration: 0 });\n queue.writeBuffer(partials, 0, header);\n const rank = [bindingOf(rankA, bytes), bindingOf(rankB, bytes)];\n const xNormBinding = bindingOf(xNorm, bytes);\n const outWeightSumBinding = bindingOf(outWeightSum, bytes);\n const partialsBinding = bindingOf(partials, partialsBytes);\n const coefficients = { alpha, beta: 1 - alpha, uniformP: 1 / n };\n let cur = 0;\n let iterationsRun = 0;\n for (;;) {\n const k = Math.min(PR_BATCH, maxIterations - iterationsRun);\n const batch = new CommandBatch(ctx, algorithm);\n const pass = batch.pass(\"iterations\");\n if (iterationsRun === 0) {\n normaliser.record(pass, weightedCore, outWeightSumBinding);\n }\n for (let i = 0; i < k; i++) {\n const params = scope.params(PR_PARAMS, {\n n,\n groups,\n iteration: iterationsRun + i + 1,\n trackConvergence: 1,\n convergeThreshold: tolerance * n,\n });\n const other = 1 - cur;\n const scaleBound = scale.bind({\n rankIn: rank[cur],\n rankPrev: rank[other],\n outWeightSum: outWeightSumBinding,\n xNorm: xNormBinding,\n partials: partialsBinding,\n P: params.binding,\n });\n scale.dispatch(pass, scaleBound, scalePlan, [params.offset]);\n const finalizeBound = finalize.bind({ partials: partialsBinding, P: params.binding });\n finalize.dispatch(pass, finalizeBound, finalizePlan, [params.offset]);\n pull.record(\n pass,\n weightedRev,\n {\n xNorm: xNormBinding,\n rankOut: rank[other],\n personalization: uploaded?.binding ?? null,\n partials: partialsBinding,\n },\n coefficients,\n );\n cur = other;\n }\n batch.endPass();\n const headerRequest = batch.readback(partials, 0, PR_PARTIAL.byteLength);\n const scoresRequest = batch.readback(rank[cur].buffer, 0, bytes);\n scope.flush();\n const submitted = batch.submit();\n const back = await submitted.readback;\n iterationsRun += k;\n ctx.assertReady();\n if (options?.signal?.aborted) {\n throw aborted(algorithm, submitted.id);\n }\n options?.onProgress?.(iterationsRun, maxIterations);\n const folded = PR_PARTIAL.read(new DataView(back), headerRequest.offset);\n const firstConverged = folded.firstConverged as number;\n const converged = firstConverged !== U32_MAX;\n if (converged || iterationsRun >= maxIterations) {\n const scores = dest ?? new Float32Array(n);\n scores.set(new Float32Array(back, scoresRequest.offset, n));\n if (converged && iterationsRun < maxIterations) {\n options?.onProgress?.(maxIterations, maxIterations);\n }\n return {\n scores,\n iterations: converged ? firstConverged : iterationsRun,\n converged,\n danglingMass: folded.danglingMass as number,\n precision: \"f32\",\n };\n }\n }\n } finally {\n uploaded?.destroy();\n scope.dispose();\n }\n}\n\n/**\n * PageRank on the device (spec 3.3, 8.2): NetworkX semantics, f32 scores, `iterations` the first converged\n * iteration (spec 9.7).\n * @param ctx - the context whose device runs the kernels\n * @param s - the snapshot (uploaded through ctx.residency, or found there)\n * @param options - dampingFactor 0.85 / maxIterations 100 / tolerance 1e-6 / weighted true, plus dest / signal / onProgress\n * @returns the scores, iterations, converged, danglingMass and precision\n */\nexport function pageRank(\n ctx: GpuContext,\n s: GraphSnapshot,\n options?: PageRankOptions & GpuRunOptions,\n): Promise<GpuPageRankResult> {\n return run(ctx, s, null, options, \"pageRank\");\n}\n\n/**\n * Personalized PageRank on the device (spec 3.3, 8.2): the personalization vector replaces the uniform 1 / n in\n * the teleport and the dangling redistribution; it is normalised to sum 1 on the host.\n * @param ctx - the context whose device runs the kernels\n * @param s - the snapshot (uploaded through ctx.residency, or found there)\n * @param personalization - one finite non-negative mass per node, not all zero\n * @param options - dampingFactor 0.85 / maxIterations 100 / tolerance 1e-6 / weighted true, plus dest / signal / onProgress\n * @returns the scores, iterations, converged, danglingMass and precision\n */\nexport async function personalizedPageRank(\n ctx: GpuContext,\n s: GraphSnapshot,\n personalization: F32,\n options?: PageRankOptions & GpuRunOptions,\n): Promise<GpuPageRankResult> {\n const n = s.nodeCount;\n const invalid = (value: unknown, expected: string): WebGpuGraphError =>\n new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `personalizedPageRank: personalization must be ${expected}`, {\n argument: \"personalization\",\n value,\n expected,\n });\n if (!(personalization instanceof Float32Array) || personalization.length !== n) {\n throw invalid(`${personalization.constructor.name}(${personalization.length})`, `a Float32Array of length ${n}`);\n }\n let total = 0;\n for (let v = 0; v < n; v++) {\n const mass = personalization[v];\n if (!Number.isFinite(mass) || mass < 0) {\n throw invalid(mass, \"finite and non-negative in every entry\");\n }\n total += mass;\n }\n if (n > 0 && !(total > 0)) {\n throw invalid(total, \"a vector whose entries sum to a positive number\");\n }\n const normalised = new Float32Array(n);\n for (let v = 0; v < n; v++) {\n normalised[v] = personalization[v] / total;\n }\n return run(ctx, s, normalised, options, \"personalizedPageRank\");\n}\n","/**\n * The power-iteration driver HITS, eigenvector centrality and Katz centrality share (spec 8.2 lines 2603-2605; M8b\n * plan PD-10): per iteration `pr-scale` at NORM_MODE 1 | 2 | 4 folds the norm term (and the L1 delta) into the\n * per-workgroup partials, `pr-finalize` folds them into the header at `partials[0]` (the square root for L2) and\n * records `firstConverged`, `pr-scale` at NORM_MODE 3 writes `xNorm[u] = x[u] / partials[0].norm` (skipped at\n * mode 4, the identity, where the first scale pass already wrote `xNorm[u] = x[u]`), and `spmv-pull` writes the\n * next iterate. Four dispatches (three for Katz), all on the device, NO readback inside the batch: the scalar\n * normaliser the host cannot supply without a readback is exactly what stays on the device, so these three batch\n * eight iterations per submit like PageRank does.\n *\n * The ping-pong is TWO buffers alternated through two cached bind groups (PD-7 / DEP-M8B-G), and `rankPrev` is the\n * buffer this iteration overwrites: it still holds x(i-2) when `pr-scale` reads it, because the scale runs before\n * the pull in the same pass (PD-9). With an `alternate` adjacency (HITS, spec 8.2: \"alternates two pulls\") the\n * iterations pull over `adjacency` and `alternate` in turn, and the ring is THREE buffers so the buffer being\n * overwritten holds x(i-3) -- the previous iterate of the same kind -- and the delta stays meaningful. The batch\n * loop duplicates src/algorithms/pagerank.ts, which its own task owns.\n */\n\nimport { type F32, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { U32_MAX } from \"../constants.js\";\nimport { type GpuContext } from \"../context.js\";\nimport { isWebGpuGraphError, WebGpuGraphError } from \"../errors.js\";\nimport { CommandBatch } from \"../kernel/batch.js\";\nimport { groupsOf, plan1d } from \"../kernel/dispatch.js\";\nimport { kernelSpec, PR_PARAMS, PR_PARTIAL } from \"../kernels.js\";\nimport { type CoreBinding } from \"../memory/residency.js\";\nimport { coreOfView } from \"../primitives/core-shape.js\";\nimport { prepareSpmvPull } from \"../primitives/spmv.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { algorithmScope } from \"./scope.js\";\n\n/** Iterations per submit (spec 8.2: k = 8). */\nconst BATCH = 8;\n/** Params slots of one batch: four blocks per iteration times the batch, plus a margin (the plan's `4 * 8 + 8`). */\nconst RING_SLOTS = 4 * BATCH + 8;\n\n/**\n * What one power iteration run needs. `adjacency` is the CoreBinding the pull walks -- the forward core for hubs\n * and eigenvector, coreOfView(view(s, \"reverse\")) for authorities and Katz (spec 8.2 lines 2603-2606). Exported\n * for runPowerIteration's signature, not imported by name.\n * @public\n */\nexport interface PowerIterationConfig {\n /**\n * 1 = L1 (sum) normalise, 2 = L2 normalise, 4 = identity (Katz: no normaliser). Never 0 or 3 here: 0 is\n * PageRank's per-node divisor and 3 is the internal scale pass this driver issues itself.\n */\n readonly normMode: 1 | 2 | 4;\n readonly adjacency: CoreBinding;\n /**\n * Null: every iteration pulls over `adjacency`. Non-null: the odd iterations (1, 3, ...) pull over `adjacency`\n * and the even ones over `alternate`, so x(i) = A_alt * norm(A * norm(x(i-2))) -- one interleaved chain of HITS,\n * whose hubs and authorities are the last iterates of the two chains (forward-first and reverse-first). The\n * ring then has three buffers and `weights` must be null or undefined (each core's own weights).\n */\n readonly alternate: CoreBinding | null;\n readonly alpha: number;\n readonly beta: number;\n readonly uniformP: number;\n readonly maxIterations: number;\n readonly tolerance: number;\n /** undefined takes the adjacency's weights, null runs UNWEIGHTED on a weighted snapshot (T4 Step 4). */\n readonly weights: Binding | null | undefined;\n readonly label: string;\n readonly signal: AbortSignal | undefined;\n readonly onProgress: ((done: number, total: number) => void) | undefined;\n}\n\n/** The iterate, the device-recorded first converged iteration, and the number of iterations actually run. */\nexport interface PowerIterationRun {\n readonly scores: F32;\n /** x(m - 1) on an alternating run: the chain's last iterate of the OTHER kind (hub or authority); null otherwise. */\n readonly previous: F32 | null;\n readonly iterations: number;\n readonly converged: boolean;\n readonly iterationsRun: number;\n}\n\n/**\n * Validates `options.dest` for a score result of `n` elements.\n * @param dest - the caller's destination array, if any\n * @param n - the node count\n * @param algorithm - the caller's name, for the message\n * @returns the destination as an F32, or null when none was given\n */\nexport function checkDest(dest: Float32Array | Uint32Array | undefined, n: number, algorithm: string): F32 | null {\n if (dest === undefined) {\n return null;\n }\n if (dest instanceof Float32Array && dest.length === n && dest.buffer instanceof ArrayBuffer) {\n return dest as F32;\n }\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${algorithm}: dest must be a Float32Array of length ${n} over an ArrayBuffer`,\n {\n argument: \"dest\",\n value: `${dest.constructor.name}(${dest.length})`,\n expected: `Float32Array(${n}) over an ArrayBuffer`,\n },\n );\n}\n\n/**\n * The resident core; a windowed plan (`E_TOO_LARGE { path: \"windowed\", algorithm: null }`, spec 3.8) is re-thrown\n * with the algorithm name (3.12). Transcribed from degree.ts, whose coreOf is module-private.\n * @param ctx - the context\n * @param s - the snapshot\n * @param algorithm - the caller's name\n * @returns the core binding\n */\nexport function coreOf(ctx: GpuContext, s: GraphSnapshot, algorithm: string): CoreBinding {\n try {\n return ctx.residency.core(s);\n } catch (error: unknown) {\n if (isWebGpuGraphError(error) && error.code === \"E_TOO_LARGE\" && error.details.path === \"windowed\") {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `${algorithm}: the arc arrays need a windowed upload, which P1-P3 plan but do not execute`,\n { ...error.details, algorithm },\n );\n }\n throw error;\n }\n}\n\n/**\n * The reverse adjacency as the CoreBinding the pull walks (the forward buffers on an undirected snapshot, PD-13).\n * @param ctx - the context\n * @param s - the snapshot (n > 0)\n * @returns the reverse core\n */\nexport function reverseOf(ctx: GpuContext, s: GraphSnapshot): CoreBinding {\n const view = ctx.residency.view(s, \"reverse\");\n return coreOfView(view, view.scalars.arcCount[0]);\n}\n\n/**\n * The E_ABORTED error of a signal.\n * @param algorithm - the caller's name\n * @param batchId - the last submitted batch, when one exists\n * @returns the error\n */\nexport function aborted(algorithm: string, batchId?: number): WebGpuGraphError {\n return new WebGpuGraphError(\n \"E_ABORTED\",\n `${algorithm}: the signal was aborted`,\n batchId === undefined ? {} : { batchId },\n );\n}\n\n/**\n * Whole-buffer binding of a scratch buffer over its first `size` bytes.\n * @param buffer - the buffer\n * @param size - the bound byte length\n * @returns the binding\n */\nfunction whole(buffer: GPUBuffer, size: number): Binding {\n return { buffer, offset: 0, size, window: null };\n}\n\n/**\n * Runs the power iteration of `config` over `n` nodes from x(0) = 1 / n, in batches of eight iterations with ONE\n * readback per batch (the header and the iterate together), stopping at the first batch whose header records a\n * converged iteration or at `maxIterations`. The returned iterate is RAW: the last `spmv-pull` output, which the\n * caller normalises once on the host. The iterate travels with the header in EVERY batch, not once after the loop:\n * whether a batch terminates the run is known only from its header, and a second readback for the iterate would\n * be a second mapAsync (the plan's case 8 counts exactly one). The cost is 4n bytes (8n on an alternating run) of\n * staging per batch of 8 that the loop then discards when it continues -- 40 MB per 8 iterations at 10M nodes;\n * pagerank.ts pays the same.\n * @param ctx - the context\n * @param n - the node count (> 0)\n * @param config - the recurrence, the adjacency and the run options\n * @returns the raw iterate, the first converged iteration, whether it converged and the iterations actually run\n */\nexport async function runPowerIteration(\n ctx: GpuContext,\n n: number,\n config: PowerIterationConfig,\n): Promise<PowerIterationRun> {\n const scope = algorithmScope(ctx, config.label, RING_SLOTS);\n try {\n const bytes = 4 * n;\n // x(i) lives in ring[i % ring.length]: two buffers for one pull per iteration, three for the alternating pair\n const ring = (config.alternate === null ? [\"rankA\", \"rankB\"] : [\"rankA\", \"rankB\", \"rankC\"]).map((label) =>\n whole(scope.scratch(bytes, label), bytes),\n );\n const xNorm = whole(scope.scratch(bytes, \"xNorm\"), bytes);\n const scalePlan = plan1d(n, ctx.workgroupSize, ctx.caps);\n const groups = groupsOf(scalePlan);\n const partialsBytes = PR_PARTIAL.byteLength * (1 + groups);\n const partialsBuffer = scope.scratch(partialsBytes, \"partials\");\n const partials = whole(partialsBuffer, partialsBytes);\n await ctx.allocator.check();\n const pullOptions = { personalization: false, dangling: false, weights: config.weights, tiers: null };\n const pulls = [{ core: config.adjacency, pull: await prepareSpmvPull(scope, config.adjacency, pullOptions) }];\n if (config.alternate !== null) {\n pulls.push({ core: config.alternate, pull: await prepareSpmvPull(scope, config.alternate, pullOptions) });\n }\n const scaleNorm = await ctx.pipelines.kernel(kernelSpec(\"pr-scale\", { NORM_MODE: config.normMode }));\n const scaleApply =\n config.normMode === 4 ? null : await ctx.pipelines.kernel(kernelSpec(\"pr-scale\", { NORM_MODE: 3 }));\n const finalize = await ctx.pipelines.kernel(kernelSpec(\"pr-finalize\", { NORM_MODE: config.normMode }));\n const finalizePlan = plan1d(1, ctx.workgroupSize, ctx.caps);\n const { queue } = ctx.device;\n queue.writeBuffer(ring[0].buffer, 0, new Float32Array(n).fill(1 / n));\n for (const slot of ring.slice(1)) {\n queue.writeBuffer(slot.buffer, 0, new Float32Array(n));\n }\n const header = new ArrayBuffer(PR_PARTIAL.byteLength);\n PR_PARTIAL.write(new DataView(header), { firstConverged: U32_MAX, iteration: 0 });\n queue.writeBuffer(partialsBuffer, 0, header);\n const coefficients = { alpha: config.alpha, beta: config.beta, uniformP: config.uniformP };\n let iterationsRun = 0;\n for (;;) {\n const k = Math.min(BATCH, config.maxIterations - iterationsRun);\n const batch = new CommandBatch(ctx, config.label);\n const pass = batch.pass(\"iterations\");\n for (let i = 0; i < k; i++) {\n const iteration = iterationsRun + i + 1;\n const params = scope.params(PR_PARAMS, {\n n,\n groups,\n iteration,\n trackConvergence: 1,\n convergeThreshold: config.tolerance * n,\n });\n const rankIn = ring[(iteration - 1) % ring.length];\n // the slot the pull overwrites still holds x(iteration - ring.length): that is rankPrev (PD-9)\n const rankOut = ring[iteration % ring.length];\n const { core, pull } = pulls[(iteration - 1) % pulls.length];\n // outWeightSum takes rankIn as its dummy: storage-ro, read only under NORM_MODE 0, never compiled here\n const scaleBindings = { rankIn, rankPrev: rankOut, outWeightSum: rankIn, xNorm, partials, P: params.binding };\n scaleNorm.dispatch(pass, scaleNorm.bind(scaleBindings), scalePlan, [params.offset]);\n finalize.dispatch(pass, finalize.bind({ partials, P: params.binding }), finalizePlan, [params.offset]);\n if (scaleApply !== null) {\n scaleApply.dispatch(pass, scaleApply.bind(scaleBindings), scalePlan, [params.offset]);\n }\n pull.record(pass, core, { xNorm, rankOut, personalization: null, partials }, coefficients);\n }\n batch.endPass();\n const headerRequest = batch.readback(partialsBuffer, 0, PR_PARTIAL.byteLength);\n const scoresRequest = batch.readback(ring[(iterationsRun + k) % ring.length].buffer, 0, bytes);\n // x(m - 1) on an alternating run: the other kind, still intact in the third ring slot\n const previousRequest =\n config.alternate === null\n ? null\n : batch.readback(ring[(iterationsRun + k - 1) % ring.length].buffer, 0, bytes);\n scope.flush();\n const submitted = batch.submit();\n const back = await submitted.readback; // the ONE mapAsync of the batch (G7 item 5)\n iterationsRun += k;\n ctx.assertReady();\n if (config.signal?.aborted === true) {\n throw aborted(config.label, submitted.id);\n }\n config.onProgress?.(iterationsRun, config.maxIterations);\n const folded = PR_PARTIAL.read(new DataView(back), headerRequest.offset);\n const firstConverged = folded.firstConverged as number;\n const converged = firstConverged !== U32_MAX;\n if (converged || iterationsRun >= config.maxIterations) {\n if (converged && iterationsRun < config.maxIterations) {\n config.onProgress?.(config.maxIterations, config.maxIterations);\n }\n return {\n scores: new Float32Array(back, scoresRequest.offset, n).slice(),\n previous: previousRequest === null ? null : new Float32Array(back, previousRequest.offset, n).slice(),\n iterations: converged ? firstConverged : iterationsRun,\n converged,\n iterationsRun,\n };\n }\n }\n } finally {\n scope.dispose();\n }\n}\n","/**\n * HITS, eigenvector centrality and Katz centrality on the device (spec 3.3 lines 794-796, 8.2 lines 2603-2605):\n * three entry points over the ONE power-iteration driver, differing only in the adjacency the pull walks, the\n * normaliser and the coefficients. Eigenvector is the L2-normalised iteration over the forward core; Katz is\n * `alpha * A^T x + beta` over the reverse view with no per-iteration normaliser; HITS alternates the two pulls with\n * sum normalisation, `a(i) = A^T norm(h(i-1))` and `h(i) = A norm(a(i-1))` (the CPU package's recurrence, which\n * design 9.7 makes the parity target), as TWO interleaved chains of the driver -- the reverse-first chain from the\n * hub seed and the forward-first chain from the authority seed -- so a call is still two runs and two readbacks.\n * Every result is normalised ONCE on the host after the readback (sum for HITS, L2 for the other two), matching\n * the f64 oracle; the per-iteration normaliser never leaves the device (PD-10).\n */\n\nimport { type F32, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { type GpuContext } from \"../context.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport {\n type EigenvectorOptions,\n type GpuHitsResult,\n type GpuScoresResult,\n type HitsOptions,\n type KatzOptions,\n} from \"../types/algorithms.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type GpuRunOptions } from \"../types/run.js\";\nimport { aborted, checkDest, coreOf, type PowerIterationRun, reverseOf, runPowerIteration } from \"./power-iteration.js\";\n\n/** The three options every entry point shares, resolved. */\ninterface Resolved {\n readonly n: number;\n readonly maxIterations: number;\n readonly tolerance: number;\n readonly weights: Binding | null | undefined;\n readonly dest: F32 | null;\n}\n\n/**\n * Resolves and validates the shared options and the run options' `dest` / `signal`.\n * @param ctx - the context\n * @param s - the snapshot\n * @param options - maxIterations / tolerance / weighted plus dest / signal\n * @param algorithm - the public name, for messages\n * @returns the resolved options\n */\nfunction resolve(\n ctx: GpuContext,\n s: GraphSnapshot,\n options: (HitsOptions & GpuRunOptions) | undefined,\n algorithm: string,\n): Resolved {\n ctx.assertReady();\n const n = s.nodeCount;\n const maxIterations = options?.maxIterations ?? 100;\n const tolerance = options?.tolerance ?? 1e-6;\n if (!Number.isInteger(maxIterations) || maxIterations < 1) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${algorithm}: maxIterations must be a positive integer`, {\n argument: \"maxIterations\",\n value: maxIterations,\n expected: \"a positive integer\",\n });\n }\n const dest = checkDest(options?.dest, n, algorithm);\n if (options?.signal?.aborted) {\n throw aborted(algorithm);\n }\n // weighted: false runs UNWEIGHTED on a weighted snapshot: the pull folds 1 per arc (prepareSpmvPull's null)\n return { n, maxIterations, tolerance, weights: options?.weighted === false ? null : undefined, dest };\n}\n\n/**\n * A finite coefficient, or E_INVALID_ARGUMENT.\n * @param value - the caller's value, or undefined for the default\n * @param fallback - the default\n * @param argument - the option name\n * @returns the coefficient\n */\nfunction finite(value: number | undefined, fallback: number, argument: string): number {\n const resolved = value ?? fallback;\n if (!Number.isFinite(resolved)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `katzCentrality: ${argument} must be a finite number`, {\n argument,\n value: resolved,\n expected: \"a finite number\",\n });\n }\n return resolved;\n}\n\n/**\n * Copies the raw iterate into its destination divided by its norm (unchanged when the norm is not positive).\n * @param raw - the driver's iterate\n * @param dest - the caller's destination, or null for the raw array itself\n * @param norm - \"sum\" (L1) or \"l2\"\n * @returns the normalised scores\n */\nfunction normalised(raw: F32, dest: F32 | null, norm: \"sum\" | \"l2\"): F32 {\n let acc = 0;\n for (const v of raw) {\n acc += norm === \"sum\" ? Math.abs(v) : v * v;\n }\n const scale = norm === \"sum\" ? acc : Math.sqrt(acc);\n const out = dest ?? raw;\n for (let v = 0; v < raw.length; v++) {\n out[v] = scale > 0 ? raw[v] / scale : raw[v];\n }\n return out;\n}\n\n/**\n * The score result of one run.\n * @param run - the driver's run\n * @param dest - the caller's destination, or null\n * @param norm - the final normaliser\n * @returns the result\n */\nfunction scoresOf(run: PowerIterationRun, dest: F32 | null, norm: \"sum\" | \"l2\"): GpuScoresResult {\n return {\n scores: normalised(run.scores, dest, norm),\n iterations: run.iterations,\n converged: run.converged,\n precision: \"f32\",\n };\n}\n\n/**\n * The n = 0 result: nothing to iterate.\n * @param dest - the caller's destination, or null\n * @param total - the run's progress denominator, reported to onProgress as both done and total\n * @param onProgress - the caller's progress callback\n * @returns the empty result\n */\nfunction empty(\n dest: F32 | null,\n total: number,\n onProgress: ((done: number, total: number) => void) | undefined,\n): GpuScoresResult {\n onProgress?.(total, total);\n return { scores: dest ?? new Float32Array(0), iterations: 0, converged: true, precision: \"f32\" };\n}\n\n/**\n * The latest iterate of one kind across the two HITS chains: a chain holds its seed's kind after an even number of\n * iterations m (in `scores`, index m) and the other kind's last iterate one back (in `previous`, index m - 1, never\n * null on an alternating run; the fallback only satisfies the type).\n * @param sameSeed - the chain seeded with the wanted kind\n * @param otherSeed - the chain seeded with the other kind\n * @returns the raw iterate with the higher index\n */\nfunction latestOfKind(sameSeed: PowerIterationRun, otherSeed: PowerIterationRun): F32 {\n const fromSame = sameSeed.iterationsRun % 2 === 0 ? sameSeed.iterationsRun : sameSeed.iterationsRun - 1;\n const fromOther = otherSeed.iterationsRun % 2 === 1 ? otherSeed.iterationsRun : otherSeed.iterationsRun - 1;\n const chain = fromSame >= fromOther ? sameSeed : otherSeed;\n const index = Math.max(fromSame, fromOther);\n return (index === chain.iterationsRun ? chain.scores : chain.previous) ?? chain.scores;\n}\n\n/**\n * Eigenvector centrality on the device (spec 3.3, 8.2): the L2-normalised power iteration over the forward\n * adjacency, converging on `delta < n * tolerance`; the scores are L2-normalised.\n * @param ctx - the context whose device runs the kernels\n * @param s - the snapshot (uploaded through ctx.residency, or found there)\n * @param options - maxIterations 100 / tolerance 1e-6 / weighted true, plus dest / signal / onProgress\n * @returns the scores, iterations, converged and precision\n */\nexport async function eigenvectorCentrality(\n ctx: GpuContext,\n s: GraphSnapshot,\n options?: EigenvectorOptions & GpuRunOptions,\n): Promise<GpuScoresResult> {\n const algorithm = \"eigenvectorCentrality\";\n const r = resolve(ctx, s, options, algorithm);\n if (r.n === 0) {\n return empty(r.dest, r.maxIterations, options?.onProgress);\n }\n const run = await runPowerIteration(ctx, r.n, {\n normMode: 2,\n adjacency: coreOf(ctx, s, algorithm),\n alternate: null,\n alpha: 1,\n beta: 0,\n uniformP: 0,\n maxIterations: r.maxIterations,\n tolerance: r.tolerance,\n weights: r.weights,\n label: algorithm,\n signal: options?.signal,\n onProgress: options?.onProgress,\n });\n return scoresOf(run, r.dest, \"l2\");\n}\n\n/**\n * Katz centrality on the device (spec 3.3, 8.2): `x = alpha * A^T x + beta` over the reverse adjacency with no\n * per-iteration normaliser; the scores are L2-normalised once at the end.\n * @param ctx - the context whose device runs the kernels\n * @param s - the snapshot (uploaded through ctx.residency, or found there)\n * @param options - alpha 0.1 / beta 1 / maxIterations 100 / tolerance 1e-6 / weighted true, plus dest / signal / onProgress\n * @returns the scores, iterations, converged and precision\n */\nexport async function katzCentrality(\n ctx: GpuContext,\n s: GraphSnapshot,\n options?: KatzOptions & GpuRunOptions,\n): Promise<GpuScoresResult> {\n const algorithm = \"katzCentrality\";\n const alpha = finite(options?.alpha, 0.1, \"alpha\");\n const beta = finite(options?.beta, 1, \"beta\");\n const r = resolve(ctx, s, options, algorithm);\n if (r.n === 0) {\n return empty(r.dest, r.maxIterations, options?.onProgress);\n }\n const run = await runPowerIteration(ctx, r.n, {\n normMode: 4,\n adjacency: reverseOf(ctx, s),\n alternate: null,\n alpha,\n beta,\n uniformP: 1,\n maxIterations: r.maxIterations,\n tolerance: r.tolerance,\n weights: r.weights,\n label: algorithm,\n signal: options?.signal,\n onProgress: options?.onProgress,\n });\n return scoresOf(run, r.dest, \"l2\");\n}\n\n/**\n * HITS on the device (spec 3.3, 8.2): `a(i) = A^T norm(h(i-1))` and `h(i) = A norm(a(i-1))` from uniform seeds,\n * sum-normalised. Those two recurrences interleave into two independent chains, each alternating the reverse and\n * the forward pull, so the driver runs twice: the chain seeded as hubs pulls reverse first and holds h(m) after an\n * even number m of iterations and a(m) after an odd one; the chain seeded as authorities is the mirror image. Each\n * chain stops at its own batch boundary, so the two can end on opposite parities holding the SAME kind; the result\n * takes the latest iterate of each kind across both chains (a chain's last two iterates are one of each kind),\n * which is h(m) and a(m) when both ran m iterations and never two vectors of one kind otherwise.\n * `iterations` is the larger of the two and `converged` their conjunction. `dest`, when given, receives the hubs.\n * Both vectors are sum-normalised.\n * @param ctx - the context whose device runs the kernels\n * @param s - the snapshot (uploaded through ctx.residency, or found there)\n * @param options - maxIterations 100 / tolerance 1e-6 / weighted true, plus dest / signal / onProgress\n * @returns hubs, authorities, iterations, converged and precision\n */\nexport async function hits(\n ctx: GpuContext,\n s: GraphSnapshot,\n options?: HitsOptions & GpuRunOptions,\n): Promise<GpuHitsResult> {\n const algorithm = \"hits\";\n const r = resolve(ctx, s, options, algorithm);\n const total = 2 * r.maxIterations;\n if (r.n === 0) {\n const { scores, iterations, converged, precision } = empty(r.dest, total, options?.onProgress);\n return { hubs: scores, authorities: new Float32Array(0), iterations, converged, precision };\n }\n const onProgress = options?.onProgress;\n const shared = {\n normMode: 1 as const,\n alpha: 1,\n beta: 0,\n uniformP: 0,\n maxIterations: r.maxIterations,\n tolerance: r.tolerance,\n weights: r.weights,\n signal: options?.signal,\n };\n const forward = coreOf(ctx, s, algorithm);\n const reverse = reverseOf(ctx, s);\n const hubSeeded = await runPowerIteration(ctx, r.n, {\n ...shared,\n adjacency: reverse,\n alternate: forward,\n label: `${algorithm}/hub-seeded`,\n onProgress:\n onProgress === undefined\n ? undefined\n : (done) => {\n onProgress(done, total);\n },\n });\n const authoritySeeded = await runPowerIteration(ctx, r.n, {\n ...shared,\n adjacency: forward,\n alternate: reverse,\n label: `${algorithm}/authority-seeded`,\n onProgress:\n onProgress === undefined\n ? undefined\n : (done) => {\n onProgress(r.maxIterations + done, total);\n },\n });\n return {\n hubs: normalised(latestOfKind(hubSeeded, authoritySeeded), r.dest, \"sum\"),\n authorities: normalised(latestOfKind(authoritySeeded, hubSeeded), null, \"sum\"),\n iterations: Math.max(hubSeeded.iterations, authoritySeeded.iterations),\n converged: hubSeeded.converged && authoritySeeded.converged,\n precision: \"f32\",\n };\n}\n","/**\n * The CPU port's random number generator, bit for bit, and the NaN-row seeding both paths share (spec 7.2 \"Initial\n * positions\", 9.3 seedPositions, 7.14 `pos`, 7.19 topology change): a seed gives the same start on the CPU and the\n * GPU because both write the same f32 values in index order. The package carries its own copy of the LCG for its\n * whole life (D27: it cannot import @graphty/layout); W1 cross-tests it against the real RandomNumberGenerator.\n */\n\nimport type { F32, GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { WebGpuGraphError } from \"../errors.js\";\n\n/** The CPU port's LCG constants (layout/src/utils/random.ts): m = 2^35 - 31, a = 185852, c = 1. */\nexport const LCG_M = 34359738337;\n/** The multiplier a of the port's LCG. */\nexport const LCG_A = 185852;\n/** The increment c of the port's LCG. */\nexport const LCG_C = 1;\n\n/**\n * The port's RandomNumberGenerator, bit for bit: `seed || Math.floor(Math.random() * 1000000)` (seed 0 / null =\n * unseeded, the quirk preserved), state = seed % m, next = (a * state + c) % m, value = state / m. The product\n * a * state stays below 2^53 (a < 2^18, state < 2^35), so every step is exact in f64, as it is in the port.\n */\nexport class Lcg {\n /** The seed actually used (a random one when unseeded). */\n readonly seed: number;\n\n private state: number;\n\n /**\n * Creates the generator; a seed of 0, -0, NaN or null means unseeded (the port's `seed || random` quirk).\n * @param seed - the seed, or null for a random seed\n */\n constructor(seed: number | null) {\n this.seed = seed === null || seed === 0 || Number.isNaN(seed) ? Math.floor(Math.random() * 1000000) : seed;\n this.state = this.seed % LCG_M;\n }\n\n /**\n * Next value in [0, 1).\n * @returns state / m after one LCG step\n */\n next(): number {\n this.state = (LCG_A * this.state + LCG_C) % LCG_M;\n return this.state / LCG_M;\n }\n}\n\n/**\n * The three center components of a CommonLayoutOptions.center (missing components are 0).\n * @param center - the caller's center, or null\n * @returns [x, y, z]; E_INVALID_ARGUMENT when a component is not finite\n */\nfunction resolveCenter(center: ArrayLike<number> | null): [number, number, number] {\n const out: [number, number, number] = [0, 0, 0];\n if (center === null) {\n return out;\n }\n for (let axis = 0; axis < 3 && axis < center.length; axis++) {\n const v = center[axis];\n if (!Number.isFinite(v)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `center[${axis}] is not finite`, {\n argument: \"center\",\n value: v,\n expected: \"finite components\",\n });\n }\n out[axis] = v;\n }\n return out;\n}\n\n/**\n * Seeds the unseeded rows of the owner's stride-3 SCENE array in index order (spec 9.3 seedPositions, 7.14 `pos`,\n * 7.19 topology change): a row is unseeded when any of its `dim` components is not finite; every such component\n * draws one LCG value; when NO row is fully finite the draw is uniform in [-1, 1) layout units per axis (`range:\n * \"fa2\"`; `\"fr\"` is [0, 1)), otherwise uniform inside the [min, max] box of the finite components per axis,\n * converted to layout units (an axis with no finite value falls back to the range box); the value is written as\n * `v * scale + center[axis]`, which for scale 1 / center 0 is bit-identical to the port's `u * 2 - 1` (resp. `u`);\n * in 2D the third component of a seeded row is written as center[2]. Finite components are never changed and a\n * fully finite row is never touched. No random number is drawn when nothing needs seeding.\n * PLAN DECISION 12 (P3-T1): the box is taken over every finite COMPONENT (the port's rule), not over the fully\n * finite ROWS only; the two differ only when a partially finite row's finite axis lies outside the fully finite\n * rows' box (pinned by test/layouts/seed.test.ts). PLAN DECISION 13: a 2D row whose x and y are finite is seeded\n * whatever its z holds.\n * @param s - the snapshot (nodeCount rows)\n * @param positions - the owner's stride-3 scene-unit array, length 3 * nodeCount, modified in place\n * @param seed - the LCG seed (0 / null = unseeded, the port's quirk)\n * @param dim - 2 or 3\n * @param scale - the scene scale (> 0)\n * @param center - the scene center, or null for the origin\n * @param range - \"fa2\" for [-1, 1), \"fr\" for [0, 1)\n */\nexport function seedPositions(\n s: GraphSnapshot,\n positions: F32,\n seed: number | null,\n dim: 2 | 3,\n scale: number,\n center: ArrayLike<number> | null,\n range: \"fa2\" | \"fr\",\n): void {\n const n = s.nodeCount;\n if (dim !== 2 && dim !== 3) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `dim must be 2 or 3, got ${String(dim)}`, {\n argument: \"dim\",\n value: dim,\n expected: \"2 or 3\",\n });\n }\n if (positions.length !== 3 * n) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `positions has ${positions.length} entries, expected ${3 * n}`,\n {\n argument: \"positions\",\n value: positions.length,\n expected: 3 * n,\n },\n );\n }\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `scale must be a finite number > 0, got ${scale}`, {\n argument: \"scale\",\n value: scale,\n expected: \"a finite number > 0\",\n });\n }\n const c = resolveCenter(center);\n\n // classify the rows and collect the per-axis box of the finite components (scene units)\n const lo = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY];\n const hi = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY];\n let finiteRows = 0;\n let unseededRows = 0;\n for (let i = 0; i < n; i++) {\n let finite = true;\n for (let axis = 0; axis < dim; axis++) {\n const v = positions[3 * i + axis];\n if (Number.isFinite(v)) {\n if (v < lo[axis]) {\n lo[axis] = v;\n }\n if (v > hi[axis]) {\n hi[axis] = v;\n }\n } else {\n finite = false;\n }\n }\n if (finite) {\n finiteRows++;\n } else {\n unseededRows++;\n }\n }\n if (unseededRows === 0) {\n return;\n }\n\n // the per-axis draw box in layout units\n const rangeLo = range === \"fr\" ? 0 : -1;\n const rangeHi = 1;\n const boxLo = [rangeLo, rangeLo, rangeLo];\n const boxHi = [rangeHi, rangeHi, rangeHi];\n if (finiteRows > 0) {\n for (let axis = 0; axis < dim; axis++) {\n if (Number.isFinite(lo[axis]) && Number.isFinite(hi[axis])) {\n boxLo[axis] = (lo[axis] - c[axis]) / scale;\n boxHi[axis] = (hi[axis] - c[axis]) / scale;\n }\n }\n }\n\n const rng = new Lcg(seed);\n for (let i = 0; i < n; i++) {\n let unseeded = false;\n for (let axis = 0; axis < dim; axis++) {\n if (!Number.isFinite(positions[3 * i + axis])) {\n unseeded = true;\n }\n }\n if (!unseeded) {\n continue;\n }\n for (let axis = 0; axis < dim; axis++) {\n const at = 3 * i + axis;\n if (!Number.isFinite(positions[at])) {\n const u = rng.next();\n const v = boxLo[axis] + u * (boxHi[axis] - boxLo[axis]);\n positions[at] = v * scale + c[axis];\n }\n }\n if (dim === 2) {\n positions[3 * i + 2] = c[2];\n }\n }\n}\n","/**\n * The shared layout state machine (spec 7.19): the buffers every model shares (positions, scenePositions, fixed,\n * partials, state + trace), the in-flight batches and their readbacks, the settle window, the fixed mask and the\n * setPosition override list (spec 7.12), the trace and the batch driver; consumes a ForceModel by composition (the\n * per-model kernel sequence, buffers, overrides, per-iteration params, controller hooks and stats decoding).\n * Positions are layout units on the device and scene units in the owner's array (spec 7.18): load() repacks\n * (scene - center) / scale into vec4f with the mass in .w (D23); the model's toScene stage, recorded once per batch\n * on the last iteration (PLAN DECISION 2), writes p * scale + center back into scenePositions.\n */\n\nimport { type F32, type GraphSnapshot, makeMask, maskTest, type NodeMask, type U32 } from \"@graphty/graph-format\";\n\nimport {\n FA2_DEFAULTS,\n FA2_FLAG_FIRST,\n MAX_1D_ITEMS,\n MAX_ITERATIONS_PER_STEP,\n PARTIAL_BYTES,\n STATE_HEADER_BYTES,\n UNIFORM_SLOT_BYTES,\n} from \"../constants.js\";\nimport { type GpuContext } from \"../context.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { hasErrorCode, WebGpuGraphError } from \"../errors.js\";\nimport { CommandBatch, type ReadbackRequest, type SubmittedBatch } from \"../kernel/batch.js\";\nimport { type PipelineCache } from \"../kernel/pipeline-cache.js\";\nimport { type UniformBlock, type UniformFieldType, type UniformValues } from \"../kernel/struct-block.js\";\nimport { UniformRing } from \"../kernel/uniform-ring.js\";\nimport { type WgslModuleSpec } from \"../kernel/wgsl.js\";\nimport { graphOverrides } from \"../kernels.js\";\nimport { type ArrayBinding, type CoreBinding } from \"../memory/residency.js\";\nimport { type PlanCaps } from \"../types/context.js\";\nimport {\n type GpuLayoutSimulation,\n type LayoutStatsBase,\n type ResolvedLayoutTuning,\n type RunOptions,\n} from \"../types/layout.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type CommonLayoutOptions, type SimulationOptions } from \"../types/options.js\";\nimport { type ResolvedWeights } from \"./inputs.js\";\nimport { seedPositions } from \"./seed.js\";\n\n// ============================================================ the model hook interface (contract 3.13)\n\n/** A model-owned buffer beyond the shared set (spec 7.19: oldForce, velocity, the grid tier's). */\nexport interface BufferSpec {\n readonly name: string;\n readonly byteLength: number;\n readonly usage: number;\n readonly zero: boolean;\n}\n\n/** Host writes into the state header collected between submits (spec 7.19 onLoad / onReheat / onSetParams). */\nexport interface StateWriter {\n /** Queues a field write (flushed by one writeBuffer before the next submit; also applied to the host shadow immediately). */\n set(field: string, value: number | readonly number[]): void;\n /** The host shadow of a field (last known value). */\n get(field: string): number | readonly number[];\n}\n\n/** What a model gets at bind time (after load() / a resize): the graph, the shared and model buffers, the ring, the cache. */\nexport interface ModelResources {\n readonly device: GPUDevice;\n readonly caps: PlanCaps;\n readonly pipelines: PipelineCache;\n readonly core: CoreBinding;\n readonly perm: Binding | null;\n /**\n * The RESOLVED weights binding (model.inputs(): source \"arcs\" -> core.weights (null on an unweighted snapshot),\n * \"column\" -> the registered ArrayBinding's binding, \"none\" -> null); group 0 is built as\n * graphBindings(core, perm, weights) (3.10).\n */\n readonly weights: Binding | null;\n readonly n: number;\n readonly dim: 2 | 3;\n readonly tier: \"exact\" | \"grid\";\n readonly ring: UniformRing;\n /** A shared or model-owned buffer by name: \"positions\", \"scenePositions\", \"fixed\", \"partials\", \"state\", \"trace\", plus every BufferSpec name. */\n buffer(name: string): Binding;\n}\n\n/** The per-load inputs a model resolves from the snapshot and its options (mass into the `.w` lane; weights into the group-0 slot). */\nexport interface ModelInputs {\n readonly mass: F32;\n readonly weights: ResolvedWeights;\n}\n\n/**\n * Spec 7.19 ForceModel (kind, buffers, overrides, paramsFor, recordIteration, onLoad, onReheat, onSetParams,\n * readStats) with SEVEN additions (CONTRACT DECISION, each with its reason): `stages` (the kernel stage names for\n * debugRunStages / inspect, spec 11.9 item 2); `params` (the model's uniform block, which must declare the shared\n * field names n, dim, flags, iterationIndex, seed, scale, center, settleThreshold, so the simulation can write\n * them); `state` and `trace` (the model's generated Fa2State / Fa2Trace blocks, so the simulation allocates,\n * initialises and decodes the state buffer through the model's own layouts, D20); `specs` (the module specs of an\n * override set, for warm() and the compile matrix); `bind` (the model compiles and binds after load(), when the\n * buffers exist); `inputs` (mass and weight resolution need the model's option names -- nodeMass / weight are\n * ForceAtlas2Options, not CommonLayoutOptions -- so the simulation calls it at load() and derives USE_PERM /\n * HAS_WEIGHTS from ModelResources, 3.10); and the optional `upTo` argument of `recordIteration` (truncates the\n * sequence after a stage, for debugRunStages / inspect). PLAN DECISION 4: the state block must declare centroid,\n * min, max (vec4f), rmsRadius, radius, meanDisplacement (f32), iteration, settledCount (u32) and fit in\n * STATE_HEADER_BYTES; the params block must declare the eight shared names with center a vec4f and fit in\n * UNIFORM_SLOT_BYTES. PLAN DECISION 6: paramsFor receives the GLOBAL iteration index; the shared fields win.\n * PLAN DECISION 2: recordIteration with `upTo` undefined records EVERY stage (toScene included); `upTo = <stage>`\n * stops after that stage.\n */\nexport interface ForceModel<Options, Stats extends LayoutStatsBase> {\n readonly kind: \"forceatlas2\" | \"fruchtermanReingold\" | \"springElectrical\";\n readonly stages: readonly string[];\n readonly params: UniformBlock;\n readonly state: UniformBlock;\n readonly trace: UniformBlock;\n buffers(n: number, dim: 2 | 3): readonly BufferSpec[];\n /** Called at load() before the upload: FA2 = { mass: resolveNodeMass(s, nodeMass), weights: resolveWeights(s, weight) }. */\n inputs(s: GraphSnapshot, options: Options): ModelInputs;\n /** The model's OWN override set; the simulation merges USE_PERM / HAS_WEIGHTS from graphOverrides(core, perm, resources.weights) before specs() / bind(). */\n overrides(options: Options): Readonly<Record<string, number | boolean>>;\n specs(overrides: Readonly<Record<string, number | boolean>>, subgroups: boolean): readonly WgslModuleSpec[];\n bind(resources: ModelResources, overrides: Readonly<Record<string, number | boolean>>): Promise<void>;\n paramsFor(iteration: number, options: Options): UniformValues;\n recordIteration(batch: CommandBatch, slot: number, tier: \"exact\" | \"grid\", upTo?: string): void;\n onLoad(state: StateWriter): void;\n onReheat(state: StateWriter): void;\n onSetParams(patch: Partial<Options>, state: StateWriter): void;\n readStats(state: DataView, trace: DataView): Stats;\n}\n\n// ============================================================ module-private helpers\n\n/** The shared params fields (name, width) every model params block must declare (PLAN DECISION 4). */\nconst SHARED_PARAM_FIELDS: readonly (readonly [string, number])[] = [\n [\"n\", 1],\n [\"dim\", 1],\n [\"flags\", 1],\n [\"iterationIndex\", 1],\n [\"seed\", 1],\n [\"scale\", 1],\n [\"center\", 4],\n [\"settleThreshold\", 1],\n];\n\n/** The state fields (name, width) the simulation writes at load() and reads after every batch (PLAN DECISION 4). */\nconst SHARED_STATE_FIELDS: readonly (readonly [string, number])[] = [\n [\"centroid\", 4],\n [\"min\", 4],\n [\"max\", 4],\n [\"rmsRadius\", 1],\n [\"radius\", 1],\n [\"meanDisplacement\", 1],\n [\"iteration\", 1],\n [\"settledCount\", 1],\n];\n\n/** The names of the shared buffers a BufferSpec may not reuse. */\nconst SHARED_BUFFER_NAMES: readonly string[] = [\"positions\", \"scenePositions\", \"fixed\", \"partials\", \"state\", \"trace\"];\n\n/** The per-batch epilogue stage: iterations 0..k-2 stop after the stage that precedes it (PLAN DECISION 2). */\nconst EPILOGUE_STAGE = \"toScene\";\n\nlet simulationCounter = 0;\n\n/**\n * An E_INVALID_ARGUMENT with the documented details shape.\n * @param argument - the argument name\n * @param value - the offending value\n * @param expected - what was expected\n * @param message - the message\n * @returns the error\n */\nfunction invalidArgument(argument: string, value: unknown, expected: unknown, message: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", message, { argument, value, expected });\n}\n\n/**\n * The E_DISPOSED of a simulation.\n * @param label - the simulation label\n * @returns the error\n */\nfunction disposedError(label: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_DISPOSED\", `${label} is disposed`, { label });\n}\n\n/**\n * Coerces a caught value to an Error for Promise rejections.\n * @param err - the caught value\n * @returns the value when it is an Error, else a wrapping Error\n */\nfunction asError(err: unknown): Error {\n if (err instanceof Error) {\n return err;\n }\n return new Error(typeof err === \"string\" ? err : \"unknown error\");\n}\n\n/**\n * Reads a field of an option record the generic type does not name (maxIter, iterations, nodeSize).\n * @param record - the options or patch\n * @param key - the field name\n * @returns the value, or undefined\n */\nfunction optionField(record: object, key: string): unknown {\n return (record as Record<string, unknown>)[key];\n}\n\n/**\n * The number of scalars of a uniform field type.\n * @param type - the field type\n * @returns 1, 2 or 4\n */\nfunction fieldWidth(type: UniformFieldType): number {\n switch (type) {\n case \"u32\":\n case \"i32\":\n case \"f32\":\n return 1;\n case \"vec2f\":\n case \"vec2u\":\n return 2;\n case \"vec4f\":\n case \"vec4u\":\n return 4;\n default:\n throw invalidArgument(\"type\", type, \"a UniformFieldType\", \"unknown uniform field type\");\n }\n}\n\n/**\n * The type of a block field, or null when the block does not declare it.\n * @param block - the block\n * @param field - the field name\n * @returns the type or null\n */\nfunction fieldTypeOrNull(block: UniformBlock, field: string): UniformFieldType | null {\n for (const [name, type] of block.fields) {\n if (name === field) {\n return type;\n }\n }\n return null;\n}\n\n/**\n * The type of a block field.\n * @param block - the block\n * @param field - the field name\n * @returns the type; E_INVALID_ARGUMENT when the block does not declare the field\n */\nfunction fieldTypeOf(block: UniformBlock, field: string): UniformFieldType {\n const type = fieldTypeOrNull(block, field);\n if (type === null) {\n throw invalidArgument(\n \"field\",\n field,\n block.fields.map((f) => f[0]),\n `block ${block.name} has no field ${field}`,\n );\n }\n return type;\n}\n\n/**\n * Asserts a block declares every (name, width) pair (PLAN DECISION 4).\n * @param block - the block\n * @param required - the required fields\n * @param what - \"model.params\" or \"model.state\", for the error\n */\nfunction requireFields(block: UniformBlock, required: readonly (readonly [string, number])[], what: string): void {\n for (const [field, width] of required) {\n const type = fieldTypeOrNull(block, field);\n if (type === null) {\n throw invalidArgument(\n what,\n field,\n required.map((r) => r[0]),\n `${what} block ${block.name} must declare ${field}`,\n );\n }\n if (fieldWidth(type) !== width) {\n throw invalidArgument(\n what,\n field,\n `a field of width ${width}`,\n `${what}.${field} must have width ${width}`,\n );\n }\n }\n}\n\n/**\n * A stable string of an override record, for the law-change comparison of setParams.\n * @param record - the overrides\n * @returns the JSON of the sorted entries\n */\nfunction stableKey(record: Readonly<Record<string, number | boolean>>): string {\n return JSON.stringify(\n Object.keys(record)\n .sort()\n .map((k) => [k, record[k]]),\n );\n}\n\n/**\n * The stats record with msPerIteration filled by the simulation (PLAN DECISION 3).\n * @param stats - the model's record\n * @param msPerIteration - the measured value\n * @returns the record\n */\nfunction withMs<S extends LayoutStatsBase>(stats: S, msPerIteration: number | null): S {\n return { ...stats, msPerIteration };\n}\n\n/**\n * True for a SharedArrayBuffer (the package never writes into one, spec 5.7).\n * @param buffer - the backing buffer\n * @returns true when shared\n */\nfunction isSharedBuffer(buffer: ArrayBufferLike): boolean {\n return typeof SharedArrayBuffer !== \"undefined\" && buffer instanceof SharedArrayBuffer;\n}\n\n/**\n * The validated scale of an option record (FA2_DEFAULTS.scale when absent).\n * @param options - the options\n * @returns the scale\n */\nfunction scaleOf(options: CommonLayoutOptions): number {\n const scale = options.scale ?? FA2_DEFAULTS.scale;\n if (!Number.isFinite(scale) || scale <= 0) {\n throw invalidArgument(\"scale\", scale, \"a finite number > 0\", `scale must be a finite number > 0, got ${scale}`);\n }\n return scale;\n}\n\n/**\n * The validated center of an option record (missing components are 0).\n * @param options - the options\n * @returns [x, y, z]\n */\nfunction centerOf(options: CommonLayoutOptions): [number, number, number] {\n const out: [number, number, number] = [0, 0, 0];\n const { center } = options;\n if (center === undefined) {\n return out;\n }\n for (let axis = 0; axis < 3 && axis < center.length; axis++) {\n const v = center[axis];\n if (!Number.isFinite(v)) {\n throw invalidArgument(\"center\", v, \"finite components\", `center[${axis}] is not finite`);\n }\n out[axis] = v;\n }\n return out;\n}\n\n/**\n * The repulsion tier of a node count under a tuning (PLAN DECISION 11).\n * @param tuning - the resolved tuning\n * @param n - the node count\n * @returns \"exact\" or \"grid\"\n */\nfunction tierFor(tuning: ResolvedLayoutTuning, n: number): \"exact\" | \"grid\" {\n if (tuning.repulsion === \"exact\") {\n return \"exact\";\n }\n if (tuning.repulsion === \"grid\") {\n return \"grid\";\n }\n return n <= tuning.exactMaxNodes ? \"exact\" : \"grid\";\n}\n\n/**\n * A whole-buffer binding.\n * @param buffer - the buffer\n * @param size - its byte length\n * @returns the binding\n */\nfunction wholeBinding(buffer: GPUBuffer, size: number): Binding {\n return { buffer, offset: 0, size, window: null };\n}\n\n/**\n * The host side of the state header (PLAN DECISION 5): a shadow of every field, a queue of the fields set since\n * the last flush, and the byte image the queued fields are copied from.\n */\nclass HeaderWriter implements StateWriter {\n private readonly block: UniformBlock;\n private readonly shadow = new Map<string, number | readonly number[]>();\n private readonly queued = new Map<string, number | readonly number[]>();\n\n /**\n * Creates a writer over a model's state block with every field 0.\n * @param block - the model's state block\n */\n constructor(block: UniformBlock) {\n this.block = block;\n this.reset();\n }\n\n /**\n * Queues a field write and applies it to the shadow.\n * @param field - the field name (E_INVALID_ARGUMENT when the block lacks it or the width differs)\n * @param value - a number for a scalar field, an array of the vector's width otherwise\n */\n set(field: string, value: number | readonly number[]): void {\n const width = fieldWidth(fieldTypeOf(this.block, field));\n const ok = width === 1 ? typeof value === \"number\" : typeof value !== \"number\" && value.length === width;\n if (!ok) {\n throw invalidArgument(\n \"value\",\n value,\n `a value of width ${width}`,\n `state field ${field} takes a value of width ${width}`,\n );\n }\n this.shadow.set(field, value);\n this.queued.set(field, value);\n }\n\n /**\n * The host shadow of a field: the last value set, or the last landed header's value.\n * @param field - the field name\n * @returns the value\n */\n get(field: string): number | readonly number[] {\n const value = this.shadow.get(field);\n if (value === undefined) {\n throw invalidArgument(\n \"field\",\n field,\n this.block.fields.map((f) => f[0]),\n `state block has no field ${field}`,\n );\n }\n return value;\n }\n\n /** Every field back to 0 and the queue cleared (load()). */\n reset(): void {\n this.shadow.clear();\n this.queued.clear();\n const zero = this.block.read(new DataView(new ArrayBuffer(this.block.byteLength)));\n for (const [name, value] of Object.entries(zero)) {\n this.shadow.set(name, value);\n }\n }\n\n /**\n * The byte image of the shadow (the block's own writer, D20).\n * @returns block.byteLength bytes\n */\n headerBytes(): ArrayBuffer {\n const bytes = new ArrayBuffer(this.block.byteLength);\n this.block.write(new DataView(bytes), Object.fromEntries(this.shadow));\n return bytes;\n }\n\n /**\n * Refreshes the shadow from a landed header; a field set since the last flush keeps its queued value.\n * @param view - the landed header\n */\n absorb(view: DataView): void {\n for (const [name, value] of Object.entries(this.block.read(view))) {\n if (!this.queued.has(name)) {\n this.shadow.set(name, value);\n }\n }\n }\n\n /**\n * The fields set since the last flush; clears the queue.\n * @returns the field names\n */\n takeQueued(): string[] {\n const fields = [...this.queued.keys()];\n this.queued.clear();\n return fields;\n }\n\n /** Drops the queue (after load() wrote the whole header). */\n clearQueued(): void {\n this.queued.clear();\n }\n}\n\n/** One batch from the step() call that created it until its readback settled (PLAN DECISION 7). */\ninterface PendingBatch {\n readonly k: number;\n readonly generation: number;\n readonly promise: Promise<void>;\n readonly resolve: () => void;\n readonly reject: (error: Error) => void;\n id: number;\n submitted: SubmittedBatch | null;\n stale: boolean;\n startedAt: number;\n sceneOffset: number;\n stateOffset: number;\n profile: ReadbackRequest | null;\n}\n\n/**\n * A pending record whose promise the simulation settles.\n * @param k - iterations of the batch\n * @param generation - the generation at the step() call\n * @returns the record\n */\nfunction createPending(k: number, generation: number): PendingBatch {\n let resolveFn: () => void = () => undefined;\n let rejectFn: (error: Error) => void = () => undefined;\n const promise = new Promise<void>((resolve, reject) => {\n resolveFn = resolve;\n rejectFn = reject;\n });\n return {\n k,\n generation,\n promise,\n resolve: () => {\n resolveFn();\n },\n reject: (error: Error) => {\n rejectFn(error);\n },\n id: 0,\n submitted: null,\n stale: false,\n startedAt: 0,\n sceneOffset: 0,\n stateOffset: 0,\n profile: null,\n };\n}\n\n/** The simulation's buffers of one load() (spec 7.3) plus the name -> Binding map the model and inspect() read. */\ninterface SimulationBuffers {\n readonly positions: GPUBuffer;\n readonly scene: GPUBuffer;\n readonly fixed: GPUBuffer;\n readonly partials: GPUBuffer;\n readonly state: GPUBuffer;\n readonly model: ReadonlyMap<string, { readonly buffer: GPUBuffer; readonly spec: BufferSpec }>;\n readonly bindings: ReadonlyMap<string, Binding>;\n readonly traceRegionBytes: number;\n}\n\n/** The registered expanded weight column of the current load (re-expanded only when column.version changed). */\ninterface WeightsUpload {\n readonly serial: number;\n readonly column: object;\n readonly version: number;\n readonly data: F32;\n readonly upload: ArrayBinding;\n}\n\n// ============================================================ the simulation\n\n/**\n * The shared layout state machine (spec 7.19): buffers, in-flight batches, readback, settle window, fixed mask,\n * setPosition overrides, trace, batch driver; consumes a ForceModel by composition.\n */\nexport class ForceSimulation<\n Options extends CommonLayoutOptions & SimulationOptions,\n Stats extends LayoutStatsBase,\n> implements GpuLayoutSimulation<Options, Stats> {\n readonly ctx: GpuContext;\n readonly model: ForceModel<Options, Stats>;\n readonly tuning: ResolvedLayoutTuning;\n /**\n * The uniform ring, sized (maxInFlight + 1) x MAX_ITERATIONS_PER_STEP slots at construction (CONTRACT DECISION:\n * reserve() wraps to 0 when the tail is short, so maxInFlight batches of up to MAX_ITERATIONS_PER_STEP slots\n * plus one wasted tail always fit without a slot being rewritten while a submitted batch still reads it; hence\n * setParams cannot change maxInFlight, 3.13 forceatlas2.ts).\n * @internal\n */\n readonly ring: UniformRing;\n /**\n * Present when ctx.debug.inspect is true: reads back any named buffer (a shared name, a BufferSpec name,\n * \"force\", \"state\", \"trace\") after the last submitted kernel; resolves a Float32Array except for \"fixed\",\n * \"trace\" (raw words) which resolve Uint32Array.\n */\n inspect?: (name: string) => Promise<Float32Array | Uint32Array>;\n /**\n * Present when ctx.debug.inspect is true: records ONE iteration truncated after stage `upTo` (a model stage\n * name), submits, awaits it (no readback into positions, no stats update).\n * @internal\n */\n debugRunStages?: (upTo: string) => Promise<void>;\n\n private readonly resolveOptions: (patch: Partial<Options>, current: Options) => Options;\n private readonly maxInFlight: number;\n private readonly label: string;\n private readonly traceBytes: number;\n private readonly writer: HeaderWriter;\n private readonly overrideList = new Map<number, number>();\n private readonly pending: PendingBatch[] = [];\n private readonly unregisterLost: () => void;\n private optionsValue: Options;\n private stateValue: \"created\" | \"loaded\" | \"disposed\" = \"created\";\n private generationValue = 0;\n private tierValue: \"exact\" | \"grid\";\n private dimValue: 2 | 3;\n private snapshot: GraphSnapshot | null = null;\n private serial: number | null = null;\n private owner: F32 | null = null;\n private n = 0;\n private scale = 1;\n private center: [number, number, number] = [0, 0, 0];\n private buffers: SimulationBuffers | null = null;\n private core: CoreBinding | null = null;\n private resources: ModelResources | null = null;\n private weightsUpload: WeightsUpload | null = null;\n private ready: Promise<void> = Promise.resolve();\n private submitChain: Promise<void> = Promise.resolve();\n private fixedWords: U32 = new Uint32Array(0);\n private fixedDirty = false;\n private iterationsSubmitted = 0;\n private iterationsDoneValue = 0;\n private settledCountValue = 0;\n private settledValue = false;\n private firstPending = true;\n private statsValue: Stats | null = null;\n private lastSubmittedBatchIdValue = 0;\n /** The id of the last batch submitted BEFORE the most recent reheat() (PLAN DECISION 21); 0 = none. */\n private reheatedAfterBatchId = 0;\n private coalescedValue = 0;\n private torndown = false;\n\n /**\n * Creates a simulation over a context and a model (state \"created\"; load() makes it \"loaded\").\n * @param ctx - the context (ready)\n * @param model - the force model\n * @param options - the option record (defaults applied by the caller's factory)\n * @param tuning - the resolved GPU tuning\n * @param resolve - how setParams merges a patch into the current record\n */\n constructor(\n ctx: GpuContext,\n model: ForceModel<Options, Stats>,\n options: Options,\n tuning: ResolvedLayoutTuning,\n resolve: (patch: Partial<Options>, current: Options) => Options,\n ) {\n ctx.assertReady();\n requireFields(model.params, SHARED_PARAM_FIELDS, \"model.params\");\n requireFields(model.state, SHARED_STATE_FIELDS, \"model.state\");\n if (model.params.byteLength > UNIFORM_SLOT_BYTES) {\n throw invalidArgument(\n \"model.params\",\n model.params.byteLength,\n `<= ${UNIFORM_SLOT_BYTES} bytes`,\n \"the params block must fit one ring slot\",\n );\n }\n if (model.state.byteLength > STATE_HEADER_BYTES) {\n throw invalidArgument(\n \"model.state\",\n model.state.byteLength,\n `<= ${STATE_HEADER_BYTES} bytes`,\n \"the state block must fit the state header\",\n );\n }\n if (model.stages.length === 0) {\n throw invalidArgument(\n \"model.stages\",\n model.stages,\n \"at least one stage name\",\n \"a model declares its stages\",\n );\n }\n const maxInFlight = options.maxInFlight ?? FA2_DEFAULTS.maxInFlight;\n if (!Number.isInteger(maxInFlight) || maxInFlight < 1) {\n throw invalidArgument(\n \"maxInFlight\",\n maxInFlight,\n \"an integer >= 1\",\n `maxInFlight must be an integer >= 1, got ${maxInFlight}`,\n );\n }\n const dim = options.dim ?? FA2_DEFAULTS.dim;\n if (dim !== 2 && dim !== 3) {\n throw invalidArgument(\"dim\", dim, \"2 or 3\", `dim must be 2 or 3, got ${String(dim)}`);\n }\n // scale and center are validated now so a bad option never reaches load()\n scaleOf(options);\n centerOf(options);\n simulationCounter++;\n this.ctx = ctx;\n this.model = model;\n this.tuning = tuning;\n this.resolveOptions = resolve;\n this.optionsValue = options;\n this.maxInFlight = maxInFlight;\n this.dimValue = dim;\n this.tierValue = tuning.repulsion === \"grid\" ? \"grid\" : \"exact\";\n this.label = `${model.kind}#${simulationCounter}`;\n this.traceBytes = model.trace.byteLength;\n this.writer = new HeaderWriter(model.state);\n this.ring = new UniformRing(\n ctx.device,\n ctx.allocator,\n (maxInFlight + 1) * MAX_ITERATIONS_PER_STEP,\n `${this.label}/ring`,\n );\n this.unregisterLost = ctx.onLost((info) => {\n this.onDeviceLost(info);\n });\n if (ctx.debug.inspect) {\n this.inspect = (name: string): Promise<Float32Array | Uint32Array> => this.inspectBuffer(name);\n this.debugRunStages = (upTo: string): Promise<void> => this.runStages(upTo);\n }\n }\n\n // ---------------------------------------------------------------- read-only state\n\n /**\n * \"created\" | \"loaded\" | \"disposed\".\n * @returns the state\n */\n get state(): \"created\" | \"loaded\" | \"disposed\" {\n return this.stateValue;\n }\n\n /**\n * The current options record (defaults applied).\n * @returns the record\n */\n get options(): Options {\n return this.optionsValue;\n }\n\n /**\n * The repulsion tier of the current load (\"exact\" until P4 lifts the grid tier).\n * @returns the tier\n */\n get tier(): \"exact\" | \"grid\" {\n return this.tierValue;\n }\n\n /**\n * The generation counter bumped by every load() (stale readbacks are discarded).\n * @internal\n * @returns the generation\n */\n get generation(): number {\n return this.generationValue;\n }\n\n /**\n * Nodes of the current load (0 before load()).\n * @returns the node count\n */\n get nodeCount(): number {\n return this.n;\n }\n\n /**\n * 2 or 3, fixed at construction (setParams({ dim }) is rejected, spec 7.13).\n * @returns the dimension\n */\n get dim(): 2 | 3 {\n return this.dimValue;\n }\n\n /**\n * iterationsDone >= the budget OR settledCount >= settleWindow of the last completed batch (spec 7.17); true for an empty graph.\n * @returns whether the layout is settled\n */\n get settled(): boolean {\n return this.settledValue;\n }\n\n /**\n * Batches created by step() and not yet landed (PLAN DECISION 7: counted from the step() call).\n * @returns the count\n */\n get inFlight(): number {\n return this.pending.length;\n }\n\n /**\n * Iterations landed since load() or the last reheat().\n * @returns the count\n */\n get iterationsDone(): number {\n return this.iterationsDoneValue;\n }\n\n /**\n * The stats of the last completed batch; before one lands, the host-written header decoded through the model\n * with an empty trace and msPerIteration null.\n * @returns the stats\n */\n get stats(): Stats {\n if (this.statsValue !== null) {\n return this.statsValue;\n }\n const header = new DataView(this.writer.headerBytes());\n const trace = new DataView(new ArrayBuffer(0));\n return withMs(this.model.readStats(header, trace), null);\n }\n\n /**\n * The override list (spec 7.12): rows whose readback is skipped while a batch older than the write is in flight.\n * @internal\n * @returns row -> lastSubmittedBatchId at the write\n */\n get overrides(): ReadonlyMap<number, number> {\n return this.overrideList;\n }\n\n /**\n * The last submitted batch id.\n * @internal\n * @returns the id (0 before any submit)\n */\n get lastSubmittedBatchId(): number {\n return this.lastSubmittedBatchIdValue;\n }\n\n /**\n * Number of step() calls that returned an existing batch's promise instead of submitting (spec 7.19 item 3;\n * read by test/helpers/frame-loop.ts).\n * @internal\n * @returns the count\n */\n get coalesced(): number {\n return this.coalescedValue;\n }\n\n // ---------------------------------------------------------------- load\n\n /**\n * Uploads the snapshot's core, seeds the NaN rows of `positions`, repacks it into layout-unit vec4f with the\n * mass in .w, writes the initial state, starts the model's compile + bind and enters \"loaded\" (spec 7.19; a\n * load() during flight bumps the generation and discards the in-flight batches). Order of the checks (PLAN\n * DECISION 16): E_DISPOSED, the context's assertReady, E_SNAPSHOT (directed), E_TOO_LARGE (nodeCount), the\n * positions array, the tuning, then the core upload and model.inputs() BEFORE any state is touched.\n * PLAN DECISION 10: nodeCount 0 loads with no GPU work at all. PLAN DECISION 11: the tier is resolved here\n * and \"grid\" is E_UNSUPPORTED until P4. PLAN DECISION 17: a same-size load() keeps the buffers and re-zeroes\n * partials, the trace region and every `zero: true` model buffer.\n * @param snapshot - an undirected snapshot\n * @param positions - the owner's stride-3 scene-unit array (NaN rows are seeded in place)\n */\n load(snapshot: GraphSnapshot, positions: F32): void {\n this.assertNotDisposed();\n this.ctx.assertReady();\n if (snapshot.directed) {\n throw new WebGpuGraphError(\n \"E_SNAPSHOT\",\n \"a layout needs an undirected snapshot: pass toUndirected().snapshot\",\n {\n reason: \"directed\",\n serial: snapshot.serial,\n },\n );\n }\n const n = snapshot.nodeCount;\n if (n > MAX_1D_ITEMS) {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `${n} nodes exceed ${MAX_1D_ITEMS} (the third partials level is P4)`,\n {\n needed: n,\n limit: MAX_1D_ITEMS,\n path: \"partials\",\n algorithm: this.model.kind,\n },\n );\n }\n if (positions.length !== 3 * n) {\n throw invalidArgument(\n \"positions\",\n positions.length,\n 3 * n,\n `positions has ${positions.length} entries, expected ${3 * n}`,\n );\n }\n if (isSharedBuffer(positions.buffer)) {\n throw invalidArgument(\n \"positions\",\n \"SharedArrayBuffer\",\n \"an ArrayBuffer-backed Float32Array\",\n \"positions must not be backed by a SharedArrayBuffer\",\n );\n }\n const scale = scaleOf(this.optionsValue);\n const center = centerOf(this.optionsValue);\n const tier = tierFor(this.tuning, n);\n if (tier === \"grid\") {\n throw new WebGpuGraphError(\n \"E_UNSUPPORTED\",\n `the grid repulsion tier lands at P4 (n = ${n}, exactMaxNodes = ${this.tuning.exactMaxNodes})`,\n {\n feature: \"repulsion.grid\",\n hint: 'pass repulsion: \"exact\" or raise exactMaxNodes',\n },\n );\n }\n const positionsBytes = 16 * n;\n if (positionsBytes > this.ctx.caps.limits.maxBufferSize) {\n throw new WebGpuGraphError(\"E_TOO_LARGE\", `${positionsBytes} bytes of positions exceed maxBufferSize`, {\n needed: positionsBytes,\n limit: this.ctx.caps.limits.maxBufferSize,\n path: \"positions\",\n algorithm: this.model.kind,\n });\n }\n let core: CoreBinding | null = null;\n let inputs: ModelInputs | null = null;\n if (n > 0) {\n core = this.ctx.residency.core(snapshot);\n if (core.plan === \"windowed\") {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n \"a windowed core cannot be walked by the layout kernels until P4\",\n {\n needed: snapshot.arcCount,\n limit: this.ctx.caps.limits.maxStorageBufferBindingSize,\n path: \"windowed\",\n algorithm: this.model.kind,\n },\n );\n }\n inputs = this.model.inputs(snapshot, this.optionsValue);\n if (inputs.mass.length !== n) {\n throw invalidArgument(\n \"nodeMass\",\n inputs.mass.length,\n n,\n `the model resolved ${inputs.mass.length} masses for ${n} nodes`,\n );\n }\n }\n\n // ---- every check passed: mutate\n this.generationValue++;\n this.discardPending();\n const resized = this.buffers === null || n !== this.n || snapshot.serial !== this.serial;\n this.snapshot = snapshot;\n this.serial = snapshot.serial;\n this.owner = positions;\n this.n = n;\n this.tierValue = tier;\n this.scale = scale;\n this.center = center;\n this.core = core;\n this.iterationsSubmitted = 0;\n this.iterationsDoneValue = 0;\n this.settledCountValue = 0;\n this.firstPending = true;\n this.statsValue = null;\n this.writer.reset();\n if (resized) {\n this.destroyBuffers();\n this.overrideList.clear();\n this.fixedWords = makeMask(n);\n this.fixedDirty = false;\n }\n if (n === 0 || core === null || inputs === null) {\n // PLAN DECISION 10: an empty graph loads with no GPU work\n this.weightsUpload = null;\n this.resources = null;\n // keep the chain (PLAN DECISION 20): a bind of the previous load may still be running and the next\n // non-empty load() must start its bind after it; its outcome is irrelevant here\n this.ready = this.ready.catch(() => undefined);\n this.settledValue = true;\n this.stateValue = \"loaded\";\n return;\n }\n const buffers = resized ? this.allocate(n) : this.requireBuffers();\n if (!resized) {\n this.clearKept(buffers);\n }\n this.buffers = buffers;\n const range = this.model.kind === \"fruchtermanReingold\" ? \"fr\" : \"fa2\";\n seedPositions(snapshot, positions, this.optionsValue.seed ?? null, this.dimValue, scale, center, range);\n this.uploadPositions(buffers, positions, inputs.mass);\n const weights = this.resolveWeightsBinding(snapshot, core, inputs.weights);\n const overrides = { ...this.model.overrides(this.optionsValue), ...graphOverrides(core, null, weights) };\n const resources = this.makeResources(core, weights, buffers);\n this.resources = resources;\n this.startBind(resources, overrides);\n this.settledValue = false;\n this.stateValue = \"loaded\";\n }\n\n // ---------------------------------------------------------------- step and the batch driver\n\n /**\n * Submits k iterations (spec 7.19 items 1-6): \"created\" -> E_NOT_LOADED; \"disposed\" -> E_DISPOSED; a released\n * snapshot -> E_RELEASED; k outside [1, MAX_ITERATIONS_PER_STEP] -> E_INVALID_ARGUMENT; settled -> resolves at\n * once; inFlight >= maxInFlight -> the OLDEST pending batch's promise (coalesced); else the batch is queued on\n * the submit chain (after the bind promise and allocator.check()) and its promise resolves when its readback\n * landed in the owner's array. The same promise object is returned for every coalesced call. PLAN DECISION 7:\n * the batch counts in `inFlight` from this call, not from its submission.\n * @param iterations - k (default options.iterationsPerStep, default 1)\n * @returns resolves when the batch landed (or was discarded); rejects E_VALIDATION / E_DEVICE_LOST / E_OUT_OF_MEMORY / E_SHADER_COMPILE\n */\n step(iterations?: number): Promise<void> {\n if (this.stateValue === \"created\") {\n return Promise.reject(\n new WebGpuGraphError(\"E_NOT_LOADED\", `${this.label}: load() first`, { state: \"created\" }),\n );\n }\n if (this.stateValue === \"disposed\") {\n return Promise.reject(disposedError(this.label));\n }\n try {\n this.ctx.assertReady();\n } catch (err) {\n return Promise.reject(asError(err));\n }\n const { snapshot } = this;\n if (snapshot !== null && this.ctx.residency.isReleased(snapshot.serial)) {\n return Promise.reject(\n new WebGpuGraphError(\n \"E_RELEASED\",\n `snapshot ${snapshot.serial} was released while ${this.label} used it`,\n {\n serial: snapshot.serial,\n },\n ),\n );\n }\n const k = iterations ?? this.optionsValue.iterationsPerStep ?? FA2_DEFAULTS.iterationsPerStep;\n if (!Number.isInteger(k) || k < 1 || k > MAX_ITERATIONS_PER_STEP) {\n return Promise.reject(\n invalidArgument(\n \"iterations\",\n k,\n `an integer in [1, ${MAX_ITERATIONS_PER_STEP}]`,\n `step(${k}): iterations must be an integer in [1, ${MAX_ITERATIONS_PER_STEP}]`,\n ),\n );\n }\n if (this.settledValue || this.n === 0) {\n return Promise.resolve();\n }\n if (this.pending.length >= this.maxInFlight) {\n this.coalescedValue++;\n return this.pending[0].promise;\n }\n const record = createPending(k, this.generationValue);\n this.pending.push(record);\n this.submitChain = this.submitChain.then(() => this.submitBatch(record));\n return record.promise;\n }\n\n /**\n * Resolves when nothing is in flight (every pending batch landed or was discarded).\n * @returns the promise\n */\n async flush(): Promise<void> {\n while (this.pending.length > 0) {\n await Promise.allSettled(this.pending.map((r) => r.promise));\n }\n }\n\n /**\n * Node batch driver: loops step(batch) until settled, the budget (`maxIter ?? options.maxIter`, PLAN DECISION\n * 1) is reached or the signal aborts (E_ABORTED; the batch in flight at the abort is discarded, spec 5.7 / Q-15).\n * @param options - maxIter, batch (default 8), signal\n * @returns the stats of the last completed batch\n */\n async run(options?: RunOptions): Promise<Stats> {\n this.assertNotDisposed();\n const batch = options?.batch ?? 8;\n if (!Number.isInteger(batch) || batch < 1 || batch > MAX_ITERATIONS_PER_STEP) {\n throw invalidArgument(\n \"batch\",\n batch,\n `an integer in [1, ${MAX_ITERATIONS_PER_STEP}]`,\n \"run(): batch must be an integer in [1, MAX_ITERATIONS_PER_STEP]\",\n );\n }\n const budget = options?.maxIter ?? this.iterationBudget();\n if (Number.isNaN(budget) || budget < 0) {\n throw invalidArgument(\"maxIter\", budget, \"a number >= 0\", \"run(): maxIter must be >= 0\");\n }\n const signal = options?.signal;\n const onAbort = (): void => {\n this.discardPending();\n };\n if (signal !== undefined) {\n if (signal.aborted) {\n throw this.abortedError();\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n try {\n while (!this.settled && this.iterationsDoneValue < budget) {\n if (signal?.aborted === true) {\n throw this.abortedError();\n }\n const k = Math.min(batch, budget - this.iterationsDoneValue);\n await this.step(k);\n }\n if (signal?.aborted === true) {\n throw this.abortedError();\n }\n return this.stats;\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n // ---------------------------------------------------------------- pins, drags, reheat, params\n\n /**\n * Copies the mask words (spec 7.12): E_INVALID_ARGUMENT when shorter than ceil(n / 32); the buffer is marked\n * dirty and re-uploaded before the next submit; reheat() iff some bit went 1 -> 0 (an unpin). PLAN DECISION\n * 18: the comparison is bit by bit below n (bits at or above n never count as an unpin).\n * @param mask - the NodeMask (LSB-first words)\n */\n setFixed(mask: NodeMask): void {\n this.assertLoaded();\n const { n } = this;\n const words = Math.ceil(n / 32);\n if (mask.length < words) {\n throw invalidArgument(\n \"mask\",\n mask.length,\n words,\n `setFixed: the mask has ${mask.length} words, ${words} needed for ${n} nodes`,\n );\n }\n let unpinned = false;\n for (let w = 0; w < words && !unpinned; w++) {\n if (this.fixedWords[w] === mask[w]) {\n continue;\n }\n const last = Math.min(n, w * 32 + 32);\n for (let i = w * 32; i < last; i++) {\n if (maskTest(this.fixedWords, i) && !maskTest(mask, i)) {\n unpinned = true;\n break;\n }\n }\n }\n this.fixedWords.set(mask.subarray(0, words));\n this.fixedDirty = true;\n if (unpinned) {\n this.reheat();\n }\n }\n\n /**\n * Writes a scene-unit position (spec 7.12): into the owner's array at once, into the device (layout units, z 0\n * in 2D, 12 bytes at 16 i, queue-ordered before the next submit), into the override list keyed by the last\n * submitted batch id, then reheat(). PLAN DECISION 18: non-finite coordinates are E_INVALID_ARGUMENT.\n * @param index - the node index (< n)\n * @param x - scene x\n * @param y - scene y\n * @param z - scene z (ignored on the device in 2D)\n */\n setPosition(index: number, x: number, y: number, z: number): void {\n this.assertLoaded();\n const { n } = this;\n if (!Number.isInteger(index) || index < 0 || index >= n) {\n throw invalidArgument(\n \"index\",\n index,\n `an integer in [0, ${n})`,\n `setPosition(${index}): index out of range`,\n );\n }\n if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)) {\n throw invalidArgument(\n \"position\",\n [x, y, z],\n \"finite coordinates\",\n \"setPosition: coordinates must be finite\",\n );\n }\n const { owner, buffers } = this;\n if (owner === null || buffers === null) {\n throw new WebGpuGraphError(\"E_NOT_LOADED\", `${this.label}: load() first`, { state: this.stateValue });\n }\n owner[3 * index] = x;\n owner[3 * index + 1] = y;\n owner[3 * index + 2] = z;\n const [cx, cy, cz] = this.center;\n const layout = new Float32Array([\n (x - cx) / this.scale,\n (y - cy) / this.scale,\n this.dimValue === 2 ? 0 : (z - cz) / this.scale,\n ]);\n this.ctx.device.queue.writeBuffer(buffers.positions, 16 * index, layout);\n this.overrideList.set(index, this.lastSubmittedBatchIdValue);\n this.reheat();\n }\n\n /**\n * iterationsDone = 0, settledCount = 0 (a queued state write), model.onReheat(writer); nothing else (D8: the\n * speed controller keeps its state). `settled` is recomputed at once (PLAN DECISION 8). Allowed before load().\n * PLAN DECISION 21: the id of the last batch submitted so far is remembered; a batch with that id or an older\n * one was computed from the pre-reheat counter, so its landed settledCount is taken as 0 (see onLanded) and a\n * drag or unpin can never leave the simulation settled through a batch that was already in flight.\n */\n reheat(): void {\n this.assertNotDisposed();\n this.iterationsDoneValue = 0;\n this.settledCountValue = 0;\n this.reheatedAfterBatchId = this.lastSubmittedBatchIdValue;\n this.writer.set(\"settledCount\", 0);\n this.model.onReheat(this.writer);\n this.settledValue = this.computeSettled();\n }\n\n /**\n * Live tuning (spec 3.3, 7.17): `dim` differing from the current -> E_INVALID_ARGUMENT; `maxInFlight` differing\n * -> E_INVALID_ARGUMENT (the ring is sized by it); a non-null `nodeSize` -> E_UNSUPPORTED; the record is\n * replaced through `resolve(patch, current)`; a change of the model's override set (a force LAW) recompiles\n * and re-binds; scale / center changes reach the next batch through the shared params of every slot (the\n * model's toScene reads them); then model.onSetParams(patch, writer) and reheat().\n * @param patch - the fields to change\n */\n setParams(patch: Partial<Options>): void {\n this.assertNotDisposed();\n const current = this.optionsValue;\n const { dim, maxInFlight } = patch;\n if (dim !== undefined && dim !== this.dimValue) {\n throw invalidArgument(\n \"dim\",\n dim,\n this.dimValue,\n \"dim is fixed at construction; graphty-element re-creates the engine on a view-mode switch (spec 7.13)\",\n );\n }\n if (maxInFlight !== undefined && maxInFlight !== this.maxInFlight) {\n throw invalidArgument(\n \"maxInFlight\",\n maxInFlight,\n this.maxInFlight,\n \"maxInFlight is fixed at construction (the uniform ring is sized by it)\",\n );\n }\n const nodeSize = optionField(patch, \"nodeSize\");\n if (nodeSize !== undefined && nodeSize !== null) {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"nodeSize (adjustSizes) is deferred (spec 7.14)\", {\n option: \"nodeSize\",\n hint: \"leave nodeSize null; the size correction ships in a later slice\",\n });\n }\n const next = this.resolveOptions(patch, current);\n const scale = scaleOf(next);\n const center = centerOf(next);\n const before = stableKey(this.model.overrides(current));\n const after = stableKey(this.model.overrides(next));\n this.optionsValue = next;\n this.scale = scale;\n this.center = center;\n const { resources, core } = this;\n if (this.stateValue === \"loaded\" && resources !== null && core !== null && before !== after) {\n const overrides = { ...this.model.overrides(next), ...graphOverrides(core, null, resources.weights) };\n this.startBind(resources, overrides);\n }\n this.model.onSetParams(patch, this.writer);\n this.reheat();\n }\n\n // ---------------------------------------------------------------- dispose and device loss\n\n /**\n * Discards in-flight batches (their promises resolve), destroys every simulation buffer and the ring, trims\n * the pool, unregisters the loss listener; state \"disposed\"; idempotent.\n */\n dispose(): void {\n if (this.stateValue === \"disposed\") {\n return;\n }\n this.stateValue = \"disposed\";\n this.teardown();\n }\n\n // ---------------------------------------------------------------- private: the batch driver\n\n /**\n * The serialised submission of one pending batch: awaits the bind / warm promise and allocator.check(), then\n * records and submits unless the record went stale meanwhile; wires the readback handlers. A record that went\n * stale while waiting (a load() or dispose() superseded it) RESOLVES even when the wait rejected (PLAN\n * DECISION 8: the rejection belongs to the superseded generation -- a bind that failed E_SHADER_COMPILE, or\n * the ring's E_DISPOSED after dispose() tore it down under a running bind).\n * @param record - the pending batch\n */\n private async submitBatch(record: PendingBatch): Promise<void> {\n try {\n await this.ready;\n await this.ctx.allocator.check();\n } catch (err) {\n this.finish(record);\n if (this.isStale(record)) {\n record.resolve();\n return;\n }\n if (hasErrorCode(err, \"E_OUT_OF_MEMORY\")) {\n this.outOfMemory();\n }\n record.reject(asError(err));\n return;\n }\n if (this.isStale(record)) {\n this.finish(record);\n record.resolve();\n return;\n }\n let submitted: SubmittedBatch;\n try {\n submitted = this.recordAndSubmit(record);\n } catch (err) {\n this.finish(record);\n record.reject(asError(err));\n return;\n }\n submitted.readback.then(\n (bytes) => {\n this.onLanded(record, bytes);\n },\n (err: unknown) => {\n this.onFailed(record, err);\n },\n );\n }\n\n /**\n * Flushes the host writes, fills k ring slots, records k iterations (only the last one runs the model's toScene\n * epilogue, PLAN DECISION 2) + the two readbacks into one CommandBatch and submits it (spec 7.19 items 4-5).\n * @param record - the pending batch\n * @returns the submitted batch\n */\n private recordAndSubmit(record: PendingBatch): SubmittedBatch {\n const buffers = this.requireBuffers();\n const { k } = record;\n const { device } = this.ctx;\n if (this.fixedDirty) {\n device.queue.writeBuffer(buffers.fixed, 0, this.fixedWords);\n this.fixedDirty = false;\n }\n this.flushStateWrites(buffers.state);\n const first = this.ring.reserve(k);\n for (let i = 0; i < k; i++) {\n const flags = i === 0 && this.firstPending ? FA2_FLAG_FIRST : 0;\n this.ring.write(first + i, this.model.params, this.paramsForSlot(this.iterationsSubmitted + i, i, flags));\n }\n this.ring.flush();\n const batch = new CommandBatch(this.ctx, `${this.label}/batch`, this.generationValue);\n const beforeEpilogue = this.lastIterationStage();\n for (let i = 0; i < k; i++) {\n // the last iteration records every stage (toScene included); the others stop before the epilogue\n this.model.recordIteration(batch, first + i, this.tierValue, i === k - 1 ? undefined : beforeEpilogue);\n }\n batch.endPass();\n const scene = batch.readback(buffers.scene, 0, 12 * this.n);\n const state = batch.readback(buffers.state, 0, STATE_HEADER_BYTES + k * this.traceBytes);\n const { profiler } = this.ctx;\n const profile = profiler === null ? null : profiler.resolveInto(batch);\n const submitted = batch.submit();\n record.submitted = submitted;\n record.id = submitted.id;\n record.sceneOffset = scene.offset;\n record.stateOffset = state.offset;\n record.profile = profile;\n record.startedAt = performance.now();\n this.lastSubmittedBatchIdValue = submitted.id;\n this.iterationsSubmitted += k;\n this.firstPending = false;\n return submitted;\n }\n\n /**\n * A landed readback (spec 7.19 item 6): stale -> discard; else the scene bytes go into the owner's array row by\n * row (skipping overridden rows, clearing overrides older than this batch), the header refreshes the shadow,\n * the stats are decoded through the model (msPerIteration from the profiler or the wall time, PLAN DECISION 3),\n * iterationsDone += k and settled is recomputed -- with the landed settledCount taken as 0 when the batch was\n * submitted before the last reheat() (PLAN DECISION 21; the header is still absorbed and the stats decoded).\n * @param record - the pending batch\n * @param bytes - the batch's readback bytes\n */\n private onLanded(record: PendingBatch, bytes: ArrayBuffer): void {\n this.finish(record);\n const { owner } = this;\n if (this.isStale(record) || owner === null) {\n record.resolve();\n return;\n }\n try {\n const { k } = record;\n const { n } = this;\n const needed = Math.max(\n record.sceneOffset + 12 * n,\n record.stateOffset + STATE_HEADER_BYTES + k * this.traceBytes,\n );\n if (bytes.byteLength < needed) {\n // a discarded readback resolves with an empty buffer\n record.resolve();\n return;\n }\n this.copyScene(owner, bytes, record);\n const header = new DataView(bytes, record.stateOffset, STATE_HEADER_BYTES);\n const trace = new DataView(bytes, record.stateOffset + STATE_HEADER_BYTES, k * this.traceBytes);\n this.writer.absorb(header);\n const settledCount = this.model.state.readField(header, \"settledCount\");\n if (typeof settledCount !== \"number\") {\n throw invalidArgument(\"settledCount\", settledCount, \"a scalar\", \"settledCount must be a scalar field\");\n }\n const ms = this.batchMilliseconds(record, bytes);\n this.statsValue = withMs(this.model.readStats(header, trace), ms / k);\n this.iterationsDoneValue += k;\n // PLAN DECISION 21: a batch in flight at reheat() carries the pre-reheat settle counter\n this.settledCountValue = record.id <= this.reheatedAfterBatchId ? 0 : settledCount;\n this.settledValue = this.computeSettled();\n record.resolve();\n } catch (err) {\n record.reject(asError(err));\n }\n }\n\n /**\n * A failed readback: a discarded batch's E_ABORTED resolves (PLAN DECISION 8); a lost device rejects\n * E_DEVICE_LOST; everything else (E_VALIDATION, E_DISPOSED) rejects as is.\n * @param record - the pending batch\n * @param err - the rejection\n */\n private onFailed(record: PendingBatch, err: unknown): void {\n this.finish(record);\n if (hasErrorCode(err, \"E_ABORTED\") && this.isStale(record)) {\n record.resolve();\n return;\n }\n if (this.ctx.state === \"lost\" && !hasErrorCode(err, \"E_DEVICE_LOST\")) {\n record.reject(\n new WebGpuGraphError(\"E_DEVICE_LOST\", \"the device was lost while the batch was in flight\", {\n reason: \"unknown\",\n message: asError(err).message,\n }),\n );\n return;\n }\n record.reject(asError(err));\n }\n\n /**\n * Copies the scene bytes of a landed batch into the owner's array, honouring the override list (spec 7.12).\n * @param owner - the owner's array\n * @param bytes - the readback\n * @param record - the batch\n */\n private copyScene(owner: F32, bytes: ArrayBuffer, record: PendingBatch): void {\n const { n } = this;\n const scene = new Float32Array(bytes, record.sceneOffset, 3 * n);\n if (this.overrideList.size === 0) {\n owner.set(scene);\n return;\n }\n for (let i = 0; i < n; i++) {\n const after = this.overrideList.get(i);\n if (after !== undefined && after >= record.id) {\n continue;\n }\n owner[3 * i] = scene[3 * i];\n owner[3 * i + 1] = scene[3 * i + 1];\n owner[3 * i + 2] = scene[3 * i + 2];\n }\n for (const [i, after] of this.overrideList) {\n if (after < record.id) {\n this.overrideList.delete(i);\n }\n }\n }\n\n /**\n * The batch's duration in milliseconds: the profiler's pass timings summed when present, else wall time.\n * @param record - the batch\n * @param bytes - its readback (the profiler's resolve lands in it)\n * @returns milliseconds\n */\n private batchMilliseconds(record: PendingBatch, bytes: ArrayBuffer): number {\n const { profiler } = this.ctx;\n if (profiler !== null && record.profile !== null) {\n const timings = profiler.timings(bytes, record.profile);\n if (timings.length > 0) {\n let ns = 0;\n for (const timing of timings) {\n ns += timing.ns;\n }\n return ns / 1e6;\n }\n }\n return performance.now() - record.startedAt;\n }\n\n /**\n * Whether a record belongs to an earlier generation, was discarded, or the simulation left \"loaded\".\n * @param record - the batch\n * @returns true when its readback must be ignored\n */\n private isStale(record: PendingBatch): boolean {\n return record.stale || this.stateValue !== \"loaded\" || record.generation !== this.generationValue;\n }\n\n /**\n * Removes a record from the pending list (idempotent).\n * @param record - the batch\n */\n private finish(record: PendingBatch): void {\n const at = this.pending.indexOf(record);\n if (at >= 0) {\n this.pending.splice(at, 1);\n }\n }\n\n /** Marks every pending batch stale and discards the submitted ones (their readbacks resolve empty or E_ABORTED). */\n private discardPending(): void {\n for (const record of this.pending) {\n record.stale = true;\n record.submitted?.discard();\n }\n }\n\n /** An OOM surfaced by allocator.check(): every simulation buffer is destroyed and the state returns to \"created\". */\n private outOfMemory(): void {\n this.discardPending();\n this.destroyBuffers();\n this.ctx.allocator.reset();\n this.settledValue = false;\n this.stateValue = \"created\";\n }\n\n /**\n * The E_ABORTED of run().\n * @returns the error\n */\n private abortedError(): WebGpuGraphError {\n return new WebGpuGraphError(\"E_ABORTED\", `${this.label}: run() aborted by the signal`, {\n batchId: this.lastSubmittedBatchIdValue,\n });\n }\n\n // ---------------------------------------------------------------- private: params, state writes, toScene\n\n /**\n * The uniform values of one iteration slot: the model's values with the shared fields on top (PLAN DECISION 6).\n * @param global - the global iteration index (iterationsSubmitted + i)\n * @param index - the slot index within the batch (the trace slot)\n * @param flags - FA2_FLAG_FIRST for the first iteration after load(), else 0\n * @returns the values\n */\n private paramsForSlot(global: number, index: number, flags: number): UniformValues {\n const [cx, cy, cz] = this.center;\n const shared: UniformValues = {\n n: this.n,\n dim: this.dimValue,\n flags,\n iterationIndex: index,\n seed: this.seedU32(),\n scale: this.scale,\n center: [cx, cy, cz, 0],\n settleThreshold: this.settleThreshold(),\n };\n return { ...this.model.paramsFor(global, this.optionsValue), ...shared };\n }\n\n /**\n * The option seed as a u32 (0 when unseeded), the near-field hash seed of P4.\n * @returns the seed\n */\n private seedU32(): number {\n const { seed } = this.optionsValue;\n if (seed === null || seed === undefined || !Number.isFinite(seed)) {\n return 0;\n }\n return Math.floor(Math.abs(seed)) % 4294967296;\n }\n\n /**\n * Writes the queued state fields, each as one writeBuffer of its own byte range (PLAN DECISION 5).\n * @param state - the state buffer\n */\n private flushStateWrites(state: GPUBuffer): void {\n const fields = this.writer.takeQueued();\n if (fields.length === 0) {\n return;\n }\n const bytes = this.writer.headerBytes();\n const block = this.model.state;\n for (const field of fields) {\n const offset = block.offsetOf(field);\n const size = 4 * fieldWidth(fieldTypeOf(block, field));\n this.ctx.device.queue.writeBuffer(state, offset, bytes, offset, size);\n }\n }\n\n /**\n * The stage that precedes the toScene epilogue in model.stages (the `upTo` of every iteration but the last), or\n * undefined when the model has no epilogue or lists it first (every iteration then records every stage).\n * @returns the stage name or undefined\n */\n private lastIterationStage(): string | undefined {\n const at = this.model.stages.indexOf(EPILOGUE_STAGE);\n if (at <= 0) {\n return undefined;\n }\n return this.model.stages[at - 1];\n }\n\n /**\n * The settle threshold of the current options (FA2_DEFAULTS when absent).\n * @returns the threshold\n */\n private settleThreshold(): number {\n return this.optionsValue.settleThreshold ?? FA2_DEFAULTS.settleThreshold;\n }\n\n /**\n * The settle window of the current options (FA2_DEFAULTS when absent).\n * @returns the window\n */\n private settleWindow(): number {\n return this.optionsValue.settleWindow ?? FA2_DEFAULTS.settleWindow;\n }\n\n /**\n * The iteration budget (PLAN DECISION 1): options.maxIter, else options.iterations, else no budget.\n * @returns the budget\n */\n private iterationBudget(): number {\n const maxIter = optionField(this.optionsValue, \"maxIter\");\n if (typeof maxIter === \"number\") {\n return maxIter;\n }\n const iterations = optionField(this.optionsValue, \"iterations\");\n if (typeof iterations === \"number\") {\n return iterations;\n }\n return Number.POSITIVE_INFINITY;\n }\n\n /**\n * The settle rule of spec 7.17 over the counters of the last completed batch.\n * @returns whether the layout is settled\n */\n private computeSettled(): boolean {\n if (this.stateValue !== \"loaded\") {\n return false;\n }\n return (\n this.n === 0 ||\n this.iterationsDoneValue >= this.iterationBudget() ||\n this.settledCountValue >= this.settleWindow()\n );\n }\n\n // ---------------------------------------------------------------- private: buffers, upload, bind\n\n /**\n * Allocates the shared buffers (spec 7.3 sizes) and the model's BufferSpecs through the allocator (every buffer\n * labelled); a `zero: true` spec must carry COPY_DST so it can be re-zeroed when kept across loads (PLAN\n * DECISION 17). The state buffer is STATE_HEADER_BYTES + MAX_ITERATIONS_PER_STEP x model.trace.byteLength:\n * contract 3.13 writes TRACE_RECORD_BYTES (32, the FA2 record) for the last factor; the model's block is the\n * same number for FA2 and is what the simulation decodes the trace with, so it is the general rule (PLAN\n * DECISION 4) and the constant is not imported here.\n * @param n - the node count (> 0)\n * @returns the buffers and the name -> Binding map\n */\n private allocate(n: number): SimulationBuffers {\n const { allocator } = this.ctx;\n const { label } = this;\n const groups = Math.ceil(n / this.ctx.workgroupSize);\n const traceRegionBytes = MAX_ITERATIONS_PER_STEP * this.traceBytes;\n const storageRw = BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST;\n const positions = allocator.createBuffer({ label: `${label}/positions`, size: 16 * n, usage: storageRw });\n const scene = allocator.createBuffer({\n label: `${label}/scenePositions`,\n size: 12 * n,\n usage: BufferUsage.STORAGE | BufferUsage.COPY_SRC,\n });\n const fixed = allocator.createBuffer({\n label: `${label}/fixed`,\n size: 4 * Math.ceil(n / 32),\n usage: storageRw,\n });\n const partials = allocator.createBuffer({\n label: `${label}/partials`,\n size: PARTIAL_BYTES * groups,\n usage: storageRw,\n });\n const state = allocator.createBuffer({\n label: `${label}/state`,\n size: STATE_HEADER_BYTES + traceRegionBytes,\n usage: storageRw,\n });\n const bindings = new Map<string, Binding>();\n bindings.set(\"positions\", wholeBinding(positions, 16 * n));\n bindings.set(\"scenePositions\", wholeBinding(scene, 12 * n));\n bindings.set(\"fixed\", wholeBinding(fixed, 4 * Math.ceil(n / 32)));\n bindings.set(\"partials\", wholeBinding(partials, PARTIAL_BYTES * groups));\n bindings.set(\"state\", { buffer: state, offset: 0, size: STATE_HEADER_BYTES, window: null });\n bindings.set(\"trace\", { buffer: state, offset: STATE_HEADER_BYTES, size: traceRegionBytes, window: null });\n const model = new Map<string, { readonly buffer: GPUBuffer; readonly spec: BufferSpec }>();\n for (const spec of this.model.buffers(n, this.dimValue)) {\n if (SHARED_BUFFER_NAMES.includes(spec.name) || bindings.has(spec.name)) {\n throw invalidArgument(\n \"BufferSpec.name\",\n spec.name,\n \"a name no other buffer uses\",\n `BufferSpec \"${spec.name}\" reuses a buffer name`,\n );\n }\n if (!Number.isInteger(spec.byteLength) || spec.byteLength <= 0 || spec.byteLength % 4 !== 0) {\n throw invalidArgument(\n \"BufferSpec.byteLength\",\n spec.byteLength,\n \"a positive multiple of 4\",\n `BufferSpec \"${spec.name}\" has byteLength ${spec.byteLength}`,\n );\n }\n if (spec.zero && (spec.usage & BufferUsage.COPY_DST) === 0) {\n throw invalidArgument(\n \"BufferSpec.usage\",\n spec.usage,\n \"COPY_DST on a zero: true spec\",\n `BufferSpec \"${spec.name}\" is zero: true but lacks COPY_DST`,\n );\n }\n const buffer = allocator.createBuffer({\n label: `${label}/${spec.name}`,\n size: spec.byteLength,\n usage: spec.usage,\n });\n model.set(spec.name, { buffer, spec });\n bindings.set(spec.name, wholeBinding(buffer, spec.byteLength));\n }\n return { positions, scene, fixed, partials, state, model, bindings, traceRegionBytes };\n }\n\n /**\n * Re-zeroes the buffers a same-size load() keeps: partials, the trace region and every `zero: true` model buffer.\n * @param buffers - the kept buffers\n */\n private clearKept(buffers: SimulationBuffers): void {\n const { device } = this.ctx;\n const encoder = device.createCommandEncoder({ label: `${this.label}/clear` });\n encoder.clearBuffer(buffers.partials);\n encoder.clearBuffer(buffers.state, STATE_HEADER_BYTES, buffers.traceRegionBytes);\n for (const { buffer, spec } of buffers.model.values()) {\n if (spec.zero) {\n encoder.clearBuffer(buffer);\n }\n }\n device.queue.submit([encoder.finish()]);\n }\n\n /**\n * Destroys every simulation buffer through the allocator (the ring lives on until dispose()). While batches are\n * still in flight the destruction is DEFERRED until their readbacks have settled: the GPU may still be copying\n * out of `scene` / `state` and Dawn's Metal backend (dawn-node 0.4.0 on macOS) has taken the worker process\n * down when a buffer with pending work was destroyed (the Vulkan backends defer internally). The simulation\n * drops its references at once either way, so nothing here is reachable afterwards.\n */\n private destroyBuffers(): void {\n const { buffers } = this;\n if (buffers === null) {\n return;\n }\n this.buffers = null;\n this.resources = null;\n const doomed = [buffers.positions, buffers.scene, buffers.fixed, buffers.partials, buffers.state];\n for (const { buffer } of buffers.model.values()) {\n doomed.push(buffer);\n }\n this.afterInFlight(() => {\n const { allocator } = this.ctx;\n for (const buffer of doomed) {\n allocator.destroy(buffer);\n }\n });\n }\n\n /**\n * Runs `action` now when no submitted batch is in flight, otherwise once every in-flight readback has settled\n * (resolved, discarded or rejected -- the staging slot is returned and the GPU work is done either way).\n * @param action - the destruction to run\n */\n private afterInFlight(action: () => void): void {\n const waits: Promise<unknown>[] = [];\n for (const record of this.pending) {\n if (record.submitted !== null) {\n waits.push(record.submitted.readback.catch(() => undefined));\n }\n }\n if (waits.length === 0) {\n action();\n return;\n }\n void Promise.all(waits).then(action, action);\n }\n\n /**\n * The buffers of the current load.\n * @returns the buffers; E_NOT_LOADED when there are none\n */\n private requireBuffers(): SimulationBuffers {\n const { buffers } = this;\n if (buffers === null) {\n throw new WebGpuGraphError(\"E_NOT_LOADED\", `${this.label}: load() first`, { state: this.stateValue });\n }\n return buffers;\n }\n\n /**\n * Repacks the seeded scene array into layout-unit vec4f (mass in .w, z = 0 in 2D), uploads it, and writes the\n * initial centroid / bbox / rmsRadius / radius (f64 over the f32 values uploaded) with iteration 0,\n * settledCount 0, meanDisplacement 0 into the state header, then model.onLoad(writer) and one whole-header\n * writeBuffer (spec 7.4, 7.17, 7.18).\n * @param buffers - the buffers\n * @param positions - the seeded owner array\n * @param mass - the resolved masses\n */\n private uploadPositions(buffers: SimulationBuffers, positions: F32, mass: F32): void {\n const { n, scale } = this;\n const [cx, cy, cz] = this.center;\n const packed = new Float32Array(4 * n);\n for (let i = 0; i < n; i++) {\n packed[4 * i] = (positions[3 * i] - cx) / scale;\n packed[4 * i + 1] = (positions[3 * i + 1] - cy) / scale;\n packed[4 * i + 2] = this.dimValue === 2 ? 0 : (positions[3 * i + 2] - cz) / scale;\n packed[4 * i + 3] = mass[i];\n }\n this.ctx.device.queue.writeBuffer(buffers.positions, 0, packed);\n let sx = 0;\n let sy = 0;\n let sz = 0;\n const lo = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY];\n const hi = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY];\n for (let i = 0; i < n; i++) {\n const x = packed[4 * i];\n const y = packed[4 * i + 1];\n const z = packed[4 * i + 2];\n sx += x;\n sy += y;\n sz += z;\n lo[0] = Math.min(lo[0], x);\n lo[1] = Math.min(lo[1], y);\n lo[2] = Math.min(lo[2], z);\n hi[0] = Math.max(hi[0], x);\n hi[1] = Math.max(hi[1], y);\n hi[2] = Math.max(hi[2], z);\n }\n const mx = sx / n;\n const my = sy / n;\n const mz = sz / n;\n let sumSq = 0;\n let maxSq = 0;\n for (let i = 0; i < n; i++) {\n const dx = packed[4 * i] - mx;\n const dy = packed[4 * i + 1] - my;\n const dz = packed[4 * i + 2] - mz;\n const q = dx * dx + dy * dy + dz * dz;\n sumSq += q;\n maxSq = Math.max(maxSq, q);\n }\n const { writer } = this;\n writer.set(\"iteration\", 0);\n writer.set(\"settledCount\", 0);\n writer.set(\"meanDisplacement\", 0);\n writer.set(\"centroid\", [mx, my, mz, 0]);\n writer.set(\"min\", [lo[0], lo[1], lo[2], 0]);\n writer.set(\"max\", [hi[0], hi[1], hi[2], 0]);\n writer.set(\"rmsRadius\", Math.sqrt(sumSq / n));\n writer.set(\"radius\", Math.sqrt(maxSq));\n this.model.onLoad(writer);\n this.ctx.device.queue.writeBuffer(buffers.state, 0, writer.headerBytes());\n writer.clearQueued();\n }\n\n /**\n * The weights binding of a load (3.10): \"arcs\" -> core.weights, \"none\" -> null, \"column\" -> the expanded array\n * registered with residency.array(expanded, \"weights\", snapshot), the previous array object reused when the\n * column and its version are unchanged (so the upload cache finds it).\n * @param snapshot - the snapshot\n * @param core - its core\n * @param resolved - model.inputs().weights\n * @returns the binding for the group-0 weights slot, or null\n */\n private resolveWeightsBinding(\n snapshot: GraphSnapshot,\n core: CoreBinding,\n resolved: ResolvedWeights,\n ): Binding | null {\n if (resolved.source === \"arcs\") {\n this.weightsUpload = null;\n return core.weights;\n }\n if (resolved.source === \"none\" || resolved.data === null || resolved.column === null) {\n this.weightsUpload = null;\n return null;\n }\n const previous = this.weightsUpload;\n const reusable =\n previous !== null &&\n previous.serial === snapshot.serial &&\n previous.column === resolved.column &&\n previous.version === resolved.column.version &&\n previous.data.length === resolved.data.length;\n const data = reusable && previous !== null ? previous.data : resolved.data;\n const upload = this.ctx.residency.array(data, \"weights\", snapshot);\n this.weightsUpload = {\n serial: snapshot.serial,\n column: resolved.column,\n version: resolved.column.version,\n data,\n upload,\n };\n return upload.binding;\n }\n\n /**\n * The ModelResources of a load.\n * @param core - the core\n * @param weights - the resolved weights binding\n * @param buffers - the buffers\n * @returns the resources\n */\n private makeResources(core: CoreBinding, weights: Binding | null, buffers: SimulationBuffers): ModelResources {\n const { bindings } = buffers;\n return {\n device: this.ctx.device,\n caps: this.ctx.caps,\n pipelines: this.ctx.pipelines,\n core,\n perm: null,\n weights,\n n: this.n,\n dim: this.dimValue,\n tier: this.tierValue,\n ring: this.ring,\n buffer: (name: string): Binding => {\n const binding = bindings.get(name);\n if (binding === undefined) {\n throw invalidArgument(\"name\", name, [...bindings.keys()], `no simulation buffer named \"${name}\"`);\n }\n return binding;\n },\n };\n }\n\n /**\n * Chains the compile + bind promise the next step() awaits on the PREVIOUS one (PLAN DECISION 20: binds are\n * serialised on `ready` for load() and setParams() alike, so a superseded load()'s bind either fails its\n * generation check before model.bind() or completes before its successor's bind starts -- it can never bind\n * the model to destroyed buffers AFTER the new bind finished). The previous promise's rejection is swallowed by\n * the chain (it belonged to the superseded generation); this promise's rejection is kept for the next step()\n * (the derived catch only silences the unhandled-rejection warning).\n * @param resources - the resources\n * @param overrides - the merged override set\n */\n private startBind(resources: ModelResources, overrides: Readonly<Record<string, number | boolean>>): void {\n const generation = this.generationValue;\n const run = (): Promise<void> => this.compileAndBind(resources, overrides, generation);\n const promise = this.ready.catch(() => undefined).then(run);\n void promise.catch(() => undefined);\n this.ready = promise;\n }\n\n /**\n * warm(model.specs()) then model.bind(); the await re-checks that the load is current before binding.\n * @param resources - the resources\n * @param overrides - the merged override set\n * @param generation - the generation the bind belongs to\n */\n private async compileAndBind(\n resources: ModelResources,\n overrides: Readonly<Record<string, number | boolean>>,\n generation: number,\n ): Promise<void> {\n const subgroups = this.ctx.caps.features.has(\"subgroups\");\n await this.ctx.pipelines.warm(this.model.specs(overrides, subgroups));\n if (this.stateValue !== \"loaded\" || generation !== this.generationValue) {\n return;\n }\n await this.model.bind(resources, overrides);\n }\n\n // ---------------------------------------------------------------- private: inspect and debug runs\n\n /**\n * inspect(name): flush, read the named buffer back, Uint32Array for \"fixed\" and \"trace\", Float32Array otherwise.\n * @param name - a shared or BufferSpec name\n * @returns the words\n */\n private async inspectBuffer(name: string): Promise<Float32Array | Uint32Array> {\n this.assertLoaded();\n const { buffers } = this;\n const binding = buffers?.bindings.get(name);\n if (buffers === null || binding === undefined) {\n throw invalidArgument(\n \"name\",\n name,\n buffers === null ? [] : [...buffers.bindings.keys()],\n `inspect(\"${name}\"): no such buffer`,\n );\n }\n await this.flush();\n const bytes = await this.ctx.readback.read(binding.buffer, binding.size, undefined, binding.offset);\n return name === \"fixed\" || name === \"trace\" ? new Uint32Array(bytes) : new Float32Array(bytes);\n }\n\n /**\n * debugRunStages(upTo): one iteration truncated after a stage, submitted alone after flush(), awaited through\n * a header readback; never advances the counters or the FA2_FLAG_FIRST flag (PLAN DECISION 9).\n * @param upTo - a model stage name\n */\n private async runStages(upTo: string): Promise<void> {\n this.assertLoaded();\n if (!this.model.stages.includes(upTo)) {\n throw invalidArgument(\n \"upTo\",\n upTo,\n [...this.model.stages],\n `debugRunStages(\"${upTo}\"): not a stage of ${this.model.kind}`,\n );\n }\n if (this.n === 0) {\n return;\n }\n await this.flush();\n await this.ready;\n await this.ctx.allocator.check();\n this.assertLoaded();\n const buffers = this.requireBuffers();\n const { device } = this.ctx;\n if (this.fixedDirty) {\n device.queue.writeBuffer(buffers.fixed, 0, this.fixedWords);\n this.fixedDirty = false;\n }\n this.flushStateWrites(buffers.state);\n const slot = this.ring.reserve(1);\n this.ring.write(\n slot,\n this.model.params,\n this.paramsForSlot(this.iterationsSubmitted, 0, this.firstPending ? FA2_FLAG_FIRST : 0),\n );\n this.ring.flush();\n const batch = new CommandBatch(this.ctx, `${this.label}/debug`, this.generationValue);\n this.model.recordIteration(batch, slot, this.tierValue, upTo);\n batch.endPass();\n batch.readback(buffers.state, 0, STATE_HEADER_BYTES);\n const submitted = batch.submit();\n this.lastSubmittedBatchIdValue = submitted.id;\n await submitted.readback;\n }\n\n // ---------------------------------------------------------------- private: lifecycle\n\n /**\n * Device loss (spec 5.7): every pending promise rejects E_DEVICE_LOST, the simulation is disposed.\n * @param info - the loss info\n */\n private onDeviceLost(info: GPUDeviceLostInfo): void {\n if (this.stateValue === \"disposed\") {\n return;\n }\n const error = new WebGpuGraphError(\"E_DEVICE_LOST\", `device lost (${info.reason}): ${info.message}`, {\n reason: info.reason,\n message: info.message,\n });\n const pending = this.pending.splice(0);\n this.stateValue = \"disposed\";\n for (const record of pending) {\n record.stale = true;\n record.reject(error);\n }\n this.teardown();\n }\n\n /** Releases everything once: pending batches discarded, buffers and ring destroyed, pool trimmed, listener unregistered. */\n private teardown(): void {\n if (this.torndown) {\n return;\n }\n this.torndown = true;\n this.discardPending();\n this.destroyBuffers();\n this.afterInFlight(() => {\n this.ring.destroy();\n });\n if (this.ctx.state === \"ready\") {\n this.ctx.pool.trim();\n }\n this.unregisterLost();\n this.core = null;\n this.snapshot = null;\n this.owner = null;\n this.weightsUpload = null;\n }\n\n /** E_DISPOSED after dispose() or device loss. */\n private assertNotDisposed(): void {\n if (this.stateValue === \"disposed\") {\n throw disposedError(this.label);\n }\n }\n\n /** E_NOT_LOADED before load(), E_DISPOSED after dispose(). */\n private assertLoaded(): void {\n if (this.stateValue === \"created\") {\n throw new WebGpuGraphError(\"E_NOT_LOADED\", `${this.label}: load() first`, { state: \"created\" });\n }\n this.assertNotDisposed();\n }\n}\n","/**\n * nodeMass and weight resolution from graph-format primitives only (spec 7.14, 7.5; D28, Q-30): the role-\"mass\"\n * node column first, then outDegree() + 1; weights from the arc array, from a named edge column expanded to arcs\n * with expandEdges, or none. The Record form of nodeMass is rejected with the hint of spec 7.14 (graphty-element\n * writes its nodeMass config as the role column once at engine creation, so both simulations find it the same way\n * and this package parses no ids).\n */\n\nimport { type Column, expandEdges, type F32, type GraphSnapshot, type NodeId } from \"@graphty/graph-format\";\n\nimport { WebGpuGraphError } from \"../errors.js\";\n\n/** The message of spec 7.14 for the Record form of nodeMass. */\nconst NODE_MASS_HINT =\n \"write a role 'mass' node column (nodes.set(name, vec, { role: 'mass', replaceRole: true })) or pass a \" +\n \"Float32Array; @graphty/layout's resolveNodeVector does this on the CPU path\";\n\n/**\n * An E_INVALID_ARGUMENT with the documented details shape.\n * @param argument - the option name\n * @param value - the offending value\n * @param expected - what was expected\n * @param message - the message\n * @returns the error\n */\nfunction invalid(argument: string, value: unknown, expected: unknown, message: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", message, { argument, value, expected });\n}\n\n/**\n * Asserts every mass is finite and > 0 (spec 7.14: a mass of 0 would divide the distributed action by zero).\n * @param mass - the masses\n * @param source - what the masses came from, for the message\n */\nfunction checkMass(mass: ArrayLike<number>, source: string): void {\n for (let i = 0; i < mass.length; i++) {\n const v = mass[i];\n if (!Number.isFinite(v) || v <= 0) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${source}: mass[${i}] = ${v} is not a finite number > 0`,\n {\n argument: \"nodeMass\",\n value: v,\n index: i,\n expected: \"finite masses > 0\",\n },\n );\n }\n }\n}\n\n/**\n * outDegree()[i] + 1 for every node (spec 7.2 \"Mass\" row; one O(n) loop over the cached view).\n * @param s - the snapshot\n * @returns a fresh F32 of nodeCount masses\n */\nfunction degreePlusOne(s: GraphSnapshot): F32 {\n const n = s.nodeCount;\n const degree = s.outDegree();\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n out[i] = degree[i] + 1;\n }\n return out;\n}\n\n/**\n * The masses of a node column: f32 as is, f64 / u32 / i32 through gpuView (f64 = the cached f32 copy; u32 / i32\n * converted to a fresh F32), u8 through column.data; every other dtype is E_INVALID_ARGUMENT (PLAN DECISION 14).\n * @param s - the snapshot (the column belongs to s.nodes)\n * @param column - the node column\n * @returns nodeCount masses\n */\nfunction massFromColumn(s: GraphSnapshot, column: Column): F32 {\n const { name } = column.meta;\n if (column.meta.components !== 1) {\n throw invalid(\n \"nodeMass\",\n name,\n \"a one-component numeric node column\",\n `node column \"${name}\" has ${column.meta.components} components; a mass column has one`,\n );\n }\n let values: ArrayLike<number>;\n switch (column.dtype) {\n case \"f32\":\n case \"f64\": {\n const view = s.nodes.gpuView(name);\n const out = view instanceof Float32Array ? view : new Float32Array(view);\n checkMass(out, `node column \"${name}\"`);\n return out;\n }\n case \"u32\":\n case \"i32\":\n values = s.nodes.gpuView(name);\n break;\n case \"u8\":\n values = column.data;\n break;\n default:\n throw invalid(\n \"nodeMass\",\n name,\n \"a numeric node column (f32, f64, u32, i32, u8)\",\n `node column \"${name}\" is ${column.dtype}, not numeric`,\n );\n }\n const out = new Float32Array(s.nodeCount);\n for (let i = 0; i < out.length; i++) {\n out[i] = values[i];\n }\n checkMass(out, `node column \"${name}\"`);\n return out;\n}\n\n/**\n * nodeMass resolution by ROLE (spec 7.14): null -> the role-\"mass\" node column when present (any numeric dtype\n * through gpuView, converted to a fresh F32 when not f32), else outDegree()[i] + 1; an F32 of length n -> as is;\n * a column NAME -> nodes.get(name) (numeric); a Record -> E_UNSUPPORTED with the spec's message. Always returns n\n * values, every one finite and > 0.\n * @param s - the snapshot\n * @param spec - the ForceAtlas2Options.nodeMass value\n * @returns nodeCount masses (the caller's array when an F32 was given)\n */\nexport function resolveNodeMass(\n s: GraphSnapshot,\n spec: F32 | string | Readonly<Record<NodeId, number>> | null | undefined,\n): F32 {\n const n = s.nodeCount;\n if (spec === null || spec === undefined) {\n const column = s.nodes.byRole(\"mass\");\n if (column === null) {\n return degreePlusOne(s);\n }\n return massFromColumn(s, column);\n }\n if (spec instanceof Float32Array) {\n if (spec.length !== n) {\n throw invalid(\"nodeMass\", spec.length, `${n} values`, `nodeMass has ${spec.length} values, expected ${n}`);\n }\n checkMass(spec, \"nodeMass\");\n return spec;\n }\n if (typeof spec === \"string\") {\n const column = s.nodes.get(spec);\n if (column === null) {\n throw invalid(\n \"nodeMass\",\n spec,\n \"an existing numeric node column\",\n `nodeMass names node column \"${spec}\", which the snapshot does not hold`,\n );\n }\n return massFromColumn(s, column);\n }\n if (ArrayBuffer.isView(spec)) {\n throw invalid(\n \"nodeMass\",\n \"typed array\",\n \"a Float32Array\",\n \"nodeMass must be a Float32Array, a column name or null\",\n );\n }\n throw new WebGpuGraphError(\n \"E_UNSUPPORTED\",\n `nodeMass as a Record is not supported on the GPU path: ${NODE_MASS_HINT}`,\n {\n option: \"nodeMass\",\n hint: NODE_MASS_HINT,\n },\n );\n}\n\n/** What resolveWeights found. */\nexport interface ResolvedWeights {\n readonly data: F32 | null;\n readonly source: \"arcs\" | \"column\" | \"none\";\n readonly column: Column | null;\n}\n\n/**\n * Weight resolution (spec 7.5, 7.14): true -> { data: s.weights, source: \"arcs\" } (data null when unweighted ->\n * ones); a string -> a name `s.edges` does not hold is E_INVALID_ARGUMENT (spec 7.14's nodeMass rule applied to\n * weight too), else `column = s.edges.get(name)`, then by `column.dtype`: f32 / f64 / u32 / i32 ->\n * expandEdges(s, s.edges.gpuView(name)) (f64 arrives as gpuView's cached f32 copy; u32 / i32 are converted to a\n * fresh F32; `Column.data` is NOT used because it is U8 for u8 / bool and absent for string / list / json), string /\n * list / json -> the gpuView E_GPU_INELIGIBLE pass-through, u8 / bool / dict -> E_INVALID_ARGUMENT (gpuView returns\n * packed words, not per-edge values); source \"column\", `column` kept for the version check; false / null /\n * undefined -> none. A named column must have one component (PLAN DECISION 15); the weight values are never\n * inspected.\n * @param s - the snapshot\n * @param spec - the ForceAtlas2Options.weight value\n * @returns the resolved weights\n */\nexport function resolveWeights(s: GraphSnapshot, spec: boolean | string | null | undefined): ResolvedWeights {\n if (spec === true) {\n return { data: s.weights, source: \"arcs\", column: null };\n }\n if (spec === false || spec === null || spec === undefined) {\n return { data: null, source: \"none\", column: null };\n }\n if (typeof spec !== \"string\") {\n throw invalid(\n \"weight\",\n spec,\n \"true, false, null or an edge column name\",\n \"weight must be true, false, null or an edge column name\",\n );\n }\n const column = s.edges.get(spec);\n if (column === null) {\n throw invalid(\n \"weight\",\n spec,\n \"an existing numeric edge column\",\n `weight names edge column \"${spec}\", which the snapshot does not hold`,\n );\n }\n if (column.meta.components !== 1) {\n throw invalid(\n \"weight\",\n spec,\n \"a one-component numeric edge column\",\n `edge column \"${spec}\" has ${column.meta.components} components; a weight column has one`,\n );\n }\n switch (column.dtype) {\n case \"f32\":\n case \"f64\":\n case \"u32\":\n case \"i32\": {\n const view = s.edges.gpuView(spec);\n const expanded = expandEdges(s, view);\n const data = expanded instanceof Float32Array ? expanded : new Float32Array(expanded);\n return { data, source: \"column\", column };\n }\n case \"string\":\n case \"list\":\n case \"json\":\n // gpuView throws the GraphFormatError E_GPU_INELIGIBLE, which passes through unchanged (D12)\n s.edges.gpuView(spec);\n throw invalid(\"weight\", spec, \"a numeric edge column\", `edge column \"${spec}\" is ${column.dtype}`);\n default:\n throw invalid(\n \"weight\",\n spec,\n \"an f32 / f64 / u32 / i32 edge column\",\n `edge column \"${spec}\" is ${column.dtype}: its gpuView is packed words, not per-edge values`,\n );\n }\n}\n","/**\n * The exact-tier repulsion stage of ForceAtlas2 (spec 7.6, 7.9, 7.10; contract 3.13): K3, the tiled all-pairs\n * repulsion with the gravity term and the swing / traction epilogue, followed by K4, the one-workgroup speed finalize\n * that folds the per-workgroup partials and runs estimateFactor on the device (D15). P1 ships the stage driven over a\n * pass the caller opens (the tests); P3-T2 records it from ForceAtlas2Model.recordIteration without changing these\n * declarations. Both kernels come from the registry (src/kernels.ts) through the pipeline cache, so a distinct\n * override set is a distinct pipeline and the subgroup twin is selected by the device's features (spec 5.1, D16).\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type DispatchPlan, plan1d } from \"../kernel/dispatch.js\";\nimport { type BoundKernel, type Kernel } from \"../kernel/kernel.js\";\nimport { type PipelineCache } from \"../kernel/pipeline-cache.js\";\nimport { type WgslModuleSpec } from \"../kernel/wgsl.js\";\nimport { kernelSpec } from \"../kernels.js\";\nimport { type PlanCaps } from \"../types/context.js\";\nimport { type Binding } from \"../types/memory.js\";\n\n/** The buffers the exact-tier repulsion stage binds (all in layout units; spec 7.3). */\nexport interface RepulsionExactResources {\n readonly pos: Binding;\n readonly state: Binding;\n readonly trace: Binding;\n readonly force: Binding;\n readonly oldForce: Binding;\n readonly fixedMask: Binding;\n readonly partials: Binding;\n readonly params: Binding;\n}\n\n/** The overrides K3 / K4 compile with. */\nexport interface RepulsionExactOverrides {\n readonly SWING_MODE: 0 | 1;\n readonly STRONG_GRAVITY: boolean;\n readonly GRAVITY_CENTER: 0 | 1;\n}\n\n/** K3 (tiled all-pairs repulsion + gravity + the swing / traction epilogue) followed by K4 (the one-workgroup speed finalize) (spec 7.6, 7.10). */\nexport class RepulsionExact {\n /** The overrides both kernels were compiled with (a frozen copy of the argument of create()). */\n readonly overrides: RepulsionExactOverrides;\n\n private readonly caps: PlanCaps;\n private readonly repulsion: Kernel;\n private readonly speedFinalize: Kernel;\n /** Exactly one workgroup of K4 (spec 7.4: \"1 workgroup\"). */\n private readonly finalizePlan: DispatchPlan;\n private boundRepulsion: BoundKernel | null = null;\n private boundSpeedFinalize: BoundKernel | null = null;\n\n /**\n * Holds the two compiled kernels; create() is the only caller.\n * @param repulsion - the K3 kernel\n * @param speedFinalize - the K4 kernel\n * @param caps - the device caps the dispatch planner reads\n * @param overrides - the override set both kernels were compiled with\n */\n private constructor(repulsion: Kernel, speedFinalize: Kernel, caps: PlanCaps, overrides: RepulsionExactOverrides) {\n this.repulsion = repulsion;\n this.speedFinalize = speedFinalize;\n this.caps = caps;\n this.overrides = Object.freeze({\n SWING_MODE: overrides.SWING_MODE,\n STRONG_GRAVITY: overrides.STRONG_GRAVITY,\n GRAVITY_CENTER: overrides.GRAVITY_CENTER,\n });\n this.finalizePlan = plan1d(speedFinalize.workgroupSize, speedFinalize.workgroupSize, caps);\n }\n\n /**\n * Compiles both kernels through the cache (the twin is selected by caps.features).\n * @param pipelines - the context's pipeline cache\n * @param caps - the device caps the dispatch planner reads\n * @param overrides - the SWING_MODE / STRONG_GRAVITY / GRAVITY_CENTER set of this stage\n * @returns the stage, ready for bind()\n */\n static async create(\n pipelines: PipelineCache,\n caps: PlanCaps,\n overrides: RepulsionExactOverrides,\n ): Promise<RepulsionExact> {\n const [repulsionSpec, finalizeSpec] = RepulsionExact.specs(overrides);\n // Sequential on purpose: PipelineCache.get runs createComputePipelineAsync inside a validation scope, and error\n // scopes form one stack per device, so two interleaved compilations would pop each other's scope.\n const repulsion = await pipelines.kernel(repulsionSpec);\n const speedFinalize = await pipelines.kernel(finalizeSpec);\n return new RepulsionExact(repulsion, speedFinalize, caps, overrides);\n }\n\n /**\n * The two specs (for warm() and the compile matrix).\n * @param overrides - the override set of the stage\n * @returns the K3 spec then the K4 spec\n */\n static specs(overrides: RepulsionExactOverrides): readonly [WgslModuleSpec, WgslModuleSpec] {\n return [\n kernelSpec(\"fa2-repulsion-exact\", {\n SWING_MODE: overrides.SWING_MODE,\n STRONG_GRAVITY: overrides.STRONG_GRAVITY,\n GRAVITY_CENTER: overrides.GRAVITY_CENTER,\n }),\n kernelSpec(\"fa2-speed-finalize\", { SWING_MODE: overrides.SWING_MODE }),\n ];\n }\n\n /**\n * Creates the bind groups once per load(): K3 takes pos, state (S), force, oldForce, fixedMask, partials and the\n * params slot; K4 takes partials, state (S), trace (T) and the params slot (the 3.10.1 binding names). The state\n * header and the trace region are two disjoint ranges of one buffer, which Kernel.bind() accepts (no writable alias).\n * @param resources - the buffers of spec 7.3\n */\n bind(resources: RepulsionExactResources): void {\n this.boundRepulsion = this.repulsion.bind({\n pos: resources.pos,\n S: resources.state,\n force: resources.force,\n oldForce: resources.oldForce,\n fixedMask: resources.fixedMask,\n partials: resources.partials,\n P: resources.params,\n });\n this.boundSpeedFinalize = this.speedFinalize.bind({\n partials: resources.partials,\n S: resources.state,\n T: resources.trace,\n P: resources.params,\n });\n }\n\n /**\n * Records K3 (plan1d(n)) then K4 (1 workgroup) with the params slot's dynamic offset.\n * @param pass - the open compute pass of the batch\n * @param n - the node count (rows [0, n) of pos / force)\n * @param paramsOffset - the dynamic offset of this iteration's Fa2Params slot in the uniform ring\n */\n record(pass: GPUComputePassEncoder, n: number, paramsOffset: number): void {\n this.recordRepulsion(pass, n, paramsOffset);\n this.recordSpeedFinalize(pass, paramsOffset);\n }\n\n /**\n * Records K3 only (the inspect() stage split, spec 11.9 item 2).\n * @param pass - the open compute pass\n * @param n - the node count\n * @param paramsOffset - the dynamic offset of the Fa2Params slot\n * @internal\n */\n recordRepulsion(pass: GPUComputePassEncoder, n: number, paramsOffset: number): void {\n const bound = this.bound(this.boundRepulsion, \"recordRepulsion\");\n const plan = plan1d(n, this.repulsion.workgroupSize, this.caps);\n this.repulsion.dispatch(pass, bound, plan, [paramsOffset]);\n }\n\n /**\n * Records K4 only.\n * @param pass - the open compute pass\n * @param paramsOffset - the dynamic offset of the Fa2Params slot\n * @internal\n */\n recordSpeedFinalize(pass: GPUComputePassEncoder, paramsOffset: number): void {\n const bound = this.bound(this.boundSpeedFinalize, \"recordSpeedFinalize\");\n this.speedFinalize.dispatch(pass, bound, this.finalizePlan, [paramsOffset]);\n }\n\n /**\n * The bound kernel of a method, or E_NOT_LOADED when bind() has not run.\n * @param bound - the cached BoundKernel, null before bind()\n * @param method - the caller's name for the message\n * @returns the bound kernel\n */\n private bound(bound: BoundKernel | null, method: string): BoundKernel {\n if (bound === null) {\n throw new WebGpuGraphError(\n \"E_NOT_LOADED\",\n `RepulsionExact.${method}(): bind() has not been called for this stage`,\n {\n state: \"unbound\",\n },\n );\n }\n return bound;\n }\n}\n","/**\n * ForceAtlas2 on the exact repulsion tier (spec 7.1-7.18; contract 3.13): the ForceModel that ForceSimulation\n * drives -- the K1 K2 K3 K4 K5 sequence per iteration and toScene per batch (spec 7.4), the override set of the option\n * record (spec 7.2 with the 4.6 NetworkX corrections), the per-iteration Fa2Params values, the controller resets of\n * spec 7.17 and the stats decoder -- plus the two option resolvers and `createForceAtlas2`. Positions are vec4f\n * (xyz + mass) in layout units on the device (D23, 7.18); the speed controller runs on the device (D15); no\n * displacement clamp (D25); K2 runs the thread-per-row tier over [0, n) with USE_PERM false (P3, spec 7.5).\n *\n * Model decisions this file fixes (the plan of P3-T2 lists the reasons): recordIteration with no `upTo` records every\n * stage including toScene; the K1-K5 dispatches of every iteration of one batch share ONE compute pass (opened by the\n * batch's first recordIteration and remembered by batch id) and toScene runs in a second pass that ends it (contract\n * 4.4); the fill kernel takes its FillParams from a model-owned 256-byte uniform buffer (\"fillParams\"); the first\n * iteration after every load() zeroes oldForce with a fill (paper mode); `repulsion: \"grid\"` is E_UNSUPPORTED at\n * load() for any n and `\"auto\"` above exactMaxNodes.\n */\n\nimport { type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport {\n FA2_DEFAULTS,\n LAYOUT_TUNING_DEFAULTS,\n MAX_ITERATIONS_PER_STEP,\n TRACE_RECORD_BYTES,\n UNIFORM_SLOT_BYTES,\n} from \"../constants.js\";\nimport { type GpuContext } from \"../context.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type CommandBatch } from \"../kernel/batch.js\";\nimport { type DispatchPlan, plan1d } from \"../kernel/dispatch.js\";\nimport { type BoundKernel, type Kernel } from \"../kernel/kernel.js\";\nimport { type UniformBlock, type UniformValues } from \"../kernel/struct-block.js\";\nimport { type WgslModuleSpec } from \"../kernel/wgsl.js\";\nimport { FA2_PARAMS, FA2_STATE, FA2_TRACE, FILL_PARAMS, graphBindings, kernelSpec } from \"../kernels.js\";\nimport {\n type ForceAtlas2Stats,\n type ForceAtlas2TraceRecord,\n type GpuLayoutSimulation,\n type GpuLayoutTuning,\n type ResolvedLayoutTuning,\n} from \"../types/layout.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type ForceAtlas2Options, type ResolvedForceAtlas2Options } from \"../types/options.js\";\nimport {\n type BufferSpec,\n type ForceModel,\n ForceSimulation,\n type ModelInputs,\n type ModelResources,\n type StateWriter,\n} from \"./force-simulation.js\";\nimport { resolveNodeMass, resolveWeights } from \"./inputs.js\";\nimport { RepulsionExact, type RepulsionExactOverrides } from \"./repulsion-exact.js\";\n\n// ============================================================ constants and small helpers\n\n/** An override record as the kernel layer takes it. */\ntype Overrides = Readonly<Record<string, number | boolean>>;\n\n/** The stage names of one iteration in dispatch order plus the per-batch toScene (spec 7.4; contract 3.13). */\nconst FA2_STAGES = [\"K1\", \"K2\", \"K3\", \"K4\", \"K5\", \"toScene\"] as const;\n\n/** Bytes of the stride-3 f32 force arrays per node. */\nconst FORCE_BYTES_PER_NODE = 12;\n\n/** The name of the model-owned FillParams buffer (a BufferSpec, reached through ModelResources.buffer). */\nconst FILL_PARAMS_BUFFER = \"fillParams\";\n\n/** The one-workgroup dispatch of K1 (spec 7.4). */\nconst ONE_WORKGROUP: DispatchPlan = { x: 1, y: 1, z: 1, items: 1, stride: null };\n\n/** Every override K2 accepts, with its default (contract 3.10.1 plus the two standard graph overrides). */\nconst K2_DEFAULTS: Overrides = { LINLOG: false, DISTRIBUTED: false, TIER: 0, USE_PERM: false, HAS_WEIGHTS: false };\n\n/** Every override K5 accepts, with its default. */\nconst K5_DEFAULTS: Overrides = { SWING_MODE: 0 };\n\n/** 2^32, the modulus of the u32 seed word (computed with `%`, never a bitwise operator). */\nconst U32_MODULUS = 4294967296;\n\n/** The resolved record with no option given: FA2_DEFAULTS plus the null / origin defaults of spec 7.14. */\nconst DEFAULT_RESOLVED: ResolvedForceAtlas2Options = Object.freeze<ResolvedForceAtlas2Options>({\n ...FA2_DEFAULTS,\n nodeMass: null,\n nodeSize: null,\n weight: null,\n center: [0, 0, 0],\n seed: null,\n});\n\n/**\n * A short, safe rendering of an argument value for error messages (never String() on an object).\n * @param value - the value\n * @returns the rendering\n */\nfunction describeValue(value: unknown): string {\n if (value === null) {\n return \"null\";\n }\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"string\") {\n return String(value);\n }\n if (typeof value === \"undefined\") {\n return \"undefined\";\n }\n if (typeof value === \"object\" && \"length\" in value && typeof value.length === \"number\") {\n return `[${value.length} values]`;\n }\n return typeof value;\n}\n\n/**\n * The E_INVALID_ARGUMENT error of an option check (contract 3.1: { argument, value, expected }).\n * @param argument - the option name\n * @param value - the value given\n * @param expected - what was expected\n * @returns the error (not thrown here)\n */\nfunction invalid(argument: string, value: unknown, expected: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${argument} must be ${expected}; got ${describeValue(value)}`, {\n argument,\n value,\n expected,\n });\n}\n\n/**\n * A numeric option: the given value when defined, else the fallback; validated by `check` (the value is checked as\n * `unknown` so a JS caller's string or object is E_INVALID_ARGUMENT too).\n * @param name - the option name\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @param check - the range predicate over a finite number\n * @param expected - the range in words (the error message)\n * @returns the value\n */\nfunction pickNumber(\n name: string,\n given: number | undefined,\n fallback: number,\n check: (value: number) => boolean,\n expected: string,\n): number {\n const value: unknown = given === undefined ? fallback : given;\n if (typeof value !== \"number\" || !Number.isFinite(value) || !check(value)) {\n throw invalid(name, value, expected);\n }\n return value;\n}\n\n/**\n * A boolean option: the given value when defined, else the fallback; a non-boolean is E_INVALID_ARGUMENT.\n * @param name - the option name\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @returns the value\n */\nfunction pickBoolean(name: string, given: boolean | undefined, fallback: boolean): boolean {\n const value: unknown = given === undefined ? fallback : given;\n if (typeof value !== \"boolean\") {\n throw invalid(name, value, \"a boolean\");\n }\n return value;\n}\n\n/**\n * The layout dimension: 2 or 3.\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @returns 2 or 3\n */\nfunction pickDim(given: 2 | 3 | undefined, fallback: 2 | 3): 2 | 3 {\n const value: unknown = given === undefined ? fallback : given;\n if (value !== 2 && value !== 3) {\n throw invalid(\"dim\", value, \"2 or 3\");\n }\n return value;\n}\n\n/**\n * The scene-unit center: an array-like of 2 (z = 0) or 3 finite numbers.\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @returns the three components\n */\nfunction pickCenter(\n given: ArrayLike<number> | undefined,\n fallback: readonly [number, number, number],\n): readonly [number, number, number] {\n if (given === undefined) {\n return fallback;\n }\n const expected = \"an array of 2 or 3 finite numbers\";\n const value: unknown = given;\n if (typeof value !== \"object\" || value === null || !(\"length\" in value)) {\n throw invalid(\"center\", given, expected);\n }\n const { length } = value;\n if (length !== 2 && length !== 3) {\n throw invalid(\"center\", given, expected);\n }\n const x: unknown = given[0];\n const y: unknown = given[1];\n const z: unknown = length === 3 ? given[2] : 0;\n if (\n typeof x !== \"number\" ||\n typeof y !== \"number\" ||\n typeof z !== \"number\" ||\n !Number.isFinite(x) ||\n !Number.isFinite(y) ||\n !Number.isFinite(z)\n ) {\n throw invalid(\"center\", given, expected);\n }\n return [x, y, z];\n}\n\n/**\n * The seed: a finite number, or null (unseeded; 0 keeps the port's \"0 = unseeded\" quirk through the Lcg).\n * @param given - the value given (undefined = absent)\n * @param fallback - the previous record's value or the default\n * @returns the seed or null\n */\nfunction pickSeed(given: number | null | undefined, fallback: number | null): number | null {\n if (given === undefined) {\n return fallback;\n }\n const value: unknown = given;\n if (value !== null && (typeof value !== \"number\" || !Number.isFinite(value))) {\n throw invalid(\"seed\", given, \"a finite number or null\");\n }\n return value;\n}\n\n/**\n * Integer >= 1.\n * @param value - a finite number\n * @returns whether it is a positive integer\n */\nfunction isPositiveInteger(value: number): boolean {\n return Number.isInteger(value) && value >= 1;\n}\n\n/**\n * The u32 word written into Fa2Params.seed: 0 for null, else floor(|seed|) mod 2^32.\n * @param seed - the resolved seed\n * @returns the u32 value\n */\nfunction seedWord(seed: number | null): number {\n if (seed === null) {\n return 0;\n }\n return Math.floor(Math.abs(seed)) % U32_MODULUS;\n}\n\n/**\n * A scalar field of a block's read() result.\n * @param values - the values read\n * @param name - the field name\n * @returns the number\n */\nfunction scalar(values: UniformValues, name: string): number {\n const value = values[name];\n if (typeof value !== \"number\") {\n throw invalid(name, value, \"a scalar field\");\n }\n return value;\n}\n\n/**\n * A vector field of a block's read() result.\n * @param values - the values read\n * @param name - the field name\n * @returns the components\n */\nfunction vector(values: UniformValues, name: string): readonly number[] {\n const value = values[name];\n if (typeof value === \"number\") {\n throw invalid(name, value, \"a vector field\");\n }\n return value;\n}\n\n/**\n * The override record a kernel gets: its defaults overlaid with the values present in the merged set (contract 3.9:\n * a name a spec does not declare is rejected at compose time, so nothing else is passed through).\n * @param merged - the merged override set of the model (plus USE_PERM / HAS_WEIGHTS from the simulation)\n * @param defaults - the kernel's accepted names with their defaults\n * @returns the kernel's override record, every accepted name explicit\n */\nfunction subset(merged: Overrides, defaults: Overrides): Overrides {\n const out: Record<string, number | boolean> = {};\n for (const name of Object.keys(defaults)) {\n out[name] = name in merged ? merged[name] : defaults[name];\n }\n return out;\n}\n\n/**\n * The K3 / K4 override values of a merged set (typed for RepulsionExact).\n * @param merged - the merged override set\n * @returns the three K3 / K4 overrides\n */\nfunction repulsionOverrides(merged: Overrides): RepulsionExactOverrides {\n return {\n SWING_MODE: merged.SWING_MODE === 1 ? 1 : 0,\n STRONG_GRAVITY: merged.STRONG_GRAVITY === true,\n GRAVITY_CENTER: merged.GRAVITY_CENTER === 1 ? 1 : 0,\n };\n}\n\n// ============================================================ the resolvers\n\n/**\n * Applies FA2_DEFAULTS to the option record; validates ranges (spec 7.14; contract 3.13). With `previous` the record\n * is a PATCH over it (an absent or explicitly undefined field keeps the previous value) and `maxInFlight` may not\n * change (the uniform ring is sized by it at construction). `nodeSize` is E_UNSUPPORTED { option: \"nodeSize\" } (the\n * adjustSizes correction is deferred); `dissuadeHubs` is kept and ignored, exactly like the CPU.\n * @param options - the caller's options (or a setParams patch)\n * @param previous - the current resolved record when resolving a patch\n * @returns the frozen resolved record\n */\nexport function resolveForceAtlas2Options(\n options: ForceAtlas2Options | undefined,\n previous?: ResolvedForceAtlas2Options,\n): ResolvedForceAtlas2Options {\n const o: ForceAtlas2Options = options ?? {};\n const base = previous ?? DEFAULT_RESOLVED;\n if (previous !== undefined && o.maxInFlight !== undefined && o.maxInFlight !== previous.maxInFlight) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `maxInFlight cannot change after creation (the uniform ring is sized by it): got ${describeValue(o.maxInFlight)}, current ${previous.maxInFlight}`,\n { argument: \"maxInFlight\", value: o.maxInFlight, expected: previous.maxInFlight },\n );\n }\n const nodeSize = o.nodeSize === undefined ? base.nodeSize : o.nodeSize;\n if (nodeSize !== null) {\n throw new WebGpuGraphError(\n \"E_UNSUPPORTED\",\n \"nodeSize (the adjustSizes correction) is not supported by the GPU ForceAtlas2 yet (spec 7.14)\",\n { option: \"nodeSize\", hint: \"pass nodeSize: null; the size-aware repulsion is deferred (spec 7.2, Q-25)\" },\n );\n }\n const resolved: ResolvedForceAtlas2Options = {\n maxIter: pickNumber(\"maxIter\", o.maxIter, base.maxIter, isPositiveInteger, \"an integer >= 1\"),\n jitterTolerance: pickNumber(\"jitterTolerance\", o.jitterTolerance, base.jitterTolerance, (v) => v > 0, \"> 0\"),\n scalingRatio: pickNumber(\"scalingRatio\", o.scalingRatio, base.scalingRatio, (v) => v > 0, \"> 0\"),\n gravity: pickNumber(\"gravity\", o.gravity, base.gravity, (v) => v >= 0, \">= 0\"),\n strongGravity: pickBoolean(\"strongGravity\", o.strongGravity, base.strongGravity),\n distributedAction: pickBoolean(\"distributedAction\", o.distributedAction, base.distributedAction),\n linlog: pickBoolean(\"linlog\", o.linlog, base.linlog),\n nodeMass: o.nodeMass === undefined ? base.nodeMass : o.nodeMass,\n nodeSize,\n weight: o.weight === undefined ? base.weight : o.weight,\n dissuadeHubs: pickBoolean(\"dissuadeHubs\", o.dissuadeHubs, base.dissuadeHubs),\n dim: pickDim(o.dim, base.dim),\n scale: pickNumber(\"scale\", o.scale, base.scale, (v) => v > 0, \"> 0\"),\n center: pickCenter(o.center, base.center),\n seed: pickSeed(o.seed, base.seed),\n settleThreshold: pickNumber(\"settleThreshold\", o.settleThreshold, base.settleThreshold, (v) => v >= 0, \">= 0\"),\n settleWindow: pickNumber(\n \"settleWindow\",\n o.settleWindow,\n base.settleWindow,\n isPositiveInteger,\n \"an integer >= 1\",\n ),\n iterationsPerStep: pickNumber(\n \"iterationsPerStep\",\n o.iterationsPerStep,\n base.iterationsPerStep,\n (v) => isPositiveInteger(v) && v <= MAX_ITERATIONS_PER_STEP,\n `an integer in [1, ${MAX_ITERATIONS_PER_STEP}]`,\n ),\n maxInFlight: pickNumber(\"maxInFlight\", o.maxInFlight, base.maxInFlight, isPositiveInteger, \"an integer >= 1\"),\n };\n return Object.freeze(resolved);\n}\n\n/**\n * Applies LAYOUT_TUNING_DEFAULTS (spec 7.14); the grid knobs are validated and stored but only `repulsion`,\n * `exactMaxNodes`, `deterministic` and `compat` have an effect in P3 (contract 3.3).\n * @param tuning - the GPU-only knobs given (any object carrying them, e.g. the createForceAtlas2 options)\n * @returns the frozen resolved tuning\n */\nexport function resolveLayoutTuning(tuning: GpuLayoutTuning | undefined): ResolvedLayoutTuning {\n const t: GpuLayoutTuning = tuning ?? {};\n const repulsion: unknown = t.repulsion ?? LAYOUT_TUNING_DEFAULTS.repulsion;\n if (repulsion !== \"exact\" && repulsion !== \"grid\" && repulsion !== \"auto\") {\n throw invalid(\"repulsion\", repulsion, '\"exact\", \"grid\" or \"auto\"');\n }\n const compat: unknown = t.compat ?? LAYOUT_TUNING_DEFAULTS.compat;\n if (compat !== \"paper\" && compat !== \"networkx\") {\n throw invalid(\"compat\", compat, '\"paper\" or \"networkx\"');\n }\n const resolved: ResolvedLayoutTuning = {\n repulsion,\n exactMaxNodes: pickNumber(\n \"exactMaxNodes\",\n t.exactMaxNodes,\n LAYOUT_TUNING_DEFAULTS.exactMaxNodes,\n isPositiveInteger,\n \"an integer >= 1\",\n ),\n nearMax: pickNumber(\"nearMax\", t.nearMax, LAYOUT_TUNING_DEFAULTS.nearMax, isPositiveInteger, \"an integer >= 1\"),\n deterministic: pickBoolean(\"deterministic\", t.deterministic, LAYOUT_TUNING_DEFAULTS.deterministic),\n gridMax2D: pickNumber(\n \"gridMax2D\",\n t.gridMax2D,\n LAYOUT_TUNING_DEFAULTS.gridMax2D,\n isPositiveInteger,\n \"an integer >= 1\",\n ),\n gridMax3D: pickNumber(\n \"gridMax3D\",\n t.gridMax3D,\n LAYOUT_TUNING_DEFAULTS.gridMax3D,\n isPositiveInteger,\n \"an integer >= 1\",\n ),\n extentFactor: pickNumber(\n \"extentFactor\",\n t.extentFactor,\n LAYOUT_TUNING_DEFAULTS.extentFactor,\n (v) => v > 0,\n \"> 0\",\n ),\n compat,\n };\n return Object.freeze(resolved);\n}\n\n// ============================================================ the model\n\n/** Everything bind() produced for one load(): the kernels, their bind groups and the dispatch plans of this n. */\ninterface BoundModel {\n readonly n: number;\n /** plan1d(n): K2, K5, toScene (every kernel compiles with the same device-derived WG). */\n readonly plan: DispatchPlan;\n /** plan1d(3n): the fills of force / oldForce (3 words per node). */\n readonly fillPlan: DispatchPlan;\n readonly k1: Kernel;\n readonly k1Bound: BoundKernel;\n readonly k2: Kernel;\n /** null when arcCount === 0 (K2 is not recorded; the fill below zeroes force instead, spec 7.5). */\n readonly k2Bound: BoundKernel | null;\n readonly repulsion: RepulsionExact;\n readonly k5: Kernel;\n readonly k5Bound: BoundKernel;\n readonly toScene: Kernel;\n readonly toSceneBound: BoundKernel;\n readonly fill: Kernel;\n /** The fill of `force` (arcCount === 0 only). */\n readonly fillForceBound: BoundKernel | null;\n /** The fill of `oldForce` on the first iteration after load() (paper mode only). */\n readonly fillOldBound: BoundKernel | null;\n}\n\n/** The ForceAtlas2 model (spec 7.4: K1 K2 K3 K4 K5 per iteration; toScene once per batch). Stages: [\"K1\", \"K2\", \"K3\", \"K4\", \"K5\", \"toScene\"]. */\nexport class ForceAtlas2Model implements ForceModel<ForceAtlas2Options, ForceAtlas2Stats> {\n /** The model kind of spec 7.19. */\n readonly kind = \"forceatlas2\";\n /** The stage names in dispatch order (the `upTo` vocabulary of recordIteration and debugRunStages). */\n readonly stages: readonly [\"K1\", \"K2\", \"K3\", \"K4\", \"K5\", \"toScene\"] = FA2_STAGES;\n /** Fa2Params: the per-iteration uniform block (the simulation writes the shared fields into it). */\n readonly params: UniformBlock = FA2_PARAMS;\n /** Fa2State: the state header block (the simulation allocates and initialises it through this layout). */\n readonly state: UniformBlock = FA2_STATE;\n /** Fa2Trace: one record per iteration of a batch. */\n readonly trace: UniformBlock = FA2_TRACE;\n /** The resolved GPU-only tuning this model was created with. */\n readonly tuning: ResolvedLayoutTuning;\n\n /**\n * The option record the model holds: the constructor's record, replaced by onSetParams() ONLY. The query hooks\n * (inputs, overrides, paramsFor) never assign it: the simulation calls overrides(next) BEFORE onSetParams(patch)\n * (3.13 setParams: the recompile decision precedes the controller reset), so a hook that tracked the record would\n * hide every law change from onSetParams (PLAN DECISION 12).\n */\n private current: ResolvedForceAtlas2Options;\n /** The resources of the last bind(), or null before the first. */\n private resources: ModelResources | null = null;\n /** The kernels and bind groups of the last bind(), or null before it (and for n === 0). */\n private bound: BoundModel | null = null;\n /** Armed by onLoad(): the next recordIteration zeroes oldForce first (paper mode). */\n private resetOldForce = false;\n /**\n * The K1-K5 compute pass of the batch being recorded, keyed by CommandBatch.id (unique per batch): every\n * recordIteration of one batch dispatches into it (ONE pass per batch, contract 4.4); null between batches and\n * after the toScene pass ended it (PLAN DECISION 2).\n */\n private openPass: { readonly id: number; readonly pass: GPUComputePassEncoder } | null = null;\n\n /**\n * Creates the model for one simulation.\n * @param tuning - the resolved GPU-only tuning (compat selects SWING_MODE / GRAVITY_CENTER; repulsion and\n * exactMaxNodes the tier rule)\n * @param resolved - the resolved option record at creation\n */\n constructor(tuning: ResolvedLayoutTuning, resolved: ResolvedForceAtlas2Options) {\n this.tuning = tuning;\n this.current = resolved;\n }\n\n /**\n * The SWING_MODE of this model: 1 in networkx mode (accumulated, position-mixed sums; m|F| local swing), else 0.\n * @returns 0 or 1\n */\n private get swingMode(): 0 | 1 {\n return this.tuning.compat === \"networkx\" ? 1 : 0;\n }\n\n /**\n * force 12n and oldForce 12n (zeroed) in BOTH swing modes (3.10.1: a writable slot is never aliased; mode 1 leaves\n * oldForce unread and unwritten), plus the 256-byte FillParams uniform buffer the fill dispatches read. n = 0\n * reports one node's worth of bytes so no zero-length buffer is ever created (spec 3.6).\n * @param n - the node count\n * @param _dim - the layout dimension (the force arrays are stride 3 in both)\n * @returns the three model-owned buffer specs\n */\n buffers(n: number, _dim: 2 | 3): readonly BufferSpec[] {\n const bytes = Math.max(1, n) * FORCE_BYTES_PER_NODE;\n const usage = BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST;\n return [\n { name: \"force\", byteLength: bytes, usage, zero: true },\n { name: \"oldForce\", byteLength: bytes, usage, zero: true },\n {\n name: FILL_PARAMS_BUFFER,\n byteLength: UNIFORM_SLOT_BYTES,\n usage: BufferUsage.UNIFORM | BufferUsage.COPY_DST,\n zero: false,\n },\n ];\n }\n\n /**\n * { mass: resolveNodeMass(s, resolved.nodeMass), weights: resolveWeights(s, resolved.weight) } (3.13 inputs.ts),\n * after the tier rule of spec 7.8 / lead f: `repulsion: \"grid\"` is E_UNSUPPORTED { feature: \"repulsion.grid\" }\n * for any n and `\"auto\"` when n > exactMaxNodes (the grid tier lands in P4); `\"exact\"` always runs.\n * @param s - the snapshot being loaded\n * @param options - the simulation's current option record\n * @returns the per-load inputs\n */\n inputs(s: GraphSnapshot, options: ForceAtlas2Options): ModelInputs {\n const resolved = resolveForceAtlas2Options(options, this.current);\n const { repulsion, exactMaxNodes } = this.tuning;\n const n = s.nodeCount;\n if (repulsion === \"grid\" || (repulsion === \"auto\" && n > exactMaxNodes)) {\n throw new WebGpuGraphError(\n \"E_UNSUPPORTED\",\n repulsion === \"grid\"\n ? 'repulsion: \"grid\" is not available yet (the grid tier lands in P4)'\n : `the graph has ${n} nodes, above exactMaxNodes ${exactMaxNodes}, and the grid tier lands in P4`,\n {\n feature: \"repulsion.grid\",\n hint: 'pass repulsion: \"exact\" (or raise exactMaxNodes) to run the exact tier at this size',\n },\n );\n }\n return { mass: resolveNodeMass(s, resolved.nodeMass), weights: resolveWeights(s, resolved.weight) };\n }\n\n /**\n * { LINLOG, DISTRIBUTED, TIER: 0, SWING_MODE: compat === \"networkx\" ? 1 : 0, STRONG_GRAVITY, GRAVITY_CENTER:\n * compat === \"networkx\" ? 1 : 0 }; USE_PERM / HAS_WEIGHTS are merged in by the simulation from ModelResources\n * (3.10, never from core.hasWeights). A pure query: the simulation calls it with the current AND the next record\n * inside setParams() to decide the recompile, so it never touches the model's record (PLAN DECISION 12).\n * @param options - an option record (the simulation's current one, or the next one of a setParams patch)\n * @returns the model's own override set\n */\n overrides(options: ForceAtlas2Options): Overrides {\n const resolved = resolveForceAtlas2Options(options, this.current);\n const mode = this.swingMode;\n return {\n LINLOG: resolved.linlog,\n DISTRIBUTED: resolved.distributedAction,\n TIER: 0,\n SWING_MODE: mode,\n STRONG_GRAVITY: resolved.strongGravity,\n GRAVITY_CENTER: mode,\n };\n }\n\n /**\n * The seven module specs of an override set in dispatch order -- K1, K2, K3, K4, K5, toScene, fill -- each with\n * only the override names its entry declares (K2 also USE_PERM / HAS_WEIGHTS), for warm() and the compile matrix.\n * @param overrides - the merged override set (the model's plus USE_PERM / HAS_WEIGHTS)\n * @param _subgroups - accepted for the ForceModel interface and unused: every reducing FA2 body carries\n * needs: [\"subgroups\"] in its registry entry and the composer picks the twin from caps.features (contract 4.3)\n * @returns the specs\n */\n specs(overrides: Overrides, _subgroups: boolean): readonly WgslModuleSpec[] {\n const [repulsionSpec, speedSpec] = RepulsionExact.specs(repulsionOverrides(overrides));\n return [\n kernelSpec(\"fa2-stats-finalize\"),\n kernelSpec(\"fa2-attraction\", subset(overrides, K2_DEFAULTS)),\n repulsionSpec,\n speedSpec,\n kernelSpec(\"fa2-integrate\", subset(overrides, K5_DEFAULTS)),\n kernelSpec(\"fa2-to-scene\"),\n kernelSpec(\"fill\"),\n ];\n }\n\n /**\n * Compiles (through the cache) and binds every kernel against the buffers of this load(): K1, K2 (or the fill of\n * force when arcCount === 0), K3 + K4 through RepulsionExact, K5, toScene, and the fill of oldForce; writes the\n * FillParams { count: 3n, value: 0, mode: 0 } into the model's uniform buffer. With n === 0 nothing is bound.\n * @param resources - the graph, the shared and model buffers, the ring and the cache\n * @param overrides - the merged override set\n */\n async bind(resources: ModelResources, overrides: Overrides): Promise<void> {\n this.dropBound();\n this.resources = resources;\n const { n, pipelines, caps, core, perm, ring, device } = resources;\n if (n === 0) {\n return;\n }\n const [k1, k2, k5, toScene, fill] = await Promise.all([\n pipelines.kernel(kernelSpec(\"fa2-stats-finalize\")),\n pipelines.kernel(kernelSpec(\"fa2-attraction\", subset(overrides, K2_DEFAULTS))),\n pipelines.kernel(kernelSpec(\"fa2-integrate\", subset(overrides, K5_DEFAULTS))),\n pipelines.kernel(kernelSpec(\"fa2-to-scene\")),\n pipelines.kernel(kernelSpec(\"fill\")),\n ]);\n const repulsion = await RepulsionExact.create(pipelines, caps, repulsionOverrides(overrides));\n if (this.resources !== resources) {\n // a newer bind() superseded this one while the pipelines compiled; its own bind groups stand\n return;\n }\n const pos = resources.buffer(\"positions\");\n const scene = resources.buffer(\"scenePositions\");\n const fixed = resources.buffer(\"fixed\");\n const partials = resources.buffer(\"partials\");\n const state = resources.buffer(\"state\");\n const trace = resources.buffer(\"trace\");\n const force = resources.buffer(\"force\");\n const oldForce = resources.buffer(\"oldForce\");\n const fillParamsBuffer = resources.buffer(FILL_PARAMS_BUFFER);\n const params = ring.binding(FA2_PARAMS);\n const fillParams: Binding = {\n buffer: fillParamsBuffer.buffer,\n offset: fillParamsBuffer.offset,\n size: FILL_PARAMS.byteLength,\n window: null,\n };\n const fillBytes = new ArrayBuffer(FILL_PARAMS.byteLength);\n FILL_PARAMS.write(new DataView(fillBytes), { count: 3 * n, value: 0, mode: 0 });\n device.queue.writeBuffer(fillParamsBuffer.buffer, fillParamsBuffer.offset, fillBytes);\n const hasArcs = core.colIdx !== null;\n repulsion.bind({ pos, state, trace, force, oldForce, fixedMask: fixed, partials, params });\n const wg = k1.workgroupSize;\n this.bound = {\n n,\n plan: plan1d(n, wg, caps),\n fillPlan: plan1d(3 * n, wg, caps),\n k1,\n k1Bound: k1.bind({ partials, S: state, T: trace, P: params }),\n k2,\n k2Bound: hasArcs\n ? k2.bind({ ...graphBindings(core, perm, resources.weights), pos, force, P: params })\n : null,\n repulsion,\n k5,\n k5Bound: k5.bind({ force, oldForce, fixedMask: fixed, S: state, pos, partials, P: params }),\n toScene,\n toSceneBound: toScene.bind({ pos, scene, P: params }),\n fill,\n fillForceBound: hasArcs ? null : fill.bind({ dst: force, P: fillParams }),\n fillOldBound: this.swingMode === 0 ? fill.bind({ dst: oldForce, P: fillParams }) : null,\n };\n }\n\n /**\n * The Fa2Params values of one iteration (the simulation overwrites the shared fields n, dim, flags,\n * iterationIndex, seed, scale, center and settleThreshold with the same values plus the flags).\n * @param iteration - the trace slot of the iteration inside its batch\n * @param options - the simulation's current option record\n * @returns the uniform values\n */\n paramsFor(iteration: number, options: ForceAtlas2Options): UniformValues {\n const { n } = this.requireResources();\n const resolved = resolveForceAtlas2Options(options, this.current);\n const { nearMax, extentFactor } = this.tuning;\n return {\n n,\n dim: resolved.dim,\n flags: 0,\n tierStart: 0,\n tierEnd: n,\n iterationIndex: iteration,\n seed: seedWord(resolved.seed),\n nearMax,\n scalingRatio: resolved.scalingRatio,\n gravity: resolved.gravity,\n jitterTolerance: resolved.jitterTolerance,\n scale: resolved.scale,\n center: [resolved.center[0], resolved.center[1], resolved.center[2], 0],\n settleThreshold: resolved.settleThreshold,\n extentFactor,\n gridMax: 0,\n levels: 0,\n pad: [0, 0, 0, 0],\n };\n }\n\n /**\n * Records one iteration into the batch: K1, K2 (or the fill of force when arcCount === 0), K3, K4, K5 in the\n * batch's ONE K1-K5 compute pass (opened by the first call of a batch and reused by every later call with the\n * same batch.id, PLAN DECISION 2), then toScene in a second pass that ends it, stopping after stage `upTo` when\n * given (spec 7.4; debugRunStages / inspect, spec 11.9 item 2). The simulation passes \"K5\" for iterations\n * 0..k-2 and undefined for the last, so toScene runs once per batch. The first call after load() zeroes\n * oldForce before K1 (paper mode). With n === 0 nothing is recorded (PLAN DECISION 9); a call before bind()\n * completed is E_NOT_LOADED (never a silent no-op).\n * @param batch - the batch being recorded\n * @param slot - the UniformRing slot holding this iteration's Fa2Params\n * @param tier - \"exact\" (the grid tier is E_UNSUPPORTED until P4; the simulation never passes \"grid\")\n * @param upTo - a stage name to stop after; undefined records every stage including toScene\n */\n recordIteration(batch: CommandBatch, slot: number, tier: \"exact\" | \"grid\", upTo?: string): void {\n if (tier === \"grid\") {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"the grid repulsion tier lands in P4\", {\n feature: \"repulsion.grid\",\n hint: 'pass repulsion: \"exact\"',\n });\n }\n const resources = this.requireResources();\n const stop = upTo === undefined ? FA2_STAGES.length - 1 : this.stageIndex(upTo);\n const { bound } = this;\n if (bound === null) {\n if (resources.n === 0) {\n return;\n }\n throw new WebGpuGraphError(\n \"E_NOT_LOADED\",\n \"the ForceAtlas2 model is not bound (bind() has not completed)\",\n {\n state: \"loaded\",\n },\n );\n }\n const offset = resources.ring.offsetOf(slot);\n const pass = this.openPass !== null && this.openPass.id === batch.id ? this.openPass.pass : batch.pass(\"fa2\");\n this.openPass = { id: batch.id, pass };\n if (this.resetOldForce) {\n this.resetOldForce = false;\n if (bound.fillOldBound !== null) {\n bound.fill.dispatch(pass, bound.fillOldBound, bound.fillPlan, [0]);\n }\n }\n bound.k1.dispatch(pass, bound.k1Bound, ONE_WORKGROUP, [offset]);\n if (stop < 1) {\n return;\n }\n if (bound.k2Bound !== null) {\n bound.k2.dispatch(pass, bound.k2Bound, bound.plan, [offset]);\n } else if (bound.fillForceBound !== null) {\n bound.fill.dispatch(pass, bound.fillForceBound, bound.fillPlan, [0]);\n }\n if (stop < 2) {\n return;\n }\n bound.repulsion.recordRepulsion(pass, bound.n, offset);\n if (stop < 3) {\n return;\n }\n bound.repulsion.recordSpeedFinalize(pass, offset);\n if (stop < 4) {\n return;\n }\n bound.k5.dispatch(pass, bound.k5Bound, bound.plan, [offset]);\n if (stop < 5) {\n return;\n }\n // the second pass ends the K1-K5 pass; the batch is complete after toScene, so nothing reuses it\n this.openPass = null;\n const scenePass = batch.pass(\"fa2-to-scene\");\n bound.toScene.dispatch(scenePass, bound.toSceneBound, bound.plan, [offset]);\n }\n\n /**\n * speed = 1, speedEfficiency = 1, swing = 1, traction = 1 (mode 1 accumulates from 1; mode 0 overwrites them each\n * iteration, the initial value is irrelevant); arms the oldForce reset of the next recordIteration.\n * @param state - the state writer of the simulation\n */\n onLoad(state: StateWriter): void {\n state.set(\"speed\", 1);\n state.set(\"speedEfficiency\", 1);\n state.set(\"swing\", 1);\n state.set(\"traction\", 1);\n this.resetOldForce = true;\n }\n\n /**\n * Mode 0: nothing (D8). Mode 1 (networkx): swing = traction = 1 (spec 7.2 \"load() and reheat() reset them to 1\").\n * @param state - the state writer of the simulation\n */\n onReheat(state: StateWriter): void {\n if (this.swingMode === 1) {\n state.set(\"swing\", 1);\n state.set(\"traction\", 1);\n }\n }\n\n /**\n * Resets speed / speedEfficiency to 1 only when linlog, strongGravity or distributedAction changed (spec 7.17);\n * a numeric tweak leaves the controller alone. The patch is validated by the same resolver the simulation uses\n * and applied over the record of the constructor / the previous onSetParams -- the only place `current` moves\n * (PLAN DECISION 12), so the comparison sees the record from BEFORE this setParams even though the simulation\n * already queried overrides(next).\n * @param patch - the setParams patch\n * @param state - the state writer of the simulation\n */\n onSetParams(patch: Partial<ForceAtlas2Options>, state: StateWriter): void {\n const next = resolveForceAtlas2Options(patch, this.current);\n const lawChanged =\n next.linlog !== this.current.linlog ||\n next.strongGravity !== this.current.strongGravity ||\n next.distributedAction !== this.current.distributedAction;\n this.current = next;\n if (lawChanged) {\n state.set(\"speed\", 1);\n state.set(\"speedEfficiency\", 1);\n }\n }\n\n /**\n * Decodes the state header and the k trace records of a completed batch (k = trace.byteLength / 32) into\n * ForceAtlas2Stats: the exact tier with null grid fields; msPerIteration null (the simulation owns the clock).\n * @param state - a DataView over the 256-byte state header\n * @param trace - a DataView over the k Fa2Trace records of the batch\n * @returns the stats\n */\n readStats(state: DataView, trace: DataView): ForceAtlas2Stats {\n const header = FA2_STATE.read(state);\n const centroid = vector(header, \"centroid\");\n const records: ForceAtlas2TraceRecord[] = [];\n const count = Math.floor(trace.byteLength / TRACE_RECORD_BYTES);\n for (let i = 0; i < count; i++) {\n const record = FA2_TRACE.read(trace, i * TRACE_RECORD_BYTES);\n records.push({\n swing: scalar(record, \"swing\"),\n traction: scalar(record, \"traction\"),\n speed: scalar(record, \"speed\"),\n speedEfficiency: scalar(record, \"speedEfficiency\"),\n meanDisplacement: scalar(record, \"meanDisplacement\"),\n settledCount: scalar(record, \"settledCount\"),\n });\n }\n return {\n iteration: scalar(header, \"iteration\"),\n meanDisplacement: scalar(header, \"meanDisplacement\"),\n rmsRadius: scalar(header, \"rmsRadius\"),\n layoutRadius: scalar(header, \"radius\"),\n centroid: [centroid[0], centroid[1], centroid[2]],\n repulsionTier: \"exact\",\n maxCellOccupancy: null,\n outsideGrid: null,\n msPerIteration: null,\n swing: scalar(header, \"swing\"),\n traction: scalar(header, \"traction\"),\n speed: scalar(header, \"speed\"),\n speedEfficiency: scalar(header, \"speedEfficiency\"),\n trace: records,\n };\n }\n\n /**\n * The resources of the last bind(), or E_NOT_LOADED before it.\n * @returns the resources\n */\n private requireResources(): ModelResources {\n if (this.resources === null) {\n throw new WebGpuGraphError(\"E_NOT_LOADED\", \"the ForceAtlas2 model has not been bound (load() first)\", {\n state: \"created\",\n });\n }\n return this.resources;\n }\n\n /**\n * The index of a stage name in FA2_STAGES, or E_INVALID_ARGUMENT.\n * @param upTo - the stage name\n * @returns its index\n */\n private stageIndex(upTo: string): number {\n for (let i = 0; i < FA2_STAGES.length; i++) {\n if (FA2_STAGES[i] === upTo) {\n return i;\n }\n }\n throw invalid(\"upTo\", upTo, FA2_STAGES.join(\" | \"));\n }\n\n /**\n * Drops the bind groups of the previous bind() (the buffers changed) so the cached kernels do not accumulate stale\n * groups across reloads; K3 / K4 live inside RepulsionExact and keep the P1-T6 behaviour. Also forgets the pass\n * of a batch recorded before the rebind.\n */\n private dropBound(): void {\n this.openPass = null;\n const { bound } = this;\n if (bound === null) {\n return;\n }\n for (const kernel of [bound.k1, bound.k2, bound.k5, bound.toScene, bound.fill]) {\n kernel.invalidate();\n }\n this.bound = null;\n }\n}\n\n// ============================================================ the factory\n\n/**\n * The resolve callback of the simulation's setParams: the patch over the current record, re-validated (the current\n * record is re-resolved first so the callback is typed without a cast).\n * @param patch - the setParams patch\n * @param current - the simulation's current option record\n * @returns the new record\n */\nfunction resolvePatch(patch: Partial<ForceAtlas2Options>, current: ForceAtlas2Options): ForceAtlas2Options {\n return resolveForceAtlas2Options(patch, resolveForceAtlas2Options(current));\n}\n\n/**\n * Spec 3.3 createForceAtlas2, verbatim: a GpuLayoutSimulation running ForceAtlas2 on the exact repulsion tier with\n * the option defaults of spec 7.14 and the GPU-only tuning of GpuLayoutTuning (contract 3.13 \"Contracts\").\n * @param ctx - the context (E_DISPOSED / E_DEVICE_LOST through assertReady)\n * @param options - the ForceAtlas2 options and the GPU-only tuning knobs in one record\n * @returns the simulation in state \"created\"; load() next\n */\nexport function createForceAtlas2(\n ctx: GpuContext,\n options?: ForceAtlas2Options & GpuLayoutTuning,\n): GpuLayoutSimulation<ForceAtlas2Options, ForceAtlas2Stats> {\n ctx.assertReady();\n const resolved = resolveForceAtlas2Options(options);\n const tuning = resolveLayoutTuning(options);\n const model = new ForceAtlas2Model(tuning, resolved);\n return new ForceSimulation<ForceAtlas2Options, ForceAtlas2Stats>(ctx, model, resolved, tuning, resolvePatch);\n}\n","/**\n * createAccelerator (spec 3.3, 9; contract 3.14): the injectable object that satisfies the CPU packages'\n * AlgorithmAccelerator and LayoutAccelerator interfaces STRUCTURALLY (spec 9.2, 9.3; the mirrors of\n * src/types/accelerator.ts until W1, D27). It carries P3's `forceAtlas2`, `release` and `dispose` and P7's seven\n * algorithm members (spec 8.2, 8.3; M8b-T8, PD-14) and nothing else: the CPU-side dispatchers (`accelerated()`,\n * `createSimulation()`) test `acc.betweennessCentrality !== undefined` and route to the CPU when the member is\n * absent (spec 2.4 row \"method missing\"), so a method the GPU does not implement must not exist here -- never a\n * throwing stub. The remaining algorithm members arrive one per shipped algorithm from P8; `fruchtermanReingold` /\n * `springElectrical` with P5.\n */\n\nimport { type F32, type F64, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { connectedComponents } from \"./algorithms/components.js\";\nimport { pageRank, personalizedPageRank } from \"./algorithms/pagerank.js\";\nimport { eigenvectorCentrality, hits, katzCentrality } from \"./algorithms/spectral.js\";\nimport { type GpuContext } from \"./context.js\";\nimport { createForceAtlas2 } from \"./layouts/forceatlas2.js\";\nimport { type AcceleratorOptions, type GpuAccelerator } from \"./types/accelerator.js\";\nimport {\n type ComponentsOptions,\n type EigenvectorOptions,\n type GpuHitsResult,\n type GpuLabelResult,\n type GpuPageRankResult,\n type GpuScoresResult,\n type HitsOptions,\n type KatzOptions,\n type PageRankOptions,\n} from \"./types/algorithms.js\";\nimport { type ForceAtlas2Stats, type GpuLayoutSimulation, type GpuLayoutTuning } from \"./types/layout.js\";\nimport { type ForceAtlas2Options } from \"./types/options.js\";\n\n/** The `algorithms` record of AcceleratorOptions (spec 3.3), named for the copy helpers. */\ntype AlgorithmDefaults = NonNullable<AcceleratorOptions[\"algorithms\"]>;\n\n/** The `algorithms.betweenness` record of AcceleratorOptions (spec 3.3: the `k` / `sources` defaults until A2). */\ntype BetweennessDefaults = NonNullable<AlgorithmDefaults[\"betweenness\"]>;\n\n/**\n * Frozen copy of the betweenness defaults; `sources` is copied into a fresh frozen array so a later mutation of\n * the caller's list is never seen by the accelerator.\n * @param defaults - the caller's record\n * @returns the frozen copy\n */\nfunction copyBetweenness(defaults: BetweennessDefaults): BetweennessDefaults {\n const copy: { k?: number | undefined; sources?: readonly number[] | undefined } = { ...defaults };\n if (defaults.sources !== undefined) {\n copy.sources = Object.freeze([...defaults.sources]);\n }\n return Object.freeze(copy);\n}\n\n/**\n * Frozen copy of the algorithms record, one level deeper for `betweenness`.\n * @param algorithms - the caller's record\n * @returns the frozen copy\n */\nfunction copyAlgorithms(algorithms: AlgorithmDefaults): AlgorithmDefaults {\n const copy: { betweenness?: BetweennessDefaults | undefined } = { ...algorithms };\n if (algorithms.betweenness !== undefined) {\n copy.betweenness = copyBetweenness(algorithms.betweenness);\n }\n return Object.freeze(copy);\n}\n\n/**\n * The frozen deep copy of the accelerator options (spec 3.3 GpuAccelerator.options: \"the tuning defaults given\n * to createAccelerator; frozen\"; contract 3.14): the record, its `layout` tuning, its `algorithms` record, the\n * `betweenness` record and the `sources` list are each fresh frozen objects, so neither the caller's later edits\n * nor a consumer's writes can change what the accelerator's simulations inherit.\n * @param options - the caller's options, or undefined\n * @returns the frozen copy (an empty frozen record when nothing was given)\n */\nfunction freezeOptions(options: AcceleratorOptions | undefined): Readonly<AcceleratorOptions> {\n if (options === undefined) {\n return Object.freeze({});\n }\n const copy: { layout?: GpuLayoutTuning | undefined; algorithms?: AlgorithmDefaults | undefined } = { ...options };\n if (options.layout !== undefined) {\n copy.layout = Object.freeze({ ...options.layout });\n }\n if (options.algorithms !== undefined) {\n copy.algorithms = copyAlgorithms(options.algorithms);\n }\n return Object.freeze(copy);\n}\n\n/**\n * Spec 3.3 createAccelerator, verbatim: the object implementing AlgorithmAccelerator & LayoutAccelerator\n * structurally; P3's forceAtlas2, release and dispose plus P7's seven algorithm members, each a delegation to\n * its algorithm with `ctx.assertReady()` first. The accelerator's algorithm defaults are not consulted by any of\n * them: only `betweenness` has any, and it belongs to P9. One per call (the app creates one and injects\n * it, spec 2.4); `kind` is \"webgpu\"; `options` is a frozen deep copy; `forceAtlas2(o)` is\n * `createForceAtlas2(ctx, { ...o, ...options.layout })`, so the GPU tuning given here wins over anything the\n * CPU-typed option object carries (spec 3.3: tuning never comes from the caller of the accelerator method);\n * `release(s)` is `ctx.release(s)`; `dispose()` is `ctx.dispose()`.\n * @param ctx - the context every simulation the accelerator creates runs on\n * @param options - GPU-only defaults inherited by every simulation (`layout`) and, from P9, the algorithm defaults\n * @returns the injectable accelerator\n * @throws E_DISPOSED / E_DEVICE_LOST from `ctx.assertReady()` (here and inside `forceAtlas2()`); `forceAtlas2()`\n * also throws what createForceAtlas2 throws (E_UNSUPPORTED for `nodeSize`, E_INVALID_ARGUMENT for a bad range)\n */\nexport function createAccelerator(ctx: GpuContext, options?: AcceleratorOptions): GpuAccelerator {\n ctx.assertReady();\n const frozen = freezeOptions(options);\n return {\n kind: \"webgpu\",\n ctx,\n options: frozen,\n /**\n * The ForceAtlas2 simulation with this accelerator's layout tuning (spec 3.3; contract 3.14).\n * @param o - the CPU option type (spec 9.3 ForceAtlas2Options); GPU tuning keys come from `options.layout`\n * @returns a fresh simulation in state \"created\"\n */\n forceAtlas2(o?: ForceAtlas2Options): GpuLayoutSimulation<ForceAtlas2Options, ForceAtlas2Stats> {\n ctx.assertReady();\n return createForceAtlas2(ctx, { ...o, ...frozen.layout });\n },\n /**\n * PageRank on the device (spec 8.2; contract 3.14).\n * @param gs - the snapshot\n * @param o - the CPU option record (spec 9.2 PageRankOptions)\n * @returns the f32 scores with `precision: \"f32\"` (spec 9.7)\n */\n async pageRank(gs: GraphSnapshot, o?: PageRankOptions): Promise<GpuPageRankResult> {\n ctx.assertReady();\n return await pageRank(ctx, gs, o);\n },\n /**\n * Personalized PageRank on the device (spec 8.2; contract 3.14). The mirror admits an f64 personalization\n * (spec 9.2 `F32 | F64`); the kernel reads f32, so an f64 vector is narrowed on the host first.\n * @param gs - the snapshot\n * @param personalization - one finite non-negative mass per node, not all zero\n * @param o - the CPU option record (spec 9.2 PageRankOptions)\n * @returns the f32 scores with `precision: \"f32\"` (spec 9.7)\n */\n async personalizedPageRank(\n gs: GraphSnapshot,\n personalization: F32 | F64,\n o?: PageRankOptions,\n ): Promise<GpuPageRankResult> {\n ctx.assertReady();\n const mass = personalization instanceof Float32Array ? personalization : Float32Array.from(personalization);\n return await personalizedPageRank(ctx, gs, mass, o);\n },\n /**\n * HITS hubs and authorities on the device (spec 8.2; contract 3.14).\n * @param gs - the snapshot\n * @param o - the CPU option record (spec 9.2 HitsOptions)\n * @returns hubs and authorities with `precision: \"f32\"` (spec 9.7)\n */\n async hits(gs: GraphSnapshot, o?: HitsOptions): Promise<GpuHitsResult> {\n ctx.assertReady();\n return await hits(ctx, gs, o);\n },\n /**\n * Eigenvector centrality on the device (spec 8.2; contract 3.14).\n * @param gs - the snapshot\n * @param o - the CPU option record (spec 9.2 EigenvectorOptions)\n * @returns the f32 scores with `precision: \"f32\"` (spec 9.7)\n */\n async eigenvectorCentrality(gs: GraphSnapshot, o?: EigenvectorOptions): Promise<GpuScoresResult> {\n ctx.assertReady();\n return await eigenvectorCentrality(ctx, gs, o);\n },\n /**\n * Katz centrality on the device (spec 8.2; contract 3.14).\n * @param gs - the snapshot\n * @param o - the CPU option record (spec 9.2 KatzOptions)\n * @returns the f32 scores with `precision: \"f32\"` (spec 9.7)\n */\n async katzCentrality(gs: GraphSnapshot, o?: KatzOptions): Promise<GpuScoresResult> {\n ctx.assertReady();\n return await katzCentrality(ctx, gs, o);\n },\n /**\n * Weakly connected components on the device (spec 8.3; contract 3.14): WCC semantics on directed input.\n * @param gs - the snapshot\n * @param o - `renumber` (default true); the mirror passes none\n * @returns the labels, the count and groups() (spec 9.7 LabelResultLike)\n */\n async connectedComponents(gs: GraphSnapshot, o?: ComponentsOptions): Promise<GpuLabelResult> {\n ctx.assertReady();\n return await connectedComponents(ctx, gs, o);\n },\n /**\n * The same algorithm as `connectedComponents` under the mirror's other name (spec 3.3, 9.2).\n * @param gs - the snapshot\n * @param o - `renumber` (default true); the mirror passes none\n * @returns the labels, the count and groups() (spec 9.7 LabelResultLike)\n */\n async weaklyConnectedComponents(gs: GraphSnapshot, o?: ComponentsOptions): Promise<GpuLabelResult> {\n ctx.assertReady();\n return await connectedComponents(ctx, gs, o);\n },\n /**\n * Destroys every device buffer recorded for the snapshot (spec 4.5); delegates to ctx.release.\n * @param s - the snapshot the app is done with\n */\n release(s: GraphSnapshot): void {\n ctx.release(s);\n },\n /**\n * Disposes the context (spec 2.8); delegates to ctx.dispose, idempotent.\n */\n dispose(): void {\n ctx.dispose();\n },\n };\n}\n"],"names":["scalar","checkDest","coreOf","resolve","RING_SLOTS","bindingOf","k","pass","aborted","invalid","normalised","run","finite","degree","out"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACCrC,MAAM;AAAA;AAAA,EAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACFpC,MAAM;AAAA;AAAA,EAAmC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACGzC,MAAM;AAAA;AAAA,EAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAxC,MAAM;AAAA;AAAA,EAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACHxC,MAAM;AAAA;AAAA,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACLlC,MAAM;AAAA;AAAA,EAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACK5B,MAAM;AAAA;AAAA,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACGlC,MAAM;AAAA;AAAA,EAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACL/B,MAAM;AAAA;AAAA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACI9B,MAAM;AAAA;AAAA,EAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACEvC,MAAM;AAAA;AAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACNhC,MAA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"}