@its-not-rocket-science/ananke 0.1.14 → 0.1.15
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/CHANGELOG.md +27 -0
- package/dist/as/injury.wasm +0 -0
- package/dist/as/injury.wat +382 -0
- package/dist/as/push.wasm +0 -0
- package/dist/as/push.wat +326 -0
- package/dist/as/units.wasm +0 -0
- package/dist/as/units.wat +290 -0
- package/dist/src/wasm-kernel.d.ts +58 -0
- package/dist/src/wasm-kernel.js +96 -0
- package/package.json +14 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,33 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [0.1.15] — 2026-03-25
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **CE-5 · WebAssembly Kernel** — shadow-mode WASM acceleration for push repulsion and
|
|
14
|
+
injury accumulation:
|
|
15
|
+
- `as/units.ts` — AssemblyScript port of `src/units.ts` (all 13 exports: SCALE constants,
|
|
16
|
+
`q()`, `clampQ()`, `qMul()`, `qDiv()`, `mulDiv()`, `sqrtQ()`, `cbrtQ()`, unit
|
|
17
|
+
converters). Compiled to `dist/as/units.wasm`.
|
|
18
|
+
- `as/push.ts` — pair-wise position repulsion kernel in flat WASM memory (64-entity
|
|
19
|
+
capacity, octagonal distance approximation, overflow-safe i64 arithmetic).
|
|
20
|
+
Compiled to `dist/as/push.wasm`.
|
|
21
|
+
- `as/injury.ts` — per-entity injury accumulation inner loop (clotting, bleed→fluid,
|
|
22
|
+
shock, consciousness, death check) matching `src/sim/step/injury.ts` constants exactly.
|
|
23
|
+
Compiled to `dist/as/injury.wasm`.
|
|
24
|
+
- `src/wasm-kernel.ts` — Node.js host bridge. `WasmKernel.shadowStep(world, tick)`
|
|
25
|
+
marshals entity state into WASM memory, runs both kernels, and returns a
|
|
26
|
+
`WasmStepReport` with per-entity velocity deltas and projected vitals. Shadow mode:
|
|
27
|
+
outputs are never applied to world state — used for validation and diagnostics only.
|
|
28
|
+
- `loadWasmKernel()` factory loads `push.wasm` + `injury.wasm` from `dist/as/` at
|
|
29
|
+
runtime via `import.meta.url` + `readFileSync`.
|
|
30
|
+
- Exported as `@its-not-rocket-science/ananke/wasm-kernel`.
|
|
31
|
+
- `dist/as/` (compiled WASM binaries) included in the published package.
|
|
32
|
+
- 61 WASM unit tests (`test/as/`) covering units, push repulsion, and injury
|
|
33
|
+
accumulation parity with the TypeScript reference implementation.
|
|
34
|
+
- Build scripts: `npm run build:wasm:all`, `npm run test:wasm`.
|
|
35
|
+
|
|
9
36
|
## [Unreleased]
|
|
10
37
|
|
|
11
38
|
### Added
|
|
Binary file
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
(module
|
|
2
|
+
(type $0 (func (param i32) (result i32)))
|
|
3
|
+
(type $1 (func (param i32 i32 i32 i32 i32 i32 i32)))
|
|
4
|
+
(type $2 (func (param i32 i32 i32 i32 i32 i32)))
|
|
5
|
+
(type $3 (func (param i32 i32) (result i32)))
|
|
6
|
+
(type $4 (func (param i32)))
|
|
7
|
+
(global $as/injury/SHOCK_FROM_FLUID i32 (i32.const 40))
|
|
8
|
+
(global $as/injury/SHOCK_FROM_INTERNAL i32 (i32.const 20))
|
|
9
|
+
(global $as/injury/CONSC_LOSS_FROM_SHOCK i32 (i32.const 100))
|
|
10
|
+
(global $as/injury/CONSC_LOSS_FROM_SUFF i32 (i32.const 200))
|
|
11
|
+
(global $as/injury/FATAL_FLUID_LOSS i32 (i32.const 8000))
|
|
12
|
+
(global $as/injury/CLOT_RATE_PER_TICK i32 (i32.const 2))
|
|
13
|
+
(global $as/injury/MAX_ENTITIES i32 (i32.const 64))
|
|
14
|
+
(global $as/injury/N_REGIONS i32 (i32.const 6))
|
|
15
|
+
(global $as/injury/ENTITY_STRIDE i32 (i32.const 120))
|
|
16
|
+
(memory $0 1)
|
|
17
|
+
(export "SHOCK_FROM_FLUID" (global $as/injury/SHOCK_FROM_FLUID))
|
|
18
|
+
(export "SHOCK_FROM_INTERNAL" (global $as/injury/SHOCK_FROM_INTERNAL))
|
|
19
|
+
(export "CONSC_LOSS_FROM_SHOCK" (global $as/injury/CONSC_LOSS_FROM_SHOCK))
|
|
20
|
+
(export "CONSC_LOSS_FROM_SUFF" (global $as/injury/CONSC_LOSS_FROM_SUFF))
|
|
21
|
+
(export "FATAL_FLUID_LOSS" (global $as/injury/FATAL_FLUID_LOSS))
|
|
22
|
+
(export "CLOT_RATE_PER_TICK" (global $as/injury/CLOT_RATE_PER_TICK))
|
|
23
|
+
(export "MAX_ENTITIES" (global $as/injury/MAX_ENTITIES))
|
|
24
|
+
(export "N_REGIONS" (global $as/injury/N_REGIONS))
|
|
25
|
+
(export "ENTITY_STRIDE" (global $as/injury/ENTITY_STRIDE))
|
|
26
|
+
(export "writeVitals" (func $as/injury/writeVitals))
|
|
27
|
+
(export "writeRegion" (func $as/injury/writeRegion))
|
|
28
|
+
(export "readFluidLoss" (func $as/injury/readFluidLoss))
|
|
29
|
+
(export "readShock" (func $as/injury/readShock))
|
|
30
|
+
(export "readConsciousness" (func $as/injury/readConsciousness))
|
|
31
|
+
(export "readDead" (func $as/injury/readDead))
|
|
32
|
+
(export "readBleedingRate" (func $as/injury/readBleedingRate))
|
|
33
|
+
(export "stepBleedAndShock" (func $as/injury/stepBleedAndShock))
|
|
34
|
+
(export "memory" (memory $0))
|
|
35
|
+
(func $as/injury/writeVitals (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32)
|
|
36
|
+
local.get $0
|
|
37
|
+
i32.const 120
|
|
38
|
+
i32.mul
|
|
39
|
+
local.tee $0
|
|
40
|
+
local.get $1
|
|
41
|
+
i32.store
|
|
42
|
+
local.get $0
|
|
43
|
+
local.get $2
|
|
44
|
+
i32.store offset=4
|
|
45
|
+
local.get $0
|
|
46
|
+
local.get $3
|
|
47
|
+
i32.store offset=8
|
|
48
|
+
local.get $0
|
|
49
|
+
local.get $4
|
|
50
|
+
i32.store offset=12
|
|
51
|
+
local.get $0
|
|
52
|
+
local.get $5
|
|
53
|
+
i32.store offset=16
|
|
54
|
+
local.get $0
|
|
55
|
+
local.get $6
|
|
56
|
+
i32.store offset=20
|
|
57
|
+
)
|
|
58
|
+
(func $as/injury/writeRegion (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32)
|
|
59
|
+
local.get $0
|
|
60
|
+
i32.const 120
|
|
61
|
+
i32.mul
|
|
62
|
+
local.tee $0
|
|
63
|
+
local.get $1
|
|
64
|
+
i32.const 2
|
|
65
|
+
i32.shl
|
|
66
|
+
local.tee $1
|
|
67
|
+
i32.const 6
|
|
68
|
+
i32.add
|
|
69
|
+
i32.const 2
|
|
70
|
+
i32.shl
|
|
71
|
+
i32.add
|
|
72
|
+
local.get $2
|
|
73
|
+
i32.store
|
|
74
|
+
local.get $0
|
|
75
|
+
local.get $1
|
|
76
|
+
i32.const 7
|
|
77
|
+
i32.add
|
|
78
|
+
i32.const 2
|
|
79
|
+
i32.shl
|
|
80
|
+
i32.add
|
|
81
|
+
local.get $3
|
|
82
|
+
i32.store
|
|
83
|
+
local.get $0
|
|
84
|
+
local.get $1
|
|
85
|
+
i32.const 8
|
|
86
|
+
i32.add
|
|
87
|
+
i32.const 2
|
|
88
|
+
i32.shl
|
|
89
|
+
i32.add
|
|
90
|
+
local.get $4
|
|
91
|
+
i32.store
|
|
92
|
+
local.get $0
|
|
93
|
+
local.get $1
|
|
94
|
+
i32.const 9
|
|
95
|
+
i32.add
|
|
96
|
+
i32.const 2
|
|
97
|
+
i32.shl
|
|
98
|
+
i32.add
|
|
99
|
+
local.get $5
|
|
100
|
+
i32.store
|
|
101
|
+
)
|
|
102
|
+
(func $as/injury/readFluidLoss (param $0 i32) (result i32)
|
|
103
|
+
local.get $0
|
|
104
|
+
i32.const 120
|
|
105
|
+
i32.mul
|
|
106
|
+
i32.load
|
|
107
|
+
)
|
|
108
|
+
(func $as/injury/readShock (param $0 i32) (result i32)
|
|
109
|
+
local.get $0
|
|
110
|
+
i32.const 120
|
|
111
|
+
i32.mul
|
|
112
|
+
i32.load offset=4
|
|
113
|
+
)
|
|
114
|
+
(func $as/injury/readConsciousness (param $0 i32) (result i32)
|
|
115
|
+
local.get $0
|
|
116
|
+
i32.const 120
|
|
117
|
+
i32.mul
|
|
118
|
+
i32.load offset=8
|
|
119
|
+
)
|
|
120
|
+
(func $as/injury/readDead (param $0 i32) (result i32)
|
|
121
|
+
local.get $0
|
|
122
|
+
i32.const 120
|
|
123
|
+
i32.mul
|
|
124
|
+
i32.load offset=12
|
|
125
|
+
)
|
|
126
|
+
(func $as/injury/readBleedingRate (param $0 i32) (param $1 i32) (result i32)
|
|
127
|
+
local.get $0
|
|
128
|
+
i32.const 120
|
|
129
|
+
i32.mul
|
|
130
|
+
local.get $1
|
|
131
|
+
i32.const 2
|
|
132
|
+
i32.shl
|
|
133
|
+
i32.const 6
|
|
134
|
+
i32.add
|
|
135
|
+
i32.const 2
|
|
136
|
+
i32.shl
|
|
137
|
+
i32.add
|
|
138
|
+
i32.load
|
|
139
|
+
)
|
|
140
|
+
(func $as/injury/stepBleedAndShock (param $0 i32)
|
|
141
|
+
(local $1 i32)
|
|
142
|
+
(local $2 i32)
|
|
143
|
+
(local $3 i32)
|
|
144
|
+
(local $4 i32)
|
|
145
|
+
(local $5 i32)
|
|
146
|
+
(local $6 i32)
|
|
147
|
+
(local $7 i32)
|
|
148
|
+
loop $for-loop|0
|
|
149
|
+
local.get $0
|
|
150
|
+
local.get $4
|
|
151
|
+
i32.gt_s
|
|
152
|
+
if
|
|
153
|
+
local.get $4
|
|
154
|
+
i32.const 120
|
|
155
|
+
i32.mul
|
|
156
|
+
i32.load offset=12
|
|
157
|
+
i32.eqz
|
|
158
|
+
if
|
|
159
|
+
i32.const 0
|
|
160
|
+
local.set $3
|
|
161
|
+
i32.const 0
|
|
162
|
+
local.set $2
|
|
163
|
+
loop $for-loop|1
|
|
164
|
+
local.get $2
|
|
165
|
+
i32.const 6
|
|
166
|
+
i32.lt_s
|
|
167
|
+
if
|
|
168
|
+
local.get $4
|
|
169
|
+
i32.const 120
|
|
170
|
+
i32.mul
|
|
171
|
+
local.tee $5
|
|
172
|
+
local.get $2
|
|
173
|
+
i32.const 2
|
|
174
|
+
i32.shl
|
|
175
|
+
local.tee $6
|
|
176
|
+
i32.const 6
|
|
177
|
+
i32.add
|
|
178
|
+
i32.const 2
|
|
179
|
+
i32.shl
|
|
180
|
+
i32.add
|
|
181
|
+
local.tee $7
|
|
182
|
+
i32.load
|
|
183
|
+
local.tee $1
|
|
184
|
+
i32.const 0
|
|
185
|
+
i32.gt_s
|
|
186
|
+
if
|
|
187
|
+
local.get $7
|
|
188
|
+
i32.const 10000
|
|
189
|
+
local.get $1
|
|
190
|
+
i32.const 10000
|
|
191
|
+
i32.const 10000
|
|
192
|
+
local.get $5
|
|
193
|
+
local.get $6
|
|
194
|
+
i32.const 7
|
|
195
|
+
i32.add
|
|
196
|
+
i32.const 2
|
|
197
|
+
i32.shl
|
|
198
|
+
i32.add
|
|
199
|
+
i32.load
|
|
200
|
+
i32.sub
|
|
201
|
+
local.tee $1
|
|
202
|
+
local.get $1
|
|
203
|
+
i32.const 10000
|
|
204
|
+
i32.gt_s
|
|
205
|
+
select
|
|
206
|
+
local.tee $1
|
|
207
|
+
i32.const 0
|
|
208
|
+
local.get $1
|
|
209
|
+
i32.const 0
|
|
210
|
+
i32.ge_s
|
|
211
|
+
select
|
|
212
|
+
i64.extend_i32_s
|
|
213
|
+
i64.const 1
|
|
214
|
+
i64.shl
|
|
215
|
+
i64.const 10000
|
|
216
|
+
i64.div_s
|
|
217
|
+
i32.wrap_i64
|
|
218
|
+
i32.sub
|
|
219
|
+
local.tee $1
|
|
220
|
+
local.get $1
|
|
221
|
+
i32.const 10000
|
|
222
|
+
i32.gt_s
|
|
223
|
+
select
|
|
224
|
+
local.tee $1
|
|
225
|
+
i32.const 0
|
|
226
|
+
local.get $1
|
|
227
|
+
i32.const 0
|
|
228
|
+
i32.ge_s
|
|
229
|
+
select
|
|
230
|
+
local.tee $1
|
|
231
|
+
i32.store
|
|
232
|
+
end
|
|
233
|
+
local.get $1
|
|
234
|
+
local.get $3
|
|
235
|
+
i32.add
|
|
236
|
+
local.set $3
|
|
237
|
+
local.get $2
|
|
238
|
+
i32.const 1
|
|
239
|
+
i32.add
|
|
240
|
+
local.set $2
|
|
241
|
+
br $for-loop|1
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
i32.const 10000
|
|
245
|
+
local.get $4
|
|
246
|
+
i32.const 120
|
|
247
|
+
i32.mul
|
|
248
|
+
local.tee $1
|
|
249
|
+
i32.load
|
|
250
|
+
local.get $3
|
|
251
|
+
i64.extend_i32_s
|
|
252
|
+
i64.const 500
|
|
253
|
+
i64.mul
|
|
254
|
+
i64.const 10000
|
|
255
|
+
i64.div_s
|
|
256
|
+
i32.wrap_i64
|
|
257
|
+
i32.add
|
|
258
|
+
local.tee $2
|
|
259
|
+
local.get $2
|
|
260
|
+
i32.const 10000
|
|
261
|
+
i32.gt_s
|
|
262
|
+
select
|
|
263
|
+
local.tee $2
|
|
264
|
+
i32.const 0
|
|
265
|
+
local.get $2
|
|
266
|
+
i32.const 0
|
|
267
|
+
i32.ge_s
|
|
268
|
+
select
|
|
269
|
+
local.set $2
|
|
270
|
+
local.get $1
|
|
271
|
+
local.get $2
|
|
272
|
+
i32.store
|
|
273
|
+
local.get $1
|
|
274
|
+
i32.const 10000
|
|
275
|
+
local.get $1
|
|
276
|
+
i64.load32_s offset=48
|
|
277
|
+
i64.const 20
|
|
278
|
+
i64.mul
|
|
279
|
+
i64.const 10000
|
|
280
|
+
i64.div_s
|
|
281
|
+
i32.wrap_i64
|
|
282
|
+
local.get $1
|
|
283
|
+
i32.const 4
|
|
284
|
+
i32.add
|
|
285
|
+
i32.load
|
|
286
|
+
local.get $2
|
|
287
|
+
i64.extend_i32_s
|
|
288
|
+
i64.const 40
|
|
289
|
+
i64.mul
|
|
290
|
+
i64.const 10000
|
|
291
|
+
i64.div_s
|
|
292
|
+
i32.wrap_i64
|
|
293
|
+
i32.add
|
|
294
|
+
i32.add
|
|
295
|
+
local.tee $3
|
|
296
|
+
local.get $3
|
|
297
|
+
i32.const 10000
|
|
298
|
+
i32.gt_s
|
|
299
|
+
select
|
|
300
|
+
local.tee $3
|
|
301
|
+
i32.const 0
|
|
302
|
+
local.get $3
|
|
303
|
+
i32.const 0
|
|
304
|
+
i32.ge_s
|
|
305
|
+
select
|
|
306
|
+
local.tee $3
|
|
307
|
+
i32.store offset=4
|
|
308
|
+
local.get $1
|
|
309
|
+
i32.const 10000
|
|
310
|
+
local.get $1
|
|
311
|
+
i32.const 8
|
|
312
|
+
i32.add
|
|
313
|
+
i32.load
|
|
314
|
+
i32.const 10000
|
|
315
|
+
local.get $3
|
|
316
|
+
i64.extend_i32_s
|
|
317
|
+
i64.const 100
|
|
318
|
+
i64.mul
|
|
319
|
+
i64.const 10000
|
|
320
|
+
i64.div_s
|
|
321
|
+
i32.wrap_i64
|
|
322
|
+
local.get $1
|
|
323
|
+
i64.load32_s offset=20
|
|
324
|
+
i64.const 200
|
|
325
|
+
i64.mul
|
|
326
|
+
i64.const 10000
|
|
327
|
+
i64.div_s
|
|
328
|
+
i32.wrap_i64
|
|
329
|
+
i32.add
|
|
330
|
+
local.tee $5
|
|
331
|
+
local.get $5
|
|
332
|
+
i32.const 10000
|
|
333
|
+
i32.gt_s
|
|
334
|
+
select
|
|
335
|
+
local.tee $5
|
|
336
|
+
i32.const 0
|
|
337
|
+
local.get $5
|
|
338
|
+
i32.const 0
|
|
339
|
+
i32.ge_s
|
|
340
|
+
select
|
|
341
|
+
i32.sub
|
|
342
|
+
local.tee $5
|
|
343
|
+
local.get $5
|
|
344
|
+
i32.const 10000
|
|
345
|
+
i32.gt_s
|
|
346
|
+
select
|
|
347
|
+
local.tee $5
|
|
348
|
+
i32.const 0
|
|
349
|
+
local.get $5
|
|
350
|
+
i32.const 0
|
|
351
|
+
i32.ge_s
|
|
352
|
+
select
|
|
353
|
+
local.tee $5
|
|
354
|
+
i32.store offset=8
|
|
355
|
+
local.get $5
|
|
356
|
+
i32.eqz
|
|
357
|
+
local.get $3
|
|
358
|
+
i32.const 10000
|
|
359
|
+
i32.ge_s
|
|
360
|
+
local.get $2
|
|
361
|
+
i32.const 8000
|
|
362
|
+
i32.ge_s
|
|
363
|
+
i32.or
|
|
364
|
+
i32.or
|
|
365
|
+
if
|
|
366
|
+
local.get $1
|
|
367
|
+
i32.const 1
|
|
368
|
+
i32.store offset=12
|
|
369
|
+
local.get $1
|
|
370
|
+
i32.const 0
|
|
371
|
+
i32.store offset=8
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
local.get $4
|
|
375
|
+
i32.const 1
|
|
376
|
+
i32.add
|
|
377
|
+
local.set $4
|
|
378
|
+
br $for-loop|0
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
)
|
|
382
|
+
)
|
|
Binary file
|
package/dist/as/push.wat
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
(module
|
|
2
|
+
(type $0 (func (param i32) (result i32)))
|
|
3
|
+
(type $1 (func (param i32 i32 i32 i32)))
|
|
4
|
+
(type $2 (func (param i32 i32) (result i32)))
|
|
5
|
+
(type $3 (func (param i32 i32 i32)))
|
|
6
|
+
(global $as/push/MAX_ENTITIES i32 (i32.const 64))
|
|
7
|
+
(global $as/push/OFFSET_POS_X i32 (i32.const 0))
|
|
8
|
+
(global $as/push/OFFSET_POS_Y i32 (i32.const 256))
|
|
9
|
+
(global $as/push/OFFSET_ALIVE i32 (i32.const 512))
|
|
10
|
+
(global $as/push/OFFSET_DV_X i32 (i32.const 768))
|
|
11
|
+
(global $as/push/OFFSET_DV_Y i32 (i32.const 1024))
|
|
12
|
+
(memory $0 1)
|
|
13
|
+
(export "MAX_ENTITIES" (global $as/push/MAX_ENTITIES))
|
|
14
|
+
(export "OFFSET_POS_X" (global $as/push/OFFSET_POS_X))
|
|
15
|
+
(export "OFFSET_POS_Y" (global $as/push/OFFSET_POS_Y))
|
|
16
|
+
(export "OFFSET_ALIVE" (global $as/push/OFFSET_ALIVE))
|
|
17
|
+
(export "OFFSET_DV_X" (global $as/push/OFFSET_DV_X))
|
|
18
|
+
(export "OFFSET_DV_Y" (global $as/push/OFFSET_DV_Y))
|
|
19
|
+
(export "writeEntity" (func $as/push/writeEntity))
|
|
20
|
+
(export "readDvX" (func $as/push/readDvX))
|
|
21
|
+
(export "readDvY" (func $as/push/readDvY))
|
|
22
|
+
(export "approxDist" (func $as/push/approxDist))
|
|
23
|
+
(export "stepRepulsionPairs" (func $as/push/stepRepulsionPairs))
|
|
24
|
+
(export "memory" (memory $0))
|
|
25
|
+
(func $as/push/writeEntity (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
|
|
26
|
+
local.get $0
|
|
27
|
+
i32.const 2
|
|
28
|
+
i32.shl
|
|
29
|
+
local.tee $0
|
|
30
|
+
local.get $1
|
|
31
|
+
i32.store
|
|
32
|
+
local.get $0
|
|
33
|
+
local.get $2
|
|
34
|
+
i32.store offset=256
|
|
35
|
+
local.get $0
|
|
36
|
+
local.get $3
|
|
37
|
+
i32.store offset=512
|
|
38
|
+
)
|
|
39
|
+
(func $as/push/readDvX (param $0 i32) (result i32)
|
|
40
|
+
local.get $0
|
|
41
|
+
i32.const 2
|
|
42
|
+
i32.shl
|
|
43
|
+
i32.load offset=768
|
|
44
|
+
)
|
|
45
|
+
(func $as/push/readDvY (param $0 i32) (result i32)
|
|
46
|
+
local.get $0
|
|
47
|
+
i32.const 2
|
|
48
|
+
i32.shl
|
|
49
|
+
i32.const 1024
|
|
50
|
+
i32.add
|
|
51
|
+
i32.load
|
|
52
|
+
)
|
|
53
|
+
(func $as/push/approxDist (param $0 i32) (param $1 i32) (result i32)
|
|
54
|
+
i32.const 0
|
|
55
|
+
local.get $0
|
|
56
|
+
i32.sub
|
|
57
|
+
local.get $0
|
|
58
|
+
local.get $0
|
|
59
|
+
i32.const 0
|
|
60
|
+
i32.lt_s
|
|
61
|
+
select
|
|
62
|
+
local.tee $0
|
|
63
|
+
i32.const 0
|
|
64
|
+
local.get $1
|
|
65
|
+
i32.sub
|
|
66
|
+
local.get $1
|
|
67
|
+
local.get $1
|
|
68
|
+
i32.const 0
|
|
69
|
+
i32.lt_s
|
|
70
|
+
select
|
|
71
|
+
local.tee $1
|
|
72
|
+
i32.const 1
|
|
73
|
+
i32.shr_s
|
|
74
|
+
i32.add
|
|
75
|
+
local.get $1
|
|
76
|
+
local.get $0
|
|
77
|
+
i32.const 1
|
|
78
|
+
i32.shr_s
|
|
79
|
+
i32.add
|
|
80
|
+
local.get $0
|
|
81
|
+
local.get $1
|
|
82
|
+
i32.gt_s
|
|
83
|
+
select
|
|
84
|
+
)
|
|
85
|
+
(func $as/push/stepRepulsionPairs (param $0 i32) (param $1 i32) (param $2 i32)
|
|
86
|
+
(local $3 i32)
|
|
87
|
+
(local $4 i64)
|
|
88
|
+
(local $5 i32)
|
|
89
|
+
(local $6 i32)
|
|
90
|
+
(local $7 i32)
|
|
91
|
+
(local $8 i64)
|
|
92
|
+
(local $9 i32)
|
|
93
|
+
(local $10 i32)
|
|
94
|
+
(local $11 i64)
|
|
95
|
+
(local $12 i32)
|
|
96
|
+
(local $13 i64)
|
|
97
|
+
(local $14 i64)
|
|
98
|
+
(local $15 i32)
|
|
99
|
+
loop $for-loop|0
|
|
100
|
+
local.get $0
|
|
101
|
+
local.get $3
|
|
102
|
+
i32.gt_s
|
|
103
|
+
if
|
|
104
|
+
local.get $3
|
|
105
|
+
i32.const 2
|
|
106
|
+
i32.shl
|
|
107
|
+
local.tee $5
|
|
108
|
+
i32.const 0
|
|
109
|
+
i32.store offset=768
|
|
110
|
+
local.get $5
|
|
111
|
+
i32.const 1024
|
|
112
|
+
i32.add
|
|
113
|
+
i32.const 0
|
|
114
|
+
i32.store
|
|
115
|
+
local.get $3
|
|
116
|
+
i32.const 1
|
|
117
|
+
i32.add
|
|
118
|
+
local.set $3
|
|
119
|
+
br $for-loop|0
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
local.get $1
|
|
123
|
+
i64.extend_i32_s
|
|
124
|
+
local.tee $4
|
|
125
|
+
local.get $4
|
|
126
|
+
i64.mul
|
|
127
|
+
local.set $4
|
|
128
|
+
i32.const 0
|
|
129
|
+
local.set $3
|
|
130
|
+
loop $for-loop|1
|
|
131
|
+
local.get $3
|
|
132
|
+
local.get $0
|
|
133
|
+
i32.const 1
|
|
134
|
+
i32.sub
|
|
135
|
+
i32.lt_s
|
|
136
|
+
if
|
|
137
|
+
local.get $3
|
|
138
|
+
i32.const 2
|
|
139
|
+
i32.shl
|
|
140
|
+
local.tee $5
|
|
141
|
+
i32.load offset=512
|
|
142
|
+
if
|
|
143
|
+
local.get $5
|
|
144
|
+
i32.load
|
|
145
|
+
local.set $6
|
|
146
|
+
local.get $5
|
|
147
|
+
i32.load offset=256
|
|
148
|
+
local.set $7
|
|
149
|
+
local.get $3
|
|
150
|
+
i32.const 1
|
|
151
|
+
i32.add
|
|
152
|
+
local.set $5
|
|
153
|
+
loop $for-loop|2
|
|
154
|
+
local.get $0
|
|
155
|
+
local.get $5
|
|
156
|
+
i32.gt_s
|
|
157
|
+
if
|
|
158
|
+
block $for-continue|2
|
|
159
|
+
local.get $5
|
|
160
|
+
i32.const 2
|
|
161
|
+
i32.shl
|
|
162
|
+
local.tee $9
|
|
163
|
+
i32.load offset=512
|
|
164
|
+
i32.eqz
|
|
165
|
+
br_if $for-continue|2
|
|
166
|
+
local.get $9
|
|
167
|
+
i32.load
|
|
168
|
+
local.get $6
|
|
169
|
+
i32.sub
|
|
170
|
+
local.tee $10
|
|
171
|
+
i64.extend_i32_s
|
|
172
|
+
local.tee $11
|
|
173
|
+
local.get $11
|
|
174
|
+
i64.mul
|
|
175
|
+
local.get $9
|
|
176
|
+
i32.load offset=256
|
|
177
|
+
local.get $7
|
|
178
|
+
i32.sub
|
|
179
|
+
local.tee $12
|
|
180
|
+
i64.extend_i32_s
|
|
181
|
+
local.tee $13
|
|
182
|
+
local.get $13
|
|
183
|
+
i64.mul
|
|
184
|
+
i64.add
|
|
185
|
+
local.tee $8
|
|
186
|
+
i64.eqz
|
|
187
|
+
local.get $4
|
|
188
|
+
local.get $8
|
|
189
|
+
i64.le_s
|
|
190
|
+
i32.or
|
|
191
|
+
br_if $for-continue|2
|
|
192
|
+
local.get $1
|
|
193
|
+
i32.const 0
|
|
194
|
+
local.get $10
|
|
195
|
+
i32.sub
|
|
196
|
+
local.get $10
|
|
197
|
+
local.get $10
|
|
198
|
+
i32.const 0
|
|
199
|
+
i32.lt_s
|
|
200
|
+
select
|
|
201
|
+
local.tee $10
|
|
202
|
+
i32.const 0
|
|
203
|
+
local.get $12
|
|
204
|
+
i32.sub
|
|
205
|
+
local.get $12
|
|
206
|
+
local.get $12
|
|
207
|
+
i32.const 0
|
|
208
|
+
i32.lt_s
|
|
209
|
+
select
|
|
210
|
+
local.tee $12
|
|
211
|
+
i32.const 1
|
|
212
|
+
i32.shr_s
|
|
213
|
+
i32.add
|
|
214
|
+
local.get $12
|
|
215
|
+
local.get $10
|
|
216
|
+
i32.const 1
|
|
217
|
+
i32.shr_s
|
|
218
|
+
i32.add
|
|
219
|
+
local.get $10
|
|
220
|
+
local.get $12
|
|
221
|
+
i32.gt_s
|
|
222
|
+
select
|
|
223
|
+
local.tee $10
|
|
224
|
+
i32.sub
|
|
225
|
+
local.tee $12
|
|
226
|
+
i32.const 0
|
|
227
|
+
i32.le_s
|
|
228
|
+
br_if $for-continue|2
|
|
229
|
+
i32.const 10000
|
|
230
|
+
local.get $12
|
|
231
|
+
i32.const 10000
|
|
232
|
+
i32.mul
|
|
233
|
+
local.get $1
|
|
234
|
+
i32.div_s
|
|
235
|
+
local.tee $12
|
|
236
|
+
local.get $12
|
|
237
|
+
i32.const 10000
|
|
238
|
+
i32.gt_s
|
|
239
|
+
select
|
|
240
|
+
local.tee $12
|
|
241
|
+
i32.const 0
|
|
242
|
+
local.get $12
|
|
243
|
+
i32.const 0
|
|
244
|
+
i32.ge_s
|
|
245
|
+
select
|
|
246
|
+
i64.extend_i32_s
|
|
247
|
+
local.tee $14
|
|
248
|
+
local.get $2
|
|
249
|
+
i64.extend_i32_s
|
|
250
|
+
local.tee $8
|
|
251
|
+
local.get $11
|
|
252
|
+
i64.mul
|
|
253
|
+
i64.mul
|
|
254
|
+
i32.const 1
|
|
255
|
+
local.get $10
|
|
256
|
+
local.get $10
|
|
257
|
+
i32.const 0
|
|
258
|
+
i32.le_s
|
|
259
|
+
select
|
|
260
|
+
i64.extend_i32_s
|
|
261
|
+
i64.const 10000
|
|
262
|
+
i64.mul
|
|
263
|
+
local.tee $11
|
|
264
|
+
i64.div_s
|
|
265
|
+
i32.wrap_i64
|
|
266
|
+
local.set $10
|
|
267
|
+
local.get $8
|
|
268
|
+
local.get $13
|
|
269
|
+
i64.mul
|
|
270
|
+
local.get $14
|
|
271
|
+
i64.mul
|
|
272
|
+
local.get $11
|
|
273
|
+
i64.div_s
|
|
274
|
+
i32.wrap_i64
|
|
275
|
+
local.set $12
|
|
276
|
+
local.get $3
|
|
277
|
+
i32.const 2
|
|
278
|
+
i32.shl
|
|
279
|
+
local.tee $15
|
|
280
|
+
local.get $15
|
|
281
|
+
i32.load offset=768
|
|
282
|
+
local.get $10
|
|
283
|
+
i32.sub
|
|
284
|
+
i32.store offset=768
|
|
285
|
+
local.get $15
|
|
286
|
+
i32.const 1024
|
|
287
|
+
i32.add
|
|
288
|
+
local.tee $15
|
|
289
|
+
local.get $15
|
|
290
|
+
i32.load
|
|
291
|
+
local.get $12
|
|
292
|
+
i32.sub
|
|
293
|
+
i32.store
|
|
294
|
+
local.get $9
|
|
295
|
+
local.get $9
|
|
296
|
+
i32.load offset=768
|
|
297
|
+
local.get $10
|
|
298
|
+
i32.add
|
|
299
|
+
i32.store offset=768
|
|
300
|
+
local.get $9
|
|
301
|
+
i32.const 1024
|
|
302
|
+
i32.add
|
|
303
|
+
local.tee $9
|
|
304
|
+
local.get $9
|
|
305
|
+
i32.load
|
|
306
|
+
local.get $12
|
|
307
|
+
i32.add
|
|
308
|
+
i32.store
|
|
309
|
+
end
|
|
310
|
+
local.get $5
|
|
311
|
+
i32.const 1
|
|
312
|
+
i32.add
|
|
313
|
+
local.set $5
|
|
314
|
+
br $for-loop|2
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
local.get $3
|
|
319
|
+
i32.const 1
|
|
320
|
+
i32.add
|
|
321
|
+
local.set $3
|
|
322
|
+
br $for-loop|1
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
)
|
|
326
|
+
)
|
|
Binary file
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
(module
|
|
2
|
+
(type $0 (func (param f64) (result i32)))
|
|
3
|
+
(type $1 (func (param i32) (result f64)))
|
|
4
|
+
(type $2 (func (param i32 i32 i32) (result i32)))
|
|
5
|
+
(type $3 (func (param i32 i32) (result i32)))
|
|
6
|
+
(type $4 (func (param i32) (result i32)))
|
|
7
|
+
(global $as/units/SCALE_Q i32 (i32.const 10000))
|
|
8
|
+
(global $as/units/SCALE_m i32 (i32.const 10000))
|
|
9
|
+
(global $as/units/SCALE_s i32 (i32.const 10000))
|
|
10
|
+
(global $as/units/SCALE_kg i32 (i32.const 1000))
|
|
11
|
+
(global $as/units/SCALE_N i32 (i32.const 100))
|
|
12
|
+
(global $as/units/SCALE_W i32 (i32.const 1))
|
|
13
|
+
(global $as/units/SCALE_J i32 (i32.const 1))
|
|
14
|
+
(global $as/units/SCALE_mps i32 (i32.const 10000))
|
|
15
|
+
(global $as/units/SCALE_mps2 i32 (i32.const 10000))
|
|
16
|
+
(global $as/units/G_mps2 i32 (i32.const 98067))
|
|
17
|
+
(memory $0 0)
|
|
18
|
+
(export "SCALE_Q" (global $as/units/SCALE_Q))
|
|
19
|
+
(export "SCALE_m" (global $as/units/SCALE_m))
|
|
20
|
+
(export "SCALE_s" (global $as/units/SCALE_s))
|
|
21
|
+
(export "SCALE_kg" (global $as/units/SCALE_kg))
|
|
22
|
+
(export "SCALE_N" (global $as/units/SCALE_N))
|
|
23
|
+
(export "SCALE_W" (global $as/units/SCALE_W))
|
|
24
|
+
(export "SCALE_J" (global $as/units/SCALE_J))
|
|
25
|
+
(export "SCALE_mps" (global $as/units/SCALE_mps))
|
|
26
|
+
(export "SCALE_mps2" (global $as/units/SCALE_mps2))
|
|
27
|
+
(export "G_mps2" (global $as/units/G_mps2))
|
|
28
|
+
(export "q" (func $as/units/q))
|
|
29
|
+
(export "clampQ" (func $as/units/clampQ))
|
|
30
|
+
(export "qMul" (func $as/units/qMul))
|
|
31
|
+
(export "qDiv" (func $as/units/qDiv))
|
|
32
|
+
(export "mulDiv" (func $as/units/mulDiv))
|
|
33
|
+
(export "to_m" (func $as/units/q))
|
|
34
|
+
(export "to_s" (func $as/units/q))
|
|
35
|
+
(export "to_kg" (func $as/units/to_kg))
|
|
36
|
+
(export "to_N" (func $as/units/to_N))
|
|
37
|
+
(export "to_W" (func $as/units/to_W))
|
|
38
|
+
(export "to_J" (func $as/units/to_W))
|
|
39
|
+
(export "to_mps" (func $as/units/q))
|
|
40
|
+
(export "to_mps2" (func $as/units/q))
|
|
41
|
+
(export "from_m" (func $as/units/from_m))
|
|
42
|
+
(export "from_s" (func $as/units/from_m))
|
|
43
|
+
(export "from_kg" (func $as/units/from_kg))
|
|
44
|
+
(export "from_N" (func $as/units/from_N))
|
|
45
|
+
(export "from_W" (func $as/units/from_W))
|
|
46
|
+
(export "from_J" (func $as/units/from_W))
|
|
47
|
+
(export "from_mps" (func $as/units/from_m))
|
|
48
|
+
(export "from_mps2" (func $as/units/from_m))
|
|
49
|
+
(export "sqrtQ" (func $as/units/sqrtQ))
|
|
50
|
+
(export "cbrtQ" (func $as/units/cbrtQ))
|
|
51
|
+
(export "memory" (memory $0))
|
|
52
|
+
(func $as/units/q (param $0 f64) (result i32)
|
|
53
|
+
(local $1 f64)
|
|
54
|
+
local.get $0
|
|
55
|
+
f64.const 1e4
|
|
56
|
+
f64.mul
|
|
57
|
+
local.tee $1
|
|
58
|
+
f64.ceil
|
|
59
|
+
local.tee $0
|
|
60
|
+
local.get $0
|
|
61
|
+
f64.const -1
|
|
62
|
+
f64.add
|
|
63
|
+
local.get $0
|
|
64
|
+
f64.const -0.5
|
|
65
|
+
f64.add
|
|
66
|
+
local.get $1
|
|
67
|
+
f64.le
|
|
68
|
+
select
|
|
69
|
+
i32.trunc_sat_f64_s
|
|
70
|
+
)
|
|
71
|
+
(func $as/units/clampQ (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
|
72
|
+
local.get $1
|
|
73
|
+
local.get $2
|
|
74
|
+
local.get $0
|
|
75
|
+
local.get $0
|
|
76
|
+
local.get $2
|
|
77
|
+
i32.gt_s
|
|
78
|
+
select
|
|
79
|
+
local.tee $0
|
|
80
|
+
local.get $0
|
|
81
|
+
local.get $1
|
|
82
|
+
i32.lt_s
|
|
83
|
+
select
|
|
84
|
+
)
|
|
85
|
+
(func $as/units/qMul (param $0 i32) (param $1 i32) (result i32)
|
|
86
|
+
local.get $0
|
|
87
|
+
i64.extend_i32_s
|
|
88
|
+
local.get $1
|
|
89
|
+
i64.extend_i32_s
|
|
90
|
+
i64.mul
|
|
91
|
+
i64.const 10000
|
|
92
|
+
i64.div_s
|
|
93
|
+
i32.wrap_i64
|
|
94
|
+
)
|
|
95
|
+
(func $as/units/qDiv (param $0 i32) (param $1 i32) (result i32)
|
|
96
|
+
local.get $0
|
|
97
|
+
i64.extend_i32_s
|
|
98
|
+
i64.const 10000
|
|
99
|
+
i64.mul
|
|
100
|
+
local.get $1
|
|
101
|
+
i64.extend_i32_s
|
|
102
|
+
i64.div_s
|
|
103
|
+
i32.wrap_i64
|
|
104
|
+
)
|
|
105
|
+
(func $as/units/mulDiv (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
|
106
|
+
local.get $0
|
|
107
|
+
i64.extend_i32_s
|
|
108
|
+
local.get $1
|
|
109
|
+
i64.extend_i32_s
|
|
110
|
+
i64.mul
|
|
111
|
+
local.get $2
|
|
112
|
+
i64.extend_i32_s
|
|
113
|
+
i64.div_s
|
|
114
|
+
i32.wrap_i64
|
|
115
|
+
)
|
|
116
|
+
(func $as/units/to_kg (param $0 f64) (result i32)
|
|
117
|
+
(local $1 f64)
|
|
118
|
+
local.get $0
|
|
119
|
+
f64.const 1e3
|
|
120
|
+
f64.mul
|
|
121
|
+
local.tee $1
|
|
122
|
+
f64.ceil
|
|
123
|
+
local.tee $0
|
|
124
|
+
local.get $0
|
|
125
|
+
f64.const -1
|
|
126
|
+
f64.add
|
|
127
|
+
local.get $0
|
|
128
|
+
f64.const -0.5
|
|
129
|
+
f64.add
|
|
130
|
+
local.get $1
|
|
131
|
+
f64.le
|
|
132
|
+
select
|
|
133
|
+
i32.trunc_sat_f64_s
|
|
134
|
+
)
|
|
135
|
+
(func $as/units/to_N (param $0 f64) (result i32)
|
|
136
|
+
(local $1 f64)
|
|
137
|
+
local.get $0
|
|
138
|
+
f64.const 100
|
|
139
|
+
f64.mul
|
|
140
|
+
local.tee $1
|
|
141
|
+
f64.ceil
|
|
142
|
+
local.tee $0
|
|
143
|
+
local.get $0
|
|
144
|
+
f64.const -1
|
|
145
|
+
f64.add
|
|
146
|
+
local.get $0
|
|
147
|
+
f64.const -0.5
|
|
148
|
+
f64.add
|
|
149
|
+
local.get $1
|
|
150
|
+
f64.le
|
|
151
|
+
select
|
|
152
|
+
i32.trunc_sat_f64_s
|
|
153
|
+
)
|
|
154
|
+
(func $as/units/to_W (param $0 f64) (result i32)
|
|
155
|
+
(local $1 f64)
|
|
156
|
+
local.get $0
|
|
157
|
+
f64.ceil
|
|
158
|
+
local.tee $1
|
|
159
|
+
local.get $1
|
|
160
|
+
f64.const -1
|
|
161
|
+
f64.add
|
|
162
|
+
local.get $1
|
|
163
|
+
f64.const -0.5
|
|
164
|
+
f64.add
|
|
165
|
+
local.get $0
|
|
166
|
+
f64.le
|
|
167
|
+
select
|
|
168
|
+
i32.trunc_sat_f64_s
|
|
169
|
+
)
|
|
170
|
+
(func $as/units/from_m (param $0 i32) (result f64)
|
|
171
|
+
local.get $0
|
|
172
|
+
f64.convert_i32_s
|
|
173
|
+
f64.const 1e4
|
|
174
|
+
f64.div
|
|
175
|
+
)
|
|
176
|
+
(func $as/units/from_kg (param $0 i32) (result f64)
|
|
177
|
+
local.get $0
|
|
178
|
+
f64.convert_i32_s
|
|
179
|
+
f64.const 1e3
|
|
180
|
+
f64.div
|
|
181
|
+
)
|
|
182
|
+
(func $as/units/from_N (param $0 i32) (result f64)
|
|
183
|
+
local.get $0
|
|
184
|
+
f64.convert_i32_s
|
|
185
|
+
f64.const 100
|
|
186
|
+
f64.div
|
|
187
|
+
)
|
|
188
|
+
(func $as/units/from_W (param $0 i32) (result f64)
|
|
189
|
+
local.get $0
|
|
190
|
+
f64.convert_i32_s
|
|
191
|
+
)
|
|
192
|
+
(func $as/units/sqrtQ (param $0 i32) (result i32)
|
|
193
|
+
(local $1 i64)
|
|
194
|
+
(local $2 i64)
|
|
195
|
+
(local $3 i32)
|
|
196
|
+
(local $4 i64)
|
|
197
|
+
i32.const 1
|
|
198
|
+
local.get $0
|
|
199
|
+
local.get $0
|
|
200
|
+
i32.const 0
|
|
201
|
+
i32.le_s
|
|
202
|
+
select
|
|
203
|
+
i64.extend_i32_s
|
|
204
|
+
i64.const 10000
|
|
205
|
+
i64.mul
|
|
206
|
+
local.set $4
|
|
207
|
+
i64.const 10000
|
|
208
|
+
local.set $1
|
|
209
|
+
loop $for-loop|0
|
|
210
|
+
local.get $3
|
|
211
|
+
i32.const 10
|
|
212
|
+
i32.lt_s
|
|
213
|
+
if
|
|
214
|
+
local.get $1
|
|
215
|
+
local.get $1
|
|
216
|
+
local.get $4
|
|
217
|
+
local.get $1
|
|
218
|
+
i64.div_s
|
|
219
|
+
i64.add
|
|
220
|
+
i64.const 2
|
|
221
|
+
i64.div_s
|
|
222
|
+
local.tee $2
|
|
223
|
+
i64.ne
|
|
224
|
+
if
|
|
225
|
+
local.get $2
|
|
226
|
+
local.set $1
|
|
227
|
+
local.get $3
|
|
228
|
+
i32.const 1
|
|
229
|
+
i32.add
|
|
230
|
+
local.set $3
|
|
231
|
+
br $for-loop|0
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
local.get $1
|
|
236
|
+
i32.wrap_i64
|
|
237
|
+
)
|
|
238
|
+
(func $as/units/cbrtQ (param $0 i32) (result i32)
|
|
239
|
+
(local $1 i64)
|
|
240
|
+
(local $2 i32)
|
|
241
|
+
(local $3 i64)
|
|
242
|
+
i32.const 1
|
|
243
|
+
local.get $0
|
|
244
|
+
local.get $0
|
|
245
|
+
i32.const 0
|
|
246
|
+
i32.le_s
|
|
247
|
+
select
|
|
248
|
+
i64.extend_i32_s
|
|
249
|
+
i64.const 100000000
|
|
250
|
+
i64.mul
|
|
251
|
+
local.set $3
|
|
252
|
+
i64.const 10000
|
|
253
|
+
local.set $1
|
|
254
|
+
loop $for-loop|0
|
|
255
|
+
local.get $2
|
|
256
|
+
i32.const 12
|
|
257
|
+
i32.lt_s
|
|
258
|
+
if
|
|
259
|
+
block $for-break0
|
|
260
|
+
local.get $3
|
|
261
|
+
local.get $1
|
|
262
|
+
local.get $1
|
|
263
|
+
i64.mul
|
|
264
|
+
i64.div_s
|
|
265
|
+
local.get $1
|
|
266
|
+
i64.const 1
|
|
267
|
+
i64.shl
|
|
268
|
+
i64.add
|
|
269
|
+
i64.const 3
|
|
270
|
+
i64.div_s
|
|
271
|
+
local.tee $1
|
|
272
|
+
i64.const 0
|
|
273
|
+
i64.le_s
|
|
274
|
+
if
|
|
275
|
+
i64.const 1
|
|
276
|
+
local.set $1
|
|
277
|
+
br $for-break0
|
|
278
|
+
end
|
|
279
|
+
local.get $2
|
|
280
|
+
i32.const 1
|
|
281
|
+
i32.add
|
|
282
|
+
local.set $2
|
|
283
|
+
br $for-loop|0
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
local.get $1
|
|
288
|
+
i32.wrap_i64
|
|
289
|
+
)
|
|
290
|
+
)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { WorldState } from "./sim/world.js";
|
|
2
|
+
interface PushExports {
|
|
3
|
+
MAX_ENTITIES: WebAssembly.Global;
|
|
4
|
+
writeEntity: (slot: number, posX: number, posY: number, alive: number) => void;
|
|
5
|
+
readDvX: (slot: number) => number;
|
|
6
|
+
readDvY: (slot: number) => number;
|
|
7
|
+
stepRepulsionPairs: (n: number, radius_m: number, repelAccel_mps2: number) => void;
|
|
8
|
+
}
|
|
9
|
+
interface InjuryExports {
|
|
10
|
+
MAX_ENTITIES: WebAssembly.Global;
|
|
11
|
+
writeVitals: (slot: number, fluidLoss: number, shock: number, consciousness: number, dead: number, fatigue: number, suffocation: number) => void;
|
|
12
|
+
writeRegion: (slot: number, r: number, bleedingRate: number, structuralDamage: number, internalDamage: number, surfaceDamage: number) => void;
|
|
13
|
+
readFluidLoss: (slot: number) => number;
|
|
14
|
+
readShock: (slot: number) => number;
|
|
15
|
+
readConsciousness: (slot: number) => number;
|
|
16
|
+
readDead: (slot: number) => number;
|
|
17
|
+
stepBleedAndShock: (n: number) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface WasmEntityReport {
|
|
20
|
+
entityId: number;
|
|
21
|
+
/** Repulsion velocity delta computed by WASM push kernel (SCALE.mps units). */
|
|
22
|
+
pushDvX: number;
|
|
23
|
+
pushDvY: number;
|
|
24
|
+
/** Projected injury state after one WASM injury tick. */
|
|
25
|
+
projFluidLoss: number;
|
|
26
|
+
projShock: number;
|
|
27
|
+
projConsciousness: number;
|
|
28
|
+
projDead: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface WasmStepReport {
|
|
31
|
+
tick: number;
|
|
32
|
+
entities: WasmEntityReport[];
|
|
33
|
+
/** True if WASM is available and ran successfully. */
|
|
34
|
+
ok: boolean;
|
|
35
|
+
summary: string;
|
|
36
|
+
}
|
|
37
|
+
export declare class WasmKernel {
|
|
38
|
+
private readonly push;
|
|
39
|
+
private readonly injury;
|
|
40
|
+
private static readonly PUSH_RADIUS_M;
|
|
41
|
+
private static readonly PUSH_REPEL_MPS2;
|
|
42
|
+
constructor(push: PushExports, injury: InjuryExports);
|
|
43
|
+
/**
|
|
44
|
+
* Run WASM push + injury steps on the current world state (shadow mode — does not
|
|
45
|
+
* mutate world). Returns a per-entity report and a one-line summary string.
|
|
46
|
+
*
|
|
47
|
+
* Call this after stepWorld() each tick for validation / diagnostics.
|
|
48
|
+
*/
|
|
49
|
+
shadowStep(world: WorldState, tick: number): WasmStepReport;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Load push.wasm and injury.wasm from dist/as/ (co-located with this compiled module)
|
|
53
|
+
* and return a WasmKernel ready for use.
|
|
54
|
+
*
|
|
55
|
+
* Throws if the WASM files are not found (e.g. npm run build:wasm:all not yet run).
|
|
56
|
+
*/
|
|
57
|
+
export declare function loadWasmKernel(): Promise<WasmKernel>;
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/wasm-kernel.ts — Node.js loader and host bridge for the AssemblyScript WASM modules.
|
|
2
|
+
//
|
|
3
|
+
// Provides a shadow-mode step that runs as/push.wasm + as/injury.wasm alongside the
|
|
4
|
+
// TypeScript kernel. In shadow mode the WASM outputs are NOT applied to world state;
|
|
5
|
+
// they are returned for the caller to log or validate.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// const kernel = await loadWasmKernel(); // once at startup
|
|
9
|
+
// const report = kernel.shadowStep(world); // after stepWorld() each tick
|
|
10
|
+
// console.log(report.summary);
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { SCALE } from "./units.js";
|
|
14
|
+
// ── Region order shared with as/injury.ts ─────────────────────────────────────
|
|
15
|
+
const REGION_ORDER = ["head", "torso", "leftArm", "rightArm", "leftLeg", "rightLeg"];
|
|
16
|
+
// ── Kernel class ──────────────────────────────────────────────────────────────
|
|
17
|
+
export class WasmKernel {
|
|
18
|
+
push;
|
|
19
|
+
injury;
|
|
20
|
+
// Canonical kernel push tuning (mirrors src/sim/kernel.ts)
|
|
21
|
+
static PUSH_RADIUS_M = Math.trunc(0.45 * SCALE.m); // 4500
|
|
22
|
+
static PUSH_REPEL_MPS2 = Math.trunc(1.5 * SCALE.mps2); // 15000
|
|
23
|
+
constructor(push, injury) {
|
|
24
|
+
this.push = push;
|
|
25
|
+
this.injury = injury;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Run WASM push + injury steps on the current world state (shadow mode — does not
|
|
29
|
+
* mutate world). Returns a per-entity report and a one-line summary string.
|
|
30
|
+
*
|
|
31
|
+
* Call this after stepWorld() each tick for validation / diagnostics.
|
|
32
|
+
*/
|
|
33
|
+
shadowStep(world, tick) {
|
|
34
|
+
const entities = world.entities;
|
|
35
|
+
const pushMax = this.push.MAX_ENTITIES.value;
|
|
36
|
+
const injMax = this.injury.MAX_ENTITIES.value;
|
|
37
|
+
const n = Math.min(entities.length, pushMax, injMax);
|
|
38
|
+
// ── Push pass (position-based repulsion) ──────────────────────────────────
|
|
39
|
+
for (let i = 0; i < n; i++) {
|
|
40
|
+
const e = entities[i];
|
|
41
|
+
this.push.writeEntity(i, e.position_m.x, e.position_m.y, e.injury.dead ? 0 : 1);
|
|
42
|
+
}
|
|
43
|
+
this.push.stepRepulsionPairs(n, WasmKernel.PUSH_RADIUS_M, WasmKernel.PUSH_REPEL_MPS2);
|
|
44
|
+
// ── Injury pass (clotting / bleed / shock / consciousness) ────────────────
|
|
45
|
+
for (let i = 0; i < n; i++) {
|
|
46
|
+
const e = entities[i];
|
|
47
|
+
const suff = e.condition["suffocation"] ?? 0;
|
|
48
|
+
this.injury.writeVitals(i, e.injury.fluidLoss, e.injury.shock, e.injury.consciousness, e.injury.dead ? 1 : 0, e.energy.fatigue, suff);
|
|
49
|
+
for (let r = 0; r < REGION_ORDER.length; r++) {
|
|
50
|
+
const reg = e.injury.byRegion[REGION_ORDER[r]];
|
|
51
|
+
this.injury.writeRegion(i, r, reg?.bleedingRate ?? 0, reg?.structuralDamage ?? 0, reg?.internalDamage ?? 0, reg?.["surfaceDamage"] ?? 0);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
this.injury.stepBleedAndShock(n);
|
|
55
|
+
// ── Build report ──────────────────────────────────────────────────────────
|
|
56
|
+
const reports = [];
|
|
57
|
+
for (let i = 0; i < n; i++) {
|
|
58
|
+
const e = entities[i];
|
|
59
|
+
reports.push({
|
|
60
|
+
entityId: e.id,
|
|
61
|
+
pushDvX: this.push.readDvX(i),
|
|
62
|
+
pushDvY: this.push.readDvY(i),
|
|
63
|
+
projFluidLoss: this.injury.readFluidLoss(i),
|
|
64
|
+
projShock: this.injury.readShock(i),
|
|
65
|
+
projConsciousness: this.injury.readConsciousness(i),
|
|
66
|
+
projDead: this.injury.readDead(i) === 1,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const summary = reports
|
|
70
|
+
.map(r => `e${r.entityId} dv=(${r.pushDvX},${r.pushDvY}) ` +
|
|
71
|
+
`fl=${(r.projFluidLoss / SCALE.Q).toFixed(3)} ` +
|
|
72
|
+
`sh=${(r.projShock / SCALE.Q).toFixed(3)} ` +
|
|
73
|
+
`co=${(r.projConsciousness / SCALE.Q).toFixed(3)}` +
|
|
74
|
+
(r.projDead ? " DEAD" : ""))
|
|
75
|
+
.join(" | ");
|
|
76
|
+
return { tick, entities: reports, ok: true, summary: `[wasm] tick ${tick}: ${summary}` };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// ── Factory ───────────────────────────────────────────────────────────────────
|
|
80
|
+
/**
|
|
81
|
+
* Load push.wasm and injury.wasm from dist/as/ (co-located with this compiled module)
|
|
82
|
+
* and return a WasmKernel ready for use.
|
|
83
|
+
*
|
|
84
|
+
* Throws if the WASM files are not found (e.g. npm run build:wasm:all not yet run).
|
|
85
|
+
*/
|
|
86
|
+
export async function loadWasmKernel() {
|
|
87
|
+
// Compiled to dist/src/wasm-kernel.js → WASM files are at ../as/*.wasm
|
|
88
|
+
const base = new URL("../as/", import.meta.url);
|
|
89
|
+
const pushBuf = readFileSync(fileURLToPath(new URL("push.wasm", base)));
|
|
90
|
+
const injuryBuf = readFileSync(fileURLToPath(new URL("injury.wasm", base)));
|
|
91
|
+
const [pushResult, injuryResult] = await Promise.all([
|
|
92
|
+
WebAssembly.instantiate(pushBuf),
|
|
93
|
+
WebAssembly.instantiate(injuryBuf),
|
|
94
|
+
]);
|
|
95
|
+
return new WasmKernel(pushResult.instance.exports, injuryResult.instance.exports);
|
|
96
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@its-not-rocket-science/ananke",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Deterministic lockstep-friendly SI-units RPG/physics core (fixed-point TS)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,10 +54,15 @@
|
|
|
54
54
|
"./competence": {
|
|
55
55
|
"import": "./dist/src/competence/index.js",
|
|
56
56
|
"types": "./dist/src/competence/index.d.ts"
|
|
57
|
+
},
|
|
58
|
+
"./wasm-kernel": {
|
|
59
|
+
"import": "./dist/src/wasm-kernel.js",
|
|
60
|
+
"types": "./dist/src/wasm-kernel.d.ts"
|
|
57
61
|
}
|
|
58
62
|
},
|
|
59
63
|
"files": [
|
|
60
64
|
"dist/src",
|
|
65
|
+
"dist/as",
|
|
61
66
|
"docs/project-overview.md",
|
|
62
67
|
"docs/host-contract.md",
|
|
63
68
|
"docs/integration-primer.md",
|
|
@@ -118,12 +123,19 @@
|
|
|
118
123
|
"benchmark-check:strict": "node dist/tools/benchmark-check.js --threshold=0.10",
|
|
119
124
|
"benchmark-check:update": "node dist/tools/benchmark-check.js --update-baseline",
|
|
120
125
|
"benchmark:guide": "node dist/tools/benchmark-guide.js",
|
|
121
|
-
"benchmark:parallel": "node dist/tools/benchmark-parallel.js"
|
|
126
|
+
"benchmark:parallel": "node dist/tools/benchmark-parallel.js",
|
|
127
|
+
"run:renderer-bridge": "node dist/tools/renderer-bridge.js",
|
|
128
|
+
"build:wasm": "asc as/units.ts --outFile dist/as/units.wasm --textFile dist/as/units.wat --runtime stub --optimize",
|
|
129
|
+
"build:wasm:push": "asc as/push.ts --outFile dist/as/push.wasm --textFile dist/as/push.wat --runtime stub --optimize --initialMemory 1",
|
|
130
|
+
"build:wasm:injury": "asc as/injury.ts --outFile dist/as/injury.wasm --textFile dist/as/injury.wat --runtime stub --optimize --initialMemory 1",
|
|
131
|
+
"build:wasm:all": "npm run build:wasm && npm run build:wasm:push && npm run build:wasm:injury",
|
|
132
|
+
"test:wasm": "npm run build:wasm:all && vitest run test/as/"
|
|
122
133
|
},
|
|
123
134
|
"devDependencies": {
|
|
124
135
|
"@eslint/js": "^9.39.3",
|
|
125
136
|
"@types/node": "^20.0.0",
|
|
126
137
|
"@vitest/coverage-v8": "^2.1.8",
|
|
138
|
+
"assemblyscript": "^0.27.37",
|
|
127
139
|
"eslint": "^9.39.3",
|
|
128
140
|
"fast-check": "^4.6.0",
|
|
129
141
|
"typescript": "^5.5.4",
|