numbl 0.0.11 → 0.0.12

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 (2) hide show
  1. package/dist-cli/cli.js +172 -89
  2. package/package.json +3 -2
package/dist-cli/cli.js CHANGED
@@ -20504,6 +20504,82 @@ var erfcxScalar = (x) => {
20504
20504
  };
20505
20505
 
20506
20506
  // src/numbl-core/builtins/math.ts
20507
+ function cRecip(re, im) {
20508
+ const d = re * re + im * im;
20509
+ return { re: re / d, im: -im / d };
20510
+ }
20511
+ function composeRecip(complexFn) {
20512
+ return (re, im) => {
20513
+ const r = cRecip(re, im);
20514
+ return complexFn(r.re, r.im);
20515
+ };
20516
+ }
20517
+ function cAcos(re, im) {
20518
+ const w2re = 1 - re * re + im * im, w2im = -2 * re * im;
20519
+ const w2r = Math.sqrt(w2re * w2re + w2im * w2im);
20520
+ const w3re = Math.sqrt((w2r + w2re) / 2);
20521
+ const w3im = w2im >= 0 ? Math.sqrt((w2r - w2re) / 2) : -Math.sqrt((w2r - w2re) / 2);
20522
+ const w4re = re - w3im, w4im = im + w3re;
20523
+ const w5re = Math.log(Math.sqrt(w4re * w4re + w4im * w4im));
20524
+ const w5im = Math.atan2(w4im, w4re);
20525
+ return { re: w5im, im: -w5re };
20526
+ }
20527
+ function cAsin(re, im) {
20528
+ const w1re = -im, w1im = re;
20529
+ const w2re = 1 - re * re + im * im, w2im = -2 * re * im;
20530
+ const w2r = Math.sqrt(w2re * w2re + w2im * w2im);
20531
+ const w3re = Math.sqrt((w2r + w2re) / 2);
20532
+ const w3im = w2im >= 0 ? Math.sqrt((w2r - w2re) / 2) : -Math.sqrt((w2r - w2re) / 2);
20533
+ const w4re = w1re + w3re, w4im = w1im + w3im;
20534
+ const w5re = Math.log(Math.sqrt(w4re * w4re + w4im * w4im));
20535
+ const w5im = Math.atan2(w4im, w4re);
20536
+ return { re: w5im, im: -w5re };
20537
+ }
20538
+ function cAcosh(re, im) {
20539
+ const a1re = re - 1, a1im = im;
20540
+ const a1r = Math.sqrt(a1re * a1re + a1im * a1im);
20541
+ const s1re = Math.sqrt((a1r + a1re) / 2);
20542
+ const s1im = a1im >= 0 ? Math.sqrt((a1r - a1re) / 2) : -Math.sqrt((a1r - a1re) / 2);
20543
+ const a2re = re + 1, a2im = im;
20544
+ const a2r = Math.sqrt(a2re * a2re + a2im * a2im);
20545
+ const s2re = Math.sqrt((a2r + a2re) / 2);
20546
+ const s2im = a2im >= 0 ? Math.sqrt((a2r - a2re) / 2) : -Math.sqrt((a2r - a2re) / 2);
20547
+ const w2re = s1re * s2re - s1im * s2im;
20548
+ const w2im = s1re * s2im + s1im * s2re;
20549
+ const w3re = re + w2re, w3im = im + w2im;
20550
+ return {
20551
+ re: Math.log(Math.sqrt(w3re * w3re + w3im * w3im)),
20552
+ im: Math.atan2(w3im, w3re)
20553
+ };
20554
+ }
20555
+ function cAsinh(re, im) {
20556
+ const z2re = re * re - im * im, z2im = 2 * re * im;
20557
+ const w1re = z2re + 1, w1im = z2im;
20558
+ const w1r = Math.sqrt(w1re * w1re + w1im * w1im);
20559
+ const w2re = Math.sqrt((w1r + w1re) / 2);
20560
+ const w2im = w1im >= 0 ? Math.sqrt((w1r - w1re) / 2) : -Math.sqrt((w1r - w1re) / 2);
20561
+ const w3re = re + w2re, w3im = im + w2im;
20562
+ return {
20563
+ re: Math.log(Math.sqrt(w3re * w3re + w3im * w3im)),
20564
+ im: Math.atan2(w3im, w3re)
20565
+ };
20566
+ }
20567
+ function cAtanh(re, im) {
20568
+ if (im === 0 && (re > 1 || re < -1)) {
20569
+ return {
20570
+ re: 0.5 * Math.log(Math.abs((1 + re) / (1 - re))),
20571
+ im: re > 0 ? Math.PI / 2 : -Math.PI / 2
20572
+ };
20573
+ }
20574
+ const w1re = 1 + re, w1im = im;
20575
+ const w2re = 1 - re, w2im = -im;
20576
+ const denom = w2re * w2re + w2im * w2im;
20577
+ const w3re = (w1re * w2re + w1im * w2im) / denom;
20578
+ const w3im = (w1im * w2re - w1re * w2im) / denom;
20579
+ const w4re = Math.log(Math.sqrt(w3re * w3re + w3im * w3im));
20580
+ const w4im = Math.atan2(w3im, w3re);
20581
+ return { re: w4re / 2, im: w4im / 2 };
20582
+ }
20507
20583
  function applyToComplex(v, fn) {
20508
20584
  if (isRuntimeComplexNumber(v)) {
20509
20585
  const result = fn(v.re, v.im);
@@ -20783,41 +20859,16 @@ function registerMathFunctions() {
20783
20859
  );
20784
20860
  register(
20785
20861
  "asin",
20786
- complexElemwise(
20787
- Math.asin,
20788
- (re, im) => {
20789
- const w1re = -im, w1im = re;
20790
- const w2re = 1 - re * re + im * im, w2im = -2 * re * im;
20791
- const w2r = Math.sqrt(w2re * w2re + w2im * w2im);
20792
- const w3re = Math.sqrt((w2r + w2re) / 2);
20793
- const w3im = w2im >= 0 ? Math.sqrt((w2r - w2re) / 2) : -Math.sqrt((w2r - w2re) / 2);
20794
- const w4re = w1re + w3re, w4im = w1im + w3im;
20795
- const w5re = Math.log(Math.sqrt(w4re * w4re + w4im * w4im));
20796
- const w5im = Math.atan2(w4im, w4re);
20797
- return { re: w5im, im: -w5re };
20798
- },
20799
- "ComplexNumber",
20800
- { nativeJs: "Math.asin" }
20801
- ),
20862
+ complexElemwise(Math.asin, cAsin, "ComplexNumber", {
20863
+ nativeJs: "Math.asin"
20864
+ }),
20802
20865
  1
20803
20866
  );
20804
20867
  register(
20805
20868
  "acos",
20806
- complexElemwise(
20807
- Math.acos,
20808
- (re, im) => {
20809
- const w2re = 1 - re * re + im * im, w2im = -2 * re * im;
20810
- const w2r = Math.sqrt(w2re * w2re + w2im * w2im);
20811
- const w3re = Math.sqrt((w2r + w2re) / 2);
20812
- const w3im = w2im >= 0 ? Math.sqrt((w2r - w2re) / 2) : -Math.sqrt((w2r - w2re) / 2);
20813
- const w4re = re - w3im, w4im = im + w3re;
20814
- const w5re = Math.log(Math.sqrt(w4re * w4re + w4im * w4im));
20815
- const w5im = Math.atan2(w4im, w4re);
20816
- return { re: w5im, im: -w5re };
20817
- },
20818
- "ComplexNumber",
20819
- { nativeJs: "Math.acos" }
20820
- ),
20869
+ complexElemwise(Math.acos, cAcos, "ComplexNumber", {
20870
+ nativeJs: "Math.acos"
20871
+ }),
20821
20872
  1
20822
20873
  );
20823
20874
  register(
@@ -20883,63 +20934,23 @@ function registerMathFunctions() {
20883
20934
  );
20884
20935
  register(
20885
20936
  "asinh",
20886
- complexElemwise(
20887
- Math.asinh,
20888
- (re, im) => {
20889
- const z2re = re * re - im * im, z2im = 2 * re * im;
20890
- const w1re = z2re + 1, w1im = z2im;
20891
- const w1r = Math.sqrt(w1re * w1re + w1im * w1im);
20892
- const w2re = Math.sqrt((w1r + w1re) / 2);
20893
- const w2im = w1im >= 0 ? Math.sqrt((w1r - w1re) / 2) : -Math.sqrt((w1r - w1re) / 2);
20894
- const w3re = re + w2re, w3im = im + w2im;
20895
- return {
20896
- re: Math.log(Math.sqrt(w3re * w3re + w3im * w3im)),
20897
- im: Math.atan2(w3im, w3re)
20898
- };
20899
- },
20900
- "ComplexNumber",
20901
- { nativeJs: "Math.asinh" }
20902
- ),
20937
+ complexElemwise(Math.asinh, cAsinh, "ComplexNumber", {
20938
+ nativeJs: "Math.asinh"
20939
+ }),
20903
20940
  1
20904
20941
  );
20905
20942
  register(
20906
20943
  "acosh",
20907
- complexElemwise(
20908
- Math.acosh,
20909
- (re, im) => {
20910
- const z2re = re * re - im * im, z2im = 2 * re * im;
20911
- const w1re = z2re - 1, w1im = z2im;
20912
- const w1r = Math.sqrt(w1re * w1re + w1im * w1im);
20913
- const w2re = Math.sqrt((w1r + w1re) / 2);
20914
- const w2im = w1im >= 0 ? Math.sqrt((w1r - w1re) / 2) : -Math.sqrt((w1r - w1re) / 2);
20915
- const w3re = re + w2re, w3im = im + w2im;
20916
- return {
20917
- re: Math.log(Math.sqrt(w3re * w3re + w3im * w3im)),
20918
- im: Math.atan2(w3im, w3re)
20919
- };
20920
- },
20921
- "ComplexNumber",
20922
- { nativeJs: "Math.acosh" }
20923
- ),
20944
+ complexElemwise(Math.acosh, cAcosh, "ComplexNumber", {
20945
+ nativeJs: "Math.acosh"
20946
+ }),
20924
20947
  1
20925
20948
  );
20926
20949
  register(
20927
20950
  "atanh",
20928
- complexElemwise(
20929
- Math.atanh,
20930
- (re, im) => {
20931
- const w1re = 1 + re, w1im = im;
20932
- const w2re = 1 - re, w2im = -im;
20933
- const denom = w2re * w2re + w2im * w2im;
20934
- const w3re = (w1re * w2re + w1im * w2im) / denom;
20935
- const w3im = (w1im * w2re - w1re * w2im) / denom;
20936
- const w4re = Math.log(Math.sqrt(w3re * w3re + w3im * w3im));
20937
- const w4im = Math.atan2(w3im, w3re);
20938
- return { re: w4re / 2, im: w4im / 2 };
20939
- },
20940
- "ComplexNumber",
20941
- { nativeJs: "Math.atanh" }
20942
- ),
20951
+ complexElemwise(Math.atanh, cAtanh, "ComplexNumber", {
20952
+ nativeJs: "Math.atanh"
20953
+ }),
20943
20954
  1
20944
20955
  );
20945
20956
  const deg2rad = Math.PI / 180;
@@ -21474,17 +21485,29 @@ function registerMathFunctions() {
21474
21485
  );
21475
21486
  register(
21476
21487
  "asech",
21477
- elemwise((x) => Math.acosh(1 / x)),
21488
+ complexElemwise(
21489
+ (x) => Math.acosh(1 / x),
21490
+ composeRecip(cAcosh),
21491
+ "ComplexNumber"
21492
+ ),
21478
21493
  1
21479
21494
  );
21480
21495
  register(
21481
21496
  "acsch",
21482
- elemwise((x) => Math.asinh(1 / x)),
21497
+ complexElemwise(
21498
+ (x) => Math.asinh(1 / x),
21499
+ composeRecip(cAsinh),
21500
+ "ComplexNumber"
21501
+ ),
21483
21502
  1
21484
21503
  );
21485
21504
  register(
21486
21505
  "acoth",
21487
- elemwise((x) => Math.atanh(1 / x)),
21506
+ complexElemwise(
21507
+ (x) => Math.atanh(1 / x),
21508
+ composeRecip(cAtanh),
21509
+ "ComplexNumber"
21510
+ ),
21488
21511
  1
21489
21512
  );
21490
21513
  register(
@@ -21504,12 +21527,20 @@ function registerMathFunctions() {
21504
21527
  );
21505
21528
  register(
21506
21529
  "asec",
21507
- elemwise((x) => Math.acos(1 / x)),
21530
+ complexElemwise(
21531
+ (x) => Math.acos(1 / x),
21532
+ composeRecip(cAcos),
21533
+ "ComplexNumber"
21534
+ ),
21508
21535
  1
21509
21536
  );
21510
21537
  register(
21511
21538
  "acsc",
21512
- elemwise((x) => Math.asin(1 / x)),
21539
+ complexElemwise(
21540
+ (x) => Math.asin(1 / x),
21541
+ composeRecip(cAsin),
21542
+ "ComplexNumber"
21543
+ ),
21513
21544
  1
21514
21545
  );
21515
21546
  register(
@@ -21517,14 +21548,26 @@ function registerMathFunctions() {
21517
21548
  elemwise((x) => Math.atan(1 / x)),
21518
21549
  1
21519
21550
  );
21551
+ const toDeg = (fn) => (re, im) => {
21552
+ const r = fn(re, im);
21553
+ return { re: r.re * rad2deg, im: r.im * rad2deg };
21554
+ };
21520
21555
  register(
21521
21556
  "asecd",
21522
- elemwise((x) => Math.acos(1 / x) * rad2deg),
21557
+ complexElemwise(
21558
+ (x) => Math.acos(1 / x) * rad2deg,
21559
+ toDeg(composeRecip(cAcos)),
21560
+ "ComplexNumber"
21561
+ ),
21523
21562
  1
21524
21563
  );
21525
21564
  register(
21526
21565
  "acscd",
21527
- elemwise((x) => Math.asin(1 / x) * rad2deg),
21566
+ complexElemwise(
21567
+ (x) => Math.asin(1 / x) * rad2deg,
21568
+ toDeg(composeRecip(cAsin)),
21569
+ "ComplexNumber"
21570
+ ),
21528
21571
  1
21529
21572
  );
21530
21573
  register(
@@ -28669,6 +28712,9 @@ var Runtime = class _Runtime {
28669
28712
  RTV = RTV;
28670
28713
  // Persistent variable storage: funcJsId → varName → value
28671
28714
  persistentStore = /* @__PURE__ */ new Map();
28715
+ // Global variable storage: varName → value (shared across all functions)
28716
+ // Public object so generated code can read/write as $rt.$g["name"]
28717
+ $g = {};
28672
28718
  // Accessor guard: prevents recursive getter/setter/subsref calls
28673
28719
  activeAccessors = /* @__PURE__ */ new Set();
28674
28720
  // Callbacks into the compiler for class information (set by executeCode).
@@ -38967,8 +39013,15 @@ function genStmt(cg, stmt) {
38967
39013
  }
38968
39014
  break;
38969
39015
  }
38970
- case "Global":
39016
+ case "Global": {
39017
+ for (const v of stmt.vars) {
39018
+ cg.globalVarRefs.set(
39019
+ v.variable.id.id,
39020
+ `$rt.$g[${JSON.stringify(v.name)}]`
39021
+ );
39022
+ }
38971
39023
  break;
39024
+ }
38972
39025
  case "Persistent": {
38973
39026
  if (cg.currentFunctionJsId) {
38974
39027
  const funcId = JSON.stringify(cg.currentFunctionJsId);
@@ -39472,6 +39525,9 @@ var Codegen = class {
39472
39525
  generationInProgress = /* @__PURE__ */ new Map();
39473
39526
  // VarId → JS name cache
39474
39527
  varNameCache = /* @__PURE__ */ new Map();
39528
+ // Global variable overrides: VarId → $rt.$g["name"] expression.
39529
+ // Set by Global statement codegen so all reads/writes go through the shared store.
39530
+ globalVarRefs = /* @__PURE__ */ new Map();
39475
39531
  // Stack of variable reference overrides (for closure capture in anonymous functions).
39476
39532
  // Each entry maps varId → replacement JS expression.
39477
39533
  varRefOverrides = [];
@@ -39552,6 +39608,8 @@ var Codegen = class {
39552
39608
  const override = this.varRefOverrides[i].get(id);
39553
39609
  if (override !== void 0) return override;
39554
39610
  }
39611
+ const globalRef = this.globalVarRefs.get(id);
39612
+ if (globalRef !== void 0) return globalRef;
39555
39613
  const cached = this.varNameCache.get(id);
39556
39614
  if (cached) return cached;
39557
39615
  const lastUnderscore = id.lastIndexOf("_");
@@ -40242,8 +40300,27 @@ var stdlibFiles = [
40242
40300
  source: "function parse(obj, varargin)\n obj.parse(varargin{:});\nend\n"
40243
40301
  }
40244
40302
  ];
40303
+ var shimFiles = [
40304
+ {
40305
+ name: "+matlab/+internal/+decomposition/DenseLU.m",
40306
+ source: "classdef DenseLU\n properties\n L\n U\n P\n end\n methods\n function obj = DenseLU(A)\n [obj.L, obj.U, obj.P] = lu(A);\n end\n function x = solve(obj, b, ~)\n x = obj.U \\ (obj.L \\ (obj.P * b));\n end\n end\nend"
40307
+ },
40308
+ {
40309
+ name: "+matlab/+internal/+math/blkdiag.m",
40310
+ source: "function B = blkdiag(varargin)\n B = builtin('blkdiag', varargin{:});\nend\n"
40311
+ },
40312
+ {
40313
+ name: "decomposition.m",
40314
+ source: "classdef decomposition\n properties\n A\n checkCondition\n isIllCond\n end\n methods\n function obj = decomposition(A, varargin)\n obj.A = A;\n obj.checkCondition = true;\n for i = 1:2:length(varargin)\n if strcmpi(varargin{i}, 'CheckCondition')\n obj.checkCondition = varargin{i+1};\n end\n end\n if obj.checkCondition\n obj.isIllCond = (rcond(A) < eps);\n else\n obj.isIllCond = false;\n end\n end\n function x = mldivide(obj, b)\n x = obj.A \\ b;\n end\n end\nend\n"
40315
+ },
40316
+ {
40317
+ name: "isIllConditioned.m",
40318
+ source: "function result = isIllConditioned(dA)\n result = dA.isIllCond;\nend\n"
40319
+ }
40320
+ ];
40245
40321
 
40246
40322
  // src/numbl-core/codegen/generateMainScriptCode.ts
40323
+ var SHIM_SEARCH_PATH = "__numbl_shims__";
40247
40324
  function generateMainScriptCode(source, mainFileName = "script.m", workspaceFiles, initialVariableNames, searchPaths) {
40248
40325
  let _t0 = performance.now();
40249
40326
  const ast = parseMFile(source, mainFileName);
@@ -40269,7 +40346,6 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
40269
40346
  }
40270
40347
  const _parseMainMs = performance.now() - _t0;
40271
40348
  const ctx = new LoweringContext(source, mainFileName);
40272
- ctx.registry.searchPaths = searchPaths ?? [];
40273
40349
  const mWorkspaceFiles = [];
40274
40350
  const jsWorkspaceFiles = [];
40275
40351
  if (workspaceFiles) {
@@ -40284,6 +40360,13 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
40284
40360
  for (const f of stdlibFiles) {
40285
40361
  mWorkspaceFiles.push(f);
40286
40362
  }
40363
+ for (const f of shimFiles) {
40364
+ mWorkspaceFiles.push({
40365
+ name: `${SHIM_SEARCH_PATH}/${f.name}`,
40366
+ source: f.source
40367
+ });
40368
+ }
40369
+ ctx.registry.searchPaths = [...searchPaths ?? [], SHIM_SEARCH_PATH];
40287
40370
  _t0 = performance.now();
40288
40371
  const jsUserFunctions = loadJsUserFunctions(jsWorkspaceFiles);
40289
40372
  const _loadJsUserFunctionsMs = performance.now() - _t0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "numbl",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "Run .m source files in the browser and on the command line by compiling to JavaScript",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -31,7 +31,8 @@
31
31
  "dev": "vite",
32
32
  "build": "npm run build:web && npm run build:cli && npm run build:plot-viewer",
33
33
  "build:plot-viewer": "vite build --config vite.plot-viewer.config.ts",
34
- "build:web": "tsc -b && vite build",
34
+ "bundle:stdlib": "tsx scripts/bundle-stdlib.ts",
35
+ "build:web": "npm run bundle:stdlib && tsc -b && vite build",
35
36
  "build:cli": "esbuild src/cli.ts --bundle --platform=node --format=esm --outfile=dist-cli/cli.js --packages=external --loader:.wasm=file",
36
37
  "build:server": "esbuild server/execution-service.ts --bundle --platform=node --format=esm --outfile=server/dist/execution-service.js --packages=external",
37
38
  "server:dev": "node --env-file=server/.env node_modules/.bin/tsx server/execution-service.ts",