@cognipilot/rumoca 0.9.4

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.
Binary file
@@ -0,0 +1,49 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Simulate a pre-lowered model with the stiff/implicit diffsol backend.
6
+ * `input_json` is the `{ solve_model, t_end, dt }` payload from the main
7
+ * module's `lower_model_to_solve_json`. Returns the same `{ "payload": ... }`
8
+ * JSON shape as the main module's `simulate_model`, so callers treat both
9
+ * paths uniformly.
10
+ */
11
+ export function simulate_solve_model_diffsol(input_json: string): string;
12
+
13
+ export function start(): void;
14
+
15
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
16
+
17
+ export interface InitOutput {
18
+ readonly memory: WebAssembly.Memory;
19
+ readonly simulate_solve_model_diffsol: (a: number, b: number) => [number, number, number, number];
20
+ readonly start: () => void;
21
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
22
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
23
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
24
+ readonly __wbindgen_externrefs: WebAssembly.Table;
25
+ readonly __externref_table_dealloc: (a: number) => void;
26
+ readonly __wbindgen_start: () => void;
27
+ }
28
+
29
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
30
+
31
+ /**
32
+ * Instantiates the given `module`, which can either be bytes or
33
+ * a precompiled `WebAssembly.Module`.
34
+ *
35
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
36
+ *
37
+ * @returns {InitOutput}
38
+ */
39
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
40
+
41
+ /**
42
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
43
+ * for everything else, calls `WebAssembly.instantiate` directly.
44
+ *
45
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
46
+ *
47
+ * @returns {Promise<InitOutput>}
48
+ */
49
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
@@ -0,0 +1,270 @@
1
+ /* @ts-self-types="./rumoca_bind_wasm_diffsol.d.ts" */
2
+
3
+ /**
4
+ * Simulate a pre-lowered model with the stiff/implicit diffsol backend.
5
+ * `input_json` is the `{ solve_model, t_end, dt }` payload from the main
6
+ * module's `lower_model_to_solve_json`. Returns the same `{ "payload": ... }`
7
+ * JSON shape as the main module's `simulate_model`, so callers treat both
8
+ * paths uniformly.
9
+ * @param {string} input_json
10
+ * @returns {string}
11
+ */
12
+ export function simulate_solve_model_diffsol(input_json) {
13
+ let deferred3_0;
14
+ let deferred3_1;
15
+ try {
16
+ const ptr0 = passStringToWasm0(input_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
17
+ const len0 = WASM_VECTOR_LEN;
18
+ const ret = wasm.simulate_solve_model_diffsol(ptr0, len0);
19
+ var ptr2 = ret[0];
20
+ var len2 = ret[1];
21
+ if (ret[3]) {
22
+ ptr2 = 0; len2 = 0;
23
+ throw takeFromExternrefTable0(ret[2]);
24
+ }
25
+ deferred3_0 = ptr2;
26
+ deferred3_1 = len2;
27
+ return getStringFromWasm0(ptr2, len2);
28
+ } finally {
29
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
30
+ }
31
+ }
32
+
33
+ export function start() {
34
+ wasm.start();
35
+ }
36
+
37
+ function __wbg_get_imports() {
38
+ const import0 = {
39
+ __proto__: null,
40
+ __wbg___wbindgen_throw_be289d5034ed271b: function(arg0, arg1) {
41
+ throw new Error(getStringFromWasm0(arg0, arg1));
42
+ },
43
+ __wbg_error_7534b8e9a36f1ab4: function(arg0, arg1) {
44
+ let deferred0_0;
45
+ let deferred0_1;
46
+ try {
47
+ deferred0_0 = arg0;
48
+ deferred0_1 = arg1;
49
+ console.error(getStringFromWasm0(arg0, arg1));
50
+ } finally {
51
+ wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
52
+ }
53
+ },
54
+ __wbg_new_8a6f238a6ece86ea: function() {
55
+ const ret = new Error();
56
+ return ret;
57
+ },
58
+ __wbg_stack_0ed75d68575b0f3c: function(arg0, arg1) {
59
+ const ret = arg1.stack;
60
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
61
+ const len1 = WASM_VECTOR_LEN;
62
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
63
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
64
+ },
65
+ __wbindgen_cast_0000000000000001: function(arg0, arg1) {
66
+ // Cast intrinsic for `Ref(String) -> Externref`.
67
+ const ret = getStringFromWasm0(arg0, arg1);
68
+ return ret;
69
+ },
70
+ __wbindgen_init_externref_table: function() {
71
+ const table = wasm.__wbindgen_externrefs;
72
+ const offset = table.grow(4);
73
+ table.set(0, undefined);
74
+ table.set(offset + 0, undefined);
75
+ table.set(offset + 1, null);
76
+ table.set(offset + 2, true);
77
+ table.set(offset + 3, false);
78
+ },
79
+ };
80
+ return {
81
+ __proto__: null,
82
+ "./rumoca_bind_wasm_diffsol_bg.js": import0,
83
+ };
84
+ }
85
+
86
+ let cachedDataViewMemory0 = null;
87
+ function getDataViewMemory0() {
88
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
89
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
90
+ }
91
+ return cachedDataViewMemory0;
92
+ }
93
+
94
+ function getStringFromWasm0(ptr, len) {
95
+ ptr = ptr >>> 0;
96
+ return decodeText(ptr, len);
97
+ }
98
+
99
+ let cachedUint8ArrayMemory0 = null;
100
+ function getUint8ArrayMemory0() {
101
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
102
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
103
+ }
104
+ return cachedUint8ArrayMemory0;
105
+ }
106
+
107
+ function passStringToWasm0(arg, malloc, realloc) {
108
+ if (realloc === undefined) {
109
+ const buf = cachedTextEncoder.encode(arg);
110
+ const ptr = malloc(buf.length, 1) >>> 0;
111
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
112
+ WASM_VECTOR_LEN = buf.length;
113
+ return ptr;
114
+ }
115
+
116
+ let len = arg.length;
117
+ let ptr = malloc(len, 1) >>> 0;
118
+
119
+ const mem = getUint8ArrayMemory0();
120
+
121
+ let offset = 0;
122
+
123
+ for (; offset < len; offset++) {
124
+ const code = arg.charCodeAt(offset);
125
+ if (code > 0x7F) break;
126
+ mem[ptr + offset] = code;
127
+ }
128
+ if (offset !== len) {
129
+ if (offset !== 0) {
130
+ arg = arg.slice(offset);
131
+ }
132
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
133
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
134
+ const ret = cachedTextEncoder.encodeInto(arg, view);
135
+
136
+ offset += ret.written;
137
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
138
+ }
139
+
140
+ WASM_VECTOR_LEN = offset;
141
+ return ptr;
142
+ }
143
+
144
+ function takeFromExternrefTable0(idx) {
145
+ const value = wasm.__wbindgen_externrefs.get(idx);
146
+ wasm.__externref_table_dealloc(idx);
147
+ return value;
148
+ }
149
+
150
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
151
+ cachedTextDecoder.decode();
152
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
153
+ let numBytesDecoded = 0;
154
+ function decodeText(ptr, len) {
155
+ numBytesDecoded += len;
156
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
157
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
158
+ cachedTextDecoder.decode();
159
+ numBytesDecoded = len;
160
+ }
161
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
162
+ }
163
+
164
+ const cachedTextEncoder = new TextEncoder();
165
+
166
+ if (!('encodeInto' in cachedTextEncoder)) {
167
+ cachedTextEncoder.encodeInto = function (arg, view) {
168
+ const buf = cachedTextEncoder.encode(arg);
169
+ view.set(buf);
170
+ return {
171
+ read: arg.length,
172
+ written: buf.length
173
+ };
174
+ };
175
+ }
176
+
177
+ let WASM_VECTOR_LEN = 0;
178
+
179
+ let wasmModule, wasm;
180
+ function __wbg_finalize_init(instance, module) {
181
+ wasm = instance.exports;
182
+ wasmModule = module;
183
+ cachedDataViewMemory0 = null;
184
+ cachedUint8ArrayMemory0 = null;
185
+ wasm.__wbindgen_start();
186
+ return wasm;
187
+ }
188
+
189
+ async function __wbg_load(module, imports) {
190
+ if (typeof Response === 'function' && module instanceof Response) {
191
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
192
+ try {
193
+ return await WebAssembly.instantiateStreaming(module, imports);
194
+ } catch (e) {
195
+ const validResponse = module.ok && expectedResponseType(module.type);
196
+
197
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
198
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
199
+
200
+ } else { throw e; }
201
+ }
202
+ }
203
+
204
+ const bytes = await module.arrayBuffer();
205
+ return await WebAssembly.instantiate(bytes, imports);
206
+ } else {
207
+ const instance = await WebAssembly.instantiate(module, imports);
208
+
209
+ if (instance instanceof WebAssembly.Instance) {
210
+ return { instance, module };
211
+ } else {
212
+ return instance;
213
+ }
214
+ }
215
+
216
+ function expectedResponseType(type) {
217
+ switch (type) {
218
+ case 'basic': case 'cors': case 'default': return true;
219
+ }
220
+ return false;
221
+ }
222
+ }
223
+
224
+ function initSync(module) {
225
+ if (wasm !== undefined) return wasm;
226
+
227
+
228
+ if (module !== undefined) {
229
+ if (Object.getPrototypeOf(module) === Object.prototype) {
230
+ ({module} = module)
231
+ } else {
232
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
233
+ }
234
+ }
235
+
236
+ const imports = __wbg_get_imports();
237
+ if (!(module instanceof WebAssembly.Module)) {
238
+ module = new WebAssembly.Module(module);
239
+ }
240
+ const instance = new WebAssembly.Instance(module, imports);
241
+ return __wbg_finalize_init(instance, module);
242
+ }
243
+
244
+ async function __wbg_init(module_or_path) {
245
+ if (wasm !== undefined) return wasm;
246
+
247
+
248
+ if (module_or_path !== undefined) {
249
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
250
+ ({module_or_path} = module_or_path)
251
+ } else {
252
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
253
+ }
254
+ }
255
+
256
+ if (module_or_path === undefined) {
257
+ module_or_path = new URL('rumoca_bind_wasm_diffsol_bg.wasm', import.meta.url);
258
+ }
259
+ const imports = __wbg_get_imports();
260
+
261
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
262
+ module_or_path = fetch(module_or_path);
263
+ }
264
+
265
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
266
+
267
+ return __wbg_finalize_init(instance, module);
268
+ }
269
+
270
+ export { initSync, __wbg_init as default };
Binary file
@@ -0,0 +1,109 @@
1
+ // Lazy diffsol (stiff/implicit) simulation driver for the @cognipilot/rumoca
2
+ // package.
3
+ //
4
+ // Why this exists: the main rumoca WASM module is SIMD-free and loads on every
5
+ // browser. The diffsol solver pulls relaxed-SIMD (via faer/pulp), and WASM
6
+ // validates a whole module at instantiation — so a single combined module
7
+ // would hard-fail the entire package on browsers without relaxed-SIMD. Instead
8
+ // the diffsol code ships as a *separate* tiny module (~0.4 MB gz,
9
+ // `rumoca_bind_wasm_diffsol.js`) that is loaded only when (a) the browser
10
+ // supports relaxed-SIMD and (b) the user actually runs a stiff solve.
11
+ //
12
+ // Usage (the main module is already initialized by the caller):
13
+ // import { diffsolAvailable, simulateWithDiffsol } from "@cognipilot/rumoca/diffsol";
14
+ // const ok = await diffsolAvailable(pkgBase); // grey out the UI if false
15
+ // const result = await simulateWithDiffsol(mainModule, pkgBase, src, model, tEnd, dt);
16
+ //
17
+ // `pkgBase` is the same base URL the main `rumoca_bind_wasm.js` was imported
18
+ // from (the addon wasm sits next to it).
19
+
20
+ // Minimal module that uses a 1-operand relaxed-SIMD op
21
+ // (`i32x4.relaxed_trunc_f32x4_s`, 0xFD 0x101). `WebAssembly.validate` returns
22
+ // false on engines without relaxed-SIMD. This is a cheap *hint* for greying out
23
+ // the UI; the authoritative check is whether the addon actually instantiates
24
+ // (see `diffsolAvailable`). NOTE: verify in a real browser as part of the
25
+ // editor smoke test.
26
+ const RELAXED_SIMD_PROBE = new Uint8Array([
27
+ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, // \0asm v1
28
+ 0x01, 0x05, 0x01, 0x60, 0x00, 0x01, 0x7b, // type: () -> v128
29
+ 0x03, 0x02, 0x01, 0x00, // func 0 : type 0
30
+ 0x0a, 0x19, 0x01, 0x17, 0x00, // code: 1 body, size 23, 0 locals
31
+ 0xfd, 0x0c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // v128.const 0
32
+ 0xfd, 0x81, 0x02, // i32x4.relaxed_trunc_f32x4_s
33
+ 0x0b, // end
34
+ ]);
35
+
36
+ /** Quick, non-authoritative hint: does this engine validate relaxed-SIMD? */
37
+ export function relaxedSimdSupported() {
38
+ try {
39
+ return WebAssembly.validate(RELAXED_SIMD_PROBE);
40
+ } catch {
41
+ return false;
42
+ }
43
+ }
44
+
45
+ let addonPromise = null;
46
+
47
+ /**
48
+ * Lazily import + initialize the diffsol addon module from `pkgBase`. Resolves
49
+ * to the module's exports, or rejects (e.g. `CompileError` on a browser without
50
+ * relaxed-SIMD). Cached after the first call.
51
+ */
52
+ export function loadDiffsolAddon(pkgBase) {
53
+ if (!addonPromise) {
54
+ addonPromise = (async () => {
55
+ const mod = await import(pkgBase + "rumoca_bind_wasm_diffsol.js");
56
+ await mod.default(); // run wasm-bindgen init (instantiates the wasm)
57
+ return mod;
58
+ })();
59
+ // Allow a retry if loading failed (e.g. transient network).
60
+ addonPromise.catch(() => {
61
+ addonPromise = null;
62
+ });
63
+ }
64
+ return addonPromise;
65
+ }
66
+
67
+ /**
68
+ * Authoritative check: true iff the diffsol addon actually instantiates in this
69
+ * browser. Downloads/compiles the addon once (cached). Use this to enable or
70
+ * grey out the stiff-solver options.
71
+ */
72
+ export async function diffsolAvailable(pkgBase) {
73
+ try {
74
+ await loadDiffsolAddon(pkgBase);
75
+ return true;
76
+ } catch {
77
+ return false;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Run a stiff (diffsol) simulation: the main module lowers the model to a
83
+ * SolveModel JSON, the addon simulates it. Returns the parsed
84
+ * `{ payload, ... }` object (same shape as the main module's `simulate_model`).
85
+ * Throws a clear error if the addon can't load (old browser) — callers should
86
+ * fall back to rk45 / the GPU path or surface the message.
87
+ */
88
+ export async function simulateWithDiffsol(mainModule, pkgBase, source, modelName, tEnd, dt) {
89
+ if (typeof mainModule.lower_model_to_solve_json !== "function") {
90
+ throw new Error(
91
+ "this rumoca build predates the diffsol addon; rebuild the package",
92
+ );
93
+ }
94
+ let addon;
95
+ try {
96
+ addon = await loadDiffsolAddon(pkgBase);
97
+ } catch (err) {
98
+ throw new Error(
99
+ "the stiff (diffsol) solver needs a browser with WebAssembly relaxed-SIMD " +
100
+ "(Chrome 114+, Firefox 120+, Safari 16.4+). Use the rk45 solver or the GPU " +
101
+ `path instead. (${err && err.message ? err.message : err})`,
102
+ );
103
+ }
104
+ // The payload carries the lowered model plus the resolved t_end/dt (so an
105
+ // annotation-driven duration is honored even when the caller passes 0).
106
+ const prepJson = mainModule.lower_model_to_solve_json(source, modelName, tEnd, dt);
107
+ const resultJson = addon.simulate_solve_model_diffsol(prepJson);
108
+ return JSON.parse(resultJson);
109
+ }