@graphty/webgpu-graph-algorithms 0.5.0 → 0.5.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 (88) hide show
  1. package/README.md +27 -21
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{context-CRbw2Wyo.js → context-BR7fx3vR.js} +47 -5
  4. package/dist/chunks/context-BR7fx3vR.js.map +1 -0
  5. package/dist/node.js +1 -1
  6. package/dist/src/accelerator.d.ts +12 -10
  7. package/dist/src/accelerator.d.ts.map +1 -1
  8. package/dist/src/accelerator.js +32 -10
  9. package/dist/src/accelerator.js.map +1 -1
  10. package/dist/src/constants.d.ts +47 -0
  11. package/dist/src/constants.d.ts.map +1 -1
  12. package/dist/src/constants.js +47 -0
  13. package/dist/src/constants.js.map +1 -1
  14. package/dist/src/index.d.ts +7 -4
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/index.js +9 -5
  17. package/dist/src/index.js.map +1 -1
  18. package/dist/src/kernel/prelude.d.ts.map +1 -1
  19. package/dist/src/kernel/prelude.js +4 -1
  20. package/dist/src/kernel/prelude.js.map +1 -1
  21. package/dist/src/kernels.d.ts +3 -3
  22. package/dist/src/kernels.d.ts.map +1 -1
  23. package/dist/src/kernels.js +27 -11
  24. package/dist/src/kernels.js.map +1 -1
  25. package/dist/src/layouts/force-simulation.d.ts +3 -1
  26. package/dist/src/layouts/force-simulation.d.ts.map +1 -1
  27. package/dist/src/layouts/force-simulation.js +13 -3
  28. package/dist/src/layouts/force-simulation.js.map +1 -1
  29. package/dist/src/layouts/forceatlas2.d.ts +1 -3
  30. package/dist/src/layouts/forceatlas2.d.ts.map +1 -1
  31. package/dist/src/layouts/forceatlas2.js +2 -191
  32. package/dist/src/layouts/forceatlas2.js.map +1 -1
  33. package/dist/src/layouts/fruchterman-reingold.d.ts +195 -0
  34. package/dist/src/layouts/fruchterman-reingold.d.ts.map +1 -0
  35. package/dist/src/layouts/fruchterman-reingold.js +579 -0
  36. package/dist/src/layouts/fruchterman-reingold.js.map +1 -0
  37. package/dist/src/layouts/model-common.d.ts +102 -0
  38. package/dist/src/layouts/model-common.d.ts.map +1 -0
  39. package/dist/src/layouts/model-common.js +198 -0
  40. package/dist/src/layouts/model-common.js.map +1 -0
  41. package/dist/src/layouts/spring-electrical.d.ts +179 -0
  42. package/dist/src/layouts/spring-electrical.d.ts.map +1 -0
  43. package/dist/src/layouts/spring-electrical.js +508 -0
  44. package/dist/src/layouts/spring-electrical.js.map +1 -0
  45. package/dist/src/types/accelerator.d.ts +7 -3
  46. package/dist/src/types/accelerator.d.ts.map +1 -1
  47. package/dist/src/types/layout.d.ts +32 -0
  48. package/dist/src/types/layout.d.ts.map +1 -1
  49. package/dist/src/types/options.d.ts +43 -1
  50. package/dist/src/types/options.d.ts.map +1 -1
  51. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +5 -2
  52. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -1
  53. package/dist/src/wgsl/fa2-attraction.wgsl.js +6 -1
  54. package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -1
  55. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +7 -2
  56. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -1
  57. package/dist/src/wgsl/fa2-integrate.wgsl.js +28 -2
  58. package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -1
  59. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +4 -2
  60. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -1
  61. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +14 -5
  62. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -1
  63. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +8 -1
  64. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -1
  65. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +33 -0
  66. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -1
  67. package/dist/tsconfig.build.tsbuildinfo +1 -1
  68. package/dist/webgpu-graph-algorithms.js +1358 -284
  69. package/dist/webgpu-graph-algorithms.js.map +1 -1
  70. package/package.json +6 -4
  71. package/src/accelerator.ts +46 -12
  72. package/src/constants.ts +70 -0
  73. package/src/index.ts +15 -5
  74. package/src/kernel/prelude.ts +6 -0
  75. package/src/kernels.ts +27 -11
  76. package/src/layouts/force-simulation.ts +20 -3
  77. package/src/layouts/forceatlas2.ts +17 -220
  78. package/src/layouts/fruchterman-reingold.ts +737 -0
  79. package/src/layouts/model-common.ts +228 -0
  80. package/src/layouts/spring-electrical.ts +666 -0
  81. package/src/types/accelerator.ts +15 -3
  82. package/src/types/layout.ts +36 -0
  83. package/src/types/options.ts +45 -1
  84. package/src/wgsl/fa2-attraction.wgsl.ts +6 -1
  85. package/src/wgsl/fa2-integrate.wgsl.ts +28 -2
  86. package/src/wgsl/fa2-repulsion-exact.wgsl.ts +14 -5
  87. package/src/wgsl/fa2-stats-finalize.wgsl.ts +33 -0
  88. package/dist/chunks/context-CRbw2Wyo.js.map +0 -1
@@ -0,0 +1,228 @@
1
+ /**
2
+ * The option and value helpers every force model's resolver and stats decoder share (PD-7): moved verbatim from
3
+ * src/layouts/forceatlas2.ts (P3-T2) so the Fruchterman-Reingold and spring-electrical models of P5 neither copy
4
+ * them nor import a sibling model. Layout zone; imports errors.ts only.
5
+ */
6
+
7
+ import { WebGpuGraphError } from "../errors.js";
8
+ import { type UniformValues } from "../kernel/struct-block.js";
9
+
10
+ /** An override record as the kernel layer takes it. */
11
+ export type Overrides = Readonly<Record<string, number | boolean>>;
12
+
13
+ /** Bytes of the stride-3 f32 force arrays per node. */
14
+ export const FORCE_BYTES_PER_NODE = 12;
15
+
16
+ /** The name of the model-owned FillParams buffer (a BufferSpec, reached through ModelResources.buffer). */
17
+ export const FILL_PARAMS_BUFFER = "fillParams";
18
+
19
+ /** 2^32, the modulus of the u32 seed word (computed with `%`, never a bitwise operator). */
20
+ const U32_MODULUS = 4294967296;
21
+
22
+ /**
23
+ * A short, safe rendering of an argument value for error messages (never String() on an object).
24
+ * @param value - the value
25
+ * @returns the rendering
26
+ */
27
+ export function describeValue(value: unknown): string {
28
+ if (value === null) {
29
+ return "null";
30
+ }
31
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
32
+ return String(value);
33
+ }
34
+ if (typeof value === "undefined") {
35
+ return "undefined";
36
+ }
37
+ if (typeof value === "object" && "length" in value && typeof value.length === "number") {
38
+ return `[${value.length} values]`;
39
+ }
40
+ return typeof value;
41
+ }
42
+
43
+ /**
44
+ * The E_INVALID_ARGUMENT error of an option check (contract 3.1: { argument, value, expected }).
45
+ * @param argument - the option name
46
+ * @param value - the value given
47
+ * @param expected - what was expected
48
+ * @returns the error (not thrown here)
49
+ */
50
+ export function invalid(argument: string, value: unknown, expected: string): WebGpuGraphError {
51
+ return new WebGpuGraphError("E_INVALID_ARGUMENT", `${argument} must be ${expected}; got ${describeValue(value)}`, {
52
+ argument,
53
+ value,
54
+ expected,
55
+ });
56
+ }
57
+
58
+ /**
59
+ * A numeric option: the given value when defined, else the fallback; validated by `check` (the value is checked as
60
+ * `unknown` so a JS caller's string or object is E_INVALID_ARGUMENT too).
61
+ * @param name - the option name
62
+ * @param given - the value given (undefined = absent)
63
+ * @param fallback - the previous record's value or the default
64
+ * @param check - the range predicate over a finite number
65
+ * @param expected - the range in words (the error message)
66
+ * @returns the value
67
+ */
68
+ export function pickNumber(
69
+ name: string,
70
+ given: number | undefined,
71
+ fallback: number,
72
+ check: (value: number) => boolean,
73
+ expected: string,
74
+ ): number {
75
+ const value: unknown = given === undefined ? fallback : given;
76
+ if (typeof value !== "number" || !Number.isFinite(value) || !check(value)) {
77
+ throw invalid(name, value, expected);
78
+ }
79
+ return value;
80
+ }
81
+
82
+ /**
83
+ * A boolean option: the given value when defined, else the fallback; a non-boolean is E_INVALID_ARGUMENT.
84
+ * @param name - the option name
85
+ * @param given - the value given (undefined = absent)
86
+ * @param fallback - the previous record's value or the default
87
+ * @returns the value
88
+ */
89
+ export function pickBoolean(name: string, given: boolean | undefined, fallback: boolean): boolean {
90
+ const value: unknown = given === undefined ? fallback : given;
91
+ if (typeof value !== "boolean") {
92
+ throw invalid(name, value, "a boolean");
93
+ }
94
+ return value;
95
+ }
96
+
97
+ /**
98
+ * The layout dimension: 2 or 3.
99
+ * @param given - the value given (undefined = absent)
100
+ * @param fallback - the previous record's value or the default
101
+ * @returns 2 or 3
102
+ */
103
+ export function pickDim(given: 2 | 3 | undefined, fallback: 2 | 3): 2 | 3 {
104
+ const value: unknown = given === undefined ? fallback : given;
105
+ if (value !== 2 && value !== 3) {
106
+ throw invalid("dim", value, "2 or 3");
107
+ }
108
+ return value;
109
+ }
110
+
111
+ /**
112
+ * The scene-unit center: an array-like of 2 (z = 0) or 3 finite numbers.
113
+ * @param given - the value given (undefined = absent)
114
+ * @param fallback - the previous record's value or the default
115
+ * @returns the three components
116
+ */
117
+ export function pickCenter(
118
+ given: ArrayLike<number> | undefined,
119
+ fallback: readonly [number, number, number],
120
+ ): readonly [number, number, number] {
121
+ if (given === undefined) {
122
+ return fallback;
123
+ }
124
+ const expected = "an array of 2 or 3 finite numbers";
125
+ const value: unknown = given;
126
+ if (typeof value !== "object" || value === null || !("length" in value)) {
127
+ throw invalid("center", given, expected);
128
+ }
129
+ const { length } = value;
130
+ if (length !== 2 && length !== 3) {
131
+ throw invalid("center", given, expected);
132
+ }
133
+ const x: unknown = given[0];
134
+ const y: unknown = given[1];
135
+ const z: unknown = length === 3 ? given[2] : 0;
136
+ if (
137
+ typeof x !== "number" ||
138
+ typeof y !== "number" ||
139
+ typeof z !== "number" ||
140
+ !Number.isFinite(x) ||
141
+ !Number.isFinite(y) ||
142
+ !Number.isFinite(z)
143
+ ) {
144
+ throw invalid("center", given, expected);
145
+ }
146
+ return [x, y, z];
147
+ }
148
+
149
+ /**
150
+ * The seed: a finite number, or null (unseeded; 0 keeps the port's "0 = unseeded" quirk through the Lcg).
151
+ * @param given - the value given (undefined = absent)
152
+ * @param fallback - the previous record's value or the default
153
+ * @returns the seed or null
154
+ */
155
+ export function pickSeed(given: number | null | undefined, fallback: number | null): number | null {
156
+ if (given === undefined) {
157
+ return fallback;
158
+ }
159
+ const value: unknown = given;
160
+ if (value !== null && (typeof value !== "number" || !Number.isFinite(value))) {
161
+ throw invalid("seed", given, "a finite number or null");
162
+ }
163
+ return value;
164
+ }
165
+
166
+ /**
167
+ * Integer >= 1.
168
+ * @param value - a finite number
169
+ * @returns whether it is a positive integer
170
+ */
171
+ export function isPositiveInteger(value: number): boolean {
172
+ return Number.isInteger(value) && value >= 1;
173
+ }
174
+
175
+ /**
176
+ * The u32 word written into Fa2Params.seed: 0 for null, else floor(|seed|) mod 2^32.
177
+ * @param seed - the resolved seed
178
+ * @returns the u32 value
179
+ */
180
+ export function seedWord(seed: number | null): number {
181
+ if (seed === null) {
182
+ return 0;
183
+ }
184
+ return Math.floor(Math.abs(seed)) % U32_MODULUS;
185
+ }
186
+
187
+ /**
188
+ * A scalar field of a block's read() result.
189
+ * @param values - the values read
190
+ * @param name - the field name
191
+ * @returns the number
192
+ */
193
+ export function scalar(values: UniformValues, name: string): number {
194
+ const value = values[name];
195
+ if (typeof value !== "number") {
196
+ throw invalid(name, value, "a scalar field");
197
+ }
198
+ return value;
199
+ }
200
+
201
+ /**
202
+ * A vector field of a block's read() result.
203
+ * @param values - the values read
204
+ * @param name - the field name
205
+ * @returns the components
206
+ */
207
+ export function vector(values: UniformValues, name: string): readonly number[] {
208
+ const value = values[name];
209
+ if (typeof value === "number") {
210
+ throw invalid(name, value, "a vector field");
211
+ }
212
+ return value;
213
+ }
214
+
215
+ /**
216
+ * The override record a kernel gets: its defaults overlaid with the values present in the merged set (contract 3.9:
217
+ * a name a spec does not declare is rejected at compose time, so nothing else is passed through).
218
+ * @param merged - the merged override set of the model (plus USE_PERM / HAS_WEIGHTS from the simulation)
219
+ * @param defaults - the kernel's accepted names with their defaults
220
+ * @returns the kernel's override record, every accepted name explicit
221
+ */
222
+ export function subset(merged: Overrides, defaults: Overrides): Overrides {
223
+ const out: Record<string, number | boolean> = {};
224
+ for (const name of Object.keys(defaults)) {
225
+ out[name] = name in merged ? merged[name] : defaults[name];
226
+ }
227
+ return out;
228
+ }