graphwise 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +41 -0
  2. package/dist/expansion/base.d.ts +12 -0
  3. package/dist/expansion/base.d.ts.map +1 -0
  4. package/dist/expansion/base.unit.test.d.ts +2 -0
  5. package/dist/expansion/base.unit.test.d.ts.map +1 -0
  6. package/dist/expansion/dome.d.ts +16 -0
  7. package/dist/expansion/dome.d.ts.map +1 -0
  8. package/dist/expansion/dome.unit.test.d.ts +2 -0
  9. package/dist/expansion/dome.unit.test.d.ts.map +1 -0
  10. package/dist/expansion/edge.d.ts +15 -0
  11. package/dist/expansion/edge.d.ts.map +1 -0
  12. package/dist/expansion/edge.unit.test.d.ts +2 -0
  13. package/dist/expansion/edge.unit.test.d.ts.map +1 -0
  14. package/dist/expansion/hae.d.ts +22 -0
  15. package/dist/expansion/hae.d.ts.map +1 -0
  16. package/dist/expansion/hae.unit.test.d.ts +2 -0
  17. package/dist/expansion/hae.unit.test.d.ts.map +1 -0
  18. package/dist/expansion/index.d.ts +22 -0
  19. package/dist/expansion/index.d.ts.map +1 -0
  20. package/dist/expansion/maze.d.ts +25 -0
  21. package/dist/expansion/maze.d.ts.map +1 -0
  22. package/dist/expansion/maze.unit.test.d.ts +2 -0
  23. package/dist/expansion/maze.unit.test.d.ts.map +1 -0
  24. package/dist/expansion/pipe.d.ts +15 -0
  25. package/dist/expansion/pipe.d.ts.map +1 -0
  26. package/dist/expansion/pipe.unit.test.d.ts +2 -0
  27. package/dist/expansion/pipe.unit.test.d.ts.map +1 -0
  28. package/dist/expansion/reach.d.ts +26 -0
  29. package/dist/expansion/reach.d.ts.map +1 -0
  30. package/dist/expansion/reach.unit.test.d.ts +2 -0
  31. package/dist/expansion/reach.unit.test.d.ts.map +1 -0
  32. package/dist/expansion/sage.d.ts +24 -0
  33. package/dist/expansion/sage.d.ts.map +1 -0
  34. package/dist/expansion/sage.unit.test.d.ts +2 -0
  35. package/dist/expansion/sage.unit.test.d.ts.map +1 -0
  36. package/dist/expansion/types.d.ts +105 -0
  37. package/dist/expansion/types.d.ts.map +1 -0
  38. package/dist/extraction/ego-network.d.ts +32 -0
  39. package/dist/extraction/ego-network.d.ts.map +1 -0
  40. package/dist/extraction/ego-network.unit.test.d.ts +5 -0
  41. package/dist/extraction/ego-network.unit.test.d.ts.map +1 -0
  42. package/dist/extraction/index.d.ts +20 -0
  43. package/dist/extraction/index.d.ts.map +1 -0
  44. package/dist/extraction/induced-subgraph.d.ts +19 -0
  45. package/dist/extraction/induced-subgraph.d.ts.map +1 -0
  46. package/dist/extraction/induced-subgraph.unit.test.d.ts +5 -0
  47. package/dist/extraction/induced-subgraph.unit.test.d.ts.map +1 -0
  48. package/dist/extraction/k-core.d.ts +24 -0
  49. package/dist/extraction/k-core.d.ts.map +1 -0
  50. package/dist/extraction/k-core.unit.test.d.ts +5 -0
  51. package/dist/extraction/k-core.unit.test.d.ts.map +1 -0
  52. package/dist/extraction/motif.d.ts +50 -0
  53. package/dist/extraction/motif.d.ts.map +1 -0
  54. package/dist/extraction/motif.unit.test.d.ts +5 -0
  55. package/dist/extraction/motif.unit.test.d.ts.map +1 -0
  56. package/dist/extraction/node-filter.d.ts +35 -0
  57. package/dist/extraction/node-filter.d.ts.map +1 -0
  58. package/dist/extraction/node-filter.unit.test.d.ts +5 -0
  59. package/dist/extraction/node-filter.unit.test.d.ts.map +1 -0
  60. package/dist/extraction/truss.d.ts +41 -0
  61. package/dist/extraction/truss.d.ts.map +1 -0
  62. package/dist/extraction/truss.unit.test.d.ts +5 -0
  63. package/dist/extraction/truss.unit.test.d.ts.map +1 -0
  64. package/dist/gpu/context.d.ts +118 -0
  65. package/dist/gpu/context.d.ts.map +1 -0
  66. package/dist/gpu/context.unit.test.d.ts +2 -0
  67. package/dist/gpu/context.unit.test.d.ts.map +1 -0
  68. package/dist/gpu/csr.d.ts +97 -0
  69. package/dist/gpu/csr.d.ts.map +1 -0
  70. package/dist/gpu/csr.unit.test.d.ts +2 -0
  71. package/dist/gpu/csr.unit.test.d.ts.map +1 -0
  72. package/dist/gpu/detect.d.ts +25 -0
  73. package/dist/gpu/detect.d.ts.map +1 -0
  74. package/dist/gpu/detect.unit.test.d.ts +2 -0
  75. package/dist/gpu/detect.unit.test.d.ts.map +1 -0
  76. package/dist/gpu/index.cjs +6 -0
  77. package/dist/gpu/index.d.ts +11 -0
  78. package/dist/gpu/index.d.ts.map +1 -0
  79. package/dist/gpu/index.js +2 -0
  80. package/dist/gpu/types.d.ts +50 -0
  81. package/dist/gpu/types.d.ts.map +1 -0
  82. package/dist/gpu-BJRVYBjx.cjs +338 -0
  83. package/dist/gpu-BJRVYBjx.cjs.map +1 -0
  84. package/dist/gpu-BveuXugy.js +315 -0
  85. package/dist/gpu-BveuXugy.js.map +1 -0
  86. package/dist/graph/adjacency-map.d.ts +95 -0
  87. package/dist/graph/adjacency-map.d.ts.map +1 -0
  88. package/dist/graph/adjacency-map.unit.test.d.ts +2 -0
  89. package/dist/graph/adjacency-map.unit.test.d.ts.map +1 -0
  90. package/dist/graph/index.cjs +3 -0
  91. package/dist/graph/index.d.ts +9 -0
  92. package/dist/graph/index.d.ts.map +1 -0
  93. package/dist/graph/index.js +2 -0
  94. package/dist/graph/interfaces.d.ts +125 -0
  95. package/dist/graph/interfaces.d.ts.map +1 -0
  96. package/dist/graph/types.d.ts +72 -0
  97. package/dist/graph/types.d.ts.map +1 -0
  98. package/dist/graph-DLWiziLB.js +222 -0
  99. package/dist/graph-DLWiziLB.js.map +1 -0
  100. package/dist/graph-az06J1YV.cjs +227 -0
  101. package/dist/graph-az06J1YV.cjs.map +1 -0
  102. package/dist/index/index.cjs +1404 -0
  103. package/dist/index/index.cjs.map +1 -0
  104. package/dist/index/index.js +1356 -0
  105. package/dist/index/index.js.map +1 -0
  106. package/dist/index.d.ts +15 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/kmeans-B0HEOU6k.cjs +234 -0
  109. package/dist/kmeans-B0HEOU6k.cjs.map +1 -0
  110. package/dist/kmeans-DgbsOznU.js +223 -0
  111. package/dist/kmeans-DgbsOznU.js.map +1 -0
  112. package/dist/ranking/baselines/shortest.d.ts +15 -0
  113. package/dist/ranking/baselines/shortest.d.ts.map +1 -0
  114. package/dist/ranking/baselines/shortest.unit.test.d.ts +2 -0
  115. package/dist/ranking/baselines/shortest.unit.test.d.ts.map +1 -0
  116. package/dist/ranking/baselines/types.d.ts +30 -0
  117. package/dist/ranking/baselines/types.d.ts.map +1 -0
  118. package/dist/ranking/index.d.ts +15 -0
  119. package/dist/ranking/index.d.ts.map +1 -0
  120. package/dist/ranking/mi/adamic-adar.d.ts +13 -0
  121. package/dist/ranking/mi/adamic-adar.d.ts.map +1 -0
  122. package/dist/ranking/mi/adaptive.d.ts +16 -0
  123. package/dist/ranking/mi/adaptive.d.ts.map +1 -0
  124. package/dist/ranking/mi/etch.d.ts +7 -0
  125. package/dist/ranking/mi/etch.d.ts.map +1 -0
  126. package/dist/ranking/mi/index.d.ts +18 -0
  127. package/dist/ranking/mi/index.d.ts.map +1 -0
  128. package/dist/ranking/mi/jaccard.d.ts +13 -0
  129. package/dist/ranking/mi/jaccard.d.ts.map +1 -0
  130. package/dist/ranking/mi/mi-variants.unit.test.d.ts +2 -0
  131. package/dist/ranking/mi/mi-variants.unit.test.d.ts.map +1 -0
  132. package/dist/ranking/mi/notch.d.ts +7 -0
  133. package/dist/ranking/mi/notch.d.ts.map +1 -0
  134. package/dist/ranking/mi/scale.d.ts +7 -0
  135. package/dist/ranking/mi/scale.d.ts.map +1 -0
  136. package/dist/ranking/mi/skew.d.ts +7 -0
  137. package/dist/ranking/mi/skew.d.ts.map +1 -0
  138. package/dist/ranking/mi/span.d.ts +7 -0
  139. package/dist/ranking/mi/span.d.ts.map +1 -0
  140. package/dist/ranking/mi/types.d.ts +35 -0
  141. package/dist/ranking/mi/types.d.ts.map +1 -0
  142. package/dist/ranking/parse.d.ts +56 -0
  143. package/dist/ranking/parse.d.ts.map +1 -0
  144. package/dist/ranking/parse.unit.test.d.ts +2 -0
  145. package/dist/ranking/parse.unit.test.d.ts.map +1 -0
  146. package/dist/schemas/define.d.ts +18 -0
  147. package/dist/schemas/define.d.ts.map +1 -0
  148. package/dist/schemas/define.unit.test.d.ts +2 -0
  149. package/dist/schemas/define.unit.test.d.ts.map +1 -0
  150. package/dist/schemas/graph.d.ts +85 -0
  151. package/dist/schemas/graph.d.ts.map +1 -0
  152. package/dist/schemas/graph.unit.test.d.ts +2 -0
  153. package/dist/schemas/graph.unit.test.d.ts.map +1 -0
  154. package/dist/schemas/index.cjs +3791 -0
  155. package/dist/schemas/index.cjs.map +1 -0
  156. package/dist/schemas/index.d.ts +3 -0
  157. package/dist/schemas/index.d.ts.map +1 -0
  158. package/dist/schemas/index.js +3782 -0
  159. package/dist/schemas/index.js.map +1 -0
  160. package/dist/seeds/grasp.d.ts +79 -0
  161. package/dist/seeds/grasp.d.ts.map +1 -0
  162. package/dist/seeds/grasp.unit.test.d.ts +2 -0
  163. package/dist/seeds/grasp.unit.test.d.ts.map +1 -0
  164. package/dist/seeds/index.cjs +4 -0
  165. package/dist/seeds/index.d.ts +10 -0
  166. package/dist/seeds/index.d.ts.map +1 -0
  167. package/dist/seeds/index.js +2 -0
  168. package/dist/seeds/stratified.d.ts +85 -0
  169. package/dist/seeds/stratified.d.ts.map +1 -0
  170. package/dist/seeds/stratified.unit.test.d.ts +2 -0
  171. package/dist/seeds/stratified.unit.test.d.ts.map +1 -0
  172. package/dist/seeds-B6J9oJfU.cjs +404 -0
  173. package/dist/seeds-B6J9oJfU.cjs.map +1 -0
  174. package/dist/seeds-UNZxqm_U.js +393 -0
  175. package/dist/seeds-UNZxqm_U.js.map +1 -0
  176. package/dist/structures/index.cjs +3 -0
  177. package/dist/structures/index.d.ts +3 -0
  178. package/dist/structures/index.d.ts.map +1 -0
  179. package/dist/structures/index.js +2 -0
  180. package/dist/structures/priority-queue.d.ts +59 -0
  181. package/dist/structures/priority-queue.d.ts.map +1 -0
  182. package/dist/structures/priority-queue.unit.test.d.ts +2 -0
  183. package/dist/structures/priority-queue.unit.test.d.ts.map +1 -0
  184. package/dist/structures-BPfhfqNP.js +133 -0
  185. package/dist/structures-BPfhfqNP.js.map +1 -0
  186. package/dist/structures-CJ_S_7fs.cjs +138 -0
  187. package/dist/structures-CJ_S_7fs.cjs.map +1 -0
  188. package/dist/traversal/bfs.d.ts +50 -0
  189. package/dist/traversal/bfs.d.ts.map +1 -0
  190. package/dist/traversal/bfs.unit.test.d.ts +2 -0
  191. package/dist/traversal/bfs.unit.test.d.ts.map +1 -0
  192. package/dist/traversal/dfs.d.ts +50 -0
  193. package/dist/traversal/dfs.d.ts.map +1 -0
  194. package/dist/traversal/dfs.unit.test.d.ts +2 -0
  195. package/dist/traversal/dfs.unit.test.d.ts.map +1 -0
  196. package/dist/traversal/index.cjs +6 -0
  197. package/dist/traversal/index.d.ts +11 -0
  198. package/dist/traversal/index.d.ts.map +1 -0
  199. package/dist/traversal/index.js +2 -0
  200. package/dist/traversal-CQCjUwUJ.js +149 -0
  201. package/dist/traversal-CQCjUwUJ.js.map +1 -0
  202. package/dist/traversal-QeHaNUWn.cjs +172 -0
  203. package/dist/traversal-QeHaNUWn.cjs.map +1 -0
  204. package/dist/utils/clustering-coefficient.d.ts +38 -0
  205. package/dist/utils/clustering-coefficient.d.ts.map +1 -0
  206. package/dist/utils/clustering-coefficient.unit.test.d.ts +2 -0
  207. package/dist/utils/clustering-coefficient.unit.test.d.ts.map +1 -0
  208. package/dist/utils/entropy.d.ts +58 -0
  209. package/dist/utils/entropy.d.ts.map +1 -0
  210. package/dist/utils/entropy.unit.test.d.ts +2 -0
  211. package/dist/utils/entropy.unit.test.d.ts.map +1 -0
  212. package/dist/utils/index.cjs +13 -0
  213. package/dist/utils/index.d.ts +9 -0
  214. package/dist/utils/index.d.ts.map +1 -0
  215. package/dist/utils/index.js +3 -0
  216. package/dist/utils/kmeans.d.ts +73 -0
  217. package/dist/utils/kmeans.d.ts.map +1 -0
  218. package/dist/utils/kmeans.unit.test.d.ts +2 -0
  219. package/dist/utils/kmeans.unit.test.d.ts.map +1 -0
  220. package/dist/utils-Q_akvlMn.js +164 -0
  221. package/dist/utils-Q_akvlMn.js.map +1 -0
  222. package/dist/utils-spZa1ZvS.cjs +205 -0
  223. package/dist/utils-spZa1ZvS.cjs.map +1 -0
  224. package/package.json +136 -8
@@ -0,0 +1,338 @@
1
+ //#region src/gpu/detect.ts
2
+ /**
3
+ * Detect WebGPU availability in the current environment.
4
+ *
5
+ * Checks for:
6
+ * - Browser: navigator.gpu
7
+ * - Node.js: global GPU constructor (Node.js 21+ with --experimental-webgpu)
8
+ * - Deno: global GPU constructor
9
+ *
10
+ * @returns Detection result with availability status and reason
11
+ */
12
+ function detectWebGPU() {
13
+ if (typeof navigator !== "undefined" && "gpu" in navigator) return { available: true };
14
+ if (typeof globalThis !== "undefined" && "GPU" in globalThis) return { available: true };
15
+ const reasons = [];
16
+ if (typeof navigator === "undefined" && typeof globalThis === "undefined") reasons.push("no global scope detected");
17
+ else if (typeof navigator !== "undefined" && !("gpu" in navigator)) reasons.push("navigator.gpu not present (browser may not support WebGPU)");
18
+ else if (typeof globalThis !== "undefined" && !("GPU" in globalThis)) reasons.push("global GPU not present (Node.js requires v21+ with --experimental-webgpu flag)");
19
+ return {
20
+ available: false,
21
+ reason: reasons.length > 0 ? reasons.join("; ") : "unknown environment"
22
+ };
23
+ }
24
+ //#endregion
25
+ //#region src/gpu/context.ts
26
+ /**
27
+ * GPU context management for WebGPU compute operations.
28
+ *
29
+ * Provides device acquisition, buffer pooling, and shader compilation
30
+ * with caching for efficient GPU resource management.
31
+ */
32
+ /**
33
+ * Type guard to check if an object has a WebGPU-compatible requestAdapter method.
34
+ */
35
+ function hasRequestAdapter(obj) {
36
+ if (typeof obj !== "object" || obj === null) return false;
37
+ if (!("requestAdapter" in obj)) return false;
38
+ const descriptor = Object.getOwnPropertyDescriptor(obj, "requestAdapter");
39
+ return descriptor !== void 0 && typeof descriptor.value === "function";
40
+ }
41
+ /**
42
+ * Manages GPU device, buffers, and compiled shaders.
43
+ *
44
+ * Use the singleton pattern via getGPUContext() for most use cases,
45
+ * or create separate contexts for isolated GPU resource pools.
46
+ */
47
+ var GPUContext = class {
48
+ device = null;
49
+ shaderCache = /* @__PURE__ */ new Map();
50
+ bufferPool = [];
51
+ destroyedBuffers = /* @__PURE__ */ new WeakSet();
52
+ /**
53
+ * Check if this context has an acquired GPU device.
54
+ */
55
+ get isReady() {
56
+ return this.device !== null;
57
+ }
58
+ /**
59
+ * Get the GPU device, throwing if not acquired.
60
+ */
61
+ getDevice() {
62
+ if (this.device === null) throw new Error("GPUContext not initialised. Call acquireDevice() first.");
63
+ return this.device;
64
+ }
65
+ /**
66
+ * Acquire a GPU device from the adapter.
67
+ *
68
+ * @param options - Context creation options
69
+ * @returns true if device was acquired successfully
70
+ * @throws Error if WebGPU is unavailable or device request fails
71
+ */
72
+ async acquireDevice(options = {}) {
73
+ const detection = detectWebGPU();
74
+ if (!detection.available) throw new Error(`WebGPU unavailable: ${detection.reason ?? "unknown reason"}`);
75
+ let adapter = null;
76
+ if (typeof navigator !== "undefined" && "gpu" in navigator) adapter = await navigator.gpu.requestAdapter({ powerPreference: options.powerPreference });
77
+ if (adapter === null && typeof globalThis !== "undefined" && "GPU" in globalThis) {
78
+ const gpuDescriptor = Object.getOwnPropertyDescriptor(globalThis, "gpu");
79
+ if (gpuDescriptor !== void 0 && hasRequestAdapter(gpuDescriptor.value)) adapter = await gpuDescriptor.value.requestAdapter({ powerPreference: options.powerPreference });
80
+ }
81
+ if (adapter === null) throw new Error("No GPU adapter found");
82
+ this.device = await adapter.requestDevice();
83
+ this.device.lost.then((info) => {
84
+ console.error(`GPU device lost: ${info.message}`);
85
+ this.device = null;
86
+ this.clearCache();
87
+ });
88
+ return true;
89
+ }
90
+ /**
91
+ * Compile a WGSL shader, using cache if available.
92
+ *
93
+ * @param code - WGSL shader code
94
+ * @param key - Optional cache key (defaults to code hash)
95
+ * @returns Compiled shader module
96
+ */
97
+ compileShader(code, key) {
98
+ const cacheKey = key ?? this.hashCode(code);
99
+ const cached = this.shaderCache.get(cacheKey);
100
+ if (cached?.code === code) return cached.module;
101
+ const module = this.getDevice().createShaderModule({ code });
102
+ this.shaderCache.set(cacheKey, {
103
+ module,
104
+ code
105
+ });
106
+ return module;
107
+ }
108
+ /**
109
+ * Create a GPU buffer, optionally reusing from pool.
110
+ *
111
+ * @param size - Buffer size in bytes
112
+ * @param usage - Buffer usage flags
113
+ * @returns GPU buffer
114
+ */
115
+ createBuffer(size, usage) {
116
+ for (let i = 0; i < this.bufferPool.length; i++) {
117
+ const buffer = this.bufferPool[i];
118
+ if (buffer !== void 0 && !this.destroyedBuffers.has(buffer) && buffer.size >= size && (buffer.usage & usage) === usage) {
119
+ this.bufferPool.splice(i, 1);
120
+ return buffer;
121
+ }
122
+ }
123
+ return this.getDevice().createBuffer({
124
+ size,
125
+ usage
126
+ });
127
+ }
128
+ /**
129
+ * Return a buffer to the pool for reuse.
130
+ *
131
+ * @param buffer - Buffer to recycle
132
+ */
133
+ recycleBuffer(buffer) {
134
+ if (!this.destroyedBuffers.has(buffer)) this.bufferPool.push(buffer);
135
+ }
136
+ /**
137
+ * Mark a buffer as destroyed (call before GPUBuffer.destroy()).
138
+ *
139
+ * @param buffer - Buffer to mark as destroyed
140
+ */
141
+ markDestroyed(buffer) {
142
+ this.destroyedBuffers.add(buffer);
143
+ }
144
+ /**
145
+ * Create a compute pipeline from shader code.
146
+ *
147
+ * @param code - WGSL compute shader code
148
+ * @param entryPoint - Entry point function name
149
+ * @returns Compute pipeline
150
+ */
151
+ createComputePipeline(code, entryPoint = "main") {
152
+ const device = this.getDevice();
153
+ const module = this.compileShader(code);
154
+ return device.createComputePipeline({
155
+ layout: "auto",
156
+ compute: {
157
+ module,
158
+ entryPoint
159
+ }
160
+ });
161
+ }
162
+ /**
163
+ * Create a compute pipeline asynchronously (preferred for performance).
164
+ *
165
+ * @param code - WGSL compute shader code
166
+ * @param entryPoint - Entry point function name
167
+ * @returns Promise resolving to compute pipeline
168
+ */
169
+ async createComputePipelineAsync(code, entryPoint = "main") {
170
+ const device = this.getDevice();
171
+ const module = this.compileShader(code);
172
+ return device.createComputePipelineAsync({
173
+ layout: "auto",
174
+ compute: {
175
+ module,
176
+ entryPoint
177
+ }
178
+ });
179
+ }
180
+ /**
181
+ * Clear all cached resources.
182
+ */
183
+ clearCache() {
184
+ this.shaderCache.clear();
185
+ for (const buffer of this.bufferPool) buffer.destroy();
186
+ this.bufferPool.length = 0;
187
+ }
188
+ /**
189
+ * Destroy the context and release all resources.
190
+ */
191
+ destroy() {
192
+ this.clearCache();
193
+ if (this.device !== null) {
194
+ this.device.destroy();
195
+ this.device = null;
196
+ }
197
+ }
198
+ /**
199
+ * Simple string hash for cache keys.
200
+ */
201
+ hashCode(str) {
202
+ let hash = 0;
203
+ for (let i = 0; i < str.length; i++) {
204
+ const char = str.charCodeAt(i);
205
+ hash = (hash << 5) - hash + char | 0;
206
+ }
207
+ return hash.toString(16);
208
+ }
209
+ };
210
+ //#endregion
211
+ //#region src/gpu/csr.ts
212
+ /**
213
+ * Convert a ReadableGraph to CSR format.
214
+ *
215
+ * For undirected graphs, each edge is stored twice (once in each direction).
216
+ * For directed graphs, edges are stored in the out-direction by default.
217
+ *
218
+ * @param graph - The graph to convert
219
+ * @param direction - Edge direction to include (default: 'out' for directed, 'both' for undirected)
220
+ * @returns CSR representation with index mapping
221
+ */
222
+ function graphToCSR(graph, direction = graph.directed ? "out" : "both") {
223
+ const nodeToIndex = /* @__PURE__ */ new Map();
224
+ const indexToNode = [];
225
+ for (const nodeId of graph.nodeIds()) {
226
+ const index = indexToNode.length;
227
+ nodeToIndex.set(nodeId, index);
228
+ indexToNode.push(nodeId);
229
+ }
230
+ const nodeCount = indexToNode.length;
231
+ const degrees = new Uint32Array(nodeCount);
232
+ for (const nodeId of graph.nodeIds()) {
233
+ const srcIndex = nodeToIndex.get(nodeId);
234
+ if (srcIndex === void 0) continue;
235
+ degrees[srcIndex] = graph.degree(nodeId, direction);
236
+ }
237
+ let totalEdges = 0;
238
+ for (let i = 0; i < nodeCount; i++) totalEdges += degrees[i] ?? 0;
239
+ const rowOffsets = new Uint32Array(nodeCount + 1);
240
+ for (let i = 0; i < nodeCount; i++) rowOffsets[i + 1] = (rowOffsets[i] ?? 0) + (degrees[i] ?? 0);
241
+ const colIndices = new Uint32Array(totalEdges);
242
+ const values = new Float32Array(totalEdges);
243
+ for (const nodeId of graph.nodeIds()) {
244
+ const srcIndex = nodeToIndex.get(nodeId);
245
+ if (srcIndex === void 0) continue;
246
+ const baseOffset = rowOffsets[srcIndex] ?? 0;
247
+ let localOffset = 0;
248
+ for (const neighbourId of graph.neighbours(nodeId, direction)) {
249
+ const dstIndex = nodeToIndex.get(neighbourId);
250
+ if (dstIndex === void 0) continue;
251
+ const edgeIdx = baseOffset + localOffset;
252
+ colIndices[edgeIdx] = dstIndex;
253
+ values[edgeIdx] = graph.getEdge(nodeId, neighbourId)?.weight ?? 1;
254
+ localOffset++;
255
+ }
256
+ }
257
+ return {
258
+ csr: {
259
+ rowOffsets,
260
+ colIndices,
261
+ values,
262
+ nodeCount,
263
+ edgeCount: graph.directed ? graph.edgeCount : graph.edgeCount * 2
264
+ },
265
+ indexMap: {
266
+ nodeToIndex,
267
+ indexToNode
268
+ }
269
+ };
270
+ }
271
+ /**
272
+ * Create GPU buffers from a CSR matrix.
273
+ *
274
+ * Buffers are created with:
275
+ * - rowOffsets/colIndices: STORAGE | COPY_DST
276
+ * - values: STORAGE | COPY_DST (if present)
277
+ *
278
+ * @param device - GPU device to create buffers on
279
+ * @param csr - CSR matrix to upload
280
+ * @returns GPU buffer group
281
+ */
282
+ function csrToGPUBuffers(device, csr) {
283
+ const rowOffsetsBuffer = device.createBuffer({
284
+ size: csr.rowOffsets.byteLength,
285
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
286
+ mappedAtCreation: false
287
+ });
288
+ device.queue.writeBuffer(rowOffsetsBuffer, 0, csr.rowOffsets);
289
+ const colIndicesBuffer = device.createBuffer({
290
+ size: csr.colIndices.byteLength,
291
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
292
+ mappedAtCreation: false
293
+ });
294
+ device.queue.writeBuffer(colIndicesBuffer, 0, csr.colIndices);
295
+ let valuesBuffer;
296
+ if (csr.values !== void 0) {
297
+ valuesBuffer = device.createBuffer({
298
+ size: csr.values.byteLength,
299
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
300
+ mappedAtCreation: false
301
+ });
302
+ device.queue.writeBuffer(valuesBuffer, 0, csr.values);
303
+ }
304
+ return {
305
+ rowOffsets: rowOffsetsBuffer,
306
+ colIndices: colIndicesBuffer,
307
+ values: valuesBuffer,
308
+ nodeCount: csr.nodeCount,
309
+ edgeCount: csr.edgeCount
310
+ };
311
+ }
312
+ //#endregion
313
+ Object.defineProperty(exports, "GPUContext", {
314
+ enumerable: true,
315
+ get: function() {
316
+ return GPUContext;
317
+ }
318
+ });
319
+ Object.defineProperty(exports, "csrToGPUBuffers", {
320
+ enumerable: true,
321
+ get: function() {
322
+ return csrToGPUBuffers;
323
+ }
324
+ });
325
+ Object.defineProperty(exports, "detectWebGPU", {
326
+ enumerable: true,
327
+ get: function() {
328
+ return detectWebGPU;
329
+ }
330
+ });
331
+ Object.defineProperty(exports, "graphToCSR", {
332
+ enumerable: true,
333
+ get: function() {
334
+ return graphToCSR;
335
+ }
336
+ });
337
+
338
+ //# sourceMappingURL=gpu-BJRVYBjx.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpu-BJRVYBjx.cjs","names":[],"sources":["../src/gpu/detect.ts","../src/gpu/context.ts","../src/gpu/csr.ts"],"sourcesContent":["/**\n * WebGPU availability detection for browser and Node.js environments.\n *\n * This module provides runtime detection of WebGPU support without\n * requiring any polyfills or runtime dependencies.\n */\n\nimport type { GPUDetectionResult } from \"./types\";\n\n/**\n * Detect WebGPU availability in the current environment.\n *\n * Checks for:\n * - Browser: navigator.gpu\n * - Node.js: global GPU constructor (Node.js 21+ with --experimental-webgpu)\n * - Deno: global GPU constructor\n *\n * @returns Detection result with availability status and reason\n */\nexport function detectWebGPU(): GPUDetectionResult {\n\t// Check for browser WebGPU API\n\tif (typeof navigator !== \"undefined\" && \"gpu\" in navigator) {\n\t\treturn { available: true };\n\t}\n\n\t// Check for Node.js / Deno global GPU\n\tif (typeof globalThis !== \"undefined\" && \"GPU\" in globalThis) {\n\t\treturn { available: true };\n\t}\n\n\t// WebGPU not available\n\tconst reasons: string[] = [];\n\n\tif (typeof navigator === \"undefined\" && typeof globalThis === \"undefined\") {\n\t\treasons.push(\"no global scope detected\");\n\t} else if (typeof navigator !== \"undefined\" && !(\"gpu\" in navigator)) {\n\t\treasons.push(\"navigator.gpu not present (browser may not support WebGPU)\");\n\t} else if (typeof globalThis !== \"undefined\" && !(\"GPU\" in globalThis)) {\n\t\treasons.push(\n\t\t\t\"global GPU not present (Node.js requires v21+ with --experimental-webgpu flag)\",\n\t\t);\n\t}\n\n\treturn {\n\t\tavailable: false,\n\t\treason: reasons.length > 0 ? reasons.join(\"; \") : \"unknown environment\",\n\t};\n}\n\n/**\n * Check if WebGPU is available (convenience function).\n *\n * @returns true if WebGPU is available, false otherwise\n */\nexport function isWebGPUAvailable(): boolean {\n\treturn detectWebGPU().available;\n}\n\n/**\n * Assert that WebGPU is available, throwing an error if not.\n *\n * @throws Error if WebGPU is not available\n */\nexport function assertWebGPUAvailable(): void {\n\tconst result = detectWebGPU();\n\tif (!result.available) {\n\t\tthrow new Error(\n\t\t\t`WebGPU required but not available: ${result.reason ?? \"unknown reason\"}`,\n\t\t);\n\t}\n}\n","/**\n * GPU context management for WebGPU compute operations.\n *\n * Provides device acquisition, buffer pooling, and shader compilation\n * with caching for efficient GPU resource management.\n */\n\nimport { detectWebGPU } from \"./detect\";\n\n/**\n * Type guard to check if an object has a WebGPU-compatible requestAdapter method.\n */\nfunction hasRequestAdapter(obj: unknown): obj is {\n\trequestAdapter: (\n\t\topts?: GPURequestAdapterOptions,\n\t) => Promise<GPUAdapter | null>;\n} {\n\tif (typeof obj !== \"object\" || obj === null) {\n\t\treturn false;\n\t}\n\tif (!(\"requestAdapter\" in obj)) {\n\t\treturn false;\n\t}\n\t// Use Object.getOwnPropertyDescriptor to safely check property type\n\tconst descriptor = Object.getOwnPropertyDescriptor(obj, \"requestAdapter\");\n\treturn descriptor !== undefined && typeof descriptor.value === \"function\";\n}\n\n/**\n * Options for creating a GPUContext.\n */\nexport interface GPUContextOptions {\n\t/** Power preference for GPU adapter */\n\treadonly powerPreference?: \"low-power\" | \"high-performance\";\n\t/** Force create new context even if one exists */\n\treadonly forceNew?: boolean;\n}\n\n/**\n * Shader module cache entry.\n */\ninterface CachedShader {\n\treadonly module: GPUShaderModule;\n\treadonly code: string;\n}\n\n/**\n * Manages GPU device, buffers, and compiled shaders.\n *\n * Use the singleton pattern via getGPUContext() for most use cases,\n * or create separate contexts for isolated GPU resource pools.\n */\nexport class GPUContext {\n\tprivate device: GPUDevice | null = null;\n\tprivate readonly shaderCache = new Map<string, CachedShader>();\n\tprivate readonly bufferPool: GPUBuffer[] = [];\n\tprivate readonly destroyedBuffers = new WeakSet<GPUBuffer>();\n\n\t/**\n\t * Check if this context has an acquired GPU device.\n\t */\n\tpublic get isReady(): boolean {\n\t\treturn this.device !== null;\n\t}\n\n\t/**\n\t * Get the GPU device, throwing if not acquired.\n\t */\n\tpublic getDevice(): GPUDevice {\n\t\tif (this.device === null) {\n\t\t\tthrow new Error(\n\t\t\t\t\"GPUContext not initialised. Call acquireDevice() first.\",\n\t\t\t);\n\t\t}\n\t\treturn this.device;\n\t}\n\n\t/**\n\t * Acquire a GPU device from the adapter.\n\t *\n\t * @param options - Context creation options\n\t * @returns true if device was acquired successfully\n\t * @throws Error if WebGPU is unavailable or device request fails\n\t */\n\tpublic async acquireDevice(\n\t\toptions: GPUContextOptions = {},\n\t): Promise<boolean> {\n\t\tconst detection = detectWebGPU();\n\t\tif (!detection.available) {\n\t\t\tthrow new Error(\n\t\t\t\t`WebGPU unavailable: ${detection.reason ?? \"unknown reason\"}`,\n\t\t\t);\n\t\t}\n\n\t\t// Get adapter\n\t\tlet adapter: GPUAdapter | null = null;\n\n\t\tif (typeof navigator !== \"undefined\" && \"gpu\" in navigator) {\n\t\t\tadapter = await navigator.gpu.requestAdapter({\n\t\t\t\tpowerPreference: options.powerPreference,\n\t\t\t});\n\t\t}\n\n\t\t// Node.js / Deno fallback via global GPU\n\t\tif (\n\t\t\tadapter === null &&\n\t\t\ttypeof globalThis !== \"undefined\" &&\n\t\t\t\"GPU\" in globalThis\n\t\t) {\n\t\t\t// Access gpu property via Object.getOwnPropertyDescriptor to avoid type assertion\n\t\t\tconst gpuDescriptor = Object.getOwnPropertyDescriptor(globalThis, \"gpu\");\n\t\t\t// Pass descriptor value directly to type guard to avoid unsafe assignment\n\t\t\tif (\n\t\t\t\tgpuDescriptor !== undefined &&\n\t\t\t\thasRequestAdapter(gpuDescriptor.value)\n\t\t\t) {\n\t\t\t\tadapter = await gpuDescriptor.value.requestAdapter({\n\t\t\t\t\tpowerPreference: options.powerPreference,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (adapter === null) {\n\t\t\tthrow new Error(\"No GPU adapter found\");\n\t\t}\n\n\t\t// Request device\n\t\tthis.device = await adapter.requestDevice();\n\n\t\t// Handle device loss\n\t\tvoid this.device.lost.then((info: GPUDeviceLostInfo): void => {\n\t\t\tconsole.error(`GPU device lost: ${info.message}`);\n\t\t\tthis.device = null;\n\t\t\tthis.clearCache();\n\t\t});\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Compile a WGSL shader, using cache if available.\n\t *\n\t * @param code - WGSL shader code\n\t * @param key - Optional cache key (defaults to code hash)\n\t * @returns Compiled shader module\n\t */\n\tpublic compileShader(code: string, key?: string): GPUShaderModule {\n\t\tconst cacheKey = key ?? this.hashCode(code);\n\t\tconst cached = this.shaderCache.get(cacheKey);\n\n\t\tif (cached?.code === code) {\n\t\t\treturn cached.module;\n\t\t}\n\n\t\tconst device = this.getDevice();\n\t\tconst module = device.createShaderModule({ code });\n\n\t\tthis.shaderCache.set(cacheKey, { module, code });\n\t\treturn module;\n\t}\n\n\t/**\n\t * Create a GPU buffer, optionally reusing from pool.\n\t *\n\t * @param size - Buffer size in bytes\n\t * @param usage - Buffer usage flags\n\t * @returns GPU buffer\n\t */\n\tpublic createBuffer(size: number, usage: GPUBufferUsageFlags): GPUBuffer {\n\t\t// Try to find a suitable buffer in the pool\n\t\tfor (let i = 0; i < this.bufferPool.length; i++) {\n\t\t\tconst buffer = this.bufferPool[i];\n\t\t\tif (\n\t\t\t\tbuffer !== undefined &&\n\t\t\t\t!this.destroyedBuffers.has(buffer) &&\n\t\t\t\tbuffer.size >= size &&\n\t\t\t\t(buffer.usage & usage) === usage\n\t\t\t) {\n\t\t\t\tthis.bufferPool.splice(i, 1);\n\t\t\t\treturn buffer;\n\t\t\t}\n\t\t}\n\n\t\t// Create new buffer\n\t\tconst device = this.getDevice();\n\t\treturn device.createBuffer({ size, usage });\n\t}\n\n\t/**\n\t * Return a buffer to the pool for reuse.\n\t *\n\t * @param buffer - Buffer to recycle\n\t */\n\tpublic recycleBuffer(buffer: GPUBuffer): void {\n\t\t// Only pool if buffer is not destroyed\n\t\tif (!this.destroyedBuffers.has(buffer)) {\n\t\t\tthis.bufferPool.push(buffer);\n\t\t}\n\t}\n\n\t/**\n\t * Mark a buffer as destroyed (call before GPUBuffer.destroy()).\n\t *\n\t * @param buffer - Buffer to mark as destroyed\n\t */\n\tpublic markDestroyed(buffer: GPUBuffer): void {\n\t\tthis.destroyedBuffers.add(buffer);\n\t}\n\n\t/**\n\t * Create a compute pipeline from shader code.\n\t *\n\t * @param code - WGSL compute shader code\n\t * @param entryPoint - Entry point function name\n\t * @returns Compute pipeline\n\t */\n\tpublic createComputePipeline(\n\t\tcode: string,\n\t\tentryPoint = \"main\",\n\t): GPUComputePipeline {\n\t\tconst device = this.getDevice();\n\t\tconst module = this.compileShader(code);\n\n\t\treturn device.createComputePipeline({\n\t\t\tlayout: \"auto\",\n\t\t\tcompute: {\n\t\t\t\tmodule,\n\t\t\t\tentryPoint,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Create a compute pipeline asynchronously (preferred for performance).\n\t *\n\t * @param code - WGSL compute shader code\n\t * @param entryPoint - Entry point function name\n\t * @returns Promise resolving to compute pipeline\n\t */\n\tpublic async createComputePipelineAsync(\n\t\tcode: string,\n\t\tentryPoint = \"main\",\n\t): Promise<GPUComputePipeline> {\n\t\tconst device = this.getDevice();\n\t\tconst module = this.compileShader(code);\n\n\t\treturn device.createComputePipelineAsync({\n\t\t\tlayout: \"auto\",\n\t\t\tcompute: {\n\t\t\t\tmodule,\n\t\t\t\tentryPoint,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Clear all cached resources.\n\t */\n\tpublic clearCache(): void {\n\t\tthis.shaderCache.clear();\n\t\tfor (const buffer of this.bufferPool) {\n\t\t\tbuffer.destroy();\n\t\t}\n\t\tthis.bufferPool.length = 0;\n\t}\n\n\t/**\n\t * Destroy the context and release all resources.\n\t */\n\tpublic destroy(): void {\n\t\tthis.clearCache();\n\t\tif (this.device !== null) {\n\t\t\tthis.device.destroy();\n\t\t\tthis.device = null;\n\t\t}\n\t}\n\n\t/**\n\t * Simple string hash for cache keys.\n\t */\n\tprivate hashCode(str: string): string {\n\t\tlet hash = 0;\n\t\tfor (let i = 0; i < str.length; i++) {\n\t\t\tconst char = str.charCodeAt(i);\n\t\t\thash = ((hash << 5) - hash + char) | 0;\n\t\t}\n\t\treturn hash.toString(16);\n\t}\n}\n\n// Singleton instance for default context\nlet defaultContext: GPUContext | null = null;\n\n/**\n * Get or create the default GPU context.\n *\n * This is a lazy singleton - the device is not acquired until\n * acquireDevice() is called.\n *\n * @param options - Context creation options\n * @returns GPU context instance\n */\nexport function getGPUContext(options?: GPUContextOptions): GPUContext {\n\tif (defaultContext === null || (options?.forceNew ?? false)) {\n\t\tdefaultContext = new GPUContext();\n\t}\n\treturn defaultContext;\n}\n\n/**\n * Create a new isolated GPU context.\n *\n * Use this when you need separate resource pools or device management.\n *\n * @returns New GPU context instance\n */\nexport function createGPUContext(): GPUContext {\n\treturn new GPUContext();\n}\n","/**\n * Compressed Sparse Row (CSR) matrix representation for GPU computation.\n *\n * CSR format is memory-efficient for sparse graphs and maps well to\n * GPU parallel operations. The format stores adjacency information\n * in three arrays: row offsets, column indices, and optional values.\n */\n\nimport type { NodeId, Direction, NodeData, EdgeData } from \"../graph/types\";\nimport type { ReadableGraph } from \"../graph\";\n\n/**\n * CSR matrix representation of a graph adjacency structure.\n *\n * The rowOffsets array has length nodeCount + 1, where rowOffsets[i]\n * gives the start index in colIndices for node i's neighbours.\n * The neighbours of node i are colIndices[rowOffsets[i] : rowOffsets[i+1]].\n */\nexport interface CSRMatrix {\n\t/** Row offsets array (length: nodeCount + 1) */\n\treadonly rowOffsets: Uint32Array;\n\t/** Column indices array (length: edgeCount for directed, 2*edgeCount for undirected) */\n\treadonly colIndices: Uint32Array;\n\t/** Optional edge weights aligned with colIndices */\n\treadonly values?: Float32Array;\n\t/** Number of nodes in the graph */\n\treadonly nodeCount: number;\n\t/** Number of directed edges (undirected edges counted once) */\n\treadonly edgeCount: number;\n}\n\n/**\n * Mapping from node IDs to CSR indices.\n *\n * Required because CSR uses dense integer indices while graphs\n * may use arbitrary string identifiers.\n */\nexport interface CSRIndexMap {\n\t/** Map from NodeId to CSR row index */\n\treadonly nodeToIndex: ReadonlyMap<NodeId, number>;\n\t/** Map from CSR row index to NodeId */\n\treadonly indexToNode: readonly NodeId[];\n}\n\n/**\n * Combined CSR matrix with index mapping.\n */\nexport interface CSRGraph {\n\treadonly csr: CSRMatrix;\n\treadonly indexMap: CSRIndexMap;\n}\n\n/**\n * Group of GPU buffers holding a CSR matrix.\n *\n * Each buffer is created with appropriate usage flags for compute operations.\n */\nexport interface GPUBufferGroup {\n\t/** Buffer containing rowOffsets data */\n\treadonly rowOffsets: GPUBuffer;\n\t/** Buffer containing colIndices data */\n\treadonly colIndices: GPUBuffer;\n\t/** Buffer containing values data (optional) */\n\treadonly values?: GPUBuffer;\n\t/** Number of nodes */\n\treadonly nodeCount: number;\n\t/** Number of edges */\n\treadonly edgeCount: number;\n}\n\n/**\n * Convert a ReadableGraph to CSR format.\n *\n * For undirected graphs, each edge is stored twice (once in each direction).\n * For directed graphs, edges are stored in the out-direction by default.\n *\n * @param graph - The graph to convert\n * @param direction - Edge direction to include (default: 'out' for directed, 'both' for undirected)\n * @returns CSR representation with index mapping\n */\nexport function graphToCSR<N extends NodeData, E extends EdgeData>(\n\tgraph: ReadableGraph<N, E>,\n\tdirection: Direction = graph.directed ? \"out\" : \"both\",\n): CSRGraph {\n\t// Build node index mapping\n\tconst nodeToIndex = new Map<NodeId, number>();\n\tconst indexToNode: NodeId[] = [];\n\n\tfor (const nodeId of graph.nodeIds()) {\n\t\tconst index = indexToNode.length;\n\t\tnodeToIndex.set(nodeId, index);\n\t\tindexToNode.push(nodeId);\n\t}\n\n\tconst nodeCount = indexToNode.length;\n\n\t// Count edges per node to build row offsets\n\tconst degrees = new Uint32Array(nodeCount);\n\n\tfor (const nodeId of graph.nodeIds()) {\n\t\tconst srcIndex = nodeToIndex.get(nodeId);\n\t\tif (srcIndex === undefined) continue;\n\t\tdegrees[srcIndex] = graph.degree(nodeId, direction);\n\t}\n\n\t// Calculate total edge count\n\tlet totalEdges = 0;\n\tfor (let i = 0; i < nodeCount; i++) {\n\t\ttotalEdges += degrees[i] ?? 0;\n\t}\n\n\t// Build rowOffsets array\n\tconst rowOffsets = new Uint32Array(nodeCount + 1);\n\tfor (let i = 0; i < nodeCount; i++) {\n\t\trowOffsets[i + 1] = (rowOffsets[i] ?? 0) + (degrees[i] ?? 0);\n\t}\n\n\t// Build colIndices and values arrays\n\tconst colIndices = new Uint32Array(totalEdges);\n\tconst values = new Float32Array(totalEdges);\n\n\tfor (const nodeId of graph.nodeIds()) {\n\t\tconst srcIndex = nodeToIndex.get(nodeId);\n\t\tif (srcIndex === undefined) continue;\n\n\t\tconst baseOffset = rowOffsets[srcIndex] ?? 0;\n\t\tlet localOffset = 0;\n\n\t\tfor (const neighbourId of graph.neighbours(nodeId, direction)) {\n\t\t\tconst dstIndex = nodeToIndex.get(neighbourId);\n\t\t\tif (dstIndex === undefined) continue;\n\n\t\t\tconst edgeIdx = baseOffset + localOffset;\n\t\t\tcolIndices[edgeIdx] = dstIndex;\n\n\t\t\t// Get edge weight if available\n\t\t\tconst edge = graph.getEdge(nodeId, neighbourId);\n\t\t\tvalues[edgeIdx] = edge?.weight ?? 1.0;\n\n\t\t\tlocalOffset++;\n\t\t}\n\t}\n\n\tconst csr: CSRMatrix = {\n\t\trowOffsets,\n\t\tcolIndices,\n\t\tvalues,\n\t\tnodeCount,\n\t\tedgeCount: graph.directed ? graph.edgeCount : graph.edgeCount * 2,\n\t};\n\n\tconst indexMap: CSRIndexMap = {\n\t\tnodeToIndex,\n\t\tindexToNode,\n\t};\n\n\treturn { csr, indexMap };\n}\n\n/**\n * Create GPU buffers from a CSR matrix.\n *\n * Buffers are created with:\n * - rowOffsets/colIndices: STORAGE | COPY_DST\n * - values: STORAGE | COPY_DST (if present)\n *\n * @param device - GPU device to create buffers on\n * @param csr - CSR matrix to upload\n * @returns GPU buffer group\n */\nexport function csrToGPUBuffers(\n\tdevice: GPUDevice,\n\tcsr: CSRMatrix,\n): GPUBufferGroup {\n\t// Row offsets buffer\n\tconst rowOffsetsBuffer = device.createBuffer({\n\t\tsize: csr.rowOffsets.byteLength,\n\t\tusage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n\t\tmappedAtCreation: false,\n\t});\n\tdevice.queue.writeBuffer(rowOffsetsBuffer, 0, csr.rowOffsets);\n\n\t// Column indices buffer\n\tconst colIndicesBuffer = device.createBuffer({\n\t\tsize: csr.colIndices.byteLength,\n\t\tusage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n\t\tmappedAtCreation: false,\n\t});\n\tdevice.queue.writeBuffer(colIndicesBuffer, 0, csr.colIndices);\n\n\t// Values buffer (optional)\n\tlet valuesBuffer: GPUBuffer | undefined;\n\tif (csr.values !== undefined) {\n\t\tvaluesBuffer = device.createBuffer({\n\t\t\tsize: csr.values.byteLength,\n\t\t\tusage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n\t\t\tmappedAtCreation: false,\n\t\t});\n\t\tdevice.queue.writeBuffer(valuesBuffer, 0, csr.values);\n\t}\n\n\treturn {\n\t\trowOffsets: rowOffsetsBuffer,\n\t\tcolIndices: colIndicesBuffer,\n\t\tvalues: valuesBuffer,\n\t\tnodeCount: csr.nodeCount,\n\t\tedgeCount: csr.edgeCount,\n\t};\n}\n\n/**\n * Create a result buffer for reading compute output.\n *\n * @param device - GPU device\n * @param byteLength - Size of the buffer in bytes\n * @returns GPU buffer configured for map reading\n */\nexport function createResultBuffer(\n\tdevice: GPUDevice,\n\tbyteLength: number,\n): GPUBuffer {\n\treturn device.createBuffer({\n\t\tsize: byteLength,\n\t\tusage:\n\t\t\tGPUBufferUsage.STORAGE |\n\t\t\tGPUBufferUsage.COPY_SRC |\n\t\t\tGPUBufferUsage.MAP_READ,\n\t});\n}\n\n/**\n * Read data from a GPU buffer to CPU.\n *\n * @param device - GPU device\n * @param buffer - Buffer to read from\n * @returns ArrayBuffer containing the buffer data\n */\nexport async function readBufferToCPU(\n\tdevice: GPUDevice,\n\tbuffer: GPUBuffer,\n): Promise<ArrayBuffer> {\n\tawait buffer.mapAsync(GPUMapMode.READ);\n\tconst data = buffer.getMappedRange().slice(0);\n\tbuffer.unmap();\n\treturn data;\n}\n"],"mappings":"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"}