numbl 0.0.17 → 0.0.18

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
@@ -1275,11 +1275,13 @@ var getItemTypeFromRuntimeValue = (value) => {
1275
1275
  length: "unknown"
1276
1276
  // do not include length or we get too many jits
1277
1277
  };
1278
- case "struct":
1279
- return {
1280
- kind: "Struct",
1281
- knownFields: Array.from(value.fields.keys())
1282
- };
1278
+ case "struct": {
1279
+ const knownFields = {};
1280
+ for (const [k, v] of value.fields) {
1281
+ knownFields[k] = getItemTypeFromRuntimeValue(v);
1282
+ }
1283
+ return { kind: "Struct", knownFields };
1284
+ }
1283
1285
  case "function":
1284
1286
  return {
1285
1287
  kind: "Function",
@@ -17022,10 +17024,309 @@ function eig(data, n, computeVL, computeVR, balance) {
17022
17024
  VR: computeVR ? vr : void 0
17023
17025
  };
17024
17026
  }
17025
- function linsolveComplex(_ARe, _AIm, _m, _n, _BRe, _BIm, _nrhs) {
17026
- throw new Error(
17027
- "linsolveComplex: not yet implemented in pure-TypeScript fallback; the native LAPACK addon is required for complex matrix left-division"
17028
- );
17027
+ function linsolveComplex(ARe, AIm, m, n, BRe, BIm, nrhs) {
17028
+ if (m === n) {
17029
+ const aRe = new Float64Array(ARe);
17030
+ const aIm = new Float64Array(AIm);
17031
+ const bRe = new Float64Array(BRe);
17032
+ const bIm = new Float64Array(BIm);
17033
+ const ipiv = new Int32Array(n);
17034
+ for (let k = 0; k < n; k++) {
17035
+ let maxVal = aRe[k + k * n] * aRe[k + k * n] + aIm[k + k * n] * aIm[k + k * n];
17036
+ let maxIdx = k;
17037
+ for (let i = k + 1; i < n; i++) {
17038
+ const v = aRe[i + k * n] * aRe[i + k * n] + aIm[i + k * n] * aIm[i + k * n];
17039
+ if (v > maxVal) {
17040
+ maxVal = v;
17041
+ maxIdx = i;
17042
+ }
17043
+ }
17044
+ ipiv[k] = maxIdx;
17045
+ if (maxIdx !== k) {
17046
+ for (let j = 0; j < n; j++) {
17047
+ let tmp = aRe[k + j * n];
17048
+ aRe[k + j * n] = aRe[maxIdx + j * n];
17049
+ aRe[maxIdx + j * n] = tmp;
17050
+ tmp = aIm[k + j * n];
17051
+ aIm[k + j * n] = aIm[maxIdx + j * n];
17052
+ aIm[maxIdx + j * n] = tmp;
17053
+ }
17054
+ }
17055
+ if (maxVal === 0) throw new Error("linsolveComplex: matrix is singular");
17056
+ const dRe = aRe[k + k * n];
17057
+ const dIm = aIm[k + k * n];
17058
+ const dAbs2 = dRe * dRe + dIm * dIm;
17059
+ for (let i = k + 1; i < n; i++) {
17060
+ const numRe = aRe[i + k * n];
17061
+ const numIm = aIm[i + k * n];
17062
+ const lRe = (numRe * dRe + numIm * dIm) / dAbs2;
17063
+ const lIm = (numIm * dRe - numRe * dIm) / dAbs2;
17064
+ aRe[i + k * n] = lRe;
17065
+ aIm[i + k * n] = lIm;
17066
+ for (let j = k + 1; j < n; j++) {
17067
+ aRe[i + j * n] -= lRe * aRe[k + j * n] - lIm * aIm[k + j * n];
17068
+ aIm[i + j * n] -= lRe * aIm[k + j * n] + lIm * aRe[k + j * n];
17069
+ }
17070
+ }
17071
+ }
17072
+ for (let i = 0; i < n; i++) {
17073
+ const pi = ipiv[i];
17074
+ if (pi !== i) {
17075
+ for (let c = 0; c < nrhs; c++) {
17076
+ let tmp = bRe[i + c * n];
17077
+ bRe[i + c * n] = bRe[pi + c * n];
17078
+ bRe[pi + c * n] = tmp;
17079
+ tmp = bIm[i + c * n];
17080
+ bIm[i + c * n] = bIm[pi + c * n];
17081
+ bIm[pi + c * n] = tmp;
17082
+ }
17083
+ }
17084
+ }
17085
+ for (let c = 0; c < nrhs; c++) {
17086
+ for (let i = 1; i < n; i++) {
17087
+ for (let k = 0; k < i; k++) {
17088
+ const lRe = aRe[i + k * n];
17089
+ const lIm = aIm[i + k * n];
17090
+ bRe[i + c * n] -= lRe * bRe[k + c * n] - lIm * bIm[k + c * n];
17091
+ bIm[i + c * n] -= lRe * bIm[k + c * n] + lIm * bRe[k + c * n];
17092
+ }
17093
+ }
17094
+ }
17095
+ for (let c = 0; c < nrhs; c++) {
17096
+ for (let i = n - 1; i >= 0; i--) {
17097
+ for (let k = i + 1; k < n; k++) {
17098
+ const uRe = aRe[i + k * n];
17099
+ const uIm = aIm[i + k * n];
17100
+ bRe[i + c * n] -= uRe * bRe[k + c * n] - uIm * bIm[k + c * n];
17101
+ bIm[i + c * n] -= uRe * bIm[k + c * n] + uIm * bRe[k + c * n];
17102
+ }
17103
+ const dRe = aRe[i + i * n];
17104
+ const dIm = aIm[i + i * n];
17105
+ const dAbs2 = dRe * dRe + dIm * dIm;
17106
+ const xRe = (bRe[i + c * n] * dRe + bIm[i + c * n] * dIm) / dAbs2;
17107
+ const xIm = (bIm[i + c * n] * dRe - bRe[i + c * n] * dIm) / dAbs2;
17108
+ bRe[i + c * n] = xRe;
17109
+ bIm[i + c * n] = xIm;
17110
+ }
17111
+ }
17112
+ return { re: bRe, im: bIm };
17113
+ } else if (m > n) {
17114
+ const kk = n;
17115
+ const aRe = new Float64Array(ARe);
17116
+ const aIm = new Float64Array(AIm);
17117
+ const tauRe = new Float64Array(kk);
17118
+ const tauIm = new Float64Array(kk);
17119
+ for (let j = 0; j < kk; j++) {
17120
+ let xnorm2 = 0;
17121
+ for (let i = j + 1; i < m; i++) {
17122
+ xnorm2 += aRe[i + j * m] * aRe[i + j * m] + aIm[i + j * m] * aIm[i + j * m];
17123
+ }
17124
+ const alphaRe = aRe[j + j * m];
17125
+ const alphaIm = aIm[j + j * m];
17126
+ const alphaAbs2 = alphaRe * alphaRe + alphaIm * alphaIm;
17127
+ if (xnorm2 === 0 && alphaIm === 0) {
17128
+ tauRe[j] = 0;
17129
+ tauIm[j] = 0;
17130
+ continue;
17131
+ }
17132
+ const xnorm = Math.sqrt(alphaAbs2 + xnorm2);
17133
+ const betaRe = alphaRe >= 0 ? -xnorm : xnorm;
17134
+ const diffRe = betaRe - alphaRe;
17135
+ const diffIm = -alphaIm;
17136
+ tauRe[j] = diffRe / betaRe;
17137
+ tauIm[j] = diffIm / betaRe;
17138
+ const denomRe = alphaRe - betaRe;
17139
+ const denomIm = alphaIm;
17140
+ const denomAbs2 = denomRe * denomRe + denomIm * denomIm;
17141
+ for (let i = j + 1; i < m; i++) {
17142
+ const numRe = aRe[i + j * m];
17143
+ const numIm = aIm[i + j * m];
17144
+ aRe[i + j * m] = (numRe * denomRe + numIm * denomIm) / denomAbs2;
17145
+ aIm[i + j * m] = (numIm * denomRe - numRe * denomIm) / denomAbs2;
17146
+ }
17147
+ aRe[j + j * m] = betaRe;
17148
+ aIm[j + j * m] = 0;
17149
+ for (let col = j + 1; col < n; col++) {
17150
+ let wRe = aRe[j + col * m];
17151
+ let wIm = aIm[j + col * m];
17152
+ for (let i = 1; i < m - j; i++) {
17153
+ const vRe = aRe[j + i + j * m];
17154
+ const vIm = -aIm[j + i + j * m];
17155
+ wRe += vRe * aRe[j + i + col * m] - vIm * aIm[j + i + col * m];
17156
+ wIm += vRe * aIm[j + i + col * m] + vIm * aRe[j + i + col * m];
17157
+ }
17158
+ const twRe = tauRe[j] * wRe - tauIm[j] * wIm;
17159
+ const twIm = tauRe[j] * wIm + tauIm[j] * wRe;
17160
+ aRe[j + col * m] -= twRe;
17161
+ aIm[j + col * m] -= twIm;
17162
+ for (let i = 1; i < m - j; i++) {
17163
+ const vRe = aRe[j + i + j * m];
17164
+ const vIm = aIm[j + i + j * m];
17165
+ aRe[j + i + col * m] -= vRe * twRe - vIm * twIm;
17166
+ aIm[j + i + col * m] -= vRe * twIm + vIm * twRe;
17167
+ }
17168
+ }
17169
+ }
17170
+ const bRe = new Float64Array(BRe);
17171
+ const bIm = new Float64Array(BIm);
17172
+ for (let j = 0; j < kk; j++) {
17173
+ if (tauRe[j] === 0 && tauIm[j] === 0) continue;
17174
+ for (let c = 0; c < nrhs; c++) {
17175
+ let wRe = bRe[j + c * m];
17176
+ let wIm = bIm[j + c * m];
17177
+ for (let i = 1; i < m - j; i++) {
17178
+ const vRe = aRe[j + i + j * m];
17179
+ const vIm = -aIm[j + i + j * m];
17180
+ wRe += vRe * bRe[j + i + c * m] - vIm * bIm[j + i + c * m];
17181
+ wIm += vRe * bIm[j + i + c * m] + vIm * bRe[j + i + c * m];
17182
+ }
17183
+ const twRe = tauRe[j] * wRe - tauIm[j] * wIm;
17184
+ const twIm = tauRe[j] * wIm + tauIm[j] * wRe;
17185
+ bRe[j + c * m] -= twRe;
17186
+ bIm[j + c * m] -= twIm;
17187
+ for (let i = 1; i < m - j; i++) {
17188
+ const vRe = aRe[j + i + j * m];
17189
+ const vIm = aIm[j + i + j * m];
17190
+ bRe[j + i + c * m] -= vRe * twRe - vIm * twIm;
17191
+ bIm[j + i + c * m] -= vRe * twIm + vIm * twRe;
17192
+ }
17193
+ }
17194
+ }
17195
+ const xRe = new Float64Array(n * nrhs);
17196
+ const xIm = new Float64Array(n * nrhs);
17197
+ for (let c = 0; c < nrhs; c++) {
17198
+ for (let i = n - 1; i >= 0; i--) {
17199
+ let valRe = bRe[i + c * m];
17200
+ let valIm = bIm[i + c * m];
17201
+ for (let k = i + 1; k < n; k++) {
17202
+ const rRe = aRe[i + k * m];
17203
+ const rIm = aIm[i + k * m];
17204
+ valRe -= rRe * xRe[k + c * n] - rIm * xIm[k + c * n];
17205
+ valIm -= rRe * xIm[k + c * n] + rIm * xRe[k + c * n];
17206
+ }
17207
+ const dRe = aRe[i + i * m];
17208
+ const dIm = aIm[i + i * m];
17209
+ const dAbs2 = dRe * dRe + dIm * dIm;
17210
+ xRe[i + c * n] = (valRe * dRe + valIm * dIm) / dAbs2;
17211
+ xIm[i + c * n] = (valIm * dRe - valRe * dIm) / dAbs2;
17212
+ }
17213
+ }
17214
+ return { re: xRe, im: xIm };
17215
+ } else {
17216
+ const ahRe = new Float64Array(n * m);
17217
+ const ahIm = new Float64Array(n * m);
17218
+ for (let i = 0; i < m; i++) {
17219
+ for (let j = 0; j < n; j++) {
17220
+ ahRe[j + i * n] = ARe[i + j * m];
17221
+ ahIm[j + i * n] = -AIm[i + j * m];
17222
+ }
17223
+ }
17224
+ const kk = m;
17225
+ const tauRe = new Float64Array(kk);
17226
+ const tauIm = new Float64Array(kk);
17227
+ for (let j = 0; j < kk; j++) {
17228
+ let xnorm2 = 0;
17229
+ for (let i = j + 1; i < n; i++) {
17230
+ xnorm2 += ahRe[i + j * n] * ahRe[i + j * n] + ahIm[i + j * n] * ahIm[i + j * n];
17231
+ }
17232
+ const alphaRe = ahRe[j + j * n];
17233
+ const alphaIm = ahIm[j + j * n];
17234
+ const alphaAbs2 = alphaRe * alphaRe + alphaIm * alphaIm;
17235
+ if (xnorm2 === 0 && alphaIm === 0) {
17236
+ tauRe[j] = 0;
17237
+ tauIm[j] = 0;
17238
+ continue;
17239
+ }
17240
+ const xnorm = Math.sqrt(alphaAbs2 + xnorm2);
17241
+ const betaRe = alphaRe >= 0 ? -xnorm : xnorm;
17242
+ const diffRe = betaRe - alphaRe;
17243
+ const diffIm = -alphaIm;
17244
+ tauRe[j] = diffRe / betaRe;
17245
+ tauIm[j] = diffIm / betaRe;
17246
+ const denomRe = alphaRe - betaRe;
17247
+ const denomIm = alphaIm;
17248
+ const denomAbs2 = denomRe * denomRe + denomIm * denomIm;
17249
+ for (let i = j + 1; i < n; i++) {
17250
+ const numRe = ahRe[i + j * n];
17251
+ const numIm = ahIm[i + j * n];
17252
+ ahRe[i + j * n] = (numRe * denomRe + numIm * denomIm) / denomAbs2;
17253
+ ahIm[i + j * n] = (numIm * denomRe - numRe * denomIm) / denomAbs2;
17254
+ }
17255
+ ahRe[j + j * n] = betaRe;
17256
+ ahIm[j + j * n] = 0;
17257
+ for (let col = j + 1; col < m; col++) {
17258
+ let wRe = ahRe[j + col * n];
17259
+ let wIm = ahIm[j + col * n];
17260
+ for (let i = 1; i < n - j; i++) {
17261
+ const vRe = ahRe[j + i + j * n];
17262
+ const vIm = -ahIm[j + i + j * n];
17263
+ wRe += vRe * ahRe[j + i + col * n] - vIm * ahIm[j + i + col * n];
17264
+ wIm += vRe * ahIm[j + i + col * n] + vIm * ahRe[j + i + col * n];
17265
+ }
17266
+ const twRe = tauRe[j] * wRe - tauIm[j] * wIm;
17267
+ const twIm = tauRe[j] * wIm + tauIm[j] * wRe;
17268
+ ahRe[j + col * n] -= twRe;
17269
+ ahIm[j + col * n] -= twIm;
17270
+ for (let i = 1; i < n - j; i++) {
17271
+ const vRe = ahRe[j + i + j * n];
17272
+ const vIm = ahIm[j + i + j * n];
17273
+ ahRe[j + i + col * n] -= vRe * twRe - vIm * twIm;
17274
+ ahIm[j + i + col * n] -= vRe * twIm + vIm * twRe;
17275
+ }
17276
+ }
17277
+ }
17278
+ const yRe = new Float64Array(m * nrhs);
17279
+ const yIm = new Float64Array(m * nrhs);
17280
+ for (let c = 0; c < nrhs; c++) {
17281
+ for (let i = 0; i < m; i++) {
17282
+ let valRe = BRe[i + c * m];
17283
+ let valIm = BIm[i + c * m];
17284
+ for (let k = 0; k < i; k++) {
17285
+ const rRe = ahRe[k + i * n];
17286
+ const rIm = -ahIm[k + i * n];
17287
+ valRe -= rRe * yRe[k + c * m] - rIm * yIm[k + c * m];
17288
+ valIm -= rRe * yIm[k + c * m] + rIm * yRe[k + c * m];
17289
+ }
17290
+ const dRe = ahRe[i + i * n];
17291
+ const dIm = -ahIm[i + i * n];
17292
+ const dAbs2 = dRe * dRe + dIm * dIm;
17293
+ yRe[i + c * m] = (valRe * dRe + valIm * dIm) / dAbs2;
17294
+ yIm[i + c * m] = (valIm * dRe - valRe * dIm) / dAbs2;
17295
+ }
17296
+ }
17297
+ const xRe = new Float64Array(n * nrhs);
17298
+ const xIm = new Float64Array(n * nrhs);
17299
+ for (let i = 0; i < m; i++) {
17300
+ for (let c = 0; c < nrhs; c++) {
17301
+ xRe[i + c * n] = yRe[i + c * m];
17302
+ xIm[i + c * n] = yIm[i + c * m];
17303
+ }
17304
+ }
17305
+ for (let j = kk - 1; j >= 0; j--) {
17306
+ if (tauRe[j] === 0 && tauIm[j] === 0) continue;
17307
+ for (let c = 0; c < nrhs; c++) {
17308
+ let wRe = xRe[j + c * n];
17309
+ let wIm = xIm[j + c * n];
17310
+ for (let i = 1; i < n - j; i++) {
17311
+ const vRe = ahRe[j + i + j * n];
17312
+ const vIm = -ahIm[j + i + j * n];
17313
+ wRe += vRe * xRe[j + i + c * n] - vIm * xIm[j + i + c * n];
17314
+ wIm += vRe * xIm[j + i + c * n] + vIm * xRe[j + i + c * n];
17315
+ }
17316
+ const twRe = tauRe[j] * wRe - tauIm[j] * wIm;
17317
+ const twIm = tauRe[j] * wIm + tauIm[j] * wRe;
17318
+ xRe[j + c * n] -= twRe;
17319
+ xIm[j + c * n] -= twIm;
17320
+ for (let i = 1; i < n - j; i++) {
17321
+ const vRe = ahRe[j + i + j * n];
17322
+ const vIm = ahIm[j + i + j * n];
17323
+ xRe[j + i + c * n] -= vRe * twRe - vIm * twIm;
17324
+ xIm[j + i + c * n] -= vRe * twIm + vIm * twRe;
17325
+ }
17326
+ }
17327
+ }
17328
+ return { re: xRe, im: xIm };
17329
+ }
17029
17330
  }
17030
17331
  function lu(data, m, n) {
17031
17332
  const a = new Float64Array(data);
@@ -17181,8 +17482,11 @@ function typeToString(ty) {
17181
17482
  return `Function<${ty.params.map(typeToString).join(", ")}, ${typeToString(
17182
17483
  ty.returns
17183
17484
  )}>`;
17184
- case "Struct":
17185
- return `Struct<${ty.knownFields ? ty.knownFields.join(", ") : "?"}>`;
17485
+ case "Struct": {
17486
+ const entries = Object.entries(ty.knownFields);
17487
+ if (entries.length === 0) return "Struct<>";
17488
+ return `Struct<${entries.map(([k, v]) => `${k}: ${typeToString(v)}`).join(", ")}>`;
17489
+ }
17186
17490
  case "Void":
17187
17491
  return "Void";
17188
17492
  case "Unknown":
@@ -17227,6 +17531,8 @@ function isChar(t) {
17227
17531
  if (t.kind === "Unknown") return void 0;
17228
17532
  return false;
17229
17533
  }
17534
+ var isScalarType = (t) => t.kind === "Number" || t.kind === "Boolean" || t.kind === "ComplexNumber";
17535
+ var isComplexType = (t) => t.kind === "ComplexNumber" || t.kind === "Tensor" && !!t.isComplex;
17230
17536
  var IType = {
17231
17537
  Num: { kind: "Number" },
17232
17538
  Complex: { kind: "ComplexNumber" },
@@ -17254,7 +17560,7 @@ var IType = {
17254
17560
  func(params, returns) {
17255
17561
  return { kind: "Function", params, returns };
17256
17562
  },
17257
- struct(fields) {
17563
+ struct(fields = {}) {
17258
17564
  return { kind: "Struct", knownFields: fields };
17259
17565
  },
17260
17566
  union(types) {
@@ -17319,16 +17625,34 @@ var IType = {
17319
17625
  }
17320
17626
  case "Struct": {
17321
17627
  if (b.kind === "Struct") {
17322
- const knownFields = a.knownFields.filter(
17323
- (f) => b.knownFields.includes(f)
17324
- );
17628
+ const knownFields = {};
17629
+ for (const [k, v] of Object.entries(a.knownFields)) {
17630
+ if (k in b.knownFields) {
17631
+ knownFields[k] = IType.unify(v, b.knownFields[k]) ?? IType.Unknown;
17632
+ } else {
17633
+ knownFields[k] = v;
17634
+ }
17635
+ }
17636
+ for (const [k, v] of Object.entries(b.knownFields)) {
17637
+ if (!(k in a.knownFields)) {
17638
+ knownFields[k] = v;
17639
+ }
17640
+ }
17325
17641
  return { kind: "Struct", knownFields };
17326
17642
  }
17327
17643
  break;
17328
17644
  }
17329
17645
  case "Union": {
17330
17646
  if (b.kind === "Union") {
17331
- const types = Array.from(/* @__PURE__ */ new Set([...a.types, ...b.types]));
17647
+ const seen = /* @__PURE__ */ new Set();
17648
+ const types = [];
17649
+ for (const t of [...a.types, ...b.types]) {
17650
+ const key = typeToString(t);
17651
+ if (!seen.has(key)) {
17652
+ seen.add(key);
17653
+ types.push(t);
17654
+ }
17655
+ }
17332
17656
  return { kind: "Union", types };
17333
17657
  }
17334
17658
  break;
@@ -17413,18 +17737,19 @@ function unregister(name) {
17413
17737
  }
17414
17738
 
17415
17739
  // src/numbl-core/builtins/linear-algebra/check-helpers.ts
17740
+ function isMatrixLike(A) {
17741
+ return isFullyUnknown(A) || isNum(A) === true || isComplex(A) === true || A.kind === "Boolean" || isTensor(A) === true;
17742
+ }
17743
+ function isOptionalStringArg(arg) {
17744
+ if (arg === void 0) return true;
17745
+ return isFullyUnknown(arg) || arg.kind === "String" || arg.kind === "Char";
17746
+ }
17416
17747
  function out(...types) {
17417
17748
  return { outputTypes: types };
17418
17749
  }
17419
17750
  function unknownMatrix(isComplex2) {
17420
17751
  return IType.tensor({ isComplex: isComplex2 || void 0 });
17421
17752
  }
17422
- function matrix(_shapeOrComplex, isComplex2) {
17423
- if (typeof _shapeOrComplex === "boolean") {
17424
- return IType.tensor({ isComplex: _shapeOrComplex || void 0 });
17425
- }
17426
- return IType.tensor({ isComplex: isComplex2 || void 0 });
17427
- }
17428
17753
  function parseEconArg(argType) {
17429
17754
  if (argType === void 0) return false;
17430
17755
  if (isFullyUnknown(argType)) return "unknown";
@@ -17444,6 +17769,103 @@ function parseStringArgLower(arg) {
17444
17769
  }
17445
17770
  return String(arg).toLowerCase();
17446
17771
  }
17772
+ function parseEconArgRuntime(arg) {
17773
+ if (arg === void 0) return false;
17774
+ if (isRuntimeNumber(arg) && arg === 0) return true;
17775
+ if (isRuntimeString(arg) && arg.toLowerCase() === "econ") return true;
17776
+ if (isRuntimeChar(arg) && arg.value.toLowerCase() === "econ") return true;
17777
+ return false;
17778
+ }
17779
+ function buildEigenvectorMatrix(packedV, wi, n, hasComplex) {
17780
+ if (!hasComplex) {
17781
+ return RTV.tensor(new FloatXArray(packedV), [n, n]);
17782
+ }
17783
+ const realPart = new FloatXArray(n * n);
17784
+ const imagPart = new FloatXArray(n * n);
17785
+ let j = 0;
17786
+ while (j < n) {
17787
+ if (Math.abs(wi[j]) === 0) {
17788
+ for (let i = 0; i < n; i++) {
17789
+ realPart[colMajorIndex(i, j, n)] = packedV[colMajorIndex(i, j, n)];
17790
+ }
17791
+ j++;
17792
+ } else {
17793
+ for (let i = 0; i < n; i++) {
17794
+ const re = packedV[colMajorIndex(i, j, n)];
17795
+ const im = packedV[colMajorIndex(i, j + 1, n)];
17796
+ realPart[colMajorIndex(i, j, n)] = re;
17797
+ imagPart[colMajorIndex(i, j, n)] = im;
17798
+ realPart[colMajorIndex(i, j + 1, n)] = re;
17799
+ imagPart[colMajorIndex(i, j + 1, n)] = -im;
17800
+ }
17801
+ j += 2;
17802
+ }
17803
+ }
17804
+ return RTV.tensor(realPart, [n, n], imagPart);
17805
+ }
17806
+ function maybeComplexTensor(re, shape, im) {
17807
+ const imag = im && im.some((v) => v !== 0) ? new FloatXArray(im) : void 0;
17808
+ return RTV.tensor(new FloatXArray(re), shape, imag);
17809
+ }
17810
+ function buildDiagMatrix(realVals, imagVals, size) {
17811
+ const [rows, cols] = typeof size === "number" ? [size, size] : size;
17812
+ const k = Math.min(rows, cols, realVals.length);
17813
+ const dReal = new FloatXArray(rows * cols);
17814
+ for (let i = 0; i < k; i++) dReal[colMajorIndex(i, i, rows)] = realVals[i];
17815
+ if (imagVals && imagVals.some((v) => v !== 0)) {
17816
+ const dImag = new FloatXArray(rows * cols);
17817
+ for (let i = 0; i < k; i++) dImag[colMajorIndex(i, i, rows)] = imagVals[i];
17818
+ return RTV.tensor(dReal, [rows, cols], dImag);
17819
+ }
17820
+ return RTV.tensor(dReal, [rows, cols]);
17821
+ }
17822
+ function gaussJordanEliminate(aug, rows, totalCols) {
17823
+ for (let col = 0; col < rows; col++) {
17824
+ let maxVal = Math.abs(aug[col * rows + col]);
17825
+ let maxRow = col;
17826
+ for (let row = col + 1; row < rows; row++) {
17827
+ const val = Math.abs(aug[col * rows + row]);
17828
+ if (val > maxVal) {
17829
+ maxVal = val;
17830
+ maxRow = row;
17831
+ }
17832
+ }
17833
+ if (maxRow !== col) {
17834
+ for (let j = 0; j < totalCols; j++) {
17835
+ const tmp = aug[j * rows + col];
17836
+ aug[j * rows + col] = aug[j * rows + maxRow];
17837
+ aug[j * rows + maxRow] = tmp;
17838
+ }
17839
+ }
17840
+ const pivot = aug[col * rows + col];
17841
+ if (Math.abs(pivot) < 1e-14) continue;
17842
+ for (let j = 0; j < totalCols; j++) aug[j * rows + col] /= pivot;
17843
+ for (let row = 0; row < rows; row++) {
17844
+ if (row === col) continue;
17845
+ const factor = aug[col * rows + row];
17846
+ for (let j = 0; j < totalCols; j++) {
17847
+ aug[j * rows + row] -= factor * aug[j * rows + col];
17848
+ }
17849
+ }
17850
+ }
17851
+ }
17852
+ function applyBuiltin(caller, name, args, nargout) {
17853
+ const branches = getBuiltin(name);
17854
+ if (!branches)
17855
+ throw new RuntimeError(`${caller}: builtin '${name}' not found`);
17856
+ for (const branch of branches) {
17857
+ const result = branch.apply(args, nargout);
17858
+ if (result !== void 0) {
17859
+ if (result instanceof Promise)
17860
+ throw new RuntimeError(
17861
+ `${caller}: builtin '${name}' returned async result`
17862
+ );
17863
+ if (Array.isArray(result)) return result[0];
17864
+ return result;
17865
+ }
17866
+ }
17867
+ throw new RuntimeError(`${caller}: builtin '${name}' returned no result`);
17868
+ }
17447
17869
 
17448
17870
  // src/numbl-core/builtins/linear-algebra/linsolve.ts
17449
17871
  function linsolveLapack(A, m, n, B, nrhs) {
@@ -17472,11 +17894,8 @@ function registerLinsolve() {
17472
17894
  {
17473
17895
  check: (argTypes, nargout) => {
17474
17896
  if (argTypes.length !== 2 || nargout !== 1) return null;
17475
- const A = argTypes[0];
17476
- const B = argTypes[1];
17477
- if (isFullyUnknown(A) || isFullyUnknown(B)) return out(unknownMatrix());
17478
- if (isNum(A) === true || isNum(B) === true) return out(unknownMatrix());
17479
- if (isTensor(A) !== true || isTensor(B) !== true) return null;
17897
+ if (!isMatrixLike(argTypes[0]) || !isMatrixLike(argTypes[1]))
17898
+ return null;
17480
17899
  return out(unknownMatrix());
17481
17900
  },
17482
17901
  apply: (args) => {
@@ -17516,23 +17935,36 @@ function registerLinsolve() {
17516
17935
  ]);
17517
17936
  }
17518
17937
 
17519
- // src/numbl-core/builtins/linear-algebra/applyBuiltin.ts
17520
- function applyBuiltin(caller, name, args, nargout) {
17521
- const branches = getBuiltin(name);
17522
- if (!branches)
17523
- throw new RuntimeError(`${caller}: builtin '${name}' not found`);
17524
- for (const branch of branches) {
17525
- const result = branch.apply(args, nargout);
17526
- if (result !== void 0) {
17527
- if (result instanceof Promise)
17528
- throw new RuntimeError(
17529
- `${caller}: builtin '${name}' returned async result`
17530
- );
17531
- if (Array.isArray(result)) return result[0];
17532
- return result;
17533
- }
17938
+ // src/numbl-core/builtins/shape-utils.ts
17939
+ function parseShapeArgs(args) {
17940
+ if (args.length === 1 && isRuntimeTensor(args[0])) {
17941
+ const t = args[0];
17942
+ const shape = [];
17943
+ for (let i = 0; i < t.data.length; i++)
17944
+ shape.push(Math.max(0, Math.round(t.data[i])));
17945
+ return shape;
17534
17946
  }
17535
- throw new RuntimeError(`${caller}: builtin '${name}' returned no result`);
17947
+ return args.map((a) => Math.max(0, Math.round(toNumber(a))));
17948
+ }
17949
+ function coerceToTensor(v, name) {
17950
+ if (isRuntimeTensor(v)) return v;
17951
+ if (isRuntimeNumber(v))
17952
+ return RTV.tensor(new FloatXArray([v]), [1, 1]);
17953
+ if (isRuntimeLogical(v))
17954
+ return RTV.tensor(new FloatXArray([v ? 1 : 0]), [1, 1]);
17955
+ if (isRuntimeComplexNumber(v))
17956
+ return RTV.tensor(
17957
+ new FloatXArray([v.re]),
17958
+ [1, 1],
17959
+ new FloatXArray([v.im])
17960
+ );
17961
+ throw new RuntimeError(`${name}: argument must be numeric`);
17962
+ }
17963
+ function toNumericVector(v, name) {
17964
+ if (isRuntimeNumber(v)) return [v];
17965
+ if (isRuntimeLogical(v)) return [v ? 1 : 0];
17966
+ if (isRuntimeTensor(v)) return Array.from(v.data);
17967
+ throw new RuntimeError(`${name}: argument must be numeric`);
17536
17968
  }
17537
17969
 
17538
17970
  // src/numbl-core/builtins/arithmetic.ts
@@ -17725,10 +18157,8 @@ function mElemMul(a, b) {
17725
18157
  return binaryOp(a, b, (x, y) => x * y);
17726
18158
  }
17727
18159
  function mDiv(a, b) {
17728
- if (isRuntimeTensor(b) && !isRuntimeNumber(a) && !isRuntimeLogical(a)) {
17729
- const at = mConjugateTranspose(
17730
- isRuntimeNumber(a) || isRuntimeLogical(a) ? RTV.tensor(new FloatXArray([toNumber(a)]), [1, 1]) : a
17731
- );
18160
+ if (isRuntimeTensor(b)) {
18161
+ const at = mConjugateTranspose(coerceToTensor(a, "mrdivide"));
17732
18162
  const bt = mConjugateTranspose(b);
17733
18163
  const result = mLeftDiv(bt, at);
17734
18164
  return mConjugateTranspose(result);
@@ -21306,13 +21736,13 @@ var ExpressionParser = class extends ParserBase {
21306
21736
  }
21307
21737
  case 51 /* LBracket */: {
21308
21738
  const start = info.position;
21309
- const matrix2 = this.parseMatrix();
21739
+ const matrix = this.parseMatrix();
21310
21740
  if (!this.consume(52 /* RBracket */)) {
21311
21741
  throw this.error("expected ']' to close matrix literal");
21312
21742
  }
21313
21743
  const end = this.lastTokenEnd();
21314
21744
  const span = this.spanFrom(start, end);
21315
- return { ...matrix2, span };
21745
+ return { ...matrix, span };
21316
21746
  }
21317
21747
  case 53 /* LBrace */: {
21318
21748
  const start = info.position;
@@ -23877,10 +24307,17 @@ function elemwise(fn, o) {
23877
24307
  const result = fn(v ? 1 : 0);
23878
24308
  return o?.isLogical ? RTV.logical(!!result) : RTV.num(result);
23879
24309
  }
24310
+ if (o?.complex && isRuntimeComplexNumber(v))
24311
+ return RTV.complex(fn(v.re), fn(v.im));
23880
24312
  if (isRuntimeTensor(v)) {
23881
24313
  const result = new FloatXArray(v.data.length);
23882
24314
  for (let i = 0; i < v.data.length; i++) result[i] = fn(v.data[i]);
23883
- const t = RTV.tensor(result, v.shape);
24315
+ let imag;
24316
+ if (o?.complex && v.imag) {
24317
+ imag = new FloatXArray(v.imag.length);
24318
+ for (let i = 0; i < v.imag.length; i++) imag[i] = fn(v.imag[i]);
24319
+ }
24320
+ const t = RTV.tensor(result, v.shape, imag);
23884
24321
  if (o?.isLogical) t._isLogical = true;
23885
24322
  return t;
23886
24323
  }
@@ -23907,70 +24344,34 @@ function elemwise(fn, o) {
23907
24344
  });
23908
24345
  return ret;
23909
24346
  }
23910
- function elemwiseComplex(fn, o) {
23911
- const ret = [];
23912
- const apply = (args) => {
23913
- if (args.length !== 1) throw new RuntimeError(`Expected 1 argument`);
23914
- const v = args[0];
23915
- if (isRuntimeNumber(v)) return RTV.num(fn(v));
23916
- if (isRuntimeLogical(v)) return RTV.num(fn(v ? 1 : 0));
23917
- if (isRuntimeComplexNumber(v)) return RTV.complex(fn(v.re), fn(v.im));
23918
- if (isRuntimeTensor(v)) {
23919
- const result = new FloatXArray(v.data.length);
23920
- for (let i = 0; i < v.data.length; i++) result[i] = fn(v.data[i]);
23921
- let imag;
23922
- if (v.imag) {
23923
- imag = new FloatXArray(v.imag.length);
23924
- for (let i = 0; i < v.imag.length; i++) imag[i] = fn(v.imag[i]);
23925
- }
23926
- return RTV.tensor(result, v.shape, imag);
23927
- }
23928
- throw new RuntimeError("Expected numeric argument");
23929
- };
23930
- if (o?.nativeJs) {
23931
- ret.push({
23932
- check: (argTypes) => {
23933
- if (argTypes.length !== 1) return null;
23934
- if (argTypes[0].kind !== "Number") return null;
23935
- return { outputTypes: [{ kind: "Number" }] };
23936
- },
23937
- apply,
23938
- nativeJsFn: o.nativeJs
23939
- });
24347
+ function binaryApply(a, b, fn) {
24348
+ const aIsT = isRuntimeTensor(a);
24349
+ const bIsT = isRuntimeTensor(b);
24350
+ if (aIsT && bIsT) {
24351
+ const result = new FloatXArray(a.data.length);
24352
+ for (let i = 0; i < a.data.length; i++)
24353
+ result[i] = fn(a.data[i], b.data[i]);
24354
+ return RTV.tensor(result, a.shape);
23940
24355
  }
23941
- ret.push({
23942
- check: elemwiseCheck,
23943
- apply
23944
- });
23945
- return ret;
24356
+ if (aIsT) {
24357
+ const bv = toNumber(b);
24358
+ const result = new FloatXArray(a.data.length);
24359
+ for (let i = 0; i < a.data.length; i++) result[i] = fn(a.data[i], bv);
24360
+ return RTV.tensor(result, a.shape);
24361
+ }
24362
+ if (bIsT) {
24363
+ const av = toNumber(a);
24364
+ const result = new FloatXArray(b.data.length);
24365
+ for (let i = 0; i < b.data.length; i++) result[i] = fn(av, b.data[i]);
24366
+ return RTV.tensor(result, b.shape);
24367
+ }
24368
+ return RTV.num(fn(toNumber(a), toNumber(b)));
23946
24369
  }
23947
24370
  function binaryScalar(fn, o) {
23948
24371
  const ret = [];
23949
24372
  const apply = (args) => {
23950
24373
  if (args.length !== 2) throw new RuntimeError(`Expected 2 arguments`);
23951
- const a = args[0];
23952
- const b = args[1];
23953
- const aIsT = isRuntimeTensor(a);
23954
- const bIsT = isRuntimeTensor(b);
23955
- if (aIsT && bIsT) {
23956
- const result = new FloatXArray(a.data.length);
23957
- for (let i = 0; i < a.data.length; i++)
23958
- result[i] = fn(a.data[i], b.data[i]);
23959
- return RTV.tensor(result, a.shape);
23960
- }
23961
- if (aIsT) {
23962
- const bv = toNumber(b);
23963
- const result = new FloatXArray(a.data.length);
23964
- for (let i = 0; i < a.data.length; i++) result[i] = fn(a.data[i], bv);
23965
- return RTV.tensor(result, a.shape);
23966
- }
23967
- if (bIsT) {
23968
- const av = toNumber(a);
23969
- const result = new FloatXArray(b.data.length);
23970
- for (let i = 0; i < b.data.length; i++) result[i] = fn(av, b.data[i]);
23971
- return RTV.tensor(result, b.shape);
23972
- }
23973
- return RTV.num(fn(toNumber(a), toNumber(b)));
24374
+ return binaryApply(args[0], args[1], fn);
23974
24375
  };
23975
24376
  if (o?.nativeJs) {
23976
24377
  ret.push({
@@ -23993,32 +24394,6 @@ function binaryScalar(fn, o) {
23993
24394
  });
23994
24395
  return ret;
23995
24396
  }
23996
- function applyBesselBinary(nuArg, zArg, fn) {
23997
- const nuIsT = isRuntimeTensor(nuArg);
23998
- const zIsT = isRuntimeTensor(zArg);
23999
- if (!nuIsT && !zIsT) {
24000
- return RTV.num(fn(toNumber(nuArg), toNumber(zArg)));
24001
- }
24002
- if (!nuIsT && zIsT) {
24003
- const nu = toNumber(nuArg);
24004
- const result2 = new FloatXArray(zArg.data.length);
24005
- for (let i = 0; i < zArg.data.length; i++) result2[i] = fn(nu, zArg.data[i]);
24006
- return RTV.tensor(result2, zArg.shape);
24007
- }
24008
- if (nuIsT && !zIsT) {
24009
- const z = toNumber(zArg);
24010
- const result2 = new FloatXArray(nuArg.data.length);
24011
- for (let i = 0; i < nuArg.data.length; i++)
24012
- result2[i] = fn(nuArg.data[i], z);
24013
- return RTV.tensor(result2, nuArg.shape);
24014
- }
24015
- const nut = nuArg;
24016
- const zt = zArg;
24017
- const result = new FloatXArray(nut.data.length);
24018
- for (let i = 0; i < nut.data.length; i++)
24019
- result[i] = fn(nut.data[i], zt.data[i]);
24020
- return RTV.tensor(result, nut.shape);
24021
- }
24022
24397
  function registerMathFunctions() {
24023
24398
  register(
24024
24399
  "sin",
@@ -24261,106 +24636,19 @@ function registerMathFunctions() {
24261
24636
  );
24262
24637
  register(
24263
24638
  "sqrt",
24264
- [
24265
- // Num branch: returns Num if value is known and non-negative, otherwise Complex
24266
- {
24267
- check: (argTypes) => {
24268
- if (argTypes.length !== 1 || argTypes[0].kind !== "Number")
24269
- return null;
24270
- return { outputTypes: [{ kind: "ComplexNumber" }] };
24271
- },
24272
- apply: (args) => {
24273
- if (args.length !== 1) throw new RuntimeError("Expected 1 argument");
24274
- const v = args[0];
24275
- if (isRuntimeNumber(v)) {
24276
- if (v < 0) return RTV.complex(0, Math.sqrt(-v));
24277
- return RTV.num(Math.sqrt(v));
24278
- }
24279
- if (isRuntimeComplexNumber(v)) {
24280
- const r = Math.sqrt(v.re * v.re + v.im * v.im);
24281
- const theta = Math.atan2(v.im, v.re);
24282
- const sqrtR = Math.sqrt(r);
24283
- const reim = {
24284
- re: sqrtR * Math.cos(theta / 2),
24285
- im: sqrtR * Math.sin(theta / 2)
24286
- };
24287
- return reim.im === 0 ? RTV.num(reim.re) : RTV.complex(reim.re, reim.im);
24288
- }
24289
- return RTV.num(Math.sqrt(toNumber(v)));
24290
- }
24291
- },
24292
- // Complex input branch
24293
- {
24294
- check: (argTypes) => {
24295
- if (argTypes.length !== 1 || argTypes[0].kind !== "ComplexNumber")
24296
- return null;
24297
- return { outputTypes: [{ kind: "ComplexNumber" }] };
24298
- },
24299
- apply: (args) => {
24300
- if (args.length !== 1) throw new RuntimeError("Expected 1 argument");
24301
- const v = args[0];
24302
- if (isRuntimeComplexNumber(v)) {
24303
- const r = Math.sqrt(v.re * v.re + v.im * v.im);
24304
- const theta = Math.atan2(v.im, v.re);
24305
- const sqrtR = Math.sqrt(r);
24306
- const re = sqrtR * Math.cos(theta / 2), im = sqrtR * Math.sin(theta / 2);
24307
- return im === 0 ? RTV.num(re) : RTV.complex(re, im);
24308
- }
24309
- if (isRuntimeNumber(v)) {
24310
- if (v < 0) return RTV.complex(0, Math.sqrt(-v));
24311
- return RTV.num(Math.sqrt(v));
24312
- }
24313
- return RTV.num(Math.sqrt(toNumber(v)));
24314
- }
24639
+ complexElemwise(
24640
+ Math.sqrt,
24641
+ (re, im) => {
24642
+ const r = Math.sqrt(re * re + im * im);
24643
+ const theta = Math.atan2(im, re);
24644
+ const sqrtR = Math.sqrt(r);
24645
+ return {
24646
+ re: sqrtR * Math.cos(theta / 2),
24647
+ im: sqrtR * Math.sin(theta / 2)
24648
+ };
24315
24649
  },
24316
- // Fallback
24317
- {
24318
- check: elemwiseCheck,
24319
- apply: (args) => {
24320
- if (args.length !== 1) throw new RuntimeError("Expected 1 argument");
24321
- const v = args[0];
24322
- if (isRuntimeNumber(v)) {
24323
- if (v < 0) return RTV.complex(0, Math.sqrt(-v));
24324
- return RTV.num(Math.sqrt(v));
24325
- }
24326
- if (isRuntimeTensor(v)) {
24327
- let hasNeg = false;
24328
- for (let i = 0; i < v.data.length; i++) {
24329
- if (v.data[i] < 0) {
24330
- hasNeg = true;
24331
- break;
24332
- }
24333
- }
24334
- if (hasNeg || v.imag) {
24335
- const re = new FloatXArray(v.data.length);
24336
- const im = new FloatXArray(v.data.length);
24337
- for (let i = 0; i < v.data.length; i++) {
24338
- const rePart = v.data[i];
24339
- const imPart = v.imag ? v.imag[i] : 0;
24340
- const r = Math.sqrt(rePart * rePart + imPart * imPart);
24341
- const theta = Math.atan2(imPart, rePart);
24342
- const sqrtR = Math.sqrt(r);
24343
- re[i] = sqrtR * Math.cos(theta / 2);
24344
- im[i] = sqrtR * Math.sin(theta / 2);
24345
- }
24346
- let allRealZeroIm = true;
24347
- for (let i = 0; i < im.length; i++) {
24348
- if (im[i] !== 0) {
24349
- allRealZeroIm = false;
24350
- break;
24351
- }
24352
- }
24353
- return RTV.tensor(re, v.shape, allRealZeroIm ? void 0 : im);
24354
- }
24355
- const result = new FloatXArray(v.data.length);
24356
- for (let i = 0; i < v.data.length; i++)
24357
- result[i] = Math.sqrt(v.data[i]);
24358
- return RTV.tensor(result, v.shape);
24359
- }
24360
- return RTV.num(Math.sqrt(toNumber(v)));
24361
- }
24362
- }
24363
- ],
24650
+ "ComplexNumber"
24651
+ ),
24364
24652
  1
24365
24653
  );
24366
24654
  register(
@@ -24373,8 +24661,16 @@ function registerMathFunctions() {
24373
24661
  ),
24374
24662
  1
24375
24663
  );
24376
- register("floor", elemwiseComplex(Math.floor, { nativeJs: "Math.floor" }), 1);
24377
- register("ceil", elemwiseComplex(Math.ceil, { nativeJs: "Math.ceil" }), 1);
24664
+ register(
24665
+ "floor",
24666
+ elemwise(Math.floor, { nativeJs: "Math.floor", complex: true }),
24667
+ 1
24668
+ );
24669
+ register(
24670
+ "ceil",
24671
+ elemwise(Math.ceil, { nativeJs: "Math.ceil", complex: true }),
24672
+ 1
24673
+ );
24378
24674
  register(
24379
24675
  "round",
24380
24676
  builtinSingle((args) => {
@@ -24903,7 +25199,7 @@ function registerMathFunctions() {
24903
25199
  if (args.length < 2 || args.length > 3)
24904
25200
  throw new RuntimeError(`${name} requires 2 or 3 arguments`);
24905
25201
  const scale = args.length === 3 ? toNumber(args[2]) : 0;
24906
- return applyBesselBinary(args[0], args[1], (nu, z) => {
25202
+ return binaryApply(args[0], args[1], (nu, z) => {
24907
25203
  const val = fn(nu, z);
24908
25204
  return scale === 1 ? val * scaleFn(z) : val;
24909
25205
  });
@@ -25201,18 +25497,6 @@ function legendreAllOrders(n, x) {
25201
25497
  return result;
25202
25498
  }
25203
25499
 
25204
- // src/numbl-core/builtins/shape-utils.ts
25205
- function parseShapeArgs(args) {
25206
- if (args.length === 1 && isRuntimeTensor(args[0])) {
25207
- const t = args[0];
25208
- const shape = [];
25209
- for (let i = 0; i < t.data.length; i++)
25210
- shape.push(Math.max(0, Math.round(t.data[i])));
25211
- return shape;
25212
- }
25213
- return args.map((a) => Math.max(0, Math.round(toNumber(a))));
25214
- }
25215
-
25216
25500
  // src/numbl-core/builtins/prng.ts
25217
25501
  var _rngState = null;
25218
25502
  var _rngSeed = 0;
@@ -26499,18 +26783,7 @@ function registerArrayManipulationFunctions() {
26499
26783
  builtinSingle((args) => {
26500
26784
  if (args.length !== 2)
26501
26785
  throw new RuntimeError("permute requires 2 arguments");
26502
- let v = args[0];
26503
- if (isRuntimeNumber(v)) {
26504
- v = RTV.tensor(new FloatXArray([v]), [1, 1]);
26505
- } else if (isRuntimeComplexNumber(v)) {
26506
- v = RTV.tensor(
26507
- new FloatXArray([v.re]),
26508
- [1, 1],
26509
- new FloatXArray([v.im])
26510
- );
26511
- } else if (!isRuntimeTensor(v)) {
26512
- throw new RuntimeError("permute: first argument must be a tensor");
26513
- }
26786
+ const v = coerceToTensor(args[0], "permute");
26514
26787
  const orderArg = args[1];
26515
26788
  let order;
26516
26789
  if (isRuntimeTensor(orderArg)) {
@@ -26547,18 +26820,7 @@ function registerArrayManipulationFunctions() {
26547
26820
  builtinSingle((args) => {
26548
26821
  if (args.length !== 2)
26549
26822
  throw new RuntimeError("ipermute requires 2 arguments");
26550
- let v = args[0];
26551
- if (isRuntimeNumber(v)) {
26552
- v = RTV.tensor(new FloatXArray([v]), [1, 1]);
26553
- } else if (isRuntimeComplexNumber(v)) {
26554
- v = RTV.tensor(
26555
- new FloatXArray([v.re]),
26556
- [1, 1],
26557
- new FloatXArray([v.im])
26558
- );
26559
- } else if (!isRuntimeTensor(v)) {
26560
- throw new RuntimeError("ipermute: first argument must be a tensor");
26561
- }
26823
+ const v = coerceToTensor(args[0], "ipermute");
26562
26824
  const orderArg = args[1];
26563
26825
  let order;
26564
26826
  if (isRuntimeTensor(orderArg)) {
@@ -26867,18 +27129,18 @@ function registerIntrospectionFunctions() {
26867
27129
  return RTV.logical(false);
26868
27130
  })
26869
27131
  );
26870
- register(
26871
- "isscalar",
27132
+ const typePred = (name, pred) => register(
27133
+ name,
26872
27134
  builtinSingle((args) => {
26873
27135
  if (args.length !== 1)
26874
- throw new RuntimeError("isscalar requires 1 argument");
26875
- const v = args[0];
26876
- if (isRuntimeNumber(v) || isRuntimeLogical(v) || isRuntimeComplexNumber(v))
26877
- return RTV.logical(true);
26878
- if (isRuntimeTensor(v)) return RTV.logical(v.data.length === 1);
26879
- return RTV.logical(false);
27136
+ throw new RuntimeError(`${name} requires 1 argument`);
27137
+ return RTV.logical(pred(args[0]));
26880
27138
  })
26881
27139
  );
27140
+ typePred(
27141
+ "isscalar",
27142
+ (v) => isRuntimeNumber(v) || isRuntimeLogical(v) || isRuntimeComplexNumber(v) || isRuntimeTensor(v) && v.data.length === 1
27143
+ );
26882
27144
  const getShape = (v) => {
26883
27145
  if (isRuntimeNumber(v) || isRuntimeLogical(v)) return [1, 1];
26884
27146
  if (isRuntimeTensor(v))
@@ -26887,118 +27149,36 @@ function registerIntrospectionFunctions() {
26887
27149
  return v.shape ?? (v.value.length === 0 ? [0, 0] : [1, v.value.length]);
26888
27150
  return [1, 1];
26889
27151
  };
26890
- register(
26891
- "isvector",
26892
- builtinSingle((args) => {
26893
- if (args.length !== 1)
26894
- throw new RuntimeError("isvector requires 1 argument");
26895
- const shape = getShape(args[0]);
26896
- const dimsGt1 = shape.filter((d) => d > 1).length;
26897
- return RTV.logical(dimsGt1 <= 1);
26898
- })
26899
- );
26900
- register(
26901
- "isrow",
26902
- builtinSingle((args) => {
26903
- if (args.length !== 1)
26904
- throw new RuntimeError("isrow requires 1 argument");
26905
- const shape = getShape(args[0]);
26906
- return RTV.logical(shape.length === 2 && shape[0] === 1);
26907
- })
26908
- );
26909
- register(
26910
- "iscolumn",
26911
- builtinSingle((args) => {
26912
- if (args.length !== 1)
26913
- throw new RuntimeError("iscolumn requires 1 argument");
26914
- const shape = getShape(args[0]);
26915
- return RTV.logical(shape.length === 2 && shape[1] === 1);
26916
- })
26917
- );
26918
- register(
26919
- "ismatrix",
26920
- builtinSingle((args) => {
26921
- if (args.length !== 1)
26922
- throw new RuntimeError("ismatrix requires 1 argument");
26923
- const shape = getShape(args[0]);
26924
- return RTV.logical(shape.length <= 2);
26925
- })
26926
- );
26927
- register(
27152
+ typePred("isvector", (v) => {
27153
+ const shape = getShape(v);
27154
+ return shape.filter((d) => d > 1).length <= 1;
27155
+ });
27156
+ typePred("isrow", (v) => {
27157
+ const shape = getShape(v);
27158
+ return shape.length === 2 && shape[0] === 1;
27159
+ });
27160
+ typePred("iscolumn", (v) => {
27161
+ const shape = getShape(v);
27162
+ return shape.length === 2 && shape[1] === 1;
27163
+ });
27164
+ typePred("ismatrix", (v) => getShape(v).length <= 2);
27165
+ typePred(
26928
27166
  "isfloat",
26929
- builtinSingle((args) => {
26930
- if (args.length !== 1)
26931
- throw new RuntimeError("isfloat requires 1 argument");
26932
- const v = args[0];
26933
- return RTV.logical(
26934
- isRuntimeNumber(v) || isRuntimeTensor(v) || isRuntimeComplexNumber(v)
26935
- );
26936
- })
26937
- );
26938
- register(
26939
- "isinteger",
26940
- builtinSingle((args) => {
26941
- if (args.length !== 1)
26942
- throw new RuntimeError("isinteger requires 1 argument");
26943
- return RTV.logical(false);
26944
- })
27167
+ (v) => isRuntimeNumber(v) || isRuntimeTensor(v) || isRuntimeComplexNumber(v)
26945
27168
  );
26946
- register(
27169
+ typePred("isinteger", () => false);
27170
+ typePred(
26947
27171
  "isnumeric",
26948
- builtinSingle((args) => {
26949
- if (args.length !== 1)
26950
- throw new RuntimeError("isnumeric requires 1 argument");
26951
- const v = args[0];
26952
- return RTV.logical(
26953
- isRuntimeNumber(v) || isRuntimeTensor(v) || isRuntimeComplexNumber(v) || isRuntimeClassInstance(v) && v._builtinData !== void 0
26954
- );
26955
- })
27172
+ (v) => isRuntimeNumber(v) || isRuntimeTensor(v) || isRuntimeComplexNumber(v) || isRuntimeClassInstance(v) && v._builtinData !== void 0
26956
27173
  );
26957
- register(
27174
+ typePred(
26958
27175
  "islogical",
26959
- builtinSingle((args) => {
26960
- if (args.length !== 1)
26961
- throw new RuntimeError("islogical requires 1 argument");
26962
- const v = args[0];
26963
- return RTV.logical(
26964
- isRuntimeLogical(v) || isRuntimeTensor(v) && v._isLogical === true
26965
- );
26966
- })
26967
- );
26968
- register(
26969
- "ischar",
26970
- builtinSingle((args) => {
26971
- if (args.length !== 1)
26972
- throw new RuntimeError("ischar requires 1 argument");
26973
- return RTV.logical(isRuntimeChar(args[0]));
26974
- })
26975
- );
26976
- register(
26977
- "isstring",
26978
- builtinSingle((args) => {
26979
- if (args.length !== 1)
26980
- throw new RuntimeError("isstring requires 1 argument");
26981
- return RTV.logical(isRuntimeString(args[0]));
26982
- })
26983
- );
26984
- register(
26985
- "iscell",
26986
- builtinSingle((args) => {
26987
- if (args.length !== 1)
26988
- throw new RuntimeError("iscell requires 1 argument");
26989
- return RTV.logical(isRuntimeCell(args[0]));
26990
- })
26991
- );
26992
- register(
26993
- "isstruct",
26994
- builtinSingle((args) => {
26995
- if (args.length !== 1)
26996
- throw new RuntimeError("isstruct requires 1 argument");
26997
- return RTV.logical(
26998
- isRuntimeStruct(args[0]) || isRuntimeStructArray(args[0])
26999
- );
27000
- })
27176
+ (v) => isRuntimeLogical(v) || isRuntimeTensor(v) && v._isLogical === true
27001
27177
  );
27178
+ typePred("ischar", (v) => isRuntimeChar(v));
27179
+ typePred("isstring", (v) => isRuntimeString(v));
27180
+ typePred("iscell", (v) => isRuntimeCell(v));
27181
+ typePred("isstruct", (v) => isRuntimeStruct(v) || isRuntimeStructArray(v));
27002
27182
  register(
27003
27183
  "isequal",
27004
27184
  builtinSingle((args) => {
@@ -27816,9 +27996,12 @@ function registerReductionFunctions() {
27816
27996
  if (scalar2 !== null) return scalar2;
27817
27997
  if (isRuntimeTensor(v)) {
27818
27998
  if (v.data.length === 0) return RTV.logical(mode === "all");
27819
- if (v.shape[0] === 1)
27999
+ const numNonSingleton = v.shape.filter((d) => d > 1).length;
28000
+ if (numNonSingleton <= 1) {
27820
28001
  return RTV.logical(scanLogical(v.data, v.imag, mode));
27821
- return logicalAlongDim(v, 1, mode);
28002
+ }
28003
+ const firstNonSingleton = v.shape.findIndex((d) => d > 1);
28004
+ return logicalAlongDim(v, firstNonSingleton + 1, mode);
27822
28005
  }
27823
28006
  throw new RuntimeError(
27824
28007
  `${name}: argument must be numeric or logical`
@@ -30247,9 +30430,6 @@ function registerSymvar() {
30247
30430
  }
30248
30431
 
30249
30432
  // src/numbl-core/builtins/linear-algebra/norm.ts
30250
- function complexAbs(re, im) {
30251
- return Math.sqrt(re * re + im * im);
30252
- }
30253
30433
  function registerNorm() {
30254
30434
  register(
30255
30435
  "norm",
@@ -30259,7 +30439,7 @@ function registerNorm() {
30259
30439
  throw new RuntimeError("norm requires at least 1 argument");
30260
30440
  const v = args[0];
30261
30441
  if (isRuntimeNumber(v)) return RTV.num(Math.abs(v));
30262
- if (isRuntimeComplexNumber(v)) return RTV.num(complexAbs(v.re, v.im));
30442
+ if (isRuntimeComplexNumber(v)) return RTV.num(Math.hypot(v.re, v.im));
30263
30443
  if (!isRuntimeTensor(v))
30264
30444
  throw new RuntimeError("norm: argument must be numeric");
30265
30445
  const shape = v.shape;
@@ -30284,7 +30464,7 @@ function registerNorm() {
30284
30464
  if (vp === Infinity) {
30285
30465
  let m = 0;
30286
30466
  for (let i = 0; i < v.data.length; i++) {
30287
- const a = imag ? complexAbs(v.data[i], imag[i]) : Math.abs(v.data[i]);
30467
+ const a = imag ? Math.hypot(v.data[i], imag[i]) : Math.abs(v.data[i]);
30288
30468
  m = Math.max(m, a);
30289
30469
  }
30290
30470
  return RTV.num(m);
@@ -30292,14 +30472,14 @@ function registerNorm() {
30292
30472
  if (vp === -Infinity) {
30293
30473
  let m = Infinity;
30294
30474
  for (let i = 0; i < v.data.length; i++) {
30295
- const a = imag ? complexAbs(v.data[i], imag[i]) : Math.abs(v.data[i]);
30475
+ const a = imag ? Math.hypot(v.data[i], imag[i]) : Math.abs(v.data[i]);
30296
30476
  m = Math.min(m, a);
30297
30477
  }
30298
30478
  return RTV.num(m);
30299
30479
  }
30300
30480
  let s = 0;
30301
30481
  for (let i = 0; i < v.data.length; i++) {
30302
- const a = imag ? complexAbs(v.data[i], imag[i]) : Math.abs(v.data[i]);
30482
+ const a = imag ? Math.hypot(v.data[i], imag[i]) : Math.abs(v.data[i]);
30303
30483
  s += Math.pow(a, vp);
30304
30484
  }
30305
30485
  return RTV.num(Math.pow(s, 1 / vp));
@@ -30319,7 +30499,7 @@ function registerNorm() {
30319
30499
  let colSum = 0;
30320
30500
  for (let i = 0; i < rows; i++) {
30321
30501
  const idx = j * rows + i;
30322
- colSum += imag ? complexAbs(v.data[idx], imag[idx]) : Math.abs(v.data[idx]);
30502
+ colSum += imag ? Math.hypot(v.data[idx], imag[idx]) : Math.abs(v.data[idx]);
30323
30503
  }
30324
30504
  maxColSum = Math.max(maxColSum, colSum);
30325
30505
  }
@@ -30331,7 +30511,7 @@ function registerNorm() {
30331
30511
  let rowSum = 0;
30332
30512
  for (let j = 0; j < cols; j++) {
30333
30513
  const idx = j * rows + i;
30334
- rowSum += imag ? complexAbs(v.data[idx], imag[idx]) : Math.abs(v.data[idx]);
30514
+ rowSum += imag ? Math.hypot(v.data[idx], imag[idx]) : Math.abs(v.data[idx]);
30335
30515
  }
30336
30516
  maxRowSum = Math.max(maxRowSum, rowSum);
30337
30517
  }
@@ -30462,23 +30642,11 @@ function registerQr() {
30462
30642
  check: (argTypes, nargout) => {
30463
30643
  if (nargout < 1 || nargout > 2 || argTypes.length < 1 || argTypes.length > 2)
30464
30644
  return null;
30465
- const econ = parseEconArg(argTypes[1]);
30466
- if (econ === null) return null;
30467
- const A = argTypes[0];
30468
- const cpx = A.kind === "Tensor" && A.isComplex;
30469
- if (nargout === 1) {
30470
- if (isFullyUnknown(A)) return out(unknownMatrix());
30471
- if (isNum(A) === true) return out(matrix([1, 1]));
30472
- if (isTensor(A) !== true) return null;
30473
- return out(unknownMatrix(cpx || void 0));
30474
- }
30475
- if (isFullyUnknown(A)) return out(unknownMatrix(), unknownMatrix());
30476
- if (isNum(A) === true) return out(matrix([1, 1]), matrix([1, 1]));
30477
- if (isTensor(A) !== true) return null;
30478
- return out(
30479
- unknownMatrix(cpx || void 0),
30480
- unknownMatrix(cpx || void 0)
30481
- );
30645
+ if (parseEconArg(argTypes[1]) === null) return null;
30646
+ if (!isMatrixLike(argTypes[0])) return null;
30647
+ const cpx = argTypes[0].kind === "Tensor" && argTypes[0].isComplex || void 0;
30648
+ if (nargout === 1) return out(unknownMatrix(cpx));
30649
+ return out(unknownMatrix(cpx), unknownMatrix(cpx));
30482
30650
  },
30483
30651
  apply: (args, nargout) => {
30484
30652
  if (args.length < 1)
@@ -30495,13 +30663,7 @@ function registerQr() {
30495
30663
  }
30496
30664
  if (!isRuntimeTensor(A))
30497
30665
  throw new RuntimeError("qr: argument must be numeric");
30498
- let econ = false;
30499
- if (args.length >= 2) {
30500
- const opt = args[1];
30501
- if (isRuntimeNumber(opt) && opt === 0) econ = true;
30502
- else if (isRuntimeString(opt) && opt.replace(/^['"]|['"]$/g, "").toLowerCase() === "econ")
30503
- econ = true;
30504
- }
30666
+ const econ = parseEconArgRuntime(args[1]);
30505
30667
  const [m, n] = tensorSize2D(A);
30506
30668
  const k = Math.min(m, n);
30507
30669
  if (A.imag) {
@@ -30752,10 +30914,8 @@ function registerInv() {
30752
30914
  check: (argTypes, nargout) => {
30753
30915
  if (argTypes.length !== 1 || nargout !== 1) return null;
30754
30916
  const A = argTypes[0];
30755
- if (isFullyUnknown(A)) return out(unknownMatrix());
30756
- if (isComplex(A) === true || isNum(A) === true) return out(A);
30757
- if (isTensor(A) !== true) return null;
30758
- return out(A);
30917
+ if (!isMatrixLike(A)) return null;
30918
+ return out(A.kind === "Unknown" ? unknownMatrix() : A);
30759
30919
  },
30760
30920
  apply: (args) => {
30761
30921
  if (args.length < 1) throw new RuntimeError("inv requires 1 argument");
@@ -30890,10 +31050,7 @@ function registerDet() {
30890
31050
  {
30891
31051
  check: (argTypes, nargout) => {
30892
31052
  if (argTypes.length !== 1 || nargout !== 1) return null;
30893
- const A = argTypes[0];
30894
- if (isFullyUnknown(A)) return out(IType.num());
30895
- if (isNum(A) === true || A.kind === "Boolean") return out(IType.num());
30896
- if (isTensor(A) !== true) return null;
31053
+ if (!isMatrixLike(argTypes[0])) return null;
30897
31054
  return out(IType.num());
30898
31055
  },
30899
31056
  apply: (args) => {
@@ -30919,10 +31076,7 @@ function registerDet() {
30919
31076
  {
30920
31077
  check: (argTypes, nargout) => {
30921
31078
  if (argTypes.length !== 1 || nargout !== 1) return null;
30922
- const A = argTypes[0];
30923
- if (isFullyUnknown(A)) return out(IType.num());
30924
- if (isNum(A) === true || A.kind === "Boolean") return out(IType.num());
30925
- if (isTensor(A) !== true) return null;
31079
+ if (!isMatrixLike(argTypes[0])) return null;
30926
31080
  return out(IType.num());
30927
31081
  },
30928
31082
  apply: (args) => {
@@ -31012,20 +31166,9 @@ function registerSvd() {
31012
31166
  check: (argTypes, nargout) => {
31013
31167
  if (nargout < 1 || nargout > 3 || argTypes.length < 1 || argTypes.length > 2)
31014
31168
  return null;
31015
- const econ = parseEconArg(argTypes[1]);
31016
- if (econ === null) return null;
31017
- const A = argTypes[0];
31018
- if (nargout === 1) {
31019
- if (isFullyUnknown(A)) return out(unknownMatrix());
31020
- if (isNum(A) === true) return out(matrix([1, 1]));
31021
- if (isTensor(A) !== true) return null;
31022
- return out(unknownMatrix());
31023
- }
31024
- if (isFullyUnknown(A))
31025
- return out(unknownMatrix(), unknownMatrix(), unknownMatrix());
31026
- if (isNum(A) === true)
31027
- return out(matrix([1, 1]), matrix([1, 1]), matrix([1, 1]));
31028
- if (isTensor(A) !== true) return null;
31169
+ if (parseEconArg(argTypes[1]) === null) return null;
31170
+ if (!isMatrixLike(argTypes[0])) return null;
31171
+ if (nargout === 1) return out(unknownMatrix());
31029
31172
  return out(unknownMatrix(), unknownMatrix(), unknownMatrix());
31030
31173
  },
31031
31174
  apply: (args, nargout) => {
@@ -31044,15 +31187,7 @@ function registerSvd() {
31044
31187
  }
31045
31188
  if (!isRuntimeTensor(A))
31046
31189
  throw new RuntimeError("svd: argument must be numeric");
31047
- let econ = false;
31048
- if (args.length >= 2) {
31049
- const opt = args[1];
31050
- if (isRuntimeNumber(opt) && opt === 0) econ = true;
31051
- else if (isRuntimeString(opt) && opt.toLowerCase() === "econ")
31052
- econ = true;
31053
- else if (isRuntimeChar(opt) && opt.value.toLowerCase() === "econ")
31054
- econ = true;
31055
- }
31190
+ const econ = parseEconArgRuntime(args[1]);
31056
31191
  const [m, n] = tensorSize2D(A);
31057
31192
  const k = Math.min(m, n);
31058
31193
  if (A.imag) {
@@ -31079,20 +31214,11 @@ function registerSvd() {
31079
31214
  [m, uCols],
31080
31215
  new FloatXArray(lapackResult2.UIm)
31081
31216
  );
31082
- let S;
31083
- if (econ) {
31084
- const S_data = new FloatXArray(k * k);
31085
- for (let i = 0; i < k; i++) {
31086
- S_data[colMajorIndex(i, i, k)] = lapackResult2.S[i];
31087
- }
31088
- S = RTV.tensor(S_data, [k, k]);
31089
- } else {
31090
- const S_data = new FloatXArray(m * n);
31091
- for (let i = 0; i < k; i++) {
31092
- S_data[colMajorIndex(i, i, m)] = lapackResult2.S[i];
31093
- }
31094
- S = RTV.tensor(S_data, [m, n]);
31095
- }
31217
+ const S = buildDiagMatrix(
31218
+ lapackResult2.S,
31219
+ void 0,
31220
+ econ ? k : [m, n]
31221
+ );
31096
31222
  const V = RTV.tensor(
31097
31223
  new FloatXArray(lapackResult2.VRe),
31098
31224
  [n, vCols],
@@ -31108,20 +31234,11 @@ function registerSvd() {
31108
31234
  const uCols = econ ? k : m;
31109
31235
  const vCols = econ ? k : n;
31110
31236
  const U = RTV.tensor(new FloatXArray(lapackResult.U), [m, uCols]);
31111
- let S;
31112
- if (econ) {
31113
- const S_data = new FloatXArray(k * k);
31114
- for (let i = 0; i < k; i++) {
31115
- S_data[colMajorIndex(i, i, k)] = lapackResult.S[i];
31116
- }
31117
- S = RTV.tensor(S_data, [k, k]);
31118
- } else {
31119
- const S_data = new FloatXArray(m * n);
31120
- for (let i = 0; i < k; i++) {
31121
- S_data[colMajorIndex(i, i, m)] = lapackResult.S[i];
31122
- }
31123
- S = RTV.tensor(S_data, [m, n]);
31124
- }
31237
+ const S = buildDiagMatrix(
31238
+ lapackResult.S,
31239
+ void 0,
31240
+ econ ? k : [m, n]
31241
+ );
31125
31242
  const V = RTV.tensor(new FloatXArray(lapackResult.V), [n, vCols]);
31126
31243
  return [U, S, V];
31127
31244
  }
@@ -31595,24 +31712,10 @@ function registerKron() {
31595
31712
 
31596
31713
  // src/numbl-core/builtins/linear-algebra/eig.ts
31597
31714
  function parseEigOptions(argTypes) {
31598
- let balance = true;
31599
- let outputForm = "matrix";
31600
31715
  for (let i = 1; i < argTypes.length; i++) {
31601
- const arg = argTypes[i];
31602
- if (isFullyUnknown(arg)) {
31603
- balance = "unknown";
31604
- outputForm = "unknown";
31605
- continue;
31606
- }
31607
- if (arg.kind === "String" || arg.kind === "Char") {
31608
- balance = "unknown";
31609
- outputForm = "unknown";
31610
- continue;
31611
- } else {
31612
- return null;
31613
- }
31716
+ if (!isOptionalStringArg(argTypes[i])) return false;
31614
31717
  }
31615
- return { balance, outputForm };
31718
+ return true;
31616
31719
  }
31617
31720
  function parseEigOptionsRuntime(args) {
31618
31721
  let balance = true;
@@ -31645,49 +31748,12 @@ function registerEig() {
31645
31748
  check: (argTypes, nargout) => {
31646
31749
  if (nargout < 1 || nargout > 3) return null;
31647
31750
  if (argTypes.length < 1 || argTypes.length > 3) return null;
31648
- const opts = parseEigOptions(argTypes);
31649
- if (opts === null) return null;
31650
- const A = argTypes[0];
31651
- if (nargout === 1) {
31652
- if (isFullyUnknown(A)) return out(unknownMatrix());
31653
- if (isNum(A) === true) return out(matrix([1, 1], true));
31654
- if (isTensor(A) !== true) return null;
31655
- return out(unknownMatrix(true));
31656
- }
31657
- if (nargout === 2) {
31658
- if (isFullyUnknown(A)) return out(unknownMatrix(), unknownMatrix());
31659
- if (isNum(A) === true)
31660
- return out(matrix([1, 1], true), matrix([1, 1], true));
31661
- if (isTensor(A) !== true) return null;
31662
- if (opts.outputForm === "vector") {
31663
- return out(unknownMatrix(true), unknownMatrix(true));
31664
- }
31665
- return out(unknownMatrix(true), unknownMatrix(true));
31666
- }
31667
- if (nargout === 3) {
31668
- if (isFullyUnknown(A))
31669
- return out(unknownMatrix(), unknownMatrix(), unknownMatrix());
31670
- if (isNum(A) === true)
31671
- return out(
31672
- matrix([1, 1], true),
31673
- matrix([1, 1], true),
31674
- matrix([1, 1], true)
31675
- );
31676
- if (isTensor(A) !== true) return null;
31677
- if (opts.outputForm === "vector") {
31678
- return out(
31679
- unknownMatrix(true),
31680
- unknownMatrix(true),
31681
- unknownMatrix(true)
31682
- );
31683
- }
31684
- return out(
31685
- unknownMatrix(true),
31686
- unknownMatrix(true),
31687
- unknownMatrix(true)
31688
- );
31689
- }
31690
- return null;
31751
+ if (!parseEigOptions(argTypes)) return null;
31752
+ if (!isMatrixLike(argTypes[0])) return null;
31753
+ const c = unknownMatrix(true);
31754
+ if (nargout === 1) return out(c);
31755
+ if (nargout === 2) return out(c, c);
31756
+ return out(c, c, c);
31691
31757
  },
31692
31758
  apply: (args, nargout) => {
31693
31759
  if (args.length < 1)
@@ -31733,80 +31799,13 @@ function registerEig() {
31733
31799
  );
31734
31800
  }
31735
31801
  const { wRe, wIm, VLRe, VLIm, VRRe, VRIm } = result2;
31736
- let hasComplex2 = false;
31737
- for (let i = 0; i < n; i++) {
31738
- if (Math.abs(wIm[i]) > 0) {
31739
- hasComplex2 = true;
31740
- break;
31741
- }
31742
- }
31743
31802
  if (nargout === 1) {
31744
- if (hasComplex2) {
31745
- return RTV.tensor(
31746
- new FloatXArray(wRe),
31747
- [n, 1],
31748
- new FloatXArray(wIm)
31749
- );
31750
- }
31751
- return RTV.tensor(new FloatXArray(wRe), [n, 1]);
31752
- }
31753
- let Vout2;
31754
- if (computeVR && VRRe && VRIm) {
31755
- if (hasComplex2) {
31756
- Vout2 = RTV.tensor(
31757
- new FloatXArray(VRRe),
31758
- [n, n],
31759
- new FloatXArray(VRIm)
31760
- );
31761
- } else {
31762
- Vout2 = RTV.tensor(new FloatXArray(VRRe), [n, n]);
31763
- }
31764
- } else {
31765
- Vout2 = RTV.tensor(new FloatXArray(n * n), [n, n]);
31766
- }
31767
- let Dout2;
31768
- if (outputForm === "vector") {
31769
- if (hasComplex2) {
31770
- Dout2 = RTV.tensor(
31771
- new FloatXArray(wRe),
31772
- [n, 1],
31773
- new FloatXArray(wIm)
31774
- );
31775
- } else {
31776
- Dout2 = RTV.tensor(new FloatXArray(wRe), [n, 1]);
31777
- }
31778
- } else {
31779
- const dReal = new FloatXArray(n * n);
31780
- for (let i = 0; i < n; i++) {
31781
- dReal[colMajorIndex(i, i, n)] = wRe[i];
31782
- }
31783
- if (hasComplex2) {
31784
- const dImag = new FloatXArray(n * n);
31785
- for (let i = 0; i < n; i++) {
31786
- dImag[colMajorIndex(i, i, n)] = wIm[i];
31787
- }
31788
- Dout2 = RTV.tensor(dReal, [n, n], dImag);
31789
- } else {
31790
- Dout2 = RTV.tensor(dReal, [n, n]);
31791
- }
31792
- }
31793
- if (nargout === 2) {
31794
- return [Vout2, Dout2];
31795
- }
31796
- let Wout2;
31797
- if (computeVL && VLRe && VLIm) {
31798
- if (hasComplex2) {
31799
- Wout2 = RTV.tensor(
31800
- new FloatXArray(VLRe),
31801
- [n, n],
31802
- new FloatXArray(VLIm)
31803
- );
31804
- } else {
31805
- Wout2 = RTV.tensor(new FloatXArray(VLRe), [n, n]);
31806
- }
31807
- } else {
31808
- Wout2 = RTV.tensor(new FloatXArray(n * n), [n, n]);
31803
+ return maybeComplexTensor(wRe, [n, 1], wIm);
31809
31804
  }
31805
+ const Vout2 = computeVR && VRRe && VRIm ? maybeComplexTensor(VRRe, [n, n], VRIm) : RTV.tensor(new FloatXArray(n * n), [n, n]);
31806
+ const Dout2 = outputForm === "vector" ? maybeComplexTensor(wRe, [n, 1], wIm) : buildDiagMatrix(wRe, wIm, n);
31807
+ if (nargout === 2) return [Vout2, Dout2];
31808
+ const Wout2 = computeVL && VLRe && VLIm ? maybeComplexTensor(VLRe, [n, n], VLIm) : RTV.tensor(new FloatXArray(n * n), [n, n]);
31810
31809
  return [Vout2, Dout2, Wout2];
31811
31810
  }
31812
31811
  const result = eigLapack(
@@ -31820,88 +31819,19 @@ function registerEig() {
31820
31819
  throw new RuntimeError("eig: LAPACK bridge not available");
31821
31820
  }
31822
31821
  const { wr, wi, VL, VR } = result;
31823
- let hasComplex = false;
31824
- for (let i = 0; i < n; i++) {
31825
- if (Math.abs(wi[i]) > 0) {
31826
- hasComplex = true;
31827
- break;
31828
- }
31829
- }
31822
+ const hasComplex = wi.some((v) => v !== 0);
31830
31823
  if (nargout === 1) {
31831
- if (hasComplex) {
31832
- return RTV.tensor(new FloatXArray(wr), [n, 1], new FloatXArray(wi));
31833
- }
31834
- return RTV.tensor(new FloatXArray(wr), [n, 1]);
31835
- }
31836
- let Vout;
31837
- if (computeVR && VR) {
31838
- Vout = buildEigenvectorMatrix(VR, wi, n, hasComplex);
31839
- } else {
31840
- Vout = RTV.tensor(new FloatXArray(n * n), [n, n]);
31841
- }
31842
- let Dout;
31843
- if (outputForm === "vector") {
31844
- if (hasComplex) {
31845
- Dout = RTV.tensor(new FloatXArray(wr), [n, 1], new FloatXArray(wi));
31846
- } else {
31847
- Dout = RTV.tensor(new FloatXArray(wr), [n, 1]);
31848
- }
31849
- } else {
31850
- const dReal = new FloatXArray(n * n);
31851
- for (let i = 0; i < n; i++) {
31852
- dReal[colMajorIndex(i, i, n)] = wr[i];
31853
- }
31854
- if (hasComplex) {
31855
- const dImag = new FloatXArray(n * n);
31856
- for (let i = 0; i < n; i++) {
31857
- dImag[colMajorIndex(i, i, n)] = wi[i];
31858
- }
31859
- Dout = RTV.tensor(dReal, [n, n], dImag);
31860
- } else {
31861
- Dout = RTV.tensor(dReal, [n, n]);
31862
- }
31863
- }
31864
- if (nargout === 2) {
31865
- return [Vout, Dout];
31866
- }
31867
- let Wout;
31868
- if (computeVL && VL) {
31869
- Wout = buildEigenvectorMatrix(VL, wi, n, hasComplex);
31870
- } else {
31871
- Wout = RTV.tensor(new FloatXArray(n * n), [n, n]);
31824
+ return maybeComplexTensor(wr, [n, 1], wi);
31872
31825
  }
31826
+ const Vout = computeVR && VR ? buildEigenvectorMatrix(VR, wi, n, hasComplex) : RTV.tensor(new FloatXArray(n * n), [n, n]);
31827
+ const Dout = outputForm === "vector" ? maybeComplexTensor(wr, [n, 1], wi) : buildDiagMatrix(wr, wi, n);
31828
+ if (nargout === 2) return [Vout, Dout];
31829
+ const Wout = computeVL && VL ? buildEigenvectorMatrix(VL, wi, n, hasComplex) : RTV.tensor(new FloatXArray(n * n), [n, n]);
31873
31830
  return [Vout, Dout, Wout];
31874
31831
  }
31875
31832
  }
31876
31833
  ]);
31877
31834
  }
31878
- function buildEigenvectorMatrix(packedV, wi, n, hasComplex) {
31879
- if (!hasComplex) {
31880
- return RTV.tensor(new FloatXArray(packedV), [n, n]);
31881
- }
31882
- const realPart = new FloatXArray(n * n);
31883
- const imagPart = new FloatXArray(n * n);
31884
- let j = 0;
31885
- while (j < n) {
31886
- if (Math.abs(wi[j]) === 0) {
31887
- for (let i = 0; i < n; i++) {
31888
- realPart[colMajorIndex(i, j, n)] = packedV[colMajorIndex(i, j, n)];
31889
- }
31890
- j++;
31891
- } else {
31892
- for (let i = 0; i < n; i++) {
31893
- const re = packedV[colMajorIndex(i, j, n)];
31894
- const im = packedV[colMajorIndex(i, j + 1, n)];
31895
- realPart[colMajorIndex(i, j, n)] = re;
31896
- imagPart[colMajorIndex(i, j, n)] = im;
31897
- realPart[colMajorIndex(i, j + 1, n)] = re;
31898
- imagPart[colMajorIndex(i, j + 1, n)] = -im;
31899
- }
31900
- j += 2;
31901
- }
31902
- }
31903
- return RTV.tensor(realPart, [n, n], imagPart);
31904
- }
31905
31835
 
31906
31836
  // src/numbl-core/builtins/linear-algebra/cond.ts
31907
31837
  function applyBuiltin2(name, args, nargout) {
@@ -31926,8 +31856,8 @@ function registerCond() {
31926
31856
  let p = 2;
31927
31857
  if (args.length >= 2) {
31928
31858
  const pArg = args[1];
31929
- if (isRuntimeString(pArg)) {
31930
- const pStr = pArg.replace(/^['"]|['"]$/g, "").toLowerCase();
31859
+ if (isRuntimeString(pArg) || isRuntimeChar(pArg)) {
31860
+ const pStr = parseStringArgLower(pArg);
31931
31861
  if (pStr === "fro") {
31932
31862
  p = "fro";
31933
31863
  } else {
@@ -32241,31 +32171,14 @@ function registerLu() {
32241
32171
  check: (argTypes, nargout) => {
32242
32172
  if (nargout < 1 || nargout > 3) return null;
32243
32173
  if (argTypes.length < 1 || argTypes.length > 2) return null;
32244
- const A = argTypes[0];
32245
- if (argTypes.length === 2) {
32246
- const fmt = argTypes[1];
32247
- if (!isFullyUnknown(fmt) && fmt.kind !== "String" && fmt.kind !== "Char")
32248
- return null;
32249
- }
32250
- if (nargout === 1) {
32251
- if (isFullyUnknown(A)) return out(unknownMatrix());
32252
- if (isNum(A) === true) return out(matrix([1, 1]));
32253
- if (isTensor(A) !== true) return null;
32254
- return out(unknownMatrix());
32255
- }
32256
- if (nargout === 2) {
32257
- if (isFullyUnknown(A)) return out(unknownMatrix(), unknownMatrix());
32258
- if (isNum(A) === true) return out(matrix([1, 1]), matrix([1, 1]));
32259
- if (isTensor(A) !== true) return null;
32260
- return out(unknownMatrix(), unknownMatrix());
32261
- }
32262
- if (isFullyUnknown(A))
32263
- return out(unknownMatrix(), unknownMatrix(), unknownMatrix());
32264
- if (isNum(A) === true)
32265
- return out(matrix([1, 1]), matrix([1, 1]), matrix([1, 1]));
32266
- if (isTensor(A) !== true || A.kind === "Tensor" && A.isComplex)
32174
+ if (!isOptionalStringArg(argTypes[1])) return null;
32175
+ if (!isMatrixLike(argTypes[0])) return null;
32176
+ if (nargout === 3 && argTypes[0].kind === "Tensor" && argTypes[0].isComplex)
32267
32177
  return null;
32268
- return out(unknownMatrix(), unknownMatrix(), unknownMatrix());
32178
+ const m = unknownMatrix();
32179
+ if (nargout === 1) return out(m);
32180
+ if (nargout === 2) return out(m, m);
32181
+ return out(m, m, m);
32269
32182
  },
32270
32183
  apply: (args, nargout) => {
32271
32184
  if (args.length < 1)
@@ -32460,21 +32373,9 @@ function registerChol() {
32460
32373
  check: (argTypes, nargout) => {
32461
32374
  if (nargout < 1 || nargout > 2) return null;
32462
32375
  if (argTypes.length < 1 || argTypes.length > 2) return null;
32463
- const A = argTypes[0];
32464
- if (argTypes.length === 2) {
32465
- const tri = argTypes[1];
32466
- if (!isFullyUnknown(tri) && tri.kind !== "String" && tri.kind !== "Char")
32467
- return null;
32468
- }
32469
- if (nargout === 1) {
32470
- if (isFullyUnknown(A)) return out(unknownMatrix());
32471
- if (isNum(A) === true) return out(matrix([1, 1]));
32472
- if (isTensor(A) !== true) return null;
32473
- return out(unknownMatrix());
32474
- }
32475
- if (isFullyUnknown(A)) return out(unknownMatrix(), IType.num());
32476
- if (isNum(A) === true) return out(matrix([1, 1]), IType.num());
32477
- if (isTensor(A) !== true) return null;
32376
+ if (!isOptionalStringArg(argTypes[1])) return null;
32377
+ if (!isMatrixLike(argTypes[0])) return null;
32378
+ if (nargout === 1) return out(unknownMatrix());
32478
32379
  return out(unknownMatrix(), IType.num());
32479
32380
  },
32480
32381
  apply: (args, nargout) => {
@@ -32648,48 +32549,14 @@ function pinvFallback(data, m, n) {
32648
32549
  }
32649
32550
  const augmented = new FloatXArray(n * (n + m));
32650
32551
  for (let i = 0; i < n; i++) {
32651
- for (let j = 0; j < n; j++) {
32652
- augmented[j * n + i] = ATA[j * n + i];
32653
- }
32654
- for (let j = 0; j < m; j++) {
32655
- augmented[(n + j) * n + i] = AT[j * n + i];
32656
- }
32657
- }
32658
- for (let col = 0; col < n; col++) {
32659
- let maxVal = Math.abs(augmented[col * n + col]);
32660
- let maxRow = col;
32661
- for (let row = col + 1; row < n; row++) {
32662
- const val = Math.abs(augmented[col * n + row]);
32663
- if (val > maxVal) {
32664
- maxVal = val;
32665
- maxRow = row;
32666
- }
32667
- }
32668
- if (maxRow !== col) {
32669
- for (let j = 0; j < n + m; j++) {
32670
- const tmp = augmented[j * n + col];
32671
- augmented[j * n + col] = augmented[j * n + maxRow];
32672
- augmented[j * n + maxRow] = tmp;
32673
- }
32674
- }
32675
- const pivot = augmented[col * n + col];
32676
- if (Math.abs(pivot) < 1e-14) continue;
32677
- for (let j = 0; j < n + m; j++) {
32678
- augmented[j * n + col] /= pivot;
32679
- }
32680
- for (let row = 0; row < n; row++) {
32681
- if (row === col) continue;
32682
- const factor = augmented[col * n + row];
32683
- for (let j = 0; j < n + m; j++) {
32684
- augmented[j * n + row] -= factor * augmented[j * n + col];
32685
- }
32686
- }
32552
+ for (let j = 0; j < n; j++) augmented[j * n + i] = ATA[j * n + i];
32553
+ for (let j = 0; j < m; j++) augmented[(n + j) * n + i] = AT[j * n + i];
32687
32554
  }
32555
+ gaussJordanEliminate(augmented, n, n + m);
32688
32556
  const result = new FloatXArray(n * m);
32689
32557
  for (let i = 0; i < n; i++) {
32690
- for (let j = 0; j < m; j++) {
32558
+ for (let j = 0; j < m; j++)
32691
32559
  result[j * n + i] = augmented[(n + j) * n + i];
32692
- }
32693
32560
  }
32694
32561
  return RTV.tensor(result, [n, m]);
32695
32562
  } else {
@@ -32705,54 +32572,20 @@ function pinvFallback(data, m, n) {
32705
32572
  }
32706
32573
  const augmented = new FloatXArray(m * 2 * m);
32707
32574
  for (let i = 0; i < m; i++) {
32708
- for (let j = 0; j < m; j++) {
32709
- augmented[j * m + i] = AAT[j * m + i];
32710
- }
32575
+ for (let j = 0; j < m; j++) augmented[j * m + i] = AAT[j * m + i];
32711
32576
  augmented[(m + i) * m + i] = 1;
32712
32577
  }
32713
- for (let col = 0; col < m; col++) {
32714
- let maxVal = Math.abs(augmented[col * m + col]);
32715
- let maxRow = col;
32716
- for (let row = col + 1; row < m; row++) {
32717
- const val = Math.abs(augmented[col * m + row]);
32718
- if (val > maxVal) {
32719
- maxVal = val;
32720
- maxRow = row;
32721
- }
32722
- }
32723
- if (maxRow !== col) {
32724
- for (let j = 0; j < 2 * m; j++) {
32725
- const tmp = augmented[j * m + col];
32726
- augmented[j * m + col] = augmented[j * m + maxRow];
32727
- augmented[j * m + maxRow] = tmp;
32728
- }
32729
- }
32730
- const pivot = augmented[col * m + col];
32731
- if (Math.abs(pivot) < 1e-14) continue;
32732
- for (let j = 0; j < 2 * m; j++) {
32733
- augmented[j * m + col] /= pivot;
32734
- }
32735
- for (let row = 0; row < m; row++) {
32736
- if (row === col) continue;
32737
- const factor = augmented[col * m + row];
32738
- for (let j = 0; j < 2 * m; j++) {
32739
- augmented[j * m + row] -= factor * augmented[j * m + col];
32740
- }
32741
- }
32742
- }
32578
+ gaussJordanEliminate(augmented, m, 2 * m);
32743
32579
  const AATinv = new FloatXArray(m * m);
32744
32580
  for (let i = 0; i < m; i++) {
32745
- for (let j = 0; j < m; j++) {
32581
+ for (let j = 0; j < m; j++)
32746
32582
  AATinv[j * m + i] = augmented[(m + j) * m + i];
32747
- }
32748
32583
  }
32749
32584
  const result = new FloatXArray(n * m);
32750
32585
  for (let i = 0; i < n; i++) {
32751
32586
  for (let j = 0; j < m; j++) {
32752
32587
  let sum = 0;
32753
- for (let k = 0; k < m; k++) {
32754
- sum += AT[k * n + i] * AATinv[j * m + k];
32755
- }
32588
+ for (let k = 0; k < m; k++) sum += AT[k * n + i] * AATinv[j * m + k];
32756
32589
  result[j * n + i] = sum;
32757
32590
  }
32758
32591
  }
@@ -32807,8 +32640,8 @@ function applyReal(A, B, n, nargout, computeEigvecs) {
32807
32640
  break;
32808
32641
  }
32809
32642
  }
32810
- const Vout = buildEigenvectorMatrix2(V, alphai, n, hasComplex);
32811
- const Wout = buildEigenvectorMatrix2(W, alphai, n, hasComplex);
32643
+ const Vout = buildEigenvectorMatrix(V, alphai, n, hasComplex);
32644
+ const Wout = buildEigenvectorMatrix(W, alphai, n, hasComplex);
32812
32645
  return [AAout, BBout, Qout, Zout, Vout, Wout];
32813
32646
  }
32814
32647
  function applyComplex(A, B, n, nargout, computeEigvecs) {
@@ -32860,44 +32693,19 @@ function registerQz() {
32860
32693
  check: (argTypes, nargout) => {
32861
32694
  if (nargout !== 4 && nargout !== 6) return null;
32862
32695
  if (argTypes.length < 2 || argTypes.length > 3) return null;
32863
- const A = argTypes[0];
32864
- const B = argTypes[1];
32865
- if (argTypes.length === 3) {
32866
- const mode = argTypes[2];
32867
- if (!isFullyUnknown(mode) && mode.kind !== "String" && mode.kind !== "Char")
32868
- return null;
32869
- }
32870
- if (!isFullyUnknown(A) && isTensor(A) !== true) return null;
32871
- if (!isFullyUnknown(B) && isTensor(B) !== true) return null;
32872
- if (nargout === 4) {
32873
- return out(
32874
- unknownMatrix(true),
32875
- unknownMatrix(true),
32876
- unknownMatrix(true),
32877
- unknownMatrix(true)
32878
- );
32879
- }
32880
- return out(
32881
- unknownMatrix(true),
32882
- unknownMatrix(true),
32883
- unknownMatrix(true),
32884
- unknownMatrix(true),
32885
- unknownMatrix(true),
32886
- unknownMatrix(true)
32887
- );
32696
+ if (!isOptionalStringArg(argTypes[2])) return null;
32697
+ if (!isMatrixLike(argTypes[0]) || !isMatrixLike(argTypes[1]))
32698
+ return null;
32699
+ const c = unknownMatrix(true);
32700
+ if (nargout === 4) return out(c, c, c, c);
32701
+ return out(c, c, c, c, c, c);
32888
32702
  },
32889
32703
  apply: (args, nargout) => {
32890
32704
  if (args.length < 2)
32891
32705
  throw new RuntimeError("qz requires at least 2 arguments");
32892
32706
  let mode = "complex";
32893
32707
  if (args.length >= 3) {
32894
- const modeArg = args[2];
32895
- let modeStr = "";
32896
- if (isRuntimeString(modeArg)) {
32897
- modeStr = modeArg.replace(/^['"]|['"]$/g, "").toLowerCase();
32898
- } else if (isRuntimeChar(modeArg)) {
32899
- modeStr = modeArg.value.replace(/^['"]|['"]$/g, "").toLowerCase();
32900
- }
32708
+ const modeStr = parseStringArgLower(args[2]);
32901
32709
  if (modeStr === "complex") mode = "complex";
32902
32710
  else if (modeStr === "real") mode = "real";
32903
32711
  else throw new RuntimeError(`qz: unknown mode '${modeStr}'`);
@@ -32923,33 +32731,6 @@ function registerQz() {
32923
32731
  }
32924
32732
  ]);
32925
32733
  }
32926
- function buildEigenvectorMatrix2(packedV, wi, n, hasComplex) {
32927
- if (!hasComplex) {
32928
- return RTV.tensor(new FloatXArray(packedV), [n, n]);
32929
- }
32930
- const realPart = new FloatXArray(n * n);
32931
- const imagPart = new FloatXArray(n * n);
32932
- let j = 0;
32933
- while (j < n) {
32934
- if (Math.abs(wi[j]) === 0) {
32935
- for (let i = 0; i < n; i++) {
32936
- realPart[colMajorIndex(i, j, n)] = packedV[colMajorIndex(i, j, n)];
32937
- }
32938
- j++;
32939
- } else {
32940
- for (let i = 0; i < n; i++) {
32941
- const re = packedV[colMajorIndex(i, j, n)];
32942
- const im = packedV[colMajorIndex(i, j + 1, n)];
32943
- realPart[colMajorIndex(i, j, n)] = re;
32944
- imagPart[colMajorIndex(i, j, n)] = im;
32945
- realPart[colMajorIndex(i, j + 1, n)] = re;
32946
- imagPart[colMajorIndex(i, j + 1, n)] = -im;
32947
- }
32948
- j += 2;
32949
- }
32950
- }
32951
- return RTV.tensor(realPart, [n, n], imagPart);
32952
- }
32953
32734
 
32954
32735
  // src/numbl-core/builtins/linear-algebra/register-linear-algebra-functions.ts
32955
32736
  function registerLinearAlgebraFunctions() {
@@ -33039,51 +32820,54 @@ function registerMiscFunctions() {
33039
32820
  );
33040
32821
  register(
33041
32822
  "struct",
33042
- builtinSingle((args) => {
33043
- if (args.length === 0) return RTV.struct(/* @__PURE__ */ new Map());
33044
- if (args.length % 2 !== 0)
33045
- throw new RuntimeError("struct: requires field-value pairs");
33046
- const fieldNames = [];
33047
- const fieldValues = [];
33048
- let hasCell = false;
33049
- let arrayLen = -1;
33050
- for (let i = 0; i < args.length; i += 2) {
33051
- const name = toString(args[i]);
33052
- const val = args[i + 1];
33053
- fieldNames.push(name);
33054
- fieldValues.push(val);
33055
- if (isRuntimeCell(val)) {
33056
- hasCell = true;
33057
- const len = val.data.length;
33058
- if (arrayLen === -1) arrayLen = len;
33059
- else if (len !== arrayLen)
33060
- throw new RuntimeError(
33061
- "struct: cell array values must have the same length"
33062
- );
32823
+ builtinSingle(
32824
+ (args) => {
32825
+ if (args.length === 0) return RTV.struct(/* @__PURE__ */ new Map());
32826
+ if (args.length % 2 !== 0)
32827
+ throw new RuntimeError("struct: requires field-value pairs");
32828
+ const fieldNames = [];
32829
+ const fieldValues = [];
32830
+ let hasCell = false;
32831
+ let arrayLen = -1;
32832
+ for (let i = 0; i < args.length; i += 2) {
32833
+ const name = toString(args[i]);
32834
+ const val = args[i + 1];
32835
+ fieldNames.push(name);
32836
+ fieldValues.push(val);
32837
+ if (isRuntimeCell(val)) {
32838
+ hasCell = true;
32839
+ const len = val.data.length;
32840
+ if (arrayLen === -1) arrayLen = len;
32841
+ else if (len !== arrayLen)
32842
+ throw new RuntimeError(
32843
+ "struct: cell array values must have the same length"
32844
+ );
32845
+ }
33063
32846
  }
33064
- }
33065
- if (!hasCell) {
33066
- const fields = /* @__PURE__ */ new Map();
33067
- for (let i = 0; i < fieldNames.length; i++) {
33068
- fields.set(fieldNames[i], fieldValues[i]);
32847
+ if (!hasCell) {
32848
+ const fields = /* @__PURE__ */ new Map();
32849
+ for (let i = 0; i < fieldNames.length; i++) {
32850
+ fields.set(fieldNames[i], fieldValues[i]);
32851
+ }
32852
+ return RTV.struct(fields);
33069
32853
  }
33070
- return RTV.struct(fields);
33071
- }
33072
- const elements = [];
33073
- for (let k = 0; k < arrayLen; k++) {
33074
- const fields = /* @__PURE__ */ new Map();
33075
- for (let i = 0; i < fieldNames.length; i++) {
33076
- const val = fieldValues[i];
33077
- if (isRuntimeCell(val)) {
33078
- fields.set(fieldNames[i], val.data[k]);
33079
- } else {
33080
- fields.set(fieldNames[i], val);
32854
+ const elements = [];
32855
+ for (let k = 0; k < arrayLen; k++) {
32856
+ const fields = /* @__PURE__ */ new Map();
32857
+ for (let i = 0; i < fieldNames.length; i++) {
32858
+ const val = fieldValues[i];
32859
+ if (isRuntimeCell(val)) {
32860
+ fields.set(fieldNames[i], val.data[k]);
32861
+ } else {
32862
+ fields.set(fieldNames[i], val);
32863
+ }
33081
32864
  }
32865
+ elements.push(RTV.struct(fields));
33082
32866
  }
33083
- elements.push(RTV.struct(fields));
33084
- }
33085
- return RTV.structArray(fieldNames, elements);
33086
- })
32867
+ return RTV.structArray(fieldNames, elements);
32868
+ },
32869
+ { outputType: IType.struct() }
32870
+ )
33087
32871
  );
33088
32872
  const fieldnamesApply = builtinSingle((args) => {
33089
32873
  if (args.length !== 1)
@@ -33171,18 +32955,11 @@ function registerMiscFunctions() {
33171
32955
  if (args.length < 2)
33172
32956
  throw new RuntimeError("mat2cell requires at least 2 arguments");
33173
32957
  let A = args[0];
32958
+ const distVec = (v) => toNumericVector(v, "mat2cell").map((x) => Math.round(x));
33174
32959
  if (isRuntimeChar(A)) {
33175
32960
  const str = A.value;
33176
- const getDistVector2 = (v) => {
33177
- if (isRuntimeNumber(v)) return [Math.round(v)];
33178
- if (isRuntimeTensor(v))
33179
- return Array.from(v.data).map((x) => Math.round(x));
33180
- throw new RuntimeError(
33181
- "mat2cell: distribution arguments must be numeric vectors"
33182
- );
33183
- };
33184
- getDistVector2(args[1]);
33185
- const colDist2 = args.length >= 3 ? getDistVector2(args[2]) : [str.length];
32961
+ distVec(args[1]);
32962
+ const colDist2 = args.length >= 3 ? distVec(args[2]) : [str.length];
33186
32963
  const nCellCols2 = colDist2.length;
33187
32964
  const cellData2 = [];
33188
32965
  let pos = 0;
@@ -33192,29 +32969,15 @@ function registerMiscFunctions() {
33192
32969
  }
33193
32970
  return RTV.cell(cellData2, [1, nCellCols2]);
33194
32971
  }
33195
- if (isRuntimeNumber(A)) {
33196
- A = RTV.tensor(new FloatXArray([A]), [1, 1]);
33197
- }
33198
- if (!isRuntimeTensor(A))
33199
- throw new RuntimeError(
33200
- "mat2cell: first argument must be a numeric array"
33201
- );
32972
+ A = coerceToTensor(A, "mat2cell");
33202
32973
  const rows = A.shape[0];
33203
32974
  const cols = A.shape.length >= 2 ? A.shape[1] : 1;
33204
- const getDistVector = (v) => {
33205
- if (isRuntimeNumber(v)) return [Math.round(v)];
33206
- if (isRuntimeTensor(v))
33207
- return Array.from(v.data).map((x) => Math.round(x));
33208
- throw new RuntimeError(
33209
- "mat2cell: distribution arguments must be numeric vectors"
33210
- );
33211
- };
33212
- const rowDist = getDistVector(args[1]);
32975
+ const rowDist = distVec(args[1]);
33213
32976
  let colDist;
33214
32977
  if (args.length === 2) {
33215
32978
  colDist = [cols];
33216
32979
  } else {
33217
- colDist = getDistVector(args[2]);
32980
+ colDist = distVec(args[2]);
33218
32981
  }
33219
32982
  const rowSum = rowDist.reduce((a, b) => a + b, 0);
33220
32983
  const colSum = colDist.reduce((a, b) => a + b, 0);
@@ -35099,8 +34862,7 @@ function _computeItemType(kind) {
35099
34862
  case "Unary": {
35100
34863
  const operandType = itemTypeForExprKind(kind.operand.kind);
35101
34864
  if (kind.op === "Not") {
35102
- if (operandType.kind === "Number" || operandType.kind === "Boolean" || operandType.kind === "ComplexNumber")
35103
- return { kind: "Boolean" };
34865
+ if (isScalarType(operandType)) return { kind: "Boolean" };
35104
34866
  if (operandType.kind === "Tensor") return operandType;
35105
34867
  return { kind: "Unknown" };
35106
34868
  }
@@ -35109,17 +34871,11 @@ function _computeItemType(kind) {
35109
34871
  case "Binary": {
35110
34872
  const leftType = itemTypeForExprKind(kind.left.kind);
35111
34873
  const rightType = itemTypeForExprKind(kind.right.kind);
35112
- const isScalar = (t) => t.kind === "Number" || t.kind === "Boolean" || t.kind === "ComplexNumber";
35113
- const isComplex2 = (t) => t.kind === "ComplexNumber" || t.kind === "Tensor" && t.isComplex;
35114
34874
  if (kind.op === "Equal" /* Equal */ || kind.op === "NotEqual" /* NotEqual */ || kind.op === "Less" /* Less */ || kind.op === "LessEqual" /* LessEqual */ || kind.op === "Greater" /* Greater */ || kind.op === "GreaterEqual" /* GreaterEqual */ || kind.op === "BitAnd" /* BitAnd */ || kind.op === "BitOr" /* BitOr */) {
35115
- if (isScalar(leftType) && isScalar(rightType))
34875
+ if (isScalarType(leftType) && isScalarType(rightType))
35116
34876
  return { kind: "Boolean" };
35117
34877
  if (leftType.kind === "Tensor" || rightType.kind === "Tensor") {
35118
- return {
35119
- kind: "Tensor",
35120
- isLogical: true,
35121
- isComplex: isComplex2(leftType) || isComplex2(rightType) ? true : void 0
35122
- };
34878
+ return { kind: "Tensor", isLogical: true };
35123
34879
  }
35124
34880
  return { kind: "Unknown" };
35125
34881
  }
@@ -35128,32 +34884,9 @@ function _computeItemType(kind) {
35128
34884
  if (leftType.kind === "Unknown" || rightType.kind === "Unknown" || leftType.kind === "ClassInstance" || rightType.kind === "ClassInstance") {
35129
34885
  return { kind: "Unknown" };
35130
34886
  }
35131
- if (kind.op === "Mul" /* Mul */) {
35132
- if (leftType.kind === "Tensor" && rightType.kind === "Tensor") {
35133
- return {
35134
- kind: "Tensor",
35135
- isComplex: isComplex2(leftType) || isComplex2(rightType) ? true : void 0
35136
- };
35137
- }
35138
- }
35139
34887
  if (leftType.kind === "Tensor" || rightType.kind === "Tensor") {
35140
- const resultIsComplex = isComplex2(leftType) || isComplex2(rightType) ? true : void 0;
35141
- if (isScalar(leftType) && rightType.kind === "Tensor") {
35142
- return { ...rightType, isComplex: resultIsComplex };
35143
- }
35144
- if (leftType.kind === "Tensor" && isScalar(rightType)) {
35145
- return { ...leftType, isComplex: resultIsComplex };
35146
- }
35147
- if (leftType.kind === "Tensor" && rightType.kind === "Tensor") {
35148
- return {
35149
- kind: "Tensor",
35150
- isComplex: resultIsComplex
35151
- };
35152
- }
35153
- return {
35154
- kind: "Tensor",
35155
- isComplex: resultIsComplex
35156
- };
34888
+ const resultIsComplex = isComplexType(leftType) || isComplexType(rightType) ? true : void 0;
34889
+ return { kind: "Tensor", isComplex: resultIsComplex };
35157
34890
  }
35158
34891
  if (leftType.kind === "ComplexNumber" || rightType.kind === "ComplexNumber") {
35159
34892
  return { kind: "ComplexNumber" };
@@ -35204,6 +34937,7 @@ function _computeItemType(kind) {
35204
34937
  }
35205
34938
  if (baseType.kind === "String") return { kind: "String" };
35206
34939
  if (baseType.kind === "Cell") return baseType;
34940
+ if (baseType.kind === "Function") return baseType.returns;
35207
34941
  return { kind: "Unknown" };
35208
34942
  }
35209
34943
  case "IndexCell": {
@@ -35219,7 +34953,13 @@ function _computeItemType(kind) {
35219
34953
  return { kind: "Tensor" };
35220
34954
  case "End":
35221
34955
  return { kind: "Number" };
35222
- case "Member":
34956
+ case "Member": {
34957
+ const baseType = itemTypeForExprKind(kind.base.kind);
34958
+ if (baseType.kind === "Struct" && kind.name in baseType.knownFields) {
34959
+ return baseType.knownFields[kind.name];
34960
+ }
34961
+ return { kind: "Unknown" };
34962
+ }
35223
34963
  case "MemberDynamic":
35224
34964
  return { kind: "Unknown" };
35225
34965
  case "MethodCall":
@@ -35227,10 +34967,15 @@ function _computeItemType(kind) {
35227
34967
  case "FuncCall": {
35228
34968
  return kind.returnType;
35229
34969
  }
35230
- case "AnonFunc":
35231
- return { kind: "Function", params: [], returns: { kind: "Unknown" } };
34970
+ case "AnonFunc": {
34971
+ const paramTypes = kind.params.map(
34972
+ (p) => p.ty ?? { kind: "Unknown" }
34973
+ );
34974
+ const returnType = itemTypeForExprKind(kind.body.kind);
34975
+ return { kind: "Function", params: paramTypes, returns: returnType };
34976
+ }
35232
34977
  case "FuncHandle":
35233
- return { kind: "Unknown" };
34978
+ return { kind: "Function", params: [], returns: { kind: "Unknown" } };
35234
34979
  case "MetaClass":
35235
34980
  return { kind: "Unknown" };
35236
34981
  case "ClassInstantiation":
@@ -35241,8 +34986,9 @@ function _computeItemType(kind) {
35241
34986
  }
35242
34987
 
35243
34988
  // src/numbl-core/lowering/varIdCollect.ts
35244
- function collectStmtVarIds(stmts, out2) {
34989
+ function collectVarIds(stmts, out2) {
35245
34990
  for (const s of stmts) {
34991
+ if (s.type === "Function") continue;
35246
34992
  collectStmtVarIdsOne(s, out2);
35247
34993
  }
35248
34994
  }
@@ -35267,57 +35013,50 @@ function collectStmtVarIdsOne(s, out2) {
35267
35013
  break;
35268
35014
  case "If":
35269
35015
  collectExprVarIds(s.cond, out2);
35270
- collectStmtVarIds(s.thenBody, out2);
35016
+ collectVarIds(s.thenBody, out2);
35271
35017
  for (const b of s.elseifBlocks) {
35272
35018
  collectExprVarIds(b.cond, out2);
35273
- collectStmtVarIds(b.body, out2);
35019
+ collectVarIds(b.body, out2);
35274
35020
  }
35275
- if (s.elseBody) collectStmtVarIds(s.elseBody, out2);
35021
+ if (s.elseBody) collectVarIds(s.elseBody, out2);
35276
35022
  break;
35277
35023
  case "While":
35278
35024
  collectExprVarIds(s.cond, out2);
35279
- collectStmtVarIds(s.body, out2);
35025
+ collectVarIds(s.body, out2);
35280
35026
  break;
35281
35027
  case "For":
35282
35028
  out2.add(s.variable.id.id);
35283
35029
  collectExprVarIds(s.expr, out2);
35284
- collectStmtVarIds(s.body, out2);
35030
+ collectVarIds(s.body, out2);
35285
35031
  break;
35286
35032
  case "Switch":
35287
35033
  collectExprVarIds(s.expr, out2);
35288
35034
  for (const c of s.cases) {
35289
35035
  collectExprVarIds(c.value, out2);
35290
- collectStmtVarIds(c.body, out2);
35036
+ collectVarIds(c.body, out2);
35291
35037
  }
35292
- if (s.otherwise) collectStmtVarIds(s.otherwise, out2);
35038
+ if (s.otherwise) collectVarIds(s.otherwise, out2);
35293
35039
  break;
35294
35040
  case "TryCatch":
35295
- collectStmtVarIds(s.tryBody, out2);
35041
+ collectVarIds(s.tryBody, out2);
35296
35042
  if (s.catchVar) out2.add(s.catchVar.id.id);
35297
- collectStmtVarIds(s.catchBody, out2);
35043
+ collectVarIds(s.catchBody, out2);
35298
35044
  break;
35299
35045
  case "Function":
35300
35046
  break;
35301
- case "Global": {
35302
- const vars = s.vars;
35303
- vars.forEach((v) => out2.add(v.variable.id.id));
35047
+ case "Global":
35048
+ case "Persistent":
35049
+ for (const v of s.vars) out2.add(v.variable.id.id);
35304
35050
  break;
35305
- }
35306
35051
  case "Return":
35307
35052
  case "Break":
35308
35053
  case "Continue":
35309
- case "Persistent":
35310
35054
  break;
35311
- default:
35312
- throw new Error(`Unhandled statement type: ${s.type}`);
35313
35055
  }
35314
35056
  }
35315
35057
  function collectExprVarIds(e, out2) {
35316
35058
  walkExpr2(e, (sub) => {
35317
35059
  if (sub.kind.type === "Var") out2.add(sub.kind.variable.id.id);
35318
- else if (sub.kind.type === "AnonFunc") {
35319
- for (const p of sub.kind.params) out2.add(p.id.id);
35320
- }
35321
35060
  });
35322
35061
  }
35323
35062
  function collectLValueVarIds(lv, out2) {
@@ -35326,8 +35065,11 @@ function collectLValueVarIds(lv, out2) {
35326
35065
  out2.add(lv.variable.id.id);
35327
35066
  break;
35328
35067
  case "Member":
35068
+ collectExprVarIds(lv.base, out2);
35069
+ break;
35329
35070
  case "MemberDynamic":
35330
35071
  collectExprVarIds(lv.base, out2);
35072
+ collectExprVarIds(lv.nameExpr, out2);
35331
35073
  break;
35332
35074
  case "Index":
35333
35075
  case "IndexCell":
@@ -35801,7 +35543,7 @@ function packResults(results, shape) {
35801
35543
  }
35802
35544
  return RTV.cell(results, [...shape]);
35803
35545
  }
35804
- function coerceToTensor(v, fnName, which) {
35546
+ function coerceToTensor2(v, fnName, which) {
35805
35547
  if (isRuntimeNumber(v)) {
35806
35548
  return RTV.tensor(new FloatXArray([v]), [1, 1]);
35807
35549
  }
@@ -36271,8 +36013,8 @@ function bsxfunImpl(rt, _nargout, args) {
36271
36013
  }
36272
36014
  const rawA = ensureRuntimeValue(args[1]);
36273
36015
  const rawB = ensureRuntimeValue(args[2]);
36274
- const a = coerceToTensor(rawA, "bsxfun", "first");
36275
- const b = coerceToTensor(rawB, "bsxfun", "second");
36016
+ const a = coerceToTensor2(rawA, "bsxfun", "first");
36017
+ const b = coerceToTensor2(rawB, "bsxfun", "second");
36276
36018
  const outShape = getBroadcastShape(a.shape, b.shape);
36277
36019
  if (!outShape)
36278
36020
  throw new RuntimeError(
@@ -38007,93 +37749,95 @@ function syncSleep(ms) {
38007
37749
  }
38008
37750
 
38009
37751
  // src/numbl-core/runtime/runtimePlot.ts
37752
+ function resolveStr(val) {
37753
+ return typeof val === "string" ? val : toString(ensureRuntimeValue(val));
37754
+ }
37755
+ function resolveNum(val, fallback) {
37756
+ if (typeof val === "number") return val;
37757
+ try {
37758
+ return toNumber(ensureRuntimeValue(val));
37759
+ } catch {
37760
+ return fallback ?? 0;
37761
+ }
37762
+ }
37763
+ function resolveOnOff(val) {
37764
+ if (typeof val === "boolean") return val;
37765
+ return resolveStr(val) === "on";
37766
+ }
38010
37767
  function plotInstr(plotInstructions, instr) {
38011
- if (instr.type === "set_figure_handle") {
38012
- let handle;
38013
- if (typeof instr.handle === "number") {
38014
- handle = instr.handle;
38015
- } else {
38016
- try {
38017
- handle = toNumber(ensureRuntimeValue(instr.handle));
38018
- } catch {
38019
- handle = 1;
38020
- }
37768
+ switch (instr.type) {
37769
+ case "set_figure_handle":
37770
+ plotInstructions.push({
37771
+ type: "set_figure_handle",
37772
+ handle: resolveNum(instr.handle, 1)
37773
+ });
37774
+ break;
37775
+ case "plot":
37776
+ plotInstructions.push({
37777
+ type: "plot",
37778
+ traces: [
37779
+ {
37780
+ x: runtimeValueToNumberArray(ensureRuntimeValue(instr.x)),
37781
+ y: runtimeValueToNumberArray(ensureRuntimeValue(instr.y))
37782
+ }
37783
+ ]
37784
+ });
37785
+ break;
37786
+ case "set_hold":
37787
+ plotInstructions.push({
37788
+ type: "set_hold",
37789
+ value: resolveOnOff(instr.value)
37790
+ });
37791
+ break;
37792
+ case "set_title":
37793
+ case "set_xlabel":
37794
+ case "set_ylabel":
37795
+ case "set_zlabel":
37796
+ case "set_sgtitle":
37797
+ plotInstructions.push({ type: instr.type, text: resolveStr(instr.text) });
37798
+ break;
37799
+ case "set_shading": {
37800
+ const shading = resolveStr(instr.shading).replace(/^'|'$/g, "");
37801
+ plotInstructions.push({ type: "set_shading", shading });
37802
+ break;
38021
37803
  }
38022
- plotInstructions.push({ type: "set_figure_handle", handle });
38023
- } else if (instr.type === "plot") {
38024
- plotInstructions.push({
38025
- type: "plot",
38026
- traces: [
38027
- {
38028
- x: runtimeValueToNumberArray(ensureRuntimeValue(instr.x)),
38029
- y: runtimeValueToNumberArray(ensureRuntimeValue(instr.y))
38030
- }
38031
- ]
38032
- });
38033
- } else if (instr.type === "set_hold") {
38034
- const val = instr.value;
38035
- let on;
38036
- if (typeof val === "string") on = val === "on";
38037
- else {
38038
- const mv = ensureRuntimeValue(val);
38039
- on = toString(mv) === "on";
38040
- }
38041
- plotInstructions.push({ type: "set_hold", value: on });
38042
- } else if (instr.type === "set_title") {
38043
- const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
38044
- plotInstructions.push({ type: "set_title", text });
38045
- } else if (instr.type === "set_xlabel") {
38046
- const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
38047
- plotInstructions.push({ type: "set_xlabel", text });
38048
- } else if (instr.type === "set_ylabel") {
38049
- const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
38050
- plotInstructions.push({ type: "set_ylabel", text });
38051
- } else if (instr.type === "set_shading") {
38052
- const raw = typeof instr.shading === "string" ? instr.shading : toString(ensureRuntimeValue(instr.shading));
38053
- const shading = raw.replace(/^'|'$/g, "");
38054
- plotInstructions.push({ type: "set_shading", shading });
38055
- } else if (instr.type === "close") {
38056
- plotInstructions.push({ type: "close" });
38057
- } else if (instr.type === "close_all") {
38058
- plotInstructions.push({ type: "close_all" });
38059
- } else if (instr.type === "clf") {
38060
- plotInstructions.push({ type: "clf" });
38061
- } else if (instr.type === "set_subplot") {
38062
- const rows = typeof instr.rows === "number" ? instr.rows : toNumber(ensureRuntimeValue(instr.rows));
38063
- const cols = typeof instr.cols === "number" ? instr.cols : toNumber(ensureRuntimeValue(instr.cols));
38064
- const index2 = typeof instr.index === "number" ? instr.index : toNumber(ensureRuntimeValue(instr.index));
38065
- plotInstructions.push({ type: "set_subplot", rows, cols, index: index2 });
38066
- } else if (instr.type === "set_sgtitle") {
38067
- const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
38068
- plotInstructions.push({ type: "set_sgtitle", text });
38069
- } else if (instr.type === "set_grid") {
38070
- const val = instr.value;
38071
- let on;
38072
- if (typeof val === "string") on = val === "on";
38073
- else if (typeof val === "boolean") on = val;
38074
- else {
38075
- const mv = ensureRuntimeValue(val);
38076
- on = toString(mv) === "on";
38077
- }
38078
- plotInstructions.push({ type: "set_grid", value: on });
38079
- } else if (instr.type === "set_zlabel") {
38080
- const text = typeof instr.text === "string" ? instr.text : toString(ensureRuntimeValue(instr.text));
38081
- plotInstructions.push({ type: "set_zlabel", text });
38082
- } else if (instr.type === "set_colorbar") {
38083
- const val = typeof instr.value === "string" ? instr.value : toString(ensureRuntimeValue(instr.value));
38084
- plotInstructions.push({ type: "set_colorbar", value: val });
38085
- } else if (instr.type === "set_colormap") {
38086
- const name = typeof instr.name === "string" ? instr.name : toString(ensureRuntimeValue(instr.name));
38087
- plotInstructions.push({
38088
- type: "set_colormap",
38089
- name: name.replace(/^"|"$/g, "")
38090
- });
38091
- } else if (instr.type === "set_axis") {
38092
- const val = typeof instr.value === "string" ? instr.value : toString(ensureRuntimeValue(instr.value));
38093
- plotInstructions.push({
38094
- type: "set_axis",
38095
- value: val.replace(/^"|"$/g, "")
38096
- });
37804
+ case "close":
37805
+ case "close_all":
37806
+ case "clf":
37807
+ plotInstructions.push({ type: instr.type });
37808
+ break;
37809
+ case "set_subplot":
37810
+ plotInstructions.push({
37811
+ type: "set_subplot",
37812
+ rows: resolveNum(instr.rows),
37813
+ cols: resolveNum(instr.cols),
37814
+ index: resolveNum(instr.index)
37815
+ });
37816
+ break;
37817
+ case "set_grid":
37818
+ plotInstructions.push({
37819
+ type: "set_grid",
37820
+ value: resolveOnOff(instr.value)
37821
+ });
37822
+ break;
37823
+ case "set_colorbar":
37824
+ plotInstructions.push({
37825
+ type: "set_colorbar",
37826
+ value: resolveStr(instr.value)
37827
+ });
37828
+ break;
37829
+ case "set_colormap":
37830
+ plotInstructions.push({
37831
+ type: "set_colormap",
37832
+ name: resolveStr(instr.name).replace(/^"|"$/g, "")
37833
+ });
37834
+ break;
37835
+ case "set_axis":
37836
+ plotInstructions.push({
37837
+ type: "set_axis",
37838
+ value: resolveStr(instr.value).replace(/^"|"$/g, "")
37839
+ });
37840
+ break;
38097
37841
  }
38098
37842
  }
38099
37843
  function viewCall(plotInstructions, args) {
@@ -39026,19 +38770,12 @@ function extractClassInfo(classDef, qualifiedName, fileName, source) {
39026
38770
  }
39027
38771
 
39028
38772
  // src/numbl-core/lowering/specKey.ts
39029
- function typeToDescriptor(ty) {
39030
- if (!ty) return { kind: "Unknown" };
39031
- if (ty.kind === "ClassInstance") {
39032
- return { kind: "ClassInstance", className: ty.className };
39033
- }
39034
- return { kind: ty.kind };
39035
- }
39036
38773
  function computeSpecKey(name, argTypes) {
39037
- const args = argTypes.map((t) => typeToDescriptor(t));
38774
+ const args = argTypes.map((t) => typeToString(t));
39038
38775
  return JSON.stringify({ name, args });
39039
38776
  }
39040
38777
  function hashForJsId(argTypes) {
39041
- const args = argTypes.map((t) => typeToDescriptor(t));
38778
+ const args = argTypes.map((t) => typeToString(t));
39042
38779
  const input = JSON.stringify(args);
39043
38780
  let hash = 2166136261;
39044
38781
  for (let i = 0; i < input.length; i++) {
@@ -39122,6 +38859,54 @@ function determineReturnType(ctx, name, candidates, args, nargout) {
39122
38859
  const specialized = ctx.getOrLowerFunctionSpecialized(name, argTypes2) ?? ctx.getOrLowerWorkspaceFunctionSpecialized(name, argTypes2);
39123
38860
  return extractOutputTypes(specialized, nargout);
39124
38861
  }
38862
+ if (candidate.type === "builtin" && name === "struct") {
38863
+ if (args.length === 0) return IType.struct();
38864
+ if (args.length % 2 === 0) {
38865
+ const fields = {};
38866
+ let allCharKeys = true;
38867
+ for (let i = 0; i < args.length; i += 2) {
38868
+ const keyExpr = args[i].kind;
38869
+ if (keyExpr.type !== "Char") {
38870
+ allCharKeys = false;
38871
+ break;
38872
+ }
38873
+ const fieldName = keyExpr.value.replace(/^'|'$/g, "");
38874
+ fields[fieldName] = itemTypeForExprKind(args[i + 1].kind);
38875
+ }
38876
+ if (allCharKeys) return IType.struct(fields);
38877
+ }
38878
+ return IType.struct();
38879
+ }
38880
+ if (candidate.type === "builtin" && (name === "arrayfun" || name === "cellfun")) {
38881
+ if (args.length >= 2) {
38882
+ const funcArgType = itemTypeForExprKind(args[0].kind);
38883
+ if (funcArgType.kind === "Function" && funcArgType.returns.kind !== "Unknown") {
38884
+ let uniformOutput = true;
38885
+ for (let i = 2; i < args.length; i++) {
38886
+ const a = args[i].kind;
38887
+ if (a.type === "Char" && a.value.replace(/^'|'$/g, "").toLowerCase() === "uniformoutput") {
38888
+ if (i + 1 < args.length) {
38889
+ const val = args[i + 1].kind;
38890
+ if (val.type === "Number" && val.value === "0") {
38891
+ uniformOutput = false;
38892
+ }
38893
+ }
38894
+ }
38895
+ }
38896
+ if (!uniformOutput) {
38897
+ return IType.cell("unknown");
38898
+ }
38899
+ const retKind = funcArgType.returns.kind;
38900
+ if (retKind === "Number" || retKind === "ComplexNumber") {
38901
+ return { kind: "Tensor", isComplex: retKind === "ComplexNumber" };
38902
+ }
38903
+ if (retKind === "Boolean") {
38904
+ return { kind: "Tensor", isLogical: true };
38905
+ }
38906
+ }
38907
+ }
38908
+ return { kind: "Unknown" };
38909
+ }
39125
38910
  const argTypes = args.map((a) => itemTypeForExprKind(a.kind));
39126
38911
  if (argTypes.some((t) => t.kind === "Unknown")) {
39127
38912
  return { kind: "Unknown" };
@@ -39805,7 +39590,7 @@ function lowerLValue(ctx, lv) {
39805
39590
  }
39806
39591
  case "Member": {
39807
39592
  if (lv.base.type === "Ident") {
39808
- const vv = ctx.lookup(lv.base.name) ?? ctx.defineVariable(lv.base.name, IType.Unknown);
39593
+ const vv = ctx.lookup(lv.base.name) ?? ctx.defineVariable(lv.base.name, void 0);
39809
39594
  const base2 = {
39810
39595
  kind: { type: "Var", variable: vv },
39811
39596
  span: lv.base.span
@@ -39816,7 +39601,7 @@ function lowerLValue(ctx, lv) {
39816
39601
  let root = lv.base;
39817
39602
  while (root.type === "Member") root = root.base;
39818
39603
  if (root.type === "Ident" && ctx.lookup(root.name) === null) {
39819
- ctx.defineVariable(root.name, IType.Unknown);
39604
+ ctx.defineVariable(root.name, void 0);
39820
39605
  }
39821
39606
  }
39822
39607
  if (lv.base.type === "Index" || lv.base.type === "IndexCell") {
@@ -40011,10 +39796,13 @@ function lowerStmt(ctx, stmt) {
40011
39796
  span
40012
39797
  };
40013
39798
  }
39799
+ if (irLv.type === "Member") {
39800
+ const fieldType = itemTypeForExprKind(value.kind);
39801
+ updateStructTypeForMemberAssign(irLv, fieldType);
39802
+ }
40014
39803
  if ((irLv.type === "Index" || irLv.type === "IndexCell") && irLv.base.kind.type === "Var") {
40015
39804
  const v = irLv.base.kind.variable;
40016
- const k = v.ty?.kind;
40017
- if (k === "Number" || k === "Boolean" || k === "ComplexNumber") {
39805
+ if (v.ty && isScalarType(v.ty)) {
40018
39806
  v.ty = IType.Unknown;
40019
39807
  }
40020
39808
  }
@@ -40125,6 +39913,24 @@ function lowerStmt(ctx, stmt) {
40125
39913
  );
40126
39914
  }
40127
39915
  }
39916
+ function updateStructTypeForMemberAssign(lv, fieldType) {
39917
+ const chain = [lv.name];
39918
+ let cursor = lv.base.kind;
39919
+ while (cursor.type === "Member") {
39920
+ chain.unshift(cursor.name);
39921
+ cursor = cursor.base.kind;
39922
+ }
39923
+ if (cursor.type !== "Var") return;
39924
+ const v = cursor.variable;
39925
+ if (v.ty && v.ty.kind !== "Struct" && v.ty.kind !== "Unknown") return;
39926
+ let ty = IType.struct({ [chain[chain.length - 1]]: fieldType });
39927
+ for (let i = chain.length - 2; i >= 0; i--) {
39928
+ ty = IType.struct({ [chain[i]]: ty });
39929
+ }
39930
+ if (!v.ty || v.ty.kind === "Struct") {
39931
+ v.ty = IType.unify(v.ty, ty);
39932
+ }
39933
+ }
40128
39934
  function lowerFunction(ctx, stmt, paramTypes) {
40129
39935
  const isNested = ctx.scopes.length > 1 && !stmt.isFileLocalSubfunction;
40130
39936
  if (isNested) {
@@ -41065,6 +40871,13 @@ var JS_RESERVED = /* @__PURE__ */ new Set([
41065
40871
  "Set",
41066
40872
  "JSON"
41067
40873
  ]);
40874
+ function assertNoUnknownArgTypes(argTypes, label) {
40875
+ if (argTypes.some((t) => !t || t.kind === "Unknown")) {
40876
+ throw new Error(
40877
+ `Cannot generate specialized function for ${label}: unknown parameter types`
40878
+ );
40879
+ }
40880
+ }
41068
40881
  function exprContainsEndShallow(expr) {
41069
40882
  let found = false;
41070
40883
  function walk(e, insideInner) {
@@ -41123,77 +40936,6 @@ function exprContainsEndShallow(expr) {
41123
40936
  walk(expr, false);
41124
40937
  return found;
41125
40938
  }
41126
- function collectVarIds(stmts, out2) {
41127
- for (const stmt of stmts) {
41128
- if (stmt.type === "Function") continue;
41129
- collectVarIdsFromStmt(stmt, out2);
41130
- }
41131
- }
41132
- function collectVarIdsFromStmt(stmt, out2) {
41133
- switch (stmt.type) {
41134
- case "Assign":
41135
- out2.add(stmt.variable.id.id);
41136
- collectVarIdsFromExpr(stmt.expr, out2);
41137
- break;
41138
- case "ExprStmt":
41139
- collectVarIdsFromExpr(stmt.expr, out2);
41140
- break;
41141
- case "MultiAssign":
41142
- collectVarIdsFromExpr(stmt.expr, out2);
41143
- for (const lv of stmt.lvalues) {
41144
- if (lv) collectVarIdsFromLValue(lv, out2);
41145
- }
41146
- break;
41147
- case "AssignLValue":
41148
- collectVarIdsFromLValue(stmt.lvalue, out2);
41149
- collectVarIdsFromExpr(stmt.expr, out2);
41150
- break;
41151
- case "If":
41152
- collectVarIdsFromExpr(stmt.cond, out2);
41153
- collectVarIds(stmt.thenBody, out2);
41154
- for (const b of stmt.elseifBlocks) {
41155
- collectVarIdsFromExpr(b.cond, out2);
41156
- collectVarIds(b.body, out2);
41157
- }
41158
- if (stmt.elseBody) collectVarIds(stmt.elseBody, out2);
41159
- break;
41160
- case "While":
41161
- collectVarIdsFromExpr(stmt.cond, out2);
41162
- collectVarIds(stmt.body, out2);
41163
- break;
41164
- case "For":
41165
- out2.add(stmt.variable.id.id);
41166
- collectVarIdsFromExpr(stmt.expr, out2);
41167
- collectVarIds(stmt.body, out2);
41168
- break;
41169
- case "Switch":
41170
- collectVarIdsFromExpr(stmt.expr, out2);
41171
- for (const c of stmt.cases) {
41172
- collectVarIdsFromExpr(c.value, out2);
41173
- collectVarIds(c.body, out2);
41174
- }
41175
- if (stmt.otherwise) collectVarIds(stmt.otherwise, out2);
41176
- break;
41177
- case "TryCatch":
41178
- collectVarIds(stmt.tryBody, out2);
41179
- if (stmt.catchVar) out2.add(stmt.catchVar.id.id);
41180
- collectVarIds(stmt.catchBody, out2);
41181
- break;
41182
- case "Global":
41183
- case "Persistent":
41184
- for (const v of stmt.vars) out2.add(v.variable.id.id);
41185
- break;
41186
- case "Return":
41187
- case "Break":
41188
- case "Continue":
41189
- break;
41190
- }
41191
- }
41192
- function collectVarIdsFromExpr(expr, out2) {
41193
- walkExpr2(expr, (e) => {
41194
- if (e.kind.type === "Var") out2.add(e.kind.variable.id.id);
41195
- });
41196
- }
41197
40939
  function collectClassProperties(ctx, className) {
41198
40940
  const classInfo = ctx.getClassInfo(className);
41199
40941
  if (!classInfo) return { propertyNames: [], propertyDefaults: /* @__PURE__ */ new Map() };
@@ -41227,17 +40969,6 @@ function genPropertyDefaults(cg, className, defaults) {
41227
40969
  }
41228
40970
  return `{${entries.join(", ")}}`;
41229
40971
  }
41230
- function collectVarIdsFromLValue(lv, out2) {
41231
- if (lv.type === "Var") {
41232
- out2.add(lv.variable.id.id);
41233
- } else if (lv.type === "Member" || lv.type === "MemberDynamic") {
41234
- collectVarIdsFromExpr(lv.base, out2);
41235
- if (lv.type === "MemberDynamic") collectVarIdsFromExpr(lv.nameExpr, out2);
41236
- } else if (lv.type === "Index" || lv.type === "IndexCell") {
41237
- collectVarIdsFromExpr(lv.base, out2);
41238
- for (const i of lv.indices) collectVarIdsFromExpr(i, out2);
41239
- }
41240
- }
41241
40972
 
41242
40973
  // src/numbl-core/codegen/codegenExpr.ts
41243
40974
  function genExpr(cg, expr) {
@@ -41578,14 +41309,14 @@ function genMember(cg, kind) {
41578
41309
  current = current.kind.base;
41579
41310
  }
41580
41311
  const rootType = itemTypeForExprKind(current.kind);
41581
- if (rootType.kind === "ClassInstance" && hasSubsref(cg, rootType.className) && cg.loweringCtx.ownerClassName !== rootType.className) {
41312
+ if (rootType.kind === "ClassInstance" && hasClassMethod(cg, rootType.className, "subsref") && cg.loweringCtx.ownerClassName !== rootType.className) {
41582
41313
  const rootCode = genExpr(cg, current);
41583
41314
  return `$rt.subsrefCall(${rootCode}, ${JSON.stringify(chain)})`;
41584
41315
  }
41585
41316
  const baseType = itemTypeForExprKind(kind.base.kind);
41586
41317
  if (baseType.kind === "ClassInstance") {
41587
41318
  const info = cg.loweringCtx.getClassInfo(baseType.className);
41588
- if (info && info.propertyNames.includes(kind.name) && !cg.loweringCtx.classHasMethod(baseType.className, `get.${kind.name}`) && !hasSubsref(cg, baseType.className)) {
41319
+ if (info && info.propertyNames.includes(kind.name) && !cg.loweringCtx.classHasMethod(baseType.className, `get.${kind.name}`) && !hasClassMethod(cg, baseType.className, "subsref")) {
41589
41320
  const base2 = genExpr(cg, kind.base);
41590
41321
  return `${base2}.fields.get(${JSON.stringify(kind.name)})`;
41591
41322
  }
@@ -41932,13 +41663,7 @@ function genClassInstantiation(cg, kind) {
41932
41663
  }
41933
41664
  }
41934
41665
  cg.ensureClassRegistered(className);
41935
- const {
41936
- propertyNames: allPropertyNames,
41937
- propertyDefaults: allPropertyDefaults
41938
- } = collectClassProperties(cg.loweringCtx, className);
41939
- const propsJson = JSON.stringify(allPropertyNames);
41940
- const isHandleClass = cg.isHandleClass(classInfo);
41941
- const defaultsArg = genPropertyDefaults(cg, className, allPropertyDefaults);
41666
+ const createExpr = cg.genCreateClassInstanceExpr(className, classInfo);
41942
41667
  if (classInfo.constructorName) {
41943
41668
  const selfType = { kind: "ClassInstance", className };
41944
41669
  const argTypes = [
@@ -41952,13 +41677,11 @@ function genClassInstantiation(cg, kind) {
41952
41677
  );
41953
41678
  if (jsId) {
41954
41679
  const instVar = cg.freshTemp("$inst");
41955
- cg.emit(
41956
- `var ${instVar} = $rt.createClassInstance(${JSON.stringify(className)}, ${propsJson}, ${defaultsArg}, ${isHandleClass});`
41957
- );
41680
+ cg.emit(`var ${instVar} = ${createExpr};`);
41958
41681
  return `${jsId}(1, ${instVar}, ${args.join(", ")})`;
41959
41682
  }
41960
41683
  }
41961
- return `$rt.createClassInstance(${JSON.stringify(className)}, ${propsJson}, ${defaultsArg}, ${isHandleClass})`;
41684
+ return createExpr;
41962
41685
  }
41963
41686
  var NATIVE_MATH_1 = {
41964
41687
  // Note: sqrt, asin, acos, log are NOT here because they can produce
@@ -42006,15 +41729,10 @@ function isOutputFunction(expr) {
42006
41729
  ];
42007
41730
  return outputFunctions.includes(expr.kind.name);
42008
41731
  }
42009
- function hasSubsref(cg, className) {
41732
+ function hasClassMethod(cg, className, methodName) {
42010
41733
  const info = cg.loweringCtx.getClassInfo(className);
42011
41734
  if (!info) return false;
42012
- return info.methodNames.has("subsref");
42013
- }
42014
- function hasSubsasgn(cg, className) {
42015
- const info = cg.loweringCtx.getClassInfo(className);
42016
- if (!info) return false;
42017
- return info.methodNames.has("subsasgn");
41735
+ return info.methodNames.has(methodName);
42018
41736
  }
42019
41737
 
42020
41738
  // src/numbl-core/codegen/codegenStmt.ts
@@ -42370,7 +42088,7 @@ function genMemberAssign(cg, lv, rhs) {
42370
42088
  const rootType = itemTypeForExprKind(root.kind);
42371
42089
  if (allMemberSteps(steps)) {
42372
42090
  const chain = [...memberNames(steps), lv.name];
42373
- if (rootType.kind === "ClassInstance" && hasSubsasgn(cg, rootType.className) && cg.loweringCtx.ownerClassName !== rootType.className) {
42091
+ if (rootType.kind === "ClassInstance" && hasClassMethod(cg, rootType.className, "subsasgn") && cg.loweringCtx.ownerClassName !== rootType.className) {
42374
42092
  cg.emit(
42375
42093
  `${rootRef} = ${`$rt.subsasgnCall(${rootRef}, ${JSON.stringify(chain)}, ${rhs})`};`
42376
42094
  );
@@ -42872,6 +42590,25 @@ var Codegen = class {
42872
42590
  }
42873
42591
  return false;
42874
42592
  }
42593
+ /**
42594
+ * Build a `$rt.createClassInstance(...)` JS expression for a class,
42595
+ * including property names, defaults, and handle-class flag.
42596
+ * Used by both genClassInstantiation and ensureWorkspaceClassConstructorGenerated.
42597
+ */
42598
+ genCreateClassInstanceExpr(className, classInfo) {
42599
+ const {
42600
+ propertyNames: allPropertyNames,
42601
+ propertyDefaults: allPropertyDefaults
42602
+ } = collectClassProperties(this.loweringCtx, className);
42603
+ const propsJson = JSON.stringify(allPropertyNames);
42604
+ const isHandleClass = this.isHandleClass(classInfo);
42605
+ const defaultsArg = genPropertyDefaults(
42606
+ this,
42607
+ className,
42608
+ allPropertyDefaults
42609
+ );
42610
+ return `$rt.createClassInstance(${JSON.stringify(className)}, ${propsJson}, ${defaultsArg}, ${isHandleClass})`;
42611
+ }
42875
42612
  getCode() {
42876
42613
  const builtinDecls = [];
42877
42614
  for (const name of [...this.usedBuiltins].sort()) {
@@ -43023,11 +42760,7 @@ var Codegen = class {
43023
42760
  * or null if it's not a local function.
43024
42761
  */
43025
42762
  ensureSpecializedFunctionGenerated(name, argTypes) {
43026
- if (argTypes.some((type) => type.kind === "Unknown")) {
43027
- throw new Error(
43028
- `Cannot generate specialized function for ${name}: unknown parameter types`
43029
- );
43030
- }
42763
+ assertNoUnknownArgTypes(argTypes, name);
43031
42764
  const filePrefix = this.loweringCtx.getRelativePath(
43032
42765
  this.loweringCtx.mainFileName
43033
42766
  );
@@ -43072,11 +42805,7 @@ var Codegen = class {
43072
42805
  });
43073
42806
  }
43074
42807
  ensureWorkspaceFunctionGenerated(name, argTypes) {
43075
- if (argTypes.some((type) => type.kind === "Unknown")) {
43076
- throw new Error(
43077
- `Cannot generate specialized function for ${name}: unknown parameter types`
43078
- );
43079
- }
42808
+ assertNoUnknownArgTypes(argTypes, name);
43080
42809
  return this.ensureExternalFunctionGenerated(name, argTypes, {
43081
42810
  specKeyPrefix: name,
43082
42811
  jsIdPrefix: "$fn_",
@@ -43085,11 +42814,7 @@ var Codegen = class {
43085
42814
  });
43086
42815
  }
43087
42816
  ensurePrivateFunctionGenerated(name, argTypes) {
43088
- if (argTypes.some((type) => type && type.kind === "Unknown")) {
43089
- throw new Error(
43090
- `Cannot generate specialized function for ${name}: unknown parameter types`
43091
- );
43092
- }
42817
+ assertNoUnknownArgTypes(argTypes, name);
43093
42818
  return this.ensureExternalFunctionGenerated(name, argTypes, {
43094
42819
  specKeyPrefix: `private:${name}`,
43095
42820
  jsIdPrefix: "$fn_priv_",
@@ -43116,11 +42841,7 @@ var Codegen = class {
43116
42841
  * Used by JIT compilation when `feval('ClassName')` is called at runtime.
43117
42842
  */
43118
42843
  ensureWorkspaceClassConstructorGenerated(className, argTypes) {
43119
- if (argTypes.some((type) => type && type.kind === "Unknown")) {
43120
- throw new Error(
43121
- `Cannot generate constructor for ${className}: unknown parameter types`
43122
- );
43123
- }
42844
+ assertNoUnknownArgTypes(argTypes, className);
43124
42845
  const classInfo = this.loweringCtx.getClassInfo(className);
43125
42846
  if (!classInfo) return null;
43126
42847
  const specKey = computeSpecKey(`${className}$$ctor`, argTypes);
@@ -43128,53 +42849,28 @@ var Codegen = class {
43128
42849
  if (existing) return existing.jsId;
43129
42850
  const hash = hashForJsId(argTypes);
43130
42851
  const jsId = `$fn_${this.sanitizeName(className)}$$ctor$${hash}`;
43131
- const {
43132
- propertyNames: allPropertyNames,
43133
- propertyDefaults: allPropertyDefaults
43134
- } = collectClassProperties(this.loweringCtx, className);
43135
- const propsJson = JSON.stringify(allPropertyNames);
43136
- const isHandleClass = this.isHandleClass(classInfo);
43137
- const defaultsArg = genPropertyDefaults(
43138
- this,
43139
- className,
43140
- allPropertyDefaults
43141
- );
43142
- this.pushEmitCapture();
42852
+ const createExpr = this.genCreateClassInstanceExpr(className, classInfo);
42853
+ let ctorJsId = null;
43143
42854
  if (classInfo.constructorName) {
43144
42855
  const selfType = { kind: "ClassInstance", className };
43145
42856
  const ctorArgTypes = [selfType, ...argTypes];
43146
- const ctorJsId = this.ensureClassMethodGenerated(
42857
+ ctorJsId = this.ensureClassMethodGenerated(
43147
42858
  className,
43148
42859
  classInfo.constructorName,
43149
42860
  ctorArgTypes
43150
42861
  );
43151
- if (ctorJsId) {
43152
- this.emit(`function ${jsId}($nargout, ...args) {`);
43153
- this.pushIndent();
43154
- this.emit(
43155
- `var $inst = $rt.createClassInstance(${JSON.stringify(className)}, ${propsJson}, ${defaultsArg}, ${isHandleClass});`
43156
- );
43157
- this.emit(`return ${ctorJsId}(1, $inst, ...args);`);
43158
- this.popIndent();
43159
- this.emit(`}`);
43160
- } else {
43161
- this.emit(`function ${jsId}($nargout, ...args) {`);
43162
- this.pushIndent();
43163
- this.emit(
43164
- `return $rt.createClassInstance(${JSON.stringify(className)}, ${propsJson}, ${defaultsArg}, ${isHandleClass});`
43165
- );
43166
- this.popIndent();
43167
- this.emit(`}`);
43168
- }
42862
+ }
42863
+ this.pushEmitCapture();
42864
+ this.emit(`function ${jsId}($nargout, ...args) {`);
42865
+ this.pushIndent();
42866
+ if (ctorJsId) {
42867
+ this.emit(`var $inst = ${createExpr};`);
42868
+ this.emit(`return ${ctorJsId}(1, $inst, ...args);`);
43169
42869
  } else {
43170
- this.emit(`function ${jsId}($nargout, ...args) {`);
43171
- this.pushIndent();
43172
- this.emit(
43173
- `return $rt.createClassInstance(${JSON.stringify(className)}, ${propsJson}, ${defaultsArg}, ${isHandleClass});`
43174
- );
43175
- this.popIndent();
43176
- this.emit(`}`);
42870
+ this.emit(`return ${createExpr};`);
43177
42871
  }
42872
+ this.popIndent();
42873
+ this.emit(`}`);
43178
42874
  this.popEmitCaptureToDefinitions();
43179
42875
  this.generatedFunctions.set(specKey, {
43180
42876
  functionId: className,
@@ -43819,9 +43515,7 @@ function generateMainScriptCode(source, mainFileName = "script.m", workspaceFile
43819
43515
  codegen.noLineTracking = true;
43820
43516
  }
43821
43517
  const scriptVarIds = /* @__PURE__ */ new Set();
43822
- for (const stmt of irBody) {
43823
- collectStmtVarIdsOne(stmt, scriptVarIds);
43824
- }
43518
+ collectVarIds(irBody, scriptVarIds);
43825
43519
  for (const v of initialVarIRVars) {
43826
43520
  scriptVarIds.add(v.id.id);
43827
43521
  }