numbl 0.4.2 → 0.4.3

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/dist-cli/cli.js CHANGED
@@ -2213,9 +2213,9 @@ function airyAllComplex(zr, zi) {
2213
2213
  sfpi += m3k * tfi;
2214
2214
  sgpr += (m3k + 1) * tgr;
2215
2215
  sgpi += (m3k + 1) * tgi;
2216
- const mag = Math.abs(tfr) + Math.abs(tfi) + Math.abs(tgr) + Math.abs(tgi);
2216
+ const mag2 = Math.abs(tfr) + Math.abs(tfi) + Math.abs(tgr) + Math.abs(tgi);
2217
2217
  const ref = Math.abs(sfr) + Math.abs(sfi) + Math.abs(sgr) + Math.abs(sgi) + 1e-300;
2218
- if (mag < 1e-16 * ref) break;
2218
+ if (mag2 < 1e-16 * ref) break;
2219
2219
  }
2220
2220
  const gr = zr * sgr - zi * sgi;
2221
2221
  const gi = zr * sgi + zi * sgr;
@@ -24554,8 +24554,8 @@ function sinpi(x) {
24554
24554
  return Math.sin(Math.PI * x);
24555
24555
  }
24556
24556
  function negRealPow(negBase, exponent) {
24557
- const mag = Math.pow(-negBase, exponent);
24558
- return { re: mag * cospi(exponent), im: mag * sinpi(exponent) };
24557
+ const mag2 = Math.pow(-negBase, exponent);
24558
+ return { re: mag2 * cospi(exponent), im: mag2 * sinpi(exponent) };
24559
24559
  }
24560
24560
  function mPow(a, b) {
24561
24561
  if (isComplexOrMixed(a, b)) {
@@ -26464,9 +26464,9 @@ function complexSqrt(re, im) {
26464
26464
  if (re >= 0) return { re: Math.sqrt(re), im: 0 };
26465
26465
  return { re: 0, im: Math.sqrt(-re) };
26466
26466
  }
26467
- const mag = Math.hypot(re, im);
26468
- if (mag === 0) return { re: 0, im: 0 };
26469
- const r = Math.sqrt(mag);
26467
+ const mag2 = Math.hypot(re, im);
26468
+ if (mag2 === 0) return { re: 0, im: 0 };
26469
+ const r = Math.sqrt(mag2);
26470
26470
  const angle2 = Math.atan2(im, re) / 2;
26471
26471
  return { re: r * Math.cos(angle2), im: r * Math.sin(angle2) };
26472
26472
  }
@@ -26514,9 +26514,9 @@ defineBuiltin({
26514
26514
  )
26515
26515
  });
26516
26516
  registerUnary("sign", Math.sign, (re, im) => {
26517
- const mag = Math.hypot(re, im);
26518
- if (mag === 0) return { re: 0, im: 0 };
26519
- return { re: re / mag, im: im / mag };
26517
+ const mag2 = Math.hypot(re, im);
26518
+ if (mag2 === 0) return { re: 0, im: 0 };
26519
+ return { re: re / mag2, im: im / mag2 };
26520
26520
  });
26521
26521
  function registerRounding(name, fn) {
26522
26522
  defineBuiltin({
@@ -33133,6 +33133,134 @@ function stream2Call(args) {
33133
33133
  return RTV.cell(cellData, [1, cellData.length]);
33134
33134
  }
33135
33135
 
33136
+ // src/numbl-core/runtime/axisCommand.ts
33137
+ var STYLE_WORDS = /* @__PURE__ */ new Set([
33138
+ "tight",
33139
+ "padded",
33140
+ "fill",
33141
+ "equal",
33142
+ "image",
33143
+ "square",
33144
+ "vis3d",
33145
+ "normal",
33146
+ "tickaligned"
33147
+ ]);
33148
+ var STYLE_RESETS_LIMITS = /* @__PURE__ */ new Set([
33149
+ "tight",
33150
+ "padded",
33151
+ "equal",
33152
+ "image",
33153
+ "tickaligned"
33154
+ ]);
33155
+ var AUTO_AXIS_TOKENS = {
33156
+ auto: ["x", "y", "z"],
33157
+ "auto x": ["x"],
33158
+ "auto y": ["y"],
33159
+ "auto z": ["z"],
33160
+ "auto xy": ["x", "y"],
33161
+ "auto yx": ["x", "y"],
33162
+ "auto xz": ["x", "z"],
33163
+ "auto zx": ["x", "z"],
33164
+ "auto yz": ["y", "z"],
33165
+ "auto zy": ["y", "z"]
33166
+ };
33167
+ function isHandle(v) {
33168
+ return isRuntimeDummyHandle(v) || isRuntimeGraphicsHandle(v);
33169
+ }
33170
+ function numericValues(v) {
33171
+ if (isRuntimeTensor(v)) return Array.from(v.data);
33172
+ if (isRuntimeNumber(v)) return [v];
33173
+ if (isRuntimeLogical(v)) return [v ? 1 : 0];
33174
+ return null;
33175
+ }
33176
+ function bound(v) {
33177
+ return Number.isFinite(v) ? v : null;
33178
+ }
33179
+ function clearLimits(axes) {
33180
+ const instr = {
33181
+ type: "set_axis_limits"
33182
+ };
33183
+ if (axes.includes("x")) instr.xlim = "auto";
33184
+ if (axes.includes("y")) instr.ylim = "auto";
33185
+ if (axes.includes("z")) instr.zlim = "auto";
33186
+ return instr;
33187
+ }
33188
+ function applyAxisCommand(args, instructions, freezeLimits) {
33189
+ let i = 0;
33190
+ while (i < args.length && isHandle(args[i])) i++;
33191
+ let applied = false;
33192
+ const styles = [];
33193
+ for (; i < args.length; i++) {
33194
+ const arg = args[i];
33195
+ const nums = numericValues(arg);
33196
+ if (nums !== null) {
33197
+ applied = true;
33198
+ if (nums.length === 1) {
33199
+ instructions.push({ type: "set_axis_visible", value: nums[0] !== 0 });
33200
+ continue;
33201
+ }
33202
+ if (nums.length === 4 || nums.length === 6 || nums.length === 8) {
33203
+ const instr = {
33204
+ type: "set_axis_limits",
33205
+ xlim: [bound(nums[0]), bound(nums[1])],
33206
+ ylim: [bound(nums[2]), bound(nums[3])]
33207
+ };
33208
+ if (nums.length >= 6) instr.zlim = [bound(nums[4]), bound(nums[5])];
33209
+ instructions.push(instr);
33210
+ if (nums.length === 8 && Number.isFinite(nums[6]) && Number.isFinite(nums[7])) {
33211
+ instructions.push({ type: "set_caxis", limits: [nums[6], nums[7]] });
33212
+ }
33213
+ continue;
33214
+ }
33215
+ throw new RuntimeError(
33216
+ "axis: limit vector must have 4, 6, or 8 elements"
33217
+ );
33218
+ }
33219
+ const kw = toString(arg).trim().replace(/^["']|["']$/g, "").toLowerCase();
33220
+ applied = true;
33221
+ if (STYLE_WORDS.has(kw)) {
33222
+ styles.push(kw);
33223
+ if (STYLE_RESETS_LIMITS.has(kw)) {
33224
+ instructions.push(clearLimits(["x", "y", "z"]));
33225
+ }
33226
+ continue;
33227
+ }
33228
+ if (kw === "manual") {
33229
+ const lim = freezeLimits?.();
33230
+ if (lim && lim.length >= 4) {
33231
+ const instr = {
33232
+ type: "set_axis_limits",
33233
+ xlim: [lim[0], lim[1]],
33234
+ ylim: [lim[2], lim[3]]
33235
+ };
33236
+ if (lim.length >= 6) instr.zlim = [lim[4], lim[5]];
33237
+ instructions.push(instr);
33238
+ }
33239
+ continue;
33240
+ }
33241
+ if (kw in AUTO_AXIS_TOKENS) {
33242
+ instructions.push(clearLimits(AUTO_AXIS_TOKENS[kw]));
33243
+ continue;
33244
+ }
33245
+ if (kw === "xy" || kw === "ij") {
33246
+ instructions.push({
33247
+ type: "set_axis_ydir",
33248
+ dir: kw === "ij" ? "reverse" : "normal"
33249
+ });
33250
+ continue;
33251
+ }
33252
+ if (kw === "on" || kw === "off") {
33253
+ instructions.push({ type: "set_axis_visible", value: kw === "on" });
33254
+ continue;
33255
+ }
33256
+ throw new RuntimeError(`axis: unknown option '${kw}'`);
33257
+ }
33258
+ if (styles.length > 0) {
33259
+ instructions.push({ type: "set_axis", value: styles.join(" ") });
33260
+ }
33261
+ return applied;
33262
+ }
33263
+
33136
33264
  // src/numbl-core/runtime/plotBuiltinDispatch.ts
33137
33265
  function dispatchPlotBuiltin(name, args, instructions, state) {
33138
33266
  switch (name) {
@@ -33321,10 +33449,7 @@ function dispatchPlotBuiltin(name, args, instructions, state) {
33321
33449
  dispatchColormap(args, instructions);
33322
33450
  return true;
33323
33451
  case "axis": {
33324
- if (args.length > 0) {
33325
- const val = toString(args[0]).replace(/^"|"$/g, "");
33326
- plotInstr(instructions, { type: "set_axis", value: val });
33327
- }
33452
+ applyAxisCommand(args, instructions);
33328
33453
  return true;
33329
33454
  }
33330
33455
  case "caxis":
@@ -37007,6 +37132,85 @@ function quadgkAdaptive(integrand, a, b, opts = {}) {
37007
37132
  };
37008
37133
  }
37009
37134
 
37135
+ // src/numbl-core/helpers/eigs-select.ts
37136
+ var SIGMA_ALIASES = {
37137
+ lm: "largestabs",
37138
+ largestabs: "largestabs",
37139
+ sm: "smallestabs",
37140
+ smallestabs: "smallestabs",
37141
+ lr: "largestreal",
37142
+ la: "largestreal",
37143
+ largestreal: "largestreal",
37144
+ sr: "smallestreal",
37145
+ sa: "smallestreal",
37146
+ smallestreal: "smallestreal",
37147
+ be: "bothendsreal",
37148
+ bothendsreal: "bothendsreal",
37149
+ li: "largestimag",
37150
+ largestimag: "largestimag",
37151
+ si: "smallestimag",
37152
+ smallestimag: "smallestimag",
37153
+ bothendsimag: "bothendsimag"
37154
+ };
37155
+ function normalizeSigmaString(s) {
37156
+ return SIGMA_ALIASES[s.trim().toLowerCase()] ?? null;
37157
+ }
37158
+ var mag = (re, im) => Math.hypot(re, im);
37159
+ function sortedBy(n, key, descending) {
37160
+ const idx = Array.from({ length: n }, (_, i) => i);
37161
+ idx.sort((a, b) => {
37162
+ const ka = key(a);
37163
+ const kb = key(b);
37164
+ if (ka !== kb) return descending ? kb - ka : ka - kb;
37165
+ return a - b;
37166
+ });
37167
+ return idx;
37168
+ }
37169
+ function bothEnds(n, key, k) {
37170
+ const nHigh = Math.ceil(k / 2);
37171
+ const nLow = Math.floor(k / 2);
37172
+ const desc = sortedBy(n, key, true);
37173
+ const high = desc.slice(0, nHigh);
37174
+ const highSet = new Set(high);
37175
+ const low = [];
37176
+ for (let i = desc.length - 1; i >= 0 && low.length < nLow; i--) {
37177
+ if (!highSet.has(desc[i])) low.push(desc[i]);
37178
+ }
37179
+ return { high, low };
37180
+ }
37181
+ function selectEigsIndices(re, im, k, sigma) {
37182
+ const n = re.length;
37183
+ const kk = Math.max(0, Math.min(k, n));
37184
+ switch (sigma.kind) {
37185
+ case "largestabs":
37186
+ return sortedBy(n, (i) => mag(re[i], im[i]), true).slice(0, kk);
37187
+ case "smallestabs":
37188
+ return sortedBy(n, (i) => mag(re[i], im[i]), false).slice(0, kk);
37189
+ case "largestreal":
37190
+ return sortedBy(n, (i) => re[i], true).slice(0, kk);
37191
+ case "smallestreal":
37192
+ return sortedBy(n, (i) => re[i], false).slice(0, kk);
37193
+ case "largestimag":
37194
+ return sortedBy(n, (i) => im[i], true).slice(0, kk);
37195
+ case "smallestimag":
37196
+ return sortedBy(n, (i) => im[i], false).slice(0, kk);
37197
+ case "scalar": {
37198
+ const { re: sr, im: si } = sigma;
37199
+ return sortedBy(n, (i) => mag(re[i] - sr, im[i] - si), false).slice(0, kk);
37200
+ }
37201
+ case "bothendsreal": {
37202
+ const { high, low } = bothEnds(n, (i) => re[i], kk);
37203
+ return [...high, ...low].sort((a, b) => re[a] - re[b] || a - b);
37204
+ }
37205
+ case "bothendsimag": {
37206
+ const { high, low } = bothEnds(n, (i) => im[i], kk);
37207
+ return [...high, ...low].sort(
37208
+ (a, b) => Math.abs(im[b]) - Math.abs(im[a]) || a - b
37209
+ );
37210
+ }
37211
+ }
37212
+ }
37213
+
37010
37214
  // src/numbl-core/runtime/specialBuiltinNames.ts
37011
37215
  var SPECIAL_BUILTIN_NAMES = [
37012
37216
  "help",
@@ -37125,6 +37329,7 @@ var SPECIAL_BUILTIN_NAMES = [
37125
37329
  "toc",
37126
37330
  "quadgk",
37127
37331
  "gmres",
37332
+ "eigs",
37128
37333
  "onCleanup"
37129
37334
  ];
37130
37335
 
@@ -38502,6 +38707,9 @@ function registerSpecialBuiltins(rt) {
38502
38707
  registerSpecial("gmres", (nargout, args) => {
38503
38708
  return _gmresImpl(rt, nargout, args);
38504
38709
  });
38710
+ registerSpecial("eigs", (nargout, args) => {
38711
+ return _eigsImpl(rt, nargout, args);
38712
+ });
38505
38713
  registerSpecial("onCleanup", (_nargout, args) => {
38506
38714
  if (args.length !== 1 || !isRuntimeFunction(args[0]))
38507
38715
  throw new RuntimeError("onCleanup requires a function handle argument");
@@ -38509,6 +38717,271 @@ function registerSpecialBuiltins(rt) {
38509
38717
  return RTV.classInstance("onCleanup", [], false);
38510
38718
  });
38511
38719
  }
38720
+ function eigsReIm(v) {
38721
+ if (isRuntimeNumber(v)) return { re: [v], im: [0] };
38722
+ if (isRuntimeComplexNumber(v)) return { re: [v.re], im: [v.im] };
38723
+ if (isRuntimeTensor(v)) {
38724
+ const re = Array.from(v.data);
38725
+ const im = v.imag ? Array.from(v.imag) : re.map(() => 0);
38726
+ return { re, im };
38727
+ }
38728
+ throw new RuntimeError("eigs: expected a numeric value");
38729
+ }
38730
+ function eigsAsTensor(v) {
38731
+ const rv = ensureRuntimeValue(v);
38732
+ if (isRuntimeTensor(rv)) return rv;
38733
+ if (isRuntimeNumber(rv))
38734
+ return RTV.tensor(allocFloat64Array([rv]), [1, 1]);
38735
+ if (isRuntimeComplexNumber(rv))
38736
+ return RTV.tensor(
38737
+ allocFloat64Array([rv.re]),
38738
+ [1, 1],
38739
+ allocFloat64Array([rv.im])
38740
+ );
38741
+ throw new RuntimeError("eigs: expected a numeric matrix");
38742
+ }
38743
+ function eigsMatrixSize(A) {
38744
+ if (isRuntimeNumber(A) || isRuntimeComplexNumber(A)) return 1;
38745
+ if (isRuntimeTensor(A)) {
38746
+ const rows = A.shape[0] ?? 1;
38747
+ const cols = A.shape[1] ?? 1;
38748
+ if (rows !== cols)
38749
+ throw new RuntimeError("eigs: input matrix must be square");
38750
+ return rows;
38751
+ }
38752
+ throw new RuntimeError("eigs: input must be a numeric matrix");
38753
+ }
38754
+ function eigsIsScalar(v) {
38755
+ return isRuntimeNumber(v) || isRuntimeComplexNumber(v) || isRuntimeTensor(v) && v.data.length === 1;
38756
+ }
38757
+ function eigsIsMatrixArg(v) {
38758
+ if (!isRuntimeTensor(v)) return false;
38759
+ if (v.data.length === 0) return true;
38760
+ const rows = v.shape[0] ?? 1;
38761
+ const cols = v.shape[1] ?? 1;
38762
+ return rows > 1 || cols > 1;
38763
+ }
38764
+ function eigsToBool(v) {
38765
+ if (isRuntimeLogical(v)) return v;
38766
+ if (isRuntimeNumber(v)) return v !== 0;
38767
+ if (isRuntimeTensor(v) && v.data.length >= 1) return v.data[0] !== 0;
38768
+ return false;
38769
+ }
38770
+ function eigsParseSigma(v) {
38771
+ if (isRuntimeString(v) || isRuntimeChar(v)) {
38772
+ const s = typeof v === "string" ? v : v.value;
38773
+ const kind = normalizeSigmaString(s);
38774
+ if (!kind) throw new RuntimeError(`eigs: unknown sigma option '${s}'`);
38775
+ return { kind };
38776
+ }
38777
+ let re;
38778
+ let im = 0;
38779
+ if (isRuntimeComplexNumber(v)) {
38780
+ re = v.re;
38781
+ im = v.im;
38782
+ } else if (isRuntimeNumber(v)) {
38783
+ re = v;
38784
+ } else if (isRuntimeTensor(v) && v.data.length >= 1) {
38785
+ re = v.data[0];
38786
+ im = v.imag ? v.imag[0] : 0;
38787
+ } else {
38788
+ throw new RuntimeError("eigs: invalid sigma argument");
38789
+ }
38790
+ if (re === 0 && im === 0) return { kind: "smallestabs" };
38791
+ return { kind: "scalar", re, im };
38792
+ }
38793
+ function eigsReconstructOperator(rt, afun, n) {
38794
+ const re = allocFloat64Array(n * n);
38795
+ const im = allocFloat64Array(n * n);
38796
+ let anyImag = false;
38797
+ for (let j = 0; j < n; j++) {
38798
+ const e = allocFloat64Array(n);
38799
+ e[j] = 1;
38800
+ const col = ensureRuntimeValue(
38801
+ rt.index(afun, [RTV.tensor(e, [n, 1])], 1)
38802
+ );
38803
+ const { re: cre, im: cim } = eigsReIm(col);
38804
+ for (let i = 0; i < n; i++) {
38805
+ re[j * n + i] = cre[i] ?? 0;
38806
+ im[j * n + i] = cim[i] ?? 0;
38807
+ if (im[j * n + i] !== 0) anyImag = true;
38808
+ }
38809
+ }
38810
+ return anyImag ? RTV.tensor(re, [n, n], im) : RTV.tensor(re, [n, n]);
38811
+ }
38812
+ function eigsRecoverAfunMatrix(rt, M, sigma, B, n) {
38813
+ if (sigma.kind === "smallestabs") {
38814
+ return eigsAsTensor(rt.dispatch("inv", 1, [M]));
38815
+ }
38816
+ if (sigma.kind === "scalar") {
38817
+ const base = eigsAsTensor(rt.dispatch("inv", 1, [M]));
38818
+ const shiftRe = allocFloat64Array(n * n);
38819
+ const shiftIm = allocFloat64Array(n * n);
38820
+ if (B && isRuntimeTensor(B)) {
38821
+ for (let i = 0; i < n * n; i++) {
38822
+ shiftRe[i] = (B.data[i] ?? 0) * sigma.re - (B.imag?.[i] ?? 0) * sigma.im;
38823
+ shiftIm[i] = (B.data[i] ?? 0) * sigma.im + (B.imag?.[i] ?? 0) * sigma.re;
38824
+ }
38825
+ } else {
38826
+ for (let d = 0; d < n; d++) {
38827
+ shiftRe[d * n + d] = sigma.re;
38828
+ shiftIm[d * n + d] = sigma.im;
38829
+ }
38830
+ }
38831
+ const shift = maybeComplexTensor(shiftRe, [n, n], shiftIm);
38832
+ return eigsAsTensor(rt.dispatch("plus", 1, [base, shift]));
38833
+ }
38834
+ return M;
38835
+ }
38836
+ function eigsReconstructCholesky(R, perm, n) {
38837
+ if (!isRuntimeTensor(R))
38838
+ throw new RuntimeError("eigs: Cholesky factor must be a matrix");
38839
+ const r = R.data;
38840
+ const rtr = allocFloat64Array(n * n);
38841
+ for (let i = 0; i < n; i++) {
38842
+ for (let j = 0; j < n; j++) {
38843
+ let s = 0;
38844
+ for (let kk = 0; kk < n; kk++) s += r[i * n + kk] * r[j * n + kk];
38845
+ rtr[j * n + i] = s;
38846
+ }
38847
+ }
38848
+ if (!perm) return RTV.tensor(rtr, [n, n]);
38849
+ const b = allocFloat64Array(n * n);
38850
+ for (let i = 0; i < n; i++) {
38851
+ for (let j = 0; j < n; j++) {
38852
+ const pi2 = (perm[i] ?? i + 1) - 1;
38853
+ const pj = (perm[j] ?? j + 1) - 1;
38854
+ b[pj * n + pi2] = rtr[j * n + i];
38855
+ }
38856
+ }
38857
+ return RTV.tensor(b, [n, n]);
38858
+ }
38859
+ function _eigsImpl(rt, nargout, args) {
38860
+ const margs = args.map((a) => ensureRuntimeValue(a));
38861
+ if (margs.length < 1)
38862
+ throw new RuntimeError("eigs requires at least 1 argument");
38863
+ let afun = null;
38864
+ let A = null;
38865
+ let n;
38866
+ let pos;
38867
+ if (isRuntimeFunction(margs[0])) {
38868
+ afun = margs[0];
38869
+ if (margs.length < 2 || !eigsIsScalar(margs[1]))
38870
+ throw new RuntimeError(
38871
+ "eigs: a function handle must be followed by the matrix size n"
38872
+ );
38873
+ n = Math.floor(toNumber(margs[1]));
38874
+ pos = 2;
38875
+ } else {
38876
+ A = margs[0];
38877
+ n = eigsMatrixSize(A);
38878
+ pos = 1;
38879
+ }
38880
+ let B = null;
38881
+ if (pos < margs.length && eigsIsMatrixArg(margs[pos])) {
38882
+ const b = margs[pos];
38883
+ if (!(isRuntimeTensor(b) && b.data.length === 0)) B = b;
38884
+ pos++;
38885
+ }
38886
+ let kReq = null;
38887
+ if (pos < margs.length && eigsIsScalar(margs[pos])) {
38888
+ kReq = Math.max(1, Math.floor(toNumber(margs[pos])));
38889
+ pos++;
38890
+ }
38891
+ let sigma = { kind: "largestabs" };
38892
+ if (pos < margs.length) {
38893
+ const a = margs[pos];
38894
+ if (isRuntimeString(a) || isRuntimeChar(a)) {
38895
+ const s = typeof a === "string" ? a : a.value;
38896
+ if (normalizeSigmaString(s)) {
38897
+ sigma = eigsParseSigma(a);
38898
+ pos++;
38899
+ }
38900
+ } else if (eigsIsScalar(a)) {
38901
+ sigma = eigsParseSigma(a);
38902
+ pos++;
38903
+ }
38904
+ }
38905
+ let isCholesky = false;
38906
+ let cholPerm = null;
38907
+ const applyOption = (key, val) => {
38908
+ const lk = key.toLowerCase();
38909
+ if (lk === "ischolesky" || lk === "cholb") isCholesky = eigsToBool(val);
38910
+ else if (lk === "choleskypermutation" || lk === "permb") {
38911
+ if (isRuntimeTensor(val)) cholPerm = Array.from(val.data);
38912
+ }
38913
+ };
38914
+ while (pos < margs.length) {
38915
+ const a = margs[pos];
38916
+ if (isRuntimeStruct(a)) {
38917
+ for (const [key, val] of a.fields) applyOption(key, val);
38918
+ pos++;
38919
+ } else if (pos + 1 < margs.length) {
38920
+ applyOption(
38921
+ isRuntimeChar(margs[pos]) ? margs[pos].value : String(toString(margs[pos])),
38922
+ margs[pos + 1]
38923
+ );
38924
+ pos += 2;
38925
+ } else {
38926
+ break;
38927
+ }
38928
+ }
38929
+ const k = kReq == null ? Math.min(6, n) : Math.min(kReq, n);
38930
+ let actualA;
38931
+ if (afun) {
38932
+ const M = eigsReconstructOperator(rt, afun, n);
38933
+ actualA = eigsRecoverAfunMatrix(rt, M, sigma, B, n);
38934
+ } else {
38935
+ actualA = A;
38936
+ }
38937
+ let effective = actualA;
38938
+ if (B) {
38939
+ const Bmat = isCholesky ? eigsReconstructCholesky(B, cholPerm, n) : B;
38940
+ effective = eigsAsTensor(rt.dispatch("mldivide", 1, [Bmat, actualA]));
38941
+ }
38942
+ if (nargout <= 1) {
38943
+ const d = ensureRuntimeValue(rt.dispatch("eig", 1, [effective]));
38944
+ const { re: re2, im: im2 } = eigsReIm(d);
38945
+ const order2 = selectEigsIndices(re2, im2, k, sigma);
38946
+ const outRe = allocFloat64Array(order2.length);
38947
+ const outIm = allocFloat64Array(order2.length);
38948
+ for (let c = 0; c < order2.length; c++) {
38949
+ outRe[c] = re2[order2[c]];
38950
+ outIm[c] = im2[order2[c]];
38951
+ }
38952
+ return maybeComplexTensor(outRe, [order2.length, 1], outIm);
38953
+ }
38954
+ const res = rt.dispatch("eig", 2, [effective]);
38955
+ const Vall = eigsAsTensor(res[0]);
38956
+ const Dall = eigsAsTensor(res[1]);
38957
+ const p2 = Dall.shape[0] ?? 1;
38958
+ const vrows = Vall.shape[0] ?? p2;
38959
+ const re = [];
38960
+ const im = [];
38961
+ for (let j = 0; j < p2; j++) {
38962
+ re.push(Dall.data[j * p2 + j]);
38963
+ im.push(Dall.imag ? Dall.imag[j * p2 + j] : 0);
38964
+ }
38965
+ const order = selectEigsIndices(re, im, k, sigma);
38966
+ const kk = order.length;
38967
+ const Vre = allocFloat64Array(vrows * kk);
38968
+ const Vim = allocFloat64Array(vrows * kk);
38969
+ const Dre = allocFloat64Array(kk * kk);
38970
+ const Dim = allocFloat64Array(kk * kk);
38971
+ for (let c = 0; c < kk; c++) {
38972
+ const s = order[c];
38973
+ for (let r = 0; r < vrows; r++) {
38974
+ Vre[c * vrows + r] = Vall.data[s * vrows + r];
38975
+ if (Vall.imag) Vim[c * vrows + r] = Vall.imag[s * vrows + r];
38976
+ }
38977
+ Dre[c * kk + c] = re[s];
38978
+ Dim[c * kk + c] = im[s];
38979
+ }
38980
+ const V = maybeComplexTensor(Vre, [vrows, kk], Vim);
38981
+ const D = maybeComplexTensor(Dre, [kk, kk], Dim);
38982
+ if (nargout === 2) return [V, D];
38983
+ return [V, D, RTV.num(0)];
38984
+ }
38512
38985
  function _ode45Impl(rt, nargout, args, tableau = dormandPrince45) {
38513
38986
  const solverName = tableau.name;
38514
38987
  if (args.length < 3)
@@ -39444,6 +39917,484 @@ function memberChainAssign(rt, base, names, rhs) {
39444
39917
  return subsasgnFallback(rt, base, names, rhs);
39445
39918
  }
39446
39919
 
39920
+ // src/graphics/figuresReducer.ts
39921
+ var defaultAxes = {
39922
+ holdOn: false,
39923
+ traces: [],
39924
+ plot3Traces: [],
39925
+ surfTraces: [],
39926
+ pcolorTraces: [],
39927
+ contourTraces: [],
39928
+ barTraces: [],
39929
+ barhTraces: [],
39930
+ bar3Traces: [],
39931
+ bar3hTraces: [],
39932
+ errorBarTraces: [],
39933
+ boxTraces: [],
39934
+ quiverTraces: [],
39935
+ quiver3Traces: [],
39936
+ areaTraces: [],
39937
+ areaBaseValue: 0
39938
+ };
39939
+ function getAxes(fig) {
39940
+ return fig.axes[fig.currentAxesIndex] || { ...defaultAxes };
39941
+ }
39942
+ function setAxes(fig, axes) {
39943
+ return {
39944
+ ...fig,
39945
+ axes: { ...fig.axes, [fig.currentAxesIndex]: axes }
39946
+ };
39947
+ }
39948
+ var initialFiguresState = {
39949
+ currentHandle: 1,
39950
+ figs: {}
39951
+ };
39952
+ var defaultFigure = {
39953
+ currentAxesIndex: 1,
39954
+ axes: {}
39955
+ };
39956
+ function ensureFig(state) {
39957
+ return state.figs[state.currentHandle] || { ...defaultFigure };
39958
+ }
39959
+ function updateAxes(state, update) {
39960
+ const fig = ensureFig(state);
39961
+ const axes = getAxes(fig);
39962
+ return {
39963
+ ...state,
39964
+ figs: {
39965
+ ...state.figs,
39966
+ [state.currentHandle]: setAxes(fig, { ...axes, ...update })
39967
+ }
39968
+ };
39969
+ }
39970
+ function addTraces(state, update) {
39971
+ const fig = ensureFig(state);
39972
+ const axes = getAxes(fig);
39973
+ const hold = axes.holdOn;
39974
+ return {
39975
+ ...state,
39976
+ figs: {
39977
+ ...state.figs,
39978
+ [state.currentHandle]: setAxes(fig, {
39979
+ ...axes,
39980
+ traces: update.traces ?? (hold ? axes.traces : []),
39981
+ plot3Traces: update.plot3Traces ?? (hold ? axes.plot3Traces : []),
39982
+ surfTraces: update.surfTraces ?? (hold ? axes.surfTraces : []),
39983
+ pcolorTraces: update.pcolorTraces ?? (hold ? axes.pcolorTraces : []),
39984
+ contourTraces: update.contourTraces ?? (hold ? axes.contourTraces : []),
39985
+ barTraces: update.barTraces ?? (hold ? axes.barTraces : []),
39986
+ barhTraces: update.barhTraces ?? (hold ? axes.barhTraces : []),
39987
+ bar3Traces: update.bar3Traces ?? (hold ? axes.bar3Traces : []),
39988
+ bar3hTraces: update.bar3hTraces ?? (hold ? axes.bar3hTraces : []),
39989
+ errorBarTraces: update.errorBarTraces ?? (hold ? axes.errorBarTraces : []),
39990
+ boxTraces: update.boxTraces ?? (hold ? axes.boxTraces : []),
39991
+ pieTrace: update.pieTrace ?? (hold ? axes.pieTrace : void 0),
39992
+ heatmapTrace: update.heatmapTrace ?? (hold ? axes.heatmapTrace : void 0),
39993
+ quiverTraces: update.quiverTraces ?? (hold ? axes.quiverTraces : []),
39994
+ quiver3Traces: update.quiver3Traces ?? (hold ? axes.quiver3Traces : []),
39995
+ areaTraces: update.areaTraces ?? (hold ? axes.areaTraces : []),
39996
+ areaBaseValue: update.areaBaseValue ?? axes.areaBaseValue,
39997
+ ...update.imagescTrace !== void 0 ? { imagescTrace: update.imagescTrace } : {}
39998
+ })
39999
+ }
40000
+ };
40001
+ }
40002
+ var figuresReducer = (state, action) => {
40003
+ switch (action.type) {
40004
+ case "set_figure_handle":
40005
+ return { ...state, currentHandle: action.handle };
40006
+ case "set_hold":
40007
+ return updateAxes(state, { holdOn: action.value });
40008
+ case "plot": {
40009
+ const axes = getAxes(ensureFig(state));
40010
+ return addTraces(state, {
40011
+ traces: axes.holdOn ? [...axes.traces, ...action.traces] : [...action.traces]
40012
+ });
40013
+ }
40014
+ case "plot3": {
40015
+ const axes = getAxes(ensureFig(state));
40016
+ return addTraces(state, {
40017
+ plot3Traces: axes.holdOn ? [...axes.plot3Traces, ...action.traces] : [...action.traces]
40018
+ });
40019
+ }
40020
+ case "surf": {
40021
+ const axes = getAxes(ensureFig(state));
40022
+ return addTraces(state, {
40023
+ surfTraces: axes.holdOn ? [...axes.surfTraces, action.trace] : [action.trace]
40024
+ });
40025
+ }
40026
+ case "surface": {
40027
+ const axes = getAxes(ensureFig(state));
40028
+ return updateAxes(state, {
40029
+ surfTraces: [...axes.surfTraces, action.trace]
40030
+ });
40031
+ }
40032
+ case "imagesc":
40033
+ return addTraces(state, { imagescTrace: action.trace });
40034
+ case "pcolor": {
40035
+ const axes = getAxes(ensureFig(state));
40036
+ return addTraces(state, {
40037
+ pcolorTraces: axes.holdOn ? [...axes.pcolorTraces, action.trace] : [action.trace]
40038
+ });
40039
+ }
40040
+ case "contour": {
40041
+ const axes = getAxes(ensureFig(state));
40042
+ return addTraces(state, {
40043
+ contourTraces: axes.holdOn ? [...axes.contourTraces, action.trace] : [action.trace]
40044
+ });
40045
+ }
40046
+ case "mesh": {
40047
+ const axes = getAxes(ensureFig(state));
40048
+ return addTraces(state, {
40049
+ surfTraces: axes.holdOn ? [...axes.surfTraces, action.trace] : [action.trace]
40050
+ });
40051
+ }
40052
+ case "bar": {
40053
+ const axes = getAxes(ensureFig(state));
40054
+ return addTraces(state, {
40055
+ barTraces: axes.holdOn ? [...axes.barTraces, ...action.traces] : [...action.traces]
40056
+ });
40057
+ }
40058
+ case "barh": {
40059
+ const axes = getAxes(ensureFig(state));
40060
+ return addTraces(state, {
40061
+ barhTraces: axes.holdOn ? [...axes.barhTraces, ...action.traces] : [...action.traces]
40062
+ });
40063
+ }
40064
+ case "bar3": {
40065
+ const axes = getAxes(ensureFig(state));
40066
+ return addTraces(state, {
40067
+ bar3Traces: axes.holdOn ? [...axes.bar3Traces, action.trace] : [action.trace]
40068
+ });
40069
+ }
40070
+ case "bar3h": {
40071
+ const axes = getAxes(ensureFig(state));
40072
+ return addTraces(state, {
40073
+ bar3hTraces: axes.holdOn ? [...axes.bar3hTraces, action.trace] : [action.trace]
40074
+ });
40075
+ }
40076
+ case "errorbar": {
40077
+ const axes = getAxes(ensureFig(state));
40078
+ return addTraces(state, {
40079
+ errorBarTraces: axes.holdOn ? [...axes.errorBarTraces, ...action.traces] : [...action.traces]
40080
+ });
40081
+ }
40082
+ case "boxchart": {
40083
+ const axes = getAxes(ensureFig(state));
40084
+ return addTraces(state, {
40085
+ boxTraces: axes.holdOn ? [...axes.boxTraces, ...action.traces] : [...action.traces]
40086
+ });
40087
+ }
40088
+ case "piechart":
40089
+ return addTraces(state, { pieTrace: action.trace });
40090
+ case "heatmap":
40091
+ return addTraces(state, { heatmapTrace: action.trace });
40092
+ case "quiver": {
40093
+ const axes = getAxes(ensureFig(state));
40094
+ return addTraces(state, {
40095
+ quiverTraces: axes.holdOn ? [...axes.quiverTraces, ...action.traces] : [...action.traces]
40096
+ });
40097
+ }
40098
+ case "quiver3": {
40099
+ const axes = getAxes(ensureFig(state));
40100
+ return addTraces(state, {
40101
+ quiver3Traces: axes.holdOn ? [...axes.quiver3Traces, action.trace] : [action.trace]
40102
+ });
40103
+ }
40104
+ case "area": {
40105
+ const axes = getAxes(ensureFig(state));
40106
+ return addTraces(state, {
40107
+ areaTraces: axes.holdOn ? [...axes.areaTraces, ...action.traces] : [...action.traces],
40108
+ areaBaseValue: action.baseValue
40109
+ });
40110
+ }
40111
+ case "close": {
40112
+ const remainingFigs = Object.fromEntries(
40113
+ Object.entries(state.figs).filter(
40114
+ ([k]) => Number(k) !== state.currentHandle
40115
+ )
40116
+ );
40117
+ const handles = Object.keys(remainingFigs).map(Number).sort((a, b) => a - b);
40118
+ return {
40119
+ ...state,
40120
+ currentHandle: handles.length > 0 ? handles[handles.length - 1] : 1,
40121
+ figs: remainingFigs
40122
+ };
40123
+ }
40124
+ case "close_all":
40125
+ case "clear":
40126
+ return initialFiguresState;
40127
+ case "set_title":
40128
+ return updateAxes(state, { title: action.text });
40129
+ case "set_xlabel":
40130
+ return updateAxes(state, { xlabel: action.text });
40131
+ case "set_ylabel":
40132
+ return updateAxes(state, { ylabel: action.text });
40133
+ case "set_zlabel":
40134
+ return updateAxes(state, { zlabel: action.text });
40135
+ case "set_shading":
40136
+ return updateAxes(state, { shading: action.shading });
40137
+ case "set_legend":
40138
+ return updateAxes(state, { legend: action.labels });
40139
+ case "set_sgtitle": {
40140
+ const fig = ensureFig(state);
40141
+ return {
40142
+ ...state,
40143
+ figs: {
40144
+ ...state.figs,
40145
+ [state.currentHandle]: { ...fig, sgtitle: action.text }
40146
+ }
40147
+ };
40148
+ }
40149
+ case "set_grid":
40150
+ return updateAxes(state, { gridOn: action.value });
40151
+ case "set_colorbar":
40152
+ return updateAxes(state, {
40153
+ colorbar: action.value !== "off",
40154
+ colorbarLocation: action.location ?? "eastoutside"
40155
+ });
40156
+ case "set_colormap":
40157
+ return updateAxes(state, {
40158
+ colormap: action.name,
40159
+ colormapData: action.data
40160
+ });
40161
+ case "set_view":
40162
+ return updateAxes(state, { view: { az: action.az, el: action.el } });
40163
+ case "set_axis":
40164
+ return updateAxes(state, { axisMode: action.value });
40165
+ case "set_axis_limits": {
40166
+ const axes = getAxes(ensureFig(state));
40167
+ const resolve3 = (prev, spec) => {
40168
+ if (spec === void 0) return prev;
40169
+ if (spec === "auto") return void 0;
40170
+ return spec;
40171
+ };
40172
+ return updateAxes(state, {
40173
+ xlim: resolve3(axes.xlim, action.xlim),
40174
+ ylim: resolve3(axes.ylim, action.ylim),
40175
+ zlim: resolve3(axes.zlim, action.zlim)
40176
+ });
40177
+ }
40178
+ case "set_axis_ydir":
40179
+ return updateAxes(state, { yDir: action.dir });
40180
+ case "set_axis_visible":
40181
+ return updateAxes(state, { axisVisible: action.value });
40182
+ case "set_axis_scale":
40183
+ return updateAxes(state, { axisScale: action.value });
40184
+ case "set_caxis":
40185
+ return updateAxes(state, { caxis: action.limits });
40186
+ case "clf": {
40187
+ const fig = state.figs[state.currentHandle];
40188
+ if (!fig) return state;
40189
+ return {
40190
+ ...state,
40191
+ figs: {
40192
+ ...state.figs,
40193
+ [state.currentHandle]: { ...defaultFigure }
40194
+ }
40195
+ };
40196
+ }
40197
+ case "cla": {
40198
+ const fig = ensureFig(state);
40199
+ const prev = getAxes(fig);
40200
+ const cleared = action.reset ? { ...defaultAxes } : {
40201
+ ...defaultAxes,
40202
+ title: prev.title,
40203
+ xlabel: prev.xlabel,
40204
+ ylabel: prev.ylabel,
40205
+ zlabel: prev.zlabel,
40206
+ gridOn: prev.gridOn,
40207
+ colorbar: prev.colorbar,
40208
+ colorbarLocation: prev.colorbarLocation,
40209
+ colormap: prev.colormap,
40210
+ colormapData: prev.colormapData,
40211
+ view: prev.view,
40212
+ axisMode: prev.axisMode,
40213
+ axisScale: prev.axisScale,
40214
+ caxis: prev.caxis,
40215
+ xlim: prev.xlim,
40216
+ ylim: prev.ylim,
40217
+ zlim: prev.zlim,
40218
+ yDir: prev.yDir,
40219
+ axisVisible: prev.axisVisible,
40220
+ shading: prev.shading
40221
+ };
40222
+ return {
40223
+ ...state,
40224
+ figs: {
40225
+ ...state.figs,
40226
+ [state.currentHandle]: setAxes(fig, cleared)
40227
+ }
40228
+ };
40229
+ }
40230
+ case "set_subplot": {
40231
+ const fig = ensureFig(state);
40232
+ const newFig = {
40233
+ ...fig,
40234
+ subplotGrid: { rows: action.rows, cols: action.cols },
40235
+ currentAxesIndex: action.index
40236
+ };
40237
+ if (!newFig.axes[action.index]) {
40238
+ newFig.axes = { ...newFig.axes, [action.index]: { ...defaultAxes } };
40239
+ }
40240
+ return {
40241
+ ...state,
40242
+ figs: { ...state.figs, [state.currentHandle]: newFig }
40243
+ };
40244
+ }
40245
+ default:
40246
+ return state;
40247
+ }
40248
+ };
40249
+
40250
+ // src/graphics/axisLimits.ts
40251
+ var EMPTY = { min: Infinity, max: -Infinity };
40252
+ function include(e, v) {
40253
+ if (Number.isFinite(v)) {
40254
+ if (v < e.min) e.min = v;
40255
+ if (v > e.max) e.max = v;
40256
+ }
40257
+ }
40258
+ function includeAll(e, vs) {
40259
+ if (!vs) return;
40260
+ for (let i = 0; i < vs.length; i++) include(e, vs[i]);
40261
+ }
40262
+ function axesIs3D(axes) {
40263
+ return (axes.surfTraces?.length ?? 0) > 0 || (axes.plot3Traces?.length ?? 0) > 0 || (axes.bar3Traces?.length ?? 0) > 0 || (axes.bar3hTraces?.length ?? 0) > 0 || (axes.quiver3Traces?.length ?? 0) > 0;
40264
+ }
40265
+ function dataExtents(axes) {
40266
+ const x = { ...EMPTY };
40267
+ const y = { ...EMPTY };
40268
+ const z = { ...EMPTY };
40269
+ for (const t of axes.traces ?? []) {
40270
+ includeAll(x, t.x);
40271
+ includeAll(y, t.y);
40272
+ }
40273
+ for (const t of axes.plot3Traces ?? []) {
40274
+ includeAll(x, t.x);
40275
+ includeAll(y, t.y);
40276
+ includeAll(z, t.z);
40277
+ }
40278
+ for (const t of [...axes.surfTraces ?? []]) {
40279
+ includeAll(x, t.x);
40280
+ includeAll(y, t.y);
40281
+ includeAll(z, t.z);
40282
+ }
40283
+ if (axes.imagescTrace) {
40284
+ include(x, axes.imagescTrace.x[0]);
40285
+ include(x, axes.imagescTrace.x[1]);
40286
+ include(y, axes.imagescTrace.y[0]);
40287
+ include(y, axes.imagescTrace.y[1]);
40288
+ }
40289
+ for (const t of axes.pcolorTraces ?? []) {
40290
+ includeAll(x, t.x);
40291
+ includeAll(y, t.y);
40292
+ }
40293
+ for (const t of axes.contourTraces ?? []) {
40294
+ includeAll(x, t.x);
40295
+ includeAll(y, t.y);
40296
+ }
40297
+ for (const bt of axes.barTraces ?? []) {
40298
+ const hw = bt.width / 2;
40299
+ for (let i = 0; i < bt.x.length; i++) {
40300
+ include(x, bt.x[i] - hw);
40301
+ include(x, bt.x[i] + hw);
40302
+ include(y, bt.y[i]);
40303
+ }
40304
+ include(y, 0);
40305
+ }
40306
+ for (const bt of axes.barhTraces ?? []) {
40307
+ const hh = bt.width / 2;
40308
+ for (let i = 0; i < bt.x.length; i++) {
40309
+ include(y, bt.x[i] - hh);
40310
+ include(y, bt.x[i] + hh);
40311
+ include(x, bt.y[i]);
40312
+ }
40313
+ include(x, 0);
40314
+ }
40315
+ for (const bt of [...axes.bar3Traces ?? [], ...axes.bar3hTraces ?? []]) {
40316
+ includeAll(x, bt.x);
40317
+ includeAll(y, bt.y);
40318
+ includeAll(z, bt.z);
40319
+ include(z, 0);
40320
+ }
40321
+ for (const et of axes.errorBarTraces ?? []) {
40322
+ for (let i = 0; i < et.x.length; i++) {
40323
+ include(x, et.xNeg ? et.x[i] - et.xNeg[i] : et.x[i]);
40324
+ include(x, et.xPos ? et.x[i] + et.xPos[i] : et.x[i]);
40325
+ include(y, et.y[i] - et.yNeg[i]);
40326
+ include(y, et.y[i] + et.yPos[i]);
40327
+ }
40328
+ }
40329
+ for (const bt of axes.boxTraces ?? []) {
40330
+ const hw = bt.width / 2;
40331
+ include(x, bt.x - hw);
40332
+ include(x, bt.x + hw);
40333
+ include(y, bt.whiskerLow);
40334
+ include(y, bt.whiskerHigh);
40335
+ for (const o of bt.outliers) include(y, o);
40336
+ }
40337
+ if (axes.areaTraces && axes.areaTraces.length > 0) {
40338
+ const base = axes.areaBaseValue ?? 0;
40339
+ include(y, base);
40340
+ const n = axes.areaTraces[0].x.length;
40341
+ for (let i = 0; i < n; i++) {
40342
+ let cum = base;
40343
+ for (const t of axes.areaTraces) {
40344
+ if (i < t.x.length) {
40345
+ include(x, t.x[i]);
40346
+ cum += t.y[i] - base;
40347
+ include(y, cum);
40348
+ }
40349
+ }
40350
+ }
40351
+ }
40352
+ for (const qt of axes.quiverTraces ?? []) {
40353
+ for (let i = 0; i < qt.x.length; i++) {
40354
+ include(x, qt.x[i]);
40355
+ include(x, qt.x[i] + qt.u[i]);
40356
+ include(y, qt.y[i]);
40357
+ include(y, qt.y[i] + qt.v[i]);
40358
+ }
40359
+ }
40360
+ for (const qt of axes.quiver3Traces ?? []) {
40361
+ for (let i = 0; i < qt.x.length; i++) {
40362
+ include(x, qt.x[i]);
40363
+ include(x, qt.x[i] + qt.u[i]);
40364
+ include(y, qt.y[i]);
40365
+ include(y, qt.y[i] + qt.v[i]);
40366
+ include(z, qt.z[i]);
40367
+ include(z, qt.z[i] + qt.w[i]);
40368
+ }
40369
+ }
40370
+ return { x, y, z };
40371
+ }
40372
+ function padExtent(e, tight) {
40373
+ if (!Number.isFinite(e.min) || !Number.isFinite(e.max)) return [0, 1];
40374
+ let { min: min2, max: max2 } = e;
40375
+ if (max2 === min2) {
40376
+ min2 -= 1;
40377
+ max2 += 1;
40378
+ return [min2, max2];
40379
+ }
40380
+ if (tight) return [min2, max2];
40381
+ const pad = (max2 - min2) * 0.05;
40382
+ return [min2 - pad, max2 + pad];
40383
+ }
40384
+ function applyExplicit(auto, explicit) {
40385
+ if (!explicit) return auto;
40386
+ return [explicit[0] ?? auto[0], explicit[1] ?? auto[1]];
40387
+ }
40388
+ function computeAxisLimits(axes) {
40389
+ const tight = axes.axisMode?.includes("tight") || axes.axisMode?.includes("image") ? true : false;
40390
+ const ext = dataExtents(axes);
40391
+ const xl = applyExplicit(padExtent(ext.x, tight), axes.xlim);
40392
+ const yl = applyExplicit(padExtent(ext.y, tight), axes.ylim);
40393
+ if (!axesIs3D(axes)) return [xl[0], xl[1], yl[0], yl[1]];
40394
+ const zl = applyExplicit(padExtent(ext.z, tight), axes.zlim);
40395
+ return [xl[0], xl[1], yl[0], yl[1], zl[0], zl[1]];
40396
+ }
40397
+
39447
40398
  // src/numbl-core/runtime/runtime.ts
39448
40399
  var Runtime = class _Runtime {
39449
40400
  constructor(options, initialVariableValues) {
@@ -39665,6 +40616,18 @@ var Runtime = class _Runtime {
39665
40616
  }
39666
40617
  return RTV.dummyHandle();
39667
40618
  };
40619
+ this.builtins["axis"] = (nargout, args) => {
40620
+ const margs = args.map((a) => ensureRuntimeValue(a));
40621
+ const applied = applyAxisCommand(
40622
+ margs,
40623
+ this.plotInstructions,
40624
+ () => this.currentAxisLimits()
40625
+ );
40626
+ if (!applied && nargout >= 1) {
40627
+ return RTV.row(this.currentAxisLimits());
40628
+ }
40629
+ return void 0;
40630
+ };
39668
40631
  this.builtins["fplot"] = (_nargout, args) => {
39669
40632
  fplotCall(this, this.plotInstructions, args.map(ensureRuntimeValue));
39670
40633
  };
@@ -40568,6 +41531,21 @@ var Runtime = class _Runtime {
40568
41531
  ishold() {
40569
41532
  return RTV.logical(this.holdState);
40570
41533
  }
41534
+ /** Current axis limits of the active axes, as MATLAB's `axis` query
41535
+ * returns them: `[xmin xmax ymin ymax]` (2-D) or with `zmin zmax`
41536
+ * appended (3-D). Reduces the accumulated plot instructions into a figure
41537
+ * state and reads the current axes' explicit/data-derived limits. */
41538
+ currentAxisLimits() {
41539
+ let state = initialFiguresState;
41540
+ for (const instr of this.plotInstructions) {
41541
+ state = figuresReducer(state, instr);
41542
+ }
41543
+ const fig = state.figs[state.currentHandle];
41544
+ if (!fig) return [0, 1, 0, 1];
41545
+ const axes = fig.axes[fig.currentAxesIndex];
41546
+ if (!axes) return [0, 1, 0, 1];
41547
+ return computeAxisLimits(axes);
41548
+ }
40571
41549
  // ── Drawnow / Pause ─────────────────────────────────────────────────
40572
41550
  drawnow() {
40573
41551
  return drawnow(this.plotInstructions, this.options);
@@ -44981,10 +45959,10 @@ function sortTensor(v, dim, descend, nargout) {
44981
45959
  const dimSize = shape[dimIdx];
44982
45960
  let cmpFlatIdx;
44983
45961
  if (im && !im.every((x) => x === 0)) {
44984
- const mag = (i) => Math.sqrt(re[i] * re[i] + im[i] * im[i]);
45962
+ const mag2 = (i) => Math.sqrt(re[i] * re[i] + im[i] * im[i]);
44985
45963
  const phase = (i) => Math.atan2(im[i], re[i]);
44986
45964
  cmpFlatIdx = (a, b) => {
44987
- const diff2 = mag(a) - mag(b);
45965
+ const diff2 = mag2(a) - mag2(b);
44988
45966
  if (diff2 !== 0) return descend ? -diff2 : diff2;
44989
45967
  const pDiff = phase(a) - phase(b);
44990
45968
  return descend ? -pDiff : pDiff;
@@ -46412,9 +47390,9 @@ function invComplexJS(dataRe, dataIm, n) {
46412
47390
  let maxRow = col;
46413
47391
  let maxMag = augRe[col * 2 * n + col] ** 2 + augIm[col * 2 * n + col] ** 2;
46414
47392
  for (let row = col + 1; row < n; row++) {
46415
- const mag = augRe[row * 2 * n + col] ** 2 + augIm[row * 2 * n + col] ** 2;
46416
- if (mag > maxMag) {
46417
- maxMag = mag;
47393
+ const mag2 = augRe[row * 2 * n + col] ** 2 + augIm[row * 2 * n + col] ** 2;
47394
+ if (mag2 > maxMag) {
47395
+ maxMag = mag2;
46418
47396
  maxRow = row;
46419
47397
  }
46420
47398
  }
@@ -46459,6 +47437,88 @@ function invComplexJS(dataRe, dataIm, n) {
46459
47437
  }
46460
47438
  return { re: resultRe, im: resultIm };
46461
47439
  }
47440
+ defineBuiltin({
47441
+ name: "expm",
47442
+ cases: [
47443
+ {
47444
+ match: (argTypes, nargout) => {
47445
+ if (argTypes.length !== 1 || nargout > 1) return null;
47446
+ if (!isNumericJitType(argTypes[0])) return null;
47447
+ const a = argTypes[0];
47448
+ if (a.kind === "number" || a.kind === "boolean") return [NUM];
47449
+ if (a.kind === "complex_or_number") return [COMPLEX_OR_NUM];
47450
+ if (a.kind === "tensor")
47451
+ return [{ kind: "tensor", isComplex: a.isComplex }];
47452
+ return null;
47453
+ },
47454
+ apply: (args) => expmApply(args)
47455
+ }
47456
+ ]
47457
+ });
47458
+ function expmApply(args) {
47459
+ if (args.length !== 1) throw new RuntimeError("expm requires 1 argument");
47460
+ const A = args[0];
47461
+ if (isRuntimeNumber(A)) return RTV.num(Math.exp(A));
47462
+ if (isRuntimeComplexNumber(A)) {
47463
+ const ex = Math.exp(A.re);
47464
+ return RTV.complex(ex * Math.cos(A.im), ex * Math.sin(A.im));
47465
+ }
47466
+ if (!isRuntimeTensor(A))
47467
+ throw new RuntimeError("expm: argument must be a numeric matrix");
47468
+ const [m, n] = tensorSize2D(A);
47469
+ if (m !== n) throw new RuntimeError("expm: input must be a square matrix");
47470
+ if (n === 0) return A;
47471
+ if (n === 1) {
47472
+ const ex = Math.exp(A.data[0]);
47473
+ if (A.imag)
47474
+ return RTV.tensor(
47475
+ Float64Array.of(ex * Math.cos(A.imag[0])),
47476
+ [1, 1],
47477
+ Float64Array.of(ex * Math.sin(A.imag[0]))
47478
+ );
47479
+ return RTV.tensor(Float64Array.of(ex), [1, 1]);
47480
+ }
47481
+ let s = 0;
47482
+ for (let scaled = matrixOneNorm(A, n); scaled > 0.5; scaled /= 2) s++;
47483
+ const As = mMul(A, RTV.num(Math.pow(2, -s)));
47484
+ const q = 6;
47485
+ const I = identityTensor(n);
47486
+ let c = 0.5;
47487
+ let E = mAdd(I, mMul(As, RTV.num(c)));
47488
+ let D = mSub(I, mMul(As, RTV.num(c)));
47489
+ let X = As;
47490
+ let plus2 = true;
47491
+ for (let k = 2; k <= q; k++) {
47492
+ c = c * (q - k + 1) / (k * (2 * q - k + 1));
47493
+ X = mMul(As, X);
47494
+ const cX = mMul(X, RTV.num(c));
47495
+ E = mAdd(E, cX);
47496
+ D = plus2 ? mAdd(D, cX) : mSub(D, cX);
47497
+ plus2 = !plus2;
47498
+ }
47499
+ let R = mLeftDiv(D, E);
47500
+ for (let i = 0; i < s; i++) R = mMul(R, R);
47501
+ return R;
47502
+ }
47503
+ function matrixOneNorm(A, n) {
47504
+ const re = A.data;
47505
+ const im = A.imag;
47506
+ let maxSum = 0;
47507
+ for (let j = 0; j < n; j++) {
47508
+ let colSum = 0;
47509
+ for (let i = 0; i < n; i++) {
47510
+ const idx = i + j * n;
47511
+ colSum += im ? Math.hypot(re[idx], im[idx]) : Math.abs(re[idx]);
47512
+ }
47513
+ if (colSum > maxSum) maxSum = colSum;
47514
+ }
47515
+ return maxSum;
47516
+ }
47517
+ function identityTensor(n) {
47518
+ const data = allocFloat64Array(n * n);
47519
+ for (let i = 0; i < n; i++) data[i + i * n] = 1;
47520
+ return RTV.tensor(data, [n, n]);
47521
+ }
46462
47522
  registerIBuiltin({
46463
47523
  name: "svd",
46464
47524
  resolve: (argTypes, nargout) => {
@@ -47985,8 +49045,8 @@ function isFiberConjugateSymmetric(re, im) {
47985
49045
  if (N <= 1) return Math.abs(im[0]) < 1e-14;
47986
49046
  let maxMag = 0;
47987
49047
  for (let i = 0; i < N; i++) {
47988
- const mag = Math.abs(re[i]) + Math.abs(im[i]);
47989
- if (mag > maxMag) maxMag = mag;
49048
+ const mag2 = Math.abs(re[i]) + Math.abs(im[i]);
49049
+ if (mag2 > maxMag) maxMag = mag2;
47990
49050
  }
47991
49051
  const tol = Math.max(1e-14, maxMag * 1e-12);
47992
49052
  if (Math.abs(im[0]) > tol) return false;
@@ -54986,6 +56046,10 @@ var H = {
54986
56046
  signatures: ["B = inv(A)"],
54987
56047
  description: "Matrix inverse."
54988
56048
  },
56049
+ expm: {
56050
+ signatures: ["Y = expm(X)"],
56051
+ description: "Matrix exponential of square matrix X (scaling-and-squaring Pad\xE9). Use exp for the element-wise exponential."
56052
+ },
54989
56053
  trace: {
54990
56054
  signatures: ["T = trace(A)"],
54991
56055
  description: "Sum of diagonal elements."
@@ -54994,6 +56058,17 @@ var H = {
54994
56058
  signatures: ["E = eig(A)", "[V, D] = eig(A)", "[V, D, W] = eig(A)"],
54995
56059
  description: "Eigenvalues and eigenvectors of square matrix. With three outputs, W contains left eigenvectors."
54996
56060
  },
56061
+ eigs: {
56062
+ signatures: [
56063
+ "d = eigs(A)",
56064
+ "d = eigs(A, k)",
56065
+ "d = eigs(A, k, sigma)",
56066
+ "d = eigs(A, B, ...)",
56067
+ "d = eigs(Afun, n, ...)",
56068
+ "[V, D, flag] = eigs(...)"
56069
+ ],
56070
+ description: "Subset of k eigenvalues/eigenvectors (default 6). sigma selects which: 'largestabs' (default), 'smallestabs', 'largestreal', 'smallestreal', 'bothendsreal', 'largestimag', 'smallestimag', 'bothendsimag', or a scalar (eigenvalues closest to it). Supports the generalized problem A*V = B*V*D and a function handle Afun. Computed densely via eig, so convergence options are accepted but ignored and flag is always 0."
56071
+ },
54997
56072
  svd: {
54998
56073
  signatures: [
54999
56074
  "S = svd(A)",
@@ -55795,6 +56870,17 @@ var H = {
55795
56870
  signatures: ["colorbar", "colorbar(MODE)"],
55796
56871
  description: "Display colorbar on current axes."
55797
56872
  },
56873
+ axis: {
56874
+ signatures: [
56875
+ "axis([xmin xmax ymin ymax])",
56876
+ "axis STYLE",
56877
+ "axis MODE",
56878
+ "axis ij | xy",
56879
+ "axis on | off",
56880
+ "LIM = axis"
56881
+ ],
56882
+ description: "Set or query axis limits, scaling, direction, and visibility. LIMITS is a 4-, 6-, or 8-element vector (inf bounds stay automatic). STYLE is tight | padded | fill | equal | image | square | vis3d | normal | tickaligned. MODE is manual | auto | 'auto x' | 'auto y' | 'auto z' (and xy combinations). 'ij' reverses the y-axis; 'off' hides the axes lines and background. LIM = axis returns the current limits."
56883
+ },
55798
56884
  xlim: {
55799
56885
  signatures: ["xlim(LIMITS)"],
55800
56886
  description: "Set x-axis limits."
@@ -56364,7 +57450,7 @@ function getSourceLine(getSource, file, line) {
56364
57450
  }
56365
57451
 
56366
57452
  // src/numbl-core/version.ts
56367
- var NUMBL_VERSION = "0.4.2";
57453
+ var NUMBL_VERSION = "0.4.3";
56368
57454
 
56369
57455
  // src/cli-repl.ts
56370
57456
  import { createInterface } from "readline";
@@ -60002,11 +61088,11 @@ function instantiateClass(className, args, nargout) {
60002
61088
  } catch {
60003
61089
  }
60004
61090
  }
60005
- const isHandle2 = this.isHandleClass(classInfo);
61091
+ const isHandle3 = this.isHandleClass(classInfo);
60006
61092
  const instance = RTV.classInstance(
60007
61093
  className,
60008
61094
  propertyNames,
60009
- isHandle2,
61095
+ isHandle3,
60010
61096
  defaults
60011
61097
  );
60012
61098
  if (classInfo.constructorName) {
@@ -62058,7 +63144,7 @@ function isNumeric2(t) {
62058
63144
  function isVoid(t) {
62059
63145
  return t.kind === "Void";
62060
63146
  }
62061
- function isHandle(t) {
63147
+ function isHandle2(t) {
62062
63148
  return t.kind === "Handle";
62063
63149
  }
62064
63150
  function isStruct(t) {
@@ -65525,17 +66611,17 @@ function complex_sort_indices(a, descending) {
65525
66611
  });
65526
66612
  return idx;
65527
66613
  }
65528
- const mag = new Float64Array(n);
66614
+ const mag2 = new Float64Array(n);
65529
66615
  const ph = new Float64Array(n);
65530
66616
  for (let i = 0; i < n; i++) {
65531
66617
  const re = a.data[i];
65532
66618
  const xi = im !== void 0 ? im[i] : 0;
65533
- mag[i] = Math.hypot(re, xi);
66619
+ mag2[i] = Math.hypot(re, xi);
65534
66620
  ph[i] = Math.atan2(xi, re);
65535
66621
  }
65536
66622
  idx.sort((p2, q) => {
65537
- if (mag[p2] < mag[q]) return descending ? 1 : -1;
65538
- if (mag[p2] > mag[q]) return descending ? -1 : 1;
66623
+ if (mag2[p2] < mag2[q]) return descending ? 1 : -1;
66624
+ if (mag2[p2] > mag2[q]) return descending ? -1 : 1;
65539
66625
  if (ph[p2] < ph[q]) return descending ? 1 : -1;
65540
66626
  if (ph[p2] > ph[q]) return descending ? -1 : 1;
65541
66627
  return p2 - q;
@@ -68356,7 +69442,7 @@ var ge = defineCompare("ge", ">=", (a, b) => a >= b);
68356
69442
  // src/numbl-core/jit/codegen/cHelpers.ts
68357
69443
  function cTypeFor(t) {
68358
69444
  if (isMultiElement(t)) return "mtoc2_tensor_t";
68359
- if (isHandle(t)) return handleTypedefName(t);
69445
+ if (isHandle2(t)) return handleTypedefName(t);
68360
69446
  if (t.kind === "Struct") return structTypedefName(t);
68361
69447
  if (t.kind === "Class") return classTypedefName(t);
68362
69448
  if (t.kind === "Cell") return cellTypedefName(t);
@@ -73992,7 +75078,7 @@ function staticAnswer(t) {
73992
75078
  }
73993
75079
  if (isString(t)) return true;
73994
75080
  if (isChar(t)) return false;
73995
- if (isStruct(t) || isClass(t) || isHandle(t)) return false;
75081
+ if (isStruct(t) || isClass(t) || isHandle2(t)) return false;
73996
75082
  return void 0;
73997
75083
  }
73998
75084
  function requireKnown(t) {
@@ -74111,7 +75197,7 @@ var isstruct = {
74111
75197
  function staticClassNameOf(t) {
74112
75198
  if (isClass(t)) return t.className;
74113
75199
  if (isStruct(t)) return "struct";
74114
- if (isHandle(t)) return "function_handle";
75200
+ if (isHandle2(t)) return "function_handle";
74115
75201
  if (isChar(t)) return "char";
74116
75202
  if (isString(t)) return "string";
74117
75203
  if (isCell(t)) return "cell";
@@ -79191,7 +80277,7 @@ function lowerFuncCall(e) {
79191
80277
  if (envEntry === void 0 && e.name === "feval") {
79192
80278
  return lowerFevalCall.call(this, e);
79193
80279
  }
79194
- if (envEntry !== void 0 && isHandle(envEntry.ty)) {
80280
+ if (envEntry !== void 0 && isHandle2(envEntry.ty)) {
79195
80281
  return dispatchHandleCall.call(this, e.name, envEntry, e.args, e.span);
79196
80282
  }
79197
80283
  if (envEntry === void 0 && this.workspace.isClass(e.name)) {
@@ -79638,7 +80724,7 @@ function lowerMultiAssign(s) {
79638
80724
  s = { ...s, lvalues: expandedLvalues };
79639
80725
  if (s.expr.type === "FuncCall") {
79640
80726
  const envEntry = this.env.get(callName);
79641
- if (envEntry !== void 0 && isHandle(envEntry.ty)) {
80727
+ if (envEntry !== void 0 && isHandle2(envEntry.ty)) {
79642
80728
  return dispatchHandleMultiAssign.call(
79643
80729
  this,
79644
80730
  callName,