@graphty/webgpu-graph-algorithms 0.4.1 → 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.
- package/README.md +27 -21
- package/dist/browser.js +1 -1
- package/dist/chunks/{context-CRbw2Wyo.js → context-BR7fx3vR.js} +47 -5
- package/dist/chunks/context-BR7fx3vR.js.map +1 -0
- package/dist/node.js +1 -1
- package/dist/src/accelerator.d.ts +15 -12
- package/dist/src/accelerator.d.ts.map +1 -1
- package/dist/src/accelerator.js +35 -12
- package/dist/src/accelerator.js.map +1 -1
- package/dist/src/constants.d.ts +47 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +47 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +8 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernel/prelude.d.ts.map +1 -1
- package/dist/src/kernel/prelude.js +4 -1
- package/dist/src/kernel/prelude.js.map +1 -1
- package/dist/src/kernels.d.ts +3 -3
- package/dist/src/kernels.d.ts.map +1 -1
- package/dist/src/kernels.js +27 -11
- package/dist/src/kernels.js.map +1 -1
- package/dist/src/layouts/force-simulation.d.ts +3 -1
- package/dist/src/layouts/force-simulation.d.ts.map +1 -1
- package/dist/src/layouts/force-simulation.js +13 -3
- package/dist/src/layouts/force-simulation.js.map +1 -1
- package/dist/src/layouts/forceatlas2.d.ts +1 -3
- package/dist/src/layouts/forceatlas2.d.ts.map +1 -1
- package/dist/src/layouts/forceatlas2.js +2 -191
- package/dist/src/layouts/forceatlas2.js.map +1 -1
- package/dist/src/layouts/fruchterman-reingold.d.ts +195 -0
- package/dist/src/layouts/fruchterman-reingold.d.ts.map +1 -0
- package/dist/src/layouts/fruchterman-reingold.js +579 -0
- package/dist/src/layouts/fruchterman-reingold.js.map +1 -0
- package/dist/src/layouts/model-common.d.ts +102 -0
- package/dist/src/layouts/model-common.d.ts.map +1 -0
- package/dist/src/layouts/model-common.js +198 -0
- package/dist/src/layouts/model-common.js.map +1 -0
- package/dist/src/layouts/spring-electrical.d.ts +179 -0
- package/dist/src/layouts/spring-electrical.d.ts.map +1 -0
- package/dist/src/layouts/spring-electrical.js +508 -0
- package/dist/src/layouts/spring-electrical.js.map +1 -0
- package/dist/src/types/accelerator.d.ts +14 -157
- package/dist/src/types/accelerator.d.ts.map +1 -1
- package/dist/src/types/accelerator.js +4 -5
- package/dist/src/types/accelerator.js.map +1 -1
- package/dist/src/types/algorithms.d.ts +1 -1
- package/dist/src/types/algorithms.js +1 -1
- package/dist/src/types/layout.d.ts +32 -0
- package/dist/src/types/layout.d.ts.map +1 -1
- package/dist/src/types/options.d.ts +43 -1
- package/dist/src/types/options.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +5 -2
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-attraction.wgsl.js +6 -1
- package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -1
- package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +7 -2
- package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-integrate.wgsl.js +28 -2
- package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -1
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +4 -2
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +14 -5
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +8 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +33 -0
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/webgpu-graph-algorithms.js +1358 -284
- package/dist/webgpu-graph-algorithms.js.map +1 -1
- package/package.json +6 -3
- package/src/accelerator.ts +49 -14
- package/src/constants.ts +70 -0
- package/src/index.ts +19 -8
- package/src/kernel/prelude.ts +6 -0
- package/src/kernels.ts +27 -11
- package/src/layouts/force-simulation.ts +20 -3
- package/src/layouts/forceatlas2.ts +17 -220
- package/src/layouts/fruchterman-reingold.ts +737 -0
- package/src/layouts/model-common.ts +228 -0
- package/src/layouts/spring-electrical.ts +666 -0
- package/src/types/accelerator.ts +58 -174
- package/src/types/algorithms.ts +1 -1
- package/src/types/layout.ts +36 -0
- package/src/types/options.ts +45 -1
- package/src/wgsl/fa2-attraction.wgsl.ts +6 -1
- package/src/wgsl/fa2-integrate.wgsl.ts +28 -2
- package/src/wgsl/fa2-repulsion-exact.wgsl.ts +14 -5
- package/src/wgsl/fa2-stats-finalize.wgsl.ts +33 -0
- 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
|
+
}
|