graphwise 1.9.1 → 1.11.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 (155) hide show
  1. package/dist/async/index.cjs +98 -1
  2. package/dist/async/index.cjs.map +1 -0
  3. package/dist/async/index.d.ts +1 -0
  4. package/dist/async/index.d.ts.map +1 -1
  5. package/dist/async/index.js +96 -2
  6. package/dist/async/index.js.map +1 -0
  7. package/dist/async/ops.d.ts +2 -0
  8. package/dist/async/ops.d.ts.map +1 -1
  9. package/dist/async/protocol.d.ts +14 -0
  10. package/dist/async/protocol.d.ts.map +1 -1
  11. package/dist/async/runner-batched.d.ts +21 -0
  12. package/dist/async/runner-batched.d.ts.map +1 -0
  13. package/dist/async/runner-batched.unit.test.d.ts +2 -0
  14. package/dist/async/runner-batched.unit.test.d.ts.map +1 -0
  15. package/dist/async/runners.d.ts.map +1 -1
  16. package/dist/expansion/base-core.d.ts.map +1 -1
  17. package/dist/expansion/fuse.d.ts +24 -1
  18. package/dist/expansion/fuse.d.ts.map +1 -1
  19. package/dist/expansion/index.cjs +9 -1
  20. package/dist/expansion/index.js +2 -2
  21. package/dist/expansion/lace.d.ts +23 -2
  22. package/dist/expansion/lace.d.ts.map +1 -1
  23. package/dist/expansion/priority-helpers.d.ts +20 -1
  24. package/dist/expansion/priority-helpers.d.ts.map +1 -1
  25. package/dist/expansion/sift.d.ts +24 -1
  26. package/dist/expansion/sift.d.ts.map +1 -1
  27. package/dist/expansion/types.d.ts +30 -0
  28. package/dist/expansion/types.d.ts.map +1 -1
  29. package/dist/{expansion-DaTroIyv.cjs → expansion--UuRowv-.cjs} +267 -4
  30. package/dist/expansion--UuRowv-.cjs.map +1 -0
  31. package/dist/{expansion-ClDhlMK8.js → expansion-CZLNK6Pr.js} +220 -5
  32. package/dist/expansion-CZLNK6Pr.js.map +1 -0
  33. package/dist/gpu/csr-graph.d.ts +68 -0
  34. package/dist/gpu/csr-graph.d.ts.map +1 -0
  35. package/dist/gpu/csr-graph.unit.test.d.ts +2 -0
  36. package/dist/gpu/csr-graph.unit.test.d.ts.map +1 -0
  37. package/dist/gpu/index.cjs +220 -15
  38. package/dist/gpu/index.cjs.map +1 -0
  39. package/dist/gpu/index.d.ts +1 -0
  40. package/dist/gpu/index.d.ts.map +1 -1
  41. package/dist/gpu/index.js +204 -2
  42. package/dist/gpu/index.js.map +1 -0
  43. package/dist/gpu/kernels/adamic-adar/kernel.d.ts +39 -0
  44. package/dist/gpu/kernels/adamic-adar/kernel.d.ts.map +1 -0
  45. package/dist/gpu/kernels/intersection/kernel.d.ts +50 -0
  46. package/dist/gpu/kernels/intersection/kernel.d.ts.map +1 -0
  47. package/dist/gpu/kernels/intersection/logic.d.ts +87 -0
  48. package/dist/gpu/kernels/intersection/logic.d.ts.map +1 -0
  49. package/dist/gpu/kernels/intersection/logic.unit.test.d.ts +2 -0
  50. package/dist/gpu/kernels/intersection/logic.unit.test.d.ts.map +1 -0
  51. package/dist/gpu/kernels/kmeans/index.d.ts +6 -0
  52. package/dist/gpu/kernels/kmeans/index.d.ts.map +1 -0
  53. package/dist/gpu/kernels/kmeans/kernel.d.ts +34 -0
  54. package/dist/gpu/kernels/kmeans/kernel.d.ts.map +1 -0
  55. package/dist/gpu/kernels/kmeans/logic.d.ts +111 -0
  56. package/dist/gpu/kernels/kmeans/logic.d.ts.map +1 -0
  57. package/dist/gpu/kernels/kmeans/logic.unit.test.d.ts +5 -0
  58. package/dist/gpu/kernels/kmeans/logic.unit.test.d.ts.map +1 -0
  59. package/dist/gpu/operations.d.ts +52 -0
  60. package/dist/gpu/operations.d.ts.map +1 -1
  61. package/dist/index/index.cjs +42 -19
  62. package/dist/index/index.js +11 -9
  63. package/dist/{jaccard-Bys9_dGW.cjs → jaccard-Bdw4B0i4.cjs} +1 -1
  64. package/dist/{jaccard-Bys9_dGW.cjs.map → jaccard-Bdw4B0i4.cjs.map} +1 -1
  65. package/dist/{jaccard-3rCdilwm.js → jaccard-BwC_NuQu.js} +1 -1
  66. package/dist/{jaccard-3rCdilwm.js.map → jaccard-BwC_NuQu.js.map} +1 -1
  67. package/dist/kernel-2oH4Cn32.cjs +1001 -0
  68. package/dist/kernel-2oH4Cn32.cjs.map +1 -0
  69. package/dist/kernel-6deK9fh1.js +724 -0
  70. package/dist/kernel-6deK9fh1.js.map +1 -0
  71. package/dist/kernel-CXeGBH3s.cjs +467 -0
  72. package/dist/kernel-CXeGBH3s.cjs.map +1 -0
  73. package/dist/kernel-CigCjrts.js +467 -0
  74. package/dist/kernel-CigCjrts.js.map +1 -0
  75. package/dist/kernel-CvnRsF7E.js +1001 -0
  76. package/dist/kernel-CvnRsF7E.js.map +1 -0
  77. package/dist/kernel-DukrXtVb.cjs +724 -0
  78. package/dist/kernel-DukrXtVb.cjs.map +1 -0
  79. package/dist/{kmeans-B8x9D1kt.cjs → kmeans-CZ7tJFYw.cjs} +1 -1
  80. package/dist/{kmeans-B8x9D1kt.cjs.map → kmeans-CZ7tJFYw.cjs.map} +1 -1
  81. package/dist/{kmeans-DKkL9rAN.js → kmeans-DLrlrp6i.js} +1 -1
  82. package/dist/{kmeans-DKkL9rAN.js.map → kmeans-DLrlrp6i.js.map} +1 -1
  83. package/dist/logic-Dbyfb_-7.cjs +289 -0
  84. package/dist/logic-Dbyfb_-7.cjs.map +1 -0
  85. package/dist/logic-DyBzRg1A.js +242 -0
  86. package/dist/logic-DyBzRg1A.js.map +1 -0
  87. package/dist/operations-D-RB67WP.cjs +2269 -0
  88. package/dist/operations-D-RB67WP.cjs.map +1 -0
  89. package/dist/operations-D9otVlIH.js +2198 -0
  90. package/dist/operations-D9otVlIH.js.map +1 -0
  91. package/dist/{ops-upIi6JIi.js → ops-D5xZr4fV.js} +60 -2
  92. package/dist/ops-D5xZr4fV.js.map +1 -0
  93. package/dist/{ops-djAsQQSh.cjs → ops-paa1Nvlf.cjs} +71 -1
  94. package/dist/ops-paa1Nvlf.cjs.map +1 -0
  95. package/dist/ranking/baselines/communicability.d.ts +12 -0
  96. package/dist/ranking/baselines/communicability.d.ts.map +1 -1
  97. package/dist/ranking/baselines/katz.d.ts +12 -0
  98. package/dist/ranking/baselines/katz.d.ts.map +1 -1
  99. package/dist/ranking/baselines/pagerank.d.ts +15 -0
  100. package/dist/ranking/baselines/pagerank.d.ts.map +1 -1
  101. package/dist/ranking/baselines/types.d.ts +3 -0
  102. package/dist/ranking/baselines/types.d.ts.map +1 -1
  103. package/dist/ranking/index.cjs +5 -2
  104. package/dist/ranking/index.js +3 -3
  105. package/dist/ranking/mi/index.cjs +1 -1
  106. package/dist/ranking/mi/index.js +1 -1
  107. package/dist/ranking/parse-gpu.d.ts +31 -0
  108. package/dist/ranking/parse-gpu.d.ts.map +1 -0
  109. package/dist/ranking/parse-gpu.unit.test.d.ts +5 -0
  110. package/dist/ranking/parse-gpu.unit.test.d.ts.map +1 -0
  111. package/dist/ranking/parse.d.ts.map +1 -1
  112. package/dist/{ranking-3ez5m67U.js → ranking-DOKDBcIR.js} +237 -11
  113. package/dist/ranking-DOKDBcIR.js.map +1 -0
  114. package/dist/{ranking-DVvajgUZ.cjs → ranking-pe5UaxKg.cjs} +254 -10
  115. package/dist/ranking-pe5UaxKg.cjs.map +1 -0
  116. package/dist/schemas/graph.d.ts +1 -1
  117. package/dist/seeds/crest.d.ts +48 -0
  118. package/dist/seeds/crest.d.ts.map +1 -0
  119. package/dist/seeds/crest.unit.test.d.ts +2 -0
  120. package/dist/seeds/crest.unit.test.d.ts.map +1 -0
  121. package/dist/seeds/crisp.d.ts +57 -0
  122. package/dist/seeds/crisp.d.ts.map +1 -0
  123. package/dist/seeds/crisp.unit.test.d.ts +2 -0
  124. package/dist/seeds/crisp.unit.test.d.ts.map +1 -0
  125. package/dist/seeds/grasp-gpu.d.ts +40 -0
  126. package/dist/seeds/grasp-gpu.d.ts.map +1 -0
  127. package/dist/seeds/index.cjs +715 -5
  128. package/dist/seeds/index.cjs.map +1 -1
  129. package/dist/seeds/index.d.ts +4 -0
  130. package/dist/seeds/index.d.ts.map +1 -1
  131. package/dist/seeds/index.js +712 -6
  132. package/dist/seeds/index.js.map +1 -1
  133. package/dist/seeds/spine.d.ts +50 -0
  134. package/dist/seeds/spine.d.ts.map +1 -0
  135. package/dist/seeds/spine.unit.test.d.ts +2 -0
  136. package/dist/seeds/spine.unit.test.d.ts.map +1 -0
  137. package/dist/seeds/stride.d.ts +55 -0
  138. package/dist/seeds/stride.d.ts.map +1 -0
  139. package/dist/seeds/stride.unit.test.d.ts +2 -0
  140. package/dist/seeds/stride.unit.test.d.ts.map +1 -0
  141. package/dist/{gpu-CHiCN0wa.js → typegpu-Dq5FfUB8.cjs} +16 -2041
  142. package/dist/typegpu-Dq5FfUB8.cjs.map +1 -0
  143. package/dist/{gpu-Y6owRVMi.cjs → typegpu-DwnJf28i.js} +2 -2127
  144. package/dist/typegpu-DwnJf28i.js.map +1 -0
  145. package/dist/utils/index.cjs +1 -1
  146. package/dist/utils/index.js +1 -1
  147. package/package.json +1 -1
  148. package/dist/expansion-ClDhlMK8.js.map +0 -1
  149. package/dist/expansion-DaTroIyv.cjs.map +0 -1
  150. package/dist/gpu-CHiCN0wa.js.map +0 -1
  151. package/dist/gpu-Y6owRVMi.cjs.map +0 -1
  152. package/dist/ops-djAsQQSh.cjs.map +0 -1
  153. package/dist/ops-upIi6JIi.js.map +0 -1
  154. package/dist/ranking-3ez5m67U.js.map +0 -1
  155. package/dist/ranking-DVvajgUZ.cjs.map +0 -1
@@ -10,17 +10,6 @@ var __exportAll$1 = (all, no_symbols) => {
10
10
  return target;
11
11
  };
12
12
  //#endregion
13
- //#region src/gpu/types.ts
14
- /**
15
- * Error thrown when GPU backend is requested but unavailable.
16
- */
17
- var GPUNotAvailableError = class extends Error {
18
- constructor(reason) {
19
- super(`WebGPU not available: ${reason}`);
20
- this.name = "GPUNotAvailableError";
21
- }
22
- };
23
- //#endregion
24
13
  //#region node_modules/.pnpm/typegpu@0.10.2/node_modules/typegpu/shared/env.js
25
14
  /**
26
15
  * This can be used to branch functionality between "dev" and "prod" modes, so that our
@@ -14909,2037 +14898,23 @@ assignInfixOperator(MatBase, "mul", Operator.star);
14909
14898
  */
14910
14899
  var src_default = tgpu_exports;
14911
14900
  //#endregion
14912
- //#region src/gpu/csr.ts
14913
- /**
14914
- * Compressed Sparse Row (CSR) matrix representation for GPU computation.
14915
- *
14916
- * CSR format is memory-efficient for sparse graphs and maps well to
14917
- * GPU parallel operations. The format stores adjacency information
14918
- * in three arrays: row offsets, column indices, and optional values.
14919
- */
14920
- /**
14921
- * Convert a ReadableGraph to CSR format.
14922
- *
14923
- * For undirected graphs, each edge is stored twice (once in each direction).
14924
- * For directed graphs, edges are stored in the out-direction by default.
14925
- *
14926
- * @param graph - The graph to convert
14927
- * @param direction - Edge direction to include (default: 'out' for directed, 'both' for undirected)
14928
- * @returns CSR representation with index mapping
14929
- */
14930
- function graphToCSR(graph, direction = graph.directed ? "out" : "both") {
14931
- const nodeToIndex = /* @__PURE__ */ new Map();
14932
- const indexToNode = [];
14933
- for (const nodeId of graph.nodeIds()) {
14934
- const index = indexToNode.length;
14935
- nodeToIndex.set(nodeId, index);
14936
- indexToNode.push(nodeId);
14937
- }
14938
- const nodeCount = indexToNode.length;
14939
- const degrees = new Uint32Array(nodeCount);
14940
- for (const nodeId of graph.nodeIds()) {
14941
- const srcIndex = nodeToIndex.get(nodeId);
14942
- if (srcIndex === void 0) continue;
14943
- degrees[srcIndex] = graph.degree(nodeId, direction);
14944
- }
14945
- let totalEdges = 0;
14946
- for (let i = 0; i < nodeCount; i++) totalEdges += degrees[i] ?? 0;
14947
- const rowOffsets = new Uint32Array(nodeCount + 1);
14948
- for (let i = 0; i < nodeCount; i++) rowOffsets[i + 1] = (rowOffsets[i] ?? 0) + (degrees[i] ?? 0);
14949
- const colIndices = new Uint32Array(totalEdges);
14950
- const values = new Float32Array(totalEdges);
14951
- for (const nodeId of graph.nodeIds()) {
14952
- const srcIndex = nodeToIndex.get(nodeId);
14953
- if (srcIndex === void 0) continue;
14954
- const baseOffset = rowOffsets[srcIndex] ?? 0;
14955
- let localOffset = 0;
14956
- for (const neighbourId of graph.neighbours(nodeId, direction)) {
14957
- const dstIndex = nodeToIndex.get(neighbourId);
14958
- if (dstIndex === void 0) continue;
14959
- const edgeIdx = baseOffset + localOffset;
14960
- colIndices[edgeIdx] = dstIndex;
14961
- values[edgeIdx] = graph.getEdge(nodeId, neighbourId)?.weight ?? 1;
14962
- localOffset++;
14963
- }
14964
- }
14965
- return {
14966
- csr: {
14967
- rowOffsets,
14968
- colIndices,
14969
- values,
14970
- nodeCount,
14971
- edgeCount: graph.directed ? graph.edgeCount : graph.edgeCount * 2
14972
- },
14973
- indexMap: {
14974
- nodeToIndex,
14975
- indexToNode
14976
- }
14977
- };
14978
- }
14979
- /**
14980
- * Create TypeGPU typed buffers from a CSR matrix.
14981
- *
14982
- * Uses TypeGPU's typed buffer API for type-safe GPU computation.
14983
- * Buffers are created with storage usage for compute operations.
14984
- *
14985
- * @param root - TypeGPU root instance
14986
- * @param csr - CSR matrix to upload
14987
- * @returns Typed buffer group
14988
- *
14989
- * @example
14990
- * ```typescript
14991
- * import { initGPU, csrToTypedBuffers, graphToCSR } from "graphwise/gpu";
14992
- *
14993
- * const root = await initGPU();
14994
- * const { csr } = graphToCSR(graph);
14995
- * const buffers = csrToTypedBuffers(root, csr);
14996
- *
14997
- * // Read data back to CPU
14998
- * const rowOffsets = await buffers.rowOffsets.read();
14999
- * console.log(rowOffsets); // Uint32Array
15000
- * ```
15001
- */
15002
- function csrToTypedBuffers(root, csr) {
15003
- const rowOffsetsArray = Array.from(csr.rowOffsets);
15004
- const colIndicesArray = Array.from(csr.colIndices);
15005
- const rowOffsetsBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, csr.rowOffsets.length), rowOffsetsArray).$usage("storage"), "rowOffsetsBuffer");
15006
- const colIndicesBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, csr.colIndices.length), colIndicesArray).$usage("storage"), "colIndicesBuffer");
15007
- if (csr.values !== void 0) {
15008
- const valuesArray = Array.from(csr.values);
15009
- return {
15010
- rowOffsets: rowOffsetsBuffer,
15011
- colIndices: colIndicesBuffer,
15012
- values: (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, csr.values.length), valuesArray).$usage("storage"), "valuesBuffer"),
15013
- nodeCount: csr.nodeCount,
15014
- edgeCount: csr.edgeCount
15015
- };
15016
- }
15017
- return {
15018
- rowOffsets: rowOffsetsBuffer,
15019
- colIndices: colIndicesBuffer,
15020
- nodeCount: csr.nodeCount,
15021
- edgeCount: csr.edgeCount
15022
- };
15023
- }
15024
- //#endregion
15025
- //#region src/gpu/detect.ts
15026
- /**
15027
- * Detect WebGPU availability in the current environment.
15028
- *
15029
- * Checks for:
15030
- * - Browser: navigator.gpu
15031
- * - Node.js: global GPU constructor (Node.js 21+ with --experimental-webgpu)
15032
- * - Deno: global GPU constructor
15033
- *
15034
- * @returns Detection result with availability status and reason
15035
- */
15036
- function detectWebGPU() {
15037
- if (typeof navigator !== "undefined" && "gpu" in navigator) return { available: true };
15038
- if (typeof globalThis !== "undefined" && "GPU" in globalThis) return { available: true };
15039
- const reasons = [];
15040
- if (typeof navigator === "undefined" && typeof globalThis === "undefined") reasons.push("no global scope detected");
15041
- else if (typeof navigator !== "undefined" && !("gpu" in navigator)) reasons.push("navigator.gpu not present (browser may not support WebGPU)");
15042
- else if (typeof globalThis !== "undefined" && !("GPU" in globalThis)) reasons.push("global GPU not present (Node.js requires v21+ with --experimental-webgpu flag)");
15043
- return {
15044
- available: false,
15045
- reason: reasons.length > 0 ? reasons.join("; ") : "unknown environment"
15046
- };
15047
- }
15048
- /**
15049
- * Check if WebGPU is available (convenience function).
15050
- *
15051
- * @returns true if WebGPU is available, false otherwise
15052
- */
15053
- function isWebGPUAvailable() {
15054
- return detectWebGPU().available;
15055
- }
15056
- /**
15057
- * Assert that WebGPU is available, throwing an error if not.
15058
- *
15059
- * @throws Error if WebGPU is not available
15060
- */
15061
- function assertWebGPUAvailable() {
15062
- const result = detectWebGPU();
15063
- if (!result.available) throw new Error(`WebGPU required but not available: ${result.reason ?? "unknown reason"}`);
15064
- }
15065
- //#endregion
15066
- //#region src/gpu/root.ts
15067
- /**
15068
- * TypeGPU root initialisation for graphwise GPU operations.
15069
- *
15070
- * Provides a simplified wrapper around TypeGPU's tgpu.init() for
15071
- * GPU device acquisition and resource management.
15072
- *
15073
- * @module gpu/root
15074
- */
15075
- /**
15076
- * Initialise a TypeGPU root for GPU compute operations.
15077
- *
15078
- * This wraps tgpu.init() with WebGPU availability checking and
15079
- * simplified options.
15080
- *
15081
- * @param options - Initialisation options
15082
- * @returns Promise resolving to a TypeGPU root instance
15083
- * @throws Error if WebGPU is unavailable or device request fails
15084
- *
15085
- * @example
15086
- * ```typescript
15087
- * import { initGPU } from "graphwise/gpu";
15088
- *
15089
- * const root = await initGPU();
15090
- * // Use root for GPU operations...
15091
- * root.destroy();
15092
- * ```
15093
- */
15094
- async function initGPU(options = {}) {
15095
- const detection = detectWebGPU();
15096
- if (!detection.available) throw new Error(`WebGPU unavailable: ${detection.reason ?? "unknown reason"}`);
15097
- return await tgpu_exports.init({ adapter: options.powerPreference ? { powerPreference: options.powerPreference } : void 0 });
15098
- }
15099
- /**
15100
- * Create a TypeGPU root from an existing GPU device.
15101
- *
15102
- * Use this when you already have a GPUDevice and want to wrap it
15103
- * with TypeGPU functionality.
15104
- *
15105
- * @param device - Existing GPU device
15106
- * @returns TypeGPU root instance
15107
- *
15108
- * @example
15109
- * ```typescript
15110
- * import { initGPUFromDevice } from "graphwise/gpu";
15111
- *
15112
- * const adapter = await navigator.gpu.requestAdapter();
15113
- * const device = await adapter.requestDevice();
15114
- * const root = initGPUFromDevice(device);
15115
- * ```
15116
- */
15117
- function initGPUFromDevice(device) {
15118
- return tgpu_exports.initFromDevice({ device });
15119
- }
15120
- //#endregion
15121
- //#region src/gpu/dispatch.ts
15122
- /**
15123
- * Backend selection and dispatch utilities for GPU compute operations.
15124
- *
15125
- * Provides the `withBackend` function that handles auto/gpu/cpu backend
15126
- * selection with timing and fallback logic.
15127
- *
15128
- * @module gpu/dispatch
15129
- */
15130
- /**
15131
- * Execute a compute operation with automatic backend selection.
15132
- *
15133
- * @param options - Backend selection and cancellation options
15134
- * @param cpuFn - CPU fallback implementation
15135
- * @param gpuFn - GPU implementation (receives TypeGPU root)
15136
- * @returns Compute result with backend used and timing
15137
- */
15138
- async function withBackend(options, cpuFn, gpuFn) {
15139
- const backend = options.backend ?? "auto";
15140
- if (options.signal?.aborted === true) throw new DOMException("Operation aborted", "AbortError");
15141
- if (backend === "cpu") {
15142
- const start = performance.now();
15143
- return {
15144
- value: cpuFn(),
15145
- backend: "cpu",
15146
- elapsedMs: performance.now() - start
15147
- };
15148
- }
15149
- if (backend === "gpu") {
15150
- const detection = detectWebGPU();
15151
- if (!detection.available) throw new GPUNotAvailableError(detection.reason ?? "Unknown reason");
15152
- const root = options.root;
15153
- if (root === void 0) throw new Error("GPU backend requires a GraphwiseGPURoot. Pass one via options.root or use backend: 'auto'.");
15154
- const start = performance.now();
15155
- return {
15156
- value: await gpuFn(root),
15157
- backend: "gpu",
15158
- elapsedMs: performance.now() - start
15159
- };
15160
- }
15161
- if (!detectWebGPU().available) {
15162
- const start = performance.now();
15163
- return {
15164
- value: cpuFn(),
15165
- backend: "cpu",
15166
- elapsedMs: performance.now() - start
15167
- };
15168
- }
15169
- const root = options.root;
15170
- if (root === void 0) {
15171
- const start = performance.now();
15172
- return {
15173
- value: cpuFn(),
15174
- backend: "cpu",
15175
- elapsedMs: performance.now() - start
15176
- };
15177
- }
15178
- const start = performance.now();
15179
- return {
15180
- value: await gpuFn(root),
15181
- backend: "gpu",
15182
- elapsedMs: performance.now() - start
15183
- };
15184
- }
15185
- //#endregion
15186
- //#region src/gpu/kernels/spmv/kernel.ts
15187
- /**
15188
- * TypeGPU compute kernel for Sparse Matrix-Vector Multiplication (SpMV).
15189
- *
15190
- * Computes y = A * x where A is a sparse matrix in CSR format.
15191
- * Uses TypeGPU's compute pipeline for parallel GPU execution.
15192
- *
15193
- * @module gpu/kernels/spmv/kernel
15194
- */
15195
- /**
15196
- * Bind group layout for SpMV kernel.
15197
- */
15198
- var SpMVLayout = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(src_default.bindGroupLayout({
15199
- rowOffsets: { storage: data_exports.arrayOf(data_exports.u32) },
15200
- colIndices: { storage: data_exports.arrayOf(data_exports.u32) },
15201
- values: { storage: data_exports.arrayOf(data_exports.f32) },
15202
- x: { storage: data_exports.arrayOf(data_exports.f32) },
15203
- y: {
15204
- storage: data_exports.arrayOf(data_exports.f32),
15205
- access: "mutable"
15206
- },
15207
- nodeCount: { uniform: data_exports.u32 },
15208
- hasValues: { uniform: data_exports.u32 }
15209
- }), "SpMVLayout");
15210
- /**
15211
- * SpMV compute pipeline: y[row] = sum(A[row,col] * x[col]).
15212
- *
15213
- * Each thread computes one row of the output vector using the CSR format:
15214
- * - rowOffsets: start/end indices for each row
15215
- * - colIndices: column index for each non-zero entry
15216
- * - values: edge weights (optional, defaults to 1.0)
15217
- */
15218
- var spmvPipeline = (($) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set($.f = ((row) => {
15219
- "use gpu";
15220
- const start = SpMVLayout.$.rowOffsets[row] ?? 0;
15221
- const end = SpMVLayout.$.rowOffsets[__tsover_add(row, 1)] ?? 0;
15222
- let sum = 0;
15223
- for (let i = start; i < end; i = __tsover_add(i, 1)) {
15224
- const col = SpMVLayout.$.colIndices[i] ?? 0;
15225
- const weight = SpMVLayout.$.hasValues !== 0 ? SpMVLayout.$.values[i] ?? 1 : 1;
15226
- sum = __tsover_add(sum, __tsover_mul(weight, SpMVLayout.$.x[col] ?? 0));
15227
- }
15228
- SpMVLayout.$.y[row] = sum;
15229
- }), {
15230
- v: 1,
15231
- name: "spmvPipeline",
15232
- ast: {
15233
- "params": [{
15234
- "type": "i",
15235
- "name": "row"
15236
- }],
15237
- "body": [0, [
15238
- [
15239
- 13,
15240
- "start",
15241
- [
15242
- 3,
15243
- [
15244
- 8,
15245
- [
15246
- 7,
15247
- [
15248
- 7,
15249
- "SpMVLayout",
15250
- "$"
15251
- ],
15252
- "rowOffsets"
15253
- ],
15254
- "row"
15255
- ],
15256
- "??",
15257
- [5, "0"]
15258
- ]
15259
- ],
15260
- [
15261
- 13,
15262
- "end",
15263
- [
15264
- 3,
15265
- [
15266
- 8,
15267
- [
15268
- 7,
15269
- [
15270
- 7,
15271
- "SpMVLayout",
15272
- "$"
15273
- ],
15274
- "rowOffsets"
15275
- ],
15276
- [
15277
- 1,
15278
- "row",
15279
- "+",
15280
- [5, "1"]
15281
- ]
15282
- ],
15283
- "??",
15284
- [5, "0"]
15285
- ]
15286
- ],
15287
- [
15288
- 12,
15289
- "sum",
15290
- [5, "0"]
15291
- ],
15292
- [
15293
- 14,
15294
- [
15295
- 12,
15296
- "i",
15297
- "start"
15298
- ],
15299
- [
15300
- 1,
15301
- "i",
15302
- "<",
15303
- "end"
15304
- ],
15305
- [
15306
- 2,
15307
- "i",
15308
- "=",
15309
- [
15310
- 1,
15311
- "i",
15312
- "+",
15313
- [5, "1"]
15314
- ]
15315
- ],
15316
- [0, [
15317
- [
15318
- 13,
15319
- "col",
15320
- [
15321
- 3,
15322
- [
15323
- 8,
15324
- [
15325
- 7,
15326
- [
15327
- 7,
15328
- "SpMVLayout",
15329
- "$"
15330
- ],
15331
- "colIndices"
15332
- ],
15333
- "i"
15334
- ],
15335
- "??",
15336
- [5, "0"]
15337
- ]
15338
- ],
15339
- [
15340
- 13,
15341
- "weight",
15342
- [
15343
- 105,
15344
- [
15345
- 1,
15346
- [
15347
- 7,
15348
- [
15349
- 7,
15350
- "SpMVLayout",
15351
- "$"
15352
- ],
15353
- "hasValues"
15354
- ],
15355
- "!==",
15356
- [5, "0"]
15357
- ],
15358
- [
15359
- 3,
15360
- [
15361
- 8,
15362
- [
15363
- 7,
15364
- [
15365
- 7,
15366
- "SpMVLayout",
15367
- "$"
15368
- ],
15369
- "values"
15370
- ],
15371
- "i"
15372
- ],
15373
- "??",
15374
- [5, "1"]
15375
- ],
15376
- [5, "1"]
15377
- ]
15378
- ],
15379
- [
15380
- 2,
15381
- "sum",
15382
- "=",
15383
- [
15384
- 1,
15385
- "sum",
15386
- "+",
15387
- [
15388
- 1,
15389
- "weight",
15390
- "*",
15391
- [
15392
- 3,
15393
- [
15394
- 8,
15395
- [
15396
- 7,
15397
- [
15398
- 7,
15399
- "SpMVLayout",
15400
- "$"
15401
- ],
15402
- "x"
15403
- ],
15404
- "col"
15405
- ],
15406
- "??",
15407
- [5, "0"]
15408
- ]
15409
- ]
15410
- ]
15411
- ]
15412
- ]]
15413
- ],
15414
- [
15415
- 2,
15416
- [
15417
- 8,
15418
- [
15419
- 7,
15420
- [
15421
- 7,
15422
- "SpMVLayout",
15423
- "$"
15424
- ],
15425
- "y"
15426
- ],
15427
- "row"
15428
- ],
15429
- "=",
15430
- "sum"
15431
- ]
15432
- ]],
15433
- "externalNames": ["SpMVLayout"]
15434
- },
15435
- externals: () => ({ SpMVLayout })
15436
- }) && $.f)({});
15437
- /**
15438
- * Dispatch SpMV on GPU.
15439
- *
15440
- * @param root - TypeGPU root instance
15441
- * @param csrBuffers - CSR matrix as typed buffers
15442
- * @param x - Input vector buffer
15443
- * @param y - Output vector buffer (mutable)
15444
- * @param nodeCount - Number of nodes/rows
15445
- * @param hasValues - Whether edge weights are present
15446
- */
15447
- function dispatchSpmv(root, csrBuffers, x, y, nodeCount, hasValues) {
15448
- const pipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createGuardedComputePipeline(spmvPipeline), "pipeline");
15449
- const valuesBuffer = csrBuffers.values ?? root.createBuffer(data_exports.arrayOf(data_exports.f32, csrBuffers.edgeCount), new Array(csrBuffers.edgeCount).fill(1)).$usage("storage");
15450
- const nodeCountBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, nodeCount).$usage("uniform"), "nodeCountBuffer");
15451
- const hasValuesBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, hasValues ? 1 : 0).$usage("uniform"), "hasValuesBuffer");
15452
- const bindGroup = root.createBindGroup(SpMVLayout, {
15453
- rowOffsets: csrBuffers.rowOffsets,
15454
- colIndices: csrBuffers.colIndices,
15455
- values: valuesBuffer,
15456
- x,
15457
- y,
15458
- nodeCount: nodeCountBuffer,
15459
- hasValues: hasValuesBuffer
15460
- });
15461
- pipeline.with(bindGroup).dispatchThreads(nodeCount);
15462
- }
15463
- //#endregion
15464
- //#region src/gpu/kernels/pagerank/kernel.ts
15465
- /**
15466
- * TypeGPU compute kernel for PageRank power iteration.
15467
- *
15468
- * Computes one iteration of PageRank:
15469
- * r(v) = (1 - d)/N + d * sum(r(u) / deg_out(u)) for u -> v
15470
- *
15471
- * Uses TypeGPU's compute pipeline for parallel GPU execution.
15472
- *
15473
- * @module gpu/kernels/pagerank/kernel
15474
- */
15475
- /**
15476
- * Bind group layout for PageRank kernel.
15477
- */
15478
- var PageRankLayout = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(src_default.bindGroupLayout({
15479
- rowOffsets: { storage: data_exports.arrayOf(data_exports.u32) },
15480
- colIndices: { storage: data_exports.arrayOf(data_exports.u32) },
15481
- ranks: { storage: data_exports.arrayOf(data_exports.f32) },
15482
- outDegrees: { storage: data_exports.arrayOf(data_exports.u32) },
15483
- newRanks: {
15484
- storage: data_exports.arrayOf(data_exports.f32),
15485
- access: "mutable"
15486
- },
15487
- nodeCount: { uniform: data_exports.u32 },
15488
- damping: { uniform: data_exports.f32 }
15489
- }), "PageRankLayout");
15490
- /**
15491
- * PageRank compute pipeline: one power iteration per dispatch.
15492
- *
15493
- * Each thread computes one node's new rank from incoming neighbours:
15494
- * newRank[v] = (1 - damping) / N + damping * sum(rank[u] / outDegree[u])
15495
- */
15496
- var pagerankPipeline = (($) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set($.f = ((node) => {
15497
- "use gpu";
15498
- const n = PageRankLayout.$.nodeCount ?? 0;
15499
- const damp = PageRankLayout.$.damping ?? .85;
15500
- const start = PageRankLayout.$.rowOffsets[node] ?? 0;
15501
- const end = PageRankLayout.$.rowOffsets[__tsover_add(node, 1)] ?? 0;
15502
- let contribution = 0;
15503
- for (let i = start; i < end; i = __tsover_add(i, 1)) {
15504
- const source = PageRankLayout.$.colIndices[i] ?? 0;
15505
- const deg = PageRankLayout.$.outDegrees[source] ?? 0;
15506
- if (deg > 0) {
15507
- const rank = PageRankLayout.$.ranks[source] ?? 0;
15508
- contribution = __tsover_add(contribution, __tsover_div(rank, deg));
15509
- }
15510
- }
15511
- const teleport = __tsover_div(__tsover_sub(1, damp), n);
15512
- PageRankLayout.$.newRanks[node] = __tsover_add(teleport, __tsover_mul(damp, contribution));
15513
- }), {
15514
- v: 1,
15515
- name: "pagerankPipeline",
15516
- ast: {
15517
- "params": [{
15518
- "type": "i",
15519
- "name": "node"
15520
- }],
15521
- "body": [0, [
15522
- [
15523
- 13,
15524
- "n",
15525
- [
15526
- 3,
15527
- [
15528
- 7,
15529
- [
15530
- 7,
15531
- "PageRankLayout",
15532
- "$"
15533
- ],
15534
- "nodeCount"
15535
- ],
15536
- "??",
15537
- [5, "0"]
15538
- ]
15539
- ],
15540
- [
15541
- 13,
15542
- "damp",
15543
- [
15544
- 3,
15545
- [
15546
- 7,
15547
- [
15548
- 7,
15549
- "PageRankLayout",
15550
- "$"
15551
- ],
15552
- "damping"
15553
- ],
15554
- "??",
15555
- [5, "0.85"]
15556
- ]
15557
- ],
15558
- [
15559
- 13,
15560
- "start",
15561
- [
15562
- 3,
15563
- [
15564
- 8,
15565
- [
15566
- 7,
15567
- [
15568
- 7,
15569
- "PageRankLayout",
15570
- "$"
15571
- ],
15572
- "rowOffsets"
15573
- ],
15574
- "node"
15575
- ],
15576
- "??",
15577
- [5, "0"]
15578
- ]
15579
- ],
15580
- [
15581
- 13,
15582
- "end",
15583
- [
15584
- 3,
15585
- [
15586
- 8,
15587
- [
15588
- 7,
15589
- [
15590
- 7,
15591
- "PageRankLayout",
15592
- "$"
15593
- ],
15594
- "rowOffsets"
15595
- ],
15596
- [
15597
- 1,
15598
- "node",
15599
- "+",
15600
- [5, "1"]
15601
- ]
15602
- ],
15603
- "??",
15604
- [5, "0"]
15605
- ]
15606
- ],
15607
- [
15608
- 12,
15609
- "contribution",
15610
- [5, "0"]
15611
- ],
15612
- [
15613
- 14,
15614
- [
15615
- 12,
15616
- "i",
15617
- "start"
15618
- ],
15619
- [
15620
- 1,
15621
- "i",
15622
- "<",
15623
- "end"
15624
- ],
15625
- [
15626
- 2,
15627
- "i",
15628
- "=",
15629
- [
15630
- 1,
15631
- "i",
15632
- "+",
15633
- [5, "1"]
15634
- ]
15635
- ],
15636
- [0, [
15637
- [
15638
- 13,
15639
- "source",
15640
- [
15641
- 3,
15642
- [
15643
- 8,
15644
- [
15645
- 7,
15646
- [
15647
- 7,
15648
- "PageRankLayout",
15649
- "$"
15650
- ],
15651
- "colIndices"
15652
- ],
15653
- "i"
15654
- ],
15655
- "??",
15656
- [5, "0"]
15657
- ]
15658
- ],
15659
- [
15660
- 13,
15661
- "deg",
15662
- [
15663
- 3,
15664
- [
15665
- 8,
15666
- [
15667
- 7,
15668
- [
15669
- 7,
15670
- "PageRankLayout",
15671
- "$"
15672
- ],
15673
- "outDegrees"
15674
- ],
15675
- "source"
15676
- ],
15677
- "??",
15678
- [5, "0"]
15679
- ]
15680
- ],
15681
- [
15682
- 11,
15683
- [
15684
- 1,
15685
- "deg",
15686
- ">",
15687
- [5, "0"]
15688
- ],
15689
- [0, [[
15690
- 13,
15691
- "rank",
15692
- [
15693
- 3,
15694
- [
15695
- 8,
15696
- [
15697
- 7,
15698
- [
15699
- 7,
15700
- "PageRankLayout",
15701
- "$"
15702
- ],
15703
- "ranks"
15704
- ],
15705
- "source"
15706
- ],
15707
- "??",
15708
- [5, "0"]
15709
- ]
15710
- ], [
15711
- 2,
15712
- "contribution",
15713
- "=",
15714
- [
15715
- 1,
15716
- "contribution",
15717
- "+",
15718
- [
15719
- 1,
15720
- "rank",
15721
- "/",
15722
- "deg"
15723
- ]
15724
- ]
15725
- ]]]
15726
- ]
15727
- ]]
15728
- ],
15729
- [
15730
- 13,
15731
- "teleport",
15732
- [
15733
- 1,
15734
- [
15735
- 1,
15736
- [5, "1"],
15737
- "-",
15738
- "damp"
15739
- ],
15740
- "/",
15741
- "n"
15742
- ]
15743
- ],
15744
- [
15745
- 2,
15746
- [
15747
- 8,
15748
- [
15749
- 7,
15750
- [
15751
- 7,
15752
- "PageRankLayout",
15753
- "$"
15754
- ],
15755
- "newRanks"
15756
- ],
15757
- "node"
15758
- ],
15759
- "=",
15760
- [
15761
- 1,
15762
- "teleport",
15763
- "+",
15764
- [
15765
- 1,
15766
- "damp",
15767
- "*",
15768
- "contribution"
15769
- ]
15770
- ]
15771
- ]
15772
- ]],
15773
- "externalNames": ["PageRankLayout"]
15774
- },
15775
- externals: () => ({ PageRankLayout })
15776
- }) && $.f)({});
15777
- /**
15778
- * Dispatch one PageRank iteration on GPU.
15779
- *
15780
- * @param root - TypeGPU root instance
15781
- * @param csrBuffers - CSR matrix as typed buffers (transpose graph: in-edges)
15782
- * @param ranks - Current rank values buffer
15783
- * @param outDegrees - Out-degree buffer for each node
15784
- * @param newRanks - Output buffer for new rank values (mutable)
15785
- * @param nodeCount - Number of nodes
15786
- * @param damping - Damping factor (typically 0.85)
15787
- */
15788
- function dispatchPagerank(root, csrBuffers, ranks, outDegrees, newRanks, nodeCount, damping) {
15789
- const pipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createGuardedComputePipeline(pagerankPipeline), "pipeline");
15790
- const nodeCountBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, nodeCount).$usage("uniform"), "nodeCountBuffer");
15791
- const dampingBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.f32, damping).$usage("uniform"), "dampingBuffer");
15792
- const bindGroup = root.createBindGroup(PageRankLayout, {
15793
- rowOffsets: csrBuffers.rowOffsets,
15794
- colIndices: csrBuffers.colIndices,
15795
- ranks,
15796
- outDegrees,
15797
- newRanks,
15798
- nodeCount: nodeCountBuffer,
15799
- damping: dampingBuffer
15800
- });
15801
- pipeline.with(bindGroup).dispatchThreads(nodeCount);
15802
- }
15803
- //#endregion
15804
- //#region src/gpu/kernels/jaccard/kernel.ts
15805
- /**
15806
- * TypeGPU compute kernel for batch Jaccard similarity.
15807
- *
15808
- * Computes Jaccard coefficient for multiple node pairs in parallel:
15809
- * J(u, v) = |N(u) ∩ N(v)| / |N(u) ∪ N(v)|
15810
- *
15811
- * Uses binary search optimisation: iterate smaller neighbourhood, search in larger.
15812
- *
15813
- * @module gpu/kernels/jaccard/kernel
15814
- */
15815
- /**
15816
- * Bind group layout for Jaccard kernel.
15817
- */
15818
- var JaccardLayout = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(src_default.bindGroupLayout({
15819
- rowOffsets: { storage: data_exports.arrayOf(data_exports.u32) },
15820
- colIndices: { storage: data_exports.arrayOf(data_exports.u32) },
15821
- pairsU: { storage: data_exports.arrayOf(data_exports.u32) },
15822
- pairsV: { storage: data_exports.arrayOf(data_exports.u32) },
15823
- results: {
15824
- storage: data_exports.arrayOf(data_exports.f32),
15825
- access: "mutable"
15826
- },
15827
- pairCount: { uniform: data_exports.u32 }
15828
- }), "JaccardLayout");
15829
- /**
15830
- * Jaccard compute pipeline: one thread per pair.
15831
- *
15832
- * For each pair (u, v):
15833
- * - Count intersection by iterating smaller neighbourhood
15834
- * - Binary search in larger neighbourhood
15835
- * - Jaccard = intersection / (degU + degV - intersection)
15836
- */
15837
- var jaccardPipeline = (($) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set($.f = ((pairIdx) => {
15838
- "use gpu";
15839
- const u = JaccardLayout.$.pairsU[pairIdx] ?? 0;
15840
- const v = JaccardLayout.$.pairsV[pairIdx] ?? 0;
15841
- const uStart = JaccardLayout.$.rowOffsets[u] ?? 0;
15842
- const uEnd = JaccardLayout.$.rowOffsets[__tsover_add(u, 1)] ?? 0;
15843
- const vStart = JaccardLayout.$.rowOffsets[v] ?? 0;
15844
- const vEnd = JaccardLayout.$.rowOffsets[__tsover_add(v, 1)] ?? 0;
15845
- const degU = __tsover_sub(uEnd, uStart);
15846
- const degV = __tsover_sub(vEnd, vStart);
15847
- if (degU === 0 || degV === 0) {
15848
- JaccardLayout.$.results[pairIdx] = 0;
15849
- return;
14901
+ Object.defineProperty(exports, "data_exports", {
14902
+ enumerable: true,
14903
+ get: function() {
14904
+ return data_exports;
15850
14905
  }
15851
- let intersection = 0;
15852
- if (degU <= degV) for (let i = uStart; i < uEnd; i = __tsover_add(i, 1)) {
15853
- const neighbour = JaccardLayout.$.colIndices[i] ?? 0;
15854
- let lo = vStart;
15855
- let hi = vEnd;
15856
- while (lo < hi) {
15857
- const mid = __tsover_add(lo, __tsover_div(__tsover_sub(hi, lo), 2));
15858
- const midVal = JaccardLayout.$.colIndices[mid] ?? 0;
15859
- if (midVal === neighbour) {
15860
- intersection = __tsover_add(intersection, 1);
15861
- lo = hi;
15862
- } else if (midVal < neighbour) lo = __tsover_add(mid, 1);
15863
- else hi = mid;
15864
- }
14906
+ });
14907
+ Object.defineProperty(exports, "src_default", {
14908
+ enumerable: true,
14909
+ get: function() {
14910
+ return src_default;
15865
14911
  }
15866
- else for (let i = vStart; i < vEnd; i = __tsover_add(i, 1)) {
15867
- const neighbour = JaccardLayout.$.colIndices[i] ?? 0;
15868
- let lo = uStart;
15869
- let hi = uEnd;
15870
- while (lo < hi) {
15871
- const mid = __tsover_add(lo, __tsover_div(__tsover_sub(hi, lo), 2));
15872
- const midVal = JaccardLayout.$.colIndices[mid] ?? 0;
15873
- if (midVal === neighbour) {
15874
- intersection = __tsover_add(intersection, 1);
15875
- lo = hi;
15876
- } else if (midVal < neighbour) lo = __tsover_add(mid, 1);
15877
- else hi = mid;
15878
- }
14912
+ });
14913
+ Object.defineProperty(exports, "tgpu_exports", {
14914
+ enumerable: true,
14915
+ get: function() {
14916
+ return tgpu_exports;
15879
14917
  }
15880
- const unionSize = __tsover_sub(__tsover_add(degU, degV), intersection);
15881
- JaccardLayout.$.results[pairIdx] = __tsover_div(intersection, unionSize);
15882
- }), {
15883
- v: 1,
15884
- name: "jaccardPipeline",
15885
- ast: {
15886
- "params": [{
15887
- "type": "i",
15888
- "name": "pairIdx"
15889
- }],
15890
- "body": [0, [
15891
- [
15892
- 13,
15893
- "u",
15894
- [
15895
- 3,
15896
- [
15897
- 8,
15898
- [
15899
- 7,
15900
- [
15901
- 7,
15902
- "JaccardLayout",
15903
- "$"
15904
- ],
15905
- "pairsU"
15906
- ],
15907
- "pairIdx"
15908
- ],
15909
- "??",
15910
- [5, "0"]
15911
- ]
15912
- ],
15913
- [
15914
- 13,
15915
- "v",
15916
- [
15917
- 3,
15918
- [
15919
- 8,
15920
- [
15921
- 7,
15922
- [
15923
- 7,
15924
- "JaccardLayout",
15925
- "$"
15926
- ],
15927
- "pairsV"
15928
- ],
15929
- "pairIdx"
15930
- ],
15931
- "??",
15932
- [5, "0"]
15933
- ]
15934
- ],
15935
- [
15936
- 13,
15937
- "uStart",
15938
- [
15939
- 3,
15940
- [
15941
- 8,
15942
- [
15943
- 7,
15944
- [
15945
- 7,
15946
- "JaccardLayout",
15947
- "$"
15948
- ],
15949
- "rowOffsets"
15950
- ],
15951
- "u"
15952
- ],
15953
- "??",
15954
- [5, "0"]
15955
- ]
15956
- ],
15957
- [
15958
- 13,
15959
- "uEnd",
15960
- [
15961
- 3,
15962
- [
15963
- 8,
15964
- [
15965
- 7,
15966
- [
15967
- 7,
15968
- "JaccardLayout",
15969
- "$"
15970
- ],
15971
- "rowOffsets"
15972
- ],
15973
- [
15974
- 1,
15975
- "u",
15976
- "+",
15977
- [5, "1"]
15978
- ]
15979
- ],
15980
- "??",
15981
- [5, "0"]
15982
- ]
15983
- ],
15984
- [
15985
- 13,
15986
- "vStart",
15987
- [
15988
- 3,
15989
- [
15990
- 8,
15991
- [
15992
- 7,
15993
- [
15994
- 7,
15995
- "JaccardLayout",
15996
- "$"
15997
- ],
15998
- "rowOffsets"
15999
- ],
16000
- "v"
16001
- ],
16002
- "??",
16003
- [5, "0"]
16004
- ]
16005
- ],
16006
- [
16007
- 13,
16008
- "vEnd",
16009
- [
16010
- 3,
16011
- [
16012
- 8,
16013
- [
16014
- 7,
16015
- [
16016
- 7,
16017
- "JaccardLayout",
16018
- "$"
16019
- ],
16020
- "rowOffsets"
16021
- ],
16022
- [
16023
- 1,
16024
- "v",
16025
- "+",
16026
- [5, "1"]
16027
- ]
16028
- ],
16029
- "??",
16030
- [5, "0"]
16031
- ]
16032
- ],
16033
- [
16034
- 13,
16035
- "degU",
16036
- [
16037
- 1,
16038
- "uEnd",
16039
- "-",
16040
- "uStart"
16041
- ]
16042
- ],
16043
- [
16044
- 13,
16045
- "degV",
16046
- [
16047
- 1,
16048
- "vEnd",
16049
- "-",
16050
- "vStart"
16051
- ]
16052
- ],
16053
- [
16054
- 11,
16055
- [
16056
- 3,
16057
- [
16058
- 1,
16059
- "degU",
16060
- "===",
16061
- [5, "0"]
16062
- ],
16063
- "||",
16064
- [
16065
- 1,
16066
- "degV",
16067
- "===",
16068
- [5, "0"]
16069
- ]
16070
- ],
16071
- [0, [[
16072
- 2,
16073
- [
16074
- 8,
16075
- [
16076
- 7,
16077
- [
16078
- 7,
16079
- "JaccardLayout",
16080
- "$"
16081
- ],
16082
- "results"
16083
- ],
16084
- "pairIdx"
16085
- ],
16086
- "=",
16087
- [5, "0"]
16088
- ], [10]]]
16089
- ],
16090
- [
16091
- 12,
16092
- "intersection",
16093
- [5, "0"]
16094
- ],
16095
- [
16096
- 11,
16097
- [
16098
- 1,
16099
- "degU",
16100
- "<=",
16101
- "degV"
16102
- ],
16103
- [0, [[
16104
- 14,
16105
- [
16106
- 12,
16107
- "i",
16108
- "uStart"
16109
- ],
16110
- [
16111
- 1,
16112
- "i",
16113
- "<",
16114
- "uEnd"
16115
- ],
16116
- [
16117
- 2,
16118
- "i",
16119
- "=",
16120
- [
16121
- 1,
16122
- "i",
16123
- "+",
16124
- [5, "1"]
16125
- ]
16126
- ],
16127
- [0, [
16128
- [
16129
- 13,
16130
- "neighbour",
16131
- [
16132
- 3,
16133
- [
16134
- 8,
16135
- [
16136
- 7,
16137
- [
16138
- 7,
16139
- "JaccardLayout",
16140
- "$"
16141
- ],
16142
- "colIndices"
16143
- ],
16144
- "i"
16145
- ],
16146
- "??",
16147
- [5, "0"]
16148
- ]
16149
- ],
16150
- [
16151
- 12,
16152
- "lo",
16153
- "vStart"
16154
- ],
16155
- [
16156
- 12,
16157
- "hi",
16158
- "vEnd"
16159
- ],
16160
- [
16161
- 15,
16162
- [
16163
- 1,
16164
- "lo",
16165
- "<",
16166
- "hi"
16167
- ],
16168
- [0, [
16169
- [
16170
- 13,
16171
- "mid",
16172
- [
16173
- 1,
16174
- "lo",
16175
- "+",
16176
- [
16177
- 1,
16178
- [
16179
- 1,
16180
- "hi",
16181
- "-",
16182
- "lo"
16183
- ],
16184
- "/",
16185
- [5, "2"]
16186
- ]
16187
- ]
16188
- ],
16189
- [
16190
- 13,
16191
- "midVal",
16192
- [
16193
- 3,
16194
- [
16195
- 8,
16196
- [
16197
- 7,
16198
- [
16199
- 7,
16200
- "JaccardLayout",
16201
- "$"
16202
- ],
16203
- "colIndices"
16204
- ],
16205
- "mid"
16206
- ],
16207
- "??",
16208
- [5, "0"]
16209
- ]
16210
- ],
16211
- [
16212
- 11,
16213
- [
16214
- 1,
16215
- "midVal",
16216
- "===",
16217
- "neighbour"
16218
- ],
16219
- [0, [[
16220
- 2,
16221
- "intersection",
16222
- "=",
16223
- [
16224
- 1,
16225
- "intersection",
16226
- "+",
16227
- [5, "1"]
16228
- ]
16229
- ], [
16230
- 2,
16231
- "lo",
16232
- "=",
16233
- "hi"
16234
- ]]],
16235
- [
16236
- 11,
16237
- [
16238
- 1,
16239
- "midVal",
16240
- "<",
16241
- "neighbour"
16242
- ],
16243
- [0, [[
16244
- 2,
16245
- "lo",
16246
- "=",
16247
- [
16248
- 1,
16249
- "mid",
16250
- "+",
16251
- [5, "1"]
16252
- ]
16253
- ]]],
16254
- [0, [[
16255
- 2,
16256
- "hi",
16257
- "=",
16258
- "mid"
16259
- ]]]
16260
- ]
16261
- ]
16262
- ]]
16263
- ]
16264
- ]]
16265
- ]]],
16266
- [0, [[
16267
- 14,
16268
- [
16269
- 12,
16270
- "i",
16271
- "vStart"
16272
- ],
16273
- [
16274
- 1,
16275
- "i",
16276
- "<",
16277
- "vEnd"
16278
- ],
16279
- [
16280
- 2,
16281
- "i",
16282
- "=",
16283
- [
16284
- 1,
16285
- "i",
16286
- "+",
16287
- [5, "1"]
16288
- ]
16289
- ],
16290
- [0, [
16291
- [
16292
- 13,
16293
- "neighbour",
16294
- [
16295
- 3,
16296
- [
16297
- 8,
16298
- [
16299
- 7,
16300
- [
16301
- 7,
16302
- "JaccardLayout",
16303
- "$"
16304
- ],
16305
- "colIndices"
16306
- ],
16307
- "i"
16308
- ],
16309
- "??",
16310
- [5, "0"]
16311
- ]
16312
- ],
16313
- [
16314
- 12,
16315
- "lo",
16316
- "uStart"
16317
- ],
16318
- [
16319
- 12,
16320
- "hi",
16321
- "uEnd"
16322
- ],
16323
- [
16324
- 15,
16325
- [
16326
- 1,
16327
- "lo",
16328
- "<",
16329
- "hi"
16330
- ],
16331
- [0, [
16332
- [
16333
- 13,
16334
- "mid",
16335
- [
16336
- 1,
16337
- "lo",
16338
- "+",
16339
- [
16340
- 1,
16341
- [
16342
- 1,
16343
- "hi",
16344
- "-",
16345
- "lo"
16346
- ],
16347
- "/",
16348
- [5, "2"]
16349
- ]
16350
- ]
16351
- ],
16352
- [
16353
- 13,
16354
- "midVal",
16355
- [
16356
- 3,
16357
- [
16358
- 8,
16359
- [
16360
- 7,
16361
- [
16362
- 7,
16363
- "JaccardLayout",
16364
- "$"
16365
- ],
16366
- "colIndices"
16367
- ],
16368
- "mid"
16369
- ],
16370
- "??",
16371
- [5, "0"]
16372
- ]
16373
- ],
16374
- [
16375
- 11,
16376
- [
16377
- 1,
16378
- "midVal",
16379
- "===",
16380
- "neighbour"
16381
- ],
16382
- [0, [[
16383
- 2,
16384
- "intersection",
16385
- "=",
16386
- [
16387
- 1,
16388
- "intersection",
16389
- "+",
16390
- [5, "1"]
16391
- ]
16392
- ], [
16393
- 2,
16394
- "lo",
16395
- "=",
16396
- "hi"
16397
- ]]],
16398
- [
16399
- 11,
16400
- [
16401
- 1,
16402
- "midVal",
16403
- "<",
16404
- "neighbour"
16405
- ],
16406
- [0, [[
16407
- 2,
16408
- "lo",
16409
- "=",
16410
- [
16411
- 1,
16412
- "mid",
16413
- "+",
16414
- [5, "1"]
16415
- ]
16416
- ]]],
16417
- [0, [[
16418
- 2,
16419
- "hi",
16420
- "=",
16421
- "mid"
16422
- ]]]
16423
- ]
16424
- ]
16425
- ]]
16426
- ]
16427
- ]]
16428
- ]]]
16429
- ],
16430
- [
16431
- 13,
16432
- "unionSize",
16433
- [
16434
- 1,
16435
- [
16436
- 1,
16437
- "degU",
16438
- "+",
16439
- "degV"
16440
- ],
16441
- "-",
16442
- "intersection"
16443
- ]
16444
- ],
16445
- [
16446
- 2,
16447
- [
16448
- 8,
16449
- [
16450
- 7,
16451
- [
16452
- 7,
16453
- "JaccardLayout",
16454
- "$"
16455
- ],
16456
- "results"
16457
- ],
16458
- "pairIdx"
16459
- ],
16460
- "=",
16461
- [
16462
- 1,
16463
- "intersection",
16464
- "/",
16465
- "unionSize"
16466
- ]
16467
- ]
16468
- ]],
16469
- "externalNames": ["JaccardLayout"]
16470
- },
16471
- externals: () => ({ JaccardLayout })
16472
- }) && $.f)({});
16473
- /**
16474
- * Dispatch batch Jaccard on GPU.
16475
- *
16476
- * @param root - TypeGPU root instance
16477
- * @param csrBuffers - CSR matrix as typed buffers
16478
- * @param pairsU - First node of each pair (u32 array)
16479
- * @param pairsV - Second node of each pair (u32 array)
16480
- * @param results - Output Jaccard coefficients (f32 array, mutable)
16481
- * @param pairCount - Number of pairs to compute
16482
- */
16483
- function dispatchJaccard(root, csrBuffers, pairsU, pairsV, results, pairCount) {
16484
- const pipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createGuardedComputePipeline(jaccardPipeline), "pipeline");
16485
- const pairCountBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, pairCount).$usage("uniform"), "pairCountBuffer");
16486
- const bindGroup = root.createBindGroup(JaccardLayout, {
16487
- rowOffsets: csrBuffers.rowOffsets,
16488
- colIndices: csrBuffers.colIndices,
16489
- pairsU,
16490
- pairsV,
16491
- results,
16492
- pairCount: pairCountBuffer
16493
- });
16494
- pipeline.with(bindGroup).dispatchThreads(pairCount);
16495
- }
16496
- //#endregion
16497
- //#region src/gpu/kernels/degree-histogram/kernel.ts
16498
- /**
16499
- * TypeGPU compute kernel for degree computation.
16500
- *
16501
- * Computes degree per node from CSR row offsets.
16502
- * Note: Histogram aggregation requires atomic operations or CPU reduction.
16503
- *
16504
- * @module gpu/kernels/degree-histogram/kernel
16505
- */
16506
- /**
16507
- * Bind group layout for degree kernel.
16508
- */
16509
- var DegreeLayout = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(src_default.bindGroupLayout({
16510
- rowOffsets: { storage: data_exports.arrayOf(data_exports.u32) },
16511
- degrees: {
16512
- storage: data_exports.arrayOf(data_exports.u32),
16513
- access: "mutable"
16514
- },
16515
- nodeCount: { uniform: data_exports.u32 }
16516
- }), "DegreeLayout");
16517
- /**
16518
- * Degree compute pipeline: compute degree for each node.
16519
- *
16520
- * Each thread computes one node's degree from CSR row offsets:
16521
- * degree[node] = rowOffsets[node+1] - rowOffsets[node]
16522
- */
16523
- var degreePipeline = (($) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set($.f = ((node) => {
16524
- "use gpu";
16525
- if (node >= (DegreeLayout.$.nodeCount ?? 0)) return;
16526
- const start = DegreeLayout.$.rowOffsets[node] ?? 0;
16527
- const end = DegreeLayout.$.rowOffsets[__tsover_add(node, 1)] ?? 0;
16528
- const deg = __tsover_sub(end, start);
16529
- DegreeLayout.$.degrees[node] = deg;
16530
- }), {
16531
- v: 1,
16532
- name: "degreePipeline",
16533
- ast: {
16534
- "params": [{
16535
- "type": "i",
16536
- "name": "node"
16537
- }],
16538
- "body": [0, [
16539
- [
16540
- 13,
16541
- "n",
16542
- [
16543
- 3,
16544
- [
16545
- 7,
16546
- [
16547
- 7,
16548
- "DegreeLayout",
16549
- "$"
16550
- ],
16551
- "nodeCount"
16552
- ],
16553
- "??",
16554
- [5, "0"]
16555
- ]
16556
- ],
16557
- [
16558
- 11,
16559
- [
16560
- 1,
16561
- "node",
16562
- ">=",
16563
- "n"
16564
- ],
16565
- [0, [[10]]]
16566
- ],
16567
- [
16568
- 13,
16569
- "start",
16570
- [
16571
- 3,
16572
- [
16573
- 8,
16574
- [
16575
- 7,
16576
- [
16577
- 7,
16578
- "DegreeLayout",
16579
- "$"
16580
- ],
16581
- "rowOffsets"
16582
- ],
16583
- "node"
16584
- ],
16585
- "??",
16586
- [5, "0"]
16587
- ]
16588
- ],
16589
- [
16590
- 13,
16591
- "end",
16592
- [
16593
- 3,
16594
- [
16595
- 8,
16596
- [
16597
- 7,
16598
- [
16599
- 7,
16600
- "DegreeLayout",
16601
- "$"
16602
- ],
16603
- "rowOffsets"
16604
- ],
16605
- [
16606
- 1,
16607
- "node",
16608
- "+",
16609
- [5, "1"]
16610
- ]
16611
- ],
16612
- "??",
16613
- [5, "0"]
16614
- ]
16615
- ],
16616
- [
16617
- 13,
16618
- "deg",
16619
- [
16620
- 1,
16621
- "end",
16622
- "-",
16623
- "start"
16624
- ]
16625
- ],
16626
- [
16627
- 2,
16628
- [
16629
- 8,
16630
- [
16631
- 7,
16632
- [
16633
- 7,
16634
- "DegreeLayout",
16635
- "$"
16636
- ],
16637
- "degrees"
16638
- ],
16639
- "node"
16640
- ],
16641
- "=",
16642
- "deg"
16643
- ]
16644
- ]],
16645
- "externalNames": ["DegreeLayout"]
16646
- },
16647
- externals: () => ({ DegreeLayout })
16648
- }) && $.f)({});
16649
- /**
16650
- * Dispatch degree computation on GPU.
16651
- *
16652
- * Note: This computes per-node degrees. Histogram aggregation should be
16653
- * done on CPU or with a separate reduction kernel.
16654
- *
16655
- * @param root - TypeGPU root instance
16656
- * @param csrBuffers - CSR matrix as typed buffers
16657
- * @param degrees - Output degree array (u32, mutable)
16658
- * @param nodeCount - Number of nodes
16659
- */
16660
- function dispatchDegreeHistogram(root, csrBuffers, degrees, nodeCount) {
16661
- const pipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createGuardedComputePipeline(degreePipeline), "pipeline");
16662
- const nodeCountBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.u32, nodeCount).$usage("uniform"), "nodeCountBuffer");
16663
- const bindGroup = root.createBindGroup(DegreeLayout, {
16664
- rowOffsets: csrBuffers.rowOffsets,
16665
- degrees,
16666
- nodeCount: nodeCountBuffer
16667
- });
16668
- pipeline.with(bindGroup).dispatchThreads(nodeCount);
16669
- }
16670
- //#endregion
16671
- //#region src/gpu/operations.ts
16672
- /**
16673
- * Sparse matrix-vector multiply on GPU.
16674
- *
16675
- * Computes y = A * x where A is the graph adjacency matrix in CSR format.
16676
- *
16677
- * @param graph - Input graph
16678
- * @param x - Input vector (must have length = graph.nodeCount)
16679
- * @param options - Compute options (backend, root, signal)
16680
- * @returns Result vector y
16681
- */
16682
- async function gpuSpmv(graph, x, options) {
16683
- const nodeCount = graph.nodeCount;
16684
- if (x.length !== nodeCount) throw new Error(`Input vector length (${String(x.length)}) must match node count (${String(nodeCount)})`);
16685
- const cpuFn = () => {
16686
- const { csr } = graphToCSR(graph);
16687
- const y = new Float32Array(nodeCount);
16688
- for (let row = 0; row < nodeCount; row++) {
16689
- const start = csr.rowOffsets[row] ?? 0;
16690
- const end = csr.rowOffsets[row + 1] ?? 0;
16691
- let sum = 0;
16692
- for (let i = start; i < end; i++) {
16693
- const col = csr.colIndices[i] ?? 0;
16694
- const weight = csr.values?.[i] ?? 1;
16695
- sum += weight * (x[col] ?? 0);
16696
- }
16697
- y[row] = sum;
16698
- }
16699
- return y;
16700
- };
16701
- const gpuFn = async (root) => {
16702
- const { csr } = graphToCSR(graph);
16703
- const csrBuffers = csrToTypedBuffers(root, csr);
16704
- const xBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, nodeCount), Array.from(x)).$usage("storage"), "xBuffer");
16705
- const yBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, nodeCount)).$usage("storage"), "yBuffer");
16706
- dispatchSpmv(root, csrBuffers, xBuffer, yBuffer, nodeCount, csr.values !== void 0);
16707
- const result = await yBuffer.read();
16708
- return new Float32Array(result);
16709
- };
16710
- return withBackend({
16711
- backend: options?.backend,
16712
- root: options?.root,
16713
- signal: options?.signal
16714
- }, cpuFn, gpuFn);
16715
- }
16716
- /**
16717
- * PageRank via GPU-accelerated power iteration.
16718
- *
16719
- * @param graph - Input graph (will be converted to transpose CSR for in-edges)
16720
- * @param options - Compute options plus damping factor and iteration count
16721
- * @returns PageRank scores for each node
16722
- */
16723
- async function gpuPageRank(graph, options) {
16724
- const nodeCount = graph.nodeCount;
16725
- const damping = options?.damping ?? .85;
16726
- const iterations = options?.iterations ?? 20;
16727
- const cpuFn = () => {
16728
- const { csr } = graphToCSR(graph);
16729
- const ranks = new Float32Array(nodeCount).fill(1 / nodeCount);
16730
- const outDegrees = new Uint32Array(nodeCount);
16731
- for (let i = 0; i < nodeCount; i++) outDegrees[i] = (csr.rowOffsets[i + 1] ?? 0) - (csr.rowOffsets[i] ?? 0);
16732
- for (let iter = 0; iter < iterations; iter++) {
16733
- const newRanks = new Float32Array(nodeCount);
16734
- for (let v = 0; v < nodeCount; v++) {
16735
- const start = csr.rowOffsets[v] ?? 0;
16736
- const end = csr.rowOffsets[v + 1] ?? 0;
16737
- let contribution = 0;
16738
- for (let i = start; i < end; i++) {
16739
- const source = csr.colIndices[i] ?? 0;
16740
- const deg = outDegrees[source] ?? 0;
16741
- if (deg > 0) contribution += (ranks[source] ?? 0) / deg;
16742
- }
16743
- newRanks[v] = (1 - damping) / nodeCount + damping * contribution;
16744
- }
16745
- ranks.set(newRanks);
16746
- }
16747
- return ranks;
16748
- };
16749
- const gpuFn = async (root) => {
16750
- const { csr } = graphToCSR(graph);
16751
- const csrBuffers = csrToTypedBuffers(root, csr);
16752
- const outDegrees = new Uint32Array(nodeCount);
16753
- for (let i = 0; i < nodeCount; i++) outDegrees[i] = (csr.rowOffsets[i + 1] ?? 0) - (csr.rowOffsets[i] ?? 0);
16754
- const outDegreesBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, nodeCount), Array.from(outDegrees)).$usage("storage"), "outDegreesBuffer");
16755
- const ranksBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, nodeCount), Array.from(new Float32Array(nodeCount).fill(1 / nodeCount))).$usage("storage"), "ranksBuffer");
16756
- const newRanksBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, nodeCount)).$usage("storage"), "newRanksBuffer");
16757
- for (let iter = 0; iter < iterations; iter++) {
16758
- dispatchPagerank(root, csrBuffers, ranksBuffer, outDegreesBuffer, newRanksBuffer, nodeCount, damping);
16759
- const newRanks = await newRanksBuffer.read();
16760
- ranksBuffer.write(Array.from(newRanks));
16761
- }
16762
- const result = await ranksBuffer.read();
16763
- return new Float32Array(result);
16764
- };
16765
- return withBackend({
16766
- backend: options?.backend,
16767
- root: options?.root,
16768
- signal: options?.signal
16769
- }, cpuFn, gpuFn);
16770
- }
16771
- /**
16772
- * Batch Jaccard similarity for node pairs on GPU.
16773
- *
16774
- * @param graph - Input graph
16775
- * @param pairs - Array of [u, v] node ID pairs
16776
- * @param options - Compute options
16777
- * @returns Jaccard coefficients for each pair
16778
- */
16779
- async function gpuJaccardBatch(graph, pairs, options) {
16780
- const pairCount = pairs.length;
16781
- const { indexMap } = graphToCSR(graph);
16782
- const cpuFn = () => {
16783
- const { csr } = graphToCSR(graph);
16784
- const results = new Float32Array(pairCount);
16785
- for (let p = 0; p < pairCount; p++) {
16786
- const pair = pairs[p];
16787
- if (pair === void 0) continue;
16788
- const [u, v] = pair;
16789
- const uIdx = indexMap.nodeToIndex.get(u);
16790
- const vIdx = indexMap.nodeToIndex.get(v);
16791
- if (uIdx === void 0 || vIdx === void 0) {
16792
- results[p] = 0;
16793
- continue;
16794
- }
16795
- const uStart = csr.rowOffsets[uIdx] ?? 0;
16796
- const uEnd = csr.rowOffsets[uIdx + 1] ?? 0;
16797
- const vStart = csr.rowOffsets[vIdx] ?? 0;
16798
- const vEnd = csr.rowOffsets[vIdx + 1] ?? 0;
16799
- const uNeighbours = new Set(Array.from(csr.colIndices.slice(uStart, uEnd)));
16800
- const vNeighbours = new Set(Array.from(csr.colIndices.slice(vStart, vEnd)));
16801
- let intersection = 0;
16802
- for (const n of uNeighbours) if (vNeighbours.has(n)) intersection++;
16803
- const union = uNeighbours.size + vNeighbours.size - intersection;
16804
- results[p] = union > 0 ? intersection / union : 0;
16805
- }
16806
- return results;
16807
- };
16808
- const gpuFn = async (root) => {
16809
- const { csr } = graphToCSR(graph);
16810
- const csrBuffers = csrToTypedBuffers(root, csr);
16811
- const pairsU = new Uint32Array(pairCount);
16812
- const pairsV = new Uint32Array(pairCount);
16813
- for (let i = 0; i < pairCount; i++) {
16814
- const pair = pairs[i];
16815
- if (pair === void 0) continue;
16816
- const uIdx = indexMap.nodeToIndex.get(pair[0]);
16817
- const vIdx = indexMap.nodeToIndex.get(pair[1]);
16818
- pairsU[i] = uIdx ?? 0;
16819
- pairsV[i] = vIdx ?? 0;
16820
- }
16821
- const pairsUBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, pairCount), Array.from(pairsU)).$usage("storage"), "pairsUBuffer");
16822
- const pairsVBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, pairCount), Array.from(pairsV)).$usage("storage"), "pairsVBuffer");
16823
- const resultsBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.f32, pairCount)).$usage("storage"), "resultsBuffer");
16824
- dispatchJaccard(root, csrBuffers, pairsUBuffer, pairsVBuffer, resultsBuffer, pairCount);
16825
- const result = await resultsBuffer.read();
16826
- return new Float32Array(result);
16827
- };
16828
- return withBackend({
16829
- backend: options?.backend,
16830
- root: options?.root,
16831
- signal: options?.signal
16832
- }, cpuFn, gpuFn);
16833
- }
16834
- /**
16835
- * BFS level assignment from source node on GPU.
16836
- *
16837
- * Note: Full GPU BFS requires atomics not yet available in TypeGPU.
16838
- * This implementation uses CPU for now but maintains the API.
16839
- *
16840
- * @param graph - Input graph
16841
- * @param source - Source node ID
16842
- * @param options - Compute options
16843
- * @returns BFS level for each node (-1 for unreachable)
16844
- */
16845
- async function gpuBfsLevels(graph, source, options) {
16846
- const nodeCount = graph.nodeCount;
16847
- const { indexMap } = graphToCSR(graph);
16848
- const cpuFn = () => {
16849
- const { csr } = graphToCSR(graph);
16850
- const levels = new Int32Array(nodeCount).fill(-1);
16851
- const visited = new Uint8Array(nodeCount);
16852
- const sourceIndex = indexMap.nodeToIndex.get(source);
16853
- if (sourceIndex === void 0) throw new Error(`Source node ${source} not found in graph`);
16854
- const queue = [sourceIndex];
16855
- levels[sourceIndex] = 0;
16856
- visited[sourceIndex] = 1;
16857
- while (queue.length > 0) {
16858
- const current = queue.shift();
16859
- if (current === void 0) break;
16860
- const currentLevel = levels[current] ?? 0;
16861
- const start = csr.rowOffsets[current] ?? 0;
16862
- const end = csr.rowOffsets[current + 1] ?? 0;
16863
- for (let i = start; i < end; i++) {
16864
- const neighbour = csr.colIndices[i] ?? 0;
16865
- if (visited[neighbour] === 0) {
16866
- visited[neighbour] = 1;
16867
- levels[neighbour] = currentLevel + 1;
16868
- queue.push(neighbour);
16869
- }
16870
- }
16871
- }
16872
- return levels;
16873
- };
16874
- const gpuFn = (_root) => {
16875
- return cpuFn();
16876
- };
16877
- return withBackend({
16878
- backend: options?.backend,
16879
- root: options?.root,
16880
- signal: options?.signal
16881
- }, cpuFn, gpuFn);
16882
- }
16883
- /**
16884
- * Degree histogram and statistics on GPU.
16885
- *
16886
- * @param graph - Input graph
16887
- * @param options - Compute options
16888
- * @returns Degree statistics with histogram
16889
- */
16890
- async function gpuDegreeHistogram(graph, options) {
16891
- const nodeCount = graph.nodeCount;
16892
- const cpuFn = () => {
16893
- const { csr } = graphToCSR(graph);
16894
- const degrees = new Uint32Array(nodeCount);
16895
- for (let i = 0; i < nodeCount; i++) degrees[i] = (csr.rowOffsets[i + 1] ?? 0) - (csr.rowOffsets[i] ?? 0);
16896
- const max = degrees.length > 0 ? Math.max(...degrees) : 0;
16897
- const histogram = Array.from({ length: max + 1 }, () => 0);
16898
- let sum = 0;
16899
- let min = Infinity;
16900
- for (const d of degrees) {
16901
- histogram[d] = (histogram[d] ?? 0) + 1;
16902
- sum += d;
16903
- if (d < min) min = d;
16904
- }
16905
- if (degrees.length === 0) min = 0;
16906
- return {
16907
- min,
16908
- max,
16909
- mean: nodeCount > 0 ? sum / nodeCount : 0,
16910
- histogram
16911
- };
16912
- };
16913
- const gpuFn = async (root) => {
16914
- const { csr } = graphToCSR(graph);
16915
- const csrBuffers = csrToTypedBuffers(root, csr);
16916
- const degreesBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? ((a) => a))(root.createBuffer(data_exports.arrayOf(data_exports.u32, nodeCount)).$usage("storage"), "degreesBuffer");
16917
- dispatchDegreeHistogram(root, csrBuffers, degreesBuffer, nodeCount);
16918
- const degrees = await degreesBuffer.read();
16919
- const max = degrees.length > 0 ? Math.max(...degrees) : 0;
16920
- const histogram = Array.from({ length: max + 1 }, () => 0);
16921
- let sum = 0;
16922
- let min = Infinity;
16923
- for (const d of degrees) {
16924
- histogram[d] = (histogram[d] ?? 0) + 1;
16925
- sum += d;
16926
- if (d < min) min = d;
16927
- }
16928
- if (degrees.length === 0) min = 0;
16929
- return {
16930
- min,
16931
- max,
16932
- mean: nodeCount > 0 ? sum / nodeCount : 0,
16933
- histogram
16934
- };
16935
- };
16936
- return withBackend({
16937
- backend: options?.backend,
16938
- root: options?.root,
16939
- signal: options?.signal
16940
- }, cpuFn, gpuFn);
16941
- }
16942
- //#endregion
16943
- export { gpuSpmv as a, initGPUFromDevice as c, isWebGPUAvailable as d, csrToTypedBuffers as f, gpuPageRank as i, assertWebGPUAvailable as l, GPUNotAvailableError as m, gpuDegreeHistogram as n, withBackend as o, graphToCSR as p, gpuJaccardBatch as r, initGPU as s, gpuBfsLevels as t, detectWebGPU as u };
14918
+ });
16944
14919
 
16945
- //# sourceMappingURL=gpu-CHiCN0wa.js.map
14920
+ //# sourceMappingURL=typegpu-Dq5FfUB8.cjs.map