numbl 0.4.12 → 0.4.14
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 +0 -4
- package/dist-browser/browser/index.d.ts +13 -4
- package/dist-browser/browser/protocol.d.ts +25 -1
- package/dist-browser/browser/session.d.ts +20 -10
- package/dist-browser/browser.js +26 -4
- package/dist-browser/numbl-core/fileIOAdapter.d.ts +4 -0
- package/dist-browser/numbl-core/native/lapack-bridge.d.ts +1 -1
- package/dist-browser/numbl-core/native/wasm-lapack-bridge.d.ts +114 -0
- package/dist-browser/numbl-core/native/wasm-lapack-browser.d.ts +34 -0
- package/dist-browser/numbl-core/runtime/datetime-format.d.ts +10 -0
- package/dist-browser/numbl-core/runtime/display.d.ts +5 -1
- package/dist-browser/numbl-core/runtime/index.d.ts +1 -1
- package/dist-browser/numbl-core/version.d.ts +1 -1
- package/dist-browser/vfs/BrowserFileIOAdapter.d.ts +1 -0
- package/dist-browser/workerErrorFormat.d.ts +7 -0
- package/dist-cli/cli.js +463 -135
- package/dist-graphics/graphics-lib.d.ts +1 -0
- package/dist-graphics/index.js +33 -0
- package/dist-lib/cli-fileio.d.ts +62 -0
- package/dist-lib/cli-scan.d.ts +6 -0
- package/dist-lib/cli-system.d.ts +13 -0
- package/dist-lib/lib.js +386 -73
- package/dist-lib/node.d.ts +30 -0
- package/dist-lib/node.js +829 -0
- package/dist-lib/numbl-core/fileIOAdapter.d.ts +4 -0
- package/dist-lib/numbl-core/native/lapack-bridge.d.ts +1 -1
- package/dist-lib/numbl-core/native/wasm-lapack-bridge.d.ts +114 -0
- package/dist-lib/numbl-core/native/wasm-lapack-browser.d.ts +34 -0
- package/dist-lib/numbl-core/runtime/datetime-format.d.ts +10 -0
- package/dist-lib/numbl-core/runtime/display.d.ts +5 -1
- package/dist-lib/numbl-core/runtime/index.d.ts +1 -1
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/dist-lib/vfs/BrowserFileIOAdapter.d.ts +1 -0
- package/dist-site-viewer/assets/{index-CGE1_vZ-.js → index-CqtJ-i-7.js} +322 -322
- package/dist-site-viewer/assets/{numbl-worker-DddtCPW_.js → numbl-worker-B-MPuV6f.js} +133 -103
- package/dist-site-viewer/index.html +1 -1
- package/package.json +6 -2
package/dist-lib/lib.js
CHANGED
|
@@ -819,6 +819,114 @@ var valuesAreEqual = (a, b) => {
|
|
|
819
819
|
}
|
|
820
820
|
};
|
|
821
821
|
|
|
822
|
+
// src/numbl-core/runtime/datetime-format.ts
|
|
823
|
+
var MONTH_ABBR = [
|
|
824
|
+
"Jan",
|
|
825
|
+
"Feb",
|
|
826
|
+
"Mar",
|
|
827
|
+
"Apr",
|
|
828
|
+
"May",
|
|
829
|
+
"Jun",
|
|
830
|
+
"Jul",
|
|
831
|
+
"Aug",
|
|
832
|
+
"Sep",
|
|
833
|
+
"Oct",
|
|
834
|
+
"Nov",
|
|
835
|
+
"Dec"
|
|
836
|
+
];
|
|
837
|
+
var MONTH_FULL = [
|
|
838
|
+
"January",
|
|
839
|
+
"February",
|
|
840
|
+
"March",
|
|
841
|
+
"April",
|
|
842
|
+
"May",
|
|
843
|
+
"June",
|
|
844
|
+
"July",
|
|
845
|
+
"August",
|
|
846
|
+
"September",
|
|
847
|
+
"October",
|
|
848
|
+
"November",
|
|
849
|
+
"December"
|
|
850
|
+
];
|
|
851
|
+
function pad(n, width) {
|
|
852
|
+
return String(n).padStart(width, "0");
|
|
853
|
+
}
|
|
854
|
+
function formatDatetimePattern(pattern, year, month, day, hour, minute, second) {
|
|
855
|
+
const wholeSec = Math.floor(second);
|
|
856
|
+
const frac = second - wholeSec;
|
|
857
|
+
const monthIdx = Math.max(0, Math.min(11, Math.floor(month) - 1));
|
|
858
|
+
const formatToken = (c, n) => {
|
|
859
|
+
switch (c) {
|
|
860
|
+
case "y":
|
|
861
|
+
case "u":
|
|
862
|
+
if (n === 2) return pad(Math.floor(year) % 100, 2);
|
|
863
|
+
return pad(Math.floor(year), n);
|
|
864
|
+
case "M":
|
|
865
|
+
if (n === 1) return String(Math.floor(month));
|
|
866
|
+
if (n === 2) return pad(Math.floor(month), 2);
|
|
867
|
+
if (n === 3) return MONTH_ABBR[monthIdx];
|
|
868
|
+
return MONTH_FULL[monthIdx];
|
|
869
|
+
case "d":
|
|
870
|
+
return pad(Math.floor(day), n);
|
|
871
|
+
case "H":
|
|
872
|
+
return pad(Math.floor(hour), n);
|
|
873
|
+
case "h":
|
|
874
|
+
return pad(Math.floor(hour) % 12 || 12, n);
|
|
875
|
+
case "m":
|
|
876
|
+
return pad(Math.floor(minute), n);
|
|
877
|
+
case "s":
|
|
878
|
+
return pad(wholeSec, n);
|
|
879
|
+
case "S":
|
|
880
|
+
return pad(Math.floor(frac * Math.pow(10, n)), n);
|
|
881
|
+
case "a":
|
|
882
|
+
return hour < 12 ? "AM" : "PM";
|
|
883
|
+
default:
|
|
884
|
+
throw new RuntimeError(
|
|
885
|
+
`datetime: unsupported format token '${c.repeat(n)}' in '${pattern}'`
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
let out = "";
|
|
890
|
+
let i = 0;
|
|
891
|
+
while (i < pattern.length) {
|
|
892
|
+
const c = pattern[i];
|
|
893
|
+
if (c === "'") {
|
|
894
|
+
i++;
|
|
895
|
+
let lit = "";
|
|
896
|
+
let closed = false;
|
|
897
|
+
while (i < pattern.length) {
|
|
898
|
+
if (pattern[i] === "'") {
|
|
899
|
+
if (pattern[i + 1] === "'") {
|
|
900
|
+
lit += "'";
|
|
901
|
+
i += 2;
|
|
902
|
+
continue;
|
|
903
|
+
}
|
|
904
|
+
i++;
|
|
905
|
+
closed = true;
|
|
906
|
+
break;
|
|
907
|
+
}
|
|
908
|
+
lit += pattern[i++];
|
|
909
|
+
}
|
|
910
|
+
if (!closed && lit !== "")
|
|
911
|
+
throw new RuntimeError(
|
|
912
|
+
`datetime: unterminated quoted literal in format '${pattern}'`
|
|
913
|
+
);
|
|
914
|
+
out += lit === "" ? "'" : lit;
|
|
915
|
+
continue;
|
|
916
|
+
}
|
|
917
|
+
if (!/[a-zA-Z]/.test(c)) {
|
|
918
|
+
out += c;
|
|
919
|
+
i++;
|
|
920
|
+
continue;
|
|
921
|
+
}
|
|
922
|
+
let j = i;
|
|
923
|
+
while (j < pattern.length && pattern[j] === c) j++;
|
|
924
|
+
out += formatToken(c, j - i);
|
|
925
|
+
i = j;
|
|
926
|
+
}
|
|
927
|
+
return out;
|
|
928
|
+
}
|
|
929
|
+
|
|
822
930
|
// src/numbl-core/runtime/display.ts
|
|
823
931
|
function displayValue(v) {
|
|
824
932
|
if (isRuntimeNumber(v)) {
|
|
@@ -1093,6 +1201,13 @@ function formatDatetimeOrDuration(v) {
|
|
|
1093
1201
|
if (v.className === "duration") return formatDurationInstance(v);
|
|
1094
1202
|
return null;
|
|
1095
1203
|
}
|
|
1204
|
+
function textField(v, name) {
|
|
1205
|
+
const fv = v.fields.get(name);
|
|
1206
|
+
if (fv === void 0) return null;
|
|
1207
|
+
if (isRuntimeString(fv)) return fv;
|
|
1208
|
+
if (isRuntimeChar(fv)) return fv.value;
|
|
1209
|
+
return null;
|
|
1210
|
+
}
|
|
1096
1211
|
function formatDatetimeInstance(v) {
|
|
1097
1212
|
const year = numField(v, "Year");
|
|
1098
1213
|
const month = numField(v, "Month");
|
|
@@ -1102,6 +1217,10 @@ function formatDatetimeInstance(v) {
|
|
|
1102
1217
|
const second = numField(v, "Second");
|
|
1103
1218
|
if (year === null || month === null || day === null || hour === null || minute === null || second === null)
|
|
1104
1219
|
return null;
|
|
1220
|
+
const fmt = textField(v, "Format");
|
|
1221
|
+
if (fmt !== null && fmt !== "") {
|
|
1222
|
+
return formatDatetimePattern(fmt, year, month, day, hour, minute, second);
|
|
1223
|
+
}
|
|
1105
1224
|
const mIdx = Math.max(0, Math.min(11, Math.floor(month) - 1));
|
|
1106
1225
|
const mon = DATETIME_MONTH_ABBR[mIdx];
|
|
1107
1226
|
const dd = String(Math.floor(day)).padStart(2, "0");
|
|
@@ -22321,8 +22440,8 @@ function sprintfFormat(fmt, args) {
|
|
|
22321
22440
|
if (width > 0) {
|
|
22322
22441
|
const padChar = zeroPad ? "0" : " ";
|
|
22323
22442
|
const padLen = Math.max(0, width - sign.length - s.length);
|
|
22324
|
-
const
|
|
22325
|
-
result += leftAlign ? sign + s + " ".repeat(padLen) : zeroPad ? sign +
|
|
22443
|
+
const pad2 = padChar.repeat(padLen);
|
|
22444
|
+
result += leftAlign ? sign + s + " ".repeat(padLen) : zeroPad ? sign + pad2 + s : pad2 + sign + s;
|
|
22326
22445
|
} else {
|
|
22327
22446
|
result += sign + s;
|
|
22328
22447
|
}
|
|
@@ -25046,6 +25165,17 @@ function indexIntoRTValue(base, indices) {
|
|
|
25046
25165
|
return base.elements[i];
|
|
25047
25166
|
}
|
|
25048
25167
|
if (isRuntimeTensor(idx)) {
|
|
25168
|
+
if (idx._isLogical) {
|
|
25169
|
+
const newElements2 = [];
|
|
25170
|
+
for (let k = 0; k < idx.data.length; k++) {
|
|
25171
|
+
if (idx.data[k] !== 0) {
|
|
25172
|
+
if (k >= base.elements.length)
|
|
25173
|
+
throw new RuntimeError("Index exceeds struct array bounds");
|
|
25174
|
+
newElements2.push(base.elements[k]);
|
|
25175
|
+
}
|
|
25176
|
+
}
|
|
25177
|
+
return RTV.structArray(base.fieldNames, newElements2);
|
|
25178
|
+
}
|
|
25049
25179
|
const newElements = [];
|
|
25050
25180
|
for (let k = 0; k < idx.data.length; k++) {
|
|
25051
25181
|
const i = Math.round(idx.data[k]) - 1;
|
|
@@ -38167,13 +38297,19 @@ registerIBuiltin({
|
|
|
38167
38297
|
resolve: (argTypes) => {
|
|
38168
38298
|
if (argTypes.length !== 1) return null;
|
|
38169
38299
|
const a = argTypes[0];
|
|
38170
|
-
if (a.kind !== "char" && a.kind !== "string" && a.kind !== "number" && a.kind !== "tensor" && a.kind !== "cell" && a.kind !== "unknown"
|
|
38300
|
+
if (a.kind !== "char" && a.kind !== "string" && a.kind !== "number" && a.kind !== "tensor" && a.kind !== "cell" && a.kind !== "unknown" && // datetime/duration only — other classes keep their own char methods
|
|
38301
|
+
// (or the generic "does not support these argument types" error).
|
|
38302
|
+
!(a.kind === "class_instance" && (a.className === "datetime" || a.className === "duration")))
|
|
38171
38303
|
return null;
|
|
38172
38304
|
return {
|
|
38173
38305
|
outputTypes: [{ kind: "char" }],
|
|
38174
38306
|
apply: (args) => {
|
|
38175
38307
|
const v = args[0];
|
|
38176
38308
|
if (isRuntimeChar(v)) return v;
|
|
38309
|
+
if (isRuntimeClassInstance(v)) {
|
|
38310
|
+
const s = formatDatetimeOrDuration(v);
|
|
38311
|
+
if (s !== null) return RTV.char(s);
|
|
38312
|
+
}
|
|
38177
38313
|
if (isRuntimeString(v)) return RTV.char(v);
|
|
38178
38314
|
if (isRuntimeNumber(v))
|
|
38179
38315
|
return RTV.char(String.fromCharCode(Math.round(v)));
|
|
@@ -40561,7 +40697,7 @@ defineBuiltin({
|
|
|
40561
40697
|
const result = invComplexJS(A.data, A.imag, n);
|
|
40562
40698
|
return RTV.tensor(result.re, [n, n], result.im);
|
|
40563
40699
|
}
|
|
40564
|
-
const bridge = getEffectiveBridge("inv");
|
|
40700
|
+
const bridge = getEffectiveBridge("inv", "inv");
|
|
40565
40701
|
return RTV.tensor(bridge.inv(toF64(A.data), n), [n, n]);
|
|
40566
40702
|
}
|
|
40567
40703
|
}
|
|
@@ -42908,6 +43044,16 @@ defineBuiltin({
|
|
|
42908
43044
|
parseReshapeDims(args, 1);
|
|
42909
43045
|
return v;
|
|
42910
43046
|
}
|
|
43047
|
+
if (isRuntimeCell(v)) {
|
|
43048
|
+
const total = v.data.length;
|
|
43049
|
+
const s = parseReshapeDims(args, total);
|
|
43050
|
+
while (s.length > 2 && s[s.length - 1] === 1) s.pop();
|
|
43051
|
+
if (s.length > 2)
|
|
43052
|
+
throw new RuntimeError("reshape: cell arrays must be 2-D");
|
|
43053
|
+
const nr = s[0];
|
|
43054
|
+
const nc = s.length >= 2 ? s[1] : 1;
|
|
43055
|
+
return RTV.cell(v.data.slice(), [nr, nc]);
|
|
43056
|
+
}
|
|
42911
43057
|
if (isRuntimeClassInstanceArray(v)) {
|
|
42912
43058
|
const total = v.elements.length;
|
|
42913
43059
|
const s = parseReshapeDims(args, total);
|
|
@@ -48654,6 +48800,32 @@ function datetimeFromUtcMs(ms) {
|
|
|
48654
48800
|
function datetimeFromDatenum(dn) {
|
|
48655
48801
|
return datetimeFromUtcMs((dn - MATLAB_EPOCH_DAYS) * 864e5);
|
|
48656
48802
|
}
|
|
48803
|
+
function withTimeZoneFormat(dt, timeZone, format) {
|
|
48804
|
+
if (timeZone === void 0 && format === void 0) return dt;
|
|
48805
|
+
const fields = new Map(dt.fields);
|
|
48806
|
+
if (timeZone !== void 0) fields.set("TimeZone", RTV.char(timeZone));
|
|
48807
|
+
if (format !== void 0) fields.set("Format", RTV.char(format));
|
|
48808
|
+
return new RuntimeClassInstance("datetime", fields, false);
|
|
48809
|
+
}
|
|
48810
|
+
function todayParts(offsetDays, utc) {
|
|
48811
|
+
const now = /* @__PURE__ */ new Date();
|
|
48812
|
+
if (utc) {
|
|
48813
|
+
const d2 = new Date(
|
|
48814
|
+
Date.UTC(
|
|
48815
|
+
now.getUTCFullYear(),
|
|
48816
|
+
now.getUTCMonth(),
|
|
48817
|
+
now.getUTCDate() + offsetDays
|
|
48818
|
+
)
|
|
48819
|
+
);
|
|
48820
|
+
return [d2.getUTCFullYear(), d2.getUTCMonth() + 1, d2.getUTCDate()];
|
|
48821
|
+
}
|
|
48822
|
+
const d = new Date(
|
|
48823
|
+
now.getFullYear(),
|
|
48824
|
+
now.getMonth(),
|
|
48825
|
+
now.getDate() + offsetDays
|
|
48826
|
+
);
|
|
48827
|
+
return [d.getFullYear(), d.getMonth() + 1, d.getDate()];
|
|
48828
|
+
}
|
|
48657
48829
|
function makeDuration(totalSeconds) {
|
|
48658
48830
|
const fields = /* @__PURE__ */ new Map([
|
|
48659
48831
|
["Seconds", RTV.num(totalSeconds)]
|
|
@@ -48703,9 +48875,10 @@ registerIBuiltin({
|
|
|
48703
48875
|
"t = datetime('now' | 'today' | 'yesterday' | 'tomorrow')",
|
|
48704
48876
|
"t = datetime(Y, M, D)",
|
|
48705
48877
|
"t = datetime(Y, M, D, H, MI, S)",
|
|
48706
|
-
"t = datetime(X, 'ConvertFrom', dateType)"
|
|
48878
|
+
"t = datetime(X, 'ConvertFrom', dateType)",
|
|
48879
|
+
"t = datetime(..., 'TimeZone', tz, 'Format', fmt)"
|
|
48707
48880
|
],
|
|
48708
|
-
description: "Create a datetime value. Supported dateType values for ConvertFrom: 'datenum', 'posixtime', 'excel', 'excel1904'."
|
|
48881
|
+
description: "Create a datetime value. Supported dateType values for ConvertFrom: 'datenum', 'posixtime', 'excel', 'excel1904'. Trailing 'TimeZone' (only '', 'local', 'UTC') and 'Format' name-value pairs are supported; the Format pattern is used by char() and display."
|
|
48709
48882
|
},
|
|
48710
48883
|
resolve: () => ({
|
|
48711
48884
|
outputTypes: [
|
|
@@ -48717,75 +48890,83 @@ registerIBuiltin({
|
|
|
48717
48890
|
}
|
|
48718
48891
|
],
|
|
48719
48892
|
apply: (args) => {
|
|
48720
|
-
|
|
48721
|
-
|
|
48893
|
+
let timeZone;
|
|
48894
|
+
let format;
|
|
48895
|
+
let positional = args;
|
|
48896
|
+
while (positional.length >= 2) {
|
|
48897
|
+
const name = argToString(positional[positional.length - 2]);
|
|
48898
|
+
if (name === null) break;
|
|
48899
|
+
const lc = name.toLowerCase();
|
|
48900
|
+
if (lc !== "timezone" && lc !== "format") break;
|
|
48901
|
+
const value = argToString(positional[positional.length - 1]);
|
|
48902
|
+
if (value === null)
|
|
48903
|
+
throw new RuntimeError(`datetime: ${name} value must be text`);
|
|
48904
|
+
if (lc === "timezone") timeZone = value;
|
|
48905
|
+
else format = value;
|
|
48906
|
+
positional = positional.slice(0, -2);
|
|
48907
|
+
}
|
|
48908
|
+
const tzLc = timeZone?.toLowerCase();
|
|
48909
|
+
if (tzLc !== void 0 && tzLc !== "" && tzLc !== "local" && tzLc !== "utc") {
|
|
48910
|
+
throw new RuntimeError(
|
|
48911
|
+
`datetime: unsupported TimeZone '${timeZone}' (supported: '', 'local', 'UTC')`
|
|
48912
|
+
);
|
|
48722
48913
|
}
|
|
48723
|
-
|
|
48724
|
-
|
|
48914
|
+
const utc = tzLc === "utc";
|
|
48915
|
+
const finish = (dt) => withTimeZoneFormat(dt, timeZone, format);
|
|
48916
|
+
if (positional.length === 0) {
|
|
48917
|
+
return finish(
|
|
48918
|
+
utc ? datetimeFromUtcMs(Date.now()) : datetimeFromDate(/* @__PURE__ */ new Date())
|
|
48919
|
+
);
|
|
48920
|
+
}
|
|
48921
|
+
if (positional.length === 1) {
|
|
48922
|
+
const s = argToString(positional[0]);
|
|
48725
48923
|
if (s !== null) {
|
|
48726
|
-
const now = /* @__PURE__ */ new Date();
|
|
48727
48924
|
const lc = s.toLowerCase();
|
|
48728
|
-
if (lc === "now")
|
|
48729
|
-
|
|
48730
|
-
|
|
48731
|
-
now.getFullYear(),
|
|
48732
|
-
now.getMonth() + 1,
|
|
48733
|
-
now.getDate(),
|
|
48734
|
-
0,
|
|
48735
|
-
0,
|
|
48736
|
-
0
|
|
48925
|
+
if (lc === "now") {
|
|
48926
|
+
return finish(
|
|
48927
|
+
utc ? datetimeFromUtcMs(Date.now()) : datetimeFromDate(/* @__PURE__ */ new Date())
|
|
48737
48928
|
);
|
|
48738
48929
|
}
|
|
48739
|
-
if (lc === "yesterday" || lc === "tomorrow") {
|
|
48740
|
-
const
|
|
48741
|
-
|
|
48742
|
-
|
|
48743
|
-
now.getDate() + (lc === "tomorrow" ? 1 : -1)
|
|
48744
|
-
);
|
|
48745
|
-
return makeDatetime(
|
|
48746
|
-
d.getFullYear(),
|
|
48747
|
-
d.getMonth() + 1,
|
|
48748
|
-
d.getDate(),
|
|
48749
|
-
0,
|
|
48750
|
-
0,
|
|
48751
|
-
0
|
|
48752
|
-
);
|
|
48930
|
+
if (lc === "today" || lc === "yesterday" || lc === "tomorrow") {
|
|
48931
|
+
const offset = lc === "tomorrow" ? 1 : lc === "yesterday" ? -1 : 0;
|
|
48932
|
+
const [Y, M, D] = todayParts(offset, utc);
|
|
48933
|
+
return finish(makeDatetime(Y, M, D, 0, 0, 0));
|
|
48753
48934
|
}
|
|
48754
48935
|
throw new RuntimeError(
|
|
48755
48936
|
`datetime: unrecognized relative-day string '${s}'`
|
|
48756
48937
|
);
|
|
48757
48938
|
}
|
|
48758
48939
|
}
|
|
48759
|
-
if (
|
|
48760
|
-
const flag = argToString(
|
|
48761
|
-
const kind = argToString(
|
|
48940
|
+
if (positional.length === 3) {
|
|
48941
|
+
const flag = argToString(positional[1]);
|
|
48942
|
+
const kind = argToString(positional[2]);
|
|
48762
48943
|
if (flag !== null && flag.toLowerCase() === "convertfrom") {
|
|
48763
48944
|
if (kind === null)
|
|
48764
48945
|
throw new RuntimeError("datetime: dateType must be text");
|
|
48765
|
-
const x = toNumber(
|
|
48946
|
+
const x = toNumber(positional[0]);
|
|
48766
48947
|
const k = kind.toLowerCase();
|
|
48767
|
-
if (k === "datenum") return datetimeFromDatenum(x);
|
|
48768
|
-
if (k === "posixtime") return datetimeFromUtcMs(x * 1e3);
|
|
48948
|
+
if (k === "datenum") return finish(datetimeFromDatenum(x));
|
|
48949
|
+
if (k === "posixtime") return finish(datetimeFromUtcMs(x * 1e3));
|
|
48769
48950
|
if (k === "excel") {
|
|
48770
|
-
return datetimeFromUtcMs((x - 25569) * 864e5);
|
|
48951
|
+
return finish(datetimeFromUtcMs((x - 25569) * 864e5));
|
|
48771
48952
|
}
|
|
48772
48953
|
if (k === "excel1904") {
|
|
48773
|
-
return datetimeFromUtcMs((x - 24107) * 864e5);
|
|
48954
|
+
return finish(datetimeFromUtcMs((x - 24107) * 864e5));
|
|
48774
48955
|
}
|
|
48775
48956
|
throw new RuntimeError(
|
|
48776
48957
|
`datetime: unsupported ConvertFrom type '${kind}'`
|
|
48777
48958
|
);
|
|
48778
48959
|
}
|
|
48779
48960
|
}
|
|
48780
|
-
if (
|
|
48781
|
-
const Y = toNumber(
|
|
48782
|
-
const M = toNumber(
|
|
48783
|
-
const D = toNumber(
|
|
48784
|
-
const H2 =
|
|
48785
|
-
const MI =
|
|
48786
|
-
const S =
|
|
48787
|
-
const MS =
|
|
48788
|
-
return makeDatetime(Y, M, D, H2, MI, S + MS / 1e3);
|
|
48961
|
+
if (positional.length === 3 || positional.length === 6 || positional.length === 7) {
|
|
48962
|
+
const Y = toNumber(positional[0]);
|
|
48963
|
+
const M = toNumber(positional[1]);
|
|
48964
|
+
const D = toNumber(positional[2]);
|
|
48965
|
+
const H2 = positional.length >= 6 ? toNumber(positional[3]) : 0;
|
|
48966
|
+
const MI = positional.length >= 6 ? toNumber(positional[4]) : 0;
|
|
48967
|
+
const S = positional.length >= 6 ? toNumber(positional[5]) : 0;
|
|
48968
|
+
const MS = positional.length >= 7 ? toNumber(positional[6]) : 0;
|
|
48969
|
+
return finish(makeDatetime(Y, M, D, H2, MI, S + MS / 1e3));
|
|
48789
48970
|
}
|
|
48790
48971
|
throw new RuntimeError(
|
|
48791
48972
|
`datetime: unsupported argument pattern (nargin=${args.length})`
|
|
@@ -56090,6 +56271,7 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
56090
56271
|
"copyfile",
|
|
56091
56272
|
"fileattrib",
|
|
56092
56273
|
"unzip",
|
|
56274
|
+
"zip",
|
|
56093
56275
|
"dir",
|
|
56094
56276
|
"warning",
|
|
56095
56277
|
"input",
|
|
@@ -57202,6 +57384,26 @@ function registerSpecialBuiltins(rt) {
|
|
|
57202
57384
|
}
|
|
57203
57385
|
return void 0;
|
|
57204
57386
|
});
|
|
57387
|
+
registerSpecial("zip", (nargout, args) => {
|
|
57388
|
+
const io = requireFileIO();
|
|
57389
|
+
if (!io.zip)
|
|
57390
|
+
throw new RuntimeError("zip is not available in this environment");
|
|
57391
|
+
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
57392
|
+
if (margs.length < 2)
|
|
57393
|
+
throw new RuntimeError("zip requires at least 2 arguments");
|
|
57394
|
+
let zipfilename = toString(margs[0]);
|
|
57395
|
+
const base = zipfilename.split(/[/\\]/).pop() ?? zipfilename;
|
|
57396
|
+
if (!base.includes(".")) zipfilename += ".zip";
|
|
57397
|
+
const fnames = margs[1];
|
|
57398
|
+
const filenames = isRuntimeCell(fnames) ? fnames.data.map((v) => toString(ensureRuntimeValue(v))) : [toString(fnames)];
|
|
57399
|
+
const rootdir = margs.length >= 3 ? toString(margs[2]) : ".";
|
|
57400
|
+
const entryNames = io.zip(zipfilename, filenames, rootdir);
|
|
57401
|
+
if (nargout >= 1) {
|
|
57402
|
+
const cellData = entryNames.map((f) => RTV.char(f));
|
|
57403
|
+
return RTV.cell(cellData, [1, cellData.length]);
|
|
57404
|
+
}
|
|
57405
|
+
return void 0;
|
|
57406
|
+
});
|
|
57205
57407
|
registerSpecial("dir", (nargout, args) => {
|
|
57206
57408
|
const io = requireFileIO();
|
|
57207
57409
|
if (!io.listDir)
|
|
@@ -61069,8 +61271,8 @@ function padExtent(e, tight) {
|
|
|
61069
61271
|
return [min2, max2];
|
|
61070
61272
|
}
|
|
61071
61273
|
if (tight) return [min2, max2];
|
|
61072
|
-
const
|
|
61073
|
-
return [min2 -
|
|
61274
|
+
const pad2 = (max2 - min2) * 0.05;
|
|
61275
|
+
return [min2 - pad2, max2 + pad2];
|
|
61074
61276
|
}
|
|
61075
61277
|
function applyExplicit(auto, explicit) {
|
|
61076
61278
|
if (!explicit) return auto;
|
|
@@ -65895,6 +66097,12 @@ function evalMember(expr, nargout) {
|
|
|
65895
66097
|
}
|
|
65896
66098
|
}
|
|
65897
66099
|
const base = this.evalExpr(expr.base);
|
|
66100
|
+
const baseRv = ensureRuntimeValue(base);
|
|
66101
|
+
if (isRuntimeStructArray(baseRv) && baseRv.elements.length !== 1) {
|
|
66102
|
+
return baseRv.elements.map(
|
|
66103
|
+
(el) => ensureRuntimeValue(this.rt.getMember(el, expr.name))
|
|
66104
|
+
);
|
|
66105
|
+
}
|
|
65898
66106
|
return this.rt.getMember(base, expr.name);
|
|
65899
66107
|
}
|
|
65900
66108
|
function tryExtractDottedName(expr) {
|
|
@@ -66106,12 +66314,31 @@ function evalCellLiteral(expr) {
|
|
|
66106
66314
|
}
|
|
66107
66315
|
return RTV.cell(elements2, [1, elements2.length]);
|
|
66108
66316
|
}
|
|
66109
|
-
const
|
|
66110
|
-
|
|
66317
|
+
const rowValues = expr.rows.map((row) => {
|
|
66318
|
+
const vals = [];
|
|
66319
|
+
for (const e of row) {
|
|
66320
|
+
const v = this.evalExpr(e);
|
|
66321
|
+
if (Array.isArray(v)) {
|
|
66322
|
+
for (const elem of v) vals.push(ensureRuntimeValue(elem));
|
|
66323
|
+
} else {
|
|
66324
|
+
vals.push(ensureRuntimeValue(v));
|
|
66325
|
+
}
|
|
66326
|
+
}
|
|
66327
|
+
return vals;
|
|
66328
|
+
});
|
|
66329
|
+
const numRows = rowValues.length;
|
|
66330
|
+
const numCols = rowValues[0].length;
|
|
66331
|
+
for (const rv of rowValues) {
|
|
66332
|
+
if (rv.length !== numCols) {
|
|
66333
|
+
throw new RuntimeError(
|
|
66334
|
+
"Cell array rows must have the same number of columns"
|
|
66335
|
+
);
|
|
66336
|
+
}
|
|
66337
|
+
}
|
|
66111
66338
|
const elements = [];
|
|
66112
66339
|
for (let c = 0; c < numCols; c++) {
|
|
66113
66340
|
for (let r = 0; r < numRows; r++) {
|
|
66114
|
-
elements.push(
|
|
66341
|
+
elements.push(rowValues[r][c]);
|
|
66115
66342
|
}
|
|
66116
66343
|
}
|
|
66117
66344
|
return RTV.cell(elements, [numRows, numCols]);
|
|
@@ -70586,8 +70813,8 @@ function mtoc2_sprintf_format(fmt, args) {
|
|
|
70586
70813
|
if (width > 0) {
|
|
70587
70814
|
const padChar = zeroPad ? "0" : " ";
|
|
70588
70815
|
const padLen = Math.max(0, width - sign.length - s.length);
|
|
70589
|
-
const
|
|
70590
|
-
result += leftAlign ? sign + s + " ".repeat(padLen) : zeroPad ? sign +
|
|
70816
|
+
const pad2 = padChar.repeat(padLen);
|
|
70817
|
+
result += leftAlign ? sign + s + " ".repeat(padLen) : zeroPad ? sign + pad2 + s : pad2 + sign + s;
|
|
70591
70818
|
} else {
|
|
70592
70819
|
result += sign + s;
|
|
70593
70820
|
}
|
|
@@ -70689,6 +70916,24 @@ function mtoc2_sprintf_format(fmt, args) {
|
|
|
70689
70916
|
case "t":
|
|
70690
70917
|
result += " ";
|
|
70691
70918
|
break;
|
|
70919
|
+
case "r":
|
|
70920
|
+
result += "\r";
|
|
70921
|
+
break;
|
|
70922
|
+
case "a":
|
|
70923
|
+
result += "\x07";
|
|
70924
|
+
break;
|
|
70925
|
+
case "b":
|
|
70926
|
+
result += "\b";
|
|
70927
|
+
break;
|
|
70928
|
+
case "f":
|
|
70929
|
+
result += "\f";
|
|
70930
|
+
break;
|
|
70931
|
+
case "v":
|
|
70932
|
+
result += "\v";
|
|
70933
|
+
break;
|
|
70934
|
+
case "0":
|
|
70935
|
+
result += "\0";
|
|
70936
|
+
break;
|
|
70692
70937
|
case "\\":
|
|
70693
70938
|
result += "\\";
|
|
70694
70939
|
break;
|
|
@@ -70872,8 +71117,8 @@ function disp_complex_slice(re, im, offset, rows, cols) {
|
|
|
70872
71117
|
for (let c = 0; c < cols; c++) {
|
|
70873
71118
|
const idx = r + c * rows;
|
|
70874
71119
|
const cell = cells[idx];
|
|
70875
|
-
const
|
|
70876
|
-
for (let i = 0; i <
|
|
71120
|
+
const pad2 = colWidths[c] - cell.length;
|
|
71121
|
+
for (let i = 0; i < pad2; i++) line += " ";
|
|
70877
71122
|
line += cell;
|
|
70878
71123
|
if (c < cols - 1) line += " ";
|
|
70879
71124
|
}
|
|
@@ -72285,6 +72530,14 @@ function mtoc2_tensor_mtimes_real(a, b) {
|
|
|
72285
72530
|
`mtoc2_tensor_mtimes_real: inner dimensions disagree (${k} vs ${k2})`
|
|
72286
72531
|
);
|
|
72287
72532
|
}
|
|
72533
|
+
if (typeof $matmulAccel === "function") {
|
|
72534
|
+
const accel = $matmulAccel(a.data, m, k, b.data, n);
|
|
72535
|
+
if (accel) {
|
|
72536
|
+
const acc = mtoc2_tensor_alloc(m, n);
|
|
72537
|
+
acc.data.set(accel);
|
|
72538
|
+
return acc;
|
|
72539
|
+
}
|
|
72540
|
+
}
|
|
72288
72541
|
const r = mtoc2_tensor_alloc(m, n);
|
|
72289
72542
|
for (let j = 0; j < n; j++) {
|
|
72290
72543
|
for (let i = 0; i < m; i++) {
|
|
@@ -73458,7 +73711,7 @@ var JS_SNIPPETS = {
|
|
|
73458
73711
|
"error_fmt.js": "// JS sibling of `error_fmt.h`. Format the message + arguments and\n// throw a runtime error. Mirrors numbl's `error(...)` behavior\n// (stderr + halt).\n//\n// The thrown error carries an `identifier` string property so a\n// `try / catch ME` arm in the interpreter can populate the `ME`\n// struct's `identifier` field. When the caller passes no identifier\n// (the common `error('msg')` form), it's the empty string.\n\n\nfunction mtoc2_error_fmt(fmt, ...args) {\n const msg = mtoc2_sprintf_format(fmt, args);\n // Numbl writes to stderr; in the JS host we route through the same\n // `$write` channel by emitting a \"stderr\" sentinel prefix the host\n // can split on. For now, throw \u2014 the CLI's runner formats the\n // exception to stderr, matching the user-visible result.\n const err = new Error(msg);\n err.identifier = \"\";\n throw err;\n}\n\nfunction mtoc2_error_fmt_id(identifier, fmt, ...args) {\n const msg = mtoc2_sprintf_format(fmt, args);\n const err = new Error(msg);\n err.identifier = identifier;\n throw err;\n}\n",
|
|
73459
73712
|
"format_complex.js": '// JS sibling of `format_complex.h`. Format a scalar complex `{re, im}`\n// the way numbl\'s `formatComplex` does. Each component is rendered\n// through `mtoc2_format_double` so the scalar formatting stays in\n// lockstep with numbl\'s `formatNumber`.\n\n\nfunction mtoc2_format_complex(z) {\n const re = z.re;\n const im = z.im;\n if (im === 0) return mtoc2_format_double(re);\n if (re === 0) return mtoc2_format_double(im) + "i";\n if (im < 0) {\n return mtoc2_format_double(re) + " - " + mtoc2_format_double(-im) + "i";\n }\n return mtoc2_format_double(re) + " + " + mtoc2_format_double(im) + "i";\n}\n',
|
|
73460
73713
|
"format_double.js": '// JS sibling of `format_double.h` \u2014 same numbl-compatible formatter,\n// in JS. Used by `emitJs` for the `disp` scalar path and (later) by\n// the interpreter via the re-export in `snippets.gen.ts`.\n\nfunction mtoc2_format_double(x) {\n if (Number.isNaN(x)) return "NaN";\n // MATLAB spells these Inf / -Inf (matches the interpreter\'s formatNumber).\n if (x === Infinity) return "Inf";\n if (x === -Infinity) return "-Inf";\n if (x === 0) x = 0;\n if (Math.abs(x) < 1e15 && x === Math.trunc(x)) return String(x);\n\n const buf = x.toExponential(4);\n const ePos = buf.indexOf("e");\n if (ePos < 0) return buf;\n const decExp = parseInt(buf.slice(ePos + 1), 10);\n\n if (decExp < -6 || decExp >= 5) {\n let mantissaEnd = ePos - 1;\n while (mantissaEnd > 0 && buf[mantissaEnd] === "0") mantissaEnd--;\n if (mantissaEnd >= 0 && buf[mantissaEnd] === ".") mantissaEnd--;\n let expPart = buf.slice(ePos + 1);\n let sign = "+";\n if (expPart[0] === "+" || expPart[0] === "-") {\n sign = expPart[0];\n expPart = expPart.slice(1);\n }\n while (expPart.length > 1 && expPart[0] === "0") expPart = expPart.slice(1);\n return buf.slice(0, mantissaEnd + 1) + "e" + sign + expPart;\n }\n\n let fracDigits = 4 - decExp;\n if (fracDigits < 0) fracDigits = 0;\n let s = x.toFixed(fracDigits);\n if (s.includes(".")) {\n while (s.endsWith("0")) s = s.slice(0, -1);\n if (s.endsWith(".")) s = s.slice(0, -1);\n }\n return s;\n}\n',
|
|
73461
|
-
"format_engine.js": '// JS sibling of `format_engine.h`. Numbl-compatible printf-style\n// formatter, ported from `numbl/src/numbl-core/helpers/string.ts`\'s\n// `sprintfFormat`. Shared by fprintf / sprintf / error / assert on\n// the JS side.\n//\n// Spec set: d i u f e E g G x X o s c %\n// Flags: - + 0 # space. Precision `.N`. Width digits. `*` consumes the\n// next numeric arg as a width.\n// Escapes interpreted AT FORMAT TIME: \\n \\t \\\\.\n// Numeric tensors flatten column-major into the scalar stream; the\n// format string cycles through args until consumed (with a "no arg\n// consumed this pass" guard against infinite output).\n\nfunction isTensor(v) {\n return typeof v === "object" && v !== null && v.mtoc2Tag === "tensor";\n}\nfunction isChar(v) {\n return typeof v === "object" && v !== null && v.mtoc2Tag === "char";\n}\n\nfunction toNumber(v) {\n if (typeof v === "number") return v;\n if (typeof v === "boolean") return v ? 1 : 0;\n if (typeof v === "string") return Number(v);\n if (isChar(v)) {\n // Match the interpreter\'s toNumber (runtime/convert.ts): a single\n // char yields its code point; a multi-char value has no scalar\n // numeric form. `Number("A")` would wrongly give NaN.\n if (v.value.length === 1) return v.value.charCodeAt(0);\n throw new Error("Cannot convert multi-char to number");\n }\n if (isTensor(v) && v.data.length === 1) return v.data[0];\n return Number(v);\n}\n\nfunction toString(v) {\n if (typeof v === "string") return v;\n if (typeof v === "number") return String(v);\n if (typeof v === "boolean") return v ? "1" : "0";\n if (isChar(v)) return v.value;\n return String(v);\n}\n\nfunction numStr(n) {\n if (n === Infinity) return "Inf";\n if (n === -Infinity) return "-Inf";\n if (Number.isNaN(n)) return "NaN";\n if (n === 0) return "0";\n const prec = 5;\n const exp = Math.floor(Math.log10(Math.abs(n)));\n let s;\n if (exp < -4 || exp >= prec) {\n s = n.toExponential(prec - 1);\n const ePos = s.indexOf("e");\n let mantissa = s.slice(0, ePos);\n const expPart0 = s.slice(ePos);\n if (mantissa.includes(".")) mantissa = mantissa.replace(/\\.?0+$/, "");\n const expPart = expPart0.replace(/([eE][+-])(\\d)$/, "$1" + "0$2");\n s = mantissa + expPart;\n } else {\n if (Number.isInteger(n)) return String(n);\n s = n.toPrecision(prec);\n if (s.includes(".")) s = s.replace(/\\.?0+$/, "");\n }\n return s;\n}\n\nfunction applyWidth(spec, str) {\n const m = spec.match(/^%([-+ #]*)0?(\\d+)?/);\n if (!m) return str;\n const explicitFlags = m[1] || "";\n const leftAlign = explicitFlags.includes("-");\n const afterPercent = spec.slice(1);\n const flagAndWidth = afterPercent.match(/^([-+ #]*)(0?)(\\d+)?/);\n const zeroFlag = flagAndWidth ? flagAndWidth[2] === "0" : false;\n const width = flagAndWidth && flagAndWidth[3] ? parseInt(flagAndWidth[3]) : 0;\n if (width <= str.length) return str;\n const zeroPad = !leftAlign && zeroFlag;\n const padLen = width - str.length;\n if (leftAlign) return str + " ".repeat(padLen);\n if (zeroPad) {\n if (str[0] === "-" || str[0] === "+") {\n return str[0] + "0".repeat(padLen) + str.slice(1);\n }\n return "0".repeat(padLen) + str;\n }\n return " ".repeat(padLen) + str;\n}\n\nfunction mtoc2_sprintf_format(fmt, args) {\n // Char literals (`\'foo\'`) come through wrapped as\n // `{mtoc2Tag:"char", value:"..."}` to match the interpreter\'s\n // RuntimeValue convention; unwrap so the format walker indexes\n // a plain JS string.\n if (isChar(fmt)) fmt = fmt.value;\n // Flatten args column-major (tensors expand element-by-element).\n const flat = [];\n for (const arg of args) {\n if (isTensor(arg)) {\n for (let k = 0; k < arg.data.length; k++) flat.push(arg.data[k]);\n } else {\n flat.push(arg);\n }\n }\n\n let result = "";\n let argIdx = 0;\n\n do {\n const startArgIdx = argIdx;\n let outOfArgs = false;\n let i = 0;\n while (i < fmt.length && !outOfArgs) {\n if (fmt[i] === "%" && i + 1 < fmt.length) {\n i++;\n let spec = "%";\n while (i < fmt.length && !"dfigeEsoxXuc%".includes(fmt[i])) {\n if (fmt[i] === "*") {\n if (argIdx >= flat.length) {\n outOfArgs = true;\n break;\n }\n spec += String(Math.round(toNumber(flat[argIdx++])));\n i++;\n } else {\n spec += fmt[i];\n i++;\n }\n }\n if (outOfArgs) break;\n if (i < fmt.length) {\n const ch = fmt[i];\n i++;\n if (ch === "%") {\n result += "%";\n } else if (argIdx >= flat.length) {\n outOfArgs = true;\n } else if (ch === "d" || ch === "i" || ch === "u") {\n const raw = toNumber(flat[argIdx++]);\n const isInt = Number.isInteger(raw);\n const canPrintAsInt = ch === "u" ? isInt && raw >= 0 : isInt;\n if (!canPrintAsInt) {\n let eStr = raw.toExponential(6);\n eStr = eStr.replace(/e([+-])(\\d)$/, "e$1" + "0$2");\n result += applyWidth(spec, eStr);\n } else {\n const n = raw;\n const flags = spec.slice(1);\n const hasPlus = flags.includes("+");\n const leftAlign = flags.includes("-");\n const widthMatch = spec.match(/^%[^0-9]*(\\d+)/);\n const width = widthMatch ? parseInt(widthMatch[1]) : 0;\n const zeroPad = !leftAlign && /^[-+ ]*0/.test(spec.slice(1));\n const s = String(Math.abs(n));\n const sign = n < 0 ? "-" : hasPlus ? "+" : "";\n if (width > 0) {\n const padChar = zeroPad ? "0" : " ";\n const padLen = Math.max(0, width - sign.length - s.length);\n const pad = padChar.repeat(padLen);\n result += leftAlign\n ? sign + s + " ".repeat(padLen)\n : zeroPad\n ? sign + pad + s\n : pad + sign + s;\n } else {\n result += sign + s;\n }\n }\n } else if (ch === "f") {\n const n = toNumber(flat[argIdx++]);\n if (!isFinite(n) || isNaN(n)) {\n result += applyWidth(spec, numStr(n));\n } else {\n const fFlags = spec.slice(1);\n const fHasPlus = fFlags.includes("+");\n const precMatch = spec.match(/\\.(\\d+)/);\n const prec = precMatch ? parseInt(precMatch[1]) : 6;\n const formatted = n.toFixed(prec);\n const fSign = n < 0 ? "" : fHasPlus ? "+" : "";\n result += applyWidth(spec, fSign + formatted);\n }\n } else if (ch === "e" || ch === "E") {\n const n = toNumber(flat[argIdx++]);\n if (!isFinite(n) || isNaN(n)) {\n result += applyWidth(spec, numStr(n));\n } else {\n const precMatch = spec.match(/\\.(\\d+)/);\n const prec = precMatch ? parseInt(precMatch[1]) : 6;\n let eStr = n.toExponential(prec);\n eStr = eStr.replace(/e([+-])(\\d)$/, "e$1" + "0$2");\n if (ch === "E") eStr = eStr.toUpperCase();\n result += applyWidth(spec, eStr);\n }\n } else if (ch === "x" || ch === "X") {\n const n = Math.round(toNumber(flat[argIdx++]));\n let s = Math.abs(n).toString(16);\n if (ch === "X") s = s.toUpperCase();\n result += applyWidth(spec, s);\n } else if (ch === "o") {\n const n = Math.round(toNumber(flat[argIdx++]));\n result += applyWidth(spec, Math.abs(n).toString(8));\n } else if (ch === "g" || ch === "G") {\n const gVal = toNumber(flat[argIdx++]);\n if (!isFinite(gVal) || isNaN(gVal)) {\n result += applyWidth(spec, numStr(gVal));\n } else {\n const precMatch = spec.match(/\\.(\\d+)/);\n const gPrec = precMatch ? parseInt(precMatch[1]) : 6;\n let gStr;\n if (gVal === 0) {\n gStr = "0";\n } else {\n const exp = Math.floor(Math.log10(Math.abs(gVal)));\n if (exp < -4 || exp >= gPrec) {\n gStr = gVal.toExponential(gPrec - 1);\n const ePos = gStr.indexOf("e");\n let mantissa = gStr.slice(0, ePos);\n let expPart = gStr.slice(ePos);\n if (mantissa.includes(".")) {\n mantissa = mantissa.replace(/\\.?0+$/, "");\n }\n expPart = expPart.replace(/e([+-])(\\d)$/, "e$1" + "0$2");\n gStr = mantissa + expPart;\n } else {\n gStr = gVal.toPrecision(gPrec);\n if (gStr.includes(".")) {\n gStr = gStr.replace(/\\.?0+$/, "");\n }\n if (gStr.includes("e")) {\n gStr = String(parseFloat(gStr));\n }\n }\n }\n if (ch === "G") gStr = gStr.toUpperCase();\n result += applyWidth(spec, gStr);\n }\n } else if (ch === "s") {\n const sArg = flat[argIdx++];\n // A numeric/logical argument to %s is a character code (MATLAB:\n // sprintf(\'%s\', 65) -> \'A\').\n const sVal =\n typeof sArg === "number" || typeof sArg === "boolean"\n ? String.fromCharCode(Math.round(toNumber(sArg)))\n : toString(sArg);\n const sFlags = spec.slice(1);\n const sLeftAlign = sFlags.includes("-");\n const sWidthMatch = spec.match(/^%[^0-9]*(\\d+)/);\n const sWidth = sWidthMatch ? parseInt(sWidthMatch[1]) : 0;\n if (sWidth > sVal.length) {\n const sPad = " ".repeat(sWidth - sVal.length);\n result += sLeftAlign ? sVal + sPad : sPad + sVal;\n } else {\n result += sVal;\n }\n } else if (ch === "c") {\n result += String.fromCharCode(Math.round(toNumber(flat[argIdx++])));\n } else {\n result += spec + ch;\n argIdx++;\n }\n }\n } else if (fmt[i] === "\\\\" && i + 1 < fmt.length) {\n i++;\n switch (fmt[i]) {\n case "n":\n result += "\\n";\n break;\n case "t":\n result += "\\t";\n break;\n case "\\\\":\n result += "\\\\";\n break;\n default:\n result += "\\\\" + fmt[i];\n }\n i++;\n } else {\n result += fmt[i];\n i++;\n }\n }\n if (argIdx === startArgIdx) break;\n } while (argIdx < flat.length);\n\n return result;\n}\n',
|
|
73714
|
+
"format_engine.js": '// JS sibling of `format_engine.h`. Numbl-compatible printf-style\n// formatter, ported from `numbl/src/numbl-core/helpers/string.ts`\'s\n// `sprintfFormat`. Shared by fprintf / sprintf / error / assert on\n// the JS side.\n//\n// Spec set: d i u f e E g G x X o s c %\n// Flags: - + 0 # space. Precision `.N`. Width digits. `*` consumes the\n// next numeric arg as a width.\n// Escapes interpreted AT FORMAT TIME: \\n \\t \\r \\a \\b \\f \\v \\0 \\\\.\n// Numeric tensors flatten column-major into the scalar stream; the\n// format string cycles through args until consumed (with a "no arg\n// consumed this pass" guard against infinite output).\n\nfunction isTensor(v) {\n return typeof v === "object" && v !== null && v.mtoc2Tag === "tensor";\n}\nfunction isChar(v) {\n return typeof v === "object" && v !== null && v.mtoc2Tag === "char";\n}\n\nfunction toNumber(v) {\n if (typeof v === "number") return v;\n if (typeof v === "boolean") return v ? 1 : 0;\n if (typeof v === "string") return Number(v);\n if (isChar(v)) {\n // Match the interpreter\'s toNumber (runtime/convert.ts): a single\n // char yields its code point; a multi-char value has no scalar\n // numeric form. `Number("A")` would wrongly give NaN.\n if (v.value.length === 1) return v.value.charCodeAt(0);\n throw new Error("Cannot convert multi-char to number");\n }\n if (isTensor(v) && v.data.length === 1) return v.data[0];\n return Number(v);\n}\n\nfunction toString(v) {\n if (typeof v === "string") return v;\n if (typeof v === "number") return String(v);\n if (typeof v === "boolean") return v ? "1" : "0";\n if (isChar(v)) return v.value;\n return String(v);\n}\n\nfunction numStr(n) {\n if (n === Infinity) return "Inf";\n if (n === -Infinity) return "-Inf";\n if (Number.isNaN(n)) return "NaN";\n if (n === 0) return "0";\n const prec = 5;\n const exp = Math.floor(Math.log10(Math.abs(n)));\n let s;\n if (exp < -4 || exp >= prec) {\n s = n.toExponential(prec - 1);\n const ePos = s.indexOf("e");\n let mantissa = s.slice(0, ePos);\n const expPart0 = s.slice(ePos);\n if (mantissa.includes(".")) mantissa = mantissa.replace(/\\.?0+$/, "");\n const expPart = expPart0.replace(/([eE][+-])(\\d)$/, "$1" + "0$2");\n s = mantissa + expPart;\n } else {\n if (Number.isInteger(n)) return String(n);\n s = n.toPrecision(prec);\n if (s.includes(".")) s = s.replace(/\\.?0+$/, "");\n }\n return s;\n}\n\nfunction applyWidth(spec, str) {\n const m = spec.match(/^%([-+ #]*)0?(\\d+)?/);\n if (!m) return str;\n const explicitFlags = m[1] || "";\n const leftAlign = explicitFlags.includes("-");\n const afterPercent = spec.slice(1);\n const flagAndWidth = afterPercent.match(/^([-+ #]*)(0?)(\\d+)?/);\n const zeroFlag = flagAndWidth ? flagAndWidth[2] === "0" : false;\n const width = flagAndWidth && flagAndWidth[3] ? parseInt(flagAndWidth[3]) : 0;\n if (width <= str.length) return str;\n const zeroPad = !leftAlign && zeroFlag;\n const padLen = width - str.length;\n if (leftAlign) return str + " ".repeat(padLen);\n if (zeroPad) {\n if (str[0] === "-" || str[0] === "+") {\n return str[0] + "0".repeat(padLen) + str.slice(1);\n }\n return "0".repeat(padLen) + str;\n }\n return " ".repeat(padLen) + str;\n}\n\nfunction mtoc2_sprintf_format(fmt, args) {\n // Char literals (`\'foo\'`) come through wrapped as\n // `{mtoc2Tag:"char", value:"..."}` to match the interpreter\'s\n // RuntimeValue convention; unwrap so the format walker indexes\n // a plain JS string.\n if (isChar(fmt)) fmt = fmt.value;\n // Flatten args column-major (tensors expand element-by-element).\n const flat = [];\n for (const arg of args) {\n if (isTensor(arg)) {\n for (let k = 0; k < arg.data.length; k++) flat.push(arg.data[k]);\n } else {\n flat.push(arg);\n }\n }\n\n let result = "";\n let argIdx = 0;\n\n do {\n const startArgIdx = argIdx;\n let outOfArgs = false;\n let i = 0;\n while (i < fmt.length && !outOfArgs) {\n if (fmt[i] === "%" && i + 1 < fmt.length) {\n i++;\n let spec = "%";\n while (i < fmt.length && !"dfigeEsoxXuc%".includes(fmt[i])) {\n if (fmt[i] === "*") {\n if (argIdx >= flat.length) {\n outOfArgs = true;\n break;\n }\n spec += String(Math.round(toNumber(flat[argIdx++])));\n i++;\n } else {\n spec += fmt[i];\n i++;\n }\n }\n if (outOfArgs) break;\n if (i < fmt.length) {\n const ch = fmt[i];\n i++;\n if (ch === "%") {\n result += "%";\n } else if (argIdx >= flat.length) {\n outOfArgs = true;\n } else if (ch === "d" || ch === "i" || ch === "u") {\n const raw = toNumber(flat[argIdx++]);\n const isInt = Number.isInteger(raw);\n const canPrintAsInt = ch === "u" ? isInt && raw >= 0 : isInt;\n if (!canPrintAsInt) {\n let eStr = raw.toExponential(6);\n eStr = eStr.replace(/e([+-])(\\d)$/, "e$1" + "0$2");\n result += applyWidth(spec, eStr);\n } else {\n const n = raw;\n const flags = spec.slice(1);\n const hasPlus = flags.includes("+");\n const leftAlign = flags.includes("-");\n const widthMatch = spec.match(/^%[^0-9]*(\\d+)/);\n const width = widthMatch ? parseInt(widthMatch[1]) : 0;\n const zeroPad = !leftAlign && /^[-+ ]*0/.test(spec.slice(1));\n const s = String(Math.abs(n));\n const sign = n < 0 ? "-" : hasPlus ? "+" : "";\n if (width > 0) {\n const padChar = zeroPad ? "0" : " ";\n const padLen = Math.max(0, width - sign.length - s.length);\n const pad = padChar.repeat(padLen);\n result += leftAlign\n ? sign + s + " ".repeat(padLen)\n : zeroPad\n ? sign + pad + s\n : pad + sign + s;\n } else {\n result += sign + s;\n }\n }\n } else if (ch === "f") {\n const n = toNumber(flat[argIdx++]);\n if (!isFinite(n) || isNaN(n)) {\n result += applyWidth(spec, numStr(n));\n } else {\n const fFlags = spec.slice(1);\n const fHasPlus = fFlags.includes("+");\n const precMatch = spec.match(/\\.(\\d+)/);\n const prec = precMatch ? parseInt(precMatch[1]) : 6;\n const formatted = n.toFixed(prec);\n const fSign = n < 0 ? "" : fHasPlus ? "+" : "";\n result += applyWidth(spec, fSign + formatted);\n }\n } else if (ch === "e" || ch === "E") {\n const n = toNumber(flat[argIdx++]);\n if (!isFinite(n) || isNaN(n)) {\n result += applyWidth(spec, numStr(n));\n } else {\n const precMatch = spec.match(/\\.(\\d+)/);\n const prec = precMatch ? parseInt(precMatch[1]) : 6;\n let eStr = n.toExponential(prec);\n eStr = eStr.replace(/e([+-])(\\d)$/, "e$1" + "0$2");\n if (ch === "E") eStr = eStr.toUpperCase();\n result += applyWidth(spec, eStr);\n }\n } else if (ch === "x" || ch === "X") {\n const n = Math.round(toNumber(flat[argIdx++]));\n let s = Math.abs(n).toString(16);\n if (ch === "X") s = s.toUpperCase();\n result += applyWidth(spec, s);\n } else if (ch === "o") {\n const n = Math.round(toNumber(flat[argIdx++]));\n result += applyWidth(spec, Math.abs(n).toString(8));\n } else if (ch === "g" || ch === "G") {\n const gVal = toNumber(flat[argIdx++]);\n if (!isFinite(gVal) || isNaN(gVal)) {\n result += applyWidth(spec, numStr(gVal));\n } else {\n const precMatch = spec.match(/\\.(\\d+)/);\n const gPrec = precMatch ? parseInt(precMatch[1]) : 6;\n let gStr;\n if (gVal === 0) {\n gStr = "0";\n } else {\n const exp = Math.floor(Math.log10(Math.abs(gVal)));\n if (exp < -4 || exp >= gPrec) {\n gStr = gVal.toExponential(gPrec - 1);\n const ePos = gStr.indexOf("e");\n let mantissa = gStr.slice(0, ePos);\n let expPart = gStr.slice(ePos);\n if (mantissa.includes(".")) {\n mantissa = mantissa.replace(/\\.?0+$/, "");\n }\n expPart = expPart.replace(/e([+-])(\\d)$/, "e$1" + "0$2");\n gStr = mantissa + expPart;\n } else {\n gStr = gVal.toPrecision(gPrec);\n if (gStr.includes(".")) {\n gStr = gStr.replace(/\\.?0+$/, "");\n }\n if (gStr.includes("e")) {\n gStr = String(parseFloat(gStr));\n }\n }\n }\n if (ch === "G") gStr = gStr.toUpperCase();\n result += applyWidth(spec, gStr);\n }\n } else if (ch === "s") {\n const sArg = flat[argIdx++];\n // A numeric/logical argument to %s is a character code (MATLAB:\n // sprintf(\'%s\', 65) -> \'A\').\n const sVal =\n typeof sArg === "number" || typeof sArg === "boolean"\n ? String.fromCharCode(Math.round(toNumber(sArg)))\n : toString(sArg);\n const sFlags = spec.slice(1);\n const sLeftAlign = sFlags.includes("-");\n const sWidthMatch = spec.match(/^%[^0-9]*(\\d+)/);\n const sWidth = sWidthMatch ? parseInt(sWidthMatch[1]) : 0;\n if (sWidth > sVal.length) {\n const sPad = " ".repeat(sWidth - sVal.length);\n result += sLeftAlign ? sVal + sPad : sPad + sVal;\n } else {\n result += sVal;\n }\n } else if (ch === "c") {\n result += String.fromCharCode(Math.round(toNumber(flat[argIdx++])));\n } else {\n result += spec + ch;\n argIdx++;\n }\n }\n } else if (fmt[i] === "\\\\" && i + 1 < fmt.length) {\n i++;\n switch (fmt[i]) {\n case "n":\n result += "\\n";\n break;\n case "t":\n result += "\\t";\n break;\n case "r":\n result += "\\r";\n break;\n case "a":\n result += "\\x07";\n break;\n case "b":\n result += "\\b";\n break;\n case "f":\n result += "\\f";\n break;\n case "v":\n result += "\\v";\n break;\n case "0":\n result += "\\0";\n break;\n case "\\\\":\n result += "\\\\";\n break;\n default:\n result += "\\\\" + fmt[i];\n }\n i++;\n } else {\n result += fmt[i];\n i++;\n }\n }\n if (argIdx === startArgIdx) break;\n } while (argIdx < flat.length);\n\n return result;\n}\n',
|
|
73462
73715
|
"fprintf.js": "// JS sibling of `fprintf.h`. Routes formatted output through\n// `mtoc2_sprintf_format` then writes via `$write` (the JS analog of\n// C's stdout). Numbl-compatible spec set & semantics.\n\n\nfunction mtoc2_fprintf(fmt, ...args) {\n $write(mtoc2_sprintf_format(fmt, args));\n}\n",
|
|
73463
73716
|
"sprintf.js": '// JS sibling of `sprintf.h`. Two output variants:\n// - `mtoc2_sprintf_str(fmt, args)` returns the formatted text as a\n// plain JS string (the equivalent of numbl\'s `String` kind).\n// - `mtoc2_sprintf_char(fmt, args)` returns it as a `mtoc2_char_tensor_t`\n// placeholder \u2014 we keep the JS shape as a `{mtoc2Tag: "char", value}`\n// object so disp/length etc. dispatch correctly.\n\n\nfunction mtoc2_sprintf_str(fmt, ...args) {\n return mtoc2_sprintf_format(fmt, args);\n}\n\nfunction mtoc2_sprintf_char(fmt, ...args) {\n return { mtoc2Tag: "char", value: mtoc2_sprintf_format(fmt, args) };\n}\n',
|
|
73464
73717
|
"warning_fmt.js": '// JS sibling of `warning_fmt.h`. Format the message and write\n// `Warning: <msg>\\n` via `$write`. Matches numbl\n// (`runtime/specialBuiltins.ts:190` \u2014 `rt.output("Warning: " + msg + "\\n")`).\n\n\nfunction mtoc2_warning_fmt(fmt, ...args) {\n $write("Warning: " + mtoc2_sprintf_format(fmt, args) + "\\n");\n}\n\nfunction mtoc2_warning_fmt_id(_id, fmt, ...args) {\n // The id is informational \u2014 numbl threads it to lastwarn state,\n // which mtoc2 doesn\'t expose. Drop it here so the visible output\n // matches the bare form.\n $write("Warning: " + mtoc2_sprintf_format(fmt, args) + "\\n");\n}\n',
|
|
@@ -73496,7 +73749,7 @@ var JS_SNIPPETS = {
|
|
|
73496
73749
|
"tensor_logspace.js": "// JS sibling of `tensor_logspace.h`. Build a 1\xD7n row tensor of n\n// logarithmically-spaced values from 10^a to 10^b. Byte-for-byte with\n// numbl's interpreter `logspace`, including the MATLAB special case\n// where an upper limit of exactly `pi` makes the last point `pi`.\n\n\nfunction mtoc2_tensor_logspace(a, b, n) {\n if (n <= 0) return mtoc2_tensor_alloc(1, 0);\n const isPi = b === Math.PI;\n const endVal = isPi ? Math.PI : Math.pow(10, b);\n const out = mtoc2_tensor_alloc(1, n);\n if (n === 1) {\n out.data[0] = endVal;\n return out;\n }\n if (isPi) {\n const logStart = Math.log10(Math.pow(10, a));\n const logEnd = Math.log10(Math.PI);\n for (let i = 0; i < n; i++) {\n const t = logStart + ((logEnd - logStart) * i) / (n - 1);\n out.data[i] = Math.pow(10, t);\n }\n } else {\n for (let i = 0; i < n; i++) {\n const t = a + ((b - a) * i) / (n - 1);\n out.data[i] = Math.pow(10, t);\n }\n }\n return out;\n}\n",
|
|
73497
73750
|
"tensor_meshgrid.js": "// JS sibling of `tensor_meshgrid.h`. MATLAB-style coordinate grid.\n\n\nfunction numel(t) {\n let n = 1;\n for (const s of t.shape) n *= s;\n return n;\n}\n\nfunction mtoc2_meshgrid_x(x, y) {\n const M = numel(x);\n const N = numel(y);\n const X = mtoc2_tensor_alloc(N, M);\n for (let j = 0; j < M; j++) {\n const xj = x.data[j];\n for (let i = 0; i < N; i++) X.data[i + j * N] = xj;\n }\n return X;\n}\n\nfunction mtoc2_meshgrid(x, y) {\n const M = numel(x);\n const N = numel(y);\n const X = mtoc2_tensor_alloc(N, M);\n const Y = mtoc2_tensor_alloc(N, M);\n for (let j = 0; j < M; j++) {\n const xj = x.data[j];\n for (let i = 0; i < N; i++) {\n X.data[i + j * N] = xj;\n Y.data[i + j * N] = y.data[i];\n }\n }\n return { X, Y };\n}\n\nfunction mtoc2_meshgrid_1arg(x) {\n return mtoc2_meshgrid(x, x);\n}\n",
|
|
73498
73751
|
"tensor_mtimes_complex.js": '// JS sibling of `tensor_mtimes_complex.h`. 2-D matrix multiplication\n// producing a complex result. Handles all three mixed cases\n// (complex \xD7 complex, complex \xD7 real, real \xD7 complex) by treating an\n// undefined imag lane as implicit zeros.\n\n\nfunction mtoc2_tensor_mtimes_complex_scalar(a, b) {\n if (a.shape.length !== 2 || b.shape.length !== 2) {\n throw new Error("mtoc2_tensor_mtimes_complex_scalar: inputs must be 2-D");\n }\n if (a.shape[0] !== 1 || b.shape[1] !== 1) {\n throw new Error("mtoc2_tensor_mtimes_complex_scalar: requires 1\xD7k * k\xD71");\n }\n if (a.shape[1] !== b.shape[0]) {\n throw new Error("mtoc2_tensor_mtimes_complex_scalar: inner-dim mismatch");\n }\n const k = a.shape[1];\n const aim = a.imag;\n const bim = b.imag;\n let accR = 0;\n let accI = 0;\n for (let p = 0; p < k; p++) {\n const ar = a.data[p];\n const ai = aim !== undefined ? aim[p] : 0;\n const br = b.data[p];\n const bi = bim !== undefined ? bim[p] : 0;\n accR += ar * br - ai * bi;\n accI += ar * bi + ai * br;\n }\n return { re: accR, im: accI };\n}\n\nfunction mtoc2_tensor_mtimes_complex(a, b) {\n if (a.shape.length !== 2 || b.shape.length !== 2) {\n throw new Error("mtoc2_tensor_mtimes_complex: inputs must be 2-D");\n }\n const m = a.shape[0];\n const k = a.shape[1];\n const k2 = b.shape[0];\n const n = b.shape[1];\n if (k !== k2) {\n throw new Error(\n `mtoc2_tensor_mtimes_complex: inner-dim mismatch (${m}\xD7${k} * ${k2}\xD7${n})`\n );\n }\n const out = mtoc2_tensor_alloc_complex(m, n);\n const aim = a.imag;\n const bim = b.imag;\n for (let j = 0; j < n; j++) {\n for (let i = 0; i < m; i++) {\n let accR = 0;\n let accI = 0;\n for (let p = 0; p < k; p++) {\n const ar = a.data[i + p * m];\n const ai = aim !== undefined ? aim[i + p * m] : 0;\n const br = b.data[p + j * k];\n const bi = bim !== undefined ? bim[p + j * k] : 0;\n accR += ar * br - ai * bi;\n accI += ar * bi + ai * br;\n }\n out.data[i + j * m] = accR;\n out.imag[i + j * m] = accI;\n }\n }\n return out;\n}\n',
|
|
73499
|
-
"tensor_mtimes_real.js": '// JS sibling of `tensor_mtimes_real.h`. Real 2-D matrix\n// multiplication A * B. Column-major in, column-major out.\n// `mtoc2_tensor_mtimes_real_scalar` mirrors the C 1\xD7k * k\xD71\n// inner-product path that returns a bare number instead of a\n// freshly-allocated 1\xD71 tensor.\n\n\nfunction mtoc2_tensor_mtimes_real(a, b) {\n if (a.shape.length !== 2 || b.shape.length !== 2) {\n throw new Error("mtoc2_tensor_mtimes_real: inputs must be 2-D");\n }\n const m = a.shape[0];\n const k = a.shape[1];\n const k2 = b.shape[0];\n const n = b.shape[1];\n if (k !== k2) {\n throw new Error(\n `mtoc2_tensor_mtimes_real: inner dimensions disagree (${k} vs ${k2})`\n );\n }\n const r = mtoc2_tensor_alloc(m, n);\n for (let j = 0; j < n; j++) {\n for (let i = 0; i < m; i++) {\n let s = 0;\n for (let p = 0; p < k; p++) {\n s += a.data[i + p * m] * b.data[p + j * k];\n }\n r.data[i + j * m] = s;\n }\n }\n return r;\n}\n\nfunction mtoc2_tensor_mtimes_real_scalar(a, b) {\n if (a.shape.length !== 2 || b.shape.length !== 2) {\n throw new Error("mtoc2_tensor_mtimes_real_scalar: inputs must be 2-D");\n }\n // The translate-time type system has already proven a is 1\xD7k and b\n // is k\xD71; this helper trusts that and just runs the inner product.\n const k = a.shape[1];\n let s = 0;\n for (let p = 0; p < k; p++) {\n s += a.data[p * a.shape[0]] * b.data[p];\n }\n return s;\n}\n',
|
|
73752
|
+
"tensor_mtimes_real.js": '// JS sibling of `tensor_mtimes_real.h`. Real 2-D matrix\n// multiplication A * B. Column-major in, column-major out.\n// `mtoc2_tensor_mtimes_real_scalar` mirrors the C 1\xD7k * k\xD71\n// inner-product path that returns a bare number instead of a\n// freshly-allocated 1\xD71 tensor.\n\n\nfunction mtoc2_tensor_mtimes_real(a, b) {\n if (a.shape.length !== 2 || b.shape.length !== 2) {\n throw new Error("mtoc2_tensor_mtimes_real: inputs must be 2-D");\n }\n const m = a.shape[0];\n const k = a.shape[1];\n const k2 = b.shape[0];\n const n = b.shape[1];\n if (k !== k2) {\n throw new Error(\n `mtoc2_tensor_mtimes_real: inner dimensions disagree (${k} vs ${k2})`\n );\n }\n // Optional WASM LAPACK accelerator. When a host installs `$matmulAccel`\n // (browser worker, after loading a bridge), delegate the multiply; a\n // falsy return means "declined" (too small / error) and we fall through\n // to the JS loop below. `typeof` guard is safe even when unset.\n if (typeof $matmulAccel === "function") {\n const accel = $matmulAccel(a.data, m, k, b.data, n);\n if (accel) {\n const acc = mtoc2_tensor_alloc(m, n);\n acc.data.set(accel);\n return acc;\n }\n }\n const r = mtoc2_tensor_alloc(m, n);\n for (let j = 0; j < n; j++) {\n for (let i = 0; i < m; i++) {\n let s = 0;\n for (let p = 0; p < k; p++) {\n s += a.data[i + p * m] * b.data[p + j * k];\n }\n r.data[i + j * m] = s;\n }\n }\n return r;\n}\n\nfunction mtoc2_tensor_mtimes_real_scalar(a, b) {\n if (a.shape.length !== 2 || b.shape.length !== 2) {\n throw new Error("mtoc2_tensor_mtimes_real_scalar: inputs must be 2-D");\n }\n // The translate-time type system has already proven a is 1\xD7k and b\n // is k\xD71; this helper trusts that and just runs the inner product.\n const k = a.shape[1];\n let s = 0;\n for (let p = 0; p < k; p++) {\n s += a.data[p * a.shape[0]] * b.data[p];\n }\n return s;\n}\n',
|
|
73500
73753
|
"tensor_norm.js": "// JS sibling of `tensor_norm.h`. Vector norms for real and complex\n// tensors. The complex variants tolerate a missing imag lane (real\n// tensor flowing through a complex-typed norm route) by treating it\n// as zero.\n\nfunction mtoc2_norm2_real(a) {\n let acc = 0;\n for (let i = 0; i < a.data.length; i++) {\n const x = a.data[i];\n acc += x * x;\n }\n return Math.sqrt(acc);\n}\n\nfunction mtoc2_norm2_complex(a) {\n let acc = 0;\n const im = a.imag;\n for (let i = 0; i < a.data.length; i++) {\n const re = a.data[i];\n const imv = im !== undefined ? im[i] : 0;\n acc += re * re + imv * imv;\n }\n return Math.sqrt(acc);\n}\n\nfunction mtoc2_norm_p_real(a, p) {\n const n = a.data.length;\n if (n === 0) return 0;\n if (p === Infinity) {\n let m = 0;\n for (let i = 0; i < n; i++) {\n const x = Math.abs(a.data[i]);\n if (x > m) m = x;\n }\n return m;\n }\n if (p === -Infinity) {\n let m = Math.abs(a.data[0]);\n for (let i = 1; i < n; i++) {\n const x = Math.abs(a.data[i]);\n if (x < m) m = x;\n }\n return m;\n }\n if (p === 1) {\n let acc = 0;\n for (let i = 0; i < n; i++) acc += Math.abs(a.data[i]);\n return acc;\n }\n if (p === 2) return mtoc2_norm2_real(a);\n let acc = 0;\n for (let i = 0; i < n; i++) acc += Math.pow(Math.abs(a.data[i]), p);\n return Math.pow(acc, 1 / p);\n}\n\nfunction mtoc2_norm_p_complex(a, p) {\n const n = a.data.length;\n if (n === 0) return 0;\n const im = a.imag;\n const abs = i => {\n const re = a.data[i];\n const imv = im !== undefined ? im[i] : 0;\n return Math.hypot(re, imv);\n };\n if (p === Infinity) {\n let m = 0;\n for (let i = 0; i < n; i++) {\n const x = abs(i);\n if (x > m) m = x;\n }\n return m;\n }\n if (p === -Infinity) {\n let m = abs(0);\n for (let i = 1; i < n; i++) {\n const x = abs(i);\n if (x < m) m = x;\n }\n return m;\n }\n if (p === 2) return mtoc2_norm2_complex(a);\n if (p === 1) {\n let acc = 0;\n for (let i = 0; i < n; i++) acc += abs(i);\n return acc;\n }\n let acc = 0;\n for (let i = 0; i < n; i++) acc += Math.pow(abs(i), p);\n return Math.pow(acc, 1 / p);\n}\n",
|
|
73501
73754
|
"tensor_ones_nd.js": "// JS sibling of `tensor_ones_nd.h`. Fill the freshly-allocated\n// tensor with `1.0`.\n\n\nfunction mtoc2_tensor_ones_nd(ndim, dims) {\n const t = mtoc2_tensor_alloc_nd(ndim, dims);\n t.data.fill(1);\n return t;\n}\n",
|
|
73502
73755
|
"tensor_ones_square.js": "// JS sibling of `tensor_ones_square.h`. See `tensor_zeros_square.js`\n// for the rationale.\n\n\nfunction mtoc2_tensor_ones_square(n) {\n return mtoc2_tensor_ones_nd(2, [n, n]);\n}\n",
|
|
@@ -82065,9 +82318,9 @@ function tileExact(src, padShape2, padReps) {
|
|
|
82065
82318
|
}
|
|
82066
82319
|
return out;
|
|
82067
82320
|
}
|
|
82068
|
-
function padTo(arr,
|
|
82321
|
+
function padTo(arr, pad2, len) {
|
|
82069
82322
|
const out = arr.slice();
|
|
82070
|
-
while (out.length < len) out.push(
|
|
82323
|
+
while (out.length < len) out.push(pad2);
|
|
82071
82324
|
return out;
|
|
82072
82325
|
}
|
|
82073
82326
|
function trimTrailingOnes(shape) {
|
|
@@ -93152,7 +93405,7 @@ var VirtualFileSystem = class {
|
|
|
93152
93405
|
};
|
|
93153
93406
|
|
|
93154
93407
|
// src/vfs/BrowserFileIOAdapter.ts
|
|
93155
|
-
import { unzipSync } from "fflate";
|
|
93408
|
+
import { unzipSync, zipSync } from "fflate";
|
|
93156
93409
|
var TEXT_DECODER = new TextDecoder("utf-8");
|
|
93157
93410
|
var TEXT_ENCODER = new TextEncoder();
|
|
93158
93411
|
var READ_CHUNK_SIZE = 8192;
|
|
@@ -93470,6 +93723,57 @@ var BrowserFileIOAdapter = class {
|
|
|
93470
93723
|
}
|
|
93471
93724
|
return extracted;
|
|
93472
93725
|
}
|
|
93726
|
+
zip(zipfilename, filenames, rootDir) {
|
|
93727
|
+
const root = this.vfs.normalizePath(rootDir);
|
|
93728
|
+
const dest = this.vfs.normalizePath(zipfilename);
|
|
93729
|
+
const entries = {};
|
|
93730
|
+
const names = [];
|
|
93731
|
+
const toEntryName = (abs2) => {
|
|
93732
|
+
const prefix = root === "/" ? "/" : root + "/";
|
|
93733
|
+
if (!abs2.startsWith(prefix)) return abs2.slice(abs2.lastIndexOf("/") + 1);
|
|
93734
|
+
return abs2.slice(prefix.length);
|
|
93735
|
+
};
|
|
93736
|
+
const addFile = (abs2) => {
|
|
93737
|
+
const name = toEntryName(abs2);
|
|
93738
|
+
entries[name] = this.vfs.readFile(abs2);
|
|
93739
|
+
names.push(name);
|
|
93740
|
+
};
|
|
93741
|
+
const addDir = (absDir) => {
|
|
93742
|
+
for (const entry of this.vfs.listDir(absDir)) {
|
|
93743
|
+
if (entry.name === "." || entry.name === "..") continue;
|
|
93744
|
+
const abs2 = absDir + "/" + entry.name;
|
|
93745
|
+
if (entry.isdir) addDir(abs2);
|
|
93746
|
+
else addFile(abs2);
|
|
93747
|
+
}
|
|
93748
|
+
};
|
|
93749
|
+
const addPath = (abs2) => {
|
|
93750
|
+
const type = this.vfs.exists(abs2);
|
|
93751
|
+
if (type === null) throw new Error(`zip: cannot find '${abs2}'`);
|
|
93752
|
+
if (type === "dir") addDir(abs2);
|
|
93753
|
+
else addFile(abs2);
|
|
93754
|
+
};
|
|
93755
|
+
for (const f of filenames) {
|
|
93756
|
+
const p2 = f.replace(/\\/g, "/");
|
|
93757
|
+
const abs2 = p2.startsWith("/") ? this.vfs.normalizePath(p2) : this.vfs.normalizePath(root + "/" + p2);
|
|
93758
|
+
const last = p2.split("/").pop() ?? p2;
|
|
93759
|
+
if (last.includes("*") || last.includes("?")) {
|
|
93760
|
+
const lastSlash = abs2.lastIndexOf("/");
|
|
93761
|
+
const dir = lastSlash > 0 ? abs2.slice(0, lastSlash) : "/";
|
|
93762
|
+
const re = new RegExp(
|
|
93763
|
+
"^" + last.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".") + "$"
|
|
93764
|
+
);
|
|
93765
|
+
if (this.vfs.exists(dir) !== "dir") continue;
|
|
93766
|
+
for (const entry of this.vfs.listDir(dir)) {
|
|
93767
|
+
if (entry.name === "." || entry.name === "..") continue;
|
|
93768
|
+
if (re.test(entry.name)) addPath(dir + "/" + entry.name);
|
|
93769
|
+
}
|
|
93770
|
+
} else {
|
|
93771
|
+
addPath(abs2);
|
|
93772
|
+
}
|
|
93773
|
+
}
|
|
93774
|
+
this.vfs.writeFile(dest, zipSync(entries));
|
|
93775
|
+
return names;
|
|
93776
|
+
}
|
|
93473
93777
|
/** Get the VFS changes for syncing back to the main thread. */
|
|
93474
93778
|
getChanges() {
|
|
93475
93779
|
for (const [, entry] of this.openFiles) {
|
|
@@ -93552,21 +93856,30 @@ var BrowserFileIOAdapter = class {
|
|
|
93552
93856
|
);
|
|
93553
93857
|
}
|
|
93554
93858
|
listDirRecursive(pattern) {
|
|
93555
|
-
const
|
|
93556
|
-
|
|
93859
|
+
const norm2 = pattern.replace(/\\/g, "/");
|
|
93860
|
+
const idx = norm2.indexOf("**");
|
|
93861
|
+
let baseDir = norm2.slice(0, idx);
|
|
93557
93862
|
if (baseDir.endsWith("/")) baseDir = baseDir.slice(0, -1);
|
|
93558
93863
|
if (!baseDir) baseDir = ".";
|
|
93864
|
+
const absBase = this.vfs.normalizePath(baseDir);
|
|
93865
|
+
if (this.vfs.exists(absBase) !== "dir") return [];
|
|
93866
|
+
const suffix = norm2.slice(idx);
|
|
93867
|
+
const DIRS = "\0";
|
|
93868
|
+
const ANY = "";
|
|
93869
|
+
const re = new RegExp(
|
|
93870
|
+
"^" + suffix.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*\//g, DIRS).replace(/\*\*/g, ANY).replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(new RegExp(DIRS, "g"), "(?:.*/)?").replace(new RegExp(ANY, "g"), ".*") + "$"
|
|
93871
|
+
);
|
|
93559
93872
|
const results = [];
|
|
93560
|
-
const walkDir = (dir) => {
|
|
93561
|
-
const
|
|
93562
|
-
|
|
93563
|
-
|
|
93873
|
+
const walkDir = (dir, rel) => {
|
|
93874
|
+
const relPrefix = rel ? rel + "/" : "";
|
|
93875
|
+
for (const entry of this.vfs.listDir(dir)) {
|
|
93876
|
+
if (re.test(relPrefix + entry.name)) results.push(entry);
|
|
93564
93877
|
if (entry.isdir && entry.name !== "." && entry.name !== "..") {
|
|
93565
|
-
walkDir(entry.folder + "/" + entry.name);
|
|
93878
|
+
walkDir(entry.folder + "/" + entry.name, relPrefix + entry.name);
|
|
93566
93879
|
}
|
|
93567
93880
|
}
|
|
93568
93881
|
};
|
|
93569
|
-
walkDir(
|
|
93882
|
+
walkDir(absBase, "");
|
|
93570
93883
|
return results;
|
|
93571
93884
|
}
|
|
93572
93885
|
};
|