numbl 0.1.2 → 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/README.md +24 -62
- package/binding.gyp +3 -1
- package/dist-cli/cli.js +2109 -893
- package/dist-lib/lib.js +1682 -468
- package/dist-lib/numbl-core/executeCode.d.ts +9 -0
- package/dist-lib/numbl-core/fileIOAdapter.d.ts +14 -2
- package/dist-lib/numbl-core/helpers/prng.d.ts +3 -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/builtins/time-system.d.ts +1 -1
- package/dist-lib/numbl-core/interpreter/builtins/types.d.ts +0 -1
- package/dist-lib/numbl-core/interpreter/interpreterSpecialBuiltins.d.ts +3 -0
- package/dist-lib/numbl-core/native/lapack-bridge.d.ts +18 -0
- package/dist-lib/numbl-core/runtime/runtime.d.ts +9 -0
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/native/elemwise.cpp +58 -0
- package/native/numbl_addon.cpp +6 -0
- package/native/numbl_addon_common.h +3 -0
- package/native/randn.cpp +101 -0
- package/native/unary_elemwise.cpp +67 -0
- package/package.json +3 -1
package/dist-lib/lib.js
CHANGED
|
@@ -18259,6 +18259,28 @@ function binaryNumberOnly(argTypes) {
|
|
|
18259
18259
|
return null;
|
|
18260
18260
|
return [{ kind: "number" }];
|
|
18261
18261
|
}
|
|
18262
|
+
var nativeUnaryOpCode = /* @__PURE__ */ new Map([
|
|
18263
|
+
[Math.exp, 0],
|
|
18264
|
+
[Math.log, 1],
|
|
18265
|
+
[Math.log2, 2],
|
|
18266
|
+
[Math.log10, 3],
|
|
18267
|
+
[Math.sqrt, 4],
|
|
18268
|
+
[Math.abs, 5],
|
|
18269
|
+
[Math.floor, 6],
|
|
18270
|
+
[Math.ceil, 7],
|
|
18271
|
+
[Math.round, 8],
|
|
18272
|
+
[Math.trunc, 9],
|
|
18273
|
+
[Math.sin, 10],
|
|
18274
|
+
[Math.cos, 11],
|
|
18275
|
+
[Math.tan, 12],
|
|
18276
|
+
[Math.asin, 13],
|
|
18277
|
+
[Math.acos, 14],
|
|
18278
|
+
[Math.atan, 15],
|
|
18279
|
+
[Math.sinh, 16],
|
|
18280
|
+
[Math.cosh, 17],
|
|
18281
|
+
[Math.tanh, 18],
|
|
18282
|
+
[Math.sign, 19]
|
|
18283
|
+
]);
|
|
18262
18284
|
function applyUnaryElemwise(v, realFn, complexFn, name) {
|
|
18263
18285
|
if (isRuntimeSparseMatrix(v))
|
|
18264
18286
|
return applyUnaryElemwise(sparseToDense(v), realFn, complexFn, name);
|
|
@@ -18271,6 +18293,14 @@ function applyUnaryElemwise(v, realFn, complexFn, name) {
|
|
|
18271
18293
|
if (isRuntimeTensor(v)) {
|
|
18272
18294
|
const n = v.data.length;
|
|
18273
18295
|
if (!v.imag) {
|
|
18296
|
+
const opCode = nativeUnaryOpCode.get(realFn);
|
|
18297
|
+
if (opCode !== void 0) {
|
|
18298
|
+
const bridge = getLapackBridge();
|
|
18299
|
+
if (bridge?.unaryElemwise && v.data instanceof Float64Array) {
|
|
18300
|
+
const result = bridge.unaryElemwise(v.data, opCode);
|
|
18301
|
+
return RTV.tensorRaw(result, v.shape.slice());
|
|
18302
|
+
}
|
|
18303
|
+
}
|
|
18274
18304
|
const out = new FloatXArray(n);
|
|
18275
18305
|
for (let i = 0; i < n; i++) out[i] = realFn(v.data[i]);
|
|
18276
18306
|
return makeTensor(out, void 0, v.shape.slice());
|
|
@@ -18759,6 +18789,258 @@ function coerceToTensor(v, name) {
|
|
|
18759
18789
|
throw new RuntimeError(`${name}: argument must be numeric`);
|
|
18760
18790
|
}
|
|
18761
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
|
+
|
|
18762
19044
|
// src/numbl-core/helpers/arithmetic.ts
|
|
18763
19045
|
function toComplex(v) {
|
|
18764
19046
|
if (isRuntimeComplexNumber(v)) return { re: v.re, im: v.im };
|
|
@@ -18934,6 +19216,18 @@ function tryNativeElemwiseReal(at, bt, opCode) {
|
|
|
18934
19216
|
);
|
|
18935
19217
|
return RTV.tensorRaw(result, at.shape);
|
|
18936
19218
|
}
|
|
19219
|
+
function tryNativeElemwiseScalar(scalar, tensor, opCode, scalarOnLeft) {
|
|
19220
|
+
if (tensor.imag) return null;
|
|
19221
|
+
const bridge = getLapackBridge();
|
|
19222
|
+
if (!bridge?.elemwiseScalar) return null;
|
|
19223
|
+
const result = bridge.elemwiseScalar(
|
|
19224
|
+
scalar,
|
|
19225
|
+
tensor.data,
|
|
19226
|
+
opCode,
|
|
19227
|
+
scalarOnLeft
|
|
19228
|
+
);
|
|
19229
|
+
return RTV.tensorRaw(result, tensor.shape);
|
|
19230
|
+
}
|
|
18937
19231
|
function tensorElemwiseComplex(at, bt, opCode, jsOp) {
|
|
18938
19232
|
const bridge = getLapackBridge();
|
|
18939
19233
|
if (bridge?.elemwiseComplex) {
|
|
@@ -18974,7 +19268,26 @@ function tensorElemwiseComplex(at, bt, opCode, jsOp) {
|
|
|
18974
19268
|
const isReal = resultIm.every((x) => x === 0);
|
|
18975
19269
|
return RTV.tensor(resultRe, at.shape, isReal ? void 0 : resultIm);
|
|
18976
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
|
+
}
|
|
18977
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
|
+
}
|
|
18978
19291
|
const m = matchSameShapeTensors(a, b);
|
|
18979
19292
|
if (m) {
|
|
18980
19293
|
const [at, bt] = m;
|
|
@@ -19004,6 +19317,13 @@ function mAdd(a, b) {
|
|
|
19004
19317
|
im: aIm + bIm
|
|
19005
19318
|
}));
|
|
19006
19319
|
}
|
|
19320
|
+
if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
|
|
19321
|
+
const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_ADD, true);
|
|
19322
|
+
if (nr) return nr;
|
|
19323
|
+
} else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
|
|
19324
|
+
const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_ADD, false);
|
|
19325
|
+
if (nr) return nr;
|
|
19326
|
+
}
|
|
19007
19327
|
return binaryOp(a, b, (x, y) => x + y);
|
|
19008
19328
|
}
|
|
19009
19329
|
function mSub(a, b) {
|
|
@@ -19036,6 +19356,13 @@ function mSub(a, b) {
|
|
|
19036
19356
|
im: aIm - bIm
|
|
19037
19357
|
}));
|
|
19038
19358
|
}
|
|
19359
|
+
if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
|
|
19360
|
+
const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_SUB, true);
|
|
19361
|
+
if (nr) return nr;
|
|
19362
|
+
} else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
|
|
19363
|
+
const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_SUB, false);
|
|
19364
|
+
if (nr) return nr;
|
|
19365
|
+
}
|
|
19039
19366
|
return binaryOp(a, b, (x, y) => x - y);
|
|
19040
19367
|
}
|
|
19041
19368
|
function mMul(a, b) {
|
|
@@ -19052,6 +19379,13 @@ function mMul(a, b) {
|
|
|
19052
19379
|
im: aRe * bIm + aIm * bRe
|
|
19053
19380
|
}));
|
|
19054
19381
|
}
|
|
19382
|
+
if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
|
|
19383
|
+
const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_MUL, true);
|
|
19384
|
+
if (nr) return nr;
|
|
19385
|
+
} else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
|
|
19386
|
+
const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_MUL, false);
|
|
19387
|
+
if (nr) return nr;
|
|
19388
|
+
}
|
|
19055
19389
|
return binaryOp(a, b, (x, y) => x * y);
|
|
19056
19390
|
}
|
|
19057
19391
|
function mElemMul(a, b) {
|
|
@@ -19084,6 +19418,13 @@ function mElemMul(a, b) {
|
|
|
19084
19418
|
im: aRe * bIm + aIm * bRe
|
|
19085
19419
|
}));
|
|
19086
19420
|
}
|
|
19421
|
+
if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
|
|
19422
|
+
const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_MUL, true);
|
|
19423
|
+
if (nr) return nr;
|
|
19424
|
+
} else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
|
|
19425
|
+
const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_MUL, false);
|
|
19426
|
+
if (nr) return nr;
|
|
19427
|
+
}
|
|
19087
19428
|
return binaryOp(a, b, (x, y) => x * y);
|
|
19088
19429
|
}
|
|
19089
19430
|
function mDiv(a, b) {
|
|
@@ -19122,6 +19463,13 @@ function mElemDiv(a, b) {
|
|
|
19122
19463
|
if (isComplexOrMixed(a, b)) {
|
|
19123
19464
|
return complexBinaryOp(a, b, complexDivide);
|
|
19124
19465
|
}
|
|
19466
|
+
if (isRuntimeNumber(a) && isRuntimeTensor(b)) {
|
|
19467
|
+
const nr = tryNativeElemwiseScalar(a, b, ELEMWISE_DIV, true);
|
|
19468
|
+
if (nr) return nr;
|
|
19469
|
+
} else if (isRuntimeTensor(a) && isRuntimeNumber(b)) {
|
|
19470
|
+
const nr = tryNativeElemwiseScalar(b, a, ELEMWISE_DIV, false);
|
|
19471
|
+
if (nr) return nr;
|
|
19472
|
+
}
|
|
19125
19473
|
return binaryOp(a, b, (x, y) => x / y);
|
|
19126
19474
|
}
|
|
19127
19475
|
function mLeftDiv(a, b) {
|
|
@@ -19834,6 +20182,7 @@ function extractTensorElement(base, i) {
|
|
|
19834
20182
|
const im2 = base.imag[i];
|
|
19835
20183
|
return im2 === 0 ? RTV.num(base.data[i]) : RTV.complex(base.data[i], im2);
|
|
19836
20184
|
}
|
|
20185
|
+
if (base._isLogical === true) return base.data[i] !== 0;
|
|
19837
20186
|
return RTV.num(base.data[i]);
|
|
19838
20187
|
}
|
|
19839
20188
|
function resolveIndex(idx, dimSize, boundsLimit = dimSize) {
|
|
@@ -19887,17 +20236,35 @@ function growTensor2D(base, newRows, newCols) {
|
|
|
19887
20236
|
}
|
|
19888
20237
|
function assignSlice(base, rowIndices, colIndices, rhs, curRows) {
|
|
19889
20238
|
if (isRuntimeTensor(rhs)) {
|
|
20239
|
+
const nR = rowIndices.length;
|
|
20240
|
+
const nC = colIndices.length;
|
|
19890
20241
|
const [rhsRows, rhsCols] = tensorSize2D(rhs);
|
|
19891
|
-
|
|
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)) {
|
|
19892
20247
|
throw new RuntimeError("Subscripted assignment dimension mismatch");
|
|
19893
20248
|
}
|
|
19894
20249
|
if (rhs.imag || base.imag) ensureImag(base);
|
|
19895
|
-
|
|
19896
|
-
for (let
|
|
19897
|
-
|
|
19898
|
-
|
|
19899
|
-
|
|
19900
|
-
|
|
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
|
+
}
|
|
19901
20268
|
}
|
|
19902
20269
|
}
|
|
19903
20270
|
} else {
|
|
@@ -20234,6 +20601,23 @@ function indexIntoScalar(base, indices) {
|
|
|
20234
20601
|
return RTV.tensor(out, [1, count]);
|
|
20235
20602
|
}
|
|
20236
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
|
+
}
|
|
20237
20621
|
for (const idx of indices) {
|
|
20238
20622
|
if (isColonIndex(idx)) continue;
|
|
20239
20623
|
const i = toNumber(idx);
|
|
@@ -20245,6 +20629,22 @@ function indexIntoTensor(base, indices) {
|
|
|
20245
20629
|
if (indices.length === 1) {
|
|
20246
20630
|
return indexIntoTensor1D(base, indices[0]);
|
|
20247
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
|
+
}
|
|
20248
20648
|
if (indices.length === 2) {
|
|
20249
20649
|
return indexIntoTensor2D(base, indices[0], indices[1]);
|
|
20250
20650
|
}
|
|
@@ -20273,6 +20673,11 @@ function indexIntoTensor1D(base, idx) {
|
|
|
20273
20673
|
}
|
|
20274
20674
|
function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
20275
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
|
+
};
|
|
20276
20681
|
if (isRuntimeNumber(rowIdx) && isColonIndex(colIdx)) {
|
|
20277
20682
|
const r = Math.round(rowIdx) - 1;
|
|
20278
20683
|
if (r < 0 || r >= rows)
|
|
@@ -20283,7 +20688,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20283
20688
|
resultData2[ci] = base.data[r + ci * rows];
|
|
20284
20689
|
if (resultImag2 && base.imag) resultImag2[ci] = base.imag[r + ci * rows];
|
|
20285
20690
|
}
|
|
20286
|
-
return RTV.tensor(resultData2, [1, cols], resultImag2);
|
|
20691
|
+
return markLogical(RTV.tensor(resultData2, [1, cols], resultImag2));
|
|
20287
20692
|
}
|
|
20288
20693
|
if (isColonIndex(rowIdx) && isRuntimeNumber(colIdx)) {
|
|
20289
20694
|
const c = Math.round(colIdx) - 1;
|
|
@@ -20295,7 +20700,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20295
20700
|
const resultImag2 = base.imag ? new FloatXArray(rows) : void 0;
|
|
20296
20701
|
if (resultImag2 && base.imag)
|
|
20297
20702
|
for (let ri = 0; ri < rows; ri++) resultImag2[ri] = base.imag[offset + ri];
|
|
20298
|
-
return RTV.tensor(resultData2, [rows, 1], resultImag2);
|
|
20703
|
+
return markLogical(RTV.tensor(resultData2, [rows, 1], resultImag2));
|
|
20299
20704
|
}
|
|
20300
20705
|
const rowIdxArr = resolveIndex(rowIdx, rows);
|
|
20301
20706
|
const colIdxArr = resolveIndex(colIdx, cols);
|
|
@@ -20317,7 +20722,7 @@ function indexIntoTensor2D(base, rowIdx, colIdx) {
|
|
|
20317
20722
|
}
|
|
20318
20723
|
}
|
|
20319
20724
|
}
|
|
20320
|
-
return RTV.tensor(resultData, [numR, numC], resultImag);
|
|
20725
|
+
return markLogical(RTV.tensor(resultData, [numR, numC], resultImag));
|
|
20321
20726
|
}
|
|
20322
20727
|
function indexIntoTensorND(base, indices) {
|
|
20323
20728
|
const shape = base.shape;
|
|
@@ -20365,7 +20770,13 @@ function indexIntoTensorND(base, indices) {
|
|
|
20365
20770
|
subs[d] = 0;
|
|
20366
20771
|
}
|
|
20367
20772
|
}
|
|
20368
|
-
|
|
20773
|
+
const result = RTV.tensor(
|
|
20774
|
+
resultData,
|
|
20775
|
+
resultShape,
|
|
20776
|
+
resultImag
|
|
20777
|
+
);
|
|
20778
|
+
if (base._isLogical === true) result._isLogical = true;
|
|
20779
|
+
return result;
|
|
20369
20780
|
}
|
|
20370
20781
|
function indexIntoCell(base, indices) {
|
|
20371
20782
|
if (indices.length === 1) {
|
|
@@ -20530,6 +20941,7 @@ function indexIntoLogical(base, indices) {
|
|
|
20530
20941
|
return base;
|
|
20531
20942
|
}
|
|
20532
20943
|
function indexIntoTensorWithTensor(base, idx) {
|
|
20944
|
+
const baseLogical = base._isLogical === true;
|
|
20533
20945
|
if (idx._isLogical) {
|
|
20534
20946
|
const selected = [];
|
|
20535
20947
|
const selectedIm = [];
|
|
@@ -20543,12 +20955,19 @@ function indexIntoTensorWithTensor(base, idx) {
|
|
|
20543
20955
|
if (selected.length === 1) {
|
|
20544
20956
|
if (hasImag2 && selectedIm[0] !== 0)
|
|
20545
20957
|
return RTV.complex(selected[0], selectedIm[0]);
|
|
20958
|
+
if (baseLogical) return selected[0] !== 0;
|
|
20546
20959
|
return RTV.num(selected[0]);
|
|
20547
20960
|
}
|
|
20548
20961
|
const imOut2 = hasImag2 && selectedIm.some((x) => x !== 0) ? new FloatXArray(selectedIm) : void 0;
|
|
20549
20962
|
const isRow = base.shape.length === 2 && base.shape[0] === 1;
|
|
20550
20963
|
const outShape2 = isRow ? [1, selected.length] : [selected.length, 1];
|
|
20551
|
-
|
|
20964
|
+
const result2 = RTV.tensor(
|
|
20965
|
+
new FloatXArray(selected),
|
|
20966
|
+
outShape2,
|
|
20967
|
+
imOut2
|
|
20968
|
+
);
|
|
20969
|
+
if (baseLogical) result2._isLogical = true;
|
|
20970
|
+
return result2;
|
|
20552
20971
|
}
|
|
20553
20972
|
const resultData = [];
|
|
20554
20973
|
const hasImag = base.imag !== void 0;
|
|
@@ -20564,7 +20983,13 @@ function indexIntoTensorWithTensor(base, idx) {
|
|
|
20564
20983
|
const baseIsVector = base.shape.length <= 2 && (base.shape[0] === 1 || base.shape[1] === 1 || base.shape.length === 1);
|
|
20565
20984
|
const outShape = idxIs0x0 ? [0, 0] : baseIsVector ? base.shape[0] === 1 ? [1, resultData.length] : [resultData.length, 1] : idx.shape;
|
|
20566
20985
|
const imOut = hasImag && imIndices.some((x) => x !== 0) ? new FloatXArray(imIndices) : void 0;
|
|
20567
|
-
|
|
20986
|
+
const result = RTV.tensor(
|
|
20987
|
+
new FloatXArray(resultData),
|
|
20988
|
+
outShape,
|
|
20989
|
+
imOut
|
|
20990
|
+
);
|
|
20991
|
+
if (baseLogical) result._isLogical = true;
|
|
20992
|
+
return result;
|
|
20568
20993
|
}
|
|
20569
20994
|
function indexIntoRTValue(base, indices) {
|
|
20570
20995
|
if (isRuntimeNumber(base) || isRuntimeComplexNumber(base)) {
|
|
@@ -20914,10 +21339,18 @@ function storeIntoTensor2D(base, indices, rhs) {
|
|
|
20914
21339
|
return storeIntoTensorColonCol(base, indices[0], rhs, rows, cols);
|
|
20915
21340
|
}
|
|
20916
21341
|
if (rowIsTensor || colIsTensor) {
|
|
20917
|
-
const
|
|
20918
|
-
|
|
20919
|
-
|
|
20920
|
-
|
|
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;
|
|
20921
21354
|
base = growTensor2D(base, maxRow, maxCol);
|
|
20922
21355
|
const [curRows] = tensorSize2D(base);
|
|
20923
21356
|
assignSlice(base, rowIndices, colIndices, rhs, curRows);
|
|
@@ -21345,6 +21778,9 @@ function horzcat(...values) {
|
|
|
21345
21778
|
if (values.some((v) => isRuntimeCell(v))) {
|
|
21346
21779
|
return cellCatAlongDim(values, 1);
|
|
21347
21780
|
}
|
|
21781
|
+
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
21782
|
+
return structCat(values);
|
|
21783
|
+
}
|
|
21348
21784
|
return catAlongDim(values, 1);
|
|
21349
21785
|
}
|
|
21350
21786
|
function vertcat(...values) {
|
|
@@ -21356,8 +21792,47 @@ function vertcat(...values) {
|
|
|
21356
21792
|
if (values.some((v) => isRuntimeCell(v))) {
|
|
21357
21793
|
return cellCatAlongDim(values, 0);
|
|
21358
21794
|
}
|
|
21795
|
+
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
21796
|
+
return structCat(values);
|
|
21797
|
+
}
|
|
21359
21798
|
return catAlongDim(values, 0);
|
|
21360
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
|
+
}
|
|
21361
21836
|
function toSparseForCat(v) {
|
|
21362
21837
|
if (isRuntimeSparseMatrix(v)) return v;
|
|
21363
21838
|
if (isRuntimeNumber(v)) {
|
|
@@ -21965,7 +22440,7 @@ var token_config_default = {
|
|
|
21965
22440
|
stripUnderscores: true,
|
|
21966
22441
|
integerToken: "Integer",
|
|
21967
22442
|
floatToken: "Float",
|
|
21968
|
-
exponentChars: ["e", "E"],
|
|
22443
|
+
exponentChars: ["e", "E", "d", "D"],
|
|
21969
22444
|
decimalPoint: ".",
|
|
21970
22445
|
dotOperatorPrefixes: ["*", "/", "\\", "^"]
|
|
21971
22446
|
},
|
|
@@ -22270,6 +22745,9 @@ function tokenizeDetailed(input) {
|
|
|
22270
22745
|
if (numCfg.stripUnderscores) {
|
|
22271
22746
|
lexeme = lexeme.replace(/_/g, "");
|
|
22272
22747
|
}
|
|
22748
|
+
if (isFloat) {
|
|
22749
|
+
lexeme = lexeme.replace(/[dD]/g, "e");
|
|
22750
|
+
}
|
|
22273
22751
|
const tok = isFloat ? Token[numCfg.floatToken] : Token[numCfg.integerToken];
|
|
22274
22752
|
lineStart = false;
|
|
22275
22753
|
out.push({ token: tok, lexeme, start, end: pos });
|
|
@@ -27430,224 +27908,88 @@ defineBuiltin({
|
|
|
27430
27908
|
}
|
|
27431
27909
|
});
|
|
27432
27910
|
|
|
27433
|
-
// src/numbl-core/
|
|
27434
|
-
|
|
27435
|
-
|
|
27436
|
-
|
|
27437
|
-
|
|
27438
|
-
|
|
27439
|
-
|
|
27440
|
-
|
|
27441
|
-
|
|
27442
|
-
if (
|
|
27443
|
-
|
|
27444
|
-
|
|
27445
|
-
|
|
27446
|
-
const expPart0 = s.slice(ePos);
|
|
27447
|
-
if (mantissa.includes(".")) mantissa = mantissa.replace(/\.?0+$/, "");
|
|
27448
|
-
const expPart = expPart0.replace(/([eE][+-])(\d)$/, "$10$2");
|
|
27449
|
-
s = mantissa + expPart;
|
|
27450
|
-
} else {
|
|
27451
|
-
if (Number.isInteger(n)) return String(n);
|
|
27452
|
-
s = n.toPrecision(prec);
|
|
27453
|
-
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 }];
|
|
27454
27924
|
}
|
|
27455
|
-
|
|
27456
|
-
}
|
|
27457
|
-
function applyWidth(spec, str) {
|
|
27458
|
-
const m = spec.match(/^%([-+ #]*)0?(\d+)?/);
|
|
27459
|
-
if (!m) return str;
|
|
27460
|
-
const explicitFlags = m[1] || "";
|
|
27461
|
-
const leftAlign = explicitFlags.includes("-");
|
|
27462
|
-
const afterPercent = spec.slice(1);
|
|
27463
|
-
const flagAndWidth = afterPercent.match(/^([-+ #]*)(0?)(\d+)?/);
|
|
27464
|
-
const zeroFlag = flagAndWidth ? flagAndWidth[2] === "0" : false;
|
|
27465
|
-
const width = flagAndWidth && flagAndWidth[3] ? parseInt(flagAndWidth[3]) : 0;
|
|
27466
|
-
if (width <= str.length) return str;
|
|
27467
|
-
const zeroPad = !leftAlign && zeroFlag;
|
|
27468
|
-
const padLen = width - str.length;
|
|
27469
|
-
if (leftAlign) return str + " ".repeat(padLen);
|
|
27470
|
-
if (zeroPad) {
|
|
27471
|
-
if (str[0] === "-" || str[0] === "+") {
|
|
27472
|
-
return str[0] + "0".repeat(padLen) + str.slice(1);
|
|
27473
|
-
}
|
|
27474
|
-
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 }];
|
|
27475
27927
|
}
|
|
27476
|
-
return
|
|
27928
|
+
return [{ kind: "boolean" }];
|
|
27477
27929
|
}
|
|
27478
|
-
function
|
|
27479
|
-
|
|
27480
|
-
|
|
27481
|
-
|
|
27482
|
-
|
|
27483
|
-
|
|
27484
|
-
|
|
27485
|
-
|
|
27486
|
-
flatArgs.push(arg);
|
|
27487
|
-
}
|
|
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);
|
|
27488
27938
|
}
|
|
27489
|
-
|
|
27490
|
-
|
|
27491
|
-
|
|
27492
|
-
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27496
|
-
|
|
27497
|
-
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
27501
|
-
|
|
27502
|
-
|
|
27503
|
-
|
|
27504
|
-
|
|
27505
|
-
|
|
27506
|
-
|
|
27507
|
-
|
|
27508
|
-
|
|
27509
|
-
|
|
27510
|
-
|
|
27511
|
-
|
|
27512
|
-
|
|
27513
|
-
|
|
27514
|
-
|
|
27515
|
-
|
|
27516
|
-
|
|
27517
|
-
|
|
27518
|
-
|
|
27519
|
-
|
|
27520
|
-
|
|
27521
|
-
|
|
27522
|
-
|
|
27523
|
-
|
|
27524
|
-
|
|
27525
|
-
|
|
27526
|
-
|
|
27527
|
-
|
|
27528
|
-
|
|
27529
|
-
|
|
27530
|
-
|
|
27531
|
-
|
|
27532
|
-
|
|
27533
|
-
|
|
27534
|
-
|
|
27535
|
-
|
|
27536
|
-
}
|
|
27537
|
-
} else if (ch === "f") {
|
|
27538
|
-
const n = toNumber(flatArgs[argIdx++]);
|
|
27539
|
-
if (!isFinite(n) || isNaN(n)) {
|
|
27540
|
-
result += applyWidth(spec, numStr(n));
|
|
27541
|
-
} else {
|
|
27542
|
-
const fFlags = spec.slice(1);
|
|
27543
|
-
const fHasPlus = fFlags.includes("+");
|
|
27544
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
27545
|
-
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
27546
|
-
const formatted = n.toFixed(prec);
|
|
27547
|
-
const fSign = n < 0 ? "" : fHasPlus ? "+" : "";
|
|
27548
|
-
result += applyWidth(spec, fSign + formatted);
|
|
27549
|
-
}
|
|
27550
|
-
} else if (ch === "e" || ch === "E") {
|
|
27551
|
-
const n = toNumber(flatArgs[argIdx++]);
|
|
27552
|
-
if (!isFinite(n) || isNaN(n)) {
|
|
27553
|
-
result += applyWidth(spec, numStr(n));
|
|
27554
|
-
} else {
|
|
27555
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
27556
|
-
const prec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
27557
|
-
let eStr = n.toExponential(prec);
|
|
27558
|
-
eStr = eStr.replace(/e([+-])(\d)$/, "e$10$2");
|
|
27559
|
-
if (ch === "E") eStr = eStr.toUpperCase();
|
|
27560
|
-
result += applyWidth(spec, eStr);
|
|
27561
|
-
}
|
|
27562
|
-
} else if (ch === "x" || ch === "X") {
|
|
27563
|
-
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
27564
|
-
let s = Math.abs(n).toString(16);
|
|
27565
|
-
if (ch === "X") s = s.toUpperCase();
|
|
27566
|
-
result += applyWidth(spec, s);
|
|
27567
|
-
} else if (ch === "o") {
|
|
27568
|
-
const n = Math.round(toNumber(flatArgs[argIdx++]));
|
|
27569
|
-
result += applyWidth(spec, Math.abs(n).toString(8));
|
|
27570
|
-
} else if (ch === "g" || ch === "G") {
|
|
27571
|
-
const gVal = toNumber(flatArgs[argIdx++]);
|
|
27572
|
-
if (!isFinite(gVal) || isNaN(gVal)) {
|
|
27573
|
-
result += applyWidth(spec, numStr(gVal));
|
|
27574
|
-
} else {
|
|
27575
|
-
const precMatch = spec.match(/\.(\d+)/);
|
|
27576
|
-
const gPrec = precMatch ? parseInt(precMatch[1]) : 6;
|
|
27577
|
-
let gStr;
|
|
27578
|
-
if (gVal === 0) {
|
|
27579
|
-
gStr = "0";
|
|
27580
|
-
} else {
|
|
27581
|
-
const exp = Math.floor(Math.log10(Math.abs(gVal)));
|
|
27582
|
-
if (exp < -4 || exp >= gPrec) {
|
|
27583
|
-
gStr = gVal.toExponential(gPrec - 1);
|
|
27584
|
-
const ePos = gStr.indexOf("e");
|
|
27585
|
-
let mantissa = gStr.slice(0, ePos);
|
|
27586
|
-
let expPart = gStr.slice(ePos);
|
|
27587
|
-
if (mantissa.includes(".")) {
|
|
27588
|
-
mantissa = mantissa.replace(/\.?0+$/, "");
|
|
27589
|
-
}
|
|
27590
|
-
expPart = expPart.replace(/e([+-])(\d)$/, "e$10$2");
|
|
27591
|
-
gStr = mantissa + expPart;
|
|
27592
|
-
} else {
|
|
27593
|
-
gStr = gVal.toPrecision(gPrec);
|
|
27594
|
-
if (gStr.includes(".")) {
|
|
27595
|
-
gStr = gStr.replace(/\.?0+$/, "");
|
|
27596
|
-
}
|
|
27597
|
-
if (gStr.includes("e")) {
|
|
27598
|
-
gStr = String(parseFloat(gStr));
|
|
27599
|
-
}
|
|
27600
|
-
}
|
|
27601
|
-
}
|
|
27602
|
-
if (ch === "G") gStr = gStr.toUpperCase();
|
|
27603
|
-
result += applyWidth(spec, gStr);
|
|
27604
|
-
}
|
|
27605
|
-
} else if (ch === "s") {
|
|
27606
|
-
const sVal = toString(flatArgs[argIdx++]);
|
|
27607
|
-
const sFlags = spec.slice(1);
|
|
27608
|
-
const sLeftAlign = sFlags.includes("-");
|
|
27609
|
-
const sWidthMatch = spec.match(/^%[^0-9]*(\d+)/);
|
|
27610
|
-
const sWidth = sWidthMatch ? parseInt(sWidthMatch[1]) : 0;
|
|
27611
|
-
if (sWidth > sVal.length) {
|
|
27612
|
-
const sPad = " ".repeat(sWidth - sVal.length);
|
|
27613
|
-
result += sLeftAlign ? sVal + sPad : sPad + sVal;
|
|
27614
|
-
} else {
|
|
27615
|
-
result += sVal;
|
|
27616
|
-
}
|
|
27617
|
-
} else if (ch === "c") {
|
|
27618
|
-
result += String.fromCharCode(
|
|
27619
|
-
Math.round(toNumber(flatArgs[argIdx++]))
|
|
27620
|
-
);
|
|
27621
|
-
} else {
|
|
27622
|
-
result += spec + ch;
|
|
27623
|
-
argIdx++;
|
|
27624
|
-
}
|
|
27625
|
-
}
|
|
27626
|
-
} else if (fmt[i] === "\\" && i + 1 < fmt.length) {
|
|
27627
|
-
i++;
|
|
27628
|
-
switch (fmt[i]) {
|
|
27629
|
-
case "n":
|
|
27630
|
-
result += "\n";
|
|
27631
|
-
break;
|
|
27632
|
-
case "t":
|
|
27633
|
-
result += " ";
|
|
27634
|
-
break;
|
|
27635
|
-
case "\\":
|
|
27636
|
-
result += "\\";
|
|
27637
|
-
break;
|
|
27638
|
-
default:
|
|
27639
|
-
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 }];
|
|
27640
27986
|
}
|
|
27641
|
-
|
|
27642
|
-
}
|
|
27643
|
-
|
|
27644
|
-
i++;
|
|
27645
|
-
}
|
|
27987
|
+
return [{ kind: "boolean" }];
|
|
27988
|
+
},
|
|
27989
|
+
apply: (args) => not(args[0])
|
|
27646
27990
|
}
|
|
27647
|
-
|
|
27648
|
-
|
|
27649
|
-
return result;
|
|
27650
|
-
}
|
|
27991
|
+
]
|
|
27992
|
+
});
|
|
27651
27993
|
|
|
27652
27994
|
// src/numbl-core/interpreter/builtins/utility.ts
|
|
27653
27995
|
function sparseToDense2(S) {
|
|
@@ -27757,7 +28099,7 @@ defineBuiltin({
|
|
|
27757
28099
|
{
|
|
27758
28100
|
match: (argTypes) => {
|
|
27759
28101
|
if (argTypes.length < 1) return null;
|
|
27760
|
-
return [
|
|
28102
|
+
return [];
|
|
27761
28103
|
},
|
|
27762
28104
|
apply: (args) => {
|
|
27763
28105
|
const v = args[0];
|
|
@@ -27778,7 +28120,7 @@ defineBuiltin({
|
|
|
27778
28120
|
const msg = args.length > 1 ? textValue(args[1]) ?? String(args[1]) : "Assertion failed";
|
|
27779
28121
|
throw new Error(msg);
|
|
27780
28122
|
}
|
|
27781
|
-
return 0;
|
|
28123
|
+
return void 0;
|
|
27782
28124
|
}
|
|
27783
28125
|
}
|
|
27784
28126
|
]
|
|
@@ -27789,7 +28131,7 @@ defineBuiltin({
|
|
|
27789
28131
|
{
|
|
27790
28132
|
match: (argTypes) => {
|
|
27791
28133
|
if (argTypes.length === 0) return null;
|
|
27792
|
-
return [
|
|
28134
|
+
return [];
|
|
27793
28135
|
},
|
|
27794
28136
|
apply: (args) => {
|
|
27795
28137
|
const first = textValue(args[0]) ?? String(args[0]);
|
|
@@ -28461,6 +28803,19 @@ defineBuiltin({
|
|
|
28461
28803
|
name: "NaN",
|
|
28462
28804
|
cases: arrayConstructorCases(nanFill, NaN)
|
|
28463
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
|
+
});
|
|
28464
28819
|
defineBuiltin({
|
|
28465
28820
|
name: "eye",
|
|
28466
28821
|
cases: arrayConstructorCases(
|
|
@@ -29298,19 +29653,33 @@ function preserveTextType(t) {
|
|
|
29298
29653
|
if (t.kind === "string") return { kind: "string" };
|
|
29299
29654
|
return null;
|
|
29300
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
|
+
}
|
|
29301
29668
|
function textPreserveResolve(fn) {
|
|
29302
29669
|
return (argTypes) => {
|
|
29303
29670
|
if (argTypes.length !== 1) return null;
|
|
29304
|
-
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);
|
|
29305
29679
|
if (!out) return null;
|
|
29306
29680
|
return {
|
|
29307
29681
|
outputTypes: [out],
|
|
29308
|
-
apply: (args) =>
|
|
29309
|
-
const v = args[0];
|
|
29310
|
-
const s = toString(v);
|
|
29311
|
-
const result = fn(s);
|
|
29312
|
-
return isRuntimeChar(v) ? RTV.char(result) : RTV.string(result);
|
|
29313
|
-
}
|
|
29682
|
+
apply: (args) => applyTextFn(args[0], fn)
|
|
29314
29683
|
};
|
|
29315
29684
|
};
|
|
29316
29685
|
}
|
|
@@ -31361,7 +31730,7 @@ defineBuiltin({
|
|
|
31361
31730
|
cases: [
|
|
31362
31731
|
{
|
|
31363
31732
|
match: (argTypes, nargout) => {
|
|
31364
|
-
if (nargout
|
|
31733
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2)
|
|
31365
31734
|
return null;
|
|
31366
31735
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
31367
31736
|
return [NUM];
|
|
@@ -31478,7 +31847,7 @@ defineBuiltin({
|
|
|
31478
31847
|
cases: [
|
|
31479
31848
|
{
|
|
31480
31849
|
match: (argTypes, nargout) => {
|
|
31481
|
-
if (nargout
|
|
31850
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 3)
|
|
31482
31851
|
return null;
|
|
31483
31852
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
31484
31853
|
const a = argTypes[0];
|
|
@@ -31557,7 +31926,7 @@ defineBuiltin({
|
|
|
31557
31926
|
cases: [
|
|
31558
31927
|
{
|
|
31559
31928
|
match: (argTypes, nargout) => {
|
|
31560
|
-
if (nargout
|
|
31929
|
+
if (nargout > 1 || argTypes.length !== 2) return null;
|
|
31561
31930
|
if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
|
|
31562
31931
|
return null;
|
|
31563
31932
|
const hasTensor = argTypes.some((t) => t.kind === "tensor");
|
|
@@ -31641,7 +32010,7 @@ defineBuiltin({
|
|
|
31641
32010
|
cases: [
|
|
31642
32011
|
{
|
|
31643
32012
|
match: (argTypes, nargout) => {
|
|
31644
|
-
if (argTypes.length !== 1 || nargout
|
|
32013
|
+
if (argTypes.length !== 1 || nargout > 1) return null;
|
|
31645
32014
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
31646
32015
|
const hasComplex = argTypes[0].kind === "complex_or_number" || argTypes[0].kind === "tensor" && argTypes[0].isComplex;
|
|
31647
32016
|
return [hasComplex ? COMPLEX_OR_NUM : NUM];
|
|
@@ -31753,7 +32122,7 @@ defineBuiltin({
|
|
|
31753
32122
|
cases: [
|
|
31754
32123
|
{
|
|
31755
32124
|
match: (argTypes, nargout) => {
|
|
31756
|
-
if (argTypes.length !== 1 || nargout
|
|
32125
|
+
if (argTypes.length !== 1 || nargout > 1) return null;
|
|
31757
32126
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
31758
32127
|
return [NUM];
|
|
31759
32128
|
},
|
|
@@ -31778,7 +32147,7 @@ defineBuiltin({
|
|
|
31778
32147
|
cases: [
|
|
31779
32148
|
{
|
|
31780
32149
|
match: (argTypes, nargout) => {
|
|
31781
|
-
if (nargout
|
|
32150
|
+
if (nargout > 1) return null;
|
|
31782
32151
|
if (argTypes.length !== 2 && argTypes.length !== 3) return null;
|
|
31783
32152
|
if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
|
|
31784
32153
|
return null;
|
|
@@ -31844,7 +32213,7 @@ defineBuiltin({
|
|
|
31844
32213
|
cases: [
|
|
31845
32214
|
{
|
|
31846
32215
|
match: (argTypes, nargout) => {
|
|
31847
|
-
if (argTypes.length !== 1 || nargout
|
|
32216
|
+
if (argTypes.length !== 1 || nargout > 1) return null;
|
|
31848
32217
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
31849
32218
|
const a = argTypes[0];
|
|
31850
32219
|
if (a.kind === "number" || a.kind === "boolean") return [NUM];
|
|
@@ -31957,11 +32326,11 @@ function invComplexJS(dataRe, dataIm, n) {
|
|
|
31957
32326
|
registerIBuiltin({
|
|
31958
32327
|
name: "svd",
|
|
31959
32328
|
resolve: (argTypes, nargout) => {
|
|
31960
|
-
if (nargout <
|
|
32329
|
+
if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 2)
|
|
31961
32330
|
return null;
|
|
31962
32331
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
31963
32332
|
const c = tensorType();
|
|
31964
|
-
if (nargout
|
|
32333
|
+
if (nargout <= 1)
|
|
31965
32334
|
return { outputTypes: [c], apply: (args, n) => svdApply(args, n) };
|
|
31966
32335
|
return { outputTypes: [c, c, c], apply: (args, n) => svdApply(args, n) };
|
|
31967
32336
|
}
|
|
@@ -31972,7 +32341,7 @@ function svdApply(args, nargout) {
|
|
|
31972
32341
|
const A = args[0];
|
|
31973
32342
|
if (isRuntimeNumber(A)) {
|
|
31974
32343
|
const val = Math.abs(A);
|
|
31975
|
-
if (nargout
|
|
32344
|
+
if (nargout <= 1) return RTV.tensor(new FloatXArray([val]), [1, 1]);
|
|
31976
32345
|
return [
|
|
31977
32346
|
RTV.tensor(new FloatXArray([A >= 0 ? 1 : -1]), [1, 1]),
|
|
31978
32347
|
RTV.tensor(new FloatXArray([val]), [1, 1]),
|
|
@@ -31999,7 +32368,7 @@ function svdApply(args, nargout) {
|
|
|
31999
32368
|
nargout === 3
|
|
32000
32369
|
);
|
|
32001
32370
|
if (!result) throw new RuntimeError("svd: complex SVD failed");
|
|
32002
|
-
if (nargout
|
|
32371
|
+
if (nargout <= 1) return RTV.tensor(new FloatXArray(result.S), [k, 1]);
|
|
32003
32372
|
const uCols = econ ? k : m;
|
|
32004
32373
|
const vCols = econ ? k : n;
|
|
32005
32374
|
return [
|
|
@@ -32020,7 +32389,7 @@ function svdApply(args, nargout) {
|
|
|
32020
32389
|
if (bridge?.svd) {
|
|
32021
32390
|
const result = bridge.svd(toF64(A.data), m, n, econ, nargout === 3);
|
|
32022
32391
|
if (result) {
|
|
32023
|
-
if (nargout
|
|
32392
|
+
if (nargout <= 1) return RTV.tensor(new FloatXArray(result.S), [k, 1]);
|
|
32024
32393
|
const uCols = econ ? k : m;
|
|
32025
32394
|
const vCols = econ ? k : n;
|
|
32026
32395
|
return [
|
|
@@ -32090,12 +32459,12 @@ function powerIterationEigenvalues(A_data, n, numEigenvalues) {
|
|
|
32090
32459
|
registerIBuiltin({
|
|
32091
32460
|
name: "qr",
|
|
32092
32461
|
resolve: (argTypes, nargout) => {
|
|
32093
|
-
if (nargout <
|
|
32462
|
+
if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 2)
|
|
32094
32463
|
return null;
|
|
32095
32464
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
32096
32465
|
const isComplex2 = argTypes[0].kind === "tensor" && argTypes[0].isComplex;
|
|
32097
32466
|
const t = tensorType(isComplex2 || void 0);
|
|
32098
|
-
if (nargout
|
|
32467
|
+
if (nargout <= 1)
|
|
32099
32468
|
return { outputTypes: [t], apply: (args, n) => qrApply(args, n) };
|
|
32100
32469
|
if (nargout === 3)
|
|
32101
32470
|
return {
|
|
@@ -32112,7 +32481,7 @@ function qrApply(args, nargout) {
|
|
|
32112
32481
|
if (isRuntimeNumber(A)) {
|
|
32113
32482
|
const val = A;
|
|
32114
32483
|
const s = val >= 0 ? 1 : -1;
|
|
32115
|
-
if (nargout
|
|
32484
|
+
if (nargout <= 1) return RTV.tensor(new FloatXArray([s * val]), [1, 1]);
|
|
32116
32485
|
if (nargout === 3)
|
|
32117
32486
|
return [
|
|
32118
32487
|
RTV.tensor(new FloatXArray([s]), [1, 1]),
|
|
@@ -32145,7 +32514,7 @@ function qrApply(args, nargout) {
|
|
|
32145
32514
|
nargout === 2
|
|
32146
32515
|
);
|
|
32147
32516
|
if (!result) throw new RuntimeError("qr: complex QR failed");
|
|
32148
|
-
if (nargout
|
|
32517
|
+
if (nargout <= 1) {
|
|
32149
32518
|
const rRows = econ ? k : m;
|
|
32150
32519
|
return RTV.tensor(
|
|
32151
32520
|
new FloatXArray(result.RRe),
|
|
@@ -32171,7 +32540,7 @@ function qrApply(args, nargout) {
|
|
|
32171
32540
|
if (bridge?.qr) {
|
|
32172
32541
|
const result = bridge.qr(toF64(A.data), m, n, econ, nargout === 2);
|
|
32173
32542
|
if (result) {
|
|
32174
|
-
if (nargout
|
|
32543
|
+
if (nargout <= 1)
|
|
32175
32544
|
return RTV.tensor(new FloatXArray(result.R), [econ ? k : m, n]);
|
|
32176
32545
|
const qCols = econ ? k : m;
|
|
32177
32546
|
return [
|
|
@@ -32214,7 +32583,7 @@ function qrApply(args, nargout) {
|
|
|
32214
32583
|
R_data[colMajorIndex(j + i, c, m)] -= scale * v[i];
|
|
32215
32584
|
}
|
|
32216
32585
|
}
|
|
32217
|
-
if (nargout
|
|
32586
|
+
if (nargout <= 1) {
|
|
32218
32587
|
if (econ) {
|
|
32219
32588
|
const R_econ = new FloatXArray(k * n);
|
|
32220
32589
|
for (let r = 0; r < k; r++)
|
|
@@ -32430,11 +32799,11 @@ function qrPivotApply(A, m, n, k, econ) {
|
|
|
32430
32799
|
registerIBuiltin({
|
|
32431
32800
|
name: "lu",
|
|
32432
32801
|
resolve: (argTypes, nargout) => {
|
|
32433
|
-
if (nargout <
|
|
32802
|
+
if (nargout < 0 || nargout > 3) return null;
|
|
32434
32803
|
if (argTypes.length < 1 || argTypes.length > 2) return null;
|
|
32435
32804
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
32436
32805
|
const t = tensorType();
|
|
32437
|
-
if (nargout
|
|
32806
|
+
if (nargout <= 1)
|
|
32438
32807
|
return { outputTypes: [t], apply: (args, n) => luApply(args, n) };
|
|
32439
32808
|
if (nargout === 2)
|
|
32440
32809
|
return { outputTypes: [t, t], apply: (args, n) => luApply(args, n) };
|
|
@@ -32453,7 +32822,7 @@ function luApply(args, nargout) {
|
|
|
32453
32822
|
if (nargout <= 2) {
|
|
32454
32823
|
const L2 = RTV.tensor(new FloatXArray([1]), [1, 1]);
|
|
32455
32824
|
const U2 = RTV.tensor(new FloatXArray([val]), [1, 1]);
|
|
32456
|
-
if (nargout
|
|
32825
|
+
if (nargout <= 1) return L2;
|
|
32457
32826
|
return [L2, U2];
|
|
32458
32827
|
}
|
|
32459
32828
|
const L = RTV.tensor(new FloatXArray([1]), [1, 1]);
|
|
@@ -32491,7 +32860,7 @@ function luApply(args, nargout) {
|
|
|
32491
32860
|
if (U_im && LU_im) U_im[i + j * k] = LU_im[i + j * m];
|
|
32492
32861
|
}
|
|
32493
32862
|
}
|
|
32494
|
-
if (nargout
|
|
32863
|
+
if (nargout <= 1)
|
|
32495
32864
|
return RTV.tensor(
|
|
32496
32865
|
new FloatXArray(LU_re),
|
|
32497
32866
|
[m, n],
|
|
@@ -32567,11 +32936,11 @@ function ipivToPermVector(ipiv, m) {
|
|
|
32567
32936
|
registerIBuiltin({
|
|
32568
32937
|
name: "eig",
|
|
32569
32938
|
resolve: (argTypes, nargout) => {
|
|
32570
|
-
if (nargout <
|
|
32939
|
+
if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 3)
|
|
32571
32940
|
return null;
|
|
32572
32941
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
32573
32942
|
const c = tensorType(true);
|
|
32574
|
-
if (nargout
|
|
32943
|
+
if (nargout <= 1)
|
|
32575
32944
|
return { outputTypes: [c], apply: (args, n) => eigApply(args, n) };
|
|
32576
32945
|
if (nargout === 2)
|
|
32577
32946
|
return { outputTypes: [c, c], apply: (args, n) => eigApply(args, n) };
|
|
@@ -32585,7 +32954,7 @@ function eigApply(args, nargout) {
|
|
|
32585
32954
|
const { balance, outputForm } = parseEigOptionsRuntime(args);
|
|
32586
32955
|
if (isRuntimeNumber(A)) {
|
|
32587
32956
|
const val = A;
|
|
32588
|
-
if (nargout
|
|
32957
|
+
if (nargout <= 1) return RTV.num(val);
|
|
32589
32958
|
const V = RTV.tensor(new FloatXArray([1]), [1, 1]);
|
|
32590
32959
|
if (nargout === 2) {
|
|
32591
32960
|
if (outputForm === "vector") return [V, RTV.num(val)];
|
|
@@ -32614,7 +32983,7 @@ function eigApply(args, nargout) {
|
|
|
32614
32983
|
);
|
|
32615
32984
|
if (!result2) throw new RuntimeError("eig: complex eig failed");
|
|
32616
32985
|
const { wRe, wIm, VLRe, VLIm, VRRe, VRIm } = result2;
|
|
32617
|
-
if (nargout
|
|
32986
|
+
if (nargout <= 1) return maybeComplexTensor(wRe, [n, 1], wIm);
|
|
32618
32987
|
const Vout2 = computeVR && VRRe && VRIm ? maybeComplexTensor(VRRe, [n, n], VRIm) : RTV.tensor(new FloatXArray(n * n), [n, n]);
|
|
32619
32988
|
const Dout2 = outputForm === "vector" ? maybeComplexTensor(wRe, [n, 1], wIm) : buildDiagMatrix(wRe, wIm, n);
|
|
32620
32989
|
if (nargout === 2) return [Vout2, Dout2];
|
|
@@ -32627,7 +32996,7 @@ function eigApply(args, nargout) {
|
|
|
32627
32996
|
if (!result) throw new RuntimeError("eig: LAPACK eig failed");
|
|
32628
32997
|
const { wr, wi, VL, VR } = result;
|
|
32629
32998
|
const hasComplex = wi.some((v) => v !== 0);
|
|
32630
|
-
if (nargout
|
|
32999
|
+
if (nargout <= 1) return maybeComplexTensor(wr, [n, 1], wi);
|
|
32631
33000
|
const Vout = computeVR && VR ? buildEigenvectorMatrix(VR, wi, n, hasComplex) : RTV.tensor(new FloatXArray(n * n), [n, n]);
|
|
32632
33001
|
const Dout = outputForm === "vector" ? maybeComplexTensor(wr, [n, 1], wi) : buildDiagMatrix(wr, wi, n);
|
|
32633
33002
|
if (nargout === 2) return [Vout, Dout];
|
|
@@ -32651,11 +33020,11 @@ function parseEigOptionsRuntime(args) {
|
|
|
32651
33020
|
registerIBuiltin({
|
|
32652
33021
|
name: "chol",
|
|
32653
33022
|
resolve: (argTypes, nargout) => {
|
|
32654
|
-
if (nargout <
|
|
33023
|
+
if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 3)
|
|
32655
33024
|
return null;
|
|
32656
33025
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
32657
33026
|
const t = tensorType();
|
|
32658
|
-
if (nargout
|
|
33027
|
+
if (nargout <= 1)
|
|
32659
33028
|
return { outputTypes: [t], apply: (args, n) => cholApply(args, n) };
|
|
32660
33029
|
if (nargout === 2)
|
|
32661
33030
|
return { outputTypes: [t, NUM], apply: (args, n) => cholApply(args, n) };
|
|
@@ -32816,7 +33185,7 @@ defineBuiltin({
|
|
|
32816
33185
|
cases: [
|
|
32817
33186
|
{
|
|
32818
33187
|
match: (argTypes, nargout) => {
|
|
32819
|
-
if (argTypes.length !== 2 || nargout
|
|
33188
|
+
if (argTypes.length !== 2 || nargout > 1) return null;
|
|
32820
33189
|
if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
|
|
32821
33190
|
return null;
|
|
32822
33191
|
return [tensorType()];
|
|
@@ -32859,7 +33228,7 @@ defineBuiltin({
|
|
|
32859
33228
|
cases: [
|
|
32860
33229
|
{
|
|
32861
33230
|
match: (argTypes, nargout) => {
|
|
32862
|
-
if (nargout
|
|
33231
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2)
|
|
32863
33232
|
return null;
|
|
32864
33233
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
32865
33234
|
return [NUM];
|
|
@@ -32920,7 +33289,7 @@ defineBuiltin({
|
|
|
32920
33289
|
cases: [
|
|
32921
33290
|
{
|
|
32922
33291
|
match: (argTypes, nargout) => {
|
|
32923
|
-
if (nargout
|
|
33292
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2)
|
|
32924
33293
|
return null;
|
|
32925
33294
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
32926
33295
|
return [NUM];
|
|
@@ -32968,7 +33337,7 @@ defineBuiltin({
|
|
|
32968
33337
|
cases: [
|
|
32969
33338
|
{
|
|
32970
33339
|
match: (argTypes, nargout) => {
|
|
32971
|
-
if (nargout
|
|
33340
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2)
|
|
32972
33341
|
return null;
|
|
32973
33342
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
32974
33343
|
const a = argTypes[0];
|
|
@@ -33065,7 +33434,7 @@ defineBuiltin({
|
|
|
33065
33434
|
cases: [
|
|
33066
33435
|
{
|
|
33067
33436
|
match: (argTypes, nargout) => {
|
|
33068
|
-
if (nargout
|
|
33437
|
+
if (nargout > 1 || argTypes.length !== 2) return null;
|
|
33069
33438
|
if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
|
|
33070
33439
|
return null;
|
|
33071
33440
|
return [tensorType()];
|
|
@@ -33073,11 +33442,15 @@ defineBuiltin({
|
|
|
33073
33442
|
apply: (args) => {
|
|
33074
33443
|
if (args.length !== 2)
|
|
33075
33444
|
throw new RuntimeError("kron requires 2 arguments");
|
|
33076
|
-
const
|
|
33077
|
-
|
|
33078
|
-
|
|
33079
|
-
|
|
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;
|
|
33080
33450
|
throw new RuntimeError("kron: arguments must be numeric");
|
|
33451
|
+
};
|
|
33452
|
+
const A = coerce(args[0]);
|
|
33453
|
+
const B = coerce(args[1]);
|
|
33081
33454
|
const [m, n] = tensorSize2D(A);
|
|
33082
33455
|
const [p2, q] = tensorSize2D(B);
|
|
33083
33456
|
const rows = m * p2, cols = n * q;
|
|
@@ -33101,7 +33474,7 @@ defineBuiltin({
|
|
|
33101
33474
|
cases: [
|
|
33102
33475
|
{
|
|
33103
33476
|
match: (argTypes, nargout) => {
|
|
33104
|
-
if (nargout
|
|
33477
|
+
if (nargout > 1 || argTypes.length === 0) return null;
|
|
33105
33478
|
if (!argTypes.every(isNumericJitType)) return null;
|
|
33106
33479
|
return [tensorType()];
|
|
33107
33480
|
},
|
|
@@ -33144,7 +33517,7 @@ defineBuiltin({
|
|
|
33144
33517
|
cases: [
|
|
33145
33518
|
{
|
|
33146
33519
|
match: (argTypes, nargout) => {
|
|
33147
|
-
if (nargout
|
|
33520
|
+
if (nargout > 1) return null;
|
|
33148
33521
|
if (argTypes.length !== 2 && argTypes.length !== 4) return null;
|
|
33149
33522
|
const xIdx = 0, yIdx = argTypes.length === 4 ? 2 : 1;
|
|
33150
33523
|
if (!isNumericJitType(argTypes[xIdx]) || !isNumericJitType(argTypes[yIdx]))
|
|
@@ -33273,7 +33646,7 @@ defineBuiltin({
|
|
|
33273
33646
|
cases: [
|
|
33274
33647
|
{
|
|
33275
33648
|
match: (argTypes, nargout) => {
|
|
33276
|
-
if (nargout
|
|
33649
|
+
if (nargout > 1 || argTypes.length !== 1) return null;
|
|
33277
33650
|
if (argTypes[0].kind !== "tensor") return null;
|
|
33278
33651
|
return [tensorType(argTypes[0].isComplex)];
|
|
33279
33652
|
},
|
|
@@ -35395,6 +35768,65 @@ defineBuiltin({
|
|
|
35395
35768
|
}
|
|
35396
35769
|
]
|
|
35397
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
|
+
});
|
|
35398
35830
|
function coordTransform(name, nArgs, nOut, fn) {
|
|
35399
35831
|
defineBuiltin({
|
|
35400
35832
|
name,
|
|
@@ -36524,6 +36956,131 @@ defineBuiltin({
|
|
|
36524
36956
|
}
|
|
36525
36957
|
]
|
|
36526
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
|
+
});
|
|
36527
37084
|
defineBuiltin({
|
|
36528
37085
|
name: "logical",
|
|
36529
37086
|
cases: [
|
|
@@ -37135,9 +37692,11 @@ registerIBuiltin({
|
|
|
37135
37692
|
// src/numbl-core/helpers/prng.ts
|
|
37136
37693
|
var _rngState = null;
|
|
37137
37694
|
var _rngSeed = 0;
|
|
37695
|
+
var _bmSpare = null;
|
|
37138
37696
|
function setRngShuffle() {
|
|
37139
37697
|
_rngState = null;
|
|
37140
37698
|
_rngSeed = 0;
|
|
37699
|
+
_bmSpare = null;
|
|
37141
37700
|
}
|
|
37142
37701
|
function setRngSeed(seed) {
|
|
37143
37702
|
_rngSeed = seed;
|
|
@@ -37153,6 +37712,7 @@ function splitmix32(seed) {
|
|
|
37153
37712
|
};
|
|
37154
37713
|
}
|
|
37155
37714
|
function seedRng(seed) {
|
|
37715
|
+
_bmSpare = null;
|
|
37156
37716
|
const sm = splitmix32(seed);
|
|
37157
37717
|
_rngState = new Uint32Array([sm(), sm(), sm(), sm()]);
|
|
37158
37718
|
if (_rngState[0] === 0 && _rngState[1] === 0 && _rngState[2] === 0 && _rngState[3] === 0) {
|
|
@@ -37179,10 +37739,60 @@ function rngRandom() {
|
|
|
37179
37739
|
return (xoshiro128ss() >>> 0) / 4294967296;
|
|
37180
37740
|
}
|
|
37181
37741
|
function boxMullerRandom() {
|
|
37182
|
-
|
|
37183
|
-
|
|
37184
|
-
|
|
37185
|
-
|
|
37742
|
+
if (_bmSpare !== null) {
|
|
37743
|
+
const s2 = _bmSpare;
|
|
37744
|
+
_bmSpare = null;
|
|
37745
|
+
return s2;
|
|
37746
|
+
}
|
|
37747
|
+
let u, v, s;
|
|
37748
|
+
do {
|
|
37749
|
+
u = 2 * rngRandom() - 1;
|
|
37750
|
+
v = 2 * rngRandom() - 1;
|
|
37751
|
+
s = u * u + v * v;
|
|
37752
|
+
} while (s >= 1 || s === 0);
|
|
37753
|
+
const mul = Math.sqrt(-2 * Math.log(s) / s);
|
|
37754
|
+
_bmSpare = v * mul;
|
|
37755
|
+
return u * mul;
|
|
37756
|
+
}
|
|
37757
|
+
function fillRandn(data) {
|
|
37758
|
+
if (_rngState !== null) {
|
|
37759
|
+
const bridge = getLapackBridge();
|
|
37760
|
+
if (bridge?.fillRandn) {
|
|
37761
|
+
const r = bridge.fillRandn(
|
|
37762
|
+
_rngState,
|
|
37763
|
+
data.length,
|
|
37764
|
+
_bmSpare ?? 0,
|
|
37765
|
+
_bmSpare !== null
|
|
37766
|
+
);
|
|
37767
|
+
_bmSpare = r.hasSpare ? r.spare : null;
|
|
37768
|
+
if (data instanceof Float64Array) {
|
|
37769
|
+
data.set(r.data);
|
|
37770
|
+
} else {
|
|
37771
|
+
for (let i2 = 0; i2 < data.length; i2++) data[i2] = r.data[i2];
|
|
37772
|
+
}
|
|
37773
|
+
return;
|
|
37774
|
+
}
|
|
37775
|
+
}
|
|
37776
|
+
const n = data.length;
|
|
37777
|
+
let i = 0;
|
|
37778
|
+
if (_bmSpare !== null && i < n) {
|
|
37779
|
+
data[i++] = _bmSpare;
|
|
37780
|
+
_bmSpare = null;
|
|
37781
|
+
}
|
|
37782
|
+
for (; i + 1 < n; i += 2) {
|
|
37783
|
+
let u, v, s;
|
|
37784
|
+
do {
|
|
37785
|
+
u = 2 * rngRandom() - 1;
|
|
37786
|
+
v = 2 * rngRandom() - 1;
|
|
37787
|
+
s = u * u + v * v;
|
|
37788
|
+
} while (s >= 1 || s === 0);
|
|
37789
|
+
const mul = Math.sqrt(-2 * Math.log(s) / s);
|
|
37790
|
+
data[i] = u * mul;
|
|
37791
|
+
data[i + 1] = v * mul;
|
|
37792
|
+
}
|
|
37793
|
+
if (i < n) {
|
|
37794
|
+
data[i] = boxMullerRandom();
|
|
37795
|
+
}
|
|
37186
37796
|
}
|
|
37187
37797
|
function getRngStateStruct() {
|
|
37188
37798
|
const stateArray = _rngState ? RTV.tensor(new FloatXArray(Array.from(_rngState).map((v) => v)), [4, 1]) : RTV.tensor(new FloatXArray(0), [0, 1]);
|
|
@@ -37250,7 +37860,7 @@ registerIBuiltin({
|
|
|
37250
37860
|
};
|
|
37251
37861
|
}
|
|
37252
37862
|
});
|
|
37253
|
-
function registerRandBuiltin(name, gen) {
|
|
37863
|
+
function registerRandBuiltin(name, gen, bulkFill) {
|
|
37254
37864
|
defineBuiltin({
|
|
37255
37865
|
name,
|
|
37256
37866
|
cases: [
|
|
@@ -37289,7 +37899,11 @@ function registerRandBuiltin(name, gen) {
|
|
|
37289
37899
|
if (shape.length === 1) shape.push(shape[0]);
|
|
37290
37900
|
const n = numel(shape);
|
|
37291
37901
|
const data = new FloatXArray(n);
|
|
37292
|
-
|
|
37902
|
+
if (bulkFill) {
|
|
37903
|
+
bulkFill(data);
|
|
37904
|
+
} else {
|
|
37905
|
+
for (let i = 0; i < n; i++) data[i] = gen();
|
|
37906
|
+
}
|
|
37293
37907
|
return RTV.tensor(data, shape);
|
|
37294
37908
|
}
|
|
37295
37909
|
}
|
|
@@ -37297,7 +37911,7 @@ function registerRandBuiltin(name, gen) {
|
|
|
37297
37911
|
});
|
|
37298
37912
|
}
|
|
37299
37913
|
registerRandBuiltin("rand", rngRandom);
|
|
37300
|
-
registerRandBuiltin("randn", boxMullerRandom);
|
|
37914
|
+
registerRandBuiltin("randn", boxMullerRandom, fillRandn);
|
|
37301
37915
|
defineBuiltin({
|
|
37302
37916
|
name: "randi",
|
|
37303
37917
|
cases: [
|
|
@@ -37744,6 +38358,9 @@ registerIBuiltin({
|
|
|
37744
38358
|
|
|
37745
38359
|
// src/numbl-core/interpreter/builtins/time-system.ts
|
|
37746
38360
|
var ticTime = 0;
|
|
38361
|
+
function getTicTime() {
|
|
38362
|
+
return ticTime;
|
|
38363
|
+
}
|
|
37747
38364
|
defineBuiltin({
|
|
37748
38365
|
name: "tic",
|
|
37749
38366
|
cases: [
|
|
@@ -37756,15 +38373,6 @@ defineBuiltin({
|
|
|
37756
38373
|
}
|
|
37757
38374
|
]
|
|
37758
38375
|
});
|
|
37759
|
-
defineBuiltin({
|
|
37760
|
-
name: "toc",
|
|
37761
|
-
cases: [
|
|
37762
|
-
{
|
|
37763
|
-
match: (argTypes) => argTypes.length === 0 ? [{ kind: "number" }] : null,
|
|
37764
|
-
apply: () => RTV.num((performance.now() - ticTime) / 1e3)
|
|
37765
|
-
}
|
|
37766
|
-
]
|
|
37767
|
-
});
|
|
37768
38376
|
defineBuiltin({
|
|
37769
38377
|
name: "clock",
|
|
37770
38378
|
cases: [
|
|
@@ -37855,6 +38463,24 @@ registerIBuiltin({
|
|
|
37855
38463
|
}
|
|
37856
38464
|
})
|
|
37857
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
|
+
});
|
|
37858
38484
|
var _platform = typeof process !== "undefined" ? process.platform : "linux";
|
|
37859
38485
|
for (const [name, val] of [
|
|
37860
38486
|
["ismac", _platform === "darwin"],
|
|
@@ -38753,6 +39379,44 @@ registerIBuiltin({
|
|
|
38753
39379
|
}
|
|
38754
39380
|
})
|
|
38755
39381
|
});
|
|
39382
|
+
var WEBOPTIONS_DEFAULTS = {
|
|
39383
|
+
CharacterEncoding: RTV.char("auto"),
|
|
39384
|
+
UserAgent: RTV.char("numbl"),
|
|
39385
|
+
Timeout: 5,
|
|
39386
|
+
Username: RTV.char(""),
|
|
39387
|
+
Password: RTV.char(""),
|
|
39388
|
+
KeyName: RTV.char(""),
|
|
39389
|
+
KeyValue: RTV.char(""),
|
|
39390
|
+
ContentType: RTV.char("auto"),
|
|
39391
|
+
MediaType: RTV.char("auto"),
|
|
39392
|
+
RequestMethod: RTV.char("auto"),
|
|
39393
|
+
ArrayFormat: RTV.char("csv"),
|
|
39394
|
+
CertificateFilename: RTV.char("default")
|
|
39395
|
+
};
|
|
39396
|
+
registerIBuiltin({
|
|
39397
|
+
name: "weboptions",
|
|
39398
|
+
resolve: () => ({
|
|
39399
|
+
outputTypes: [{ kind: "struct" }],
|
|
39400
|
+
apply: (args) => {
|
|
39401
|
+
const fields = /* @__PURE__ */ new Map();
|
|
39402
|
+
for (const [k, v] of Object.entries(WEBOPTIONS_DEFAULTS)) {
|
|
39403
|
+
fields.set(k, v);
|
|
39404
|
+
}
|
|
39405
|
+
if (args.length % 2 !== 0)
|
|
39406
|
+
throw new RuntimeError("weboptions: expected name-value pairs");
|
|
39407
|
+
for (let i = 0; i < args.length; i += 2) {
|
|
39408
|
+
const key = args[i];
|
|
39409
|
+
if (!isRuntimeChar(key) && !isRuntimeString(key))
|
|
39410
|
+
throw new RuntimeError("weboptions: option name must be a string");
|
|
39411
|
+
const name = isRuntimeChar(key) ? key.value : key;
|
|
39412
|
+
if (!(name in WEBOPTIONS_DEFAULTS))
|
|
39413
|
+
throw new RuntimeError(`weboptions: unknown option '${name}'`);
|
|
39414
|
+
fields.set(name, args[i + 1]);
|
|
39415
|
+
}
|
|
39416
|
+
return RTV.struct(Object.fromEntries(fields));
|
|
39417
|
+
}
|
|
39418
|
+
})
|
|
39419
|
+
});
|
|
38756
39420
|
registerIBuiltin({
|
|
38757
39421
|
name: "odeget",
|
|
38758
39422
|
resolve: () => ({
|
|
@@ -38862,7 +39526,7 @@ for (const name of ["clear", "clc", "clf"]) {
|
|
|
38862
39526
|
name,
|
|
38863
39527
|
resolve: () => ({
|
|
38864
39528
|
outputTypes: [],
|
|
38865
|
-
apply: () => 0
|
|
39529
|
+
apply: () => void 0
|
|
38866
39530
|
})
|
|
38867
39531
|
});
|
|
38868
39532
|
}
|
|
@@ -38996,7 +39660,7 @@ registerIBuiltin({
|
|
|
38996
39660
|
name: "set",
|
|
38997
39661
|
resolve: () => ({
|
|
38998
39662
|
outputTypes: [],
|
|
38999
|
-
apply: () => 0
|
|
39663
|
+
apply: () => void 0
|
|
39000
39664
|
})
|
|
39001
39665
|
});
|
|
39002
39666
|
for (const name of [
|
|
@@ -39018,7 +39682,7 @@ for (const name of [
|
|
|
39018
39682
|
name,
|
|
39019
39683
|
resolve: () => ({
|
|
39020
39684
|
outputTypes: [],
|
|
39021
|
-
apply: () => 0
|
|
39685
|
+
apply: () => void 0
|
|
39022
39686
|
})
|
|
39023
39687
|
});
|
|
39024
39688
|
}
|
|
@@ -43738,6 +44402,114 @@ function bisectEvent(eventIdx, step, events) {
|
|
|
43738
44402
|
return [tOld + xFinal * h, denseOutputEval(yOld, Q, h, xFinal)];
|
|
43739
44403
|
}
|
|
43740
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
|
+
|
|
43741
44513
|
// src/numbl-core/runtime/specialBuiltinNames.ts
|
|
43742
44514
|
var SPECIAL_BUILTIN_NAMES = [
|
|
43743
44515
|
"help",
|
|
@@ -43826,6 +44598,7 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
43826
44598
|
"webread",
|
|
43827
44599
|
"delete",
|
|
43828
44600
|
"rmdir",
|
|
44601
|
+
"movefile",
|
|
43829
44602
|
"unzip",
|
|
43830
44603
|
"dir",
|
|
43831
44604
|
"warning",
|
|
@@ -43838,7 +44611,9 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
43838
44611
|
"cd",
|
|
43839
44612
|
"ode45",
|
|
43840
44613
|
"ode23",
|
|
43841
|
-
"deval"
|
|
44614
|
+
"deval",
|
|
44615
|
+
"toc",
|
|
44616
|
+
"quadgk"
|
|
43842
44617
|
];
|
|
43843
44618
|
|
|
43844
44619
|
// src/numbl-core/runtime/specialBuiltins.ts
|
|
@@ -43852,49 +44627,74 @@ function registerSpecial(name, fn) {
|
|
|
43852
44627
|
})
|
|
43853
44628
|
});
|
|
43854
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
|
+
}
|
|
43855
44642
|
function registerSpecialBuiltins(rt) {
|
|
43856
|
-
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
|
+
};
|
|
43857
44649
|
if (args.length === 0) {
|
|
43858
44650
|
const names = getAllBuiltinNames().sort();
|
|
43859
|
-
|
|
43860
|
-
|
|
43861
|
-
|
|
43862
|
-
|
|
43863
|
-
|
|
43864
|
-
|
|
43865
|
-
|
|
43866
|
-
|
|
43867
|
-
|
|
43868
|
-
|
|
43869
|
-
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}'.
|
|
43870
44661
|
`);
|
|
43871
|
-
|
|
43872
|
-
|
|
44662
|
+
} else {
|
|
44663
|
+
emit(`Unknown function '${name}'.
|
|
43873
44664
|
`);
|
|
43874
|
-
|
|
43875
|
-
|
|
43876
|
-
|
|
43877
|
-
rt.output(` ${h.signatures.join("\n ")}
|
|
44665
|
+
}
|
|
44666
|
+
} else {
|
|
44667
|
+
emit(` ${h.signatures.join("\n ")}
|
|
43878
44668
|
|
|
43879
44669
|
`);
|
|
43880
|
-
|
|
44670
|
+
emit(`${h.description}
|
|
43881
44671
|
`);
|
|
43882
|
-
|
|
44672
|
+
}
|
|
44673
|
+
}
|
|
44674
|
+
return nargout >= 1 ? RTV.char(text) : void 0;
|
|
43883
44675
|
});
|
|
43884
|
-
|
|
44676
|
+
registerSpecialVoid("disp", (args) => {
|
|
43885
44677
|
if (args.length >= 1) {
|
|
43886
44678
|
const mv = ensureRuntimeValue(args[0]);
|
|
43887
|
-
if (isRuntimeTensor(mv) && mv.data.length === 0) return
|
|
44679
|
+
if (isRuntimeTensor(mv) && mv.data.length === 0) return;
|
|
43888
44680
|
rt.output(displayValue(mv) + "\n");
|
|
43889
44681
|
}
|
|
43890
|
-
return 0;
|
|
43891
44682
|
});
|
|
43892
|
-
registerSpecial("
|
|
43893
|
-
|
|
44683
|
+
registerSpecial("toc", (nargout) => {
|
|
44684
|
+
const elapsed = (performance.now() - getTicTime()) / 1e3;
|
|
44685
|
+
if (nargout === 0) {
|
|
44686
|
+
rt.output(`Elapsed time is ${elapsed.toFixed(6)} seconds.
|
|
44687
|
+
`);
|
|
44688
|
+
}
|
|
44689
|
+
return RTV.num(elapsed);
|
|
44690
|
+
});
|
|
44691
|
+
registerSpecial("warning", (nargout, args) => {
|
|
44692
|
+
if (args.length === 0) return nargout >= 1 ? RTV.num(0) : void 0;
|
|
43894
44693
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
43895
44694
|
if (margs.length === 2 && isRuntimeChar(margs[0]) && isRuntimeChar(margs[1])) {
|
|
43896
44695
|
const state = toString(margs[0]);
|
|
43897
44696
|
if (state === "on" || state === "off") {
|
|
44697
|
+
if (nargout === 0) return void 0;
|
|
43898
44698
|
return RTV.struct(
|
|
43899
44699
|
/* @__PURE__ */ new Map([
|
|
43900
44700
|
["state", RTV.char("on")],
|
|
@@ -43923,9 +44723,9 @@ function registerSpecialBuiltins(rt) {
|
|
|
43923
44723
|
} else {
|
|
43924
44724
|
rt.output("Warning: " + sprintfFormat(fmt, fmtArgs) + "\n");
|
|
43925
44725
|
}
|
|
43926
|
-
return RTV.num(0);
|
|
44726
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
43927
44727
|
});
|
|
43928
|
-
registerSpecial("fprintf", (
|
|
44728
|
+
registerSpecial("fprintf", (nargout, args) => {
|
|
43929
44729
|
let output = "";
|
|
43930
44730
|
if (args.length >= 1) {
|
|
43931
44731
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -43936,27 +44736,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
43936
44736
|
fmtIdx = 1;
|
|
43937
44737
|
}
|
|
43938
44738
|
const fmt = toString(margs[fmtIdx]);
|
|
43939
|
-
|
|
43940
|
-
for (let i = fmtIdx + 1; i < margs.length; i++) {
|
|
43941
|
-
const a = margs[i];
|
|
43942
|
-
if (isRuntimeTensor(a)) {
|
|
43943
|
-
for (let j = 0; j < a.data.length; j++)
|
|
43944
|
-
scalarArgs.push(RTV.num(a.data[j]));
|
|
43945
|
-
} else {
|
|
43946
|
-
scalarArgs.push(a);
|
|
43947
|
-
}
|
|
43948
|
-
}
|
|
43949
|
-
const specCount = (fmt.match(/%[^%]/g) || []).length;
|
|
43950
|
-
if (specCount === 0 || scalarArgs.length === 0) {
|
|
43951
|
-
output = sprintfFormat(fmt, scalarArgs);
|
|
43952
|
-
} else {
|
|
43953
|
-
let idx = 0;
|
|
43954
|
-
while (idx < scalarArgs.length) {
|
|
43955
|
-
const batch = scalarArgs.slice(idx, idx + specCount);
|
|
43956
|
-
output += sprintfFormat(fmt, batch);
|
|
43957
|
-
idx += specCount;
|
|
43958
|
-
}
|
|
43959
|
-
}
|
|
44739
|
+
output = sprintfFormat(fmt, margs.slice(fmtIdx + 1));
|
|
43960
44740
|
if (fid === 1 || fid === 2) {
|
|
43961
44741
|
rt.output(output);
|
|
43962
44742
|
} else {
|
|
@@ -43967,7 +44747,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
43967
44747
|
rt.fileIO.fwrite(fid, output);
|
|
43968
44748
|
}
|
|
43969
44749
|
}
|
|
43970
|
-
return output.length;
|
|
44750
|
+
return nargout >= 1 ? output.length : void 0;
|
|
43971
44751
|
});
|
|
43972
44752
|
registerSpecial("arrayfun", (nargout, args) => {
|
|
43973
44753
|
return arrayfunImpl(rt, nargout, args);
|
|
@@ -43999,6 +44779,55 @@ function registerSpecialBuiltins(rt) {
|
|
|
43999
44779
|
registerSpecial("bsxfun", (nargout, args) => {
|
|
44000
44780
|
return bsxfunImpl(rt, nargout, args);
|
|
44001
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
|
+
});
|
|
44002
44831
|
registerSpecial("subsref", (nargout, args) => {
|
|
44003
44832
|
return subsrefBuiltin(rt, nargout, args);
|
|
44004
44833
|
});
|
|
@@ -44527,6 +45356,40 @@ function registerSpecialBuiltins(rt) {
|
|
|
44527
45356
|
RTV.char("")
|
|
44528
45357
|
];
|
|
44529
45358
|
});
|
|
45359
|
+
function extractWebOptions(arg) {
|
|
45360
|
+
if (!isRuntimeStruct(arg)) return void 0;
|
|
45361
|
+
const s = arg;
|
|
45362
|
+
if (!s.fields.has("Timeout")) return void 0;
|
|
45363
|
+
const opts = {};
|
|
45364
|
+
const t = s.fields.get("Timeout");
|
|
45365
|
+
if (t !== void 0) opts.timeout = toNumber(t);
|
|
45366
|
+
const rm = s.fields.get("RequestMethod");
|
|
45367
|
+
if (rm !== void 0) {
|
|
45368
|
+
const v = toString(rm);
|
|
45369
|
+
if (v !== "auto") opts.requestMethod = v;
|
|
45370
|
+
}
|
|
45371
|
+
const un = s.fields.get("Username");
|
|
45372
|
+
if (un !== void 0) {
|
|
45373
|
+
const v = toString(un);
|
|
45374
|
+
if (v) opts.username = v;
|
|
45375
|
+
}
|
|
45376
|
+
const pw = s.fields.get("Password");
|
|
45377
|
+
if (pw !== void 0) {
|
|
45378
|
+
const v = toString(pw);
|
|
45379
|
+
if (v) opts.password = v;
|
|
45380
|
+
}
|
|
45381
|
+
const kn = s.fields.get("KeyName");
|
|
45382
|
+
if (kn !== void 0) {
|
|
45383
|
+
const v = toString(kn);
|
|
45384
|
+
if (v) opts.keyName = v;
|
|
45385
|
+
}
|
|
45386
|
+
const kv = s.fields.get("KeyValue");
|
|
45387
|
+
if (kv !== void 0) {
|
|
45388
|
+
const v = toString(kv);
|
|
45389
|
+
if (v) opts.keyValue = v;
|
|
45390
|
+
}
|
|
45391
|
+
return opts;
|
|
45392
|
+
}
|
|
44530
45393
|
registerSpecial("websave", (_nargout, args) => {
|
|
44531
45394
|
const io = requireFileIO();
|
|
44532
45395
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -44536,8 +45399,14 @@ function registerSpecialBuiltins(rt) {
|
|
|
44536
45399
|
throw new RuntimeError("websave is not available in this environment");
|
|
44537
45400
|
const filename = toString(margs[0]);
|
|
44538
45401
|
let url = toString(margs[1]);
|
|
45402
|
+
let webOpts;
|
|
45403
|
+
let queryEnd = margs.length;
|
|
45404
|
+
if (margs.length > 2) {
|
|
45405
|
+
webOpts = extractWebOptions(margs[margs.length - 1]);
|
|
45406
|
+
if (webOpts) queryEnd = margs.length - 1;
|
|
45407
|
+
}
|
|
44539
45408
|
const queryParts = [];
|
|
44540
|
-
for (let i = 2; i + 1 <
|
|
45409
|
+
for (let i = 2; i + 1 < queryEnd; i += 2) {
|
|
44541
45410
|
const name = encodeURIComponent(toString(margs[i]));
|
|
44542
45411
|
const value = encodeURIComponent(toString(margs[i + 1]));
|
|
44543
45412
|
queryParts.push(`${name}=${value}`);
|
|
@@ -44546,7 +45415,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44546
45415
|
const sep = url.includes("?") ? "&" : "?";
|
|
44547
45416
|
url += sep + queryParts.join("&");
|
|
44548
45417
|
}
|
|
44549
|
-
io.websave(url, filename);
|
|
45418
|
+
io.websave(url, filename, webOpts);
|
|
44550
45419
|
return RTV.char(filename);
|
|
44551
45420
|
});
|
|
44552
45421
|
registerSpecial("webread", (_nargout, args) => {
|
|
@@ -44557,8 +45426,14 @@ function registerSpecialBuiltins(rt) {
|
|
|
44557
45426
|
if (!io.webread)
|
|
44558
45427
|
throw new RuntimeError("webread is not available in this environment");
|
|
44559
45428
|
let url = toString(margs[0]);
|
|
45429
|
+
let webOpts;
|
|
45430
|
+
let queryEnd = margs.length;
|
|
45431
|
+
if (margs.length > 1) {
|
|
45432
|
+
webOpts = extractWebOptions(margs[margs.length - 1]);
|
|
45433
|
+
if (webOpts) queryEnd = margs.length - 1;
|
|
45434
|
+
}
|
|
44560
45435
|
const queryParts = [];
|
|
44561
|
-
for (let i = 1; i + 1 <
|
|
45436
|
+
for (let i = 1; i + 1 < queryEnd; i += 2) {
|
|
44562
45437
|
const name = encodeURIComponent(toString(margs[i]));
|
|
44563
45438
|
const value = encodeURIComponent(toString(margs[i + 1]));
|
|
44564
45439
|
queryParts.push(`${name}=${value}`);
|
|
@@ -44567,7 +45442,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44567
45442
|
const sep = url.includes("?") ? "&" : "?";
|
|
44568
45443
|
url += sep + queryParts.join("&");
|
|
44569
45444
|
}
|
|
44570
|
-
const text = io.webread(url);
|
|
45445
|
+
const text = io.webread(url, webOpts);
|
|
44571
45446
|
try {
|
|
44572
45447
|
const parsed = JSON.parse(text);
|
|
44573
45448
|
return convertJsonValue(parsed);
|
|
@@ -44575,7 +45450,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44575
45450
|
return RTV.char(text);
|
|
44576
45451
|
}
|
|
44577
45452
|
});
|
|
44578
|
-
|
|
45453
|
+
registerSpecialVoid("delete", (args) => {
|
|
44579
45454
|
const io = requireFileIO();
|
|
44580
45455
|
if (!io.deleteFile)
|
|
44581
45456
|
throw new RuntimeError("delete is not available in this environment");
|
|
@@ -44585,7 +45460,6 @@ function registerSpecialBuiltins(rt) {
|
|
|
44585
45460
|
for (const arg of margs) {
|
|
44586
45461
|
io.deleteFile(toString(arg));
|
|
44587
45462
|
}
|
|
44588
|
-
return 0;
|
|
44589
45463
|
});
|
|
44590
45464
|
registerSpecial("rmdir", (nargout, args) => {
|
|
44591
45465
|
const io = requireFileIO();
|
|
@@ -44608,6 +45482,34 @@ function registerSpecialBuiltins(rt) {
|
|
|
44608
45482
|
RTV.char("")
|
|
44609
45483
|
];
|
|
44610
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
|
+
});
|
|
44611
45513
|
registerSpecial("unzip", (nargout, args) => {
|
|
44612
45514
|
const io = requireFileIO();
|
|
44613
45515
|
if (!io.unzip)
|
|
@@ -44659,7 +45561,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44659
45561
|
const cellData = extracted.map((f) => RTV.char(f));
|
|
44660
45562
|
return RTV.cell(cellData, [1, cellData.length]);
|
|
44661
45563
|
}
|
|
44662
|
-
return 0;
|
|
45564
|
+
return void 0;
|
|
44663
45565
|
});
|
|
44664
45566
|
registerSpecial("dir", (nargout, args) => {
|
|
44665
45567
|
const io = requireFileIO();
|
|
@@ -44756,7 +45658,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44756
45658
|
const parts = margs.map((a) => toString(a));
|
|
44757
45659
|
return RTV.char(parts.join("/"));
|
|
44758
45660
|
});
|
|
44759
|
-
|
|
45661
|
+
registerSpecialVoid("assignin", (args) => {
|
|
44760
45662
|
if (args.length < 3)
|
|
44761
45663
|
throw new RuntimeError("assignin requires 3 arguments");
|
|
44762
45664
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -44771,7 +45673,6 @@ function registerSpecialBuiltins(rt) {
|
|
|
44771
45673
|
} else {
|
|
44772
45674
|
rt.setWorkspaceVariable(varName, args[2]);
|
|
44773
45675
|
}
|
|
44774
|
-
return 0;
|
|
44775
45676
|
});
|
|
44776
45677
|
registerSpecial("evalin", (_nargout, args) => {
|
|
44777
45678
|
if (args.length < 2)
|
|
@@ -44792,13 +45693,12 @@ function registerSpecialBuiltins(rt) {
|
|
|
44792
45693
|
}
|
|
44793
45694
|
return val;
|
|
44794
45695
|
});
|
|
44795
|
-
|
|
45696
|
+
registerSpecialVoid("drawnow", () => {
|
|
44796
45697
|
rt.drawnow();
|
|
44797
|
-
return 0;
|
|
44798
45698
|
});
|
|
44799
|
-
registerSpecial("pause", (
|
|
45699
|
+
registerSpecial("pause", (nargout, args) => {
|
|
44800
45700
|
rt.pause(args[0] ?? 0);
|
|
44801
|
-
return 0;
|
|
45701
|
+
return nargout >= 1 ? RTV.char("on") : void 0;
|
|
44802
45702
|
});
|
|
44803
45703
|
registerSpecial("mfilename", (_nargout, args) => {
|
|
44804
45704
|
const file = rt.$file ?? "";
|
|
@@ -44842,7 +45742,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
44842
45742
|
}
|
|
44843
45743
|
}
|
|
44844
45744
|
if (nargout >= 1) return RTV.char(rt.searchPaths.join(";"));
|
|
44845
|
-
return 0;
|
|
45745
|
+
return void 0;
|
|
44846
45746
|
});
|
|
44847
45747
|
registerSpecial("rmpath", (nargout, args) => {
|
|
44848
45748
|
if (!rt.onPathChange) {
|
|
@@ -44862,11 +45762,11 @@ function registerSpecialBuiltins(rt) {
|
|
|
44862
45762
|
}
|
|
44863
45763
|
}
|
|
44864
45764
|
if (nargout >= 1) return RTV.char(rt.searchPaths.join(";"));
|
|
44865
|
-
return 0;
|
|
45765
|
+
return void 0;
|
|
44866
45766
|
});
|
|
44867
|
-
registerSpecial("savepath", () => {
|
|
45767
|
+
registerSpecial("savepath", (nargout) => {
|
|
44868
45768
|
rt.output("Warning: savepath is a no-op in numbl\n");
|
|
44869
|
-
return 0;
|
|
45769
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
44870
45770
|
});
|
|
44871
45771
|
registerSpecial("input", (_nargout, args) => {
|
|
44872
45772
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
@@ -44929,11 +45829,11 @@ function registerSpecialBuiltins(rt) {
|
|
|
44929
45829
|
}
|
|
44930
45830
|
return RTV.char(sys?.getEnv(toString(args[0])) ?? "");
|
|
44931
45831
|
});
|
|
44932
|
-
|
|
45832
|
+
registerSpecialVoid("setenv", (args) => {
|
|
44933
45833
|
const sys = rt.system;
|
|
44934
45834
|
if (args.length === 2) {
|
|
44935
45835
|
sys?.setEnv(toString(args[0]), toString(args[1]));
|
|
44936
|
-
return
|
|
45836
|
+
return;
|
|
44937
45837
|
}
|
|
44938
45838
|
if (args.length === 1) {
|
|
44939
45839
|
const d = args[0];
|
|
@@ -44941,20 +45841,26 @@ function registerSpecialBuiltins(rt) {
|
|
|
44941
45841
|
for (const { key, value } of d.entries.values()) {
|
|
44942
45842
|
sys?.setEnv(toString(key), toString(value));
|
|
44943
45843
|
}
|
|
44944
|
-
return
|
|
45844
|
+
return;
|
|
44945
45845
|
}
|
|
44946
45846
|
sys?.setEnv(toString(d), "");
|
|
44947
|
-
return
|
|
45847
|
+
return;
|
|
44948
45848
|
}
|
|
44949
45849
|
throw new RuntimeError("setenv: invalid arguments");
|
|
44950
45850
|
});
|
|
44951
45851
|
registerSpecial("pwd", () => {
|
|
44952
45852
|
return RTV.char(rt.system?.cwd() ?? "/");
|
|
44953
45853
|
});
|
|
44954
|
-
registerSpecial("cd", (
|
|
45854
|
+
registerSpecial("cd", (nargout, args) => {
|
|
44955
45855
|
const sys = rt.system;
|
|
44956
45856
|
const curDir = sys?.cwd() ?? "/";
|
|
44957
|
-
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
|
+
}
|
|
44958
45864
|
const target = toString(args[0]);
|
|
44959
45865
|
if (sys) {
|
|
44960
45866
|
try {
|
|
@@ -44962,15 +45868,18 @@ function registerSpecialBuiltins(rt) {
|
|
|
44962
45868
|
} catch {
|
|
44963
45869
|
throw new RuntimeError(`Cannot change directory to '${target}'`);
|
|
44964
45870
|
}
|
|
45871
|
+
if (rt.onCwdChange) {
|
|
45872
|
+
rt.onCwdChange(sys.cwd());
|
|
45873
|
+
}
|
|
44965
45874
|
}
|
|
44966
|
-
return RTV.char(curDir);
|
|
45875
|
+
return nargout >= 1 ? RTV.char(curDir) : void 0;
|
|
44967
45876
|
});
|
|
44968
|
-
registerSpecial("figure", (
|
|
45877
|
+
registerSpecial("figure", (nargout, args) => {
|
|
44969
45878
|
const handle = args.length > 0 ? args[0] : 1;
|
|
44970
45879
|
plotInstr(rt.plotInstructions, { type: "set_figure_handle", handle });
|
|
44971
|
-
return 0;
|
|
45880
|
+
return nargout >= 1 ? RTV.num(toNumber(ensureRuntimeValue(handle))) : void 0;
|
|
44972
45881
|
});
|
|
44973
|
-
registerSpecial("subplot", (
|
|
45882
|
+
registerSpecial("subplot", (nargout, args) => {
|
|
44974
45883
|
if (args.length >= 3) {
|
|
44975
45884
|
plotInstr(rt.plotInstructions, {
|
|
44976
45885
|
type: "set_subplot",
|
|
@@ -44979,43 +45888,41 @@ function registerSpecialBuiltins(rt) {
|
|
|
44979
45888
|
index: args[2]
|
|
44980
45889
|
});
|
|
44981
45890
|
}
|
|
44982
|
-
return 0;
|
|
45891
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
44983
45892
|
});
|
|
44984
|
-
registerSpecial("title", (
|
|
45893
|
+
registerSpecial("title", (nargout, args) => {
|
|
44985
45894
|
if (args.length > 0) {
|
|
44986
45895
|
plotInstr(rt.plotInstructions, { type: "set_title", text: args[0] });
|
|
44987
45896
|
}
|
|
44988
|
-
return 0;
|
|
45897
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
44989
45898
|
});
|
|
44990
|
-
registerSpecial("xlabel", (
|
|
45899
|
+
registerSpecial("xlabel", (nargout, args) => {
|
|
44991
45900
|
if (args.length > 0) {
|
|
44992
45901
|
plotInstr(rt.plotInstructions, { type: "set_xlabel", text: args[0] });
|
|
44993
45902
|
}
|
|
44994
|
-
return 0;
|
|
45903
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
44995
45904
|
});
|
|
44996
|
-
registerSpecial("ylabel", (
|
|
45905
|
+
registerSpecial("ylabel", (nargout, args) => {
|
|
44997
45906
|
if (args.length > 0) {
|
|
44998
45907
|
plotInstr(rt.plotInstructions, { type: "set_ylabel", text: args[0] });
|
|
44999
45908
|
}
|
|
45000
|
-
return 0;
|
|
45909
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45001
45910
|
});
|
|
45002
|
-
|
|
45911
|
+
registerSpecialVoid("hold", (args) => {
|
|
45003
45912
|
if (args.length > 0) {
|
|
45004
45913
|
plotInstr(rt.plotInstructions, { type: "set_hold", value: args[0] });
|
|
45005
45914
|
}
|
|
45006
|
-
return 0;
|
|
45007
45915
|
});
|
|
45008
|
-
|
|
45916
|
+
registerSpecialVoid("grid", (args) => {
|
|
45009
45917
|
if (args.length > 0) {
|
|
45010
45918
|
plotInstr(rt.plotInstructions, { type: "set_grid", value: args[0] });
|
|
45011
45919
|
}
|
|
45012
|
-
return 0;
|
|
45013
45920
|
});
|
|
45014
|
-
registerSpecial("legend", (
|
|
45921
|
+
registerSpecial("legend", (nargout, args) => {
|
|
45015
45922
|
legendCall(rt.plotInstructions, args);
|
|
45016
|
-
return 0;
|
|
45923
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45017
45924
|
});
|
|
45018
|
-
registerSpecial("close", (
|
|
45925
|
+
registerSpecial("close", (nargout, args) => {
|
|
45019
45926
|
if (args.length > 0) {
|
|
45020
45927
|
const val = toString(args[0]);
|
|
45021
45928
|
if (val === "all") {
|
|
@@ -45026,26 +45933,25 @@ function registerSpecialBuiltins(rt) {
|
|
|
45026
45933
|
} else {
|
|
45027
45934
|
plotInstr(rt.plotInstructions, { type: "close" });
|
|
45028
45935
|
}
|
|
45029
|
-
return 0;
|
|
45936
|
+
return nargout >= 1 ? RTV.num(1) : void 0;
|
|
45030
45937
|
});
|
|
45031
|
-
registerSpecial("sgtitle", (
|
|
45938
|
+
registerSpecial("sgtitle", (nargout, args) => {
|
|
45032
45939
|
if (args.length > 0) {
|
|
45033
45940
|
plotInstr(rt.plotInstructions, { type: "set_sgtitle", text: args[0] });
|
|
45034
45941
|
}
|
|
45035
|
-
return 0;
|
|
45942
|
+
return nargout >= 1 ? RTV.num(0) : void 0;
|
|
45036
45943
|
});
|
|
45037
|
-
|
|
45944
|
+
registerSpecialVoid("shading", (args) => {
|
|
45038
45945
|
if (args.length > 0) {
|
|
45039
45946
|
plotInstr(rt.plotInstructions, {
|
|
45040
45947
|
type: "set_shading",
|
|
45041
45948
|
shading: args[0]
|
|
45042
45949
|
});
|
|
45043
45950
|
}
|
|
45044
|
-
return 0;
|
|
45045
45951
|
});
|
|
45046
|
-
registerSpecial("clf", () => {
|
|
45952
|
+
registerSpecial("clf", (nargout) => {
|
|
45047
45953
|
plotInstr(rt.plotInstructions, { type: "clf" });
|
|
45048
|
-
return 0;
|
|
45954
|
+
return nargout >= 1 ? RTV.num(1) : void 0;
|
|
45049
45955
|
});
|
|
45050
45956
|
registerSpecial("ode45", (nargout, args) => {
|
|
45051
45957
|
return _ode45Impl(rt, nargout, args, dormandPrince45);
|
|
@@ -45590,6 +46496,29 @@ function methodDispatch(rt, name, nargout, args) {
|
|
|
45590
46496
|
}
|
|
45591
46497
|
return fieldVal;
|
|
45592
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
|
+
}
|
|
45593
46522
|
try {
|
|
45594
46523
|
return callClassMethod(rt, firstRV.className, name, nargout, args);
|
|
45595
46524
|
} catch (e) {
|
|
@@ -46158,6 +47087,7 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
46158
47087
|
const im2 = t.imag[i];
|
|
46159
47088
|
return im2 === 0 ? t.data[i] : RTV.complex(t.data[i], im2);
|
|
46160
47089
|
}
|
|
47090
|
+
if (t._isLogical === true) return t.data[i] !== 0;
|
|
46161
47091
|
return t.data[i];
|
|
46162
47092
|
}
|
|
46163
47093
|
} else if (nIdx === 2) {
|
|
@@ -46166,7 +47096,14 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
46166
47096
|
if (typeof ri === "number" && typeof ci === "number") {
|
|
46167
47097
|
const s = t.shape;
|
|
46168
47098
|
const rows = s.length === 0 ? 1 : s.length === 1 ? 1 : s[0];
|
|
46169
|
-
|
|
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
|
+
}
|
|
46170
47107
|
const r = Math.round(ri) - 1;
|
|
46171
47108
|
const c = Math.round(ci) - 1;
|
|
46172
47109
|
if (r < 0 || r >= rows || c < 0 || c >= cols)
|
|
@@ -46176,6 +47113,7 @@ function index(rt, base, indices, nargout = 1, skipSubsref = false) {
|
|
|
46176
47113
|
const im2 = t.imag[lin];
|
|
46177
47114
|
return im2 === 0 ? t.data[lin] : RTV.complex(t.data[lin], im2);
|
|
46178
47115
|
}
|
|
47116
|
+
if (t._isLogical === true) return t.data[lin] !== 0;
|
|
46179
47117
|
return t.data[lin];
|
|
46180
47118
|
}
|
|
46181
47119
|
} else if (nIdx >= 3) {
|
|
@@ -46566,14 +47504,20 @@ function multiOutputCellAssign(base, indices, results) {
|
|
|
46566
47504
|
if (base === void 0 || base === null) base = RTV.cell([], [0, 0]);
|
|
46567
47505
|
let mv = ensureRuntimeValue(base);
|
|
46568
47506
|
if (!isRuntimeCell(mv)) mv = RTV.cell([], [0, 0]);
|
|
46569
|
-
const idxMv = ensureRuntimeValue(indices);
|
|
46570
47507
|
let idxArray;
|
|
46571
|
-
if (
|
|
46572
|
-
|
|
46573
|
-
|
|
46574
|
-
|
|
47508
|
+
if (indices === COLON_SENTINEL) {
|
|
47509
|
+
const n = mv.data.length;
|
|
47510
|
+
idxArray = [];
|
|
47511
|
+
for (let i = 1; i <= n; i++) idxArray.push(i);
|
|
46575
47512
|
} else {
|
|
46576
|
-
|
|
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
|
+
}
|
|
46577
47521
|
}
|
|
46578
47522
|
for (let i = 0; i < idxArray.length && i < results.length; i++) {
|
|
46579
47523
|
const idx = idxArray[i];
|
|
@@ -46800,6 +47744,8 @@ var Runtime = class _Runtime {
|
|
|
46800
47744
|
classMethodCache = /* @__PURE__ */ new Map();
|
|
46801
47745
|
/** Callback for addpath/rmpath — mutates search paths and rebuilds function index. */
|
|
46802
47746
|
onPathChange = null;
|
|
47747
|
+
/** Callback invoked after cd() to update the implicit cwd search path. */
|
|
47748
|
+
onCwdChange = null;
|
|
46803
47749
|
/** Reference to the active search paths (set by executeCode). */
|
|
46804
47750
|
searchPaths = [];
|
|
46805
47751
|
// Workspace accessors: varName → { get, set } closures over script-level vars
|
|
@@ -47079,23 +48025,26 @@ var Runtime = class _Runtime {
|
|
|
47079
48025
|
if (e instanceof RuntimeError) {
|
|
47080
48026
|
return RTV.struct(
|
|
47081
48027
|
/* @__PURE__ */ new Map([
|
|
47082
|
-
["message", RTV.
|
|
47083
|
-
["identifier", RTV.
|
|
48028
|
+
["message", RTV.char(e.message)],
|
|
48029
|
+
["identifier", RTV.char(e.identifier)],
|
|
48030
|
+
["stack", buildStackField(e)]
|
|
47084
48031
|
])
|
|
47085
48032
|
);
|
|
47086
48033
|
}
|
|
47087
48034
|
if (e instanceof Error) {
|
|
47088
48035
|
return RTV.struct(
|
|
47089
48036
|
/* @__PURE__ */ new Map([
|
|
47090
|
-
["message", RTV.
|
|
47091
|
-
["identifier", RTV.
|
|
48037
|
+
["message", RTV.char(e.message)],
|
|
48038
|
+
["identifier", RTV.char("")],
|
|
48039
|
+
["stack", emptyStackField()]
|
|
47092
48040
|
])
|
|
47093
48041
|
);
|
|
47094
48042
|
}
|
|
47095
48043
|
return RTV.struct(
|
|
47096
48044
|
/* @__PURE__ */ new Map([
|
|
47097
|
-
["message", RTV.
|
|
47098
|
-
["identifier", RTV.
|
|
48045
|
+
["message", RTV.char(String(e))],
|
|
48046
|
+
["identifier", RTV.char("")],
|
|
48047
|
+
["stack", emptyStackField()]
|
|
47099
48048
|
])
|
|
47100
48049
|
);
|
|
47101
48050
|
}
|
|
@@ -47927,6 +48876,63 @@ var rstr = (s) => {
|
|
|
47927
48876
|
if (isRuntimeChar(s)) return s.value;
|
|
47928
48877
|
throw new RuntimeError(`Expected string or char, got ${kstr(s)}`);
|
|
47929
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
|
+
}
|
|
47930
48936
|
|
|
47931
48937
|
// src/numbl-core/jsUserFunctions.ts
|
|
47932
48938
|
function funcNameFromFile(fileName) {
|
|
@@ -49175,9 +50181,7 @@ function lowerStmt(ctx, stmt) {
|
|
|
49175
50181
|
result = lowerAssign(ctx, stmt);
|
|
49176
50182
|
break;
|
|
49177
50183
|
case "ExprStmt":
|
|
49178
|
-
|
|
49179
|
-
result = lowerExprStmt(ctx, stmt);
|
|
49180
|
-
break;
|
|
50184
|
+
return null;
|
|
49181
50185
|
case "If":
|
|
49182
50186
|
result = lowerIf(ctx, stmt);
|
|
49183
50187
|
break;
|
|
@@ -49252,11 +50256,6 @@ function lowerMultiAssign(ctx, stmt) {
|
|
|
49252
50256
|
}
|
|
49253
50257
|
];
|
|
49254
50258
|
}
|
|
49255
|
-
function lowerExprStmt(ctx, stmt) {
|
|
49256
|
-
const expr = lowerExpr(ctx, stmt.expr);
|
|
49257
|
-
if (!expr) return null;
|
|
49258
|
-
return [{ tag: "ExprStmt", expr }];
|
|
49259
|
-
}
|
|
49260
50259
|
function lowerIf(ctx, stmt) {
|
|
49261
50260
|
const cond = lowerExpr(ctx, stmt.cond);
|
|
49262
50261
|
if (!cond) return null;
|
|
@@ -50325,10 +51324,14 @@ function execStmt(stmt) {
|
|
|
50325
51324
|
}
|
|
50326
51325
|
switch (stmt.type) {
|
|
50327
51326
|
case "ExprStmt": {
|
|
50328
|
-
const val = this.
|
|
51327
|
+
const val = this.evalExprNargout(stmt.expr, 0);
|
|
50329
51328
|
const singleVal = Array.isArray(val) ? val[0] : val;
|
|
51329
|
+
if (singleVal === void 0) {
|
|
51330
|
+
return null;
|
|
51331
|
+
}
|
|
50330
51332
|
const rv = ensureRuntimeValue(singleVal);
|
|
50331
51333
|
this.ans = rv;
|
|
51334
|
+
this.env.set("ans", rv);
|
|
50332
51335
|
if (!stmt.suppressed && !this.isOutputExpr(stmt.expr)) {
|
|
50333
51336
|
this.rt.displayResult(rv);
|
|
50334
51337
|
}
|
|
@@ -50349,19 +51352,25 @@ function execStmt(stmt) {
|
|
|
50349
51352
|
if (stmt.lvalues.length === 1 && stmt.lvalues[0].type === "IndexCell") {
|
|
50350
51353
|
const lv = stmt.lvalues[0];
|
|
50351
51354
|
const cellBase = lv.base.type === "Ident" ? this.env.get(lv.base.name) ?? RTV.cell([], [0, 0]) : this.evalExpr(lv.base);
|
|
50352
|
-
const indices =
|
|
50353
|
-
const idxVal = ensureRuntimeValue(indices[0]);
|
|
51355
|
+
const indices = this.evalIndicesWithEnd(cellBase, lv.indices);
|
|
50354
51356
|
let expandedCount = 1;
|
|
50355
|
-
|
|
50356
|
-
|
|
50357
|
-
|
|
50358
|
-
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
|
+
}
|
|
50359
51368
|
}
|
|
50360
51369
|
const val2 = this.evalExprNargout(stmt.expr, expandedCount);
|
|
50361
51370
|
const values2 = Array.isArray(val2) ? val2 : [val2];
|
|
50362
51371
|
const result = this.rt.multiOutputCellAssign(
|
|
50363
51372
|
cellBase,
|
|
50364
|
-
|
|
51373
|
+
idx0,
|
|
50365
51374
|
values2.map((v) => ensureRuntimeValue(v))
|
|
50366
51375
|
);
|
|
50367
51376
|
if (lv.base.type === "Ident") {
|
|
@@ -50378,10 +51387,12 @@ function execStmt(stmt) {
|
|
|
50378
51387
|
const rv = this.rt.share(i < values.length ? values[i] : void 0);
|
|
50379
51388
|
this.assignLValue(lv, rv);
|
|
50380
51389
|
}
|
|
50381
|
-
if (!stmt.suppressed
|
|
50382
|
-
|
|
50383
|
-
|
|
50384
|
-
|
|
51390
|
+
if (!stmt.suppressed) {
|
|
51391
|
+
for (let i = 0; i < stmt.lvalues.length; i++) {
|
|
51392
|
+
const lv = stmt.lvalues[i];
|
|
51393
|
+
if (lv.type === "Var" && i < values.length) {
|
|
51394
|
+
this.rt.displayAssign(lv.name, ensureRuntimeValue(values[i]));
|
|
51395
|
+
}
|
|
50385
51396
|
}
|
|
50386
51397
|
}
|
|
50387
51398
|
return null;
|
|
@@ -50738,6 +51749,18 @@ function evalArgs(argExprs) {
|
|
|
50738
51749
|
}
|
|
50739
51750
|
return args;
|
|
50740
51751
|
}
|
|
51752
|
+
var binopProfileName = {
|
|
51753
|
+
["Add" /* Add */]: "plus",
|
|
51754
|
+
["Sub" /* Sub */]: "minus",
|
|
51755
|
+
["Mul" /* Mul */]: "mtimes",
|
|
51756
|
+
["ElemMul" /* ElemMul */]: "times",
|
|
51757
|
+
["Div" /* Div */]: "mrdivide",
|
|
51758
|
+
["ElemDiv" /* ElemDiv */]: "rdivide",
|
|
51759
|
+
["LeftDiv" /* LeftDiv */]: "mldivide",
|
|
51760
|
+
["ElemLeftDiv" /* ElemLeftDiv */]: "ldivide",
|
|
51761
|
+
["Pow" /* Pow */]: "mpower",
|
|
51762
|
+
["ElemPow" /* ElemPow */]: "power"
|
|
51763
|
+
};
|
|
50741
51764
|
function evalBinary(expr) {
|
|
50742
51765
|
if (expr.op === "AndAnd" /* AndAnd */) {
|
|
50743
51766
|
const left2 = this.evalExpr(expr.left);
|
|
@@ -50763,6 +51786,13 @@ function evalBinary(expr) {
|
|
|
50763
51786
|
if (!isNaN(r)) return r;
|
|
50764
51787
|
return mPow(ensureRuntimeValue(left), ensureRuntimeValue(right));
|
|
50765
51788
|
}
|
|
51789
|
+
if (this.rt.profilingEnabled && (typeof left !== "number" || typeof right !== "number")) {
|
|
51790
|
+
const opName = binopProfileName[expr.op] ?? expr.op;
|
|
51791
|
+
this.rt.profileEnter("builtin:interp:" + opName);
|
|
51792
|
+
const result = binop(expr.op, left, right);
|
|
51793
|
+
this.rt.profileLeave();
|
|
51794
|
+
return result;
|
|
51795
|
+
}
|
|
50766
51796
|
return binop(expr.op, left, right);
|
|
50767
51797
|
}
|
|
50768
51798
|
function evalUnary(expr) {
|
|
@@ -50902,7 +51932,11 @@ function evalAnonFunc(expr) {
|
|
|
50902
51932
|
capturedMethodName,
|
|
50903
51933
|
() => {
|
|
50904
51934
|
try {
|
|
50905
|
-
|
|
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;
|
|
50906
51940
|
} finally {
|
|
50907
51941
|
this.env = savedEnv;
|
|
50908
51942
|
}
|
|
@@ -51161,7 +52195,6 @@ function switchMatch2(switchVal, caseVal) {
|
|
|
51161
52195
|
return switchMatch(switchVal, caseVal);
|
|
51162
52196
|
}
|
|
51163
52197
|
function isOutputExpr(expr) {
|
|
51164
|
-
if (expr.type !== "FuncCall") return false;
|
|
51165
52198
|
const outputFunctions = [
|
|
51166
52199
|
"disp",
|
|
51167
52200
|
"display",
|
|
@@ -51169,9 +52202,12 @@ function isOutputExpr(expr) {
|
|
|
51169
52202
|
"warning",
|
|
51170
52203
|
"assert",
|
|
51171
52204
|
"tic",
|
|
52205
|
+
"toc",
|
|
51172
52206
|
"help"
|
|
51173
52207
|
];
|
|
51174
|
-
return outputFunctions.includes(expr.name);
|
|
52208
|
+
if (expr.type === "FuncCall") return outputFunctions.includes(expr.name);
|
|
52209
|
+
if (expr.type === "Ident") return outputFunctions.includes(expr.name);
|
|
52210
|
+
return false;
|
|
51175
52211
|
}
|
|
51176
52212
|
|
|
51177
52213
|
// src/numbl-core/interpreter/interpreterFunctions.ts
|
|
@@ -51380,6 +52416,17 @@ register("exist", (ctx, args) => {
|
|
|
51380
52416
|
}
|
|
51381
52417
|
return FALL_THROUGH;
|
|
51382
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
|
+
});
|
|
51383
52430
|
register("isfolder", (ctx, args) => {
|
|
51384
52431
|
if (args.length < 1) return FALL_THROUGH;
|
|
51385
52432
|
const fio = ctx.rt.fileIO;
|
|
@@ -51482,6 +52529,9 @@ register("run", (ctx, args) => {
|
|
|
51482
52529
|
} catch {
|
|
51483
52530
|
throw new RuntimeError(`Cannot change directory to '${scriptDir}'`);
|
|
51484
52531
|
}
|
|
52532
|
+
if (ctx.rt.onCwdChange) {
|
|
52533
|
+
ctx.rt.onCwdChange(sys.cwd());
|
|
52534
|
+
}
|
|
51485
52535
|
}
|
|
51486
52536
|
const cwdAfterCd = sys?.cwd() ?? "/";
|
|
51487
52537
|
try {
|
|
@@ -51493,6 +52543,9 @@ register("run", (ctx, args) => {
|
|
|
51493
52543
|
sys.chdir(oldCwd);
|
|
51494
52544
|
} catch {
|
|
51495
52545
|
}
|
|
52546
|
+
if (ctx.rt.onCwdChange) {
|
|
52547
|
+
ctx.rt.onCwdChange(sys.cwd());
|
|
52548
|
+
}
|
|
51496
52549
|
}
|
|
51497
52550
|
}
|
|
51498
52551
|
return void 0;
|
|
@@ -51512,7 +52565,14 @@ function callFunction(name, args, nargout) {
|
|
|
51512
52565
|
workspaceEnv: this.workspaceEnv,
|
|
51513
52566
|
evalInLocalScope: (codeArg, fileName) => this.evalInLocalScope(codeArg, fileName),
|
|
51514
52567
|
callFunction: (n, a, no) => this.callFunction(n, a, no),
|
|
51515
|
-
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
|
+
}
|
|
51516
52576
|
};
|
|
51517
52577
|
const result = specialHandler(ctx, args, nargout);
|
|
51518
52578
|
if (result !== FALL_THROUGH) return result;
|
|
@@ -51546,13 +52606,18 @@ function interpretTarget(target, args, nargout) {
|
|
|
51546
52606
|
const argTypes = margs.map(inferJitType);
|
|
51547
52607
|
const resolution = ib.resolve(argTypes, nargout);
|
|
51548
52608
|
if (resolution) {
|
|
52609
|
+
const isVoid = resolution.outputTypes.length === 0;
|
|
52610
|
+
if (isVoid && nargout > 0) {
|
|
52611
|
+
throw new RuntimeError("Too many output arguments.");
|
|
52612
|
+
}
|
|
51549
52613
|
if (this.rt.profilingEnabled) {
|
|
51550
52614
|
this.rt.profileEnter("builtin:interp:" + target.name);
|
|
51551
|
-
const
|
|
52615
|
+
const result2 = resolution.apply(margs, nargout);
|
|
51552
52616
|
this.rt.profileLeave();
|
|
51553
|
-
return
|
|
52617
|
+
return isVoid ? void 0 : result2;
|
|
51554
52618
|
}
|
|
51555
|
-
|
|
52619
|
+
const result = resolution.apply(margs, nargout);
|
|
52620
|
+
return isVoid ? void 0 : result;
|
|
51556
52621
|
}
|
|
51557
52622
|
}
|
|
51558
52623
|
const builtin = this.rt.builtins[target.name];
|
|
@@ -51644,7 +52709,19 @@ function interpretLocalFunction(target, args, nargout) {
|
|
|
51644
52709
|
function interpretWorkspaceFunction(target, args, nargout) {
|
|
51645
52710
|
const dotIdx = target.name.lastIndexOf(".");
|
|
51646
52711
|
const primaryName = dotIdx >= 0 ? target.name.slice(dotIdx + 1) : target.name;
|
|
51647
|
-
|
|
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
|
+
}
|
|
51648
52725
|
if (!fn) {
|
|
51649
52726
|
const entry = this.ctx.registry.filesByFuncName.get(target.name);
|
|
51650
52727
|
if (entry) {
|
|
@@ -51788,6 +52865,11 @@ function interpretConstructor(classInfo, args, nargout) {
|
|
|
51788
52865
|
return args[0];
|
|
51789
52866
|
}
|
|
51790
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
|
+
}
|
|
51791
52873
|
if (this.optimization >= 1 && narginOverride === void 0) {
|
|
51792
52874
|
const jitResult = tryJitCall(this, fn, args, nargout);
|
|
51793
52875
|
if (jitResult !== JIT_SKIP) return jitResult;
|
|
@@ -51837,10 +52919,11 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
51837
52919
|
}
|
|
51838
52920
|
}
|
|
51839
52921
|
}
|
|
51840
|
-
const hasVarargout =
|
|
52922
|
+
const hasVarargout = hasVarargoutDecl;
|
|
51841
52923
|
const regularOutputs = hasVarargout ? fn.outputs.slice(0, -1) : fn.outputs;
|
|
52924
|
+
const collectCount = nargout === 0 && regularOutputs.length > 0 ? 1 : Math.min(regularOutputs.length, nargout);
|
|
51842
52925
|
const outputs = [];
|
|
51843
|
-
for (let i = 0; i <
|
|
52926
|
+
for (let i = 0; i < collectCount; i++) {
|
|
51844
52927
|
const val = this.env.get(regularOutputs[i]);
|
|
51845
52928
|
if (val === void 0 && nargout >= i + 1) {
|
|
51846
52929
|
throw new RuntimeError(
|
|
@@ -53410,10 +54493,17 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
53410
54493
|
if (options.log) {
|
|
53411
54494
|
options.log("AST parsed, starting interpretation");
|
|
53412
54495
|
}
|
|
54496
|
+
const isRepl = mainFileName === "repl";
|
|
53413
54497
|
const localFunctions = [];
|
|
53414
54498
|
const localClasses = [];
|
|
53415
54499
|
for (const stmt of ast.body) {
|
|
53416
54500
|
if (stmt.type === "Function") {
|
|
54501
|
+
if (isRepl) {
|
|
54502
|
+
throw new RuntimeError(
|
|
54503
|
+
"Function definitions are not supported in the REPL. Save the function to a .m file instead.",
|
|
54504
|
+
stmt.span
|
|
54505
|
+
);
|
|
54506
|
+
}
|
|
53417
54507
|
localFunctions.push(stmt);
|
|
53418
54508
|
} else if (stmt.type === "ClassDef") {
|
|
53419
54509
|
localClasses.push(stmt);
|
|
@@ -53434,6 +54524,31 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
53434
54524
|
}
|
|
53435
54525
|
}
|
|
53436
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
|
+
}
|
|
53437
54552
|
const jsUserFunctions = loadJsUserFunctions(
|
|
53438
54553
|
jsWorkspaceFiles,
|
|
53439
54554
|
wasmWorkspaceFiles,
|
|
@@ -53451,6 +54566,9 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
53451
54566
|
stdlibShimNames.add(shimName);
|
|
53452
54567
|
}
|
|
53453
54568
|
ctx.registry.searchPaths = [...searchPaths ?? [], SHIM_SEARCH_PATH];
|
|
54569
|
+
if (implicitCwdPath !== null) {
|
|
54570
|
+
ctx.registry.searchPaths.unshift(implicitCwdPath);
|
|
54571
|
+
}
|
|
53454
54572
|
ctx.fileASTCache.set(mainFileName, ast);
|
|
53455
54573
|
const skippedFiles = /* @__PURE__ */ new Set();
|
|
53456
54574
|
for (const f of mWorkspaceFiles) {
|
|
@@ -53484,6 +54602,11 @@ function executeCode(source, options = {}, workspaceFiles, mainFileName = "scrip
|
|
|
53484
54602
|
ctx.registerWorkspaceFiles(mWorkspaceFiles);
|
|
53485
54603
|
}
|
|
53486
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
|
+
}
|
|
53487
54610
|
const rt = new Runtime(options, options.initialVariableValues);
|
|
53488
54611
|
const savedIBuiltins = /* @__PURE__ */ new Map();
|
|
53489
54612
|
for (const ib of jsUserFunctions) {
|
|
@@ -53525,13 +54648,39 @@ ${jsCode}`
|
|
|
53525
54648
|
interpreter.installRuntimeCallbacks();
|
|
53526
54649
|
rt.searchPaths = ctx.registry.searchPaths;
|
|
53527
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
|
+
};
|
|
53528
54676
|
rt.onPathChange = (action, dir, position) => {
|
|
53529
54677
|
const fileIO = options.fileIO;
|
|
53530
54678
|
const absDir = fileIO?.resolvePath?.(dir) ?? dir;
|
|
53531
54679
|
if (action === "add") {
|
|
53532
54680
|
if (ctx.registry.searchPaths.includes(absDir)) return;
|
|
53533
54681
|
if (position === "begin") {
|
|
53534
|
-
ctx.registry.searchPaths
|
|
54682
|
+
const cwdIsFirst = implicitCwdPath !== null && ctx.registry.searchPaths[0] === implicitCwdPath;
|
|
54683
|
+
ctx.registry.searchPaths.splice(cwdIsFirst ? 1 : 0, 0, absDir);
|
|
53535
54684
|
} else {
|
|
53536
54685
|
const shimIdx = ctx.registry.searchPaths.indexOf(SHIM_SEARCH_PATH);
|
|
53537
54686
|
if (shimIdx >= 0) {
|
|
@@ -53549,10 +54698,14 @@ ${jsCode}`
|
|
|
53549
54698
|
try {
|
|
53550
54699
|
ctx.fileASTCache.set(f.name, parseMFile(f.source, f.name));
|
|
53551
54700
|
} catch (e) {
|
|
53552
|
-
if (e instanceof SyntaxError
|
|
53553
|
-
|
|
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)`);
|
|
53554
54707
|
}
|
|
53555
|
-
|
|
54708
|
+
continue;
|
|
53556
54709
|
}
|
|
53557
54710
|
interpreter.fileSources.set(f.name, f.source);
|
|
53558
54711
|
mWorkspaceFiles.push(f);
|
|
@@ -53592,26 +54745,76 @@ ${jsCode}`
|
|
|
53592
54745
|
}
|
|
53593
54746
|
}
|
|
53594
54747
|
}
|
|
53595
|
-
|
|
53596
|
-
|
|
53597
|
-
|
|
53598
|
-
|
|
53599
|
-
|
|
53600
|
-
|
|
53601
|
-
|
|
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))
|
|
53602
54758
|
);
|
|
53603
|
-
const
|
|
53604
|
-
|
|
53605
|
-
|
|
53606
|
-
|
|
53607
|
-
|
|
53608
|
-
|
|
53609
|
-
|
|
53610
|
-
|
|
53611
|
-
|
|
53612
|
-
|
|
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();
|
|
53613
54810
|
};
|
|
53614
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
|
+
);
|
|
53615
54818
|
const evalResult = executeCode(
|
|
53616
54819
|
code,
|
|
53617
54820
|
{
|
|
@@ -53619,11 +54822,18 @@ ${jsCode}`
|
|
|
53619
54822
|
displayResults: false,
|
|
53620
54823
|
initialVariableValues: initialVars,
|
|
53621
54824
|
fileIO: options.fileIO,
|
|
53622
|
-
|
|
54825
|
+
system: options.system,
|
|
54826
|
+
onInput: options.onInput,
|
|
54827
|
+
implicitCwdPath
|
|
53623
54828
|
},
|
|
53624
|
-
|
|
53625
|
-
fileName
|
|
54829
|
+
nestedWorkspaceFiles,
|
|
54830
|
+
fileName,
|
|
54831
|
+
nestedSearchPaths,
|
|
54832
|
+
nativeBridge
|
|
53626
54833
|
);
|
|
54834
|
+
if (evalResult.implicitCwdPath !== void 0) {
|
|
54835
|
+
implicitCwdPath = evalResult.implicitCwdPath;
|
|
54836
|
+
}
|
|
53627
54837
|
return {
|
|
53628
54838
|
returnValue: evalResult.returnValue,
|
|
53629
54839
|
variableValues: evalResult.variableValues,
|
|
@@ -53639,7 +54849,7 @@ ${jsCode}`
|
|
|
53639
54849
|
output: rt.outputLines,
|
|
53640
54850
|
generatedJS: jitSections.length > 0 ? `// Interpreter mode \u2014 JIT compiled sections:
|
|
53641
54851
|
|
|
53642
|
-
${jitSections.join("\n\n")}` : "//
|
|
54852
|
+
${jitSections.join("\n\n")}` : "// No JS generated",
|
|
53643
54853
|
plotInstructions: rt.plotInstructions,
|
|
53644
54854
|
returnValue: interpreter.ans ?? RTV.num(0),
|
|
53645
54855
|
variableValues: interpreter.getVariableValues(),
|
|
@@ -53655,17 +54865,18 @@ ${jitSections.join("\n\n")}` : "// interpreted mode \u2014 no JS generated",
|
|
|
53655
54865
|
}
|
|
53656
54866
|
if (pathsModified) {
|
|
53657
54867
|
result.searchPaths = ctx.registry.searchPaths.filter(
|
|
53658
|
-
(p2) => p2 !== SHIM_SEARCH_PATH
|
|
54868
|
+
(p2) => p2 !== SHIM_SEARCH_PATH && p2 !== implicitCwdPath
|
|
53659
54869
|
);
|
|
53660
54870
|
result.workspaceFiles = mWorkspaceFiles.filter(
|
|
53661
54871
|
(f) => !stdlibShimNames.has(f.name)
|
|
53662
54872
|
);
|
|
53663
54873
|
}
|
|
54874
|
+
result.implicitCwdPath = implicitCwdPath;
|
|
53664
54875
|
return result;
|
|
53665
54876
|
} catch (e) {
|
|
53666
54877
|
const generatedJS = jitSections.length > 0 ? `// Interpreter mode \u2014 JIT compiled sections:
|
|
53667
54878
|
|
|
53668
|
-
${jitSections.join("\n\n")}` : "//
|
|
54879
|
+
${jitSections.join("\n\n")}` : "// No JS generated";
|
|
53669
54880
|
if (e instanceof RuntimeError) {
|
|
53670
54881
|
if (e.line === null && rt.$file && rt.$line > 0) {
|
|
53671
54882
|
e.file = rt.$file;
|
|
@@ -53696,6 +54907,9 @@ ${jitSections.join("\n\n")}` : "// interpreted mode \u2014 no JS generated";
|
|
|
53696
54907
|
unregisterIBuiltin(ib.name);
|
|
53697
54908
|
}
|
|
53698
54909
|
}
|
|
54910
|
+
for (const [, ib] of savedSpecialBuiltins) {
|
|
54911
|
+
registerDynamicIBuiltin(ib);
|
|
54912
|
+
}
|
|
53699
54913
|
}
|
|
53700
54914
|
}
|
|
53701
54915
|
export {
|