@graphty/webgpu-graph-algorithms 0.0.0 → 0.2.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 (269) hide show
  1. package/README.md +344 -23
  2. package/dist/browser.d.ts +1 -0
  3. package/dist/browser.js +32 -0
  4. package/dist/browser.js.map +1 -0
  5. package/dist/chunks/context-E6iKaeuJ.js +3136 -0
  6. package/dist/chunks/context-E6iKaeuJ.js.map +1 -0
  7. package/dist/node.d.ts +1 -0
  8. package/dist/node.js +131 -0
  9. package/dist/node.js.map +1 -0
  10. package/dist/src/accelerator.d.ts +26 -0
  11. package/dist/src/accelerator.d.ts.map +1 -0
  12. package/dist/src/accelerator.js +101 -0
  13. package/dist/src/accelerator.js.map +1 -0
  14. package/dist/src/algorithms/degree.d.ts +35 -0
  15. package/dist/src/algorithms/degree.d.ts.map +1 -0
  16. package/dist/src/algorithms/degree.js +119 -0
  17. package/dist/src/algorithms/degree.js.map +1 -0
  18. package/dist/src/browser/index.d.ts +23 -0
  19. package/dist/src/browser/index.d.ts.map +1 -0
  20. package/dist/src/browser/index.js +48 -0
  21. package/dist/src/browser/index.js.map +1 -0
  22. package/dist/src/constants.d.ts +92 -0
  23. package/dist/src/constants.d.ts.map +1 -0
  24. package/dist/src/constants.js +92 -0
  25. package/dist/src/constants.js.map +1 -0
  26. package/dist/src/context.d.ts +84 -0
  27. package/dist/src/context.d.ts.map +1 -0
  28. package/dist/src/context.js +304 -0
  29. package/dist/src/context.js.map +1 -0
  30. package/dist/src/device/acquire.d.ts +57 -0
  31. package/dist/src/device/acquire.d.ts.map +1 -0
  32. package/dist/src/device/acquire.js +232 -0
  33. package/dist/src/device/acquire.js.map +1 -0
  34. package/dist/src/device/caps.d.ts +43 -0
  35. package/dist/src/device/caps.d.ts.map +1 -0
  36. package/dist/src/device/caps.js +104 -0
  37. package/dist/src/device/caps.js.map +1 -0
  38. package/dist/src/device/error-scope.d.ts +75 -0
  39. package/dist/src/device/error-scope.d.ts.map +1 -0
  40. package/dist/src/device/error-scope.js +152 -0
  41. package/dist/src/device/error-scope.js.map +1 -0
  42. package/dist/src/device/lost.d.ts +51 -0
  43. package/dist/src/device/lost.d.ts.map +1 -0
  44. package/dist/src/device/lost.js +130 -0
  45. package/dist/src/device/lost.js.map +1 -0
  46. package/dist/src/device/webgpu-constants.d.ts +31 -0
  47. package/dist/src/device/webgpu-constants.d.ts.map +1 -0
  48. package/dist/src/device/webgpu-constants.js +31 -0
  49. package/dist/src/device/webgpu-constants.js.map +1 -0
  50. package/dist/src/errors.d.ts +56 -0
  51. package/dist/src/errors.d.ts.map +1 -0
  52. package/dist/src/errors.js +57 -0
  53. package/dist/src/errors.js.map +1 -0
  54. package/dist/src/index.d.ts +29 -0
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/index.js +27 -0
  57. package/dist/src/index.js.map +1 -0
  58. package/dist/src/kernel/batch.d.ts +116 -0
  59. package/dist/src/kernel/batch.d.ts.map +1 -0
  60. package/dist/src/kernel/batch.js +335 -0
  61. package/dist/src/kernel/batch.js.map +1 -0
  62. package/dist/src/kernel/dispatch.d.ts +59 -0
  63. package/dist/src/kernel/dispatch.d.ts.map +1 -0
  64. package/dist/src/kernel/dispatch.js +139 -0
  65. package/dist/src/kernel/dispatch.js.map +1 -0
  66. package/dist/src/kernel/kernel.d.ts +84 -0
  67. package/dist/src/kernel/kernel.d.ts.map +1 -0
  68. package/dist/src/kernel/kernel.js +239 -0
  69. package/dist/src/kernel/kernel.js.map +1 -0
  70. package/dist/src/kernel/pipeline-cache.d.ts +90 -0
  71. package/dist/src/kernel/pipeline-cache.d.ts.map +1 -0
  72. package/dist/src/kernel/pipeline-cache.js +251 -0
  73. package/dist/src/kernel/pipeline-cache.js.map +1 -0
  74. package/dist/src/kernel/prelude.d.ts +35 -0
  75. package/dist/src/kernel/prelude.d.ts.map +1 -0
  76. package/dist/src/kernel/prelude.js +211 -0
  77. package/dist/src/kernel/prelude.js.map +1 -0
  78. package/dist/src/kernel/profiler.d.ts +64 -0
  79. package/dist/src/kernel/profiler.d.ts.map +1 -0
  80. package/dist/src/kernel/profiler.js +120 -0
  81. package/dist/src/kernel/profiler.js.map +1 -0
  82. package/dist/src/kernel/struct-block.d.ts +122 -0
  83. package/dist/src/kernel/struct-block.d.ts.map +1 -0
  84. package/dist/src/kernel/struct-block.js +353 -0
  85. package/dist/src/kernel/struct-block.js.map +1 -0
  86. package/dist/src/kernel/uniform-ring.d.ts +70 -0
  87. package/dist/src/kernel/uniform-ring.d.ts.map +1 -0
  88. package/dist/src/kernel/uniform-ring.js +146 -0
  89. package/dist/src/kernel/uniform-ring.js.map +1 -0
  90. package/dist/src/kernel/wgsl.d.ts +88 -0
  91. package/dist/src/kernel/wgsl.d.ts.map +1 -0
  92. package/dist/src/kernel/wgsl.js +390 -0
  93. package/dist/src/kernel/wgsl.js.map +1 -0
  94. package/dist/src/kernels.d.ts +81 -0
  95. package/dist/src/kernels.d.ts.map +1 -0
  96. package/dist/src/kernels.js +417 -0
  97. package/dist/src/kernels.js.map +1 -0
  98. package/dist/src/layouts/force-simulation.d.ts +498 -0
  99. package/dist/src/layouts/force-simulation.d.ts.map +1 -0
  100. package/dist/src/layouts/force-simulation.js +1650 -0
  101. package/dist/src/layouts/force-simulation.js.map +1 -0
  102. package/dist/src/layouts/forceatlas2.d.ts +210 -0
  103. package/dist/src/layouts/forceatlas2.d.ts.map +1 -0
  104. package/dist/src/layouts/forceatlas2.js +759 -0
  105. package/dist/src/layouts/forceatlas2.js.map +1 -0
  106. package/dist/src/layouts/inputs.d.ts +40 -0
  107. package/dist/src/layouts/inputs.d.ts.map +1 -0
  108. package/dist/src/layouts/inputs.js +185 -0
  109. package/dist/src/layouts/inputs.js.map +1 -0
  110. package/dist/src/layouts/repulsion-exact.d.ts +85 -0
  111. package/dist/src/layouts/repulsion-exact.d.ts.map +1 -0
  112. package/dist/src/layouts/repulsion-exact.js +134 -0
  113. package/dist/src/layouts/repulsion-exact.js.map +1 -0
  114. package/dist/src/layouts/seed.d.ts +56 -0
  115. package/dist/src/layouts/seed.d.ts.map +1 -0
  116. package/dist/src/layouts/seed.js +173 -0
  117. package/dist/src/layouts/seed.js.map +1 -0
  118. package/dist/src/memory/buffer-pool.d.ts +73 -0
  119. package/dist/src/memory/buffer-pool.d.ts.map +1 -0
  120. package/dist/src/memory/buffer-pool.js +170 -0
  121. package/dist/src/memory/buffer-pool.js.map +1 -0
  122. package/dist/src/memory/lease.d.ts +53 -0
  123. package/dist/src/memory/lease.d.ts.map +1 -0
  124. package/dist/src/memory/lease.js +85 -0
  125. package/dist/src/memory/lease.js.map +1 -0
  126. package/dist/src/memory/readback.d.ts +143 -0
  127. package/dist/src/memory/readback.d.ts.map +1 -0
  128. package/dist/src/memory/readback.js +375 -0
  129. package/dist/src/memory/readback.js.map +1 -0
  130. package/dist/src/memory/residency.d.ts +83 -0
  131. package/dist/src/memory/residency.d.ts.map +1 -0
  132. package/dist/src/memory/residency.js +573 -0
  133. package/dist/src/memory/residency.js.map +1 -0
  134. package/dist/src/memory/upload-plan.d.ts +101 -0
  135. package/dist/src/memory/upload-plan.d.ts.map +1 -0
  136. package/dist/src/memory/upload-plan.js +265 -0
  137. package/dist/src/memory/upload-plan.js.map +1 -0
  138. package/dist/src/node/index.d.ts +64 -0
  139. package/dist/src/node/index.d.ts.map +1 -0
  140. package/dist/src/node/index.js +183 -0
  141. package/dist/src/node/index.js.map +1 -0
  142. package/dist/src/primitives/reduce.d.ts +57 -0
  143. package/dist/src/primitives/reduce.d.ts.map +1 -0
  144. package/dist/src/primitives/reduce.js +161 -0
  145. package/dist/src/primitives/reduce.js.map +1 -0
  146. package/dist/src/primitives/segmented-reduce.d.ts +38 -0
  147. package/dist/src/primitives/segmented-reduce.d.ts.map +1 -0
  148. package/dist/src/primitives/segmented-reduce.js +211 -0
  149. package/dist/src/primitives/segmented-reduce.js.map +1 -0
  150. package/dist/src/types/accelerator.d.ts +209 -0
  151. package/dist/src/types/accelerator.d.ts.map +1 -0
  152. package/dist/src/types/accelerator.js +8 -0
  153. package/dist/src/types/accelerator.js.map +1 -0
  154. package/dist/src/types/context.d.ts +114 -0
  155. package/dist/src/types/context.d.ts.map +1 -0
  156. package/dist/src/types/context.js +7 -0
  157. package/dist/src/types/context.js.map +1 -0
  158. package/dist/src/types/layout.d.ts +95 -0
  159. package/dist/src/types/layout.d.ts.map +1 -0
  160. package/dist/src/types/layout.js +6 -0
  161. package/dist/src/types/layout.js.map +1 -0
  162. package/dist/src/types/memory.d.ts +22 -0
  163. package/dist/src/types/memory.d.ts.map +1 -0
  164. package/dist/src/types/memory.js +7 -0
  165. package/dist/src/types/memory.js.map +1 -0
  166. package/dist/src/types/options.d.ts +78 -0
  167. package/dist/src/types/options.d.ts.map +1 -0
  168. package/dist/src/types/options.js +7 -0
  169. package/dist/src/types/options.js.map +1 -0
  170. package/dist/src/types/run.d.ts +13 -0
  171. package/dist/src/types/run.d.ts.map +1 -0
  172. package/dist/src/types/run.js +6 -0
  173. package/dist/src/types/run.js.map +1 -0
  174. package/dist/src/wgsl/degree.wgsl.d.ts +10 -0
  175. package/dist/src/wgsl/degree.wgsl.d.ts.map +1 -0
  176. package/dist/src/wgsl/degree.wgsl.js +25 -0
  177. package/dist/src/wgsl/degree.wgsl.js.map +1 -0
  178. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +12 -0
  179. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -0
  180. package/dist/src/wgsl/fa2-attraction.wgsl.js +37 -0
  181. package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -0
  182. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +13 -0
  183. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -0
  184. package/dist/src/wgsl/fa2-integrate.wgsl.js +69 -0
  185. package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -0
  186. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +12 -0
  187. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -0
  188. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +79 -0
  189. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -0
  190. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts +15 -0
  191. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts.map +1 -0
  192. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js +54 -0
  193. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js.map +1 -0
  194. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +14 -0
  195. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -0
  196. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +57 -0
  197. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -0
  198. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts +11 -0
  199. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts.map +1 -0
  200. package/dist/src/wgsl/fa2-to-scene.wgsl.js +19 -0
  201. package/dist/src/wgsl/fa2-to-scene.wgsl.js.map +1 -0
  202. package/dist/src/wgsl/fill.wgsl.d.ts +7 -0
  203. package/dist/src/wgsl/fill.wgsl.d.ts.map +1 -0
  204. package/dist/src/wgsl/fill.wgsl.js +14 -0
  205. package/dist/src/wgsl/fill.wgsl.js.map +1 -0
  206. package/dist/src/wgsl/reduce.wgsl.d.ts +10 -0
  207. package/dist/src/wgsl/reduce.wgsl.d.ts.map +1 -0
  208. package/dist/src/wgsl/reduce.wgsl.js +63 -0
  209. package/dist/src/wgsl/reduce.wgsl.js.map +1 -0
  210. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +13 -0
  211. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -0
  212. package/dist/src/wgsl/segmented-reduce.wgsl.js +35 -0
  213. package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -0
  214. package/dist/tsconfig.build.tsbuildinfo +1 -0
  215. package/dist/webgpu-graph-algorithms.d.ts +1 -0
  216. package/dist/webgpu-graph-algorithms.js +4454 -0
  217. package/dist/webgpu-graph-algorithms.js.map +1 -0
  218. package/package.json +108 -17
  219. package/src/accelerator.ts +117 -0
  220. package/src/algorithms/degree.ts +142 -0
  221. package/src/browser/index.ts +57 -0
  222. package/src/constants.ts +116 -0
  223. package/src/context.ts +399 -0
  224. package/src/device/acquire.ts +256 -0
  225. package/src/device/caps.ts +122 -0
  226. package/src/device/error-scope.ts +171 -0
  227. package/src/device/lost.ts +142 -0
  228. package/src/device/webgpu-constants.ts +44 -0
  229. package/src/errors.ts +94 -0
  230. package/src/index.ts +102 -0
  231. package/src/kernel/batch.ts +427 -0
  232. package/src/kernel/dispatch.ts +162 -0
  233. package/src/kernel/kernel.ts +311 -0
  234. package/src/kernel/pipeline-cache.ts +288 -0
  235. package/src/kernel/prelude.ts +229 -0
  236. package/src/kernel/profiler.ts +148 -0
  237. package/src/kernel/struct-block.ts +439 -0
  238. package/src/kernel/uniform-ring.ts +184 -0
  239. package/src/kernel/wgsl.ts +490 -0
  240. package/src/kernels.ts +511 -0
  241. package/src/layouts/force-simulation.ts +2111 -0
  242. package/src/layouts/forceatlas2.ts +942 -0
  243. package/src/layouts/inputs.ts +252 -0
  244. package/src/layouts/repulsion-exact.ts +183 -0
  245. package/src/layouts/seed.ts +198 -0
  246. package/src/memory/buffer-pool.ts +204 -0
  247. package/src/memory/lease.ts +93 -0
  248. package/src/memory/readback.ts +429 -0
  249. package/src/memory/residency.ts +753 -0
  250. package/src/memory/upload-plan.ts +350 -0
  251. package/src/node/index.ts +230 -0
  252. package/src/primitives/reduce.ts +233 -0
  253. package/src/primitives/segmented-reduce.ts +270 -0
  254. package/src/types/accelerator.ts +236 -0
  255. package/src/types/context.ts +135 -0
  256. package/src/types/layout.ts +103 -0
  257. package/src/types/memory.ts +23 -0
  258. package/src/types/options.ts +84 -0
  259. package/src/types/run.ts +13 -0
  260. package/src/wgsl/degree.wgsl.ts +24 -0
  261. package/src/wgsl/fa2-attraction.wgsl.ts +37 -0
  262. package/src/wgsl/fa2-integrate.wgsl.ts +69 -0
  263. package/src/wgsl/fa2-repulsion-exact.wgsl.ts +78 -0
  264. package/src/wgsl/fa2-speed-finalize.wgsl.ts +53 -0
  265. package/src/wgsl/fa2-stats-finalize.wgsl.ts +57 -0
  266. package/src/wgsl/fa2-to-scene.wgsl.ts +19 -0
  267. package/src/wgsl/fill.wgsl.ts +13 -0
  268. package/src/wgsl/reduce.wgsl.ts +62 -0
  269. package/src/wgsl/segmented-reduce.wgsl.ts +35 -0
@@ -0,0 +1,173 @@
1
+ /**
2
+ * The CPU port's random number generator, bit for bit, and the NaN-row seeding both paths share (spec 7.2 "Initial
3
+ * positions", 9.3 seedPositions, 7.14 `pos`, 7.19 topology change): a seed gives the same start on the CPU and the
4
+ * GPU because both write the same f32 values in index order. The package carries its own copy of the LCG for its
5
+ * whole life (D27: it cannot import @graphty/layout); W1 cross-tests it against the real RandomNumberGenerator.
6
+ */
7
+ import { WebGpuGraphError } from "../errors.js";
8
+ /** The CPU port's LCG constants (layout/src/utils/random.ts): m = 2^35 - 31, a = 185852, c = 1. */
9
+ export const LCG_M = 34359738337;
10
+ /** The multiplier a of the port's LCG. */
11
+ export const LCG_A = 185852;
12
+ /** The increment c of the port's LCG. */
13
+ export const LCG_C = 1;
14
+ /**
15
+ * The port's RandomNumberGenerator, bit for bit: `seed || Math.floor(Math.random() * 1000000)` (seed 0 / null =
16
+ * unseeded, the quirk preserved), state = seed % m, next = (a * state + c) % m, value = state / m. The product
17
+ * a * state stays below 2^53 (a < 2^18, state < 2^35), so every step is exact in f64, as it is in the port.
18
+ */
19
+ export class Lcg {
20
+ /**
21
+ * Creates the generator; a seed of 0, -0, NaN or null means unseeded (the port's `seed || random` quirk).
22
+ * @param seed - the seed, or null for a random seed
23
+ */
24
+ constructor(seed) {
25
+ this.seed = seed === null || seed === 0 || Number.isNaN(seed) ? Math.floor(Math.random() * 1000000) : seed;
26
+ this.state = this.seed % LCG_M;
27
+ }
28
+ /**
29
+ * Next value in [0, 1).
30
+ * @returns state / m after one LCG step
31
+ */
32
+ next() {
33
+ this.state = (LCG_A * this.state + LCG_C) % LCG_M;
34
+ return this.state / LCG_M;
35
+ }
36
+ }
37
+ /**
38
+ * The three center components of a CommonLayoutOptions.center (missing components are 0).
39
+ * @param center - the caller's center, or null
40
+ * @returns [x, y, z]; E_INVALID_ARGUMENT when a component is not finite
41
+ */
42
+ function resolveCenter(center) {
43
+ const out = [0, 0, 0];
44
+ if (center === null) {
45
+ return out;
46
+ }
47
+ for (let axis = 0; axis < 3 && axis < center.length; axis++) {
48
+ const v = center[axis];
49
+ if (!Number.isFinite(v)) {
50
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `center[${axis}] is not finite`, {
51
+ argument: "center",
52
+ value: v,
53
+ expected: "finite components",
54
+ });
55
+ }
56
+ out[axis] = v;
57
+ }
58
+ return out;
59
+ }
60
+ /**
61
+ * Seeds the unseeded rows of the owner's stride-3 SCENE array in index order (spec 9.3 seedPositions, 7.14 `pos`,
62
+ * 7.19 topology change): a row is unseeded when any of its `dim` components is not finite; every such component
63
+ * draws one LCG value; when NO row is fully finite the draw is uniform in [-1, 1) layout units per axis (`range:
64
+ * "fa2"`; `"fr"` is [0, 1)), otherwise uniform inside the [min, max] box of the finite components per axis,
65
+ * converted to layout units (an axis with no finite value falls back to the range box); the value is written as
66
+ * `v * scale + center[axis]`, which for scale 1 / center 0 is bit-identical to the port's `u * 2 - 1` (resp. `u`);
67
+ * in 2D the third component of a seeded row is written as center[2]. Finite components are never changed and a
68
+ * fully finite row is never touched. No random number is drawn when nothing needs seeding.
69
+ * PLAN DECISION 12 (P3-T1): the box is taken over every finite COMPONENT (the port's rule), not over the fully
70
+ * finite ROWS only; the two differ only when a partially finite row's finite axis lies outside the fully finite
71
+ * rows' box (pinned by test/layouts/seed.test.ts). PLAN DECISION 13: a 2D row whose x and y are finite is seeded
72
+ * whatever its z holds.
73
+ * @param s - the snapshot (nodeCount rows)
74
+ * @param positions - the owner's stride-3 scene-unit array, length 3 * nodeCount, modified in place
75
+ * @param seed - the LCG seed (0 / null = unseeded, the port's quirk)
76
+ * @param dim - 2 or 3
77
+ * @param scale - the scene scale (> 0)
78
+ * @param center - the scene center, or null for the origin
79
+ * @param range - "fa2" for [-1, 1), "fr" for [0, 1)
80
+ */
81
+ export function seedPositions(s, positions, seed, dim, scale, center, range) {
82
+ const n = s.nodeCount;
83
+ if (dim !== 2 && dim !== 3) {
84
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `dim must be 2 or 3, got ${String(dim)}`, {
85
+ argument: "dim",
86
+ value: dim,
87
+ expected: "2 or 3",
88
+ });
89
+ }
90
+ if (positions.length !== 3 * n) {
91
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `positions has ${positions.length} entries, expected ${3 * n}`, {
92
+ argument: "positions",
93
+ value: positions.length,
94
+ expected: 3 * n,
95
+ });
96
+ }
97
+ if (!Number.isFinite(scale) || scale <= 0) {
98
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `scale must be a finite number > 0, got ${scale}`, {
99
+ argument: "scale",
100
+ value: scale,
101
+ expected: "a finite number > 0",
102
+ });
103
+ }
104
+ const c = resolveCenter(center);
105
+ // classify the rows and collect the per-axis box of the finite components (scene units)
106
+ const lo = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY];
107
+ const hi = [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY];
108
+ let finiteRows = 0;
109
+ let unseededRows = 0;
110
+ for (let i = 0; i < n; i++) {
111
+ let finite = true;
112
+ for (let axis = 0; axis < dim; axis++) {
113
+ const v = positions[3 * i + axis];
114
+ if (Number.isFinite(v)) {
115
+ if (v < lo[axis]) {
116
+ lo[axis] = v;
117
+ }
118
+ if (v > hi[axis]) {
119
+ hi[axis] = v;
120
+ }
121
+ }
122
+ else {
123
+ finite = false;
124
+ }
125
+ }
126
+ if (finite) {
127
+ finiteRows++;
128
+ }
129
+ else {
130
+ unseededRows++;
131
+ }
132
+ }
133
+ if (unseededRows === 0) {
134
+ return;
135
+ }
136
+ // the per-axis draw box in layout units
137
+ const rangeLo = range === "fr" ? 0 : -1;
138
+ const rangeHi = 1;
139
+ const boxLo = [rangeLo, rangeLo, rangeLo];
140
+ const boxHi = [rangeHi, rangeHi, rangeHi];
141
+ if (finiteRows > 0) {
142
+ for (let axis = 0; axis < dim; axis++) {
143
+ if (Number.isFinite(lo[axis]) && Number.isFinite(hi[axis])) {
144
+ boxLo[axis] = (lo[axis] - c[axis]) / scale;
145
+ boxHi[axis] = (hi[axis] - c[axis]) / scale;
146
+ }
147
+ }
148
+ }
149
+ const rng = new Lcg(seed);
150
+ for (let i = 0; i < n; i++) {
151
+ let unseeded = false;
152
+ for (let axis = 0; axis < dim; axis++) {
153
+ if (!Number.isFinite(positions[3 * i + axis])) {
154
+ unseeded = true;
155
+ }
156
+ }
157
+ if (!unseeded) {
158
+ continue;
159
+ }
160
+ for (let axis = 0; axis < dim; axis++) {
161
+ const at = 3 * i + axis;
162
+ if (!Number.isFinite(positions[at])) {
163
+ const u = rng.next();
164
+ const v = boxLo[axis] + u * (boxHi[axis] - boxLo[axis]);
165
+ positions[at] = v * scale + c[axis];
166
+ }
167
+ }
168
+ if (dim === 2) {
169
+ positions[3 * i + 2] = c[2];
170
+ }
171
+ }
172
+ }
173
+ //# sourceMappingURL=seed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed.js","sourceRoot":"","sources":["../../../src/layouts/seed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Size-class pool of GPUBuffers by usage (spec 4.4): a request rounds up to a class (powers of two from 4 KiB to
3
+ * 64 MiB, then 16 MiB steps), an idle buffer of that (class, usage) is reused, otherwise one is created through the
4
+ * context's AllocationTracker (so the OOM scope of spec 5.7 and the resident accounting are shared with the
5
+ * residency); `release` keeps at most maxIdlePerClass idle buffers per (class, usage); `trim` destroys the idle
6
+ * ones (ctx.release and layouts on dispose); `destroyAll` everything (ctx.dispose). The Lease scope object arrives
7
+ * with P2-T1 (`lease()`, PLAN DECISION 1). Classes above maxBufferSize are never created: a request that fits the
8
+ * device but whose class overshoots gets the capped class (PLAN DECISION 14).
9
+ */
10
+ import { type AllocationTracker } from "../device/error-scope.js";
11
+ import { Lease } from "./lease.js";
12
+ /** Size-class pool of GPUBuffers by usage (spec 4.4). */
13
+ export declare class BufferPool {
14
+ private readonly allocator;
15
+ private readonly maxBufferSize;
16
+ private readonly maxIdlePerClass;
17
+ private readonly idle;
18
+ private readonly live;
19
+ private liveBytesValue;
20
+ private idleBytesValue;
21
+ private disposed;
22
+ /**
23
+ * Creates an empty pool.
24
+ * @param _device - the device (buffers are created through the allocator, which owns it; the parameter keeps
25
+ * the contract's constructor shape)
26
+ * @param allocator - the context's OOM-scoped allocator
27
+ * @param maxBufferSize - the device's maxBufferSize (classes above it are never created)
28
+ * @param options - pool options
29
+ * @param options.maxIdlePerClass - idle buffers kept per (class, usage); default POOL_MAX_IDLE_PER_CLASS
30
+ */
31
+ constructor(_device: GPUDevice, allocator: AllocationTracker, maxBufferSize: number, options?: {
32
+ readonly maxIdlePerClass?: number | undefined;
33
+ });
34
+ /**
35
+ * The size class a byte length rounds up to: powers of two from 4 KiB to 64 MiB, then 16 MiB steps (pure).
36
+ * @param byteLength - a positive integer
37
+ * @returns the class in bytes
38
+ */
39
+ static sizeClass(byteLength: number): number;
40
+ /**
41
+ * Acquires a buffer of at least byteLength (an idle one of the class and usage, else a new one through the
42
+ * allocator); E_TOO_LARGE above maxBufferSize.
43
+ * @param byteLength - the bytes needed
44
+ * @param usage - the GPUBufferUsage flags
45
+ * @param label - the buffer label (a reused buffer is relabelled)
46
+ * @returns a buffer of the class size
47
+ */
48
+ acquire(byteLength: number, usage: number, label: string): GPUBuffer;
49
+ /**
50
+ * Returns a buffer to its class; destroys it when the class already holds maxIdlePerClass idle buffers. A no-op
51
+ * after destroyAll() (so a `finally` never masks the original error).
52
+ * @param buffer - a buffer acquired from this pool and not yet released
53
+ */
54
+ release(buffer: GPUBuffer): void;
55
+ /** Destroys every idle buffer. */
56
+ trim(): void;
57
+ /**
58
+ * A scope object that releases everything acquired through it (spec 4.4, P2).
59
+ * @returns a fresh lease over this pool
60
+ */
61
+ lease(): Lease;
62
+ /**
63
+ * Bytes of buffers acquired and not yet released (class sizes).
64
+ * @returns the live byte count
65
+ */
66
+ get liveBytes(): number;
67
+ /**
68
+ * Bytes of idle buffers (class sizes).
69
+ * @returns the idle byte count
70
+ */
71
+ get idleBytes(): number;
72
+ }
73
+ //# sourceMappingURL=buffer-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer-pool.d.ts","sourceRoot":"","sources":["../../../src/memory/buffer-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAkBnC,yDAAyD;AACzD,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkC;IACvD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IACxD,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;;;;;OAQG;gBAEC,OAAO,EAAE,SAAS,EAClB,SAAS,EAAE,iBAAiB,EAC5B,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE;IAO/D;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAkB5C;;;;;;;OAOG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS;IA2BpE;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IA4BhC,kCAAkC;IAClC,IAAI,IAAI,IAAI;IAqBZ;;;OAGG;IACH,KAAK,IAAI,KAAK;IAId;;;OAGG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;;OAGG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;CACJ"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Size-class pool of GPUBuffers by usage (spec 4.4): a request rounds up to a class (powers of two from 4 KiB to
3
+ * 64 MiB, then 16 MiB steps), an idle buffer of that (class, usage) is reused, otherwise one is created through the
4
+ * context's AllocationTracker (so the OOM scope of spec 5.7 and the resident accounting are shared with the
5
+ * residency); `release` keeps at most maxIdlePerClass idle buffers per (class, usage); `trim` destroys the idle
6
+ * ones (ctx.release and layouts on dispose); `destroyAll` everything (ctx.dispose). The Lease scope object arrives
7
+ * with P2-T1 (`lease()`, PLAN DECISION 1). Classes above maxBufferSize are never created: a request that fits the
8
+ * device but whose class overshoots gets the capped class (PLAN DECISION 14).
9
+ */
10
+ import { POOL_LINEAR_STEP_BYTES, POOL_MAX_IDLE_PER_CLASS, POOL_MAX_POW2_CLASS_BYTES, POOL_MIN_CLASS_BYTES, } from "../constants.js";
11
+ import { WebGpuGraphError } from "../errors.js";
12
+ import { Lease } from "./lease.js";
13
+ /**
14
+ * The idle-list key of a (class, usage) pair.
15
+ * @param sizeClass - the class in bytes
16
+ * @param usage - the GPUBufferUsage flags
17
+ * @returns the map key
18
+ */
19
+ function classKey(sizeClass, usage) {
20
+ return `${sizeClass}:${usage}`;
21
+ }
22
+ /** Size-class pool of GPUBuffers by usage (spec 4.4). */
23
+ export class BufferPool {
24
+ /**
25
+ * Creates an empty pool.
26
+ * @param _device - the device (buffers are created through the allocator, which owns it; the parameter keeps
27
+ * the contract's constructor shape)
28
+ * @param allocator - the context's OOM-scoped allocator
29
+ * @param maxBufferSize - the device's maxBufferSize (classes above it are never created)
30
+ * @param options - pool options
31
+ * @param options.maxIdlePerClass - idle buffers kept per (class, usage); default POOL_MAX_IDLE_PER_CLASS
32
+ */
33
+ constructor(_device, allocator, maxBufferSize, options) {
34
+ this.idle = new Map();
35
+ this.live = new Map();
36
+ this.liveBytesValue = 0;
37
+ this.idleBytesValue = 0;
38
+ this.disposed = false;
39
+ this.allocator = allocator;
40
+ this.maxBufferSize = maxBufferSize - (maxBufferSize % 4);
41
+ this.maxIdlePerClass = options?.maxIdlePerClass ?? POOL_MAX_IDLE_PER_CLASS;
42
+ }
43
+ /**
44
+ * The size class a byte length rounds up to: powers of two from 4 KiB to 64 MiB, then 16 MiB steps (pure).
45
+ * @param byteLength - a positive integer
46
+ * @returns the class in bytes
47
+ */
48
+ static sizeClass(byteLength) {
49
+ if (!Number.isInteger(byteLength) || byteLength <= 0) {
50
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", "byteLength: expected a positive integer", {
51
+ argument: "byteLength",
52
+ value: byteLength,
53
+ expected: "a positive integer",
54
+ });
55
+ }
56
+ if (byteLength > POOL_MAX_POW2_CLASS_BYTES) {
57
+ return Math.ceil(byteLength / POOL_LINEAR_STEP_BYTES) * POOL_LINEAR_STEP_BYTES;
58
+ }
59
+ let sizeClass = POOL_MIN_CLASS_BYTES;
60
+ while (sizeClass < byteLength) {
61
+ sizeClass *= 2;
62
+ }
63
+ return sizeClass;
64
+ }
65
+ /**
66
+ * Acquires a buffer of at least byteLength (an idle one of the class and usage, else a new one through the
67
+ * allocator); E_TOO_LARGE above maxBufferSize.
68
+ * @param byteLength - the bytes needed
69
+ * @param usage - the GPUBufferUsage flags
70
+ * @param label - the buffer label (a reused buffer is relabelled)
71
+ * @returns a buffer of the class size
72
+ */
73
+ acquire(byteLength, usage, label) {
74
+ if (this.disposed) {
75
+ throw new WebGpuGraphError("E_DISPOSED", "the buffer pool was disposed", { label: "pool" });
76
+ }
77
+ const rounded = BufferPool.sizeClass(byteLength);
78
+ if (byteLength > this.maxBufferSize) {
79
+ throw new WebGpuGraphError("E_TOO_LARGE", `pool: ${byteLength} bytes exceed the device maxBufferSize of ${this.maxBufferSize} bytes`, { needed: byteLength, limit: this.maxBufferSize, path: "pool", algorithm: null });
80
+ }
81
+ const sizeClass = Math.min(rounded, this.maxBufferSize);
82
+ const key = classKey(sizeClass, usage);
83
+ const idle = this.idle.get(key);
84
+ let buffer = idle?.pop();
85
+ if (buffer === undefined) {
86
+ buffer = this.allocator.createBuffer({ label, size: sizeClass, usage });
87
+ }
88
+ else {
89
+ this.idleBytesValue -= sizeClass;
90
+ buffer.label = label;
91
+ }
92
+ this.live.set(buffer, { sizeClass, usage });
93
+ this.liveBytesValue += sizeClass;
94
+ return buffer;
95
+ }
96
+ /**
97
+ * Returns a buffer to its class; destroys it when the class already holds maxIdlePerClass idle buffers. A no-op
98
+ * after destroyAll() (so a `finally` never masks the original error).
99
+ * @param buffer - a buffer acquired from this pool and not yet released
100
+ */
101
+ release(buffer) {
102
+ if (this.disposed) {
103
+ return;
104
+ }
105
+ const entry = this.live.get(buffer);
106
+ if (entry === undefined) {
107
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", "buffer: not a live buffer of this pool", {
108
+ argument: "buffer",
109
+ value: buffer.label,
110
+ expected: "a buffer acquired from this pool and not yet released",
111
+ });
112
+ }
113
+ this.live.delete(buffer);
114
+ this.liveBytesValue -= entry.sizeClass;
115
+ const key = classKey(entry.sizeClass, entry.usage);
116
+ let idle = this.idle.get(key);
117
+ if (idle === undefined) {
118
+ idle = [];
119
+ this.idle.set(key, idle);
120
+ }
121
+ if (idle.length >= this.maxIdlePerClass) {
122
+ this.allocator.destroy(buffer);
123
+ return;
124
+ }
125
+ idle.push(buffer);
126
+ this.idleBytesValue += entry.sizeClass;
127
+ }
128
+ /** Destroys every idle buffer. */
129
+ trim() {
130
+ for (const buffers of this.idle.values()) {
131
+ for (const buffer of buffers) {
132
+ this.allocator.destroy(buffer);
133
+ }
134
+ }
135
+ this.idle.clear();
136
+ this.idleBytesValue = 0;
137
+ }
138
+ /** Destroys everything, idle and live (ctx.dispose()); idempotent. @internal */
139
+ destroyAll() {
140
+ this.trim();
141
+ for (const buffer of this.live.keys()) {
142
+ this.allocator.destroy(buffer);
143
+ }
144
+ this.live.clear();
145
+ this.liveBytesValue = 0;
146
+ this.disposed = true;
147
+ }
148
+ /**
149
+ * A scope object that releases everything acquired through it (spec 4.4, P2).
150
+ * @returns a fresh lease over this pool
151
+ */
152
+ lease() {
153
+ return new Lease(this);
154
+ }
155
+ /**
156
+ * Bytes of buffers acquired and not yet released (class sizes).
157
+ * @returns the live byte count
158
+ */
159
+ get liveBytes() {
160
+ return this.liveBytesValue;
161
+ }
162
+ /**
163
+ * Bytes of idle buffers (class sizes).
164
+ * @returns the idle byte count
165
+ */
166
+ get idleBytes() {
167
+ return this.idleBytesValue;
168
+ }
169
+ }
170
+ //# sourceMappingURL=buffer-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer-pool.js","sourceRoot":"","sources":["../../../src/memory/buffer-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The Lease scope object of spec 4.4: every buffer an algorithm acquires through it goes back to the
3
+ * BufferPool in ONE `release()` call placed in the algorithm's `finally` block, so scratch never
4
+ * outlives the call that took it (a `try / finally`, not `Symbol.dispose`, until the monorepo's
5
+ * TypeScript target supports `using`). Persistent buffers (layout state) are owned by the simulation
6
+ * object instead and freed by its `dispose()`.
7
+ */
8
+ import type { BufferPool } from "./buffer-pool.js";
9
+ /** Scope object algorithms use: every buffer acquired through it is released by `release()` in a finally block (spec 4.4). */
10
+ export declare class Lease {
11
+ private readonly pool;
12
+ private readonly buffers;
13
+ private released;
14
+ /**
15
+ * Creates a lease over a pool; `pool.lease()` is the usual way to get one.
16
+ * @param pool - the pool every acquisition of this lease goes through
17
+ */
18
+ constructor(pool: BufferPool);
19
+ /**
20
+ * pool.acquire(byteLength, STORAGE | COPY_SRC | COPY_DST, label).
21
+ * @param byteLength - bytes needed; the pool rounds up to its size class
22
+ * @param label - the buffer label
23
+ * @returns the buffer, returned to the pool by `release()`
24
+ */
25
+ storage(byteLength: number, label: string): GPUBuffer;
26
+ /**
27
+ * pool.acquire(byteLength, UNIFORM | COPY_DST, label).
28
+ * @param byteLength - bytes needed; the pool rounds up to its size class
29
+ * @param label - the buffer label
30
+ * @returns the buffer, returned to the pool by `release()`
31
+ */
32
+ uniform(byteLength: number, label: string): GPUBuffer;
33
+ /**
34
+ * pool.acquire with explicit usage.
35
+ * @param byteLength - bytes needed; the pool rounds up to its size class
36
+ * @param usage - the GPUBufferUsage bits
37
+ * @param label - the buffer label
38
+ * @returns the buffer, returned to the pool by `release()`
39
+ */
40
+ acquire(byteLength: number, usage: number, label: string): GPUBuffer;
41
+ /**
42
+ * Releases every buffer acquired through this lease; idempotent. A pool that `ctx.dispose()` already
43
+ * destroyed has nothing left to take back, so its E_DISPOSED is swallowed here: the lease sits in a
44
+ * `finally` block and must never mask the error that unwound the algorithm.
45
+ */
46
+ release(): void;
47
+ /**
48
+ * Live buffers of this lease.
49
+ * @returns the number of buffers acquired through the lease and not yet released
50
+ */
51
+ get count(): number;
52
+ }
53
+ //# sourceMappingURL=lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease.d.ts","sourceRoot":"","sources":["../../../src/memory/lease.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,8HAA8H;AAC9H,qBAAa,KAAK;IACd,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;OAGG;gBACS,IAAI,EAAE,UAAU;IAI5B;;;;;OAKG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS;IAIrD;;;;;OAKG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS;IAIrD;;;;;;OAMG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS;IASpE;;;;OAIG;IACH,OAAO,IAAI,IAAI;IAkBf;;;OAGG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;CACJ"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * The Lease scope object of spec 4.4: every buffer an algorithm acquires through it goes back to the
3
+ * BufferPool in ONE `release()` call placed in the algorithm's `finally` block, so scratch never
4
+ * outlives the call that took it (a `try / finally`, not `Symbol.dispose`, until the monorepo's
5
+ * TypeScript target supports `using`). Persistent buffers (layout state) are owned by the simulation
6
+ * object instead and freed by its `dispose()`.
7
+ */
8
+ import { BufferUsage } from "../device/webgpu-constants.js";
9
+ import { hasErrorCode, WebGpuGraphError } from "../errors.js";
10
+ /** Scope object algorithms use: every buffer acquired through it is released by `release()` in a finally block (spec 4.4). */
11
+ export class Lease {
12
+ /**
13
+ * Creates a lease over a pool; `pool.lease()` is the usual way to get one.
14
+ * @param pool - the pool every acquisition of this lease goes through
15
+ */
16
+ constructor(pool) {
17
+ this.buffers = new Set();
18
+ this.released = false;
19
+ this.pool = pool;
20
+ }
21
+ /**
22
+ * pool.acquire(byteLength, STORAGE | COPY_SRC | COPY_DST, label).
23
+ * @param byteLength - bytes needed; the pool rounds up to its size class
24
+ * @param label - the buffer label
25
+ * @returns the buffer, returned to the pool by `release()`
26
+ */
27
+ storage(byteLength, label) {
28
+ return this.acquire(byteLength, BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST, label);
29
+ }
30
+ /**
31
+ * pool.acquire(byteLength, UNIFORM | COPY_DST, label).
32
+ * @param byteLength - bytes needed; the pool rounds up to its size class
33
+ * @param label - the buffer label
34
+ * @returns the buffer, returned to the pool by `release()`
35
+ */
36
+ uniform(byteLength, label) {
37
+ return this.acquire(byteLength, BufferUsage.UNIFORM | BufferUsage.COPY_DST, label);
38
+ }
39
+ /**
40
+ * pool.acquire with explicit usage.
41
+ * @param byteLength - bytes needed; the pool rounds up to its size class
42
+ * @param usage - the GPUBufferUsage bits
43
+ * @param label - the buffer label
44
+ * @returns the buffer, returned to the pool by `release()`
45
+ */
46
+ acquire(byteLength, usage, label) {
47
+ if (this.released) {
48
+ throw new WebGpuGraphError("E_DISPOSED", `lease already released: cannot acquire "${label}"`, { label });
49
+ }
50
+ const buffer = this.pool.acquire(byteLength, usage, label);
51
+ this.buffers.add(buffer);
52
+ return buffer;
53
+ }
54
+ /**
55
+ * Releases every buffer acquired through this lease; idempotent. A pool that `ctx.dispose()` already
56
+ * destroyed has nothing left to take back, so its E_DISPOSED is swallowed here: the lease sits in a
57
+ * `finally` block and must never mask the error that unwound the algorithm.
58
+ */
59
+ release() {
60
+ if (this.released) {
61
+ return;
62
+ }
63
+ this.released = true;
64
+ const owned = [...this.buffers];
65
+ this.buffers.clear();
66
+ for (const buffer of owned) {
67
+ try {
68
+ this.pool.release(buffer);
69
+ }
70
+ catch (error) {
71
+ if (!hasErrorCode(error, "E_DISPOSED")) {
72
+ throw error;
73
+ }
74
+ }
75
+ }
76
+ }
77
+ /**
78
+ * Live buffers of this lease.
79
+ * @returns the number of buffers acquired through the lease and not yet released
80
+ */
81
+ get count() {
82
+ return this.buffers.size;
83
+ }
84
+ }
85
+ //# sourceMappingURL=lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease.js","sourceRoot":"","sources":["../../../src/memory/lease.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAG9D,8HAA8H;AAC9H,MAAM,OAAO,KAAK;IAKd;;;OAGG;IACH,YAAY,IAAgB;QAPX,YAAO,GAAG,IAAI,GAAG,EAAa,CAAC;QACxC,aAAQ,GAAG,KAAK,CAAC;QAOrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,UAAkB,EAAE,KAAa;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9G,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,UAAkB,EAAE,KAAa;QACrC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACvF,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,UAAkB,EAAE,KAAa,EAAE,KAAa;QACpD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,MAAM,IAAI,gBAAgB,CAAC,YAAY,EAAE,2CAA2C,KAAK,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7G,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzB,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACH,OAAO;QACH,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO;QACX,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC;oBACrC,MAAM,KAAK,CAAC;gBAChB,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC7B,CAAC;CACJ"}