numbl 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cli/cli.js +1450 -415
- package/dist-lib/lib.js +1361 -393
- package/dist-lib/numbl-core/executeCode.d.ts +9 -0
- package/dist-lib/numbl-core/fileIOAdapter.d.ts +2 -0
- package/dist-lib/numbl-core/helpers/quadgk.d.ts +32 -0
- package/dist-lib/numbl-core/helpers/string.d.ts +6 -0
- package/dist-lib/numbl-core/interpreter/builtins/index.d.ts +1 -0
- package/dist-lib/numbl-core/interpreter/builtins/logical.d.ts +9 -0
- package/dist-lib/numbl-core/interpreter/interpreterSpecialBuiltins.d.ts +3 -0
- package/dist-lib/numbl-core/runtime/runtime.d.ts +9 -0
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/package.json +1 -1
package/dist-lib/lib.js
CHANGED
|
@@ -18789,6 +18789,258 @@ function coerceToTensor(v, name) {
|
|
|
18789
18789
|
throw new RuntimeError(`${name}: argument must be numeric`);
|
|
18790
18790
|
}
|
|
18791
18791
|
|
|
18792
|
+
// src/numbl-core/helpers/string.ts
|
|
18793
|
+
function numStr(n) {
|
|
18794
|
+
if (n === Infinity) return "Inf";
|
|
18795
|
+
if (n === -Infinity) return "-Inf";
|
|
18796
|
+
if (isNaN(n)) return "NaN";
|
|
18797
|
+
if (n === 0) return "0";
|
|
18798
|
+
const prec = 5;
|
|
18799
|
+
const exp = Math.floor(Math.log10(Math.abs(n)));
|
|
18800
|
+
let s;
|
|
18801
|
+
if (exp < -4 || exp >= prec) {
|
|
18802
|
+
s = n.toExponential(prec - 1);
|
|
18803
|
+
const ePos = s.indexOf("e");
|
|
18804
|
+
let mantissa = s.slice(0, ePos);
|
|
18805
|
+
const expPart0 = s.slice(ePos);
|
|
18806
|
+
if (mantissa.includes(".")) mantissa = mantissa.replace(/\.?0+$/, "");
|
|
18807
|
+
const expPart = expPart0.replace(/([eE][+-])(\d)$/, "$10$2");
|
|
18808
|
+
s = mantissa + expPart;
|
|
18809
|
+
} else {
|
|
18810
|
+
if (Number.isInteger(n)) return String(n);
|
|
18811
|
+
s = n.toPrecision(prec);
|
|
18812
|
+
if (s.includes(".")) s = s.replace(/\.?0+$/, "");
|
|
18813
|
+
}
|
|
18814
|
+
return s;
|
|
18815
|
+
}
|
|
18816
|
+
function num2strScalar(n) {
|
|
18817
|
+
if (n === Infinity) return "Inf";
|
|
18818
|
+
if (n === -Infinity) return "-Inf";
|
|
18819
|
+
if (isNaN(n)) return "NaN";
|
|
18820
|
+
if (n === 0) return "0";
|
|
18821
|
+
if (Number.isInteger(n)) return String(n);
|
|
18822
|
+
const prec = 5;
|
|
18823
|
+
const exp = Math.floor(Math.log10(Math.abs(n)));
|
|
18824
|
+
let s;
|
|
18825
|
+
if (exp < -4 || exp >= prec) {
|
|
18826
|
+
s = n.toExponential(prec - 1);
|
|
18827
|
+
const ePos = s.indexOf("e");
|
|
18828
|
+
let mantissa = s.slice(0, ePos);
|
|
18829
|
+
const expPart0 = s.slice(ePos);
|
|
18830
|
+
if (mantissa.includes(".")) mantissa = mantissa.replace(/\.?0+$/, "");
|
|
18831
|
+
const expPart = expPart0.replace(/([eE][+-])(\d)$/, "$10$2");
|
|
18832
|
+
s = mantissa + expPart;
|
|
18833
|
+
} else {
|
|
18834
|
+
s = n.toPrecision(prec);
|
|
18835
|
+
if (s.includes(".")) s = s.replace(/\.?0+$/, "");
|
|
18836
|
+
}
|
|
18837
|
+
return s;
|
|
18838
|
+
}
|
|
18839
|
+
function applyWidth(spec, str) {
|
|
18840
|
+
const m = spec.match(/^%([-+ #]*)0?(\d+)?/);
|
|
18841
|
+
if (!m) return str;
|
|
18842
|
+
const explicitFlags = m[1] || "";
|
|
18843
|
+
const leftAlign = explicitFlags.includes("-");
|
|
18844
|
+
const afterPercent = spec.slice(1);
|
|
18845
|
+
const flagAndWidth = afterPercent.match(/^([-+ #]*)(0?)(\d+)?/);
|
|
18846
|
+
const zeroFlag = flagAndWidth ? flagAndWidth[2] === "0" : false;
|
|
18847
|
+
const width = flagAndWidth && flagAndWidth[3] ? parseInt(flagAndWidth[3]) : 0;
|
|
18848
|
+
if (width <= str.length) return str;
|
|
18849
|
+
const zeroPad = !leftAlign && zeroFlag;
|
|
18850
|
+
const padLen = width - str.length;
|
|
18851
|
+
if (leftAlign) return str + " ".repeat(padLen);
|
|
18852
|
+
if (zeroPad) {
|
|
18853
|
+
if (str[0] === "-" || str[0] === "+") {
|
|
18854
|
+
return str[0] + "0".repeat(padLen) + str.slice(1);
|
|
18855
|
+
}
|
|
18856
|
+
return "0".repeat(padLen) + str;
|
|
18857
|
+
}
|
|
18858
|
+
return " ".repeat(padLen) + str;
|
|
18859
|
+
}
|
|
18860
|
+
function sprintfFormat(fmt, args) {
|
|
18861
|
+
const flatArgs = [];
|
|
18862
|
+
for (const arg of args) {
|
|
18863
|
+
if (isRuntimeTensor(arg)) {
|
|
18864
|
+
for (let k = 0; k < arg.data.length; k++) {
|
|
18865
|
+
flatArgs.push(arg.data[k]);
|
|
18866
|
+
}
|
|
18867
|
+
} else {
|
|
18868
|
+
flatArgs.push(arg);
|
|
18869
|
+
}
|
|
18870
|
+
}
|
|
18871
|
+
let result = "";
|
|
18872
|
+
let argIdx = 0;
|
|
18873
|
+
do {
|
|
18874
|
+
const startArgIdx = argIdx;
|
|
18875
|
+
let outOfArgs = false;
|
|
18876
|
+
let i = 0;
|
|
18877
|
+
while (i < fmt.length && !outOfArgs) {
|
|
18878
|
+
if (fmt[i] === "%" && i + 1 < fmt.length) {
|
|
18879
|
+
i++;
|
|
18880
|
+
let spec = "%";
|
|
18881
|
+
while (i < fmt.length && !"dfigeEsoxXuc%".includes(fmt[i])) {
|
|
18882
|
+
if (fmt[i] === "*") {
|
|
18883
|
+
if (argIdx >= flatArgs.length) {
|
|
18884
|
+
outOfArgs = true;
|
|
18885
|
+
break;
|
|
18886
|
+
}
|
|
18887
|
+
spec += String(Math.round(toNumber(flatArgs[argIdx++])));
|
|
18888
|
+
i++;
|
|
18889
|
+
} else {
|
|
18890
|
+
spec += fmt[i];
|
|
18891
|
+
i++;
|
|
18892
|
+
}
|
|
18893
|
+
}
|
|
18894
|
+
if (outOfArgs) break;
|
|
18895
|
+
if (i < fmt.length) {
|
|
18896
|
+
const ch = fmt[i];
|
|
18897
|
+
i++;
|
|
18898
|
+
if (ch === "%") {
|
|
18899
|
+
result += "%";
|
|
18900
|
+
} else if (argIdx >= flatArgs.length) {
|
|
18901
|
+
outOfArgs = true;
|
|
18902
|
+
} else if (ch === "d" || ch === "i" || ch === "u") {
|
|
18903
|
+
const raw = toNumber(flatArgs[argIdx++]);
|
|
18904
|
+
const isInt = Number.isInteger(raw);
|
|
18905
|
+
const canPrintAsInt = ch === "u" ? isInt && raw >= 0 : isInt;
|
|
18906
|
+
if (!canPrintAsInt) {
|
|
18907
|
+
let eStr = raw.toExponential(6);
|
|
18908
|
+
eStr = eStr.replace(/e([+-])(\d)$/, "e$10$2");
|
|
18909
|
+
result += applyWidth(spec, eStr);
|
|
18910
|
+
} else {
|
|
18911
|
+
const n = raw;
|
|
18912
|
+
const flags = spec.slice(1);
|
|
18913
|
+
const hasPlus = flags.includes("+");
|
|
18914
|
+
const leftAlign = flags.includes("-");
|
|
18915
|
+
const widthMatch = spec.match(/^%[^0-9]*(\d+)/);
|
|
18916
|
+
const width = widthMatch ? parseInt(widthMatch[1]) : 0;
|
|
18917
|
+
const zeroPad = !leftAlign && /^[-+ ]*0/.test(spec.slice(1));
|
|
18918
|
+
const s = String(Math.abs(n));
|
|
18919
|
+
const sign = n < 0 ? "-" : hasPlus ? "+" : "";
|
|
18920
|
+
if (width > 0) {
|
|
18921
|
+
const padChar = zeroPad ? "0" : " ";
|
|
18922
|
+
const padLen = Math.max(0, width - sign.length - s.length);
|
|
18923
|
+
const pad = padChar.repeat(padLen);
|
|
18924
|
+
result += leftAlign ? sign + s + " ".repeat(padLen) : zeroPad ? sign + pad + s : pad + sign + s;
|
|
18925
|
+
} else {
|
|
18926
|
+
result += sign + s;
|
|
18927
|
+
}
|
|
18928
|
+
}
|
|
18929
|
+
} else if (ch === "f") {
|
|
18930
|
+
const n = toNumber(flatArgs[argIdx++]);
|
|
18931
|
+
if (!isFinite(n) || isNaN(n)) {
|
|
18932
|
+
result += applyWidth(spec, numStr(n));
|
|
18933
|
+
} else {
|
|
18934
|
+
const fFlags = spec.slice(1);
|
|
18935
|
+
const fHasPlus = fFlags.includes("+");
|
|
18936
|
+
const precMatch = spec.match(/\.(\d+)/);
|
|
18937
|
+
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
18938
|
+
const formatted = n.toFixed(prec);
|
|
18939
|
+
const fSign = n < 0 ? "" : fHasPlus ? "+" : "";
|
|
18940
|
+
result += applyWidth(spec, fSign + formatted);
|
|
18941
|
+
}
|
|
18942
|
+
} else if (ch === "e" || ch === "E") {
|
|
18943
|
+
const n = toNumber(flatArgs[argIdx++]);
|
|
18944
|
+
if (!isFinite(n) || isNaN(n)) {
|
|
18945
|
+
result += applyWidth(spec, numStr(n));
|
|
18946
|
+
} else {
|
|
18947
|
+
const precMatch = spec.match(/\.(\d+)/);
|
|
18948
|
+
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
18949
|
+
let eStr = n.toExponential(prec);
|
|
18950
|
+
eStr = eStr.replace(/e([+-])(\d)$/, "e$10$2");
|
|
18951
|
+
if (ch === "E") eStr = eStr.toUpperCase();
|
|
18952
|
+
result += applyWidth(spec, eStr);
|
|
18953
|
+
}
|
|
18954
|
+
} else if (ch === "x" || ch === "X") {
|
|
18955
|
+
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
18956
|
+
let s = Math.abs(n).toString(16);
|
|
18957
|
+
if (ch === "X") s = s.toUpperCase();
|
|
18958
|
+
result += applyWidth(spec, s);
|
|
18959
|
+
} else if (ch === "o") {
|
|
18960
|
+
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
18961
|
+
result += applyWidth(spec, Math.abs(n).toString(8));
|
|
18962
|
+
} else if (ch === "g" || ch === "G") {
|
|
18963
|
+
const gVal = toNumber(flatArgs[argIdx++]);
|
|
18964
|
+
if (!isFinite(gVal) || isNaN(gVal)) {
|
|
18965
|
+
result += applyWidth(spec, numStr(gVal));
|
|
18966
|
+
} else {
|
|
18967
|
+
const precMatch = spec.match(/\.(\d+)/);
|
|
18968
|
+
const gPrec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
18969
|
+
let gStr;
|
|
18970
|
+
if (gVal === 0) {
|
|
18971
|
+
gStr = "0";
|
|
18972
|
+
} else {
|
|
18973
|
+
const exp = Math.floor(Math.log10(Math.abs(gVal)));
|
|
18974
|
+
if (exp < -4 || exp >= gPrec) {
|
|
18975
|
+
gStr = gVal.toExponential(gPrec - 1);
|
|
18976
|
+
const ePos = gStr.indexOf("e");
|
|
18977
|
+
let mantissa = gStr.slice(0, ePos);
|
|
18978
|
+
let expPart = gStr.slice(ePos);
|
|
18979
|
+
if (mantissa.includes(".")) {
|
|
18980
|
+
mantissa = mantissa.replace(/\.?0+$/, "");
|
|
18981
|
+
}
|
|
18982
|
+
expPart = expPart.replace(/e([+-])(\d)$/, "e$10$2");
|
|
18983
|
+
gStr = mantissa + expPart;
|
|
18984
|
+
} else {
|
|
18985
|
+
gStr = gVal.toPrecision(gPrec);
|
|
18986
|
+
if (gStr.includes(".")) {
|
|
18987
|
+
gStr = gStr.replace(/\.?0+$/, "");
|
|
18988
|
+
}
|
|
18989
|
+
if (gStr.includes("e")) {
|
|
18990
|
+
gStr = String(parseFloat(gStr));
|
|
18991
|
+
}
|
|
18992
|
+
}
|
|
18993
|
+
}
|
|
18994
|
+
if (ch === "G") gStr = gStr.toUpperCase();
|
|
18995
|
+
result += applyWidth(spec, gStr);
|
|
18996
|
+
}
|
|
18997
|
+
} else if (ch === "s") {
|
|
18998
|
+
const sVal = toString(flatArgs[argIdx++]);
|
|
18999
|
+
const sFlags = spec.slice(1);
|
|
19000
|
+
const sLeftAlign = sFlags.includes("-");
|
|
19001
|
+
const sWidthMatch = spec.match(/^%[^0-9]*(\d+)/);
|
|
19002
|
+
const sWidth = sWidthMatch ? parseInt(sWidthMatch[1]) : 0;
|
|
19003
|
+
if (sWidth > sVal.length) {
|
|
19004
|
+
const sPad = " ".repeat(sWidth - sVal.length);
|
|
19005
|
+
result += sLeftAlign ? sVal + sPad : sPad + sVal;
|
|
19006
|
+
} else {
|
|
19007
|
+
result += sVal;
|
|
19008
|
+
}
|
|
19009
|
+
} else if (ch === "c") {
|
|
19010
|
+
result += String.fromCharCode(
|
|
19011
|
+
Math.round(toNumber(flatArgs[argIdx++]))
|
|
19012
|
+
);
|
|
19013
|
+
} else {
|
|
19014
|
+
result += spec + ch;
|
|
19015
|
+
argIdx++;
|
|
19016
|
+
}
|
|
19017
|
+
}
|
|
19018
|
+
} else if (fmt[i] === "\\" && i + 1 < fmt.length) {
|
|
19019
|
+
i++;
|
|
19020
|
+
switch (fmt[i]) {
|
|
19021
|
+
case "n":
|
|
19022
|
+
result += "\n";
|
|
19023
|
+
break;
|
|
19024
|
+
case "t":
|
|
19025
|
+
result += " ";
|
|
19026
|
+
break;
|
|
19027
|
+
case "\\":
|
|
19028
|
+
result += "\\";
|
|
19029
|
+
break;
|
|
19030
|
+
default:
|
|
19031
|
+
result += "\\" + fmt[i];
|
|
19032
|
+
}
|
|
19033
|
+
i++;
|
|
19034
|
+
} else {
|
|
19035
|
+
result += fmt[i];
|
|
19036
|
+
i++;
|
|
19037
|
+
}
|
|
19038
|
+
}
|
|
19039
|
+
if (argIdx === startArgIdx) break;
|
|
19040
|
+
} while (argIdx < flatArgs.length);
|
|
19041
|
+
return result;
|
|
19042
|
+
}
|
|
19043
|
+
|
|
18792
19044
|
// src/numbl-core/helpers/arithmetic.ts
|
|
18793
19045
|
function toComplex(v) {
|
|
18794
19046
|
if (isRuntimeComplexNumber(v)) return { re: v.re, im: v.im };
|
|
@@ -19016,7 +19268,26 @@ function tensorElemwiseComplex(at, bt, opCode, jsOp) {
|
|
|
19016
19268
|
const isReal = resultIm.every((x) => x === 0);
|
|
19017
19269
|
return RTV.tensor(resultRe, at.shape, isReal ? void 0 : resultIm);
|
|
19018
19270
|
}
|
|
19271
|
+
function coerceToConcatString(v) {
|
|
19272
|
+
if (isRuntimeString(v)) return v;
|
|
19273
|
+
if (isRuntimeChar(v)) return v.value;
|
|
19274
|
+
if (isRuntimeLogical(v)) return v ? "true" : "false";
|
|
19275
|
+
if (isRuntimeNumber(v)) return num2strScalar(v);
|
|
19276
|
+
if (isRuntimeTensor(v) && v.data.length === 1 && !v.imag) {
|
|
19277
|
+
const x = v.data[0];
|
|
19278
|
+
if (v._isLogical === true) return x ? "true" : "false";
|
|
19279
|
+
return num2strScalar(x);
|
|
19280
|
+
}
|
|
19281
|
+
return null;
|
|
19282
|
+
}
|
|
19019
19283
|
function mAdd(a, b) {
|
|
19284
|
+
if (isRuntimeString(a) || isRuntimeString(b)) {
|
|
19285
|
+
const aStr = coerceToConcatString(a);
|
|
19286
|
+
const bStr = coerceToConcatString(b);
|
|
19287
|
+
if (aStr !== null && bStr !== null) {
|
|
19288
|
+
return RTV.string(aStr + bStr);
|
|
19289
|
+
}
|
|
19290
|
+
}
|
|
19020
19291
|
const m = matchSameShapeTensors(a, b);
|
|
19021
19292
|
if (m) {
|
|
19022
19293
|
const [at, bt] = m;
|
|
@@ -19911,6 +20182,7 @@ function extractTensorElement(base, i) {
|
|
|
19911
20182
|
const im2 = base.imag[i];
|
|
19912
20183
|
return im2 === 0 ? RTV.num(base.data[i]) : RTV.complex(base.data[i], im2);
|
|
19913
20184
|
}
|
|
20185
|
+
if (base._isLogical === true) return base.data[i] !== 0;
|
|
19914
20186
|
return RTV.num(base.data[i]);
|
|
19915
20187
|
}
|
|
19916
20188
|
function resolveIndex(idx, dimSize, boundsLimit = dimSize) {
|
|
@@ -19964,17 +20236,35 @@ function growTensor2D(base, newRows, newCols) {
|
|
|
19964
20236
|
}
|
|
19965
20237
|
function assignSlice(base, rowIndices, colIndices, rhs, curRows) {
|
|
19966
20238
|
if (isRuntimeTensor(rhs)) {
|
|
20239
|
+
const nR = rowIndices.length;
|
|
20240
|
+
const nC = colIndices.length;
|
|
19967
20241
|
const [rhsRows, rhsCols] = tensorSize2D(rhs);
|
|
19968
|
-
|
|
20242
|
+
const shapeMatches = rhsRows === nR && rhsCols === nC;
|
|
20243
|
+
const sliceIsVector = nR === 1 || nC === 1;
|
|
20244
|
+
const rhsIsVector = rhsRows === 1 || rhsCols === 1;
|
|
20245
|
+
const countMatches = rhs.data.length === nR * nC;
|
|
20246
|
+
if (!shapeMatches && !(sliceIsVector && rhsIsVector && countMatches)) {
|
|
19969
20247
|
throw new RuntimeError("Subscripted assignment dimension mismatch");
|
|
19970
20248
|
}
|
|
19971
20249
|
if (rhs.imag || base.imag) ensureImag(base);
|
|
19972
|
-
|
|
19973
|
-
for (let
|
|
19974
|
-
|
|
19975
|
-
|
|
19976
|
-
|
|
19977
|
-
|
|
20250
|
+
if (shapeMatches) {
|
|
20251
|
+
for (let ri = 0; ri < nR; ri++) {
|
|
20252
|
+
for (let ci = 0; ci < nC; ci++) {
|
|
20253
|
+
const dstLi = colMajorIndex(rowIndices[ri], colIndices[ci], curRows);
|
|
20254
|
+
const srcLi = colMajorIndex(ri, ci, rhsRows);
|
|
20255
|
+
base.data[dstLi] = rhs.data[srcLi];
|
|
20256
|
+
if (base.imag) base.imag[dstLi] = rhs.imag ? rhs.imag[srcLi] : 0;
|
|
20257
|
+
}
|
|
20258
|
+
}
|
|
20259
|
+
} else {
|
|
20260
|
+
let k = 0;
|
|
20261
|
+
for (let ci = 0; ci < nC; ci++) {
|
|
20262
|
+
for (let ri = 0; ri < nR; ri++) {
|
|
20263
|
+
const dstLi = colMajorIndex(rowIndices[ri], colIndices[ci], curRows);
|
|
20264
|
+
base.data[dstLi] = rhs.data[k];
|
|
20265
|
+
if (base.imag) base.imag[dstLi] = rhs.imag ? rhs.imag[k] : 0;
|
|
20266
|
+
k++;
|
|
20267
|
+
}
|
|
19978
20268
|
}
|
|
19979
20269
|
}
|
|
19980
20270
|
} else {
|
|
@@ -20311,6 +20601,23 @@ function indexIntoScalar(base, indices) {
|
|
|
20311
20601
|
return RTV.tensor(out, [1, count]);
|
|
20312
20602
|
}
|
|
20313
20603
|
}
|
|
20604
|
+
if (indices.length === 1 && isRuntimeTensor(indices[0])) {
|
|
20605
|
+
const idx = indices[0];
|
|
20606
|
+
for (let i = 0; i < idx.data.length; i++) {
|
|
20607
|
+
const k = Math.round(idx.data[i]);
|
|
20608
|
+
if (k !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
20609
|
+
}
|
|
20610
|
+
const n = idx.data.length;
|
|
20611
|
+
const scalarRe = isRuntimeNumber(base) ? base : base.re;
|
|
20612
|
+
const data = new FloatXArray(n);
|
|
20613
|
+
data.fill(scalarRe);
|
|
20614
|
+
if (isRuntimeComplexNumber(base) && base.im !== 0) {
|
|
20615
|
+
const im2 = new FloatXArray(n);
|
|
20616
|
+
im2.fill(base.im);
|
|
20617
|
+
return RTV.tensor(data, [...idx.shape], im2);
|
|
20618
|
+
}
|
|
20619
|
+
return RTV.tensor(data, [...idx.shape]);
|
|
20620
|
+
}
|
|
20314
20621
|
for (const idx of indices) {
|
|
20315
20622
|
if (isColonIndex(idx)) continue;
|
|
20316
20623
|
const i = toNumber(idx);
|
|
@@ -20322,6 +20629,22 @@ function indexIntoTensor(base, indices) {
|
|
|
20322
20629
|
if (indices.length === 1) {
|
|
20323
20630
|
return indexIntoTensor1D(base, indices[0]);
|
|
20324
20631
|
}
|
|
20632
|
+
if (base.shape.length > indices.length) {
|
|
20633
|
+
const collapsedShape = [];
|
|
20634
|
+
for (let d = 0; d < indices.length - 1; d++) {
|
|
20635
|
+
collapsedShape.push(base.shape[d]);
|
|
20636
|
+
}
|
|
20637
|
+
let tail = 1;
|
|
20638
|
+
for (let d = indices.length - 1; d < base.shape.length; d++) {
|
|
20639
|
+
tail *= base.shape[d];
|
|
20640
|
+
}
|
|
20641
|
+
collapsedShape.push(tail);
|
|
20642
|
+
const view = { ...base, shape: collapsedShape };
|
|
20643
|
+
if (indices.length === 2) {
|
|
20644
|
+
return indexIntoTensor2D(view, indices[0], indices[1]);
|
|
20645
|
+
}
|
|
20646
|
+
return indexIntoTensorND(view, indices);
|
|
20647
|
+
}
|
|
20325
20648
|
if (indices.length === 2) {
|
|
20326
20649
|
return indexIntoTensor2D(base, indices[0], indices[1]);
|
|
20327
20650
|
}
|
|
@@ -20350,6 +20673,11 @@ function indexIntoTensor1D(base, idx) {
|
|
|
20350
20673
|
}
|
|
20351
20674
|
function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
20352
20675
|
const [rows, cols] = tensorSize2D(base);
|
|
20676
|
+
const baseLogical = base._isLogical === true;
|
|
20677
|
+
const markLogical = (t) => {
|
|
20678
|
+
if (baseLogical && isRuntimeTensor(t)) t._isLogical = true;
|
|
20679
|
+
return t;
|
|
20680
|
+
};
|
|
20353
20681
|
if (isRuntimeNumber(rowIdx) && isColonIndex(colIdx)) {
|
|
20354
20682
|
const r = Math.round(rowIdx) - 1;
|
|
20355
20683
|
if (r < 0 || r >= rows)
|
|
@@ -20360,7 +20688,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20360
20688
|
resultData2[ci] = base.data[r + ci * rows];
|
|
20361
20689
|
if (resultImag2 && base.imag) resultImag2[ci] = base.imag[r + ci * rows];
|
|
20362
20690
|
}
|
|
20363
|
-
return RTV.tensor(resultData2, [1, cols], resultImag2);
|
|
20691
|
+
return markLogical(RTV.tensor(resultData2, [1, cols], resultImag2));
|
|
20364
20692
|
}
|
|
20365
20693
|
if (isColonIndex(rowIdx) && isRuntimeNumber(colIdx)) {
|
|
20366
20694
|
const c = Math.round(colIdx) - 1;
|
|
@@ -20372,7 +20700,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20372
20700
|
const resultImag2 = base.imag ? new FloatXArray(rows) : void 0;
|
|
20373
20701
|
if (resultImag2 && base.imag)
|
|
20374
20702
|
for (let ri = 0; ri < rows; ri++) resultImag2[ri] = base.imag[offset + ri];
|
|
20375
|
-
return RTV.tensor(resultData2, [rows, 1], resultImag2);
|
|
20703
|
+
return markLogical(RTV.tensor(resultData2, [rows, 1], resultImag2));
|
|
20376
20704
|
}
|
|
20377
20705
|
const rowIdxArr = resolveIndex(rowIdx, rows);
|
|
20378
20706
|
const colIdxArr = resolveIndex(colIdx, cols);
|
|
@@ -20394,7 +20722,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20394
20722
|
}
|
|
20395
20723
|
}
|
|
20396
20724
|
}
|
|
20397
|
-
return RTV.tensor(resultData, [numR, numC], resultImag);
|
|
20725
|
+
return markLogical(RTV.tensor(resultData, [numR, numC], resultImag));
|
|
20398
20726
|
}
|
|
20399
20727
|
function indexIntoTensorND(base, indices) {
|
|
20400
20728
|
const shape = base.shape;
|
|
@@ -20442,7 +20770,13 @@ function indexIntoTensorND(base, indices) {
|
|
|
20442
20770
|
subs[d] = 0;
|
|
20443
20771
|
}
|
|
20444
20772
|
}
|
|
20445
|
-
|
|
20773
|
+
const result = RTV.tensor(
|
|
20774
|
+
resultData,
|
|
20775
|
+
resultShape,
|
|
20776
|
+
resultImag
|
|
20777
|
+
);
|
|
20778
|
+
if (base._isLogical === true) result._isLogical = true;
|
|
20779
|
+
return result;
|
|
20446
20780
|
}
|
|
20447
20781
|
function indexIntoCell(base, indices) {
|
|
20448
20782
|
if (indices.length === 1) {
|
|
@@ -20607,6 +20941,7 @@ function indexIntoLogical(base, indices) {
|
|
|
20607
20941
|
return base;
|
|
20608
20942
|
}
|
|
20609
20943
|
function indexIntoTensorWithTensor(base, idx) {
|
|
20944
|
+
const baseLogical = base._isLogical === true;
|
|
20610
20945
|
if (idx._isLogical) {
|
|
20611
20946
|
const selected = [];
|
|
20612
20947
|
const selectedIm = [];
|
|
@@ -20620,12 +20955,19 @@ function indexIntoTensorWithTensor(base, idx) {
|
|
|
20620
20955
|
if (selected.length === 1) {
|
|
20621
20956
|
if (hasImag2 && selectedIm[0] !== 0)
|
|
20622
20957
|
return RTV.complex(selected[0], selectedIm[0]);
|
|
20958
|
+
if (baseLogical) return selected[0] !== 0;
|
|
20623
20959
|
return RTV.num(selected[0]);
|
|
20624
20960
|
}
|
|
20625
20961
|
const imOut2 = hasImag2 && selectedIm.some((x) => x !== 0) ? new FloatXArray(selectedIm) : void 0;
|
|
20626
20962
|
const isRow = base.shape.length === 2 && base.shape[0] === 1;
|
|
20627
20963
|
const outShape2 = isRow ? [1, selected.length] : [selected.length, 1];
|
|
20628
|
-
|
|
20964
|
+
const result2 = RTV.tensor(
|
|
20965
|
+
new FloatXArray(selected),
|
|
20966
|
+
outShape2,
|
|
20967
|
+
imOut2
|
|
20968
|
+
);
|
|
20969
|
+
if (baseLogical) result2._isLogical = true;
|
|
20970
|
+
return result2;
|
|
20629
20971
|
}
|
|
20630
20972
|
const resultData = [];
|
|
20631
20973
|
const hasImag = base.imag !== void 0;
|
|
@@ -20641,7 +20983,13 @@ function indexIntoTensorWithTensor(base, idx) {
|
|
|
20641
20983
|
const baseIsVector = base.shape.length <= 2 && (base.shape[0] === 1 || base.shape[1] === 1 || base.shape.length === 1);
|
|
20642
20984
|
const outShape = idxIs0x0 ? [0, 0] : baseIsVector ? base.shape[0] === 1 ? [1, resultData.length] : [resultData.length, 1] : idx.shape;
|
|
20643
20985
|
const imOut = hasImag && imIndices.some((x) => x !== 0) ? new FloatXArray(imIndices) : void 0;
|
|
20644
|
-
|
|
20986
|
+
const result = RTV.tensor(
|
|
20987
|
+
new FloatXArray(resultData),
|
|
20988
|
+
outShape,
|
|
20989
|
+
imOut
|
|
20990
|
+
);
|
|
20991
|
+
if (baseLogical) result._isLogical = true;
|
|
20992
|
+
return result;
|
|
20645
20993
|
}
|
|
20646
20994
|
function indexIntoRTValue(base, indices) {
|
|
20647
20995
|
if (isRuntimeNumber(base) || isRuntimeComplexNumber(base)) {
|
|
@@ -20991,10 +21339,18 @@ function storeIntoTensor2D(base, indices, rhs) {
|
|
|
20991
21339
|
return storeIntoTensorColonCol(base, indices[0], rhs, rows, cols);
|
|
20992
21340
|
}
|
|
20993
21341
|
if (rowIsTensor || colIsTensor) {
|
|
20994
|
-
const
|
|
20995
|
-
|
|
20996
|
-
|
|
20997
|
-
|
|
21342
|
+
const isEmpty = base.data.length === 0;
|
|
21343
|
+
let effectiveCols = cols;
|
|
21344
|
+
let effectiveRows = rows;
|
|
21345
|
+
if (isEmpty && isRuntimeTensor(rhs)) {
|
|
21346
|
+
const [rhsRowsG, rhsColsG] = tensorSize2D(rhs);
|
|
21347
|
+
if (rowIsColon && !colIsColon) effectiveRows = rhsRowsG;
|
|
21348
|
+
if (colIsColon && !rowIsColon) effectiveCols = rhsColsG;
|
|
21349
|
+
}
|
|
21350
|
+
const rowIndices = rowIsColon ? Array.from({ length: effectiveRows }, (_, i) => i) : resolveIndex(indices[0], rows, 0);
|
|
21351
|
+
const colIndices = colIsColon ? Array.from({ length: effectiveCols }, (_, i) => i) : resolveIndex(indices[1], cols, 0);
|
|
21352
|
+
const maxRow = rowIndices.length > 0 ? Math.max(...rowIndices) + 1 : effectiveRows;
|
|
21353
|
+
const maxCol = colIndices.length > 0 ? Math.max(...colIndices) + 1 : effectiveCols;
|
|
20998
21354
|
base = growTensor2D(base, maxRow, maxCol);
|
|
20999
21355
|
const [curRows] = tensorSize2D(base);
|
|
21000
21356
|
assignSlice(base, rowIndices, colIndices, rhs, curRows);
|
|
@@ -21422,6 +21778,9 @@ function horzcat(...values) {
|
|
|
21422
21778
|
if (values.some((v) => isRuntimeCell(v))) {
|
|
21423
21779
|
return cellCatAlongDim(values, 1);
|
|
21424
21780
|
}
|
|
21781
|
+
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
21782
|
+
return structCat(values);
|
|
21783
|
+
}
|
|
21425
21784
|
return catAlongDim(values, 1);
|
|
21426
21785
|
}
|
|
21427
21786
|
function vertcat(...values) {
|
|
@@ -21433,8 +21792,47 @@ function vertcat(...values) {
|
|
|
21433
21792
|
if (values.some((v) => isRuntimeCell(v))) {
|
|
21434
21793
|
return cellCatAlongDim(values, 0);
|
|
21435
21794
|
}
|
|
21795
|
+
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
21796
|
+
return structCat(values);
|
|
21797
|
+
}
|
|
21436
21798
|
return catAlongDim(values, 0);
|
|
21437
21799
|
}
|
|
21800
|
+
function structCat(values) {
|
|
21801
|
+
const elements = [];
|
|
21802
|
+
let fieldNames = null;
|
|
21803
|
+
for (const v of values) {
|
|
21804
|
+
if (isRuntimeStruct(v)) {
|
|
21805
|
+
const keys = Array.from(v.fields.keys());
|
|
21806
|
+
if (fieldNames === null) fieldNames = keys;
|
|
21807
|
+
else if (!arraysEqual(fieldNames, keys)) {
|
|
21808
|
+
throw new RuntimeError(
|
|
21809
|
+
"Cannot concatenate structs with different field names"
|
|
21810
|
+
);
|
|
21811
|
+
}
|
|
21812
|
+
elements.push(v);
|
|
21813
|
+
} else if (isRuntimeStructArray(v)) {
|
|
21814
|
+
if (fieldNames === null) fieldNames = [...v.fieldNames];
|
|
21815
|
+
else if (!arraysEqual(fieldNames, v.fieldNames)) {
|
|
21816
|
+
throw new RuntimeError(
|
|
21817
|
+
"Cannot concatenate struct arrays with different field names"
|
|
21818
|
+
);
|
|
21819
|
+
}
|
|
21820
|
+
for (const e of v.elements) elements.push(e);
|
|
21821
|
+
} else {
|
|
21822
|
+
if (isRuntimeTensor(v) && v.data.length === 0 && v.shape.every((d) => d === 0)) {
|
|
21823
|
+
continue;
|
|
21824
|
+
}
|
|
21825
|
+
throw new RuntimeError(`Cannot concatenate ${kstr(v)} into struct`);
|
|
21826
|
+
}
|
|
21827
|
+
}
|
|
21828
|
+
if (fieldNames === null) fieldNames = [];
|
|
21829
|
+
return RTV.structArray(fieldNames, elements);
|
|
21830
|
+
}
|
|
21831
|
+
function arraysEqual(a, b) {
|
|
21832
|
+
if (a.length !== b.length) return false;
|
|
21833
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
21834
|
+
return true;
|
|
21835
|
+
}
|
|
21438
21836
|
function toSparseForCat(v) {
|
|
21439
21837
|
if (isRuntimeSparseMatrix(v)) return v;
|
|
21440
21838
|
if (isRuntimeNumber(v)) {
|
|
@@ -22042,7 +22440,7 @@ var token_config_default = {
|
|
|
22042
22440
|
stripUnderscores: true,
|
|
22043
22441
|
integerToken: "Integer",
|
|
22044
22442
|
floatToken: "Float",
|
|
22045
|
-
exponentChars: ["e", "E"],
|
|
22443
|
+
exponentChars: ["e", "E", "d", "D"],
|
|
22046
22444
|
decimalPoint: ".",
|
|
22047
22445
|
dotOperatorPrefixes: ["*", "/", "\\", "^"]
|
|
22048
22446
|
},
|
|
@@ -22347,6 +22745,9 @@ function tokenizeDetailed(input) {
|
|
|
22347
22745
|
if (numCfg.stripUnderscores) {
|
|
22348
22746
|
lexeme = lexeme.replace(/_/g, "");
|
|
22349
22747
|
}
|
|
22748
|
+
if (isFloat) {
|
|
22749
|
+
lexeme = lexeme.replace(/[dD]/g, "e");
|
|
22750
|
+
}
|
|
22350
22751
|
const tok = isFloat ? Token[numCfg.floatToken] : Token[numCfg.integerToken];
|
|
22351
22752
|
lineStart = false;
|
|
22352
22753
|
out.push({ token: tok, lexeme, start, end: pos });
|
|
@@ -27507,224 +27908,88 @@ defineBuiltin({
|
|
|
27507
27908
|
}
|
|
27508
27909
|
});
|
|
27509
27910
|
|
|
27510
|
-
// src/numbl-core/
|
|
27511
|
-
|
|
27512
|
-
|
|
27513
|
-
|
|
27514
|
-
|
|
27515
|
-
|
|
27516
|
-
|
|
27517
|
-
|
|
27518
|
-
|
|
27519
|
-
if (
|
|
27520
|
-
|
|
27521
|
-
|
|
27522
|
-
|
|
27523
|
-
const expPart0 = s.slice(ePos);
|
|
27524
|
-
if (mantissa.includes(".")) mantissa = mantissa.replace(/\.?0+$/, "");
|
|
27525
|
-
const expPart = expPart0.replace(/([eE][+-])(\d)$/, "$10$2");
|
|
27526
|
-
s = mantissa + expPart;
|
|
27527
|
-
} else {
|
|
27528
|
-
if (Number.isInteger(n)) return String(n);
|
|
27529
|
-
s = n.toPrecision(prec);
|
|
27530
|
-
if (s.includes(".")) s = s.replace(/\.?0+$/, "");
|
|
27911
|
+
// src/numbl-core/interpreter/builtins/logical.ts
|
|
27912
|
+
var LOGICAL_KINDS = /* @__PURE__ */ new Set([
|
|
27913
|
+
"number",
|
|
27914
|
+
"boolean",
|
|
27915
|
+
"tensor",
|
|
27916
|
+
"sparse_matrix"
|
|
27917
|
+
]);
|
|
27918
|
+
function binaryLogicalMatch(argTypes) {
|
|
27919
|
+
if (argTypes.length !== 2) return null;
|
|
27920
|
+
if (!LOGICAL_KINDS.has(argTypes[0].kind)) return null;
|
|
27921
|
+
if (!LOGICAL_KINDS.has(argTypes[1].kind)) return null;
|
|
27922
|
+
if (argTypes[0].kind === "tensor" || argTypes[1].kind === "tensor") {
|
|
27923
|
+
return [{ kind: "tensor", isComplex: false, isLogical: true }];
|
|
27531
27924
|
}
|
|
27532
|
-
|
|
27533
|
-
}
|
|
27534
|
-
function applyWidth(spec, str) {
|
|
27535
|
-
const m = spec.match(/^%([-+ #]*)0?(\d+)?/);
|
|
27536
|
-
if (!m) return str;
|
|
27537
|
-
const explicitFlags = m[1] || "";
|
|
27538
|
-
const leftAlign = explicitFlags.includes("-");
|
|
27539
|
-
const afterPercent = spec.slice(1);
|
|
27540
|
-
const flagAndWidth = afterPercent.match(/^([-+ #]*)(0?)(\d+)?/);
|
|
27541
|
-
const zeroFlag = flagAndWidth ? flagAndWidth[2] === "0" : false;
|
|
27542
|
-
const width = flagAndWidth && flagAndWidth[3] ? parseInt(flagAndWidth[3]) : 0;
|
|
27543
|
-
if (width <= str.length) return str;
|
|
27544
|
-
const zeroPad = !leftAlign && zeroFlag;
|
|
27545
|
-
const padLen = width - str.length;
|
|
27546
|
-
if (leftAlign) return str + " ".repeat(padLen);
|
|
27547
|
-
if (zeroPad) {
|
|
27548
|
-
if (str[0] === "-" || str[0] === "+") {
|
|
27549
|
-
return str[0] + "0".repeat(padLen) + str.slice(1);
|
|
27550
|
-
}
|
|
27551
|
-
return "0".repeat(padLen) + str;
|
|
27925
|
+
if (argTypes[0].kind === "sparse_matrix" || argTypes[1].kind === "sparse_matrix") {
|
|
27926
|
+
return [{ kind: "tensor", isComplex: false, isLogical: true }];
|
|
27552
27927
|
}
|
|
27553
|
-
return
|
|
27928
|
+
return [{ kind: "boolean" }];
|
|
27554
27929
|
}
|
|
27555
|
-
function
|
|
27556
|
-
|
|
27557
|
-
|
|
27558
|
-
|
|
27559
|
-
|
|
27560
|
-
|
|
27561
|
-
|
|
27562
|
-
|
|
27563
|
-
flatArgs.push(arg);
|
|
27564
|
-
}
|
|
27930
|
+
function isTensorLike(v) {
|
|
27931
|
+
return isRuntimeTensor(v) || isRuntimeSparseMatrix(v);
|
|
27932
|
+
}
|
|
27933
|
+
function applyBinaryLogical(args, op, scalarFn) {
|
|
27934
|
+
const a = args[0];
|
|
27935
|
+
const b = args[1];
|
|
27936
|
+
if (isTensorLike(a) || isTensorLike(b)) {
|
|
27937
|
+
return elementWiseLogicalOp(a, b, op);
|
|
27565
27938
|
}
|
|
27566
|
-
|
|
27567
|
-
|
|
27568
|
-
|
|
27569
|
-
|
|
27570
|
-
|
|
27571
|
-
|
|
27572
|
-
|
|
27573
|
-
|
|
27574
|
-
|
|
27575
|
-
|
|
27576
|
-
|
|
27577
|
-
|
|
27578
|
-
|
|
27579
|
-
|
|
27580
|
-
|
|
27581
|
-
|
|
27582
|
-
|
|
27583
|
-
|
|
27584
|
-
|
|
27585
|
-
|
|
27586
|
-
|
|
27587
|
-
|
|
27588
|
-
|
|
27589
|
-
|
|
27590
|
-
|
|
27591
|
-
|
|
27592
|
-
|
|
27593
|
-
|
|
27594
|
-
|
|
27595
|
-
|
|
27596
|
-
|
|
27597
|
-
|
|
27598
|
-
|
|
27599
|
-
|
|
27600
|
-
|
|
27601
|
-
|
|
27602
|
-
|
|
27603
|
-
|
|
27604
|
-
|
|
27605
|
-
|
|
27606
|
-
|
|
27607
|
-
|
|
27608
|
-
|
|
27609
|
-
|
|
27610
|
-
|
|
27611
|
-
|
|
27612
|
-
|
|
27613
|
-
}
|
|
27614
|
-
} else if (ch === "f") {
|
|
27615
|
-
const n = toNumber(flatArgs[argIdx++]);
|
|
27616
|
-
if (!isFinite(n) || isNaN(n)) {
|
|
27617
|
-
result += applyWidth(spec, numStr(n));
|
|
27618
|
-
} else {
|
|
27619
|
-
const fFlags = spec.slice(1);
|
|
27620
|
-
const fHasPlus = fFlags.includes("+");
|
|
27621
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
27622
|
-
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
27623
|
-
const formatted = n.toFixed(prec);
|
|
27624
|
-
const fSign = n < 0 ? "" : fHasPlus ? "+" : "";
|
|
27625
|
-
result += applyWidth(spec, fSign + formatted);
|
|
27626
|
-
}
|
|
27627
|
-
} else if (ch === "e" || ch === "E") {
|
|
27628
|
-
const n = toNumber(flatArgs[argIdx++]);
|
|
27629
|
-
if (!isFinite(n) || isNaN(n)) {
|
|
27630
|
-
result += applyWidth(spec, numStr(n));
|
|
27631
|
-
} else {
|
|
27632
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
27633
|
-
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
27634
|
-
let eStr = n.toExponential(prec);
|
|
27635
|
-
eStr = eStr.replace(/e([+-])(\d)$/, "e$10$2");
|
|
27636
|
-
if (ch === "E") eStr = eStr.toUpperCase();
|
|
27637
|
-
result += applyWidth(spec, eStr);
|
|
27638
|
-
}
|
|
27639
|
-
} else if (ch === "x" || ch === "X") {
|
|
27640
|
-
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
27641
|
-
let s = Math.abs(n).toString(16);
|
|
27642
|
-
if (ch === "X") s = s.toUpperCase();
|
|
27643
|
-
result += applyWidth(spec, s);
|
|
27644
|
-
} else if (ch === "o") {
|
|
27645
|
-
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
27646
|
-
result += applyWidth(spec, Math.abs(n).toString(8));
|
|
27647
|
-
} else if (ch === "g" || ch === "G") {
|
|
27648
|
-
const gVal = toNumber(flatArgs[argIdx++]);
|
|
27649
|
-
if (!isFinite(gVal) || isNaN(gVal)) {
|
|
27650
|
-
result += applyWidth(spec, numStr(gVal));
|
|
27651
|
-
} else {
|
|
27652
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
27653
|
-
const gPrec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
27654
|
-
let gStr;
|
|
27655
|
-
if (gVal === 0) {
|
|
27656
|
-
gStr = "0";
|
|
27657
|
-
} else {
|
|
27658
|
-
const exp = Math.floor(Math.log10(Math.abs(gVal)));
|
|
27659
|
-
if (exp < -4 || exp >= gPrec) {
|
|
27660
|
-
gStr = gVal.toExponential(gPrec - 1);
|
|
27661
|
-
const ePos = gStr.indexOf("e");
|
|
27662
|
-
let mantissa = gStr.slice(0, ePos);
|
|
27663
|
-
let expPart = gStr.slice(ePos);
|
|
27664
|
-
if (mantissa.includes(".")) {
|
|
27665
|
-
mantissa = mantissa.replace(/\.?0+$/, "");
|
|
27666
|
-
}
|
|
27667
|
-
expPart = expPart.replace(/e([+-])(\d)$/, "e$10$2");
|
|
27668
|
-
gStr = mantissa + expPart;
|
|
27669
|
-
} else {
|
|
27670
|
-
gStr = gVal.toPrecision(gPrec);
|
|
27671
|
-
if (gStr.includes(".")) {
|
|
27672
|
-
gStr = gStr.replace(/\.?0+$/, "");
|
|
27673
|
-
}
|
|
27674
|
-
if (gStr.includes("e")) {
|
|
27675
|
-
gStr = String(parseFloat(gStr));
|
|
27676
|
-
}
|
|
27677
|
-
}
|
|
27678
|
-
}
|
|
27679
|
-
if (ch === "G") gStr = gStr.toUpperCase();
|
|
27680
|
-
result += applyWidth(spec, gStr);
|
|
27681
|
-
}
|
|
27682
|
-
} else if (ch === "s") {
|
|
27683
|
-
const sVal = toString(flatArgs[argIdx++]);
|
|
27684
|
-
const sFlags = spec.slice(1);
|
|
27685
|
-
const sLeftAlign = sFlags.includes("-");
|
|
27686
|
-
const sWidthMatch = spec.match(/^%[^0-9]*(\d+)/);
|
|
27687
|
-
const sWidth = sWidthMatch ? parseInt(sWidthMatch[1]) : 0;
|
|
27688
|
-
if (sWidth > sVal.length) {
|
|
27689
|
-
const sPad = " ".repeat(sWidth - sVal.length);
|
|
27690
|
-
result += sLeftAlign ? sVal + sPad : sPad + sVal;
|
|
27691
|
-
} else {
|
|
27692
|
-
result += sVal;
|
|
27693
|
-
}
|
|
27694
|
-
} else if (ch === "c") {
|
|
27695
|
-
result += String.fromCharCode(
|
|
27696
|
-
Math.round(toNumber(flatArgs[argIdx++]))
|
|
27697
|
-
);
|
|
27698
|
-
} else {
|
|
27699
|
-
result += spec + ch;
|
|
27700
|
-
argIdx++;
|
|
27701
|
-
}
|
|
27702
|
-
}
|
|
27703
|
-
} else if (fmt[i] === "\\" && i + 1 < fmt.length) {
|
|
27704
|
-
i++;
|
|
27705
|
-
switch (fmt[i]) {
|
|
27706
|
-
case "n":
|
|
27707
|
-
result += "\n";
|
|
27708
|
-
break;
|
|
27709
|
-
case "t":
|
|
27710
|
-
result += " ";
|
|
27711
|
-
break;
|
|
27712
|
-
case "\\":
|
|
27713
|
-
result += "\\";
|
|
27714
|
-
break;
|
|
27715
|
-
default:
|
|
27716
|
-
result += "\\" + fmt[i];
|
|
27939
|
+
return RTV.logical(scalarFn(toBool(a), toBool(b)));
|
|
27940
|
+
}
|
|
27941
|
+
var orCase = {
|
|
27942
|
+
match: binaryLogicalMatch,
|
|
27943
|
+
apply: (args) => applyBinaryLogical(
|
|
27944
|
+
args,
|
|
27945
|
+
(x, y) => x !== 0 || y !== 0 ? 1 : 0,
|
|
27946
|
+
(a, b) => a || b
|
|
27947
|
+
)
|
|
27948
|
+
};
|
|
27949
|
+
defineBuiltin({
|
|
27950
|
+
name: "or",
|
|
27951
|
+
help: {
|
|
27952
|
+
signatures: ["TF = or(A, B)"],
|
|
27953
|
+
description: "Logical OR. Functional form of A | B; returns a logical scalar or tensor."
|
|
27954
|
+
},
|
|
27955
|
+
cases: [orCase]
|
|
27956
|
+
});
|
|
27957
|
+
var andCase = {
|
|
27958
|
+
match: binaryLogicalMatch,
|
|
27959
|
+
apply: (args) => applyBinaryLogical(
|
|
27960
|
+
args,
|
|
27961
|
+
(x, y) => x !== 0 && y !== 0 ? 1 : 0,
|
|
27962
|
+
(a, b) => a && b
|
|
27963
|
+
)
|
|
27964
|
+
};
|
|
27965
|
+
defineBuiltin({
|
|
27966
|
+
name: "and",
|
|
27967
|
+
help: {
|
|
27968
|
+
signatures: ["TF = and(A, B)"],
|
|
27969
|
+
description: "Logical AND. Functional form of A & B; returns a logical scalar or tensor."
|
|
27970
|
+
},
|
|
27971
|
+
cases: [andCase]
|
|
27972
|
+
});
|
|
27973
|
+
defineBuiltin({
|
|
27974
|
+
name: "not",
|
|
27975
|
+
help: {
|
|
27976
|
+
signatures: ["TF = not(A)"],
|
|
27977
|
+
description: "Logical negation. Functional form of ~A; returns a logical scalar or tensor."
|
|
27978
|
+
},
|
|
27979
|
+
cases: [
|
|
27980
|
+
{
|
|
27981
|
+
match: (argTypes) => {
|
|
27982
|
+
if (argTypes.length !== 1) return null;
|
|
27983
|
+
if (!LOGICAL_KINDS.has(argTypes[0].kind)) return null;
|
|
27984
|
+
if (argTypes[0].kind === "tensor" || argTypes[0].kind === "sparse_matrix") {
|
|
27985
|
+
return [{ kind: "tensor", isComplex: false, isLogical: true }];
|
|
27717
27986
|
}
|
|
27718
|
-
|
|
27719
|
-
}
|
|
27720
|
-
|
|
27721
|
-
i++;
|
|
27722
|
-
}
|
|
27987
|
+
return [{ kind: "boolean" }];
|
|
27988
|
+
},
|
|
27989
|
+
apply: (args) => not(args[0])
|
|
27723
27990
|
}
|
|
27724
|
-
|
|
27725
|
-
|
|
27726
|
-
return result;
|
|
27727
|
-
}
|
|
27991
|
+
]
|
|
27992
|
+
});
|
|
27728
27993
|
|
|
27729
27994
|
// src/numbl-core/interpreter/builtins/utility.ts
|
|
27730
27995
|
function sparseToDense2(S) {
|
|
@@ -27834,7 +28099,7 @@ defineBuiltin({
|
|
|
27834
28099
|
{
|
|
27835
28100
|
match: (argTypes) => {
|
|
27836
28101
|
if (argTypes.length < 1) return null;
|
|
27837
|
-
return [
|
|
28102
|
+
return [];
|
|
27838
28103
|
},
|
|
27839
28104
|
apply: (args) => {
|
|
27840
28105
|
const v = args[0];
|
|
@@ -27855,7 +28120,7 @@ defineBuiltin({
|
|
|
27855
28120
|
const msg = args.length > 1 ? textValue(args[1]) ?? String(args[1]) : "Assertion failed";
|
|
27856
28121
|
throw new Error(msg);
|
|
27857
28122
|
}
|
|
27858
|
-
return 0;
|
|
28123
|
+
return void 0;
|
|
27859
28124
|
}
|
|
27860
28125
|
}
|
|
27861
28126
|
]
|
|
@@ -27866,7 +28131,7 @@ defineBuiltin({
|
|
|
27866
28131
|
{
|
|
27867
28132
|
match: (argTypes) => {
|
|
27868
28133
|
if (argTypes.length === 0) return null;
|
|
27869
|
-
return [
|
|
28134
|
+
return [];
|
|
27870
28135
|
},
|
|
27871
28136
|
apply: (args) => {
|
|
27872
28137
|
const first = textValue(args[0]) ?? String(args[0]);
|
|
@@ -28538,6 +28803,19 @@ defineBuiltin({
|
|
|
28538
28803
|
name: "NaN",
|
|
28539
28804
|
cases: arrayConstructorCases(nanFill, NaN)
|
|
28540
28805
|
});
|
|
28806
|
+
function infFill(shape) {
|
|
28807
|
+
const data = new FloatXArray(numel(shape));
|
|
28808
|
+
data.fill(Infinity);
|
|
28809
|
+
return makeTensor(data, void 0, shape);
|
|
28810
|
+
}
|
|
28811
|
+
defineBuiltin({
|
|
28812
|
+
name: "inf",
|
|
28813
|
+
cases: arrayConstructorCases(infFill, Infinity)
|
|
28814
|
+
});
|
|
28815
|
+
defineBuiltin({
|
|
28816
|
+
name: "Inf",
|
|
28817
|
+
cases: arrayConstructorCases(infFill, Infinity)
|
|
28818
|
+
});
|
|
28541
28819
|
defineBuiltin({
|
|
28542
28820
|
name: "eye",
|
|
28543
28821
|
cases: arrayConstructorCases(
|
|
@@ -29375,19 +29653,33 @@ function preserveTextType(t) {
|
|
|
29375
29653
|
if (t.kind === "string") return { kind: "string" };
|
|
29376
29654
|
return null;
|
|
29377
29655
|
}
|
|
29656
|
+
function applyTextFn(v, fn) {
|
|
29657
|
+
if (isRuntimeCell(v)) {
|
|
29658
|
+
const out = new Array(v.data.length);
|
|
29659
|
+
for (let i = 0; i < v.data.length; i++) {
|
|
29660
|
+
out[i] = applyTextFn(v.data[i], fn);
|
|
29661
|
+
}
|
|
29662
|
+
return RTV.cell(out, [...v.shape]);
|
|
29663
|
+
}
|
|
29664
|
+
if (isRuntimeChar(v)) return RTV.char(fn(v.value));
|
|
29665
|
+
if (isRuntimeString(v)) return RTV.string(fn(toString(v)));
|
|
29666
|
+
return v;
|
|
29667
|
+
}
|
|
29378
29668
|
function textPreserveResolve(fn) {
|
|
29379
29669
|
return (argTypes) => {
|
|
29380
29670
|
if (argTypes.length !== 1) return null;
|
|
29381
|
-
const
|
|
29671
|
+
const t = argTypes[0];
|
|
29672
|
+
if (t.kind === "cell") {
|
|
29673
|
+
return {
|
|
29674
|
+
outputTypes: [{ kind: "cell" }],
|
|
29675
|
+
apply: (args) => applyTextFn(args[0], fn)
|
|
29676
|
+
};
|
|
29677
|
+
}
|
|
29678
|
+
const out = preserveTextType(t);
|
|
29382
29679
|
if (!out) return null;
|
|
29383
29680
|
return {
|
|
29384
29681
|
outputTypes: [out],
|
|
29385
|
-
apply: (args) =>
|
|
29386
|
-
const v = args[0];
|
|
29387
|
-
const s = toString(v);
|
|
29388
|
-
const result = fn(s);
|
|
29389
|
-
return isRuntimeChar(v) ? RTV.char(result) : RTV.string(result);
|
|
29390
|
-
}
|
|
29682
|
+
apply: (args) => applyTextFn(args[0], fn)
|
|
29391
29683
|
};
|
|
29392
29684
|
};
|
|
29393
29685
|
}
|
|
@@ -33150,11 +33442,15 @@ defineBuiltin({
|
|
|
33150
33442
|
apply: (args) => {
|
|
33151
33443
|
if (args.length !== 2)
|
|
33152
33444
|
throw new RuntimeError("kron requires 2 arguments");
|
|
33153
|
-
const
|
|
33154
|
-
|
|
33155
|
-
|
|
33156
|
-
|
|
33445
|
+
const coerce = (v) => {
|
|
33446
|
+
if (isRuntimeNumber(v))
|
|
33447
|
+
return RTV.tensor(new FloatXArray([v]), [1, 1]);
|
|
33448
|
+
if (isRuntimeSparseMatrix(v)) return sparseToDense(v);
|
|
33449
|
+
if (isRuntimeTensor(v)) return v;
|
|
33157
33450
|
throw new RuntimeError("kron: arguments must be numeric");
|
|
33451
|
+
};
|
|
33452
|
+
const A = coerce(args[0]);
|
|
33453
|
+
const B = coerce(args[1]);
|
|
33158
33454
|
const [m, n] = tensorSize2D(A);
|
|
33159
33455
|
const [p2, q] = tensorSize2D(B);
|
|
33160
33456
|
const rows = m * p2, cols = n * q;
|
|
@@ -35472,6 +35768,65 @@ defineBuiltin({
|
|
|
35472
35768
|
}
|
|
35473
35769
|
]
|
|
35474
35770
|
});
|
|
35771
|
+
defineBuiltin({
|
|
35772
|
+
name: "bitget",
|
|
35773
|
+
cases: [
|
|
35774
|
+
{
|
|
35775
|
+
match: (argTypes) => {
|
|
35776
|
+
if (argTypes.length !== 2) return null;
|
|
35777
|
+
return [{ kind: "unknown" }];
|
|
35778
|
+
},
|
|
35779
|
+
// bitget(A, bit) returns bit number `bit` (1-based, 1 = LSB) of each
|
|
35780
|
+
// element of A. MATLAB supports vector `bit` with broadcasting; we
|
|
35781
|
+
// match the scalar-or-same-shape rules used by the other bitwise ops.
|
|
35782
|
+
apply: (args) => bitwiseOp(
|
|
35783
|
+
args[0],
|
|
35784
|
+
args[1],
|
|
35785
|
+
(a, bit) => {
|
|
35786
|
+
const b = Math.round(bit);
|
|
35787
|
+
if (b < 1) return 0;
|
|
35788
|
+
if (b <= 31) return a >>> b - 1 & 1;
|
|
35789
|
+
const bi = BigInt(a);
|
|
35790
|
+
return Number(bi >> BigInt(b - 1) & 1n);
|
|
35791
|
+
},
|
|
35792
|
+
"bitget"
|
|
35793
|
+
)
|
|
35794
|
+
}
|
|
35795
|
+
]
|
|
35796
|
+
});
|
|
35797
|
+
defineBuiltin({
|
|
35798
|
+
name: "bitset",
|
|
35799
|
+
cases: [
|
|
35800
|
+
{
|
|
35801
|
+
match: (argTypes) => {
|
|
35802
|
+
if (argTypes.length < 2 || argTypes.length > 3) return null;
|
|
35803
|
+
return [{ kind: "unknown" }];
|
|
35804
|
+
},
|
|
35805
|
+
// bitset(A, bit) → set bit to 1
|
|
35806
|
+
// bitset(A, bit, v) → set bit to v (0 or 1)
|
|
35807
|
+
apply: (args) => {
|
|
35808
|
+
const v = args.length >= 3 ? Math.round(toNumber(args[2])) : 1;
|
|
35809
|
+
return bitwiseOp(
|
|
35810
|
+
args[0],
|
|
35811
|
+
args[1],
|
|
35812
|
+
(a, bit) => {
|
|
35813
|
+
const b = Math.round(bit);
|
|
35814
|
+
if (b < 1) return a;
|
|
35815
|
+
if (b <= 31) {
|
|
35816
|
+
const mask2 = 1 << b - 1;
|
|
35817
|
+
return v ? a | mask2 : a & ~mask2;
|
|
35818
|
+
}
|
|
35819
|
+
const bi = BigInt(a);
|
|
35820
|
+
const mask = 1n << BigInt(b - 1);
|
|
35821
|
+
const out = v ? bi | mask : bi & ~mask;
|
|
35822
|
+
return Number(out);
|
|
35823
|
+
},
|
|
35824
|
+
"bitset"
|
|
35825
|
+
);
|
|
35826
|
+
}
|
|
35827
|
+
}
|
|
35828
|
+
]
|
|
35829
|
+
});
|
|
35475
35830
|
function coordTransform(name, nArgs, nOut, fn) {
|
|
35476
35831
|
defineBuiltin({
|
|
35477
35832
|
name,
|
|
@@ -36601,6 +36956,131 @@ defineBuiltin({
|
|
|
36601
36956
|
}
|
|
36602
36957
|
]
|
|
36603
36958
|
});
|
|
36959
|
+
var INT_RANGES = [
|
|
36960
|
+
{ name: "int8", min: -128, max: 127 },
|
|
36961
|
+
{ name: "int16", min: -32768, max: 32767 },
|
|
36962
|
+
{ name: "int32", min: -2147483648, max: 2147483647 },
|
|
36963
|
+
// int64/uint64 can't represent their full native range as doubles;
|
|
36964
|
+
// clamp at Number.MAX_SAFE_INTEGER to avoid silent precision loss.
|
|
36965
|
+
{
|
|
36966
|
+
name: "int64",
|
|
36967
|
+
min: -Number.MAX_SAFE_INTEGER,
|
|
36968
|
+
max: Number.MAX_SAFE_INTEGER
|
|
36969
|
+
},
|
|
36970
|
+
{ name: "uint8", min: 0, max: 255 },
|
|
36971
|
+
{ name: "uint16", min: 0, max: 65535 },
|
|
36972
|
+
{ name: "uint32", min: 0, max: 4294967295 },
|
|
36973
|
+
{ name: "uint64", min: 0, max: Number.MAX_SAFE_INTEGER }
|
|
36974
|
+
];
|
|
36975
|
+
function saturateRoundToward(x, min, max) {
|
|
36976
|
+
if (isNaN(x)) return 0;
|
|
36977
|
+
const r = x >= 0 ? Math.floor(x + 0.5) : -Math.floor(-x + 0.5);
|
|
36978
|
+
if (r < min) return min;
|
|
36979
|
+
if (r > max) return max;
|
|
36980
|
+
return r;
|
|
36981
|
+
}
|
|
36982
|
+
for (const { name, min, max } of INT_RANGES) {
|
|
36983
|
+
defineBuiltin({
|
|
36984
|
+
name,
|
|
36985
|
+
cases: [
|
|
36986
|
+
{
|
|
36987
|
+
match: (argTypes) => {
|
|
36988
|
+
if (argTypes.length !== 1) return null;
|
|
36989
|
+
const a = argTypes[0];
|
|
36990
|
+
if (a.kind === "number" || a.kind === "boolean" || a.kind === "char" || a.kind === "complex_or_number")
|
|
36991
|
+
return [{ kind: "number" }];
|
|
36992
|
+
if (a.kind === "tensor")
|
|
36993
|
+
return [
|
|
36994
|
+
{
|
|
36995
|
+
kind: "tensor",
|
|
36996
|
+
isComplex: false,
|
|
36997
|
+
shape: a.shape,
|
|
36998
|
+
ndim: a.ndim
|
|
36999
|
+
}
|
|
37000
|
+
];
|
|
37001
|
+
return null;
|
|
37002
|
+
},
|
|
37003
|
+
apply: (args) => {
|
|
37004
|
+
const v = args[0];
|
|
37005
|
+
if (isRuntimeNumber(v))
|
|
37006
|
+
return RTV.num(saturateRoundToward(v, min, max));
|
|
37007
|
+
if (isRuntimeLogical(v)) return RTV.num(v ? 1 : 0);
|
|
37008
|
+
if (isRuntimeComplexNumber(v))
|
|
37009
|
+
return RTV.num(saturateRoundToward(v.re, min, max));
|
|
37010
|
+
if (isRuntimeChar(v)) {
|
|
37011
|
+
if (v.value.length === 0)
|
|
37012
|
+
return RTV.tensor(new FloatXArray(0), [0, 0]);
|
|
37013
|
+
if (v.value.length === 1)
|
|
37014
|
+
return RTV.num(
|
|
37015
|
+
saturateRoundToward(v.value.charCodeAt(0), min, max)
|
|
37016
|
+
);
|
|
37017
|
+
const out = new FloatXArray(v.value.length);
|
|
37018
|
+
for (let i = 0; i < v.value.length; i++) {
|
|
37019
|
+
out[i] = saturateRoundToward(v.value.charCodeAt(i), min, max);
|
|
37020
|
+
}
|
|
37021
|
+
return RTV.row(Array.from(out));
|
|
37022
|
+
}
|
|
37023
|
+
if (isRuntimeTensor(v)) {
|
|
37024
|
+
const data = new FloatXArray(v.data.length);
|
|
37025
|
+
for (let i = 0; i < v.data.length; i++) {
|
|
37026
|
+
data[i] = saturateRoundToward(v.data[i], min, max);
|
|
37027
|
+
}
|
|
37028
|
+
return RTV.tensor(data, [...v.shape]);
|
|
37029
|
+
}
|
|
37030
|
+
return RTV.num(saturateRoundToward(toNumber(v), min, max));
|
|
37031
|
+
}
|
|
37032
|
+
}
|
|
37033
|
+
]
|
|
37034
|
+
});
|
|
37035
|
+
}
|
|
37036
|
+
defineBuiltin({
|
|
37037
|
+
name: "idivide",
|
|
37038
|
+
cases: [
|
|
37039
|
+
{
|
|
37040
|
+
match: (argTypes) => {
|
|
37041
|
+
if (argTypes.length < 2 || argTypes.length > 3) return null;
|
|
37042
|
+
return [{ kind: "unknown" }];
|
|
37043
|
+
},
|
|
37044
|
+
apply: (args) => {
|
|
37045
|
+
const divFix = (a2, b2) => {
|
|
37046
|
+
if (b2 === 0) {
|
|
37047
|
+
return 0;
|
|
37048
|
+
}
|
|
37049
|
+
const q = a2 / b2;
|
|
37050
|
+
return q >= 0 ? Math.floor(q) : -Math.floor(-q);
|
|
37051
|
+
};
|
|
37052
|
+
const a = args[0];
|
|
37053
|
+
const b = args[1];
|
|
37054
|
+
if (isRuntimeNumber(a) && isRuntimeNumber(b)) {
|
|
37055
|
+
return RTV.num(divFix(a, b));
|
|
37056
|
+
}
|
|
37057
|
+
if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
|
|
37058
|
+
const bv = b;
|
|
37059
|
+
const data = new FloatXArray(a.data.length);
|
|
37060
|
+
for (let i = 0; i < a.data.length; i++)
|
|
37061
|
+
data[i] = divFix(a.data[i], bv);
|
|
37062
|
+
return RTV.tensor(data, [...a.shape]);
|
|
37063
|
+
}
|
|
37064
|
+
if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
|
|
37065
|
+
const av = a;
|
|
37066
|
+
const data = new FloatXArray(b.data.length);
|
|
37067
|
+
for (let i = 0; i < b.data.length; i++)
|
|
37068
|
+
data[i] = divFix(av, b.data[i]);
|
|
37069
|
+
return RTV.tensor(data, [...b.shape]);
|
|
37070
|
+
}
|
|
37071
|
+
if (isRuntimeTensor(a) && isRuntimeTensor(b)) {
|
|
37072
|
+
if (a.data.length !== b.data.length)
|
|
37073
|
+
throw new RuntimeError("idivide: arrays must be the same size");
|
|
37074
|
+
const data = new FloatXArray(a.data.length);
|
|
37075
|
+
for (let i = 0; i < a.data.length; i++)
|
|
37076
|
+
data[i] = divFix(a.data[i], b.data[i]);
|
|
37077
|
+
return RTV.tensor(data, [...a.shape]);
|
|
37078
|
+
}
|
|
37079
|
+
throw new RuntimeError("idivide: arguments must be numeric");
|
|
37080
|
+
}
|
|
37081
|
+
}
|
|
37082
|
+
]
|
|
37083
|
+
});
|
|
36604
37084
|
defineBuiltin({
|
|
36605
37085
|
name: "logical",
|
|
36606
37086
|
cases: [
|
|
@@ -37983,6 +38463,24 @@ registerIBuiltin({
|
|
|
37983
38463
|
}
|
|
37984
38464
|
})
|
|
37985
38465
|
});
|
|
38466
|
+
function getMexExt() {
|
|
38467
|
+
if (typeof process === "undefined") return "";
|
|
38468
|
+
const platform = process.platform;
|
|
38469
|
+
const cpuArch = process.arch;
|
|
38470
|
+
if (platform === "win32") return "mexw64";
|
|
38471
|
+
if (platform === "darwin")
|
|
38472
|
+
return cpuArch === "arm64" ? "mexmaca64" : "mexmaci64";
|
|
38473
|
+
return "mexa64";
|
|
38474
|
+
}
|
|
38475
|
+
defineBuiltin({
|
|
38476
|
+
name: "mexext",
|
|
38477
|
+
cases: [
|
|
38478
|
+
{
|
|
38479
|
+
match: (argTypes) => argTypes.length === 0 ? [{ kind: "char" }] : null,
|
|
38480
|
+
apply: () => RTV.char(getMexExt())
|
|
38481
|
+
}
|
|
38482
|
+
]
|
|
38483
|
+
});
|
|
37986
38484
|
var _platform = typeof process !== "undefined" ? process.platform : "linux";
|
|
37987
38485
|
for (const [name, val] of [
|
|
37988
38486
|
["ismac", _platform === "darwin"],
|
|
@@ -39028,7 +39526,7 @@ for (const name of ["clear", "clc", "clf"]) {
|
|
|
39028
39526
|
name,
|
|
39029
39527
|
resolve: () => ({
|
|
39030
39528
|
outputTypes: [],
|
|
39031
|
-
apply: () => 0
|
|
39529
|
+
apply: () => void 0
|
|
39032
39530
|
})
|
|
39033
39531
|
});
|
|
39034
39532
|
}
|
|
@@ -39162,7 +39660,7 @@ registerIBuiltin({
|
|
|
39162
39660
|
name: "set",
|
|
39163
39661
|
resolve: () => ({
|
|
39164
39662
|
outputTypes: [],
|
|
39165
|
-
apply: () => 0
|
|
39663
|
+
apply: () => void 0
|
|
39166
39664
|
})
|
|
39167
39665
|
});
|
|
39168
39666
|
for (const name of [
|
|
@@ -39184,7 +39682,7 @@ for (const name of [
|
|
|
39184
39682
|
name,
|
|
39185
39683
|
resolve: () => ({
|
|
39186
39684
|
outputTypes: [],
|
|
39187
|
-
apply: () => 0
|
|
39685
|
+
apply: () => void 0
|
|
39188
39686
|
})
|
|
39189
39687
|
});
|
|
39190
39688
|
}
|
|
@@ -43904,6 +44402,114 @@ function bisectEvent(eventIdx, step, events) {
|
|
|
43904
44402
|
return [tOld + xFinal * h, denseOutputEval(yOld, Q, h, xFinal)];
|
|
43905
44403
|
}
|
|
43906
44404
|
|
|
44405
|
+
// src/numbl-core/helpers/quadgk.ts
|
|
44406
|
+
var XK = [
|
|
44407
|
+
-0.9914553711208126,
|
|
44408
|
+
-0.9491079123427585,
|
|
44409
|
+
-0.8648644233597691,
|
|
44410
|
+
-0.7415311855993945,
|
|
44411
|
+
-0.586087235467691,
|
|
44412
|
+
-0.4058451513773972,
|
|
44413
|
+
-0.2077849550078985,
|
|
44414
|
+
0,
|
|
44415
|
+
0.2077849550078985,
|
|
44416
|
+
0.4058451513773972,
|
|
44417
|
+
0.586087235467691,
|
|
44418
|
+
0.7415311855993945,
|
|
44419
|
+
0.8648644233597691,
|
|
44420
|
+
0.9491079123427585,
|
|
44421
|
+
0.9914553711208126
|
|
44422
|
+
];
|
|
44423
|
+
var WK = [
|
|
44424
|
+
0.0229353220105292,
|
|
44425
|
+
0.0630920926299786,
|
|
44426
|
+
0.1047900103222502,
|
|
44427
|
+
0.1406532597155259,
|
|
44428
|
+
0.1690047266392679,
|
|
44429
|
+
0.1903505780647854,
|
|
44430
|
+
0.2044329400752989,
|
|
44431
|
+
0.2094821410847278,
|
|
44432
|
+
0.2044329400752989,
|
|
44433
|
+
0.1903505780647854,
|
|
44434
|
+
0.1690047266392679,
|
|
44435
|
+
0.1406532597155259,
|
|
44436
|
+
0.1047900103222502,
|
|
44437
|
+
0.0630920926299786,
|
|
44438
|
+
0.0229353220105292
|
|
44439
|
+
];
|
|
44440
|
+
var WG = [
|
|
44441
|
+
0.1294849661688697,
|
|
44442
|
+
0.2797053914892767,
|
|
44443
|
+
0.3818300505051189,
|
|
44444
|
+
0.4179591836734694,
|
|
44445
|
+
0.3818300505051189,
|
|
44446
|
+
0.2797053914892767,
|
|
44447
|
+
0.1294849661688697
|
|
44448
|
+
];
|
|
44449
|
+
function kronrodNodes(lo, hi) {
|
|
44450
|
+
const m = (lo + hi) / 2;
|
|
44451
|
+
const h = (hi - lo) / 2;
|
|
44452
|
+
const out = new Array(15);
|
|
44453
|
+
for (let i = 0; i < 15; i++) out[i] = m + h * XK[i];
|
|
44454
|
+
return out;
|
|
44455
|
+
}
|
|
44456
|
+
function segmentEstimate(lo, hi, fv) {
|
|
44457
|
+
const h = (hi - lo) / 2;
|
|
44458
|
+
let K = 0;
|
|
44459
|
+
let G = 0;
|
|
44460
|
+
for (let i = 0; i < 15; i++) K += WK[i] * fv[i];
|
|
44461
|
+
for (let i = 0; i < 7; i++) G += WG[i] * fv[2 * i + 1];
|
|
44462
|
+
K *= h;
|
|
44463
|
+
G *= h;
|
|
44464
|
+
return { K, err: Math.abs(K - G) };
|
|
44465
|
+
}
|
|
44466
|
+
function quadgkAdaptive(integrand, a, b, opts = {}) {
|
|
44467
|
+
const relTol = opts.relTol ?? 1e-6;
|
|
44468
|
+
const absTol = opts.absTol ?? 1e-10;
|
|
44469
|
+
const maxIntervals = opts.maxIntervalCount ?? 650;
|
|
44470
|
+
if (a === b) return { value: 0, errbnd: 0, intervalsUsed: 0 };
|
|
44471
|
+
const sign = a < b ? 1 : -1;
|
|
44472
|
+
const lo0 = Math.min(a, b);
|
|
44473
|
+
const hi0 = Math.max(a, b);
|
|
44474
|
+
const segmentOn = (lo, hi) => {
|
|
44475
|
+
const pts = kronrodNodes(lo, hi);
|
|
44476
|
+
const fv = integrand(pts);
|
|
44477
|
+
if (fv.length !== 15) {
|
|
44478
|
+
throw new Error(
|
|
44479
|
+
`quadgk: integrand must return 15 values for 15 nodes, got ${fv.length}`
|
|
44480
|
+
);
|
|
44481
|
+
}
|
|
44482
|
+
return segmentEstimate(lo, hi, fv);
|
|
44483
|
+
};
|
|
44484
|
+
const initial = segmentOn(lo0, hi0);
|
|
44485
|
+
let totalK = initial.K;
|
|
44486
|
+
let totalErr = initial.err;
|
|
44487
|
+
const worklist = [{ lo: lo0, hi: hi0, ...initial }];
|
|
44488
|
+
const converged = () => totalErr <= Math.max(absTol, relTol * Math.abs(totalK));
|
|
44489
|
+
let iters = 0;
|
|
44490
|
+
while (!converged() && worklist.length < maxIntervals && iters < 1e4) {
|
|
44491
|
+
iters++;
|
|
44492
|
+
let worstIdx = 0;
|
|
44493
|
+
for (let i = 1; i < worklist.length; i++) {
|
|
44494
|
+
if (worklist[i].err > worklist[worstIdx].err) worstIdx = i;
|
|
44495
|
+
}
|
|
44496
|
+
const worst = worklist[worstIdx];
|
|
44497
|
+
if (worst.hi - worst.lo <= 1e-15 * (hi0 - lo0)) break;
|
|
44498
|
+
const mid = (worst.lo + worst.hi) / 2;
|
|
44499
|
+
const s1 = segmentOn(worst.lo, mid);
|
|
44500
|
+
const s2 = segmentOn(mid, worst.hi);
|
|
44501
|
+
totalK += s1.K + s2.K - worst.K;
|
|
44502
|
+
totalErr += s1.err + s2.err - worst.err;
|
|
44503
|
+
worklist[worstIdx] = { lo: worst.lo, hi: mid, ...s1 };
|
|
44504
|
+
worklist.push({ lo: mid, hi: worst.hi, ...s2 });
|
|
44505
|
+
}
|
|
44506
|
+
return {
|
|
44507
|
+
value: sign * totalK,
|
|
44508
|
+
errbnd: totalErr,
|
|
44509
|
+
intervalsUsed: worklist.length
|
|
44510
|
+
};
|
|
44511
|
+
}
|
|
44512
|
+
|
|
43907
44513
|
// src/numbl-core/runtime/specialBuiltinNames.ts
|
|
43908
44514
|
var SPECIAL_BUILTIN_NAMES = [
|
|
43909
44515
|
"help",
|
|
@@ -43992,6 +44598,7 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
43992
44598
|
"webread",
|
|
43993
44599
|
"delete",
|
|
43994
44600
|
"rmdir",
|
|
44601
|
+
"movefile",
|
|
43995
44602
|
"unzip",
|
|
43996
44603
|
"dir",
|
|
43997
44604
|
"warning",
|
|
@@ -44005,7 +44612,8 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
44005
44612
|
"ode45",
|
|
44006
44613
|
"ode23",
|
|
44007
44614
|
"deval",
|
|
44008
|
-
"toc"
|
|
44615
|
+
"toc",
|
|
44616
|
+
"quadgk"
|
|
44009
44617
|
];
|
|
44010
44618
|
|
|
44011
44619
|
// src/numbl-core/runtime/specialBuiltins.ts
|
|
@@ -44019,42 +44627,58 @@ function registerSpecial(name, fn) {
|
|
|
44019
44627
|
})
|
|
44020
44628
|
});
|
|
44021
44629
|
}
|
|
44630
|
+
function registerSpecialVoid(name, fn) {
|
|
44631
|
+
registerDynamicIBuiltin({
|
|
44632
|
+
name,
|
|
44633
|
+
resolve: () => ({
|
|
44634
|
+
outputTypes: [],
|
|
44635
|
+
apply: (args) => {
|
|
44636
|
+
fn(args);
|
|
44637
|
+
return void 0;
|
|
44638
|
+
}
|
|
44639
|
+
})
|
|
44640
|
+
});
|
|
44641
|
+
}
|
|
44022
44642
|
function registerSpecialBuiltins(rt) {
|
|
44023
|
-
registerSpecial("help", (
|
|
44643
|
+
registerSpecial("help", (nargout, args) => {
|
|
44644
|
+
let text = "";
|
|
44645
|
+
const emit = (s) => {
|
|
44646
|
+
text += s;
|
|
44647
|
+
if (nargout === 0) rt.output(s);
|
|
44648
|
+
};
|
|
44024
44649
|
if (args.length === 0) {
|
|
44025
44650
|
const names = getAllBuiltinNames().sort();
|
|
44026
|
-
|
|
44027
|
-
|
|
44028
|
-
|
|
44029
|
-
|
|
44030
|
-
|
|
44031
|
-
|
|
44032
|
-
|
|
44033
|
-
|
|
44034
|
-
|
|
44035
|
-
|
|
44036
|
-
rt.output(`No help available for '${name}'.
|
|
44651
|
+
emit("Available builtins:\n");
|
|
44652
|
+
emit(" " + names.join(", ") + "\n");
|
|
44653
|
+
emit("\nType 'help <name>' for help on a specific builtin.\n");
|
|
44654
|
+
} else {
|
|
44655
|
+
const name = toString(args[0]);
|
|
44656
|
+
const h = getIBuiltinHelp(name);
|
|
44657
|
+
if (!h) {
|
|
44658
|
+
const allNames = getAllBuiltinNames();
|
|
44659
|
+
if (allNames.includes(name)) {
|
|
44660
|
+
emit(`No help available for '${name}'.
|
|
44037
44661
|
`);
|
|
44038
|
-
|
|
44039
|
-
|
|
44662
|
+
} else {
|
|
44663
|
+
emit(`Unknown function '${name}'.
|
|
44040
44664
|
`);
|
|
44041
|
-
|
|
44042
|
-
|
|
44043
|
-
|
|
44044
|
-
rt.output(` ${h.signatures.join("\n ")}
|
|
44665
|
+
}
|
|
44666
|
+
} else {
|
|
44667
|
+
emit(` ${h.signatures.join("\n ")}
|
|
44045
44668
|
|
|
44046
44669
|
`);
|
|
44047
|
-
|
|
44670
|
+
emit(`${h.description}
|
|
44048
44671
|
`);
|
|
44049
|
-
|
|
44672
|
+
}
|
|
44673
|
+
}
|
|
44674
|
+
return nargout >= 1 ? RTV.char(text) : void 0;
|
|
44050
44675
|
});
|
|
44051
|
-
|
|
44676
|
+
registerSpecialVoid("disp", (args) => {
|
|
44052
44677
|
if (args.length >= 1) {
|
|
44053
44678
|
const mv = ensureRuntimeValue(args[0]);
|
|
44054
|
-
if (isRuntimeTensor(mv) && mv.data.length === 0) return
|
|
44679
|
+
if (isRuntimeTensor(mv) && mv.data.length === 0) return;
|
|
44055
44680
|
rt.output(displayValue(mv) + "\n");
|
|
44056
44681
|
}
|
|
44057
|
-
return 0;
|
|
44058
44682
|
});
|
|
44059
44683
|
registerSpecial("toc", (nargout) => {
|
|
44060
44684
|
const elapsed = (performance.now() - getTicTime()) / 1e3;
|
|
@@ -44064,12 +44688,13 @@ function registerSpecialBuiltins(rt) {
|
|
|
44064
44688
|
}
|
|
44065
44689
|
return RTV.num(elapsed);
|
|
44066
44690
|
});
|
|
44067
|
-
registerSpecial("warning", (
|
|
44068
|
-
if (args.length === 0) return RTV.num(0);
|
|
44691
|
+
registerSpecial("warning", (nargout, args) => {
|
|
44692
|
+
if (args.length === 0) return nargout >= 1 ? RTV.num(0) : void 0;
|
|
44069
44693
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
44070
44694
|
if (margs.length === 2 && isRuntimeChar(margs[0]) && isRuntimeChar(margs[1])) {
|
|
44071
44695
|
const state = toString(margs[0]);
|
|
44072
44696
|
if (state === "on" || state === "off") {
|
|
44697
|
+
if (nargout === 0) return void 0;
|
|
44073
44698
|
return RTV.struct(
|
|
44074
44699
|
/* @__PURE__ */ new Map([
|
|
44075
44700
|
["state", RTV.char("on")],
|
|
@@ -44098,9 +44723,9 @@ function registerSpecialBuiltins(rt) {
|
|
|
44098
44723
|
} else {
|
|
44099
44724
|
rt.output("Warning: " + sprintfFormat(fmt, fmtArgs) + "\n");
|
|
44100
44725
|
}
|
|
44101
|
-
return RTV.num(0);
|
|
44726
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
44102
44727
|
});
|
|
44103
|
-
registerSpecial("fprintf", (
|
|
44728
|
+
registerSpecial("fprintf", (nargout, args) => {
|
|
44104
44729
|
let output = "";
|
|
44105
44730
|
if (args.length >= 1) {
|
|
44106
44731
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -44111,27 +44736,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44111
44736
|
fmtIdx = 1;
|
|
44112
44737
|
}
|
|
44113
44738
|
const fmt = toString(margs[fmtIdx]);
|
|
44114
|
-
|
|
44115
|
-
for (let i = fmtIdx + 1; i < margs.length; i++) {
|
|
44116
|
-
const a = margs[i];
|
|
44117
|
-
if (isRuntimeTensor(a)) {
|
|
44118
|
-
for (let j = 0; j < a.data.length; j++)
|
|
44119
|
-
scalarArgs.push(RTV.num(a.data[j]));
|
|
44120
|
-
} else {
|
|
44121
|
-
scalarArgs.push(a);
|
|
44122
|
-
}
|
|
44123
|
-
}
|
|
44124
|
-
const specCount = (fmt.match(/%[^%]/g) || []).length;
|
|
44125
|
-
if (specCount === 0 || scalarArgs.length === 0) {
|
|
44126
|
-
output = sprintfFormat(fmt, scalarArgs);
|
|
44127
|
-
} else {
|
|
44128
|
-
let idx = 0;
|
|
44129
|
-
while (idx < scalarArgs.length) {
|
|
44130
|
-
const batch = scalarArgs.slice(idx, idx + specCount);
|
|
44131
|
-
output += sprintfFormat(fmt, batch);
|
|
44132
|
-
idx += specCount;
|
|
44133
|
-
}
|
|
44134
|
-
}
|
|
44739
|
+
output = sprintfFormat(fmt, margs.slice(fmtIdx + 1));
|
|
44135
44740
|
if (fid === 1 || fid === 2) {
|
|
44136
44741
|
rt.output(output);
|
|
44137
44742
|
} else {
|
|
@@ -44142,7 +44747,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44142
44747
|
rt.fileIO.fwrite(fid, output);
|
|
44143
44748
|
}
|
|
44144
44749
|
}
|
|
44145
|
-
return output.length;
|
|
44750
|
+
return nargout >= 1 ? output.length : void 0;
|
|
44146
44751
|
});
|
|
44147
44752
|
registerSpecial("arrayfun", (nargout, args) => {
|
|
44148
44753
|
return arrayfunImpl(rt, nargout, args);
|
|
@@ -44174,6 +44779,55 @@ function registerSpecialBuiltins(rt) {
|
|
|
44174
44779
|
registerSpecial("bsxfun", (nargout, args) => {
|
|
44175
44780
|
return bsxfunImpl(rt, nargout, args);
|
|
44176
44781
|
});
|
|
44782
|
+
registerSpecial("quadgk", (nargout, args) => {
|
|
44783
|
+
if (args.length < 3)
|
|
44784
|
+
throw new RuntimeError(
|
|
44785
|
+
"quadgk: requires at least 3 arguments (fun, a, b)"
|
|
44786
|
+
);
|
|
44787
|
+
const fnArg = ensureRuntimeValue(args[0]);
|
|
44788
|
+
if (!isRuntimeFunction(fnArg))
|
|
44789
|
+
throw new RuntimeError("quadgk: first argument must be a function");
|
|
44790
|
+
const a = toNumber(ensureRuntimeValue(args[1]));
|
|
44791
|
+
const b = toNumber(ensureRuntimeValue(args[2]));
|
|
44792
|
+
let relTol;
|
|
44793
|
+
let absTol;
|
|
44794
|
+
let maxIntervalCount;
|
|
44795
|
+
for (let i = 3; i + 1 < args.length; i += 2) {
|
|
44796
|
+
const keyRv = ensureRuntimeValue(args[i]);
|
|
44797
|
+
const key = isRuntimeChar(keyRv) ? keyRv.value : isRuntimeString(keyRv) ? keyRv : "";
|
|
44798
|
+
const lowerKey = key.toLowerCase();
|
|
44799
|
+
const valRv = ensureRuntimeValue(args[i + 1]);
|
|
44800
|
+
if (lowerKey === "reltol") relTol = toNumber(valRv);
|
|
44801
|
+
else if (lowerKey === "abstol") absTol = toNumber(valRv);
|
|
44802
|
+
else if (lowerKey === "maxintervalcount")
|
|
44803
|
+
maxIntervalCount = toNumber(valRv);
|
|
44804
|
+
}
|
|
44805
|
+
const integrand = (pts) => {
|
|
44806
|
+
const vecData = new FloatXArray(pts);
|
|
44807
|
+
const vec = RTV.tensor(vecData, [1, pts.length]);
|
|
44808
|
+
const resultRaw = rt.index(fnArg, [vec], 1);
|
|
44809
|
+
const rv = ensureRuntimeValue(resultRaw);
|
|
44810
|
+
if (isRuntimeNumber(rv)) {
|
|
44811
|
+
return new Array(pts.length).fill(rv);
|
|
44812
|
+
}
|
|
44813
|
+
if (isRuntimeTensor(rv)) {
|
|
44814
|
+
if (rv.data.length !== pts.length) {
|
|
44815
|
+
throw new RuntimeError(
|
|
44816
|
+
`quadgk: integrand returned ${rv.data.length} values for ${pts.length} nodes`
|
|
44817
|
+
);
|
|
44818
|
+
}
|
|
44819
|
+
return Array.from(rv.data);
|
|
44820
|
+
}
|
|
44821
|
+
throw new RuntimeError("quadgk: integrand must return a numeric vector");
|
|
44822
|
+
};
|
|
44823
|
+
const result = quadgkAdaptive(integrand, a, b, {
|
|
44824
|
+
relTol,
|
|
44825
|
+
absTol,
|
|
44826
|
+
maxIntervalCount
|
|
44827
|
+
});
|
|
44828
|
+
if (nargout >= 2) return [result.value, result.errbnd];
|
|
44829
|
+
return result.value;
|
|
44830
|
+
});
|
|
44177
44831
|
registerSpecial("subsref", (nargout, args) => {
|
|
44178
44832
|
return subsrefBuiltin(rt, nargout, args);
|
|
44179
44833
|
});
|
|
@@ -44796,7 +45450,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44796
45450
|
return RTV.char(text);
|
|
44797
45451
|
}
|
|
44798
45452
|
});
|
|
44799
|
-
|
|
45453
|
+
registerSpecialVoid("delete", (args) => {
|
|
44800
45454
|
const io = requireFileIO();
|
|
44801
45455
|
if (!io.deleteFile)
|
|
44802
45456
|
throw new RuntimeError("delete is not available in this environment");
|
|
@@ -44806,7 +45460,6 @@ function registerSpecialBuiltins(rt) {
|
|
|
44806
45460
|
for (const arg of margs) {
|
|
44807
45461
|
io.deleteFile(toString(arg));
|
|
44808
45462
|
}
|
|
44809
|
-
return 0;
|
|
44810
45463
|
});
|
|
44811
45464
|
registerSpecial("rmdir", (nargout, args) => {
|
|
44812
45465
|
const io = requireFileIO();
|
|
@@ -44829,6 +45482,34 @@ function registerSpecialBuiltins(rt) {
|
|
|
44829
45482
|
RTV.char("")
|
|
44830
45483
|
];
|
|
44831
45484
|
});
|
|
45485
|
+
registerSpecial("movefile", (nargout, args) => {
|
|
45486
|
+
const io = requireFileIO();
|
|
45487
|
+
if (!io.movefile)
|
|
45488
|
+
throw new RuntimeError("movefile is not available in this environment");
|
|
45489
|
+
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
45490
|
+
if (margs.length < 1)
|
|
45491
|
+
throw new RuntimeError("movefile requires at least 1 argument");
|
|
45492
|
+
const source = toString(margs[0]);
|
|
45493
|
+
const destination = margs.length >= 2 ? toString(margs[1]) : rt.system?.cwd() ?? ".";
|
|
45494
|
+
let force = false;
|
|
45495
|
+
if (margs.length >= 3) {
|
|
45496
|
+
const third = toString(margs[2]);
|
|
45497
|
+
if (third.toLowerCase() === "f") force = true;
|
|
45498
|
+
}
|
|
45499
|
+
const ok = io.movefile(source, destination, force);
|
|
45500
|
+
if (nargout === 0) {
|
|
45501
|
+
if (!ok)
|
|
45502
|
+
throw new RuntimeError(
|
|
45503
|
+
`movefile: cannot move '${source}' to '${destination}'`
|
|
45504
|
+
);
|
|
45505
|
+
return void 0;
|
|
45506
|
+
}
|
|
45507
|
+
return nargout <= 1 ? RTV.num(ok ? 1 : 0) : [
|
|
45508
|
+
RTV.num(ok ? 1 : 0),
|
|
45509
|
+
RTV.char(ok ? "" : `Cannot move '${source}' to '${destination}'`),
|
|
45510
|
+
RTV.char("")
|
|
45511
|
+
];
|
|
45512
|
+
});
|
|
44832
45513
|
registerSpecial("unzip", (nargout, args) => {
|
|
44833
45514
|
const io = requireFileIO();
|
|
44834
45515
|
if (!io.unzip)
|
|
@@ -44880,7 +45561,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44880
45561
|
const cellData = extracted.map((f) => RTV.char(f));
|
|
44881
45562
|
return RTV.cell(cellData, [1, cellData.length]);
|
|
44882
45563
|
}
|
|
44883
|
-
return 0;
|
|
45564
|
+
return void 0;
|
|
44884
45565
|
});
|
|
44885
45566
|
registerSpecial("dir", (nargout, args) => {
|
|
44886
45567
|
const io = requireFileIO();
|
|
@@ -44977,7 +45658,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44977
45658
|
const parts = margs.map((a) => toString(a));
|
|
44978
45659
|
return RTV.char(parts.join("/"));
|
|
44979
45660
|
});
|
|
44980
|
-
|
|
45661
|
+
registerSpecialVoid("assignin", (args) => {
|
|
44981
45662
|
if (args.length < 3)
|
|
44982
45663
|
throw new RuntimeError("assignin requires 3 arguments");
|
|
44983
45664
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -44992,7 +45673,6 @@ function registerSpecialBuiltins(rt) {
|
|
|
44992
45673
|
} else {
|
|
44993
45674
|
rt.setWorkspaceVariable(varName, args[2]);
|
|
44994
45675
|
}
|
|
44995
|
-
return 0;
|
|
44996
45676
|
});
|
|
44997
45677
|
registerSpecial("evalin", (_nargout, args) => {
|
|
44998
45678
|
if (args.length < 2)
|
|
@@ -45013,13 +45693,12 @@ function registerSpecialBuiltins(rt) {
|
|
|
45013
45693
|
}
|
|
45014
45694
|
return val;
|
|
45015
45695
|
});
|
|
45016
|
-
|
|
45696
|
+
registerSpecialVoid("drawnow", () => {
|
|
45017
45697
|
rt.drawnow();
|
|
45018
|
-
return 0;
|
|
45019
45698
|
});
|
|
45020
|
-
registerSpecial("pause", (
|
|
45699
|
+
registerSpecial("pause", (nargout, args) => {
|
|
45021
45700
|
rt.pause(args[0] ?? 0);
|
|
45022
|
-
return 0;
|
|
45701
|
+
return nargout >= 1 ? RTV.char("on") : void 0;
|
|
45023
45702
|
});
|
|
45024
45703
|
registerSpecial("mfilename", (_nargout, args) => {
|
|
45025
45704
|
const file = rt.$file ?? "";
|
|
@@ -45063,7 +45742,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
45063
45742
|
}
|
|
45064
45743
|
}
|
|
45065
45744
|
if (nargout >= 1) return RTV.char(rt.searchPaths.join(";"));
|
|
45066
|
-
return 0;
|
|
45745
|
+
return void 0;
|
|
45067
45746
|
});
|
|
45068
45747
|
registerSpecial("rmpath", (nargout, args) => {
|
|
45069
45748
|
if (!rt.onPathChange) {
|
|
@@ -45083,11 +45762,11 @@ function registerSpecialBuiltins(rt) {
|
|
|
45083
45762
|
}
|
|
45084
45763
|
}
|
|
45085
45764
|
if (nargout >= 1) return RTV.char(rt.searchPaths.join(";"));
|
|
45086
|
-
return 0;
|
|
45765
|
+
return void 0;
|
|
45087
45766
|
});
|
|
45088
|
-
registerSpecial("savepath", () => {
|
|
45767
|
+
registerSpecial("savepath", (nargout) => {
|
|
45089
45768
|
rt.output("Warning: savepath is a no-op in numbl\n");
|
|
45090
|
-
return 0;
|
|
45769
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45091
45770
|
});
|
|
45092
45771
|
registerSpecial("input", (_nargout, args) => {
|
|
45093
45772
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -45150,11 +45829,11 @@ function registerSpecialBuiltins(rt) {
|
|
|
45150
45829
|
}
|
|
45151
45830
|
return RTV.char(sys?.getEnv(toString(args[0])) ?? "");
|
|
45152
45831
|
});
|
|
45153
|
-
|
|
45832
|
+
registerSpecialVoid("setenv", (args) => {
|
|
45154
45833
|
const sys = rt.system;
|
|
45155
45834
|
if (args.length === 2) {
|
|
45156
45835
|
sys?.setEnv(toString(args[0]), toString(args[1]));
|
|
45157
|
-
return
|
|
45836
|
+
return;
|
|
45158
45837
|
}
|
|
45159
45838
|
if (args.length === 1) {
|
|
45160
45839
|
const d = args[0];
|
|
@@ -45162,20 +45841,26 @@ function registerSpecialBuiltins(rt) {
|
|
|
45162
45841
|
for (const { key, value } of d.entries.values()) {
|
|
45163
45842
|
sys?.setEnv(toString(key), toString(value));
|
|
45164
45843
|
}
|
|
45165
|
-
return
|
|
45844
|
+
return;
|
|
45166
45845
|
}
|
|
45167
45846
|
sys?.setEnv(toString(d), "");
|
|
45168
|
-
return
|
|
45847
|
+
return;
|
|
45169
45848
|
}
|
|
45170
45849
|
throw new RuntimeError("setenv: invalid arguments");
|
|
45171
45850
|
});
|
|
45172
45851
|
registerSpecial("pwd", () => {
|
|
45173
45852
|
return RTV.char(rt.system?.cwd() ?? "/");
|
|
45174
45853
|
});
|
|
45175
|
-
registerSpecial("cd", (
|
|
45854
|
+
registerSpecial("cd", (nargout, args) => {
|
|
45176
45855
|
const sys = rt.system;
|
|
45177
45856
|
const curDir = sys?.cwd() ?? "/";
|
|
45178
|
-
if (args.length === 0)
|
|
45857
|
+
if (args.length === 0) {
|
|
45858
|
+
if (nargout === 0) {
|
|
45859
|
+
rt.output(curDir + "\n");
|
|
45860
|
+
return void 0;
|
|
45861
|
+
}
|
|
45862
|
+
return RTV.char(curDir);
|
|
45863
|
+
}
|
|
45179
45864
|
const target = toString(args[0]);
|
|
45180
45865
|
if (sys) {
|
|
45181
45866
|
try {
|
|
@@ -45183,15 +45868,18 @@ function registerSpecialBuiltins(rt) {
|
|
|
45183
45868
|
} catch {
|
|
45184
45869
|
throw new RuntimeError(`Cannot change directory to '${target}'`);
|
|
45185
45870
|
}
|
|
45871
|
+
if (rt.onCwdChange) {
|
|
45872
|
+
rt.onCwdChange(sys.cwd());
|
|
45873
|
+
}
|
|
45186
45874
|
}
|
|
45187
|
-
return RTV.char(curDir);
|
|
45875
|
+
return nargout >= 1 ? RTV.char(curDir) : void 0;
|
|
45188
45876
|
});
|
|
45189
|
-
registerSpecial("figure", (
|
|
45877
|
+
registerSpecial("figure", (nargout, args) => {
|
|
45190
45878
|
const handle = args.length > 0 ? args[0] : 1;
|
|
45191
45879
|
plotInstr(rt.plotInstructions, { type: "set_figure_handle", handle });
|
|
45192
|
-
return 0;
|
|
45880
|
+
return nargout >= 1 ? RTV.num(toNumber(ensureRuntimeValue(handle))) : void 0;
|
|
45193
45881
|
});
|
|
45194
|
-
registerSpecial("subplot", (
|
|
45882
|
+
registerSpecial("subplot", (nargout, args) => {
|
|
45195
45883
|
if (args.length >= 3) {
|
|
45196
45884
|
plotInstr(rt.plotInstructions, {
|
|
45197
45885
|
type: "set_subplot",
|
|
@@ -45200,43 +45888,41 @@ function registerSpecialBuiltins(rt) {
|
|
|
45200
45888
|
index: args[2]
|
|
45201
45889
|
});
|
|
45202
45890
|
}
|
|
45203
|
-
return 0;
|
|
45891
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45204
45892
|
});
|
|
45205
|
-
registerSpecial("title", (
|
|
45893
|
+
registerSpecial("title", (nargout, args) => {
|
|
45206
45894
|
if (args.length > 0) {
|
|
45207
45895
|
plotInstr(rt.plotInstructions, { type: "set_title", text: args[0] });
|
|
45208
45896
|
}
|
|
45209
|
-
return 0;
|
|
45897
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45210
45898
|
});
|
|
45211
|
-
registerSpecial("xlabel", (
|
|
45899
|
+
registerSpecial("xlabel", (nargout, args) => {
|
|
45212
45900
|
if (args.length > 0) {
|
|
45213
45901
|
plotInstr(rt.plotInstructions, { type: "set_xlabel", text: args[0] });
|
|
45214
45902
|
}
|
|
45215
|
-
return 0;
|
|
45903
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45216
45904
|
});
|
|
45217
|
-
registerSpecial("ylabel", (
|
|
45905
|
+
registerSpecial("ylabel", (nargout, args) => {
|
|
45218
45906
|
if (args.length > 0) {
|
|
45219
45907
|
plotInstr(rt.plotInstructions, { type: "set_ylabel", text: args[0] });
|
|
45220
45908
|
}
|
|
45221
|
-
return 0;
|
|
45909
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45222
45910
|
});
|
|
45223
|
-
|
|
45911
|
+
registerSpecialVoid("hold", (args) => {
|
|
45224
45912
|
if (args.length > 0) {
|
|
45225
45913
|
plotInstr(rt.plotInstructions, { type: "set_hold", value: args[0] });
|
|
45226
45914
|
}
|
|
45227
|
-
return 0;
|
|
45228
45915
|
});
|
|
45229
|
-
|
|
45916
|
+
registerSpecialVoid("grid", (args) => {
|
|
45230
45917
|
if (args.length > 0) {
|
|
45231
45918
|
plotInstr(rt.plotInstructions, { type: "set_grid", value: args[0] });
|
|
45232
45919
|
}
|
|
45233
|
-
return 0;
|
|
45234
45920
|
});
|
|
45235
|
-
registerSpecial("legend", (
|
|
45921
|
+
registerSpecial("legend", (nargout, args) => {
|
|
45236
45922
|
legendCall(rt.plotInstructions, args);
|
|
45237
|
-
return 0;
|
|
45923
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45238
45924
|
});
|
|
45239
|
-
registerSpecial("close", (
|
|
45925
|
+
registerSpecial("close", (nargout, args) => {
|
|
45240
45926
|
if (args.length > 0) {
|
|
45241
45927
|
const val = toString(args[0]);
|
|
45242
45928
|
if (val === "all") {
|
|
@@ -45247,26 +45933,25 @@ function registerSpecialBuiltins(rt) {
|
|
|
45247
45933
|
} else {
|
|
45248
45934
|
plotInstr(rt.plotInstructions, { type: "close" });
|
|
45249
45935
|
}
|
|
45250
|
-
return 0;
|
|
45936
|
+
return nargout >= 1 ? RTV.num(1) : void 0;
|
|
45251
45937
|
});
|
|
45252
|
-
registerSpecial("sgtitle", (
|
|
45938
|
+
registerSpecial("sgtitle", (nargout, args) => {
|
|
45253
45939
|
if (args.length > 0) {
|
|
45254
45940
|
plotInstr(rt.plotInstructions, { type: "set_sgtitle", text: args[0] });
|
|
45255
45941
|
}
|
|
45256
|
-
return 0;
|
|
45942
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45257
45943
|
});
|
|
45258
|
-
|
|
45944
|
+
registerSpecialVoid("shading", (args) => {
|
|
45259
45945
|
if (args.length > 0) {
|
|
45260
45946
|
plotInstr(rt.plotInstructions, {
|
|
45261
45947
|
type: "set_shading",
|
|
45262
45948
|
shading: args[0]
|
|
45263
45949
|
});
|
|
45264
45950
|
}
|
|
45265
|
-
return 0;
|
|
45266
45951
|
});
|
|
45267
|
-
registerSpecial("clf", () => {
|
|
45952
|
+
registerSpecial("clf", (nargout) => {
|
|
45268
45953
|
plotInstr(rt.plotInstructions, { type: "clf" });
|
|
45269
|
-
return 0;
|
|
45954
|
+
return nargout >= 1 ? RTV.num(1) : void 0;
|
|
45270
45955
|
});
|
|
45271
45956
|
registerSpecial("ode45", (nargout, args) => {
|
|
45272
45957
|
return _ode45Impl(rt, nargout, args, dormandPrince45);
|
|
@@ -45811,6 +46496,29 @@ function methodDispatch(rt, name, nargout, args) {
|
|
|
45811
46496
|
}
|
|
45812
46497
|
return fieldVal;
|
|
45813
46498
|
}
|
|
46499
|
+
{
|
|
46500
|
+
const accessorKey = `${firstRV.className}.get.${name}`;
|
|
46501
|
+
if (!rt.activeAccessors.has(accessorKey)) {
|
|
46502
|
+
const getter = rt.cachedResolveClassMethod(
|
|
46503
|
+
firstRV.className,
|
|
46504
|
+
`get.${name}`
|
|
46505
|
+
);
|
|
46506
|
+
if (getter) {
|
|
46507
|
+
rt.activeAccessors.add(accessorKey);
|
|
46508
|
+
let gotVal;
|
|
46509
|
+
try {
|
|
46510
|
+
gotVal = getter(1, first);
|
|
46511
|
+
} finally {
|
|
46512
|
+
rt.activeAccessors.delete(accessorKey);
|
|
46513
|
+
}
|
|
46514
|
+
const remaining = args.slice(1);
|
|
46515
|
+
if (remaining.length > 0) {
|
|
46516
|
+
return rt.index(gotVal, remaining, nargout);
|
|
46517
|
+
}
|
|
46518
|
+
return gotVal;
|
|
46519
|
+
}
|
|
46520
|
+
}
|
|
46521
|
+
}
|
|
45814
46522
|
try {
|
|
45815
46523
|
return callClassMethod(rt, firstRV.className, name, nargout, args);
|
|
45816
46524
|
} catch (e) {
|
|
@@ -46379,6 +47087,7 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
46379
47087
|
const im2 = t.imag[i];
|
|
46380
47088
|
return im2 === 0 ? t.data[i] : RTV.complex(t.data[i], im2);
|
|
46381
47089
|
}
|
|
47090
|
+
if (t._isLogical === true) return t.data[i] !== 0;
|
|
46382
47091
|
return t.data[i];
|
|
46383
47092
|
}
|
|
46384
47093
|
} else if (nIdx === 2) {
|
|
@@ -46387,7 +47096,14 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
46387
47096
|
if (typeof ri === "number" && typeof ci === "number") {
|
|
46388
47097
|
const s = t.shape;
|
|
46389
47098
|
const rows = s.length === 0 ? 1 : s.length === 1 ? 1 : s[0];
|
|
46390
|
-
|
|
47099
|
+
let cols;
|
|
47100
|
+
if (s.length === 0) cols = 1;
|
|
47101
|
+
else if (s.length === 1) cols = s[0];
|
|
47102
|
+
else if (s.length === 2) cols = s[1];
|
|
47103
|
+
else {
|
|
47104
|
+
cols = 1;
|
|
47105
|
+
for (let k = 1; k < s.length; k++) cols *= s[k];
|
|
47106
|
+
}
|
|
46391
47107
|
const r = Math.round(ri) - 1;
|
|
46392
47108
|
const c = Math.round(ci) - 1;
|
|
46393
47109
|
if (r < 0 || r >= rows || c < 0 || c >= cols)
|
|
@@ -46397,6 +47113,7 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
46397
47113
|
const im2 = t.imag[lin];
|
|
46398
47114
|
return im2 === 0 ? t.data[lin] : RTV.complex(t.data[lin], im2);
|
|
46399
47115
|
}
|
|
47116
|
+
if (t._isLogical === true) return t.data[lin] !== 0;
|
|
46400
47117
|
return t.data[lin];
|
|
46401
47118
|
}
|
|
46402
47119
|
} else if (nIdx >= 3) {
|
|
@@ -46787,14 +47504,20 @@ function multiOutputCellAssign(base, indices, results) {
|
|
|
46787
47504
|
if (base === void 0 || base === null) base = RTV.cell([], [0, 0]);
|
|
46788
47505
|
let mv = ensureRuntimeValue(base);
|
|
46789
47506
|
if (!isRuntimeCell(mv)) mv = RTV.cell([], [0, 0]);
|
|
46790
|
-
const idxMv = ensureRuntimeValue(indices);
|
|
46791
47507
|
let idxArray;
|
|
46792
|
-
if (
|
|
46793
|
-
|
|
46794
|
-
|
|
46795
|
-
|
|
47508
|
+
if (indices === COLON_SENTINEL) {
|
|
47509
|
+
const n = mv.data.length;
|
|
47510
|
+
idxArray = [];
|
|
47511
|
+
for (let i = 1; i <= n; i++) idxArray.push(i);
|
|
46796
47512
|
} else {
|
|
46797
|
-
|
|
47513
|
+
const idxMv = ensureRuntimeValue(indices);
|
|
47514
|
+
if (isRuntimeTensor(idxMv)) {
|
|
47515
|
+
idxArray = Array.from(idxMv.data);
|
|
47516
|
+
} else if (isRuntimeNumber(idxMv)) {
|
|
47517
|
+
idxArray = [idxMv];
|
|
47518
|
+
} else {
|
|
47519
|
+
idxArray = [1];
|
|
47520
|
+
}
|
|
46798
47521
|
}
|
|
46799
47522
|
for (let i = 0; i < idxArray.length && i < results.length; i++) {
|
|
46800
47523
|
const idx = idxArray[i];
|
|
@@ -47021,6 +47744,8 @@ var Runtime = class _Runtime {
|
|
|
47021
47744
|
classMethodCache = /* @__PURE__ */ new Map();
|
|
47022
47745
|
/** Callback for addpath/rmpath — mutates search paths and rebuilds function index. */
|
|
47023
47746
|
onPathChange = null;
|
|
47747
|
+
/** Callback invoked after cd() to update the implicit cwd search path. */
|
|
47748
|
+
onCwdChange = null;
|
|
47024
47749
|
/** Reference to the active search paths (set by executeCode). */
|
|
47025
47750
|
searchPaths = [];
|
|
47026
47751
|
// Workspace accessors: varName → { get, set } closures over script-level vars
|
|
@@ -47300,23 +48025,26 @@ var Runtime = class _Runtime {
|
|
|
47300
48025
|
if (e instanceof RuntimeError) {
|
|
47301
48026
|
return RTV.struct(
|
|
47302
48027
|
/* @__PURE__ */ new Map([
|
|
47303
|
-
["message", RTV.
|
|
47304
|
-
["identifier", RTV.
|
|
48028
|
+
["message", RTV.char(e.message)],
|
|
48029
|
+
["identifier", RTV.char(e.identifier)],
|
|
48030
|
+
["stack", buildStackField(e)]
|
|
47305
48031
|
])
|
|
47306
48032
|
);
|
|
47307
48033
|
}
|
|
47308
48034
|
if (e instanceof Error) {
|
|
47309
48035
|
return RTV.struct(
|
|
47310
48036
|
/* @__PURE__ */ new Map([
|
|
47311
|
-
["message", RTV.
|
|
47312
|
-
["identifier", RTV.
|
|
48037
|
+
["message", RTV.char(e.message)],
|
|
48038
|
+
["identifier", RTV.char("")],
|
|
48039
|
+
["stack", emptyStackField()]
|
|
47313
48040
|
])
|
|
47314
48041
|
);
|
|
47315
48042
|
}
|
|
47316
48043
|
return RTV.struct(
|
|
47317
48044
|
/* @__PURE__ */ new Map([
|
|
47318
|
-
["message", RTV.
|
|
47319
|
-
["identifier", RTV.
|
|
48045
|
+
["message", RTV.char(String(e))],
|
|
48046
|
+
["identifier", RTV.char("")],
|
|
48047
|
+
["stack", emptyStackField()]
|
|
47320
48048
|
])
|
|
47321
48049
|
);
|
|
47322
48050
|
}
|
|
@@ -48148,6 +48876,63 @@ var rstr = (s) => {
|
|
|
48148
48876
|
if (isRuntimeChar(s)) return s.value;
|
|
48149
48877
|
throw new RuntimeError(`Expected string or char, got ${kstr(s)}`);
|
|
48150
48878
|
};
|
|
48879
|
+
function emptyStackField() {
|
|
48880
|
+
return RTV.structArray(["file", "name", "line"], []);
|
|
48881
|
+
}
|
|
48882
|
+
function buildStackField(e) {
|
|
48883
|
+
const fieldNames = ["file", "name", "line"];
|
|
48884
|
+
const frames = e.callStack;
|
|
48885
|
+
if (!frames || frames.length === 0) {
|
|
48886
|
+
if (e.file || e.line !== null) {
|
|
48887
|
+
return RTV.structArray(fieldNames, [
|
|
48888
|
+
RTV.struct(
|
|
48889
|
+
/* @__PURE__ */ new Map([
|
|
48890
|
+
["file", RTV.char(e.file ?? "")],
|
|
48891
|
+
["name", RTV.char("")],
|
|
48892
|
+
["line", e.line ?? 0]
|
|
48893
|
+
])
|
|
48894
|
+
)
|
|
48895
|
+
]);
|
|
48896
|
+
}
|
|
48897
|
+
return emptyStackField();
|
|
48898
|
+
}
|
|
48899
|
+
const elements = [];
|
|
48900
|
+
const N = frames.length;
|
|
48901
|
+
for (let i = N - 1; i >= 0; i--) {
|
|
48902
|
+
let frameFile;
|
|
48903
|
+
let frameLine;
|
|
48904
|
+
if (i === N - 1) {
|
|
48905
|
+
frameFile = e.file;
|
|
48906
|
+
frameLine = e.line ?? 0;
|
|
48907
|
+
} else {
|
|
48908
|
+
const callerFrame = frames[i + 1];
|
|
48909
|
+
frameFile = callerFrame.callerFile;
|
|
48910
|
+
frameLine = callerFrame.callerLine;
|
|
48911
|
+
}
|
|
48912
|
+
elements.push(
|
|
48913
|
+
RTV.struct(
|
|
48914
|
+
/* @__PURE__ */ new Map([
|
|
48915
|
+
["file", RTV.char(frameFile ?? "")],
|
|
48916
|
+
["name", RTV.char(frames[i].name)],
|
|
48917
|
+
["line", frameLine]
|
|
48918
|
+
])
|
|
48919
|
+
)
|
|
48920
|
+
);
|
|
48921
|
+
}
|
|
48922
|
+
const outermost = frames[0];
|
|
48923
|
+
if (outermost.callerFile && outermost.callerLine > 0) {
|
|
48924
|
+
elements.push(
|
|
48925
|
+
RTV.struct(
|
|
48926
|
+
/* @__PURE__ */ new Map([
|
|
48927
|
+
["file", RTV.char(outermost.callerFile)],
|
|
48928
|
+
["name", RTV.char("")],
|
|
48929
|
+
["line", outermost.callerLine]
|
|
48930
|
+
])
|
|
48931
|
+
)
|
|
48932
|
+
);
|
|
48933
|
+
}
|
|
48934
|
+
return RTV.structArray(fieldNames, elements);
|
|
48935
|
+
}
|
|
48151
48936
|
|
|
48152
48937
|
// src/numbl-core/jsUserFunctions.ts
|
|
48153
48938
|
function funcNameFromFile(fileName) {
|
|
@@ -50541,6 +51326,9 @@ function execStmt(stmt) {
|
|
|
50541
51326
|
case "ExprStmt": {
|
|
50542
51327
|
const val = this.evalExprNargout(stmt.expr, 0);
|
|
50543
51328
|
const singleVal = Array.isArray(val) ? val[0] : val;
|
|
51329
|
+
if (singleVal === void 0) {
|
|
51330
|
+
return null;
|
|
51331
|
+
}
|
|
50544
51332
|
const rv = ensureRuntimeValue(singleVal);
|
|
50545
51333
|
this.ans = rv;
|
|
50546
51334
|
this.env.set("ans", rv);
|
|
@@ -50564,19 +51352,25 @@ function execStmt(stmt) {
|
|
|
50564
51352
|
if (stmt.lvalues.length === 1 && stmt.lvalues[0].type === "IndexCell") {
|
|
50565
51353
|
const lv = stmt.lvalues[0];
|
|
50566
51354
|
const cellBase = lv.base.type === "Ident" ? this.env.get(lv.base.name) ?? RTV.cell([], [0, 0]) : this.evalExpr(lv.base);
|
|
50567
|
-
const indices =
|
|
50568
|
-
const idxVal = ensureRuntimeValue(indices[0]);
|
|
51355
|
+
const indices = this.evalIndicesWithEnd(cellBase, lv.indices);
|
|
50569
51356
|
let expandedCount = 1;
|
|
50570
|
-
|
|
50571
|
-
|
|
50572
|
-
|
|
50573
|
-
expandedCount =
|
|
51357
|
+
const idx0 = indices[0];
|
|
51358
|
+
if (idx0 === COLON_SENTINEL) {
|
|
51359
|
+
const baseRv = ensureRuntimeValue(cellBase);
|
|
51360
|
+
expandedCount = isRuntimeCell(baseRv) ? baseRv.data.length : 0;
|
|
51361
|
+
} else {
|
|
51362
|
+
const idxVal = ensureRuntimeValue(idx0);
|
|
51363
|
+
if (isRuntimeTensor(idxVal)) {
|
|
51364
|
+
expandedCount = idxVal.data.length;
|
|
51365
|
+
} else if (typeof idxVal === "number") {
|
|
51366
|
+
expandedCount = 1;
|
|
51367
|
+
}
|
|
50574
51368
|
}
|
|
50575
51369
|
const val2 = this.evalExprNargout(stmt.expr, expandedCount);
|
|
50576
51370
|
const values2 = Array.isArray(val2) ? val2 : [val2];
|
|
50577
51371
|
const result = this.rt.multiOutputCellAssign(
|
|
50578
51372
|
cellBase,
|
|
50579
|
-
|
|
51373
|
+
idx0,
|
|
50580
51374
|
values2.map((v) => ensureRuntimeValue(v))
|
|
50581
51375
|
);
|
|
50582
51376
|
if (lv.base.type === "Ident") {
|
|
@@ -51138,7 +51932,11 @@ function evalAnonFunc(expr) {
|
|
|
51138
51932
|
capturedMethodName,
|
|
51139
51933
|
() => {
|
|
51140
51934
|
try {
|
|
51141
|
-
|
|
51935
|
+
const result = this.evalExprNargout(bodyExpr, narg);
|
|
51936
|
+
if (narg > 1 && !(Array.isArray(result) && result.length >= narg)) {
|
|
51937
|
+
throw new RuntimeError("Too many output arguments.");
|
|
51938
|
+
}
|
|
51939
|
+
return result;
|
|
51142
51940
|
} finally {
|
|
51143
51941
|
this.env = savedEnv;
|
|
51144
51942
|
}
|
|
@@ -51618,6 +52416,17 @@ register("exist", (ctx, args) => {
|
|
|
51618
52416
|
}
|
|
51619
52417
|
return FALL_THROUGH;
|
|
51620
52418
|
});
|
|
52419
|
+
register("which", (ctx, args) => {
|
|
52420
|
+
if (args.length < 1) return FALL_THROUGH;
|
|
52421
|
+
const nameArg = toString(ensureRuntimeValue(args[0]));
|
|
52422
|
+
if (ctx.env.has(nameArg)) return RTV.char("variable");
|
|
52423
|
+
const filePath = ctx.lookupWorkspaceFile(nameArg);
|
|
52424
|
+
if (filePath) return RTV.char(filePath);
|
|
52425
|
+
if (ctx.rt.builtins[nameArg] || getIBuiltin(nameArg)) {
|
|
52426
|
+
return RTV.char("built-in");
|
|
52427
|
+
}
|
|
52428
|
+
return RTV.char("");
|
|
52429
|
+
});
|
|
51621
52430
|
register("isfolder", (ctx, args) => {
|
|
51622
52431
|
if (args.length < 1) return FALL_THROUGH;
|
|
51623
52432
|
const fio = ctx.rt.fileIO;
|
|
@@ -51720,6 +52529,9 @@ register("run", (ctx, args) => {
|
|
|
51720
52529
|
} catch {
|
|
51721
52530
|
throw new RuntimeError(`Cannot change directory to '${scriptDir}'`);
|
|
51722
52531
|
}
|
|
52532
|
+
if (ctx.rt.onCwdChange) {
|
|
52533
|
+
ctx.rt.onCwdChange(sys.cwd());
|
|
52534
|
+
}
|
|
51723
52535
|
}
|
|
51724
52536
|
const cwdAfterCd = sys?.cwd() ?? "/";
|
|
51725
52537
|
try {
|
|
@@ -51731,6 +52543,9 @@ register("run", (ctx, args) => {
|
|
|
51731
52543
|
sys.chdir(oldCwd);
|
|
51732
52544
|
} catch {
|
|
51733
52545
|
}
|
|
52546
|
+
if (ctx.rt.onCwdChange) {
|
|
52547
|
+
ctx.rt.onCwdChange(sys.cwd());
|
|
52548
|
+
}
|
|
51734
52549
|
}
|
|
51735
52550
|
}
|
|
51736
52551
|
return void 0;
|
|
@@ -51750,7 +52565,14 @@ function callFunction(name, args, nargout) {
|
|
|
51750
52565
|
workspaceEnv: this.workspaceEnv,
|
|
51751
52566
|
evalInLocalScope: (codeArg, fileName) => this.evalInLocalScope(codeArg, fileName),
|
|
51752
52567
|
callFunction: (n, a, no) => this.callFunction(n, a, no),
|
|
51753
|
-
rt: this.rt
|
|
52568
|
+
rt: this.rt,
|
|
52569
|
+
lookupWorkspaceFile: (n) => {
|
|
52570
|
+
const entry = this.ctx.registry.filesByFuncName.get(n);
|
|
52571
|
+
if (entry) return entry.fileName;
|
|
52572
|
+
const classInfo = this.ctx.getClassInfo(n);
|
|
52573
|
+
if (classInfo) return classInfo.fileName;
|
|
52574
|
+
return void 0;
|
|
52575
|
+
}
|
|
51754
52576
|
};
|
|
51755
52577
|
const result = specialHandler(ctx, args, nargout);
|
|
51756
52578
|
if (result !== FALL_THROUGH) return result;
|
|
@@ -51784,13 +52606,18 @@ function interpretTarget(target, args, nargout) {
|
|
|
51784
52606
|
const argTypes = margs.map(inferJitType);
|
|
51785
52607
|
const resolution = ib.resolve(argTypes, nargout);
|
|
51786
52608
|
if (resolution) {
|
|
52609
|
+
const isVoid = resolution.outputTypes.length === 0;
|
|
52610
|
+
if (isVoid && nargout > 0) {
|
|
52611
|
+
throw new RuntimeError("Too many output arguments.");
|
|
52612
|
+
}
|
|
51787
52613
|
if (this.rt.profilingEnabled) {
|
|
51788
52614
|
this.rt.profileEnter("builtin:interp:" + target.name);
|
|
51789
|
-
const
|
|
52615
|
+
const result2 = resolution.apply(margs, nargout);
|
|
51790
52616
|
this.rt.profileLeave();
|
|
51791
|
-
return
|
|
52617
|
+
return isVoid ? void 0 : result2;
|
|
51792
52618
|
}
|
|
51793
|
-
|
|
52619
|
+
const result = resolution.apply(margs, nargout);
|
|
52620
|
+
return isVoid ? void 0 : result;
|
|
51794
52621
|
}
|
|
51795
52622
|
}
|
|
51796
52623
|
const builtin = this.rt.builtins[target.name];
|
|
@@ -51882,7 +52709,19 @@ function interpretLocalFunction(target, args, nargout) {
|
|
|
51882
52709
|
function interpretWorkspaceFunction(target, args, nargout) {
|
|
51883
52710
|
const dotIdx = target.name.lastIndexOf(".");
|
|
51884
52711
|
const primaryName = dotIdx >= 0 ? target.name.slice(dotIdx + 1) : target.name;
|
|
51885
|
-
|
|
52712
|
+
let fn = this.findFunctionInWorkspaceFile(target.name, primaryName);
|
|
52713
|
+
if (!fn) {
|
|
52714
|
+
const entry = this.ctx.registry.filesByFuncName.get(target.name);
|
|
52715
|
+
if (entry) {
|
|
52716
|
+
const ast = this.ctx.getCachedAST(entry.fileName);
|
|
52717
|
+
for (const stmt of ast.body) {
|
|
52718
|
+
if (stmt.type === "Function") {
|
|
52719
|
+
fn = funcDefFromStmt(stmt);
|
|
52720
|
+
break;
|
|
52721
|
+
}
|
|
52722
|
+
}
|
|
52723
|
+
}
|
|
52724
|
+
}
|
|
51886
52725
|
if (!fn) {
|
|
51887
52726
|
const entry = this.ctx.registry.filesByFuncName.get(target.name);
|
|
51888
52727
|
if (entry) {
|
|
@@ -52026,6 +52865,11 @@ function interpretConstructor(classInfo, args, nargout) {
|
|
|
52026
52865
|
return args[0];
|
|
52027
52866
|
}
|
|
52028
52867
|
function callUserFunction(fn, args, nargout, narginOverride) {
|
|
52868
|
+
const hasVarargoutDecl = fn.outputs.length > 0 && fn.outputs[fn.outputs.length - 1] === "varargout";
|
|
52869
|
+
const declaredRegularOutputs = hasVarargoutDecl ? fn.outputs.length - 1 : fn.outputs.length;
|
|
52870
|
+
if (!hasVarargoutDecl && nargout > declaredRegularOutputs) {
|
|
52871
|
+
throw new RuntimeError("Too many output arguments.");
|
|
52872
|
+
}
|
|
52029
52873
|
if (this.optimization >= 1 && narginOverride === void 0) {
|
|
52030
52874
|
const jitResult = tryJitCall(this, fn, args, nargout);
|
|
52031
52875
|
if (jitResult !== JIT_SKIP) return jitResult;
|
|
@@ -52075,7 +52919,7 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
52075
52919
|
}
|
|
52076
52920
|
}
|
|
52077
52921
|
}
|
|
52078
|
-
const hasVarargout =
|
|
52922
|
+
const hasVarargout = hasVarargoutDecl;
|
|
52079
52923
|
const regularOutputs = hasVarargout ? fn.outputs.slice(0, -1) : fn.outputs;
|
|
52080
52924
|
const collectCount = nargout === 0 && regularOutputs.length > 0 ? 1 : Math.min(regularOutputs.length, nargout);
|
|
52081
52925
|
const outputs = [];
|
|
@@ -53680,6 +54524,31 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
53680
54524
|
}
|
|
53681
54525
|
}
|
|
53682
54526
|
}
|
|
54527
|
+
let implicitCwdPath = null;
|
|
54528
|
+
if (options.implicitCwdPath !== null && options.system && options.fileIO?.scanDirectory) {
|
|
54529
|
+
try {
|
|
54530
|
+
const cwd = options.implicitCwdPath ?? options.system.cwd();
|
|
54531
|
+
const absCwd = options.fileIO.resolvePath?.(cwd) ?? cwd;
|
|
54532
|
+
const explicitPaths = searchPaths ?? [];
|
|
54533
|
+
if (!explicitPaths.includes(absCwd)) {
|
|
54534
|
+
implicitCwdPath = absCwd;
|
|
54535
|
+
const prefix = absCwd.endsWith("/") ? absCwd : absCwd + "/";
|
|
54536
|
+
const alreadyHave = mWorkspaceFiles.some(
|
|
54537
|
+
(f) => f.name === absCwd || f.name.startsWith(prefix)
|
|
54538
|
+
);
|
|
54539
|
+
if (!alreadyHave) {
|
|
54540
|
+
const cwdFiles = options.fileIO.scanDirectory(absCwd);
|
|
54541
|
+
for (const f of cwdFiles) {
|
|
54542
|
+
if (f.name.endsWith(".m")) {
|
|
54543
|
+
mWorkspaceFiles.push(f);
|
|
54544
|
+
}
|
|
54545
|
+
}
|
|
54546
|
+
}
|
|
54547
|
+
}
|
|
54548
|
+
} catch {
|
|
54549
|
+
implicitCwdPath = null;
|
|
54550
|
+
}
|
|
54551
|
+
}
|
|
53683
54552
|
const jsUserFunctions = loadJsUserFunctions(
|
|
53684
54553
|
jsWorkspaceFiles,
|
|
53685
54554
|
wasmWorkspaceFiles,
|
|
@@ -53697,6 +54566,9 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
53697
54566
|
stdlibShimNames.add(shimName);
|
|
53698
54567
|
}
|
|
53699
54568
|
ctx.registry.searchPaths = [...searchPaths ?? [], SHIM_SEARCH_PATH];
|
|
54569
|
+
if (implicitCwdPath !== null) {
|
|
54570
|
+
ctx.registry.searchPaths.unshift(implicitCwdPath);
|
|
54571
|
+
}
|
|
53700
54572
|
ctx.fileASTCache.set(mainFileName, ast);
|
|
53701
54573
|
const skippedFiles = /* @__PURE__ */ new Set();
|
|
53702
54574
|
for (const f of mWorkspaceFiles) {
|
|
@@ -53730,6 +54602,11 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
53730
54602
|
ctx.registerWorkspaceFiles(mWorkspaceFiles);
|
|
53731
54603
|
}
|
|
53732
54604
|
const functionIndex = ctx.buildFunctionIndex(jsUserFunctionNames);
|
|
54605
|
+
const savedSpecialBuiltins = /* @__PURE__ */ new Map();
|
|
54606
|
+
for (const name of SPECIAL_BUILTIN_NAMES) {
|
|
54607
|
+
const existing = getIBuiltin(name);
|
|
54608
|
+
if (existing) savedSpecialBuiltins.set(name, existing);
|
|
54609
|
+
}
|
|
53733
54610
|
const rt = new Runtime(options, options.initialVariableValues);
|
|
53734
54611
|
const savedIBuiltins = /* @__PURE__ */ new Map();
|
|
53735
54612
|
for (const ib of jsUserFunctions) {
|
|
@@ -53771,13 +54648,39 @@ ${jsCode}`
|
|
|
53771
54648
|
interpreter.installRuntimeCallbacks();
|
|
53772
54649
|
rt.searchPaths = ctx.registry.searchPaths;
|
|
53773
54650
|
let pathsModified = false;
|
|
54651
|
+
const rebuildWorkspace = () => {
|
|
54652
|
+
const paths = ctx.registry.searchPaths;
|
|
54653
|
+
const priorityOf = (name) => {
|
|
54654
|
+
let bestIdx = paths.length;
|
|
54655
|
+
let bestLen = -1;
|
|
54656
|
+
for (let i = 0; i < paths.length; i++) {
|
|
54657
|
+
const p2 = paths[i];
|
|
54658
|
+
const withSep = p2.endsWith("/") ? p2 : p2 + "/";
|
|
54659
|
+
if (name === p2 || name.startsWith(withSep)) {
|
|
54660
|
+
if (p2.length > bestLen) {
|
|
54661
|
+
bestLen = p2.length;
|
|
54662
|
+
bestIdx = i;
|
|
54663
|
+
}
|
|
54664
|
+
}
|
|
54665
|
+
}
|
|
54666
|
+
return bestIdx;
|
|
54667
|
+
};
|
|
54668
|
+
mWorkspaceFiles.sort((a, b) => priorityOf(a.name) - priorityOf(b.name));
|
|
54669
|
+
ctx.clearWorkspaceRegistrations();
|
|
54670
|
+
ctx.registerWorkspaceFiles(mWorkspaceFiles);
|
|
54671
|
+
const newIndex = ctx.buildFunctionIndex(jsUserFunctionNames);
|
|
54672
|
+
interpreter.functionIndex = newIndex;
|
|
54673
|
+
interpreter.clearAllCaches();
|
|
54674
|
+
pathsModified = true;
|
|
54675
|
+
};
|
|
53774
54676
|
rt.onPathChange = (action, dir, position) => {
|
|
53775
54677
|
const fileIO = options.fileIO;
|
|
53776
54678
|
const absDir = fileIO?.resolvePath?.(dir) ?? dir;
|
|
53777
54679
|
if (action === "add") {
|
|
53778
54680
|
if (ctx.registry.searchPaths.includes(absDir)) return;
|
|
53779
54681
|
if (position === "begin") {
|
|
53780
|
-
ctx.registry.searchPaths
|
|
54682
|
+
const cwdIsFirst = implicitCwdPath !== null && ctx.registry.searchPaths[0] === implicitCwdPath;
|
|
54683
|
+
ctx.registry.searchPaths.splice(cwdIsFirst ? 1 : 0, 0, absDir);
|
|
53781
54684
|
} else {
|
|
53782
54685
|
const shimIdx = ctx.registry.searchPaths.indexOf(SHIM_SEARCH_PATH);
|
|
53783
54686
|
if (shimIdx >= 0) {
|
|
@@ -53795,10 +54698,14 @@ ${jsCode}`
|
|
|
53795
54698
|
try {
|
|
53796
54699
|
ctx.fileASTCache.set(f.name, parseMFile(f.source, f.name));
|
|
53797
54700
|
} catch (e) {
|
|
53798
|
-
if (e instanceof SyntaxError
|
|
53799
|
-
|
|
54701
|
+
if (e instanceof SyntaxError) {
|
|
54702
|
+
console.warn(
|
|
54703
|
+
`Warning: skipping ${f.name} (syntax error at line ${e.line ?? "?"})`
|
|
54704
|
+
);
|
|
54705
|
+
} else {
|
|
54706
|
+
console.warn(`Warning: skipping ${f.name} (parse error)`);
|
|
53800
54707
|
}
|
|
53801
|
-
|
|
54708
|
+
continue;
|
|
53802
54709
|
}
|
|
53803
54710
|
interpreter.fileSources.set(f.name, f.source);
|
|
53804
54711
|
mWorkspaceFiles.push(f);
|
|
@@ -53838,26 +54745,76 @@ ${jsCode}`
|
|
|
53838
54745
|
}
|
|
53839
54746
|
}
|
|
53840
54747
|
}
|
|
53841
|
-
|
|
53842
|
-
|
|
53843
|
-
|
|
53844
|
-
|
|
53845
|
-
|
|
53846
|
-
|
|
53847
|
-
|
|
54748
|
+
rebuildWorkspace();
|
|
54749
|
+
};
|
|
54750
|
+
rt.onCwdChange = (newCwd) => {
|
|
54751
|
+
const fileIO = options.fileIO;
|
|
54752
|
+
const absNewCwd = fileIO?.resolvePath?.(newCwd) ?? newCwd;
|
|
54753
|
+
if (implicitCwdPath === absNewCwd) return;
|
|
54754
|
+
if (implicitCwdPath !== null) {
|
|
54755
|
+
const oldPrefix = implicitCwdPath.endsWith("/") ? implicitCwdPath : implicitCwdPath + "/";
|
|
54756
|
+
const deeperPaths = ctx.registry.searchPaths.filter(
|
|
54757
|
+
(p2) => p2 !== implicitCwdPath && p2 !== SHIM_SEARCH_PATH && (p2 === implicitCwdPath || p2.startsWith(oldPrefix))
|
|
53848
54758
|
);
|
|
53849
|
-
const
|
|
53850
|
-
|
|
53851
|
-
|
|
53852
|
-
|
|
53853
|
-
|
|
53854
|
-
|
|
53855
|
-
|
|
53856
|
-
|
|
53857
|
-
|
|
53858
|
-
|
|
54759
|
+
const fileBelongsToDeeperPath = (fname) => {
|
|
54760
|
+
for (const p2 of deeperPaths) {
|
|
54761
|
+
const withSep = p2.endsWith("/") ? p2 : p2 + "/";
|
|
54762
|
+
if (fname === p2 || fname.startsWith(withSep)) return true;
|
|
54763
|
+
}
|
|
54764
|
+
return false;
|
|
54765
|
+
};
|
|
54766
|
+
for (let i = mWorkspaceFiles.length - 1; i >= 0; i--) {
|
|
54767
|
+
const fname = mWorkspaceFiles[i].name;
|
|
54768
|
+
if ((fname === implicitCwdPath || fname.startsWith(oldPrefix)) && !fileBelongsToDeeperPath(fname)) {
|
|
54769
|
+
ctx.fileASTCache.delete(fname);
|
|
54770
|
+
interpreter.fileSources.delete(fname);
|
|
54771
|
+
mWorkspaceFiles.splice(i, 1);
|
|
54772
|
+
}
|
|
54773
|
+
}
|
|
54774
|
+
const oldIdx = ctx.registry.searchPaths.indexOf(implicitCwdPath);
|
|
54775
|
+
if (oldIdx >= 0) ctx.registry.searchPaths.splice(oldIdx, 1);
|
|
54776
|
+
implicitCwdPath = null;
|
|
54777
|
+
}
|
|
54778
|
+
if (ctx.registry.searchPaths.includes(absNewCwd)) {
|
|
54779
|
+
rebuildWorkspace();
|
|
54780
|
+
return;
|
|
54781
|
+
}
|
|
54782
|
+
ctx.registry.searchPaths.unshift(absNewCwd);
|
|
54783
|
+
implicitCwdPath = absNewCwd;
|
|
54784
|
+
if (fileIO?.scanDirectory) {
|
|
54785
|
+
let newFiles = [];
|
|
54786
|
+
try {
|
|
54787
|
+
newFiles = fileIO.scanDirectory(absNewCwd);
|
|
54788
|
+
} catch {
|
|
54789
|
+
}
|
|
54790
|
+
for (const f of newFiles) {
|
|
54791
|
+
if (f.name.endsWith(".m") && !ctx.fileASTCache.has(f.name)) {
|
|
54792
|
+
try {
|
|
54793
|
+
ctx.fileASTCache.set(f.name, parseMFile(f.source, f.name));
|
|
54794
|
+
} catch (e) {
|
|
54795
|
+
if (e instanceof SyntaxError) {
|
|
54796
|
+
console.warn(
|
|
54797
|
+
`Warning: skipping ${f.name} (syntax error at line ${e.line ?? "?"})`
|
|
54798
|
+
);
|
|
54799
|
+
} else {
|
|
54800
|
+
console.warn(`Warning: skipping ${f.name} (parse error)`);
|
|
54801
|
+
}
|
|
54802
|
+
continue;
|
|
54803
|
+
}
|
|
54804
|
+
interpreter.fileSources.set(f.name, f.source);
|
|
54805
|
+
mWorkspaceFiles.push(f);
|
|
54806
|
+
}
|
|
54807
|
+
}
|
|
54808
|
+
}
|
|
54809
|
+
rebuildWorkspace();
|
|
53859
54810
|
};
|
|
53860
54811
|
rt.evalLocalCallback = (code, initialVars, onOutput, fileName) => {
|
|
54812
|
+
const nestedSearchPaths = ctx.registry.searchPaths.filter(
|
|
54813
|
+
(p2) => p2 !== SHIM_SEARCH_PATH && p2 !== implicitCwdPath
|
|
54814
|
+
);
|
|
54815
|
+
const nestedWorkspaceFiles = mWorkspaceFiles.filter(
|
|
54816
|
+
(f) => !stdlibShimNames.has(f.name)
|
|
54817
|
+
);
|
|
53861
54818
|
const evalResult = executeCode(
|
|
53862
54819
|
code,
|
|
53863
54820
|
{
|
|
@@ -53865,11 +54822,18 @@ ${jsCode}`
|
|
|
53865
54822
|
displayResults: false,
|
|
53866
54823
|
initialVariableValues: initialVars,
|
|
53867
54824
|
fileIO: options.fileIO,
|
|
53868
|
-
|
|
54825
|
+
system: options.system,
|
|
54826
|
+
onInput: options.onInput,
|
|
54827
|
+
implicitCwdPath
|
|
53869
54828
|
},
|
|
53870
|
-
|
|
53871
|
-
fileName
|
|
54829
|
+
nestedWorkspaceFiles,
|
|
54830
|
+
fileName,
|
|
54831
|
+
nestedSearchPaths,
|
|
54832
|
+
nativeBridge
|
|
53872
54833
|
);
|
|
54834
|
+
if (evalResult.implicitCwdPath !== void 0) {
|
|
54835
|
+
implicitCwdPath = evalResult.implicitCwdPath;
|
|
54836
|
+
}
|
|
53873
54837
|
return {
|
|
53874
54838
|
returnValue: evalResult.returnValue,
|
|
53875
54839
|
variableValues: evalResult.variableValues,
|
|
@@ -53901,12 +54865,13 @@ ${jitSections.join("\n\n")}` : "// No JS generated",
|
|
|
53901
54865
|
}
|
|
53902
54866
|
if (pathsModified) {
|
|
53903
54867
|
result.searchPaths = ctx.registry.searchPaths.filter(
|
|
53904
|
-
(p2) => p2 !== SHIM_SEARCH_PATH
|
|
54868
|
+
(p2) => p2 !== SHIM_SEARCH_PATH && p2 !== implicitCwdPath
|
|
53905
54869
|
);
|
|
53906
54870
|
result.workspaceFiles = mWorkspaceFiles.filter(
|
|
53907
54871
|
(f) => !stdlibShimNames.has(f.name)
|
|
53908
54872
|
);
|
|
53909
54873
|
}
|
|
54874
|
+
result.implicitCwdPath = implicitCwdPath;
|
|
53910
54875
|
return result;
|
|
53911
54876
|
} catch (e) {
|
|
53912
54877
|
const generatedJS = jitSections.length > 0 ? `// Interpreter mode \u2014 JIT compiled sections:
|
|
@@ -53942,6 +54907,9 @@ ${jitSections.join("\n\n")}` : "// No JS generated";
|
|
|
53942
54907
|
unregisterIBuiltin(ib.name);
|
|
53943
54908
|
}
|
|
53944
54909
|
}
|
|
54910
|
+
for (const [, ib] of savedSpecialBuiltins) {
|
|
54911
|
+
registerDynamicIBuiltin(ib);
|
|
54912
|
+
}
|
|
53945
54913
|
}
|
|
53946
54914
|
}
|
|
53947
54915
|
export {
|