@graphty/webgpu-graph-algorithms 0.0.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/README.md +378 -23
  2. package/dist/browser.d.ts +1 -0
  3. package/dist/browser.js +32 -0
  4. package/dist/browser.js.map +1 -0
  5. package/dist/chunks/context-E6iKaeuJ.js +3136 -0
  6. package/dist/chunks/context-E6iKaeuJ.js.map +1 -0
  7. package/dist/node.d.ts +1 -0
  8. package/dist/node.js +131 -0
  9. package/dist/node.js.map +1 -0
  10. package/dist/src/accelerator.d.ts +26 -0
  11. package/dist/src/accelerator.d.ts.map +1 -0
  12. package/dist/src/accelerator.js +101 -0
  13. package/dist/src/accelerator.js.map +1 -0
  14. package/dist/src/algorithms/degree.d.ts +35 -0
  15. package/dist/src/algorithms/degree.d.ts.map +1 -0
  16. package/dist/src/algorithms/degree.js +119 -0
  17. package/dist/src/algorithms/degree.js.map +1 -0
  18. package/dist/src/browser/index.d.ts +23 -0
  19. package/dist/src/browser/index.d.ts.map +1 -0
  20. package/dist/src/browser/index.js +48 -0
  21. package/dist/src/browser/index.js.map +1 -0
  22. package/dist/src/constants.d.ts +92 -0
  23. package/dist/src/constants.d.ts.map +1 -0
  24. package/dist/src/constants.js +92 -0
  25. package/dist/src/constants.js.map +1 -0
  26. package/dist/src/context.d.ts +84 -0
  27. package/dist/src/context.d.ts.map +1 -0
  28. package/dist/src/context.js +304 -0
  29. package/dist/src/context.js.map +1 -0
  30. package/dist/src/device/acquire.d.ts +57 -0
  31. package/dist/src/device/acquire.d.ts.map +1 -0
  32. package/dist/src/device/acquire.js +232 -0
  33. package/dist/src/device/acquire.js.map +1 -0
  34. package/dist/src/device/caps.d.ts +43 -0
  35. package/dist/src/device/caps.d.ts.map +1 -0
  36. package/dist/src/device/caps.js +104 -0
  37. package/dist/src/device/caps.js.map +1 -0
  38. package/dist/src/device/error-scope.d.ts +75 -0
  39. package/dist/src/device/error-scope.d.ts.map +1 -0
  40. package/dist/src/device/error-scope.js +152 -0
  41. package/dist/src/device/error-scope.js.map +1 -0
  42. package/dist/src/device/lost.d.ts +51 -0
  43. package/dist/src/device/lost.d.ts.map +1 -0
  44. package/dist/src/device/lost.js +130 -0
  45. package/dist/src/device/lost.js.map +1 -0
  46. package/dist/src/device/webgpu-constants.d.ts +31 -0
  47. package/dist/src/device/webgpu-constants.d.ts.map +1 -0
  48. package/dist/src/device/webgpu-constants.js +31 -0
  49. package/dist/src/device/webgpu-constants.js.map +1 -0
  50. package/dist/src/errors.d.ts +56 -0
  51. package/dist/src/errors.d.ts.map +1 -0
  52. package/dist/src/errors.js +57 -0
  53. package/dist/src/errors.js.map +1 -0
  54. package/dist/src/index.d.ts +29 -0
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/index.js +27 -0
  57. package/dist/src/index.js.map +1 -0
  58. package/dist/src/kernel/batch.d.ts +116 -0
  59. package/dist/src/kernel/batch.d.ts.map +1 -0
  60. package/dist/src/kernel/batch.js +335 -0
  61. package/dist/src/kernel/batch.js.map +1 -0
  62. package/dist/src/kernel/dispatch.d.ts +59 -0
  63. package/dist/src/kernel/dispatch.d.ts.map +1 -0
  64. package/dist/src/kernel/dispatch.js +139 -0
  65. package/dist/src/kernel/dispatch.js.map +1 -0
  66. package/dist/src/kernel/kernel.d.ts +84 -0
  67. package/dist/src/kernel/kernel.d.ts.map +1 -0
  68. package/dist/src/kernel/kernel.js +239 -0
  69. package/dist/src/kernel/kernel.js.map +1 -0
  70. package/dist/src/kernel/pipeline-cache.d.ts +90 -0
  71. package/dist/src/kernel/pipeline-cache.d.ts.map +1 -0
  72. package/dist/src/kernel/pipeline-cache.js +251 -0
  73. package/dist/src/kernel/pipeline-cache.js.map +1 -0
  74. package/dist/src/kernel/prelude.d.ts +35 -0
  75. package/dist/src/kernel/prelude.d.ts.map +1 -0
  76. package/dist/src/kernel/prelude.js +211 -0
  77. package/dist/src/kernel/prelude.js.map +1 -0
  78. package/dist/src/kernel/profiler.d.ts +64 -0
  79. package/dist/src/kernel/profiler.d.ts.map +1 -0
  80. package/dist/src/kernel/profiler.js +120 -0
  81. package/dist/src/kernel/profiler.js.map +1 -0
  82. package/dist/src/kernel/struct-block.d.ts +122 -0
  83. package/dist/src/kernel/struct-block.d.ts.map +1 -0
  84. package/dist/src/kernel/struct-block.js +353 -0
  85. package/dist/src/kernel/struct-block.js.map +1 -0
  86. package/dist/src/kernel/uniform-ring.d.ts +70 -0
  87. package/dist/src/kernel/uniform-ring.d.ts.map +1 -0
  88. package/dist/src/kernel/uniform-ring.js +146 -0
  89. package/dist/src/kernel/uniform-ring.js.map +1 -0
  90. package/dist/src/kernel/wgsl.d.ts +88 -0
  91. package/dist/src/kernel/wgsl.d.ts.map +1 -0
  92. package/dist/src/kernel/wgsl.js +390 -0
  93. package/dist/src/kernel/wgsl.js.map +1 -0
  94. package/dist/src/kernels.d.ts +81 -0
  95. package/dist/src/kernels.d.ts.map +1 -0
  96. package/dist/src/kernels.js +417 -0
  97. package/dist/src/kernels.js.map +1 -0
  98. package/dist/src/layouts/force-simulation.d.ts +498 -0
  99. package/dist/src/layouts/force-simulation.d.ts.map +1 -0
  100. package/dist/src/layouts/force-simulation.js +1650 -0
  101. package/dist/src/layouts/force-simulation.js.map +1 -0
  102. package/dist/src/layouts/forceatlas2.d.ts +210 -0
  103. package/dist/src/layouts/forceatlas2.d.ts.map +1 -0
  104. package/dist/src/layouts/forceatlas2.js +759 -0
  105. package/dist/src/layouts/forceatlas2.js.map +1 -0
  106. package/dist/src/layouts/inputs.d.ts +40 -0
  107. package/dist/src/layouts/inputs.d.ts.map +1 -0
  108. package/dist/src/layouts/inputs.js +185 -0
  109. package/dist/src/layouts/inputs.js.map +1 -0
  110. package/dist/src/layouts/repulsion-exact.d.ts +85 -0
  111. package/dist/src/layouts/repulsion-exact.d.ts.map +1 -0
  112. package/dist/src/layouts/repulsion-exact.js +134 -0
  113. package/dist/src/layouts/repulsion-exact.js.map +1 -0
  114. package/dist/src/layouts/seed.d.ts +56 -0
  115. package/dist/src/layouts/seed.d.ts.map +1 -0
  116. package/dist/src/layouts/seed.js +173 -0
  117. package/dist/src/layouts/seed.js.map +1 -0
  118. package/dist/src/memory/buffer-pool.d.ts +73 -0
  119. package/dist/src/memory/buffer-pool.d.ts.map +1 -0
  120. package/dist/src/memory/buffer-pool.js +170 -0
  121. package/dist/src/memory/buffer-pool.js.map +1 -0
  122. package/dist/src/memory/lease.d.ts +53 -0
  123. package/dist/src/memory/lease.d.ts.map +1 -0
  124. package/dist/src/memory/lease.js +85 -0
  125. package/dist/src/memory/lease.js.map +1 -0
  126. package/dist/src/memory/readback.d.ts +143 -0
  127. package/dist/src/memory/readback.d.ts.map +1 -0
  128. package/dist/src/memory/readback.js +375 -0
  129. package/dist/src/memory/readback.js.map +1 -0
  130. package/dist/src/memory/residency.d.ts +83 -0
  131. package/dist/src/memory/residency.d.ts.map +1 -0
  132. package/dist/src/memory/residency.js +573 -0
  133. package/dist/src/memory/residency.js.map +1 -0
  134. package/dist/src/memory/upload-plan.d.ts +101 -0
  135. package/dist/src/memory/upload-plan.d.ts.map +1 -0
  136. package/dist/src/memory/upload-plan.js +265 -0
  137. package/dist/src/memory/upload-plan.js.map +1 -0
  138. package/dist/src/node/index.d.ts +64 -0
  139. package/dist/src/node/index.d.ts.map +1 -0
  140. package/dist/src/node/index.js +183 -0
  141. package/dist/src/node/index.js.map +1 -0
  142. package/dist/src/primitives/reduce.d.ts +57 -0
  143. package/dist/src/primitives/reduce.d.ts.map +1 -0
  144. package/dist/src/primitives/reduce.js +161 -0
  145. package/dist/src/primitives/reduce.js.map +1 -0
  146. package/dist/src/primitives/segmented-reduce.d.ts +38 -0
  147. package/dist/src/primitives/segmented-reduce.d.ts.map +1 -0
  148. package/dist/src/primitives/segmented-reduce.js +211 -0
  149. package/dist/src/primitives/segmented-reduce.js.map +1 -0
  150. package/dist/src/types/accelerator.d.ts +209 -0
  151. package/dist/src/types/accelerator.d.ts.map +1 -0
  152. package/dist/src/types/accelerator.js +8 -0
  153. package/dist/src/types/accelerator.js.map +1 -0
  154. package/dist/src/types/context.d.ts +114 -0
  155. package/dist/src/types/context.d.ts.map +1 -0
  156. package/dist/src/types/context.js +7 -0
  157. package/dist/src/types/context.js.map +1 -0
  158. package/dist/src/types/layout.d.ts +95 -0
  159. package/dist/src/types/layout.d.ts.map +1 -0
  160. package/dist/src/types/layout.js +6 -0
  161. package/dist/src/types/layout.js.map +1 -0
  162. package/dist/src/types/memory.d.ts +22 -0
  163. package/dist/src/types/memory.d.ts.map +1 -0
  164. package/dist/src/types/memory.js +7 -0
  165. package/dist/src/types/memory.js.map +1 -0
  166. package/dist/src/types/options.d.ts +78 -0
  167. package/dist/src/types/options.d.ts.map +1 -0
  168. package/dist/src/types/options.js +7 -0
  169. package/dist/src/types/options.js.map +1 -0
  170. package/dist/src/types/run.d.ts +13 -0
  171. package/dist/src/types/run.d.ts.map +1 -0
  172. package/dist/src/types/run.js +6 -0
  173. package/dist/src/types/run.js.map +1 -0
  174. package/dist/src/wgsl/degree.wgsl.d.ts +10 -0
  175. package/dist/src/wgsl/degree.wgsl.d.ts.map +1 -0
  176. package/dist/src/wgsl/degree.wgsl.js +25 -0
  177. package/dist/src/wgsl/degree.wgsl.js.map +1 -0
  178. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +12 -0
  179. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -0
  180. package/dist/src/wgsl/fa2-attraction.wgsl.js +37 -0
  181. package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -0
  182. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +13 -0
  183. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -0
  184. package/dist/src/wgsl/fa2-integrate.wgsl.js +69 -0
  185. package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -0
  186. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +12 -0
  187. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -0
  188. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +79 -0
  189. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -0
  190. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts +15 -0
  191. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts.map +1 -0
  192. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js +54 -0
  193. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js.map +1 -0
  194. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +14 -0
  195. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -0
  196. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +57 -0
  197. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -0
  198. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts +11 -0
  199. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts.map +1 -0
  200. package/dist/src/wgsl/fa2-to-scene.wgsl.js +19 -0
  201. package/dist/src/wgsl/fa2-to-scene.wgsl.js.map +1 -0
  202. package/dist/src/wgsl/fill.wgsl.d.ts +7 -0
  203. package/dist/src/wgsl/fill.wgsl.d.ts.map +1 -0
  204. package/dist/src/wgsl/fill.wgsl.js +14 -0
  205. package/dist/src/wgsl/fill.wgsl.js.map +1 -0
  206. package/dist/src/wgsl/reduce.wgsl.d.ts +10 -0
  207. package/dist/src/wgsl/reduce.wgsl.d.ts.map +1 -0
  208. package/dist/src/wgsl/reduce.wgsl.js +63 -0
  209. package/dist/src/wgsl/reduce.wgsl.js.map +1 -0
  210. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +13 -0
  211. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -0
  212. package/dist/src/wgsl/segmented-reduce.wgsl.js +35 -0
  213. package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -0
  214. package/dist/tsconfig.build.tsbuildinfo +1 -0
  215. package/dist/webgpu-graph-algorithms.d.ts +1 -0
  216. package/dist/webgpu-graph-algorithms.js +4454 -0
  217. package/dist/webgpu-graph-algorithms.js.map +1 -0
  218. package/package.json +108 -17
  219. package/src/accelerator.ts +117 -0
  220. package/src/algorithms/degree.ts +142 -0
  221. package/src/browser/index.ts +57 -0
  222. package/src/constants.ts +116 -0
  223. package/src/context.ts +399 -0
  224. package/src/device/acquire.ts +256 -0
  225. package/src/device/caps.ts +122 -0
  226. package/src/device/error-scope.ts +171 -0
  227. package/src/device/lost.ts +142 -0
  228. package/src/device/webgpu-constants.ts +44 -0
  229. package/src/errors.ts +94 -0
  230. package/src/index.ts +102 -0
  231. package/src/kernel/batch.ts +427 -0
  232. package/src/kernel/dispatch.ts +162 -0
  233. package/src/kernel/kernel.ts +311 -0
  234. package/src/kernel/pipeline-cache.ts +288 -0
  235. package/src/kernel/prelude.ts +229 -0
  236. package/src/kernel/profiler.ts +148 -0
  237. package/src/kernel/struct-block.ts +439 -0
  238. package/src/kernel/uniform-ring.ts +184 -0
  239. package/src/kernel/wgsl.ts +490 -0
  240. package/src/kernels.ts +511 -0
  241. package/src/layouts/force-simulation.ts +2111 -0
  242. package/src/layouts/forceatlas2.ts +942 -0
  243. package/src/layouts/inputs.ts +252 -0
  244. package/src/layouts/repulsion-exact.ts +183 -0
  245. package/src/layouts/seed.ts +198 -0
  246. package/src/memory/buffer-pool.ts +204 -0
  247. package/src/memory/lease.ts +93 -0
  248. package/src/memory/readback.ts +429 -0
  249. package/src/memory/residency.ts +753 -0
  250. package/src/memory/upload-plan.ts +350 -0
  251. package/src/node/index.ts +230 -0
  252. package/src/primitives/reduce.ts +233 -0
  253. package/src/primitives/segmented-reduce.ts +270 -0
  254. package/src/types/accelerator.ts +236 -0
  255. package/src/types/context.ts +135 -0
  256. package/src/types/layout.ts +103 -0
  257. package/src/types/memory.ts +23 -0
  258. package/src/types/options.ts +84 -0
  259. package/src/types/run.ts +13 -0
  260. package/src/wgsl/degree.wgsl.ts +24 -0
  261. package/src/wgsl/fa2-attraction.wgsl.ts +37 -0
  262. package/src/wgsl/fa2-integrate.wgsl.ts +69 -0
  263. package/src/wgsl/fa2-repulsion-exact.wgsl.ts +78 -0
  264. package/src/wgsl/fa2-speed-finalize.wgsl.ts +53 -0
  265. package/src/wgsl/fa2-stats-finalize.wgsl.ts +57 -0
  266. package/src/wgsl/fa2-to-scene.wgsl.ts +19 -0
  267. package/src/wgsl/fill.wgsl.ts +13 -0
  268. package/src/wgsl/reduce.wgsl.ts +62 -0
  269. package/src/wgsl/segmented-reduce.wgsl.ts +35 -0
package/package.json CHANGED
@@ -1,26 +1,117 @@
1
1
  {
2
2
  "name": "@graphty/webgpu-graph-algorithms",
3
- "version": "0.0.0",
4
- "description": "OIDC trusted publishing setup package for @graphty/webgpu-graph-algorithms",
5
- "license": "MIT",
3
+ "version": "0.2.1",
4
+ "description": "WebGPU-accelerated graph algorithms and layouts over the @graphty/graph-format snapshot, for Node (Dawn) and browsers",
6
5
  "author": "Adam Powers <apowers@ato.ms>",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/graphty-org/webgpu-graph-algorithms.git",
10
- "directory": "packages/webgpu-graph-algorithms"
11
- },
12
- "homepage": "https://github.com/graphty-org/webgpu-graph-algorithms#readme",
13
- "bugs": {
14
- "url": "https://github.com/graphty-org/webgpu-graph-algorithms/issues"
15
- },
16
- "publishConfig": {
17
- "access": "public",
18
- "provenance": true
6
+ "type": "module",
7
+ "main": "dist/webgpu-graph-algorithms.js",
8
+ "types": "dist/webgpu-graph-algorithms.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/webgpu-graph-algorithms.d.ts",
12
+ "import": "./dist/webgpu-graph-algorithms.js",
13
+ "default": "./dist/webgpu-graph-algorithms.js"
14
+ },
15
+ "./browser": {
16
+ "types": "./dist/browser.d.ts",
17
+ "import": "./dist/browser.js",
18
+ "default": "./dist/browser.js"
19
+ },
20
+ "./node": {
21
+ "types": "./dist/node.d.ts",
22
+ "import": "./dist/node.js",
23
+ "default": "./dist/node.js"
24
+ }
19
25
  },
26
+ "sideEffects": false,
20
27
  "files": [
21
28
  "dist/",
22
29
  "src/",
23
30
  "README.md",
24
31
  "LICENSE"
25
- ]
26
- }
32
+ ],
33
+ "publishConfig": {
34
+ "access": "public",
35
+ "provenance": true
36
+ },
37
+ "engines": {
38
+ "node": ">=18.19.0"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/graphty-org/graphty-monorepo.git",
43
+ "directory": "webgpu-graph-algorithms"
44
+ },
45
+ "keywords": [
46
+ "graph",
47
+ "webgpu",
48
+ "wgsl",
49
+ "gpu",
50
+ "graph-algorithms",
51
+ "force-directed",
52
+ "forceatlas2",
53
+ "layout",
54
+ "graph-format"
55
+ ],
56
+ "license": "MIT",
57
+ "bugs": {
58
+ "url": "https://github.com/graphty-org/graphty-monorepo/issues"
59
+ },
60
+ "homepage": "https://github.com/graphty-org/graphty-monorepo/tree/master/webgpu-graph-algorithms#readme",
61
+ "dependencies": {
62
+ "@webgpu/types": "^0.1.72",
63
+ "@graphty/graph-format": "^1.0.0"
64
+ },
65
+ "peerDependencies": {
66
+ "@graphty/algorithms": "^1.0.0",
67
+ "@graphty/graph-format": "^1.0.0",
68
+ "@graphty/layout": "^1.0.0",
69
+ "webgpu": ">=0.4.0 <1.0.0"
70
+ },
71
+ "peerDependenciesMeta": {
72
+ "@graphty/algorithms": {
73
+ "optional": true
74
+ },
75
+ "@graphty/layout": {
76
+ "optional": true
77
+ },
78
+ "webgpu": {
79
+ "optional": true
80
+ }
81
+ },
82
+ "devDependencies": {
83
+ "@vitest/browser": "^3.2.4",
84
+ "@vitest/coverage-v8": "^3.2.4",
85
+ "@vitest/ui": "^3.2.4",
86
+ "fast-check": "^4.2.0",
87
+ "playwright": "^1.54.1",
88
+ "tsx": "^4.20.3",
89
+ "typescript": "^5.9.3",
90
+ "vite": "^7.0.5",
91
+ "vitest": "^3.2.4",
92
+ "webgpu": "0.4.0"
93
+ },
94
+ "scripts": {
95
+ "build": "tsc -p tsconfig.build.json",
96
+ "build:bundle": "node scripts/build-bundle.js",
97
+ "build:all": "npm run build && npm run build:bundle",
98
+ "lint": "eslint && tsc --noEmit -p tsconfig.json && tsc -p tsconfig.strict-consumer.json",
99
+ "lint:fix": "eslint --fix",
100
+ "typecheck": "tsc --noEmit -p tsconfig.json",
101
+ "typecheck:strict-consumer": "tsc -p tsconfig.strict-consumer.json",
102
+ "test": "vitest",
103
+ "test:ui": "vitest --ui",
104
+ "test:run": "vitest run --project=node",
105
+ "test:node": "vitest run --project=node",
106
+ "test:browser": "vitest run --project=browser",
107
+ "test:browser:ci": "node scripts/run-browser-project.js",
108
+ "test:limits": "vitest run --project=node-limits",
109
+ "coverage": "vitest run --project=node --coverage",
110
+ "coverage:preview": "npx serve coverage -p 9058",
111
+ "bench": "tsx benchmarks/run.ts",
112
+ "bench:compare": "node scripts/bench-compare.js",
113
+ "benchmark": "tsx benchmarks/run.ts",
114
+ "gpu:report": "node scripts/gpu-report.js",
115
+ "ready:commit": "npm run build:all && npm run lint && npm run test:node"
116
+ }
117
+ }
@@ -0,0 +1,117 @@
1
+ /**
2
+ * createAccelerator (spec 3.3, 9; contract 3.14): the injectable object that satisfies the CPU packages'
3
+ * AlgorithmAccelerator and LayoutAccelerator interfaces STRUCTURALLY (spec 9.2, 9.3; the mirrors of
4
+ * src/types/accelerator.ts until W1, D27). At P3 it carries `forceAtlas2`, `release` and `dispose` and nothing
5
+ * else: the CPU-side dispatchers (`accelerated()`, `createSimulation()`) test `acc.pageRank !== undefined` and
6
+ * route to the CPU when the member is absent (spec 2.4 row "method missing"), so a method the GPU does not
7
+ * implement must not exist here -- never a throwing stub. The algorithm members arrive one per shipped algorithm
8
+ * from P7; `fruchtermanReingold` / `springElectrical` with P5.
9
+ */
10
+
11
+ import { type GraphSnapshot } from "@graphty/graph-format";
12
+
13
+ import { type GpuContext } from "./context.js";
14
+ import { createForceAtlas2 } from "./layouts/forceatlas2.js";
15
+ import { type AcceleratorOptions, type GpuAccelerator } from "./types/accelerator.js";
16
+ import { type ForceAtlas2Stats, type GpuLayoutSimulation, type GpuLayoutTuning } from "./types/layout.js";
17
+ import { type ForceAtlas2Options } from "./types/options.js";
18
+
19
+ /** The `algorithms` record of AcceleratorOptions (spec 3.3), named for the copy helpers. */
20
+ type AlgorithmDefaults = NonNullable<AcceleratorOptions["algorithms"]>;
21
+
22
+ /** The `algorithms.betweenness` record of AcceleratorOptions (spec 3.3: the `k` / `sources` defaults until A2). */
23
+ type BetweennessDefaults = NonNullable<AlgorithmDefaults["betweenness"]>;
24
+
25
+ /**
26
+ * Frozen copy of the betweenness defaults; `sources` is copied into a fresh frozen array so a later mutation of
27
+ * the caller's list is never seen by the accelerator.
28
+ * @param defaults - the caller's record
29
+ * @returns the frozen copy
30
+ */
31
+ function copyBetweenness(defaults: BetweennessDefaults): BetweennessDefaults {
32
+ const copy: { k?: number | undefined; sources?: readonly number[] | undefined } = { ...defaults };
33
+ if (defaults.sources !== undefined) {
34
+ copy.sources = Object.freeze([...defaults.sources]);
35
+ }
36
+ return Object.freeze(copy);
37
+ }
38
+
39
+ /**
40
+ * Frozen copy of the algorithms record, one level deeper for `betweenness`.
41
+ * @param algorithms - the caller's record
42
+ * @returns the frozen copy
43
+ */
44
+ function copyAlgorithms(algorithms: AlgorithmDefaults): AlgorithmDefaults {
45
+ const copy: { betweenness?: BetweennessDefaults | undefined } = { ...algorithms };
46
+ if (algorithms.betweenness !== undefined) {
47
+ copy.betweenness = copyBetweenness(algorithms.betweenness);
48
+ }
49
+ return Object.freeze(copy);
50
+ }
51
+
52
+ /**
53
+ * The frozen deep copy of the accelerator options (spec 3.3 GpuAccelerator.options: "the tuning defaults given
54
+ * to createAccelerator; frozen"; contract 3.14): the record, its `layout` tuning, its `algorithms` record, the
55
+ * `betweenness` record and the `sources` list are each fresh frozen objects, so neither the caller's later edits
56
+ * nor a consumer's writes can change what the accelerator's simulations inherit.
57
+ * @param options - the caller's options, or undefined
58
+ * @returns the frozen copy (an empty frozen record when nothing was given)
59
+ */
60
+ function freezeOptions(options: AcceleratorOptions | undefined): Readonly<AcceleratorOptions> {
61
+ if (options === undefined) {
62
+ return Object.freeze({});
63
+ }
64
+ const copy: { layout?: GpuLayoutTuning | undefined; algorithms?: AlgorithmDefaults | undefined } = { ...options };
65
+ if (options.layout !== undefined) {
66
+ copy.layout = Object.freeze({ ...options.layout });
67
+ }
68
+ if (options.algorithms !== undefined) {
69
+ copy.algorithms = copyAlgorithms(options.algorithms);
70
+ }
71
+ return Object.freeze(copy);
72
+ }
73
+
74
+ /**
75
+ * Spec 3.3 createAccelerator, verbatim: the object implementing AlgorithmAccelerator & LayoutAccelerator
76
+ * structurally; at P3 it carries forceAtlas2, release and dispose. One per call (the app creates one and injects
77
+ * it, spec 2.4); `kind` is "webgpu"; `options` is a frozen deep copy; `forceAtlas2(o)` is
78
+ * `createForceAtlas2(ctx, { ...o, ...options.layout })`, so the GPU tuning given here wins over anything the
79
+ * CPU-typed option object carries (spec 3.3: tuning never comes from the caller of the accelerator method);
80
+ * `release(s)` is `ctx.release(s)`; `dispose()` is `ctx.dispose()`.
81
+ * @param ctx - the context every simulation the accelerator creates runs on
82
+ * @param options - GPU-only defaults inherited by every simulation (`layout`) and, from P9, the algorithm defaults
83
+ * @returns the injectable accelerator
84
+ * @throws E_DISPOSED / E_DEVICE_LOST from `ctx.assertReady()` (here and inside `forceAtlas2()`); `forceAtlas2()`
85
+ * also throws what createForceAtlas2 throws (E_UNSUPPORTED for `nodeSize`, E_INVALID_ARGUMENT for a bad range)
86
+ */
87
+ export function createAccelerator(ctx: GpuContext, options?: AcceleratorOptions): GpuAccelerator {
88
+ ctx.assertReady();
89
+ const frozen = freezeOptions(options);
90
+ return {
91
+ kind: "webgpu",
92
+ ctx,
93
+ options: frozen,
94
+ /**
95
+ * The ForceAtlas2 simulation with this accelerator's layout tuning (spec 3.3; contract 3.14).
96
+ * @param o - the CPU option type (spec 9.3 ForceAtlas2Options); GPU tuning keys come from `options.layout`
97
+ * @returns a fresh simulation in state "created"
98
+ */
99
+ forceAtlas2(o?: ForceAtlas2Options): GpuLayoutSimulation<ForceAtlas2Options, ForceAtlas2Stats> {
100
+ ctx.assertReady();
101
+ return createForceAtlas2(ctx, { ...o, ...frozen.layout });
102
+ },
103
+ /**
104
+ * Destroys every device buffer recorded for the snapshot (spec 4.5); delegates to ctx.release.
105
+ * @param s - the snapshot the app is done with
106
+ */
107
+ release(s: GraphSnapshot): void {
108
+ ctx.release(s);
109
+ },
110
+ /**
111
+ * Disposes the context (spec 2.8); delegates to ctx.dispose, idempotent.
112
+ */
113
+ dispose(): void {
114
+ ctx.dispose();
115
+ },
116
+ };
117
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * `degree(ctx, s)` -- the walking-skeleton algorithm, kept public as a diagnostic (spec 3.3, 11.5): the out-degree of
3
+ * every node computed on the device by the row-walking `degree` kernel (4.5) over the resident core of the snapshot,
4
+ * with the group-0 dummy-binding pattern of spec 3.5 (`colIdx` in the `weights` slot when the snapshot is unweighted,
5
+ * `rowPtr` in the `perm` slot because P1-P3 pass no row permutation, so `USE_PERM` is false). The result equals
6
+ * `snapshot.outDegree()`; the point of the kernel is to prove the upload, bind, dispatch and readback path end to end
7
+ * on every adapter (bitwise identical across adapters, spec 11.5), not to be faster than the CPU (the README says
8
+ * so).
9
+ *
10
+ * Contract (3.12): `ctx.assertReady()` first; `nodeCount === 0` returns an empty `Uint32Array` (or `dest`) with no
11
+ * GPU work (spec 5.6: there is no work, which is not a fallback); an already-aborted `signal` is `E_ABORTED` before
12
+ * any work; `dest` must be a `Uint32Array` of length n over an `ArrayBuffer`; a windowed core is `E_TOO_LARGE
13
+ * { path: "windowed", algorithm: "degree" }` until P4 executes windows -- `residency.core()` (3.8) throws that error
14
+ * itself with `algorithm: null` before it would ever return a windowed `CoreBinding`, so `degree` catches it and
15
+ * re-throws the same error with `algorithm: "degree"` (the 3.12 detail) instead of testing `core.plan`, which never
16
+ * observes "windowed" in P1-P3; `arcCount === 0` skips the dispatch (only `rowPtr` is resident)
17
+ * and the result is zeros; otherwise ONE dispatch over rows [0, n) with `accumulate = 0` (every row is written, so no
18
+ * fill precedes it), a readback into the result, `onProgress(1, 1)`, and the scratch returned in a finally. Two runs
19
+ * are bitwise identical (spec 11.9 item 4).
20
+ */
21
+
22
+ import { type GraphSnapshot, type U32 } from "@graphty/graph-format";
23
+
24
+ import { type GpuContext } from "../context.js";
25
+ import { BufferUsage } from "../device/webgpu-constants.js";
26
+ import { isWebGpuGraphError, WebGpuGraphError } from "../errors.js";
27
+ import { plan1d } from "../kernel/dispatch.js";
28
+ import { graphBindings, graphOverrides, kernelSpec, RANGE_PARAMS } from "../kernels.js";
29
+ import { type CoreBinding } from "../memory/residency.js";
30
+ import { type Binding } from "../types/memory.js";
31
+ import { type GpuRunOptions } from "../types/run.js";
32
+
33
+ /**
34
+ * Validates `options.dest` for a result of `n` elements.
35
+ * @param dest - the caller's destination array, if any
36
+ * @param n - the node count
37
+ * @returns the destination as a U32, or null when none was given
38
+ */
39
+ function checkDest(dest: Float32Array | Uint32Array | undefined, n: number): U32 | null {
40
+ if (dest === undefined) {
41
+ return null;
42
+ }
43
+ if (dest instanceof Uint32Array && dest.length === n && dest.buffer instanceof ArrayBuffer) {
44
+ return dest as U32;
45
+ }
46
+ throw new WebGpuGraphError(
47
+ "E_INVALID_ARGUMENT",
48
+ `degree: dest must be a Uint32Array of length ${n} over an ArrayBuffer`,
49
+ {
50
+ argument: "dest",
51
+ value: `${dest.constructor.name}(${dest.length})`,
52
+ expected: `Uint32Array(${n}) over an ArrayBuffer`,
53
+ },
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Uploads (or finds) the core through the residency; a windowed plan, which the residency reports as `E_TOO_LARGE
59
+ * { path: "windowed", algorithm: null }` (3.8), is re-thrown with `algorithm: "degree"` (3.12) and its other details
60
+ * (`needed`, `limit`, `path`) kept. Every other error passes through untouched.
61
+ * @param ctx - the context whose residency holds the core
62
+ * @param s - the snapshot
63
+ * @returns the resident core binding (arena or perArray)
64
+ */
65
+ function coreOf(ctx: GpuContext, s: GraphSnapshot): CoreBinding {
66
+ try {
67
+ return ctx.residency.core(s);
68
+ } catch (error: unknown) {
69
+ if (isWebGpuGraphError(error) && error.code === "E_TOO_LARGE" && error.details.path === "windowed") {
70
+ throw new WebGpuGraphError(
71
+ "E_TOO_LARGE",
72
+ "degree: the arc arrays need a windowed upload, which P1-P3 plan but do not execute",
73
+ { ...error.details, algorithm: "degree" },
74
+ );
75
+ }
76
+ throw error;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * The walking-skeleton kernel, kept public as a diagnostic (spec 3.3): out-degree per node through the row-walking
82
+ * gather with the USE_PERM dummy pattern; equals snapshot.outDegree().
83
+ * @param ctx - the context whose device runs the kernel
84
+ * @param s - the snapshot (uploaded through ctx.residency, or found there)
85
+ * @param options - dest / signal / onProgress (spec 3.3). PLAN DECISION: spelled `?: GpuRunOptions` rather than the
86
+ * contract's `?: GpuRunOptions | undefined` because the root ESLint rule no-duplicate-type-constituents rejects the
87
+ * explicit undefined on an optional parameter (the call signature is identical; P1-T3 made the same choice).
88
+ * @returns the out-degree of every node, index-aligned (`dest` itself when given)
89
+ */
90
+ export async function degree(ctx: GpuContext, s: GraphSnapshot, options?: GpuRunOptions): Promise<U32> {
91
+ ctx.assertReady();
92
+ const n = s.nodeCount;
93
+ const dest = checkDest(options?.dest, n);
94
+ if (options?.signal?.aborted) {
95
+ throw new WebGpuGraphError("E_ABORTED", "degree: the signal was aborted before any work started", {});
96
+ }
97
+ if (n === 0) {
98
+ options?.onProgress?.(1, 1);
99
+ return dest ?? new Uint32Array(0);
100
+ }
101
+ const core = coreOf(ctx, s);
102
+ if (s.arcCount === 0) {
103
+ const zeros = dest ?? new Uint32Array(n);
104
+ zeros.fill(0);
105
+ options?.onProgress?.(1, 1);
106
+ return zeros;
107
+ }
108
+ const byteLength = n * 4;
109
+ const out = ctx.pool.acquire(
110
+ byteLength,
111
+ BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST,
112
+ "degree/out",
113
+ );
114
+ const params = ctx.pool.acquire(
115
+ RANGE_PARAMS.byteLength,
116
+ BufferUsage.UNIFORM | BufferUsage.COPY_DST,
117
+ "degree/params",
118
+ );
119
+ try {
120
+ await ctx.allocator.check();
121
+ const kernel = await ctx.pipelines.kernel(kernelSpec("degree", graphOverrides(core, null)));
122
+ const bytes = new ArrayBuffer(RANGE_PARAMS.byteLength);
123
+ RANGE_PARAMS.write(new DataView(bytes), { start: 0, end: n, arcBase: 0, arcEnd: s.arcCount, accumulate: 0, n });
124
+ ctx.device.queue.writeBuffer(params, 0, bytes);
125
+ const outBinding: Binding = { buffer: out, offset: 0, size: byteLength, window: null };
126
+ const paramsBinding: Binding = { buffer: params, offset: 0, size: RANGE_PARAMS.byteLength, window: null };
127
+ const bound = kernel.bind({ ...graphBindings(core, null), out: outBinding, P: paramsBinding });
128
+ const encoder = ctx.device.createCommandEncoder({ label: "degree" });
129
+ const pass = encoder.beginComputePass({ label: "degree" });
130
+ kernel.dispatch(pass, bound, plan1d(n, ctx.workgroupSize, ctx.caps), [0]);
131
+ pass.end();
132
+ ctx.device.queue.submit([encoder.finish()]);
133
+ ctx.assertReady();
134
+ const result = await ctx.readback.read(out, byteLength, dest ?? undefined);
135
+ ctx.assertReady();
136
+ options?.onProgress?.(1, 1);
137
+ return dest ?? new Uint32Array(result);
138
+ } finally {
139
+ ctx.pool.release(params);
140
+ ctx.pool.release(out);
141
+ }
142
+ }
@@ -0,0 +1,57 @@
1
+ /// <reference types="@webgpu/types" preserve="true" />
2
+ /**
3
+ * The ./browser entry (spec 2.1, 2.3, 3.4; contract 3.6): the only directory of the package allowed to read
4
+ * navigator.gpu. probeBrowserWebGpu never throws; requestGpuContext tags the context runtime "browser".
5
+ */
6
+
7
+ import { GpuContext } from "../context.js";
8
+ import { WebGpuGraphError } from "../errors.js";
9
+ import type { GpuContextOptions, ProbeResult } from "../types/context.js";
10
+
11
+ /** Options of the browser helpers (spec 3.4); a type alias, not an empty `extends` interface, which strictTypeChecked's no-empty-object-type (allowInterfaces "never") reports. */
12
+ export type BrowserGpuOptions = Omit<GpuContextOptions, "gpu" | "device" | "runtime">;
13
+
14
+ /**
15
+ * navigator.gpu, or undefined when the runtime has no navigator or no WebGPU (Node 22 has a navigator
16
+ * without gpu; browsers without WebGPU have navigator.gpu undefined).
17
+ * @returns the GPU object or undefined
18
+ */
19
+ function navigatorGpu(): GPU | undefined {
20
+ if (typeof navigator === "undefined") {
21
+ return undefined;
22
+ }
23
+ const candidate: { readonly gpu?: GPU | undefined } = navigator;
24
+ return candidate.gpu;
25
+ }
26
+
27
+ /**
28
+ * navigator.gpu absent -> { ok: false, code: "E_NO_WEBGPU" }; else GpuContext.probe. Never throws.
29
+ * @param options - the power preference and the software policy
30
+ * @returns the probe result
31
+ */
32
+ export function probeBrowserWebGpu(options?: BrowserGpuOptions): Promise<ProbeResult> {
33
+ return GpuContext.probe({
34
+ gpu: navigatorGpu(),
35
+ powerPreference: options?.powerPreference ?? "high-performance",
36
+ rejectSoftware: options?.rejectSoftware,
37
+ });
38
+ }
39
+
40
+ /**
41
+ * GpuContext.create({ gpu: navigator.gpu, powerPreference: "high-performance", runtime: "browser", ...options });
42
+ * pass `{ adapter: probe.adapter }` to reuse the probed adapter; create() honours rejectSoftware.
43
+ * @param options - see BrowserGpuOptions
44
+ * @returns the context
45
+ */
46
+ export function requestGpuContext(options?: BrowserGpuOptions): Promise<GpuContext> {
47
+ const gpu = navigatorGpu();
48
+ if (gpu === undefined && options?.adapter === undefined) {
49
+ return Promise.reject(
50
+ new WebGpuGraphError("E_NO_WEBGPU", "navigator.gpu is undefined: this browser or context has no WebGPU", {
51
+ reason: "navigator.gpu is undefined",
52
+ hint: "WebGPU needs a supporting browser and a secure context (https or localhost)",
53
+ }),
54
+ );
55
+ }
56
+ return GpuContext.create({ powerPreference: "high-performance", ...options, gpu, runtime: "browser" });
57
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Every numeric constant the package and the WGSL prelude share (spec 3.1, 3.5, 5.2, 7.8, 7.14, 7.17;
3
+ * contract 3.2). The prelude (src/kernel/prelude.ts, P1-T3) interpolates these values and never retypes them
4
+ * as literals (the literal grep of spec 3.5 enforces it); the planners read them; test/device/constants.test.ts
5
+ * pins them. graph-format's INVALID_INDEX is imported by the prelude directly and is deliberately not copied.
6
+ */
7
+
8
+ /** Workgroup size of every 1D kernel; `WG = min(WORKGROUP_SIZE, caps.limits.maxComputeInvocationsPerWorkgroup)` at runtime (spec 5.1). */
9
+ export const WORKGROUP_SIZE = 256;
10
+ /** The spec minimum of maxComputeWorkgroupsPerDimension; asserted equal to the device limit at create() (spec 2.2, 5.2). */
11
+ export const MAX_WORKGROUPS_PER_DIM = 65535;
12
+ /** Items a 1D dispatch of WORKGROUP_SIZE covers: 65535 x 256 = 16,776,960, NOT 2^24 (design 10.6). */
13
+ export const MAX_1D_ITEMS = MAX_WORKGROUPS_PER_DIM * WORKGROUP_SIZE;
14
+ /** The largest u32 (the `min` identity of the u32 reduce); interpolated into the prelude as `U32_MAX` so no body types the literal (contract 4.1). */
15
+ export const U32_MAX = 0xffffffff;
16
+ /** Arc-window boundaries are multiples of 64 arcs = 256 bytes (design 10.6). */
17
+ export const ARC_WINDOW_ALIGN = 64;
18
+ /** Storage-binding offset alignment the package always honours (spec 2.6): the graph-format arena is 256-aligned. */
19
+ export const STORAGE_ALIGN = 256;
20
+ /** Stride of one UniformRing slot: minUniformBufferOffsetAlignment is 256 on every runtime the package targets (spec 5.3). */
21
+ export const UNIFORM_SLOT_BYTES = 256;
22
+ /**
23
+ * Exact-tier crossover default, re-fixed at G3 by the spec 7.8 rule (spec Q-6; docs/decisions/G3.md section 3): the
24
+ * largest rung of the T-4 ladder (1k / 4k / 8k / 16k / 32k / 65k, E = 10n, 2D) with <= 4 ms per iteration, rounded down
25
+ * to a power of two. Measured on the RTX 4070 SUPER under Dawn-node: benchmarks/results/nvidia-lovelace-driver580.json,
26
+ * session 2026-09-16T02:07:45.933Z, the "ms/iteration (profiler)" rows (the GPU time of the iteration's passes at the
27
+ * card's working clock; the step(1) wall rows beside them include the 12n readback): 2.560 ms at 32k, 8.405 ms at 65k.
28
+ * The rule's second clause -- not slower than the grid tier at the same n -- has no grid tier to compare with in P3 and
29
+ * is re-checked at G4 (spec 7.8). A consumer whose GPU differs (integrated, Apple, T4) passes its own value through
30
+ * createAccelerator(ctx, { layout: { exactMaxNodes } }); P4's calibrateLayout(ctx) measures it.
31
+ */
32
+ export const EXACT_MAX_NODES = 32768;
33
+ /** Default number of MAP_READ staging buffers in the Readback ring (spec 4.4). */
34
+ export const DEFAULT_STAGING_SLOTS = 3;
35
+ /** Timestamp query-set size of the Profiler (spec 5.5: "a query set of 256 slots"; 2 slots per pass). */
36
+ export const PROFILER_QUERY_SLOTS = 256;
37
+ /** Byte size above which createBuffer runs inside an "out-of-memory" error scope (spec 5.7). */
38
+ export const OOM_SCOPE_THRESHOLD_BYTES = 16 * 1024 * 1024;
39
+ /** Idle buffers kept per (size class, usage) by the BufferPool (spec 4.4). */
40
+ export const POOL_MAX_IDLE_PER_CLASS = 4;
41
+ /** Smallest power-of-two pool class (spec 4.4). */
42
+ export const POOL_MIN_CLASS_BYTES = 4 * 1024;
43
+ /** Largest power-of-two pool class; above it the classes grow linearly (spec 4.4). */
44
+ export const POOL_MAX_POW2_CLASS_BYTES = 64 * 1024 * 1024;
45
+ /** The linear step of the pool classes above the largest power of two (spec 4.4). */
46
+ export const POOL_LINEAR_STEP_BYTES = 16 * 1024 * 1024;
47
+ /** Default `warnUnreleasedSnapshots` (spec 2.2, 4.1). */
48
+ export const DEFAULT_WARN_UNRELEASED_SNAPSHOTS = 2;
49
+ /** CONTRACT DECISION: the largest `iterations` a single step() records (the trace region and the uniform ring are sized by it); larger values are E_INVALID_ARGUMENT. */
50
+ export const MAX_ITERATIONS_PER_STEP = 256;
51
+ /** Bytes of one Fa2Trace record (spec 7.3: 32-byte records). */
52
+ export const TRACE_RECORD_BYTES = 32;
53
+ /** CONTRACT DECISION: the state header is padded to 256 bytes so the trace region that follows it in the same buffer starts at a legal 256-aligned binding offset (spec 7.3 says "128 + k x 32"; 128 is not a legal storage offset). */
54
+ export const STATE_HEADER_BYTES = 256;
55
+ /** Bytes of one per-workgroup partials record (spec 7.3: exactly 64 B). */
56
+ export const PARTIAL_BYTES = 64;
57
+ /** ForceAtlas2 defaults (spec 7.14, 7.17, 7.19). */
58
+ export const FA2_DEFAULTS: Readonly<{
59
+ maxIter: 100;
60
+ jitterTolerance: 1;
61
+ scalingRatio: 2;
62
+ gravity: 1;
63
+ strongGravity: false;
64
+ distributedAction: false;
65
+ linlog: false;
66
+ dissuadeHubs: false;
67
+ dim: 2;
68
+ scale: 1;
69
+ settleThreshold: 0.001;
70
+ settleWindow: 10;
71
+ iterationsPerStep: 1;
72
+ maxInFlight: 2;
73
+ }> = Object.freeze({
74
+ maxIter: 100,
75
+ jitterTolerance: 1,
76
+ scalingRatio: 2,
77
+ gravity: 1,
78
+ strongGravity: false,
79
+ distributedAction: false,
80
+ linlog: false,
81
+ dissuadeHubs: false,
82
+ dim: 2,
83
+ scale: 1,
84
+ settleThreshold: 0.001,
85
+ settleWindow: 10,
86
+ iterationsPerStep: 1,
87
+ maxInFlight: 2,
88
+ });
89
+ /** GPU-only layout tuning defaults (spec 7.14): repulsion "auto", exactMaxNodes EXACT_MAX_NODES, nearMax 64, deterministic true, gridMax2D 512, gridMax3D 128, extentFactor 6, compat "paper". */
90
+ export const LAYOUT_TUNING_DEFAULTS: Readonly<{
91
+ repulsion: "auto";
92
+ exactMaxNodes: number;
93
+ nearMax: 64;
94
+ deterministic: true;
95
+ gridMax2D: 512;
96
+ gridMax3D: 128;
97
+ extentFactor: 6;
98
+ compat: "paper";
99
+ }> = Object.freeze({
100
+ repulsion: "auto",
101
+ exactMaxNodes: EXACT_MAX_NODES,
102
+ nearMax: 64,
103
+ deterministic: true,
104
+ gridMax2D: 512,
105
+ gridMax3D: 128,
106
+ extentFactor: 6,
107
+ compat: "paper",
108
+ });
109
+ /** The distance floor `max(d, 0.01)` of spec 7.2; interpolated into the prelude (contract 4.1). */
110
+ export const FA2_DISTANCE_FLOOR = 0.01;
111
+ /** The square of FA2_DISTANCE_FLOOR. */
112
+ export const FA2_DISTANCE_FLOOR_SQ = 0.0001;
113
+ /** The coincident threshold `d^2 < 1e-8` of spec 7.2. */
114
+ export const FA2_COINCIDENT_SQ = 1e-8;
115
+ /** Bits of Fa2Params.flags (contract 4.4). */
116
+ export const FA2_FLAG_FIRST = 1;