numbl 0.4.6 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cli/cli.js +2600 -228
- package/dist-graphics/graphics/FigureView.d.ts +6 -0
- package/dist-graphics/graphics/SurfView.d.ts +18 -0
- package/dist-graphics/graphics/axisLimits.d.ts +23 -0
- package/dist-graphics/graphics/drawPlot.d.ts +2 -0
- package/dist-graphics/graphics/exportFigureHdf5.d.ts +21 -0
- package/dist-graphics/graphics/figureHashTransport.d.ts +24 -0
- package/dist-graphics/graphics/figureHdf5Schema.d.ts +19 -0
- package/dist-graphics/graphics/figureUpload.d.ts +45 -0
- package/dist-graphics/graphics/figuresReducer.d.ts +86 -0
- package/dist-graphics/graphics/importFigureHdf5.d.ts +9 -0
- package/dist-graphics/graphics/openInFigureViewer.d.ts +26 -0
- package/dist-graphics/graphics/plotHelpers.d.ts +6 -0
- package/dist-graphics/graphics/plotLegend.d.ts +2 -0
- package/dist-graphics/graphics/plotMarkers.d.ts +2 -0
- package/dist-graphics/graphics/restoreNaNs.d.ts +2 -0
- package/dist-graphics/graphics/surfColormap.d.ts +2 -0
- package/dist-graphics/graphics/types.d.ts +423 -0
- package/dist-graphics/graphics/uihtmlSrcDoc.d.ts +23 -0
- package/dist-graphics/graphics-lib.d.ts +21 -0
- package/dist-graphics/index.js +35334 -0
- package/dist-lib/lib.d.ts +4 -0
- package/dist-lib/lib.js +3286 -222
- package/dist-lib/numbl-core/executors/jit/hostHelpers.d.ts +4 -0
- package/dist-lib/numbl-core/fileIOAdapter.d.ts +13 -0
- package/dist-lib/numbl-core/interpreter/builtins/gallery.d.ts +7 -0
- package/dist-lib/numbl-core/interpreter/builtins/geometry.d.ts +3 -3
- package/dist-lib/numbl-core/interpreter/builtins/graph.d.ts +29 -0
- package/dist-lib/numbl-core/interpreter/builtins/index.d.ts +2 -0
- package/dist-lib/numbl-core/interpreter/interpreter.d.ts +5 -0
- package/dist-lib/numbl-core/interpreter/interpreterExec.d.ts +14 -1
- package/dist-lib/numbl-core/interpreter/interpreterFunctions.d.ts +6 -0
- package/dist-lib/numbl-core/interpreter/interpreterSpecialBuiltins.d.ts +4 -0
- package/dist-lib/numbl-core/interpreter/types.d.ts +13 -0
- package/dist-lib/numbl-core/jit/builtins/defs/math/rand.d.ts +2 -0
- package/dist-lib/numbl-core/jitDeclineDiagnostics.d.ts +32 -0
- package/dist-lib/numbl-core/jsUserFunctions.d.ts +13 -0
- package/dist-lib/numbl-core/lowering/classInfo.d.ts +19 -2
- package/dist-lib/numbl-core/native/geometry-bridge.d.ts +10 -0
- package/dist-lib/numbl-core/parser/ArgumentsParser.d.ts +6 -1
- package/dist-lib/numbl-core/runtime/constructors.d.ts +2 -1
- package/dist-lib/numbl-core/runtime/runtime.d.ts +2 -1
- package/dist-lib/numbl-core/runtime/runtimeMemberAccess.d.ts +1 -1
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/dist-lib/vfs/BrowserFileIOAdapter.d.ts +54 -0
- package/dist-lib/vfs/BrowserSystemAdapter.d.ts +27 -0
- package/dist-lib/vfs/VirtualFileSystem.d.ts +66 -0
- package/dist-plot-viewer/assets/hdf5_hl-C9YUKPMe.js +24296 -0
- package/dist-plot-viewer/assets/index-YeXWXIxH.js +4504 -0
- package/dist-plot-viewer/index.html +1 -1
- package/dist-site-viewer/assets/hdf5_hl-C9YUKPMe.js +24296 -0
- package/dist-site-viewer/assets/index-C-wfkZK0.js +4829 -0
- package/dist-site-viewer/assets/numbl-worker-Bnbz2rMQ.js +5228 -0
- package/dist-site-viewer/index.html +1 -1
- package/native/lapack_svd.cpp +50 -0
- package/package.json +21 -2
- package/dist-plot-viewer/assets/index-D4grNz8m.js +0 -4504
- package/dist-site-viewer/assets/index-B2mCFC55.js +0 -4826
- package/dist-site-viewer/assets/numbl-worker-DWZE29ck.js +0 -5116
package/dist-cli/cli.js
CHANGED
|
@@ -320,6 +320,7 @@ import { homedir as homedir4 } from "os";
|
|
|
320
320
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
321
321
|
import { createRequire } from "module";
|
|
322
322
|
import { execSync as execSync2 } from "child_process";
|
|
323
|
+
import { createHash as createHash2 } from "crypto";
|
|
323
324
|
|
|
324
325
|
// src/cli-plot-server.ts
|
|
325
326
|
import { createServer } from "node:http";
|
|
@@ -2628,6 +2629,9 @@ var RTV = {
|
|
|
2628
2629
|
}
|
|
2629
2630
|
return new RuntimeClassInstance(className, fields, isHandleClass2);
|
|
2630
2631
|
},
|
|
2632
|
+
classInstanceArray(className, elements, shape) {
|
|
2633
|
+
return new RuntimeClassInstanceArray(className, elements, shape);
|
|
2634
|
+
},
|
|
2631
2635
|
complex(re, im) {
|
|
2632
2636
|
return new RuntimeComplexNumber(re, im);
|
|
2633
2637
|
},
|
|
@@ -21187,6 +21191,24 @@ function lu(data, m, n) {
|
|
|
21187
21191
|
}
|
|
21188
21192
|
function svd(data, m, n, econ, computeUV) {
|
|
21189
21193
|
const k = Math.min(m, n);
|
|
21194
|
+
let finite = true;
|
|
21195
|
+
for (let i = 0; i < data.length; i++) {
|
|
21196
|
+
if (!Number.isFinite(data[i])) {
|
|
21197
|
+
finite = false;
|
|
21198
|
+
break;
|
|
21199
|
+
}
|
|
21200
|
+
}
|
|
21201
|
+
if (!finite) {
|
|
21202
|
+
const sNan = allocFloat64Array(k).fill(NaN);
|
|
21203
|
+
if (!computeUV) return { S: sNan };
|
|
21204
|
+
const uCols2 = econ ? k : m;
|
|
21205
|
+
const vCols2 = econ ? k : n;
|
|
21206
|
+
return {
|
|
21207
|
+
U: allocFloat64Array(m * uCols2).fill(NaN),
|
|
21208
|
+
S: sNan,
|
|
21209
|
+
V: allocFloat64Array(n * vCols2).fill(NaN)
|
|
21210
|
+
};
|
|
21211
|
+
}
|
|
21190
21212
|
const a = allocFloat64Array(data);
|
|
21191
21213
|
const s = allocFloat64Array(k);
|
|
21192
21214
|
const JOBU_A2 = 0;
|
|
@@ -22413,8 +22435,8 @@ function indexIntoScalar(base, indices) {
|
|
|
22413
22435
|
const idx = indices[0];
|
|
22414
22436
|
if (isRuntimeTensor(idx)) {
|
|
22415
22437
|
const is0x0 = idx.shape.length === 2 && idx.shape[0] === 0 && idx.shape[1] === 0;
|
|
22416
|
-
const
|
|
22417
|
-
return RTV.tensor(allocFloat64Array(0),
|
|
22438
|
+
const outShape2 = is0x0 ? [0, 0] : [...idx.shape];
|
|
22439
|
+
return RTV.tensor(allocFloat64Array(0), outShape2);
|
|
22418
22440
|
}
|
|
22419
22441
|
}
|
|
22420
22442
|
if (indices.length === 1) {
|
|
@@ -22444,22 +22466,46 @@ function indexIntoScalar(base, indices) {
|
|
|
22444
22466
|
if (k !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
22445
22467
|
}
|
|
22446
22468
|
const n = idx.data.length;
|
|
22447
|
-
const
|
|
22448
|
-
const
|
|
22449
|
-
|
|
22469
|
+
const scalarRe2 = isRuntimeNumber(base) ? base : base.re;
|
|
22470
|
+
const data2 = allocFloat64Array(n);
|
|
22471
|
+
data2.fill(scalarRe2);
|
|
22450
22472
|
if (isRuntimeComplexNumber(base) && base.im !== 0) {
|
|
22451
22473
|
const im = allocFloat64Array(n);
|
|
22452
22474
|
im.fill(base.im);
|
|
22453
|
-
return RTV.tensor(
|
|
22475
|
+
return RTV.tensor(data2, [...idx.shape], im);
|
|
22454
22476
|
}
|
|
22455
|
-
return RTV.tensor(
|
|
22477
|
+
return RTV.tensor(data2, [...idx.shape]);
|
|
22456
22478
|
}
|
|
22479
|
+
const dimLengths = [];
|
|
22480
|
+
let anyTensor = false;
|
|
22457
22481
|
for (const idx of indices) {
|
|
22458
|
-
if (isColonIndex(idx))
|
|
22459
|
-
|
|
22460
|
-
if (
|
|
22482
|
+
if (isColonIndex(idx)) {
|
|
22483
|
+
dimLengths.push(1);
|
|
22484
|
+
} else if (isRuntimeTensor(idx)) {
|
|
22485
|
+
anyTensor = true;
|
|
22486
|
+
for (let i = 0; i < idx.data.length; i++) {
|
|
22487
|
+
if (Math.round(idx.data[i]) !== 1)
|
|
22488
|
+
throw new RuntimeError("Index exceeds array bounds");
|
|
22489
|
+
}
|
|
22490
|
+
dimLengths.push(idx.data.length);
|
|
22491
|
+
} else {
|
|
22492
|
+
if (Math.round(toNumber(idx)) !== 1)
|
|
22493
|
+
throw new RuntimeError("Index exceeds array bounds");
|
|
22494
|
+
dimLengths.push(1);
|
|
22495
|
+
}
|
|
22461
22496
|
}
|
|
22462
|
-
return base;
|
|
22497
|
+
if (!anyTensor) return base;
|
|
22498
|
+
const total = dimLengths.reduce((a, b) => a * b, 1);
|
|
22499
|
+
const scalarRe = isRuntimeNumber(base) ? base : base.re;
|
|
22500
|
+
const data = allocFloat64Array(total);
|
|
22501
|
+
data.fill(scalarRe);
|
|
22502
|
+
const outShape = dimLengths.length >= 2 ? dimLengths : [dimLengths[0], 1];
|
|
22503
|
+
if (isRuntimeComplexNumber(base) && base.im !== 0) {
|
|
22504
|
+
const im = allocFloat64Array(total);
|
|
22505
|
+
im.fill(base.im);
|
|
22506
|
+
return RTV.tensor(data, outShape, im);
|
|
22507
|
+
}
|
|
22508
|
+
return RTV.tensor(data, outShape);
|
|
22463
22509
|
}
|
|
22464
22510
|
function indexIntoTensor(base, indices) {
|
|
22465
22511
|
if (indices.length === 1) {
|
|
@@ -22494,11 +22540,13 @@ function indexIntoTensor(base, indices) {
|
|
|
22494
22540
|
function indexIntoTensor1D(base, idx) {
|
|
22495
22541
|
if (isColonIndex(idx)) {
|
|
22496
22542
|
const imag2 = base.imag ? allocFloat64Array(base.imag) : void 0;
|
|
22497
|
-
|
|
22543
|
+
const result = RTV.tensor(
|
|
22498
22544
|
allocFloat64Array(base.data),
|
|
22499
22545
|
[base.data.length, 1],
|
|
22500
22546
|
imag2
|
|
22501
22547
|
);
|
|
22548
|
+
if (base._isLogical === true) result._isLogical = true;
|
|
22549
|
+
return result;
|
|
22502
22550
|
}
|
|
22503
22551
|
if (isRuntimeLogical(idx)) {
|
|
22504
22552
|
if (!idx) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
@@ -22696,6 +22744,17 @@ function indexIntoChar(base, indices) {
|
|
|
22696
22744
|
if (indices.length === 1) {
|
|
22697
22745
|
const idx = indices[0];
|
|
22698
22746
|
if (isColonIndex(idx)) return base;
|
|
22747
|
+
if (isRuntimeTensor(idx) && idx._isLogical) {
|
|
22748
|
+
let result = "";
|
|
22749
|
+
for (let k = 0; k < idx.data.length; k++) {
|
|
22750
|
+
if (idx.data[k] !== 0) {
|
|
22751
|
+
if (k >= base.value.length)
|
|
22752
|
+
throw new RuntimeError("Index exceeds char array length");
|
|
22753
|
+
result += base.value[k];
|
|
22754
|
+
}
|
|
22755
|
+
}
|
|
22756
|
+
return RTV.char(result);
|
|
22757
|
+
}
|
|
22699
22758
|
if (isRuntimeTensor(idx)) {
|
|
22700
22759
|
let result = "";
|
|
22701
22760
|
for (let k = 0; k < idx.data.length; k++) {
|
|
@@ -22714,22 +22773,19 @@ function indexIntoChar(base, indices) {
|
|
|
22714
22773
|
if (indices.length === 2) {
|
|
22715
22774
|
const rowIdx = indices[0];
|
|
22716
22775
|
const colIdx = indices[1];
|
|
22717
|
-
|
|
22718
|
-
|
|
22719
|
-
|
|
22720
|
-
|
|
22721
|
-
|
|
22722
|
-
|
|
22723
|
-
|
|
22724
|
-
|
|
22725
|
-
|
|
22726
|
-
|
|
22727
|
-
|
|
22728
|
-
|
|
22729
|
-
|
|
22730
|
-
} else {
|
|
22731
|
-
cols = [Math.round(toNumber(colIdx)) - 1];
|
|
22732
|
-
}
|
|
22776
|
+
const toPositions = (idx) => {
|
|
22777
|
+
if (isRuntimeTensor(idx) && idx._isLogical) {
|
|
22778
|
+
const out = [];
|
|
22779
|
+
for (let i = 0; i < idx.data.length; i++)
|
|
22780
|
+
if (idx.data[i] !== 0) out.push(i);
|
|
22781
|
+
return out;
|
|
22782
|
+
}
|
|
22783
|
+
if (isRuntimeTensor(idx))
|
|
22784
|
+
return Array.from(idx.data, (v) => Math.round(v) - 1);
|
|
22785
|
+
return [Math.round(toNumber(idx)) - 1];
|
|
22786
|
+
};
|
|
22787
|
+
const rows = isColonIndex(rowIdx) ? Array.from({ length: nRows }, (_, i) => i) : toPositions(rowIdx);
|
|
22788
|
+
const cols = isColonIndex(colIdx) ? Array.from({ length: nCols }, (_, i) => i) : toPositions(colIdx);
|
|
22733
22789
|
let result = "";
|
|
22734
22790
|
for (const r of rows) {
|
|
22735
22791
|
for (const c of cols) {
|
|
@@ -22755,11 +22811,11 @@ function indexIntoLogical(base, indices) {
|
|
|
22755
22811
|
const vi = Math.round(idx.data[i2]);
|
|
22756
22812
|
if (vi !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
22757
22813
|
}
|
|
22758
|
-
const
|
|
22759
|
-
|
|
22760
|
-
const
|
|
22761
|
-
|
|
22762
|
-
return
|
|
22814
|
+
const data2 = allocFloat64Array(idx.data.length);
|
|
22815
|
+
data2.fill(base ? 1 : 0);
|
|
22816
|
+
const result2 = RTV.tensor(data2, [...idx.shape]);
|
|
22817
|
+
result2._isLogical = true;
|
|
22818
|
+
return result2;
|
|
22763
22819
|
}
|
|
22764
22820
|
if (isRuntimeLogical(idx)) {
|
|
22765
22821
|
if (!idx) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
@@ -22769,16 +22825,35 @@ function indexIntoLogical(base, indices) {
|
|
|
22769
22825
|
if (i !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
22770
22826
|
return base;
|
|
22771
22827
|
}
|
|
22828
|
+
const dimLengths = [];
|
|
22829
|
+
let anyTensor = false;
|
|
22772
22830
|
for (const idx of indices) {
|
|
22773
|
-
if (isColonIndex(idx))
|
|
22774
|
-
|
|
22831
|
+
if (isColonIndex(idx)) {
|
|
22832
|
+
dimLengths.push(1);
|
|
22833
|
+
} else if (isRuntimeLogical(idx)) {
|
|
22775
22834
|
if (!idx) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
22776
|
-
|
|
22835
|
+
dimLengths.push(1);
|
|
22836
|
+
} else if (isRuntimeTensor(idx)) {
|
|
22837
|
+
anyTensor = true;
|
|
22838
|
+
for (let i = 0; i < idx.data.length; i++) {
|
|
22839
|
+
if (Math.round(idx.data[i]) !== 1)
|
|
22840
|
+
throw new RuntimeError("Index exceeds array bounds");
|
|
22841
|
+
}
|
|
22842
|
+
dimLengths.push(idx.data.length);
|
|
22843
|
+
} else {
|
|
22844
|
+
if (Math.round(toNumber(idx)) !== 1)
|
|
22845
|
+
throw new RuntimeError("Index exceeds array bounds");
|
|
22846
|
+
dimLengths.push(1);
|
|
22777
22847
|
}
|
|
22778
|
-
const i = Math.round(toNumber(idx));
|
|
22779
|
-
if (i !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
22780
22848
|
}
|
|
22781
|
-
return base;
|
|
22849
|
+
if (!anyTensor) return base;
|
|
22850
|
+
const total = dimLengths.reduce((a, b) => a * b, 1);
|
|
22851
|
+
const data = allocFloat64Array(total);
|
|
22852
|
+
data.fill(base ? 1 : 0);
|
|
22853
|
+
const outShape = dimLengths.length >= 2 ? dimLengths : [dimLengths[0], 1];
|
|
22854
|
+
const result = RTV.tensor(data, outShape);
|
|
22855
|
+
result._isLogical = true;
|
|
22856
|
+
return result;
|
|
22782
22857
|
}
|
|
22783
22858
|
function indexIntoTensorWithTensor(base, idx) {
|
|
22784
22859
|
const baseLogical = base._isLogical === true;
|
|
@@ -22858,11 +22933,15 @@ function indexIntoRTValue(base, indices) {
|
|
|
22858
22933
|
return indexIntoLogical(base, indices);
|
|
22859
22934
|
}
|
|
22860
22935
|
if (isRuntimeStruct(base) || isRuntimeClassInstance(base)) {
|
|
22861
|
-
|
|
22862
|
-
|
|
22863
|
-
if (
|
|
22864
|
-
|
|
22865
|
-
|
|
22936
|
+
const allOnes = indices.length >= 1 && indices.every((idx) => {
|
|
22937
|
+
if (isRuntimeNumber(idx)) return Math.round(idx) === 1;
|
|
22938
|
+
if (isRuntimeLogical(idx)) return idx === true;
|
|
22939
|
+
if (isRuntimeTensor(idx))
|
|
22940
|
+
return idx.data.length === 1 && Math.round(idx.data[0]) === 1;
|
|
22941
|
+
return false;
|
|
22942
|
+
});
|
|
22943
|
+
if (allOnes) return base;
|
|
22944
|
+
throw new RuntimeError("Index exceeds struct dimensions");
|
|
22866
22945
|
}
|
|
22867
22946
|
if (isRuntimeSparseMatrix(base)) {
|
|
22868
22947
|
return indexIntoSparse(base, indices);
|
|
@@ -22912,7 +22991,13 @@ function storeIntoTensor(base, indices, rhs, _rt) {
|
|
|
22912
22991
|
}
|
|
22913
22992
|
if (isShared(base)) {
|
|
22914
22993
|
const cowImag = base.imag ? allocFloat64Array(base.imag) : void 0;
|
|
22915
|
-
|
|
22994
|
+
const copy = RTV.tensor(
|
|
22995
|
+
allocFloat64Array(base.data),
|
|
22996
|
+
[...base.shape],
|
|
22997
|
+
cowImag
|
|
22998
|
+
);
|
|
22999
|
+
copy._isLogical = base._isLogical;
|
|
23000
|
+
base = copy;
|
|
22916
23001
|
}
|
|
22917
23002
|
if (indices.length === 1) {
|
|
22918
23003
|
return storeIntoTensor1D(base, indices[0], rhs);
|
|
@@ -22940,7 +23025,9 @@ function deleteTensorElements(base, idx) {
|
|
|
22940
23025
|
toDelete.add(Math.round(idx.data[i]) - 1);
|
|
22941
23026
|
}
|
|
22942
23027
|
} else if (isColonIndex(idx)) {
|
|
22943
|
-
|
|
23028
|
+
const empty = RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
23029
|
+
empty._isLogical = base._isLogical;
|
|
23030
|
+
return empty;
|
|
22944
23031
|
}
|
|
22945
23032
|
if (toDelete.size === 0) return base;
|
|
22946
23033
|
const newData = [];
|
|
@@ -22955,7 +23042,9 @@ function deleteTensorElements(base, idx) {
|
|
|
22955
23042
|
const baseIsColVec = base.shape.length >= 2 && base.shape[1] === 1 && base.shape[0] !== 1;
|
|
22956
23043
|
const outShape = baseIsColVec ? [newData.length, 1] : [1, newData.length];
|
|
22957
23044
|
const imOut = hasImag && newIm.some((x) => x !== 0) ? allocFloat64Array(newIm) : void 0;
|
|
22958
|
-
|
|
23045
|
+
const result = RTV.tensor(allocFloat64Array(newData), outShape, imOut);
|
|
23046
|
+
result._isLogical = base._isLogical;
|
|
23047
|
+
return result;
|
|
22959
23048
|
}
|
|
22960
23049
|
function collectDelIndices(idx, dimLen) {
|
|
22961
23050
|
const s = /* @__PURE__ */ new Set();
|
|
@@ -22995,7 +23084,9 @@ function deleteTensorRowsOrCols(base, indices) {
|
|
|
22995
23084
|
if (newIm && base.imag) newIm[dstIdx] = base.imag[srcIdx];
|
|
22996
23085
|
}
|
|
22997
23086
|
}
|
|
22998
|
-
|
|
23087
|
+
const result = RTV.tensor(newData, [newNrows, ncols], newIm);
|
|
23088
|
+
result._isLogical = base._isLogical;
|
|
23089
|
+
return result;
|
|
22999
23090
|
}
|
|
23000
23091
|
if (isColonIndex(indices[0])) {
|
|
23001
23092
|
const delCols = collectDelIndices(indices[1], ncols);
|
|
@@ -23014,7 +23105,9 @@ function deleteTensorRowsOrCols(base, indices) {
|
|
|
23014
23105
|
if (newIm && base.imag) newIm[dstIdx] = base.imag[srcIdx];
|
|
23015
23106
|
}
|
|
23016
23107
|
}
|
|
23017
|
-
|
|
23108
|
+
const result = RTV.tensor(newData, [nrows, newNcols], newIm);
|
|
23109
|
+
result._isLogical = base._isLogical;
|
|
23110
|
+
return result;
|
|
23018
23111
|
}
|
|
23019
23112
|
throw new RuntimeError("Cannot delete from both row and column dimensions");
|
|
23020
23113
|
}
|
|
@@ -23084,6 +23177,9 @@ function storeIntoTensor1D(base, idx, rhs) {
|
|
|
23084
23177
|
}
|
|
23085
23178
|
function storeIntoTensorByVector(base, idx, rhs) {
|
|
23086
23179
|
if (idx._isLogical) {
|
|
23180
|
+
if (isRuntimeTensor(rhs) && rhs.data.length === 1) {
|
|
23181
|
+
rhs = rhs.imag && rhs.imag[0] !== 0 ? RTV.complex(rhs.data[0], rhs.imag[0]) : RTV.num(rhs.data[0]);
|
|
23182
|
+
}
|
|
23087
23183
|
const { re: rhsRe, im: rhsIm } = isRuntimeTensor(rhs) ? { re: null, im: null } : toReIm(rhs);
|
|
23088
23184
|
let maxTruthy = -1;
|
|
23089
23185
|
for (let i = 0; i < idx.data.length; i++) {
|
|
@@ -23333,7 +23429,8 @@ function storeIntoTensorND(base, indices, rhs) {
|
|
|
23333
23429
|
const dimIndices = indices.map((idx, dim) => {
|
|
23334
23430
|
const dimSize = dim < shape.length ? shape[dim] : 1;
|
|
23335
23431
|
if (isColonIndex(idx)) {
|
|
23336
|
-
|
|
23432
|
+
const dimSizeUnknown = dimSize === 0 || dim >= shape.length;
|
|
23433
|
+
if (dimSizeUnknown && rhsShape) {
|
|
23337
23434
|
const rDim = rhsDimCursor < rhsShape.length ? rhsShape[rhsDimCursor] : 1;
|
|
23338
23435
|
rhsDimCursor++;
|
|
23339
23436
|
return Array.from({ length: rDim }, (_, i) => i);
|
|
@@ -23650,6 +23747,9 @@ function horzcat(...values) {
|
|
|
23650
23747
|
if (values.some((v) => isRuntimeSparseMatrix(v))) {
|
|
23651
23748
|
return sparseCatAlongDim(values, 1);
|
|
23652
23749
|
}
|
|
23750
|
+
if (values.some((v) => isRuntimeCell(v))) {
|
|
23751
|
+
return cellCatAlongDim(values, 1);
|
|
23752
|
+
}
|
|
23653
23753
|
if (values.some((v) => isRuntimeChar(v))) {
|
|
23654
23754
|
let result = "";
|
|
23655
23755
|
for (const v of values) {
|
|
@@ -23670,9 +23770,6 @@ function horzcat(...values) {
|
|
|
23670
23770
|
}
|
|
23671
23771
|
return RTV.string(result);
|
|
23672
23772
|
}
|
|
23673
|
-
if (values.some((v) => isRuntimeCell(v))) {
|
|
23674
|
-
return cellCatAlongDim(values, 1);
|
|
23675
|
-
}
|
|
23676
23773
|
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
23677
23774
|
return structCat(values);
|
|
23678
23775
|
}
|
|
@@ -23684,12 +23781,12 @@ function vertcat(...values) {
|
|
|
23684
23781
|
if (values.some((v) => isRuntimeSparseMatrix(v))) {
|
|
23685
23782
|
return sparseCatAlongDim(values, 0);
|
|
23686
23783
|
}
|
|
23687
|
-
if (values.some((v) => isRuntimeChar(v))) {
|
|
23688
|
-
return vertcatChars(values);
|
|
23689
|
-
}
|
|
23690
23784
|
if (values.some((v) => isRuntimeCell(v))) {
|
|
23691
23785
|
return cellCatAlongDim(values, 0);
|
|
23692
23786
|
}
|
|
23787
|
+
if (values.some((v) => isRuntimeChar(v))) {
|
|
23788
|
+
return vertcatChars(values);
|
|
23789
|
+
}
|
|
23693
23790
|
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
23694
23791
|
return structCat(values);
|
|
23695
23792
|
}
|
|
@@ -24035,11 +24132,22 @@ function catAlongDim(values, dimIdx) {
|
|
|
24035
24132
|
if (allLogical) result._isLogical = true;
|
|
24036
24133
|
return result;
|
|
24037
24134
|
}
|
|
24135
|
+
function isEmptyNonCellOperand(v) {
|
|
24136
|
+
if (isRuntimeChar(v)) return v.value.length === 0;
|
|
24137
|
+
if (isRuntimeTensor(v)) return v.data.length === 0;
|
|
24138
|
+
return false;
|
|
24139
|
+
}
|
|
24038
24140
|
function cellCatAlongDim(values, dimIdx) {
|
|
24039
|
-
let cells =
|
|
24040
|
-
|
|
24041
|
-
|
|
24042
|
-
|
|
24141
|
+
let cells = [];
|
|
24142
|
+
for (const v of values) {
|
|
24143
|
+
if (isRuntimeCell(v)) {
|
|
24144
|
+
cells.push(v);
|
|
24145
|
+
} else if (isEmptyNonCellOperand(v)) {
|
|
24146
|
+
continue;
|
|
24147
|
+
} else {
|
|
24148
|
+
cells.push(RTV.cell([v], [1, 1]));
|
|
24149
|
+
}
|
|
24150
|
+
}
|
|
24043
24151
|
cells = cells.filter((c) => c.data.length > 0);
|
|
24044
24152
|
if (cells.length === 0) return RTV.cell([], [0, 0]);
|
|
24045
24153
|
if (cells.length === 1) return cells[0];
|
|
@@ -27229,6 +27337,24 @@ function sprintfFormat(fmt, args) {
|
|
|
27229
27337
|
case "t":
|
|
27230
27338
|
result += " ";
|
|
27231
27339
|
break;
|
|
27340
|
+
case "r":
|
|
27341
|
+
result += "\r";
|
|
27342
|
+
break;
|
|
27343
|
+
case "a":
|
|
27344
|
+
result += "\x07";
|
|
27345
|
+
break;
|
|
27346
|
+
case "b":
|
|
27347
|
+
result += "\b";
|
|
27348
|
+
break;
|
|
27349
|
+
case "f":
|
|
27350
|
+
result += "\f";
|
|
27351
|
+
break;
|
|
27352
|
+
case "v":
|
|
27353
|
+
result += "\v";
|
|
27354
|
+
break;
|
|
27355
|
+
case "0":
|
|
27356
|
+
result += "\0";
|
|
27357
|
+
break;
|
|
27232
27358
|
case "\\":
|
|
27233
27359
|
result += "\\";
|
|
27234
27360
|
break;
|
|
@@ -31459,7 +31585,7 @@ var ExpressionParser = class extends ParserBase {
|
|
|
31459
31585
|
}
|
|
31460
31586
|
} else if (expr.type === "Ident" && this.peekToken() === 41 /* At */ && this.peekTokenAt(1) === 4 /* Ident */) {
|
|
31461
31587
|
this.pos++;
|
|
31462
|
-
const className = this.
|
|
31588
|
+
const className = this.parseQualifiedName();
|
|
31463
31589
|
if (!this.consume(50 /* LParen */)) {
|
|
31464
31590
|
throw this.error("expected '(' after superclass name in super call");
|
|
31465
31591
|
}
|
|
@@ -32060,7 +32186,10 @@ var ControlFlowParser = class extends CommandParser {
|
|
|
32060
32186
|
let catchBody = [];
|
|
32061
32187
|
if (this.consume(27 /* Catch */)) {
|
|
32062
32188
|
if (this.peekToken() === 4 /* Ident */) {
|
|
32063
|
-
|
|
32189
|
+
const after = this.peekTokenAt(1);
|
|
32190
|
+
if (after === void 0 || after === 68 /* Newline */ || after === 49 /* Semicolon */ || after === 47 /* Comma */ || after === 15 /* End */) {
|
|
32191
|
+
catchVar = this.expectIdent();
|
|
32192
|
+
}
|
|
32064
32193
|
}
|
|
32065
32194
|
catchBody = this.parseBlock((t) => t === 15 /* End */);
|
|
32066
32195
|
}
|
|
@@ -32185,8 +32314,12 @@ var ArgumentsParser = class extends ControlFlowParser {
|
|
|
32185
32314
|
dimensions = this.parseArgDimensions();
|
|
32186
32315
|
}
|
|
32187
32316
|
let className = null;
|
|
32188
|
-
if (this.peekToken() === 4 /* Ident */
|
|
32317
|
+
if (this.peekToken() === 4 /* Ident */) {
|
|
32189
32318
|
className = this.next().lexeme;
|
|
32319
|
+
while (this.peekToken() === 45 /* Dot */) {
|
|
32320
|
+
this.consume(45 /* Dot */);
|
|
32321
|
+
className += "." + this.expectIdent();
|
|
32322
|
+
}
|
|
32190
32323
|
}
|
|
32191
32324
|
let validators = [];
|
|
32192
32325
|
if (this.peekToken() === 54 /* LBrace */) {
|
|
@@ -32222,18 +32355,28 @@ var ArgumentsParser = class extends ControlFlowParser {
|
|
|
32222
32355
|
return dims;
|
|
32223
32356
|
}
|
|
32224
32357
|
/**
|
|
32225
|
-
* Parse validator list: {mustBeNumeric, mustBePositive}
|
|
32358
|
+
* Parse validator list: {mustBeNumeric, mustBePositive}. Validators may be
|
|
32359
|
+
* full function calls with arguments, e.g.
|
|
32360
|
+
* `{mustBeMember(x,["a","b"]), mustBeInRange(x,0,7)}`. The validator bodies
|
|
32361
|
+
* are not enforced at runtime, so we capture the top-level validator name
|
|
32362
|
+
* tokens and skip past any nested `(...)`, `[...]`, `{...}` so parsing
|
|
32363
|
+
* resumes correctly at the default value (`= expr`) or end of line.
|
|
32226
32364
|
*/
|
|
32227
32365
|
parseArgValidators() {
|
|
32228
32366
|
this.consume(54 /* LBrace */);
|
|
32229
32367
|
const validators = [];
|
|
32230
|
-
|
|
32231
|
-
|
|
32232
|
-
|
|
32233
|
-
|
|
32234
|
-
|
|
32235
|
-
|
|
32368
|
+
let depth = 0;
|
|
32369
|
+
while (this.peekToken() !== void 0) {
|
|
32370
|
+
const tok = this.peekToken();
|
|
32371
|
+
if (depth === 0 && tok === 55 /* RBrace */) break;
|
|
32372
|
+
if (tok === 50 /* LParen */ || tok === 52 /* LBracket */ || tok === 54 /* LBrace */) {
|
|
32373
|
+
depth++;
|
|
32374
|
+
} else if (tok === 51 /* RParen */ || tok === 53 /* RBracket */ || tok === 55 /* RBrace */) {
|
|
32375
|
+
depth--;
|
|
32376
|
+
} else if (depth === 0 && tok === 4 /* Ident */) {
|
|
32377
|
+
validators.push(this.peek().lexeme);
|
|
32236
32378
|
}
|
|
32379
|
+
this.next();
|
|
32237
32380
|
}
|
|
32238
32381
|
this.consume(55 /* RBrace */);
|
|
32239
32382
|
return validators;
|
|
@@ -32264,7 +32407,8 @@ var FunctionParser = class extends ArgumentsParser {
|
|
|
32264
32407
|
if (this.consume(52 /* LBracket */)) {
|
|
32265
32408
|
if (this.peekToken() !== 53 /* RBracket */) {
|
|
32266
32409
|
outputs.push(this.expectIdentOrTilde());
|
|
32267
|
-
while (this.
|
|
32410
|
+
while (this.peekToken() === 47 /* Comma */ || this.peekToken() === 4 /* Ident */ || this.peekToken() === 40 /* Tilde */) {
|
|
32411
|
+
this.consume(47 /* Comma */);
|
|
32268
32412
|
outputs.push(this.expectIdentOrTilde());
|
|
32269
32413
|
}
|
|
32270
32414
|
}
|
|
@@ -32372,6 +32516,14 @@ var FunctionParser = class extends ArgumentsParser {
|
|
|
32372
32516
|
};
|
|
32373
32517
|
|
|
32374
32518
|
// src/numbl-core/parser/ClassParser.ts
|
|
32519
|
+
var HANDLE_BASE_CLASSES = /* @__PURE__ */ new Set([
|
|
32520
|
+
"handle",
|
|
32521
|
+
"dynamicprops",
|
|
32522
|
+
"matlab.mixin.Copyable",
|
|
32523
|
+
"matlab.mixin.SetGet",
|
|
32524
|
+
"matlab.mixin.SetGetExactNames",
|
|
32525
|
+
"hgsetget"
|
|
32526
|
+
]);
|
|
32375
32527
|
var ClassParser = class extends FunctionParser {
|
|
32376
32528
|
// ── Imports & ClassDef ───────────────────────────────────────────────
|
|
32377
32529
|
parseImport() {
|
|
@@ -32406,7 +32558,11 @@ var ClassParser = class extends FunctionParser {
|
|
|
32406
32558
|
const name = this.parseQualifiedName();
|
|
32407
32559
|
let superClass = null;
|
|
32408
32560
|
if (this.consume(43 /* Less */)) {
|
|
32409
|
-
|
|
32561
|
+
const supers = [this.parseQualifiedName()];
|
|
32562
|
+
while (this.consume(38 /* And */)) {
|
|
32563
|
+
supers.push(this.parseQualifiedName());
|
|
32564
|
+
}
|
|
32565
|
+
superClass = supers.some((s) => HANDLE_BASE_CLASSES.has(s)) ? "handle" : supers[0];
|
|
32410
32566
|
}
|
|
32411
32567
|
const members = [];
|
|
32412
32568
|
while (true) {
|
|
@@ -33281,7 +33437,7 @@ function insertFunctionEndTokens(tokens) {
|
|
|
33281
33437
|
}
|
|
33282
33438
|
if (BLOCK_OPENERS.has(tok.token)) {
|
|
33283
33439
|
depth++;
|
|
33284
|
-
} else if (tok.token === 15 /* End */ && groupDepth === 0) {
|
|
33440
|
+
} else if (tok.token === 15 /* End */ && groupDepth === 0 && tokens[i - 1]?.token !== 45 /* Dot */) {
|
|
33285
33441
|
depth--;
|
|
33286
33442
|
if (depth === 0 && inFunction) {
|
|
33287
33443
|
inFunction = false;
|
|
@@ -34806,7 +34962,9 @@ function dispatchPlotBuiltin(name, args, instructions, state) {
|
|
|
34806
34962
|
return true;
|
|
34807
34963
|
}
|
|
34808
34964
|
case "close": {
|
|
34809
|
-
|
|
34965
|
+
const a0 = args[0];
|
|
34966
|
+
const isText3 = a0 !== void 0 && (isRuntimeChar(a0) || isRuntimeString(a0));
|
|
34967
|
+
if (isText3 && toString(a0) === "all") {
|
|
34810
34968
|
plotInstr(instructions, { type: "close_all" });
|
|
34811
34969
|
} else {
|
|
34812
34970
|
plotInstr(instructions, { type: "close" });
|
|
@@ -35414,43 +35572,40 @@ function methodDispatch(rt, name, nargout, args) {
|
|
|
35414
35572
|
}
|
|
35415
35573
|
}
|
|
35416
35574
|
}
|
|
35417
|
-
|
|
35418
|
-
|
|
35419
|
-
|
|
35420
|
-
if (
|
|
35421
|
-
const
|
|
35422
|
-
|
|
35423
|
-
|
|
35424
|
-
|
|
35425
|
-
|
|
35426
|
-
);
|
|
35427
|
-
|
|
35428
|
-
|
|
35429
|
-
|
|
35430
|
-
RTV.
|
|
35431
|
-
|
|
35432
|
-
|
|
35433
|
-
|
|
35434
|
-
RTV.
|
|
35435
|
-
|
|
35436
|
-
|
|
35437
|
-
|
|
35438
|
-
|
|
35439
|
-
|
|
35440
|
-
|
|
35441
|
-
|
|
35442
|
-
|
|
35443
|
-
|
|
35444
|
-
|
|
35445
|
-
|
|
35446
|
-
} finally {
|
|
35447
|
-
rt.activeAccessors.delete(guardKey);
|
|
35448
|
-
}
|
|
35575
|
+
const methodExists = rt.cachedResolveClassMethod(firstRV.className, name) !== null;
|
|
35576
|
+
if (!methodExists) {
|
|
35577
|
+
const guardKey = `${firstRV.className}.subsref`;
|
|
35578
|
+
if (!rt.activeAccessors.has(guardKey)) {
|
|
35579
|
+
const subsrefFn = rt.cachedResolveClassMethod(
|
|
35580
|
+
firstRV.className,
|
|
35581
|
+
"subsref"
|
|
35582
|
+
);
|
|
35583
|
+
if (subsrefFn) {
|
|
35584
|
+
const remaining = args.slice(1);
|
|
35585
|
+
const sEntries = [
|
|
35586
|
+
RTV.struct({
|
|
35587
|
+
type: RTV.char("."),
|
|
35588
|
+
subs: RTV.char(name)
|
|
35589
|
+
}),
|
|
35590
|
+
RTV.struct({
|
|
35591
|
+
type: RTV.char("()"),
|
|
35592
|
+
subs: RTV.cell(
|
|
35593
|
+
remaining.map((a) => ensureRuntimeValue(a)),
|
|
35594
|
+
[1, remaining.length]
|
|
35595
|
+
)
|
|
35596
|
+
})
|
|
35597
|
+
];
|
|
35598
|
+
const S = RTV.structArray(["type", "subs"], sEntries);
|
|
35599
|
+
rt.activeAccessors.add(guardKey);
|
|
35600
|
+
try {
|
|
35601
|
+
return subsrefFn(nargout, first, S);
|
|
35602
|
+
} finally {
|
|
35603
|
+
rt.activeAccessors.delete(guardKey);
|
|
35449
35604
|
}
|
|
35450
35605
|
}
|
|
35451
35606
|
}
|
|
35452
|
-
throw e;
|
|
35453
35607
|
}
|
|
35608
|
+
return callClassMethod(rt, firstRV.className, name, nargout, args);
|
|
35454
35609
|
}
|
|
35455
35610
|
}
|
|
35456
35611
|
const builtin = rt.builtins[name];
|
|
@@ -35507,11 +35662,13 @@ function arrayfunCellfunImpl(rt, name, nargout, args) {
|
|
|
35507
35662
|
const getElem = (arr, i) => {
|
|
35508
35663
|
if (isRuntimeCell(arr)) return arr.data[i];
|
|
35509
35664
|
if (isRuntimeTensor(arr)) return arr.data[i];
|
|
35665
|
+
if (isRuntimeStructArray(arr)) return arr.elements[i];
|
|
35510
35666
|
return arr;
|
|
35511
35667
|
};
|
|
35512
35668
|
const getLen = (arr) => {
|
|
35513
35669
|
if (isRuntimeCell(arr)) return arr.data.length;
|
|
35514
35670
|
if (isRuntimeTensor(arr)) return arr.data.length;
|
|
35671
|
+
if (isRuntimeStructArray(arr)) return arr.elements.length;
|
|
35515
35672
|
return 1;
|
|
35516
35673
|
};
|
|
35517
35674
|
const collectArgs = (i) => {
|
|
@@ -35547,9 +35704,9 @@ function arrayfunCellfunImpl(rt, name, nargout, args) {
|
|
|
35547
35704
|
if (allLogical && arrArg.data.length > 0) result._isLogical = true;
|
|
35548
35705
|
return result;
|
|
35549
35706
|
}
|
|
35550
|
-
if (isRuntimeCell(arrArg) || extraInputs.length > 0 || nargout > 1) {
|
|
35707
|
+
if (isRuntimeCell(arrArg) || isRuntimeStructArray(arrArg) || extraInputs.length > 0 || nargout > 1) {
|
|
35551
35708
|
const len = getLen(arrArg);
|
|
35552
|
-
const shape = isRuntimeCell(arrArg)
|
|
35709
|
+
const shape = isRuntimeCell(arrArg) || isRuntimeTensor(arrArg) ? [...arrArg.shape] : [1, len];
|
|
35553
35710
|
if (nargout > 1) {
|
|
35554
35711
|
const allResults = Array.from(
|
|
35555
35712
|
{ length: nargout },
|
|
@@ -36770,6 +36927,28 @@ function indexStore(rt, base, indices, rhs, skipSubsasgn = false) {
|
|
|
36770
36927
|
if (isRuntimeStruct(mv)) {
|
|
36771
36928
|
return ensureRuntimeValue(rhs);
|
|
36772
36929
|
}
|
|
36930
|
+
if (indices.length === 1 && isRuntimeClassInstance(ensureRuntimeValue(rhs)) && // Object-array growth uses a numeric position. A char/string index (e.g. a
|
|
36931
|
+
// key into a containers.Map whose value happens to be a class instance)
|
|
36932
|
+
// must fall through to the subsasgn dispatch below, not be coerced to a
|
|
36933
|
+
// number — `toNumber` on a multi-char value throws.
|
|
36934
|
+
!isRuntimeChar(ensureRuntimeValue(indices[0]))) {
|
|
36935
|
+
const k = Math.round(toNumber(ensureRuntimeValue(indices[0]))) - 1;
|
|
36936
|
+
const growsArray = isRuntimeClassInstanceArray(mv) || isRuntimeTensor(mv) && mv.data.length === 0 || isRuntimeClassInstance(mv) && k >= 1;
|
|
36937
|
+
if (growsArray) {
|
|
36938
|
+
if (k < 0) throw new RuntimeError("Index must be a positive integer");
|
|
36939
|
+
const rhsInst = ensureRuntimeValue(rhs);
|
|
36940
|
+
const existing = isRuntimeClassInstanceArray(mv) ? [...mv.elements] : isRuntimeClassInstance(mv) ? [mv] : [];
|
|
36941
|
+
const className = isRuntimeClassInstanceArray(mv) ? mv.className : isRuntimeClassInstance(mv) ? mv.className : rhsInst.className;
|
|
36942
|
+
while (existing.length < k) {
|
|
36943
|
+
existing.push(
|
|
36944
|
+
RTV.classInstance(className, [...rhsInst.fields.keys()], false)
|
|
36945
|
+
);
|
|
36946
|
+
}
|
|
36947
|
+
existing[k] = rhsInst;
|
|
36948
|
+
if (existing.length === 1) return existing[0];
|
|
36949
|
+
return RTV.classInstanceArray(className, existing, [1, existing.length]);
|
|
36950
|
+
}
|
|
36951
|
+
}
|
|
36773
36952
|
if (isRuntimeClassInstance(mv)) {
|
|
36774
36953
|
const guardKey = `${mv.className}.subsasgn`;
|
|
36775
36954
|
if (!skipSubsasgn && !rt.activeAccessors.has(guardKey)) {
|
|
@@ -37190,6 +37369,11 @@ function validateDim(x) {
|
|
|
37190
37369
|
throw new RuntimeError("Size inputs must be nonnegative integers.");
|
|
37191
37370
|
return Math.max(0, x);
|
|
37192
37371
|
}
|
|
37372
|
+
function toScalarDim(v) {
|
|
37373
|
+
if (isRuntimeTensor(v) && v.data.length !== 1)
|
|
37374
|
+
throw new RuntimeError("Size inputs must be scalar.");
|
|
37375
|
+
return validateDim(toNumber(v));
|
|
37376
|
+
}
|
|
37193
37377
|
function parseShapeArgs(args) {
|
|
37194
37378
|
if (args.length === 1 && isRuntimeTensor(args[0])) {
|
|
37195
37379
|
const t = args[0];
|
|
@@ -37197,7 +37381,7 @@ function parseShapeArgs(args) {
|
|
|
37197
37381
|
for (let i = 0; i < t.data.length; i++) shape.push(validateDim(t.data[i]));
|
|
37198
37382
|
return shape;
|
|
37199
37383
|
}
|
|
37200
|
-
return args.map(
|
|
37384
|
+
return args.map(toScalarDim);
|
|
37201
37385
|
}
|
|
37202
37386
|
function arrayConstructorCases(fillFn, scalarValue, opts) {
|
|
37203
37387
|
const cases = [
|
|
@@ -37238,12 +37422,14 @@ function arrayConstructorCases(fillFn, scalarValue, opts) {
|
|
|
37238
37422
|
return fillFn(shape);
|
|
37239
37423
|
}
|
|
37240
37424
|
},
|
|
37241
|
-
// Multiple scalar args
|
|
37425
|
+
// Multiple scalar args. A 1×1 array counts as a scalar dimension, so
|
|
37426
|
+
// accept `tensor` here too (apply-time validates each is scalar).
|
|
37242
37427
|
{
|
|
37243
37428
|
match: (argTypes) => {
|
|
37244
37429
|
if (argTypes.length <= 1) return null;
|
|
37245
37430
|
for (const a of argTypes) {
|
|
37246
|
-
if (a.kind !== "number" && a.kind !== "boolean"
|
|
37431
|
+
if (a.kind !== "number" && a.kind !== "boolean" && a.kind !== "tensor")
|
|
37432
|
+
return null;
|
|
37247
37433
|
}
|
|
37248
37434
|
const shape = argTypes.map(
|
|
37249
37435
|
(a) => a.kind === "number" && typeof a.exact === "number" ? a.exact : -1
|
|
@@ -37803,6 +37989,13 @@ registerIBuiltin({
|
|
|
37803
37989
|
apply: (_args, nargout) => nargout >= 1 ? RTV.dummyHandle() : void 0
|
|
37804
37990
|
})
|
|
37805
37991
|
});
|
|
37992
|
+
registerIBuiltin({
|
|
37993
|
+
name: "waitbar",
|
|
37994
|
+
resolve: () => ({
|
|
37995
|
+
outputTypes: [{ kind: "unknown" }],
|
|
37996
|
+
apply: (_args, nargout) => nargout >= 1 ? RTV.dummyHandle() : void 0
|
|
37997
|
+
})
|
|
37998
|
+
});
|
|
37806
37999
|
registerIBuiltin({
|
|
37807
38000
|
name: "get",
|
|
37808
38001
|
resolve: () => ({
|
|
@@ -39001,6 +39194,8 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
39001
39194
|
"delete",
|
|
39002
39195
|
"rmdir",
|
|
39003
39196
|
"movefile",
|
|
39197
|
+
"copyfile",
|
|
39198
|
+
"fileattrib",
|
|
39004
39199
|
"unzip",
|
|
39005
39200
|
"dir",
|
|
39006
39201
|
"warning",
|
|
@@ -39010,6 +39205,7 @@ var SPECIAL_BUILTIN_NAMES = [
|
|
|
39010
39205
|
"userpath",
|
|
39011
39206
|
"getenv",
|
|
39012
39207
|
"setenv",
|
|
39208
|
+
"maxNumCompThreads",
|
|
39013
39209
|
"pwd",
|
|
39014
39210
|
"cd",
|
|
39015
39211
|
"ode45",
|
|
@@ -39117,8 +39313,8 @@ function registerSpecialBuiltins(rt) {
|
|
|
39117
39313
|
if (args.length === 0) return nargout >= 1 ? RTV.num(0) : void 0;
|
|
39118
39314
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
39119
39315
|
if (margs.length === 2 && isRuntimeChar(margs[0]) && isRuntimeChar(margs[1])) {
|
|
39120
|
-
const
|
|
39121
|
-
if (
|
|
39316
|
+
const mode = toString(margs[0]);
|
|
39317
|
+
if (mode === "on" || mode === "off") {
|
|
39122
39318
|
if (nargout === 0) return void 0;
|
|
39123
39319
|
return RTV.struct(
|
|
39124
39320
|
/* @__PURE__ */ new Map([
|
|
@@ -39127,6 +39323,14 @@ function registerSpecialBuiltins(rt) {
|
|
|
39127
39323
|
])
|
|
39128
39324
|
);
|
|
39129
39325
|
}
|
|
39326
|
+
if (mode === "query") {
|
|
39327
|
+
return RTV.struct(
|
|
39328
|
+
/* @__PURE__ */ new Map([
|
|
39329
|
+
["state", RTV.char("on")],
|
|
39330
|
+
["identifier", margs[1]]
|
|
39331
|
+
])
|
|
39332
|
+
);
|
|
39333
|
+
}
|
|
39130
39334
|
}
|
|
39131
39335
|
let fmtIdx = 0;
|
|
39132
39336
|
if (margs.length >= 2 && isRuntimeChar(margs[0]) && toString(margs[0]).includes(":")) {
|
|
@@ -39943,6 +40147,65 @@ function registerSpecialBuiltins(rt) {
|
|
|
39943
40147
|
RTV.char("")
|
|
39944
40148
|
];
|
|
39945
40149
|
});
|
|
40150
|
+
registerSpecial("copyfile", (nargout, args) => {
|
|
40151
|
+
const io = requireFileIO();
|
|
40152
|
+
if (!io.copyfile)
|
|
40153
|
+
throw new RuntimeError("copyfile is not available in this environment");
|
|
40154
|
+
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
40155
|
+
if (margs.length < 1)
|
|
40156
|
+
throw new RuntimeError("copyfile requires at least 1 argument");
|
|
40157
|
+
const source = toString(margs[0]);
|
|
40158
|
+
const destination = margs.length >= 2 ? toString(margs[1]) : rt.system?.cwd() ?? ".";
|
|
40159
|
+
let force = false;
|
|
40160
|
+
if (margs.length >= 3) {
|
|
40161
|
+
const third = toString(margs[2]);
|
|
40162
|
+
if (third.toLowerCase() === "f") force = true;
|
|
40163
|
+
}
|
|
40164
|
+
const ok = io.copyfile(source, destination, force);
|
|
40165
|
+
if (nargout === 0) {
|
|
40166
|
+
if (!ok)
|
|
40167
|
+
throw new RuntimeError(
|
|
40168
|
+
`copyfile: cannot copy '${source}' to '${destination}'`
|
|
40169
|
+
);
|
|
40170
|
+
return void 0;
|
|
40171
|
+
}
|
|
40172
|
+
return nargout <= 1 ? RTV.num(ok ? 1 : 0) : [
|
|
40173
|
+
RTV.num(ok ? 1 : 0),
|
|
40174
|
+
RTV.char(ok ? "" : `Cannot copy '${source}' to '${destination}'`),
|
|
40175
|
+
RTV.char("")
|
|
40176
|
+
];
|
|
40177
|
+
});
|
|
40178
|
+
registerSpecial("fileattrib", (nargout, args) => {
|
|
40179
|
+
const io = requireFileIO();
|
|
40180
|
+
if (!io.fileattrib)
|
|
40181
|
+
throw new RuntimeError("fileattrib is not available in this environment");
|
|
40182
|
+
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
40183
|
+
if (margs.length < 1)
|
|
40184
|
+
throw new RuntimeError("fileattrib requires at least 1 argument");
|
|
40185
|
+
const p2 = toString(margs[0]);
|
|
40186
|
+
const info = io.fileattrib(p2);
|
|
40187
|
+
if (nargout === 0) {
|
|
40188
|
+
if (!info)
|
|
40189
|
+
throw new RuntimeError(
|
|
40190
|
+
`fileattrib: cannot find '${p2}': No such file or directory`
|
|
40191
|
+
);
|
|
40192
|
+
return void 0;
|
|
40193
|
+
}
|
|
40194
|
+
const values = info ? RTV.struct(
|
|
40195
|
+
/* @__PURE__ */ new Map([
|
|
40196
|
+
["Name", RTV.char(info.Name)],
|
|
40197
|
+
["archive", RTV.num(0)],
|
|
40198
|
+
["system", RTV.num(0)],
|
|
40199
|
+
["hidden", RTV.num(0)],
|
|
40200
|
+
["directory", RTV.num(info.directory ? 1 : 0)],
|
|
40201
|
+
["UserRead", RTV.num(info.UserRead ? 1 : 0)],
|
|
40202
|
+
["UserWrite", RTV.num(info.UserWrite ? 1 : 0)],
|
|
40203
|
+
["UserExecute", RTV.num(info.UserExecute ? 1 : 0)]
|
|
40204
|
+
])
|
|
40205
|
+
) : RTV.char(`No such file or directory: ${p2}`);
|
|
40206
|
+
if (nargout <= 1) return RTV.num(info ? 1 : 0);
|
|
40207
|
+
return [RTV.num(info ? 1 : 0), values, RTV.char("")];
|
|
40208
|
+
});
|
|
39946
40209
|
registerSpecial("unzip", (nargout, args) => {
|
|
39947
40210
|
const io = requireFileIO();
|
|
39948
40211
|
if (!io.unzip)
|
|
@@ -40268,6 +40531,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
40268
40531
|
}
|
|
40269
40532
|
return RTV.char(sys?.getEnv(toString(args[0])) ?? "");
|
|
40270
40533
|
});
|
|
40534
|
+
registerSpecial("maxNumCompThreads", () => RTV.num(1));
|
|
40271
40535
|
registerSpecialVoid("setenv", (args) => {
|
|
40272
40536
|
const sys = rt.system;
|
|
40273
40537
|
if (args.length === 2) {
|
|
@@ -40649,6 +40913,10 @@ function _eigsImpl(rt, nargout, args) {
|
|
|
40649
40913
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
40650
40914
|
if (margs.length < 1)
|
|
40651
40915
|
throw new RuntimeError("eigs requires at least 1 argument");
|
|
40916
|
+
for (let i = 0; i < margs.length; i++) {
|
|
40917
|
+
const mi = margs[i];
|
|
40918
|
+
if (isRuntimeSparseMatrix(mi)) margs[i] = sparseToDense(mi);
|
|
40919
|
+
}
|
|
40652
40920
|
let afun = null;
|
|
40653
40921
|
let A = null;
|
|
40654
40922
|
let n;
|
|
@@ -41566,12 +41834,17 @@ function getMember(rt, base, name) {
|
|
|
41566
41834
|
`No property or method '${name}' for class '${mv.className}'`
|
|
41567
41835
|
);
|
|
41568
41836
|
}
|
|
41837
|
+
if (isRuntimeClassInstanceArray(mv)) {
|
|
41838
|
+
const values = mv.elements.map(
|
|
41839
|
+
(el) => ensureRuntimeValue(getMember(rt, el, name))
|
|
41840
|
+
);
|
|
41841
|
+
return horzcat(...values);
|
|
41842
|
+
}
|
|
41569
41843
|
return getRTValueField(mv, name);
|
|
41570
41844
|
}
|
|
41571
|
-
function getMemberDynamic(base, nameExpr) {
|
|
41572
|
-
const mv = ensureRuntimeValue(base);
|
|
41845
|
+
function getMemberDynamic(rt, base, nameExpr) {
|
|
41573
41846
|
const name = toString(ensureRuntimeValue(nameExpr));
|
|
41574
|
-
return
|
|
41847
|
+
return ensureRuntimeValue(getMember(rt, base, name));
|
|
41575
41848
|
}
|
|
41576
41849
|
function getMemberOrEmpty(base, name) {
|
|
41577
41850
|
try {
|
|
@@ -41593,7 +41866,7 @@ function setMemberReturn(rt, base, name, rhs) {
|
|
|
41593
41866
|
if (setter) {
|
|
41594
41867
|
rt.activeAccessors.add(accessorKey);
|
|
41595
41868
|
try {
|
|
41596
|
-
const result = setter(
|
|
41869
|
+
const result = setter(0, base, rhs);
|
|
41597
41870
|
return result !== void 0 ? result : base;
|
|
41598
41871
|
} finally {
|
|
41599
41872
|
rt.activeAccessors.delete(accessorKey);
|
|
@@ -41605,10 +41878,8 @@ function setMemberReturn(rt, base, name, rhs) {
|
|
|
41605
41878
|
return setRTValueField(mv, name, rhsMv, rt);
|
|
41606
41879
|
}
|
|
41607
41880
|
function setMemberDynamicReturn(rt, base, nameExpr, rhs) {
|
|
41608
|
-
const mv = ensureRuntimeValue(base);
|
|
41609
41881
|
const name = toString(ensureRuntimeValue(nameExpr));
|
|
41610
|
-
|
|
41611
|
-
return setRTValueField(mv, name, rhsMv, rt);
|
|
41882
|
+
return ensureRuntimeValue(setMemberReturn(rt, base, name, rhs));
|
|
41612
41883
|
}
|
|
41613
41884
|
function subsrefCall(rt, base, names) {
|
|
41614
41885
|
const mv = ensureRuntimeValue(base);
|
|
@@ -44257,7 +44528,7 @@ var Runtime = class _Runtime {
|
|
|
44257
44528
|
return getMember(this, base, name);
|
|
44258
44529
|
}
|
|
44259
44530
|
getMemberDynamic(base, nameExpr) {
|
|
44260
|
-
return getMemberDynamic(base, nameExpr);
|
|
44531
|
+
return getMemberDynamic(this, base, nameExpr);
|
|
44261
44532
|
}
|
|
44262
44533
|
getMemberOrEmpty(base, name) {
|
|
44263
44534
|
return getMemberOrEmpty(base, name);
|
|
@@ -45564,6 +45835,8 @@ defineBuiltin({
|
|
|
45564
45835
|
if (isRuntimeComplexNumber(v)) return v.im === 0;
|
|
45565
45836
|
if (isRuntimeTensor(v)) return imagAllZero(v.imag);
|
|
45566
45837
|
if (isRuntimeSparseMatrix(v)) return !v.pi || imagAllZero(v.pi);
|
|
45838
|
+
if (isRuntimeCell(v) || isRuntimeStruct(v) || isRuntimeStructArray(v) || isRuntimeString(v) || isRuntimeFunction(v))
|
|
45839
|
+
return false;
|
|
45567
45840
|
return true;
|
|
45568
45841
|
}
|
|
45569
45842
|
}
|
|
@@ -46035,10 +46308,79 @@ defineBuiltin({
|
|
|
46035
46308
|
name: "ischar",
|
|
46036
46309
|
cases: [anyToLogicalCase((args) => isRuntimeChar(args[0]))]
|
|
46037
46310
|
});
|
|
46311
|
+
defineBuiltin({
|
|
46312
|
+
name: "isstr",
|
|
46313
|
+
cases: [anyToLogicalCase((args) => isRuntimeChar(args[0]))]
|
|
46314
|
+
});
|
|
46038
46315
|
defineBuiltin({
|
|
46039
46316
|
name: "isstring",
|
|
46040
46317
|
cases: [anyToLogicalCase((args) => isRuntimeString(args[0]))]
|
|
46041
46318
|
});
|
|
46319
|
+
var MATLAB_KEYWORDS = /* @__PURE__ */ new Set([
|
|
46320
|
+
"break",
|
|
46321
|
+
"case",
|
|
46322
|
+
"catch",
|
|
46323
|
+
"classdef",
|
|
46324
|
+
"continue",
|
|
46325
|
+
"else",
|
|
46326
|
+
"elseif",
|
|
46327
|
+
"end",
|
|
46328
|
+
"for",
|
|
46329
|
+
"function",
|
|
46330
|
+
"global",
|
|
46331
|
+
"if",
|
|
46332
|
+
"otherwise",
|
|
46333
|
+
"parfor",
|
|
46334
|
+
"persistent",
|
|
46335
|
+
"return",
|
|
46336
|
+
"spmd",
|
|
46337
|
+
"switch",
|
|
46338
|
+
"try",
|
|
46339
|
+
"while"
|
|
46340
|
+
]);
|
|
46341
|
+
function singleRowText(v) {
|
|
46342
|
+
if (isRuntimeChar(v)) {
|
|
46343
|
+
if (v.shape && v.shape.length >= 1 && v.shape[0] > 1) return null;
|
|
46344
|
+
return v.value;
|
|
46345
|
+
}
|
|
46346
|
+
if (isRuntimeString(v)) return v;
|
|
46347
|
+
return null;
|
|
46348
|
+
}
|
|
46349
|
+
defineBuiltin({
|
|
46350
|
+
name: "isvarname",
|
|
46351
|
+
cases: [
|
|
46352
|
+
anyToLogicalCase((args) => {
|
|
46353
|
+
const s = singleRowText(args[0]);
|
|
46354
|
+
if (s === null || s.length === 0 || s.length > 63) return false;
|
|
46355
|
+
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(s)) return false;
|
|
46356
|
+
return !MATLAB_KEYWORDS.has(s);
|
|
46357
|
+
})
|
|
46358
|
+
]
|
|
46359
|
+
});
|
|
46360
|
+
defineBuiltin({
|
|
46361
|
+
name: "iskeyword",
|
|
46362
|
+
cases: [
|
|
46363
|
+
{
|
|
46364
|
+
// iskeyword() with no args returns the list of keywords (column cell).
|
|
46365
|
+
match: (argTypes) => {
|
|
46366
|
+
if (argTypes.length === 0) return [{ kind: "cell" }];
|
|
46367
|
+
if (argTypes.length === 1) return [{ kind: "boolean" }];
|
|
46368
|
+
return null;
|
|
46369
|
+
},
|
|
46370
|
+
apply: (args) => {
|
|
46371
|
+
if (args.length === 0) {
|
|
46372
|
+
const names = [...MATLAB_KEYWORDS].sort();
|
|
46373
|
+
return RTV.cell(
|
|
46374
|
+
names.map((n) => RTV.char(n)),
|
|
46375
|
+
[names.length, 1]
|
|
46376
|
+
);
|
|
46377
|
+
}
|
|
46378
|
+
const s = singleRowText(args[0]);
|
|
46379
|
+
return RTV.logical(s !== null && MATLAB_KEYWORDS.has(s));
|
|
46380
|
+
}
|
|
46381
|
+
}
|
|
46382
|
+
]
|
|
46383
|
+
});
|
|
46042
46384
|
defineBuiltin({
|
|
46043
46385
|
name: "iscell",
|
|
46044
46386
|
cases: [anyToLogicalCase((args) => isRuntimeCell(args[0]))]
|
|
@@ -46055,6 +46397,82 @@ defineBuiltin({
|
|
|
46055
46397
|
name: "issparse",
|
|
46056
46398
|
cases: [anyToLogicalCase((args) => isRuntimeSparseMatrix(args[0]))]
|
|
46057
46399
|
});
|
|
46400
|
+
defineBuiltin({
|
|
46401
|
+
name: "isobject",
|
|
46402
|
+
cases: [
|
|
46403
|
+
anyToLogicalCase(
|
|
46404
|
+
(args) => isRuntimeClassInstance(args[0]) || isRuntimeClassInstanceArray(args[0])
|
|
46405
|
+
)
|
|
46406
|
+
]
|
|
46407
|
+
});
|
|
46408
|
+
defineBuiltin({
|
|
46409
|
+
name: "isprop",
|
|
46410
|
+
help: {
|
|
46411
|
+
signatures: ["tf = isprop(obj, PropertyName)"],
|
|
46412
|
+
description: "Return logical 1 where PropertyName is a property of object obj, else 0. The result has the same size as obj. Only class objects have properties: structs (even with that field), numeric, char and other built-in types always return false. Methods are not properties."
|
|
46413
|
+
},
|
|
46414
|
+
cases: [
|
|
46415
|
+
{
|
|
46416
|
+
match: (argTypes) => {
|
|
46417
|
+
if (argTypes.length !== 2) return null;
|
|
46418
|
+
return [{ kind: "boolean" }];
|
|
46419
|
+
},
|
|
46420
|
+
apply: (args) => {
|
|
46421
|
+
const v = args[0];
|
|
46422
|
+
const nameArg = args[1];
|
|
46423
|
+
let propName = null;
|
|
46424
|
+
if (isRuntimeChar(nameArg)) propName = nameArg.value;
|
|
46425
|
+
else if (isRuntimeString(nameArg)) propName = nameArg;
|
|
46426
|
+
let answer = false;
|
|
46427
|
+
if (propName !== null) {
|
|
46428
|
+
if (isRuntimeClassInstance(v)) answer = v.fields.has(propName);
|
|
46429
|
+
else if (isRuntimeClassInstanceArray(v))
|
|
46430
|
+
answer = v.elements.length > 0 && v.elements[0].fields.has(propName);
|
|
46431
|
+
}
|
|
46432
|
+
const shape = getShape(v);
|
|
46433
|
+
const n = shape.reduce((a, b) => a * b, 1);
|
|
46434
|
+
if (n === 1) return RTV.logical(answer);
|
|
46435
|
+
const data = allocFloat64Array(n);
|
|
46436
|
+
if (answer) data.fill(1);
|
|
46437
|
+
return new RuntimeTensor(data, shape, void 0, true);
|
|
46438
|
+
}
|
|
46439
|
+
}
|
|
46440
|
+
]
|
|
46441
|
+
});
|
|
46442
|
+
defineBuiltin({
|
|
46443
|
+
name: "addprop",
|
|
46444
|
+
help: {
|
|
46445
|
+
signatures: ["p = addprop(obj, PropertyName)"],
|
|
46446
|
+
description: "Add a dynamic property named PropertyName to the dynamicprops (handle) object obj. The property can then be read and assigned via obj.PropertyName. Returns a meta.DynamicProperty describing the new property."
|
|
46447
|
+
},
|
|
46448
|
+
cases: [
|
|
46449
|
+
{
|
|
46450
|
+
match: (argTypes) => {
|
|
46451
|
+
if (argTypes.length !== 2) return null;
|
|
46452
|
+
return [{ kind: "unknown" }];
|
|
46453
|
+
},
|
|
46454
|
+
apply: (args) => {
|
|
46455
|
+
const obj = args[0];
|
|
46456
|
+
if (!isRuntimeClassInstance(obj))
|
|
46457
|
+
throw new RuntimeError(
|
|
46458
|
+
"addprop: first argument must be a dynamicprops object"
|
|
46459
|
+
);
|
|
46460
|
+
const name = toString(args[1]);
|
|
46461
|
+
if (!obj.fields.has(name)) {
|
|
46462
|
+
const empty = RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
46463
|
+
incref(empty);
|
|
46464
|
+
obj.fields.set(name, empty);
|
|
46465
|
+
}
|
|
46466
|
+
return RTV.classInstance(
|
|
46467
|
+
"meta.DynamicProperty",
|
|
46468
|
+
["Name"],
|
|
46469
|
+
true,
|
|
46470
|
+
/* @__PURE__ */ new Map([["Name", RTV.char(name)]])
|
|
46471
|
+
);
|
|
46472
|
+
}
|
|
46473
|
+
}
|
|
46474
|
+
]
|
|
46475
|
+
});
|
|
46058
46476
|
defineBuiltin({
|
|
46059
46477
|
name: "isscalar",
|
|
46060
46478
|
cases: [
|
|
@@ -46252,6 +46670,30 @@ function mkChar(value) {
|
|
|
46252
46670
|
defineBuiltin({
|
|
46253
46671
|
name: "class",
|
|
46254
46672
|
cases: [
|
|
46673
|
+
// Old-style (pre-classdef) constructor form: class(structData, 'ClassName')
|
|
46674
|
+
// builds a value-type instance whose fields are the struct's fields. The
|
|
46675
|
+
// optional class(s,'Name',parent,...) inheritance form is not supported
|
|
46676
|
+
// (returns null → "unsupported argument types").
|
|
46677
|
+
{
|
|
46678
|
+
match: (argTypes) => {
|
|
46679
|
+
if (argTypes.length !== 2) return null;
|
|
46680
|
+
if (argTypes[0].kind !== "struct") return null;
|
|
46681
|
+
const k = argTypes[1].kind;
|
|
46682
|
+
if (k !== "char" && k !== "string") return null;
|
|
46683
|
+
return [{ kind: "unknown" }];
|
|
46684
|
+
},
|
|
46685
|
+
apply: (args) => {
|
|
46686
|
+
const s = args[0];
|
|
46687
|
+
if (!isRuntimeStruct(s))
|
|
46688
|
+
throw new RuntimeError(
|
|
46689
|
+
"class: first argument must be a scalar struct"
|
|
46690
|
+
);
|
|
46691
|
+
const nameVal = args[1];
|
|
46692
|
+
const className = isRuntimeChar(nameVal) ? nameVal.value : isRuntimeString(nameVal) ? nameVal : String(nameVal);
|
|
46693
|
+
const fieldNames = [...s.fields.keys()];
|
|
46694
|
+
return RTV.classInstance(className, fieldNames, false, s.fields);
|
|
46695
|
+
}
|
|
46696
|
+
},
|
|
46255
46697
|
{
|
|
46256
46698
|
match: (argTypes) => {
|
|
46257
46699
|
if (argTypes.length !== 1) return null;
|
|
@@ -46289,6 +46731,26 @@ defineBuiltin({
|
|
|
46289
46731
|
}
|
|
46290
46732
|
]
|
|
46291
46733
|
});
|
|
46734
|
+
for (const name of ["superiorto", "inferiorto"]) {
|
|
46735
|
+
defineBuiltin({
|
|
46736
|
+
name,
|
|
46737
|
+
help: {
|
|
46738
|
+
signatures: [`${name}('Class1', 'Class2', ...)`],
|
|
46739
|
+
description: name === "superiorto" ? "Establish superior class relationship (old-style class precedence). Accepted as a no-op." : "Establish inferior class relationship (old-style class precedence). Accepted as a no-op."
|
|
46740
|
+
},
|
|
46741
|
+
cases: [
|
|
46742
|
+
{
|
|
46743
|
+
match: (argTypes) => {
|
|
46744
|
+
for (const t of argTypes) {
|
|
46745
|
+
if (t.kind !== "char" && t.kind !== "string") return null;
|
|
46746
|
+
}
|
|
46747
|
+
return [];
|
|
46748
|
+
},
|
|
46749
|
+
apply: () => void 0
|
|
46750
|
+
}
|
|
46751
|
+
]
|
|
46752
|
+
});
|
|
46753
|
+
}
|
|
46292
46754
|
function fieldnamesApply(args) {
|
|
46293
46755
|
if (args.length !== 1)
|
|
46294
46756
|
throw new RuntimeError("fieldnames requires 1 argument");
|
|
@@ -46856,7 +47318,6 @@ function anyAllApply(name, mode) {
|
|
|
46856
47318
|
if (isRuntimeComplexNumber(v)) return RTV.logical(v.re !== 0 || v.im !== 0);
|
|
46857
47319
|
if (isRuntimeTensor(v)) {
|
|
46858
47320
|
if (args.length === 1) {
|
|
46859
|
-
if (v.data.length === 0) return RTV.logical(mode === "all");
|
|
46860
47321
|
const d = firstReduceDim(v.shape);
|
|
46861
47322
|
if (d === 0) return RTV.logical(scanLogical(v.data, v.imag, mode));
|
|
46862
47323
|
return logicalAlongDim(v, d, mode);
|
|
@@ -47126,7 +47587,12 @@ function applyTextFn(v, fn) {
|
|
|
47126
47587
|
}
|
|
47127
47588
|
return RTV.cell(out, [...v.shape]);
|
|
47128
47589
|
}
|
|
47129
|
-
if (isRuntimeChar(v))
|
|
47590
|
+
if (isRuntimeChar(v)) {
|
|
47591
|
+
if (v.shape && (v.shape[0] ?? 1) > 1) {
|
|
47592
|
+
return charRowsToMatrix(valueToCharRows(v).map(fn));
|
|
47593
|
+
}
|
|
47594
|
+
return RTV.char(fn(v.value));
|
|
47595
|
+
}
|
|
47130
47596
|
if (isRuntimeString(v)) return RTV.string(fn(toString(v)));
|
|
47131
47597
|
return v;
|
|
47132
47598
|
}
|
|
@@ -47278,7 +47744,7 @@ registerIBuiltin({
|
|
|
47278
47744
|
const str = toString(args[0]);
|
|
47279
47745
|
const pat = toString(args[1]);
|
|
47280
47746
|
const rep = toString(args[2]);
|
|
47281
|
-
let flags = "
|
|
47747
|
+
let flags = "gs";
|
|
47282
47748
|
for (let i = 3; i < args.length; i++) {
|
|
47283
47749
|
const opt = toString(args[i]).toLowerCase();
|
|
47284
47750
|
if (opt === "ignorecase") flags += "i";
|
|
@@ -47642,6 +48108,38 @@ registerIBuiltin({
|
|
|
47642
48108
|
};
|
|
47643
48109
|
}
|
|
47644
48110
|
});
|
|
48111
|
+
registerIBuiltin({
|
|
48112
|
+
name: "isspace",
|
|
48113
|
+
help: {
|
|
48114
|
+
signatures: ["TF = isspace(str)"],
|
|
48115
|
+
description: "Return a logical array the same size as str, true where the character is whitespace. Numeric input is treated as Unicode code points."
|
|
48116
|
+
},
|
|
48117
|
+
resolve: (argTypes) => {
|
|
48118
|
+
if (argTypes.length !== 1) return null;
|
|
48119
|
+
const k = argTypes[0].kind;
|
|
48120
|
+
if (k !== "char" && k !== "string" && k !== "number" && k !== "boolean" && k !== "tensor") {
|
|
48121
|
+
return null;
|
|
48122
|
+
}
|
|
48123
|
+
const pred = (cp) => RE_WSPACE.test(String.fromCodePoint(cp));
|
|
48124
|
+
return {
|
|
48125
|
+
outputTypes: [{ kind: "tensor", isComplex: false, isLogical: true }],
|
|
48126
|
+
apply: (args) => {
|
|
48127
|
+
const v = args[0];
|
|
48128
|
+
if (isRuntimeChar(v)) {
|
|
48129
|
+
return logicalRowFromString(
|
|
48130
|
+
v.value,
|
|
48131
|
+
pred,
|
|
48132
|
+
v.shape ? [...v.shape] : void 0
|
|
48133
|
+
);
|
|
48134
|
+
}
|
|
48135
|
+
if (isRuntimeString(v)) return logicalRowFromString(toString(v), pred);
|
|
48136
|
+
if (isRuntimeTensor(v))
|
|
48137
|
+
return logicalFromNumericTensor(v.data, v.shape, pred);
|
|
48138
|
+
return logicalFromNumericTensor([toNumber(v)], [1, 1], pred);
|
|
48139
|
+
}
|
|
48140
|
+
};
|
|
48141
|
+
}
|
|
48142
|
+
});
|
|
47645
48143
|
registerIBuiltin({
|
|
47646
48144
|
name: "contains",
|
|
47647
48145
|
resolve: (argTypes) => {
|
|
@@ -48089,12 +48587,102 @@ registerIBuiltin({
|
|
|
48089
48587
|
};
|
|
48090
48588
|
}
|
|
48091
48589
|
});
|
|
48590
|
+
function collectRows(v) {
|
|
48591
|
+
if (isRuntimeCell(v)) {
|
|
48592
|
+
const rows = [];
|
|
48593
|
+
for (const el of v.data) rows.push(...valueToCharRows(el));
|
|
48594
|
+
return rows;
|
|
48595
|
+
}
|
|
48596
|
+
return valueToCharRows(v);
|
|
48597
|
+
}
|
|
48598
|
+
registerIBuiltin({
|
|
48599
|
+
name: "strmatch",
|
|
48600
|
+
help: {
|
|
48601
|
+
signatures: [
|
|
48602
|
+
"x = strmatch(str, strarray)",
|
|
48603
|
+
"x = strmatch(str, strarray, 'exact')"
|
|
48604
|
+
],
|
|
48605
|
+
description: "(Legacy) Find rows of STRARRAY that begin with STR, or that equal STR when 'exact' is given. Returns a column vector of matching row indices."
|
|
48606
|
+
},
|
|
48607
|
+
resolve: (argTypes) => {
|
|
48608
|
+
if (argTypes.length < 2 || argTypes.length > 3) return null;
|
|
48609
|
+
if (!isTextType(argTypes[0])) return null;
|
|
48610
|
+
const sa = argTypes[1];
|
|
48611
|
+
if (sa.kind !== "char" && sa.kind !== "string" && sa.kind !== "cell")
|
|
48612
|
+
return null;
|
|
48613
|
+
return {
|
|
48614
|
+
outputTypes: [{ kind: "tensor", isComplex: false }],
|
|
48615
|
+
apply: (args) => {
|
|
48616
|
+
const str = toString(args[0]);
|
|
48617
|
+
let rows = collectRows(args[1]);
|
|
48618
|
+
const n = rows.length === 0 ? 0 : Math.max(...rows.map((r) => r.length));
|
|
48619
|
+
rows = rows.map((r) => r.padEnd(n, " "));
|
|
48620
|
+
const exactMatch = args.length === 3;
|
|
48621
|
+
let s = str;
|
|
48622
|
+
let len = s.length;
|
|
48623
|
+
if (len > n) {
|
|
48624
|
+
return RTV.tensor(allocFloat64Array(0), [0, 1]);
|
|
48625
|
+
}
|
|
48626
|
+
if (exactMatch && len < n) {
|
|
48627
|
+
const useNull = rows.some((r) => r.charCodeAt(n - 1) === 0);
|
|
48628
|
+
s = s.padEnd(n, useNull ? "\0" : " ");
|
|
48629
|
+
len = n;
|
|
48630
|
+
}
|
|
48631
|
+
const matches2 = [];
|
|
48632
|
+
for (let r = 0; r < rows.length; r++) {
|
|
48633
|
+
let ok = true;
|
|
48634
|
+
for (let i = 0; i < len; i++) {
|
|
48635
|
+
if (rows[r][i] !== s[i]) {
|
|
48636
|
+
ok = false;
|
|
48637
|
+
break;
|
|
48638
|
+
}
|
|
48639
|
+
}
|
|
48640
|
+
if (ok) matches2.push(r + 1);
|
|
48641
|
+
}
|
|
48642
|
+
return RTV.tensor(allocFloat64Array(matches2), [matches2.length, 1]);
|
|
48643
|
+
}
|
|
48644
|
+
};
|
|
48645
|
+
}
|
|
48646
|
+
});
|
|
48647
|
+
function valueToCharRows(v) {
|
|
48648
|
+
if (isRuntimeChar(v)) {
|
|
48649
|
+
const cols = v.shape ? v.shape[1] ?? v.value.length : v.value.length;
|
|
48650
|
+
const numRows = v.shape ? v.shape[0] ?? 1 : 1;
|
|
48651
|
+
if (numRows <= 1) return [v.value];
|
|
48652
|
+
const out = [];
|
|
48653
|
+
for (let r = 0; r < numRows; r++)
|
|
48654
|
+
out.push(v.value.slice(r * cols, (r + 1) * cols));
|
|
48655
|
+
return out;
|
|
48656
|
+
}
|
|
48657
|
+
if (isRuntimeString(v)) return [v];
|
|
48658
|
+
if (isRuntimeNumber(v)) return [String.fromCharCode(Math.round(v))];
|
|
48659
|
+
if (isRuntimeTensor(v)) {
|
|
48660
|
+
const rows = v.shape.length >= 2 ? v.shape[0] ?? 1 : 1;
|
|
48661
|
+
const cols = v.shape.length >= 2 ? v.shape[1] ?? 0 : v.data.length;
|
|
48662
|
+
const out = [];
|
|
48663
|
+
for (let r = 0; r < rows; r++) {
|
|
48664
|
+
let s = "";
|
|
48665
|
+
for (let c = 0; c < cols; c++)
|
|
48666
|
+
s += String.fromCharCode(Math.round(v.data[c * rows + r]));
|
|
48667
|
+
out.push(s);
|
|
48668
|
+
}
|
|
48669
|
+
return out;
|
|
48670
|
+
}
|
|
48671
|
+
throw new RuntimeError("char: unsupported cell element type");
|
|
48672
|
+
}
|
|
48673
|
+
function charRowsToMatrix(rows) {
|
|
48674
|
+
if (rows.length === 0) return RTV.char("");
|
|
48675
|
+
const width = Math.max(...rows.map((r) => r.length));
|
|
48676
|
+
const padded = rows.map((r) => r.padEnd(width, " "));
|
|
48677
|
+
if (rows.length === 1) return RTV.char(padded[0]);
|
|
48678
|
+
return new RuntimeChar(padded.join(""), [rows.length, width]);
|
|
48679
|
+
}
|
|
48092
48680
|
registerIBuiltin({
|
|
48093
48681
|
name: "char",
|
|
48094
48682
|
resolve: (argTypes) => {
|
|
48095
48683
|
if (argTypes.length !== 1) return null;
|
|
48096
48684
|
const a = argTypes[0];
|
|
48097
|
-
if (a.kind !== "char" && a.kind !== "string" && a.kind !== "number" && a.kind !== "tensor")
|
|
48685
|
+
if (a.kind !== "char" && a.kind !== "string" && a.kind !== "number" && a.kind !== "tensor" && a.kind !== "cell")
|
|
48098
48686
|
return null;
|
|
48099
48687
|
return {
|
|
48100
48688
|
outputTypes: [{ kind: "char" }],
|
|
@@ -48111,6 +48699,11 @@ registerIBuiltin({
|
|
|
48111
48699
|
}
|
|
48112
48700
|
return RTV.char(chars.join(""));
|
|
48113
48701
|
}
|
|
48702
|
+
if (isRuntimeCell(v)) {
|
|
48703
|
+
const rows = [];
|
|
48704
|
+
for (const el of v.data) rows.push(...valueToCharRows(el));
|
|
48705
|
+
return charRowsToMatrix(rows);
|
|
48706
|
+
}
|
|
48114
48707
|
throw new RuntimeError("char: unsupported arguments");
|
|
48115
48708
|
}
|
|
48116
48709
|
};
|
|
@@ -48178,6 +48771,8 @@ registerIBuiltin({
|
|
|
48178
48771
|
if (!isTextType(argTypes[0]) || !isTextType(argTypes[1])) return null;
|
|
48179
48772
|
const outputTypes = [{ kind: "number" }];
|
|
48180
48773
|
if (nargout >= 2) outputTypes.push({ kind: "number" });
|
|
48774
|
+
if (nargout >= 3) outputTypes.push({ kind: "char" });
|
|
48775
|
+
if (nargout >= 4) outputTypes.push({ kind: "number" });
|
|
48181
48776
|
return {
|
|
48182
48777
|
outputTypes,
|
|
48183
48778
|
apply: (args, nout) => {
|
|
@@ -48187,6 +48782,7 @@ registerIBuiltin({
|
|
|
48187
48782
|
const results = [];
|
|
48188
48783
|
let strPos = 0;
|
|
48189
48784
|
let fmtPos = 0;
|
|
48785
|
+
let matchFailure = false;
|
|
48190
48786
|
while (fmtPos < fmt.length && strPos < str.length && results.length < maxCount) {
|
|
48191
48787
|
if (fmt[fmtPos] === "%") {
|
|
48192
48788
|
fmtPos++;
|
|
@@ -48198,22 +48794,34 @@ registerIBuiltin({
|
|
|
48198
48794
|
}
|
|
48199
48795
|
if (spec === "d" || spec === "i") {
|
|
48200
48796
|
const m = str.slice(strPos).match(/^[+-]?\d+/);
|
|
48201
|
-
if (!m)
|
|
48797
|
+
if (!m) {
|
|
48798
|
+
matchFailure = true;
|
|
48799
|
+
break;
|
|
48800
|
+
}
|
|
48202
48801
|
results.push(parseInt(m[0], 10));
|
|
48203
48802
|
strPos += m[0].length;
|
|
48204
48803
|
} else if (spec === "f" || spec === "e" || spec === "g") {
|
|
48205
48804
|
const m = str.slice(strPos).match(/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/);
|
|
48206
|
-
if (!m)
|
|
48805
|
+
if (!m) {
|
|
48806
|
+
matchFailure = true;
|
|
48807
|
+
break;
|
|
48808
|
+
}
|
|
48207
48809
|
results.push(parseFloat(m[0]));
|
|
48208
48810
|
strPos += m[0].length;
|
|
48209
48811
|
} else if (spec === "x") {
|
|
48210
48812
|
const m = str.slice(strPos).match(/^[+-]?[0-9a-fA-F]+/);
|
|
48211
|
-
if (!m)
|
|
48813
|
+
if (!m) {
|
|
48814
|
+
matchFailure = true;
|
|
48815
|
+
break;
|
|
48816
|
+
}
|
|
48212
48817
|
results.push(parseInt(m[0], 16));
|
|
48213
48818
|
strPos += m[0].length;
|
|
48214
48819
|
} else if (spec === "o") {
|
|
48215
48820
|
const m = str.slice(strPos).match(/^[+-]?[0-7]+/);
|
|
48216
|
-
if (!m)
|
|
48821
|
+
if (!m) {
|
|
48822
|
+
matchFailure = true;
|
|
48823
|
+
break;
|
|
48824
|
+
}
|
|
48217
48825
|
results.push(parseInt(m[0], 8));
|
|
48218
48826
|
strPos += m[0].length;
|
|
48219
48827
|
} else if (spec === "c") {
|
|
@@ -48221,7 +48829,10 @@ registerIBuiltin({
|
|
|
48221
48829
|
strPos++;
|
|
48222
48830
|
} else if (spec === "s") {
|
|
48223
48831
|
const m = str.slice(strPos).match(/^\S+/);
|
|
48224
|
-
if (!m)
|
|
48832
|
+
if (!m) {
|
|
48833
|
+
matchFailure = true;
|
|
48834
|
+
break;
|
|
48835
|
+
}
|
|
48225
48836
|
for (let ci = 0; ci < m[0].length && results.length < maxCount; ci++) {
|
|
48226
48837
|
results.push(m[0].charCodeAt(ci));
|
|
48227
48838
|
}
|
|
@@ -48231,7 +48842,10 @@ registerIBuiltin({
|
|
|
48231
48842
|
fmtPos++;
|
|
48232
48843
|
while (strPos < str.length && /\s/.test(str[strPos])) strPos++;
|
|
48233
48844
|
} else {
|
|
48234
|
-
if (str[strPos] !== fmt[fmtPos])
|
|
48845
|
+
if (str[strPos] !== fmt[fmtPos]) {
|
|
48846
|
+
matchFailure = true;
|
|
48847
|
+
break;
|
|
48848
|
+
}
|
|
48235
48849
|
strPos++;
|
|
48236
48850
|
fmtPos++;
|
|
48237
48851
|
}
|
|
@@ -48241,7 +48855,16 @@ registerIBuiltin({
|
|
|
48241
48855
|
}
|
|
48242
48856
|
const vals = results.length === 1 ? RTV.num(results[0]) : RTV.tensor(allocFloat64Array(results), [results.length, 1]);
|
|
48243
48857
|
if (nout >= 2) {
|
|
48244
|
-
|
|
48858
|
+
const out = [vals, RTV.num(results.length)];
|
|
48859
|
+
if (nout >= 3) {
|
|
48860
|
+
out.push(
|
|
48861
|
+
RTV.char(matchFailure ? "Matching failure in format." : "")
|
|
48862
|
+
);
|
|
48863
|
+
}
|
|
48864
|
+
if (nout >= 4) {
|
|
48865
|
+
out.push(RTV.num(strPos + 1));
|
|
48866
|
+
}
|
|
48867
|
+
return out;
|
|
48245
48868
|
}
|
|
48246
48869
|
return vals;
|
|
48247
48870
|
}
|
|
@@ -49652,8 +50275,34 @@ function normImplTensor(v, args) {
|
|
|
49652
50275
|
return RTV.num(maxRowSum);
|
|
49653
50276
|
}
|
|
49654
50277
|
if (p2 === 2) {
|
|
50278
|
+
let anyNaN = false;
|
|
50279
|
+
let anyInf = false;
|
|
50280
|
+
for (let i = 0; i < v.data.length; i++) {
|
|
50281
|
+
const re = v.data[i];
|
|
50282
|
+
const im = imag2 ? imag2[i] : 0;
|
|
50283
|
+
if (Number.isNaN(re) || Number.isNaN(im)) anyNaN = true;
|
|
50284
|
+
else if (!isFinite(re) || !isFinite(im)) anyInf = true;
|
|
50285
|
+
}
|
|
50286
|
+
if (anyNaN) return RTV.num(NaN);
|
|
50287
|
+
if (anyInf) return RTV.num(Infinity);
|
|
49655
50288
|
const bridge = getEffectiveBridge("norm", "svd");
|
|
49656
50289
|
if (bridge && bridge.svd) {
|
|
50290
|
+
if (imag2) {
|
|
50291
|
+
const R = allocFloat64Array(4 * rows * cols);
|
|
50292
|
+
const tm = 2 * rows;
|
|
50293
|
+
for (let j = 0; j < cols; j++) {
|
|
50294
|
+
for (let i = 0; i < rows; i++) {
|
|
50295
|
+
const a = v.data[j * rows + i];
|
|
50296
|
+
const b = imag2[j * rows + i];
|
|
50297
|
+
R[j * tm + i] = a;
|
|
50298
|
+
R[j * tm + (rows + i)] = b;
|
|
50299
|
+
R[(cols + j) * tm + i] = -b;
|
|
50300
|
+
R[(cols + j) * tm + (rows + i)] = a;
|
|
50301
|
+
}
|
|
50302
|
+
}
|
|
50303
|
+
const result2 = bridge.svd(R, tm, 2 * cols, false, false);
|
|
50304
|
+
return RTV.num(result2.S[0]);
|
|
50305
|
+
}
|
|
49657
50306
|
const f64 = v.data instanceof Float64Array ? v.data : allocFloat64Array(v.data);
|
|
49658
50307
|
const result = bridge.svd(f64, rows, cols, false, false);
|
|
49659
50308
|
return RTV.num(result.S[0]);
|
|
@@ -50413,6 +51062,100 @@ function svdApply(args, nargout) {
|
|
|
50413
51062
|
[k, 1]
|
|
50414
51063
|
);
|
|
50415
51064
|
}
|
|
51065
|
+
function nullApply(args) {
|
|
51066
|
+
let A = args[0];
|
|
51067
|
+
if (isRuntimeNumber(A) || isRuntimeComplexNumber(A)) {
|
|
51068
|
+
A = isRuntimeNumber(A) ? RTV.tensor(allocFloat64Array([A]), [1, 1]) : RTV.tensor(
|
|
51069
|
+
allocFloat64Array([A.re]),
|
|
51070
|
+
[1, 1],
|
|
51071
|
+
allocFloat64Array([A.im])
|
|
51072
|
+
);
|
|
51073
|
+
}
|
|
51074
|
+
if (!isRuntimeTensor(A))
|
|
51075
|
+
throw new RuntimeError("null: argument must be a numeric matrix");
|
|
51076
|
+
const [m, n] = tensorSize2D(A);
|
|
51077
|
+
const [, Sdiag, V] = svdApply([A], 3);
|
|
51078
|
+
const k = Math.min(m, n);
|
|
51079
|
+
const s = [];
|
|
51080
|
+
for (let i = 0; i < k; i++) s.push(Sdiag.data[colMajorIndex(i, i, m)]);
|
|
51081
|
+
const maxS = s.length > 0 ? Math.max(...s) : 0;
|
|
51082
|
+
const tol = args.length > 1 && args[1] !== void 0 ? toNumber(args[1]) : Math.max(m, n) * epsOf(maxS);
|
|
51083
|
+
let r = 0;
|
|
51084
|
+
for (const sv of s) if (sv > tol) r++;
|
|
51085
|
+
const cols = n - r;
|
|
51086
|
+
const out = allocFloat64Array(n * cols);
|
|
51087
|
+
const outImag = V.imag ? allocFloat64Array(n * cols) : void 0;
|
|
51088
|
+
for (let c = 0; c < cols; c++) {
|
|
51089
|
+
for (let i = 0; i < n; i++) {
|
|
51090
|
+
const src = colMajorIndex(i, r + c, n);
|
|
51091
|
+
out[colMajorIndex(i, c, n)] = V.data[src];
|
|
51092
|
+
if (outImag) outImag[colMajorIndex(i, c, n)] = V.imag[src];
|
|
51093
|
+
}
|
|
51094
|
+
}
|
|
51095
|
+
return RTV.tensor(out, [n, cols], outImag);
|
|
51096
|
+
}
|
|
51097
|
+
registerIBuiltin({
|
|
51098
|
+
name: "null",
|
|
51099
|
+
resolve: (argTypes, nargout) => {
|
|
51100
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2) return null;
|
|
51101
|
+
if (!isNumericJitType(argTypes[0])) return null;
|
|
51102
|
+
const isComplex = argTypes[0].kind === "tensor" && argTypes[0].isComplex;
|
|
51103
|
+
return {
|
|
51104
|
+
outputTypes: [tensorType(isComplex || void 0)],
|
|
51105
|
+
apply: (args) => nullApply(args)
|
|
51106
|
+
};
|
|
51107
|
+
}
|
|
51108
|
+
});
|
|
51109
|
+
function computeBandwidth(A) {
|
|
51110
|
+
let lower = 0;
|
|
51111
|
+
let upper = 0;
|
|
51112
|
+
const note = (i, j) => {
|
|
51113
|
+
if (i > j) lower = Math.max(lower, i - j);
|
|
51114
|
+
else if (j > i) upper = Math.max(upper, j - i);
|
|
51115
|
+
};
|
|
51116
|
+
if (isRuntimeNumber(A) || isRuntimeComplexNumber(A)) return [0, 0];
|
|
51117
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
51118
|
+
for (let j = 0; j < A.n; j++) {
|
|
51119
|
+
for (let k = A.jc[j]; k < A.jc[j + 1]; k++) {
|
|
51120
|
+
if (A.pr[k] === 0 && (!A.pi || A.pi[k] === 0)) continue;
|
|
51121
|
+
note(A.ir[k], j);
|
|
51122
|
+
}
|
|
51123
|
+
}
|
|
51124
|
+
return [lower, upper];
|
|
51125
|
+
}
|
|
51126
|
+
if (isRuntimeTensor(A)) {
|
|
51127
|
+
const [m, n] = tensorSize2D(A);
|
|
51128
|
+
for (let j = 0; j < n; j++) {
|
|
51129
|
+
for (let i = 0; i < m; i++) {
|
|
51130
|
+
const idx = colMajorIndex(i, j, m);
|
|
51131
|
+
if (A.data[idx] === 0 && (!A.imag || A.imag[idx] === 0)) continue;
|
|
51132
|
+
note(i, j);
|
|
51133
|
+
}
|
|
51134
|
+
}
|
|
51135
|
+
return [lower, upper];
|
|
51136
|
+
}
|
|
51137
|
+
throw new RuntimeError("bandwidth: first argument must be a numeric matrix");
|
|
51138
|
+
}
|
|
51139
|
+
function bandwidthApply(args, nargout) {
|
|
51140
|
+
const [lower, upper] = computeBandwidth(args[0]);
|
|
51141
|
+
if (args.length >= 2 && args[1] !== void 0) {
|
|
51142
|
+
const type = parseStringArgLower(args[1]);
|
|
51143
|
+
if (type === "lower") return RTV.num(lower);
|
|
51144
|
+
if (type === "upper") return RTV.num(upper);
|
|
51145
|
+
throw new RuntimeError("bandwidth: TYPE must be 'lower' or 'upper'");
|
|
51146
|
+
}
|
|
51147
|
+
if (nargout >= 2) return [RTV.num(lower), RTV.num(upper)];
|
|
51148
|
+
return RTV.num(lower);
|
|
51149
|
+
}
|
|
51150
|
+
registerIBuiltin({
|
|
51151
|
+
name: "bandwidth",
|
|
51152
|
+
resolve: (argTypes, nargout) => {
|
|
51153
|
+
if (nargout > 2 || argTypes.length < 1 || argTypes.length > 2) return null;
|
|
51154
|
+
if (!isNumericJitType(argTypes[0])) return null;
|
|
51155
|
+
const outs = nargout >= 2 ? [NUM, NUM] : [NUM];
|
|
51156
|
+
return { outputTypes: outs, apply: (args, n) => bandwidthApply(args, n) };
|
|
51157
|
+
}
|
|
51158
|
+
});
|
|
50416
51159
|
function computeATA(A_data, m, n) {
|
|
50417
51160
|
const result = allocFloat64Array(n * n);
|
|
50418
51161
|
for (let j = 0; j < n; j++)
|
|
@@ -52283,6 +53026,33 @@ function validateSizeArg(x) {
|
|
|
52283
53026
|
}
|
|
52284
53027
|
return x < 0 ? 0 : x;
|
|
52285
53028
|
}
|
|
53029
|
+
function parseReshapeDims(args, total) {
|
|
53030
|
+
let rawDims;
|
|
53031
|
+
if (args.length === 2 && isRuntimeTensor(args[1]) && args[1].data.length > 1) {
|
|
53032
|
+
rawDims = Array.from(args[1].data).map((x) => validateSizeArg(x));
|
|
53033
|
+
} else {
|
|
53034
|
+
rawDims = args.slice(1).map((a) => {
|
|
53035
|
+
if (isRuntimeTensor(a) && a.data.length === 0) return null;
|
|
53036
|
+
return validateSizeArg(toNumber(a));
|
|
53037
|
+
});
|
|
53038
|
+
}
|
|
53039
|
+
const autoCount = rawDims.filter((d) => d === null).length;
|
|
53040
|
+
if (autoCount > 1)
|
|
53041
|
+
throw new RuntimeError("reshape: only one dimension size can be []");
|
|
53042
|
+
let shape;
|
|
53043
|
+
if (autoCount === 1) {
|
|
53044
|
+
const known = rawDims.filter((d) => d !== null);
|
|
53045
|
+
const knownProduct = known.reduce((a, b) => a * b, 1);
|
|
53046
|
+
if (knownProduct === 0 || total % knownProduct !== 0)
|
|
53047
|
+
throw new RuntimeError("reshape: number of elements must not change");
|
|
53048
|
+
shape = rawDims.map((d) => d === null ? total / knownProduct : d);
|
|
53049
|
+
} else {
|
|
53050
|
+
shape = rawDims;
|
|
53051
|
+
}
|
|
53052
|
+
if (numel(shape) !== total)
|
|
53053
|
+
throw new RuntimeError("reshape: number of elements must not change");
|
|
53054
|
+
return shape;
|
|
53055
|
+
}
|
|
52286
53056
|
defineBuiltin({
|
|
52287
53057
|
name: "reshape",
|
|
52288
53058
|
cases: [
|
|
@@ -52294,31 +53064,31 @@ defineBuiltin({
|
|
|
52294
53064
|
const v = args[0];
|
|
52295
53065
|
if (isRuntimeSparseMatrix(v)) {
|
|
52296
53066
|
const totalEl = v.m * v.n;
|
|
52297
|
-
let
|
|
53067
|
+
let rawDims;
|
|
52298
53068
|
if (args.length === 2 && isRuntimeTensor(args[1]) && args[1].data.length > 1) {
|
|
52299
|
-
|
|
53069
|
+
rawDims = Array.from(args[1].data).map((x) => Math.round(x));
|
|
52300
53070
|
} else {
|
|
52301
|
-
|
|
53071
|
+
rawDims = args.slice(1).map((a) => {
|
|
52302
53072
|
if (isRuntimeTensor(a) && a.data.length === 0) return null;
|
|
52303
53073
|
return Math.round(toNumber(a));
|
|
52304
53074
|
});
|
|
52305
53075
|
}
|
|
52306
|
-
const
|
|
52307
|
-
if (
|
|
53076
|
+
const autoCount = rawDims.filter((d) => d === null).length;
|
|
53077
|
+
if (autoCount > 1)
|
|
52308
53078
|
throw new RuntimeError(
|
|
52309
53079
|
"reshape: only one dimension size can be []"
|
|
52310
53080
|
);
|
|
52311
53081
|
let shape2;
|
|
52312
|
-
if (
|
|
52313
|
-
const known =
|
|
53082
|
+
if (autoCount === 1) {
|
|
53083
|
+
const known = rawDims.filter((d) => d !== null);
|
|
52314
53084
|
const knownProduct = known.reduce((a, b) => a * b, 1);
|
|
52315
53085
|
if (totalEl % knownProduct !== 0)
|
|
52316
53086
|
throw new RuntimeError(
|
|
52317
53087
|
"reshape: number of elements must not change"
|
|
52318
53088
|
);
|
|
52319
|
-
shape2 =
|
|
53089
|
+
shape2 = rawDims.map((d) => d === null ? totalEl / knownProduct : d);
|
|
52320
53090
|
} else {
|
|
52321
|
-
shape2 =
|
|
53091
|
+
shape2 = rawDims;
|
|
52322
53092
|
}
|
|
52323
53093
|
if (shape2.length !== 2)
|
|
52324
53094
|
throw new RuntimeError("reshape: sparse matrices must be 2-D");
|
|
@@ -52356,40 +53126,32 @@ defineBuiltin({
|
|
|
52356
53126
|
jc[newN] = ti;
|
|
52357
53127
|
return RTV.sparseMatrix(newM, newN, ir, jc, pr, pi2);
|
|
52358
53128
|
}
|
|
53129
|
+
if (isRuntimeChar(v)) {
|
|
53130
|
+
const srcRows = v.shape ? v.shape[0] : 1;
|
|
53131
|
+
const srcCols = v.shape ? v.shape[1] ?? 0 : v.value.length;
|
|
53132
|
+
const total = v.value.length;
|
|
53133
|
+
const reqShape = parseReshapeDims(args, total);
|
|
53134
|
+
const s = [...reqShape];
|
|
53135
|
+
while (s.length > 2 && s[s.length - 1] === 1) s.pop();
|
|
53136
|
+
if (s.length > 2)
|
|
53137
|
+
throw new RuntimeError("reshape: char arrays must be 2-D");
|
|
53138
|
+
const nr = s[0];
|
|
53139
|
+
const nc = s.length >= 2 ? s[1] : 1;
|
|
53140
|
+
const linear = new Array(total);
|
|
53141
|
+
for (let j = 0; j < srcCols; j++)
|
|
53142
|
+
for (let i = 0; i < srcRows; i++)
|
|
53143
|
+
linear[j * srcRows + i] = v.value[i * srcCols + j];
|
|
53144
|
+
const chars = new Array(total);
|
|
53145
|
+
for (let j2 = 0; j2 < nc; j2++)
|
|
53146
|
+
for (let i2 = 0; i2 < nr; i2++)
|
|
53147
|
+
chars[i2 * nc + j2] = linear[j2 * nr + i2];
|
|
53148
|
+
return new RuntimeChar(chars.join(""), [nr, nc]);
|
|
53149
|
+
}
|
|
52359
53150
|
if (!isRuntimeTensor(v) && !isRuntimeNumber(v) && !isRuntimeComplexNumber(v))
|
|
52360
53151
|
throw new RuntimeError("reshape: first argument must be numeric");
|
|
52361
53152
|
const data = isRuntimeTensor(v) ? v.data : isRuntimeComplexNumber(v) ? allocFloat64Array([v.re]) : allocFloat64Array([v]);
|
|
52362
53153
|
const imag2 = isRuntimeTensor(v) ? v.imag : isRuntimeComplexNumber(v) ? allocFloat64Array([v.im]) : void 0;
|
|
52363
|
-
|
|
52364
|
-
if (args.length === 2 && isRuntimeTensor(args[1]) && args[1].data.length > 1) {
|
|
52365
|
-
rawDims = Array.from(args[1].data).map((x) => validateSizeArg(x));
|
|
52366
|
-
} else {
|
|
52367
|
-
rawDims = args.slice(1).map((a) => {
|
|
52368
|
-
if (isRuntimeTensor(a) && a.data.length === 0) return null;
|
|
52369
|
-
return validateSizeArg(toNumber(a));
|
|
52370
|
-
});
|
|
52371
|
-
}
|
|
52372
|
-
const autoCount = rawDims.filter((d) => d === null).length;
|
|
52373
|
-
if (autoCount > 1)
|
|
52374
|
-
throw new RuntimeError("reshape: only one dimension size can be []");
|
|
52375
|
-
let shape;
|
|
52376
|
-
if (autoCount === 1) {
|
|
52377
|
-
const known = rawDims.filter((d) => d !== null);
|
|
52378
|
-
const knownProduct = known.reduce((a, b) => a * b, 1);
|
|
52379
|
-
if (data.length % knownProduct !== 0)
|
|
52380
|
-
throw new RuntimeError(
|
|
52381
|
-
"reshape: number of elements must not change"
|
|
52382
|
-
);
|
|
52383
|
-
shape = rawDims.map(
|
|
52384
|
-
(d) => d === null ? data.length / knownProduct : d
|
|
52385
|
-
);
|
|
52386
|
-
} else {
|
|
52387
|
-
shape = rawDims;
|
|
52388
|
-
}
|
|
52389
|
-
const n = numel(shape);
|
|
52390
|
-
if (n !== data.length) {
|
|
52391
|
-
throw new RuntimeError("reshape: number of elements must not change");
|
|
52392
|
-
}
|
|
53154
|
+
const shape = parseReshapeDims(args, data.length);
|
|
52393
53155
|
if (isRuntimeTensor(v)) {
|
|
52394
53156
|
const dataCopy = allocFloat64Array(data);
|
|
52395
53157
|
const imagCopy = imag2 ? allocFloat64Array(imag2) : void 0;
|
|
@@ -52801,6 +53563,35 @@ defineBuiltin({
|
|
|
52801
53563
|
}
|
|
52802
53564
|
]
|
|
52803
53565
|
});
|
|
53566
|
+
function repmatObjects(v, repArgs) {
|
|
53567
|
+
const srcElements = isRuntimeClassInstanceArray(v) ? v.elements : [v];
|
|
53568
|
+
const [rows, cols] = isRuntimeClassInstanceArray(v) ? v.shape : [1, 1];
|
|
53569
|
+
const className = v.className;
|
|
53570
|
+
let reps;
|
|
53571
|
+
if (repArgs.length === 1) {
|
|
53572
|
+
const arg1 = repArgs[0];
|
|
53573
|
+
if (isRuntimeTensor(arg1)) {
|
|
53574
|
+
reps = Array.from(arg1.data).map((x) => validateSizeArg(x));
|
|
53575
|
+
} else {
|
|
53576
|
+
const n = validateSizeArg(toNumber(arg1));
|
|
53577
|
+
reps = [n, n];
|
|
53578
|
+
}
|
|
53579
|
+
} else {
|
|
53580
|
+
reps = repArgs.map((a) => validateSizeArg(toNumber(a)));
|
|
53581
|
+
}
|
|
53582
|
+
const rRep = reps[0] ?? 1;
|
|
53583
|
+
const cRep = reps.length >= 2 ? reps[1] : reps[0] ?? 1;
|
|
53584
|
+
const newRows = rows * rRep;
|
|
53585
|
+
const newCols = cols * cRep;
|
|
53586
|
+
const out = new Array(Math.max(0, newRows * newCols));
|
|
53587
|
+
for (let J = 0; J < newCols; J++) {
|
|
53588
|
+
for (let I = 0; I < newRows; I++) {
|
|
53589
|
+
const src = srcElements[I % rows + J % cols * rows];
|
|
53590
|
+
out[I + J * newRows] = copyClassInstance(src);
|
|
53591
|
+
}
|
|
53592
|
+
}
|
|
53593
|
+
return out.length === 1 ? out[0] : RTV.classInstanceArray(className, out, [newRows, newCols]);
|
|
53594
|
+
}
|
|
52804
53595
|
defineBuiltin({
|
|
52805
53596
|
name: "repmat",
|
|
52806
53597
|
cases: [
|
|
@@ -52825,6 +53616,8 @@ defineBuiltin({
|
|
|
52825
53616
|
if (args.length < 2)
|
|
52826
53617
|
throw new RuntimeError("repmat requires at least 2 arguments");
|
|
52827
53618
|
let v = args[0];
|
|
53619
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v))
|
|
53620
|
+
return repmatObjects(v, args.slice(1));
|
|
52828
53621
|
if (isRuntimeSparseMatrix(v)) v = sparseToDense(v);
|
|
52829
53622
|
let reps;
|
|
52830
53623
|
if (args.length === 2) {
|
|
@@ -52989,6 +53782,62 @@ defineBuiltin({
|
|
|
52989
53782
|
}
|
|
52990
53783
|
]
|
|
52991
53784
|
});
|
|
53785
|
+
function copyClassInstance(inst) {
|
|
53786
|
+
if (inst.isHandleClass) return inst;
|
|
53787
|
+
return new RuntimeClassInstance(
|
|
53788
|
+
inst.className,
|
|
53789
|
+
new Map(inst.fields),
|
|
53790
|
+
inst.isHandleClass,
|
|
53791
|
+
inst._builtinData
|
|
53792
|
+
);
|
|
53793
|
+
}
|
|
53794
|
+
function repelemObjects(v, repArgs) {
|
|
53795
|
+
const srcElements = isRuntimeClassInstanceArray(v) ? v.elements : [v];
|
|
53796
|
+
const [rows, cols] = isRuntimeClassInstanceArray(v) ? v.shape : [1, 1];
|
|
53797
|
+
const className = v.className;
|
|
53798
|
+
const wrap = (elements, shape) => elements.length === 1 ? elements[0] : RTV.classInstanceArray(className, elements, shape);
|
|
53799
|
+
if (repArgs.length === 1) {
|
|
53800
|
+
const repArg = repArgs[0];
|
|
53801
|
+
if (isRuntimeTensor(repArg) && repArg.data.length > 1) {
|
|
53802
|
+
const counts = repArg.data;
|
|
53803
|
+
if (counts.length !== srcElements.length)
|
|
53804
|
+
throw new RuntimeError(
|
|
53805
|
+
`repelem: counts vector length (${counts.length}) must match the number of elements (${srcElements.length})`
|
|
53806
|
+
);
|
|
53807
|
+
const out3 = [];
|
|
53808
|
+
for (let i = 0; i < srcElements.length; i++) {
|
|
53809
|
+
const c = Math.max(0, Math.round(counts[i]));
|
|
53810
|
+
for (let j = 0; j < c; j++) out3.push(copyClassInstance(srcElements[i]));
|
|
53811
|
+
}
|
|
53812
|
+
const isCol2 = cols === 1 && rows !== 1;
|
|
53813
|
+
return wrap(out3, isCol2 ? [out3.length, 1] : [1, out3.length]);
|
|
53814
|
+
}
|
|
53815
|
+
const n = Math.max(0, Math.round(toNumber(repArg)));
|
|
53816
|
+
const out2 = [];
|
|
53817
|
+
for (const el of srcElements)
|
|
53818
|
+
for (let j = 0; j < n; j++) out2.push(copyClassInstance(el));
|
|
53819
|
+
const isCol = cols === 1 && rows !== 1;
|
|
53820
|
+
return wrap(out2, isCol ? [out2.length, 1] : [1, out2.length]);
|
|
53821
|
+
}
|
|
53822
|
+
const rRep = Math.max(0, Math.round(toNumber(repArgs[0])));
|
|
53823
|
+
const cRep = Math.max(0, Math.round(toNumber(repArgs[1])));
|
|
53824
|
+
const newRows = rows * rRep;
|
|
53825
|
+
const newCols = cols * cRep;
|
|
53826
|
+
const out = new Array(newRows * newCols);
|
|
53827
|
+
for (let c = 0; c < cols; c++) {
|
|
53828
|
+
for (let r = 0; r < rows; r++) {
|
|
53829
|
+
const src = srcElements[c * rows + r];
|
|
53830
|
+
for (let dc = 0; dc < cRep; dc++) {
|
|
53831
|
+
for (let dr = 0; dr < rRep; dr++) {
|
|
53832
|
+
const dstRow = r * rRep + dr;
|
|
53833
|
+
const dstCol = c * cRep + dc;
|
|
53834
|
+
out[dstCol * newRows + dstRow] = copyClassInstance(src);
|
|
53835
|
+
}
|
|
53836
|
+
}
|
|
53837
|
+
}
|
|
53838
|
+
}
|
|
53839
|
+
return wrap(out, [newRows, newCols]);
|
|
53840
|
+
}
|
|
52992
53841
|
defineBuiltin({
|
|
52993
53842
|
name: "repelem",
|
|
52994
53843
|
cases: [
|
|
@@ -52998,6 +53847,8 @@ defineBuiltin({
|
|
|
52998
53847
|
if (args.length < 2)
|
|
52999
53848
|
throw new RuntimeError("repelem requires at least 2 arguments");
|
|
53000
53849
|
const v = args[0];
|
|
53850
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v))
|
|
53851
|
+
return repelemObjects(v, args.slice(1));
|
|
53001
53852
|
if (args.length === 2) {
|
|
53002
53853
|
const repArg = args[1];
|
|
53003
53854
|
if (isRuntimeTensor(repArg) && repArg.data.length > 1) {
|
|
@@ -53120,7 +53971,15 @@ defineBuiltin({
|
|
|
53120
53971
|
}
|
|
53121
53972
|
return RTV.tensor(dataCopy, newShape, imagCopy);
|
|
53122
53973
|
}
|
|
53123
|
-
|
|
53974
|
+
if (isRuntimeCell(v)) {
|
|
53975
|
+
const shape = [...v.shape];
|
|
53976
|
+
while (shape.length > 2 && shape[shape.length - 1] === 1) shape.pop();
|
|
53977
|
+
if (shape.length <= 2) return RTV.cell(v.data, shape);
|
|
53978
|
+
const newShape = shape.filter((d) => d !== 1);
|
|
53979
|
+
while (newShape.length < 2) newShape.push(1);
|
|
53980
|
+
return RTV.cell(v.data, newShape);
|
|
53981
|
+
}
|
|
53982
|
+
return v;
|
|
53124
53983
|
}
|
|
53125
53984
|
}
|
|
53126
53985
|
]
|
|
@@ -53790,6 +54649,8 @@ defineBuiltin({
|
|
|
53790
54649
|
]
|
|
53791
54650
|
});
|
|
53792
54651
|
function bitwiseOp(a, b, op, name) {
|
|
54652
|
+
if (typeof a === "boolean") a = a ? 1 : 0;
|
|
54653
|
+
if (typeof b === "boolean") b = b ? 1 : 0;
|
|
53793
54654
|
if (isRuntimeNumber(a) && isRuntimeNumber(b)) {
|
|
53794
54655
|
return RTV.num(op(Math.round(a), Math.round(b)));
|
|
53795
54656
|
}
|
|
@@ -56057,6 +56918,56 @@ defineBuiltin({
|
|
|
56057
56918
|
}
|
|
56058
56919
|
]
|
|
56059
56920
|
});
|
|
56921
|
+
function froundArray(src) {
|
|
56922
|
+
const out = allocFloat64Array(src.length);
|
|
56923
|
+
for (let i = 0; i < src.length; i++) out[i] = Math.fround(src[i]);
|
|
56924
|
+
return out;
|
|
56925
|
+
}
|
|
56926
|
+
function singleApply(v) {
|
|
56927
|
+
if (isRuntimeChar(v)) {
|
|
56928
|
+
if (v.value.length === 0) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
56929
|
+
if (v.value.length === 1)
|
|
56930
|
+
return RTV.num(Math.fround(v.value.charCodeAt(0)));
|
|
56931
|
+
return RTV.row(Array.from(v.value).map((c) => Math.fround(c.charCodeAt(0))));
|
|
56932
|
+
}
|
|
56933
|
+
if (isRuntimeLogical(v)) return RTV.num(v ? 1 : 0);
|
|
56934
|
+
if (isRuntimeNumber(v)) return RTV.num(Math.fround(v));
|
|
56935
|
+
if (isRuntimeComplexNumber(v))
|
|
56936
|
+
return RTV.complex(Math.fround(v.re), Math.fround(v.im));
|
|
56937
|
+
if (isRuntimeTensor(v)) {
|
|
56938
|
+
const imag2 = v.imag ? froundArray(v.imag) : void 0;
|
|
56939
|
+
return RTV.tensor(froundArray(v.data), v.shape.slice(), imag2);
|
|
56940
|
+
}
|
|
56941
|
+
if (isRuntimeClassInstance(v) && v._builtinData !== void 0)
|
|
56942
|
+
return singleApply(v._builtinData);
|
|
56943
|
+
return RTV.num(Math.fround(toNumber(v)));
|
|
56944
|
+
}
|
|
56945
|
+
defineBuiltin({
|
|
56946
|
+
name: "single",
|
|
56947
|
+
cases: [
|
|
56948
|
+
{
|
|
56949
|
+
match: (argTypes) => {
|
|
56950
|
+
if (argTypes.length !== 1) return null;
|
|
56951
|
+
const a = argTypes[0];
|
|
56952
|
+
if (a.kind === "number" || a.kind === "boolean" || a.kind === "char" || a.kind === "class_instance")
|
|
56953
|
+
return [{ kind: "number" }];
|
|
56954
|
+
if (a.kind === "complex_or_number")
|
|
56955
|
+
return [{ kind: "complex_or_number" }];
|
|
56956
|
+
if (a.kind === "tensor")
|
|
56957
|
+
return [
|
|
56958
|
+
{
|
|
56959
|
+
kind: "tensor",
|
|
56960
|
+
isComplex: a.isComplex,
|
|
56961
|
+
shape: a.shape,
|
|
56962
|
+
ndim: a.ndim
|
|
56963
|
+
}
|
|
56964
|
+
];
|
|
56965
|
+
return null;
|
|
56966
|
+
},
|
|
56967
|
+
apply: (args) => singleApply(args[0])
|
|
56968
|
+
}
|
|
56969
|
+
]
|
|
56970
|
+
});
|
|
56060
56971
|
var INT_RANGES = [
|
|
56061
56972
|
{ name: "int8", min: -128, max: 127 },
|
|
56062
56973
|
{ name: "int16", min: -32768, max: 32767 },
|
|
@@ -56611,11 +57522,20 @@ defineBuiltin({
|
|
|
56611
57522
|
},
|
|
56612
57523
|
apply: (args) => {
|
|
56613
57524
|
const v = args[0];
|
|
56614
|
-
|
|
56615
|
-
|
|
56616
|
-
|
|
56617
|
-
return
|
|
56618
|
-
|
|
57525
|
+
const hasField = (name) => {
|
|
57526
|
+
if (isRuntimeStructArray(v)) return v.fieldNames.includes(name);
|
|
57527
|
+
if (!isRuntimeStruct(v) && !isRuntimeClassInstance(v)) return false;
|
|
57528
|
+
return v.fields.has(name);
|
|
57529
|
+
};
|
|
57530
|
+
if (isRuntimeCell(args[1])) {
|
|
57531
|
+
const cell = args[1];
|
|
57532
|
+
const result = allocFloat64Array(cell.data.length);
|
|
57533
|
+
for (let i = 0; i < cell.data.length; i++) {
|
|
57534
|
+
result[i] = hasField(toString(cell.data[i])) ? 1 : 0;
|
|
57535
|
+
}
|
|
57536
|
+
return new RuntimeTensor(result, cell.shape.slice(), void 0, true);
|
|
57537
|
+
}
|
|
57538
|
+
return RTV.logical(hasField(toString(args[1])));
|
|
56619
57539
|
}
|
|
56620
57540
|
}
|
|
56621
57541
|
]
|
|
@@ -56732,7 +57652,7 @@ function regexpImpl(caseSensitive, name, args, nargout) {
|
|
|
56732
57652
|
if (outModes.length === 0) {
|
|
56733
57653
|
outModes.push("start", "end", "tokenextents", "match", "tokens", "names");
|
|
56734
57654
|
}
|
|
56735
|
-
const flags = caseSensitive ? "
|
|
57655
|
+
const flags = caseSensitive ? "gs" : "gis";
|
|
56736
57656
|
const re = new RegExp(pat, flags);
|
|
56737
57657
|
const starts = [];
|
|
56738
57658
|
const ends = [];
|
|
@@ -57452,6 +58372,13 @@ registerIBuiltin({
|
|
|
57452
58372
|
if (args.length === 1) return RTV.cell([A], [1, 1]);
|
|
57453
58373
|
A = RTV.tensor(allocFloat64Array([A ? 1 : 0]), [1, 1]);
|
|
57454
58374
|
}
|
|
58375
|
+
if (isRuntimeStruct(A)) {
|
|
58376
|
+
return RTV.cell([A], [1, 1]);
|
|
58377
|
+
}
|
|
58378
|
+
if (isRuntimeStructArray(A)) {
|
|
58379
|
+
const elems = A.elements;
|
|
58380
|
+
return RTV.cell([...elems], [1, elems.length]);
|
|
58381
|
+
}
|
|
57455
58382
|
if (!isRuntimeTensor(A))
|
|
57456
58383
|
throw new RuntimeError(
|
|
57457
58384
|
"num2cell: first argument must be a numeric array"
|
|
@@ -57575,6 +58502,69 @@ registerIBuiltin({
|
|
|
57575
58502
|
};
|
|
57576
58503
|
}
|
|
57577
58504
|
});
|
|
58505
|
+
registerIBuiltin({
|
|
58506
|
+
name: "getfield",
|
|
58507
|
+
resolve: (argTypes) => {
|
|
58508
|
+
if (argTypes.length < 2) return null;
|
|
58509
|
+
return {
|
|
58510
|
+
outputTypes: [{ kind: "unknown" }],
|
|
58511
|
+
apply: (args) => {
|
|
58512
|
+
let v = args[0];
|
|
58513
|
+
for (let i = 1; i < args.length; i++) {
|
|
58514
|
+
if (isRuntimeCell(args[i]))
|
|
58515
|
+
throw new RuntimeError(
|
|
58516
|
+
"getfield: index ({}) subscripts are not supported"
|
|
58517
|
+
);
|
|
58518
|
+
if (!isRuntimeStruct(v))
|
|
58519
|
+
throw new RuntimeError("getfield: argument must be a structure");
|
|
58520
|
+
const name = toString(args[i]);
|
|
58521
|
+
if (!v.fields.has(name))
|
|
58522
|
+
throw new RuntimeError(
|
|
58523
|
+
`Reference to non-existent field '${name}'.`
|
|
58524
|
+
);
|
|
58525
|
+
v = v.fields.get(name);
|
|
58526
|
+
}
|
|
58527
|
+
return v;
|
|
58528
|
+
}
|
|
58529
|
+
};
|
|
58530
|
+
}
|
|
58531
|
+
});
|
|
58532
|
+
registerIBuiltin({
|
|
58533
|
+
name: "setfield",
|
|
58534
|
+
resolve: (argTypes) => {
|
|
58535
|
+
if (argTypes.length < 3) return null;
|
|
58536
|
+
return {
|
|
58537
|
+
outputTypes: [{ kind: "struct", fields: {} }],
|
|
58538
|
+
apply: (args) => {
|
|
58539
|
+
const value = args[args.length - 1];
|
|
58540
|
+
const fieldArgs = args.slice(1, args.length - 1);
|
|
58541
|
+
const setChain = (s, depth) => {
|
|
58542
|
+
const fa = fieldArgs[depth];
|
|
58543
|
+
if (isRuntimeCell(fa))
|
|
58544
|
+
throw new RuntimeError(
|
|
58545
|
+
"setfield: index ({}) subscripts are not supported"
|
|
58546
|
+
);
|
|
58547
|
+
const name = toString(fa);
|
|
58548
|
+
const base = isRuntimeStruct(s) ? s.fields : /* @__PURE__ */ new Map();
|
|
58549
|
+
if (!isRuntimeStruct(s) && !(isRuntimeTensor(s) && s.data.length === 0))
|
|
58550
|
+
throw new RuntimeError("setfield: argument must be a structure");
|
|
58551
|
+
const newFields = new Map(base);
|
|
58552
|
+
if (depth === fieldArgs.length - 1) {
|
|
58553
|
+
newFields.set(name, value);
|
|
58554
|
+
} else {
|
|
58555
|
+
const child = newFields.get(name);
|
|
58556
|
+
newFields.set(
|
|
58557
|
+
name,
|
|
58558
|
+
setChain(child ?? RTV.struct(/* @__PURE__ */ new Map()), depth + 1)
|
|
58559
|
+
);
|
|
58560
|
+
}
|
|
58561
|
+
return RTV.struct(newFields);
|
|
58562
|
+
};
|
|
58563
|
+
return setChain(args[0], 0);
|
|
58564
|
+
}
|
|
58565
|
+
};
|
|
58566
|
+
}
|
|
58567
|
+
});
|
|
57578
58568
|
registerIBuiltin({
|
|
57579
58569
|
name: "namedargs2cell",
|
|
57580
58570
|
resolve: (argTypes) => {
|
|
@@ -57596,6 +58586,10 @@ registerIBuiltin({
|
|
|
57596
58586
|
};
|
|
57597
58587
|
}
|
|
57598
58588
|
});
|
|
58589
|
+
function rmfieldNames(arg) {
|
|
58590
|
+
if (isRuntimeCell(arg)) return arg.data.map(toString);
|
|
58591
|
+
return [toString(arg)];
|
|
58592
|
+
}
|
|
57599
58593
|
registerIBuiltin({
|
|
57600
58594
|
name: "rmfield",
|
|
57601
58595
|
resolve: (argTypes) => {
|
|
@@ -57604,25 +58598,26 @@ registerIBuiltin({
|
|
|
57604
58598
|
outputTypes: [{ kind: "struct", fields: {} }],
|
|
57605
58599
|
apply: (args) => {
|
|
57606
58600
|
const v = args[0];
|
|
58601
|
+
const names = rmfieldNames(args[1]);
|
|
57607
58602
|
if (isRuntimeStructArray(v)) {
|
|
57608
|
-
const
|
|
57609
|
-
|
|
57610
|
-
|
|
57611
|
-
const newFieldNames = v.fieldNames.filter((n) => n
|
|
58603
|
+
for (const name of names)
|
|
58604
|
+
if (!v.fieldNames.includes(name))
|
|
58605
|
+
throw new RuntimeError(`rmfield: field '${name}' does not exist`);
|
|
58606
|
+
const newFieldNames = v.fieldNames.filter((n) => !names.includes(n));
|
|
57612
58607
|
const newElements = v.elements.map((el) => {
|
|
57613
58608
|
const newFields2 = new Map(el.fields);
|
|
57614
|
-
newFields2.delete(
|
|
58609
|
+
for (const name of names) newFields2.delete(name);
|
|
57615
58610
|
return RTV.struct(newFields2);
|
|
57616
58611
|
});
|
|
57617
58612
|
return RTV.structArray(newFieldNames, newElements);
|
|
57618
58613
|
}
|
|
57619
58614
|
if (!isRuntimeStruct(v))
|
|
57620
58615
|
throw new RuntimeError("rmfield: first argument must be a struct");
|
|
57621
|
-
const name
|
|
57622
|
-
|
|
57623
|
-
|
|
58616
|
+
for (const name of names)
|
|
58617
|
+
if (!v.fields.has(name))
|
|
58618
|
+
throw new RuntimeError(`rmfield: field '${name}' does not exist`);
|
|
57624
58619
|
const newFields = new Map(v.fields);
|
|
57625
|
-
newFields.delete(name);
|
|
58620
|
+
for (const name of names) newFields.delete(name);
|
|
57626
58621
|
return RTV.struct(newFields);
|
|
57627
58622
|
}
|
|
57628
58623
|
};
|
|
@@ -57843,6 +58838,23 @@ registerIBuiltin({
|
|
|
57843
58838
|
}
|
|
57844
58839
|
})
|
|
57845
58840
|
});
|
|
58841
|
+
registerIBuiltin({
|
|
58842
|
+
name: "spalloc",
|
|
58843
|
+
resolve: () => ({
|
|
58844
|
+
outputTypes: [{ kind: "unknown" }],
|
|
58845
|
+
apply: (args) => {
|
|
58846
|
+
const m = args.length >= 1 ? Math.round(toNumber(args[0])) : 0;
|
|
58847
|
+
const n = args.length >= 2 ? Math.round(toNumber(args[1])) : 0;
|
|
58848
|
+
return RTV.sparseMatrix(
|
|
58849
|
+
m,
|
|
58850
|
+
n,
|
|
58851
|
+
new Int32Array(0),
|
|
58852
|
+
new Int32Array(n + 1),
|
|
58853
|
+
allocFloat64Array(0)
|
|
58854
|
+
);
|
|
58855
|
+
}
|
|
58856
|
+
})
|
|
58857
|
+
});
|
|
57846
58858
|
registerIBuiltin({
|
|
57847
58859
|
name: "speye",
|
|
57848
58860
|
resolve: () => ({
|
|
@@ -58128,6 +59140,598 @@ registerIBuiltin({
|
|
|
58128
59140
|
}
|
|
58129
59141
|
})
|
|
58130
59142
|
});
|
|
59143
|
+
var SPPARMS_KEYS = [
|
|
59144
|
+
"spumoni",
|
|
59145
|
+
"thr_rel",
|
|
59146
|
+
"thr_abs",
|
|
59147
|
+
"exact_d",
|
|
59148
|
+
"supernd",
|
|
59149
|
+
"rreduce",
|
|
59150
|
+
"wh_frac",
|
|
59151
|
+
"autommd",
|
|
59152
|
+
"autoamd",
|
|
59153
|
+
"piv_tol",
|
|
59154
|
+
"bandden",
|
|
59155
|
+
"umfpack",
|
|
59156
|
+
"sym_tol",
|
|
59157
|
+
"ldl_tol",
|
|
59158
|
+
"usema57",
|
|
59159
|
+
"spqrtol",
|
|
59160
|
+
"sp_ctor",
|
|
59161
|
+
"reorder",
|
|
59162
|
+
"no_redo"
|
|
59163
|
+
];
|
|
59164
|
+
var SPPARMS_DEFAULTS = [
|
|
59165
|
+
0,
|
|
59166
|
+
1.1,
|
|
59167
|
+
1,
|
|
59168
|
+
0,
|
|
59169
|
+
3,
|
|
59170
|
+
3,
|
|
59171
|
+
0.5,
|
|
59172
|
+
1,
|
|
59173
|
+
1,
|
|
59174
|
+
0.1,
|
|
59175
|
+
0.5,
|
|
59176
|
+
1,
|
|
59177
|
+
1e-3,
|
|
59178
|
+
0.01,
|
|
59179
|
+
1,
|
|
59180
|
+
-2,
|
|
59181
|
+
0,
|
|
59182
|
+
0,
|
|
59183
|
+
0
|
|
59184
|
+
];
|
|
59185
|
+
var spparmsState = Float64Array.from(SPPARMS_DEFAULTS);
|
|
59186
|
+
function spparmsVector() {
|
|
59187
|
+
return RTV.tensor(allocFloat64Array(Array.from(spparmsState)), [
|
|
59188
|
+
spparmsState.length,
|
|
59189
|
+
1
|
|
59190
|
+
]);
|
|
59191
|
+
}
|
|
59192
|
+
registerIBuiltin({
|
|
59193
|
+
name: "spparms",
|
|
59194
|
+
resolve: (argTypes, nargout) => {
|
|
59195
|
+
if (argTypes.length > 2) return null;
|
|
59196
|
+
const tensorOut = { kind: "tensor", isComplex: false };
|
|
59197
|
+
const outputTypes = nargout >= 2 ? [{ kind: "char" }, tensorOut] : [tensorOut];
|
|
59198
|
+
return {
|
|
59199
|
+
outputTypes,
|
|
59200
|
+
apply: (args, n) => {
|
|
59201
|
+
if (args.length === 0) {
|
|
59202
|
+
if (n >= 2) {
|
|
59203
|
+
const width = Math.max(...SPPARMS_KEYS.map((k) => k.length));
|
|
59204
|
+
const padded = SPPARMS_KEYS.map((k) => k.padEnd(width)).join("");
|
|
59205
|
+
return [
|
|
59206
|
+
new RuntimeChar(padded, [SPPARMS_KEYS.length, width]),
|
|
59207
|
+
spparmsVector()
|
|
59208
|
+
];
|
|
59209
|
+
}
|
|
59210
|
+
return spparmsVector();
|
|
59211
|
+
}
|
|
59212
|
+
const first = args[0];
|
|
59213
|
+
if (isRuntimeChar(first) || isRuntimeString(first)) {
|
|
59214
|
+
const key = parseStringArgLower(first);
|
|
59215
|
+
if (args.length >= 2) {
|
|
59216
|
+
const idx2 = SPPARMS_KEYS.indexOf(key);
|
|
59217
|
+
if (idx2 >= 0) spparmsState[idx2] = toNumber(args[1]);
|
|
59218
|
+
return RTV.num(0);
|
|
59219
|
+
}
|
|
59220
|
+
if (key === "default") {
|
|
59221
|
+
spparmsState = Float64Array.from(SPPARMS_DEFAULTS);
|
|
59222
|
+
return RTV.num(0);
|
|
59223
|
+
}
|
|
59224
|
+
if (key === "tight") {
|
|
59225
|
+
return RTV.num(0);
|
|
59226
|
+
}
|
|
59227
|
+
const idx = SPPARMS_KEYS.indexOf(key);
|
|
59228
|
+
if (idx >= 0) return RTV.num(spparmsState[idx]);
|
|
59229
|
+
throw new RuntimeError(`spparms: unknown parameter '${key}'`);
|
|
59230
|
+
}
|
|
59231
|
+
const vals = isRuntimeNumber(first) ? [first] : isRuntimeTensor(first) ? Array.from(first.data) : null;
|
|
59232
|
+
if (vals === null)
|
|
59233
|
+
throw new RuntimeError(
|
|
59234
|
+
"spparms: argument must be a parameter name or value vector"
|
|
59235
|
+
);
|
|
59236
|
+
const next = Float64Array.from(spparmsState);
|
|
59237
|
+
for (let i = 0; i < Math.min(vals.length, next.length); i++)
|
|
59238
|
+
next[i] = vals[i];
|
|
59239
|
+
spparmsState = next;
|
|
59240
|
+
return RTV.num(0);
|
|
59241
|
+
}
|
|
59242
|
+
};
|
|
59243
|
+
}
|
|
59244
|
+
});
|
|
59245
|
+
|
|
59246
|
+
// src/numbl-core/interpreter/builtins/graph.ts
|
|
59247
|
+
function isGraph(v) {
|
|
59248
|
+
return isRuntimeClassInstance(v) && v.className === "graph";
|
|
59249
|
+
}
|
|
59250
|
+
function requireGraph(v, fn) {
|
|
59251
|
+
if (!isGraph(v)) {
|
|
59252
|
+
throw new RuntimeError(`${fn}: first argument must be a graph`);
|
|
59253
|
+
}
|
|
59254
|
+
return v;
|
|
59255
|
+
}
|
|
59256
|
+
function graphN(g) {
|
|
59257
|
+
return toNumber(g.fields.get("_n") ?? 0);
|
|
59258
|
+
}
|
|
59259
|
+
function graphWeighted(g) {
|
|
59260
|
+
const w = g.fields.get("_weighted");
|
|
59261
|
+
return w === true;
|
|
59262
|
+
}
|
|
59263
|
+
function graphAdj(g) {
|
|
59264
|
+
const a = g.fields.get("_A");
|
|
59265
|
+
if (a === void 0 || !isRuntimeSparseMatrix(a)) {
|
|
59266
|
+
throw new RuntimeError("graph: corrupt internal adjacency");
|
|
59267
|
+
}
|
|
59268
|
+
return a;
|
|
59269
|
+
}
|
|
59270
|
+
function buildSymAdj(n, edges) {
|
|
59271
|
+
const triplets = [];
|
|
59272
|
+
for (const e of edges) {
|
|
59273
|
+
if (e.w === 0) continue;
|
|
59274
|
+
const u = e.u - 1;
|
|
59275
|
+
const v = e.v - 1;
|
|
59276
|
+
if (u === v) {
|
|
59277
|
+
triplets.push({ col: u, row: u, val: e.w });
|
|
59278
|
+
} else {
|
|
59279
|
+
triplets.push({ col: v, row: u, val: e.w });
|
|
59280
|
+
triplets.push({ col: u, row: v, val: e.w });
|
|
59281
|
+
}
|
|
59282
|
+
}
|
|
59283
|
+
triplets.sort((a, b) => a.col - b.col || a.row - b.row);
|
|
59284
|
+
const ir = [];
|
|
59285
|
+
const pr = [];
|
|
59286
|
+
const cols = [];
|
|
59287
|
+
let prevCol = -1;
|
|
59288
|
+
let prevRow = -1;
|
|
59289
|
+
for (const t of triplets) {
|
|
59290
|
+
if (t.col === prevCol && t.row === prevRow) {
|
|
59291
|
+
pr[pr.length - 1] += t.val;
|
|
59292
|
+
} else {
|
|
59293
|
+
ir.push(t.row);
|
|
59294
|
+
pr.push(t.val);
|
|
59295
|
+
cols.push(t.col);
|
|
59296
|
+
prevCol = t.col;
|
|
59297
|
+
prevRow = t.row;
|
|
59298
|
+
}
|
|
59299
|
+
}
|
|
59300
|
+
const jc = new Int32Array(n + 1);
|
|
59301
|
+
let ci = 0;
|
|
59302
|
+
for (let c = 0; c < n; c++) {
|
|
59303
|
+
jc[c] = ci;
|
|
59304
|
+
while (ci < cols.length && cols[ci] === c) ci++;
|
|
59305
|
+
}
|
|
59306
|
+
jc[n] = ci;
|
|
59307
|
+
return RTV.sparseMatrix(n, n, new Int32Array(ir), jc, allocFloat64Array(pr));
|
|
59308
|
+
}
|
|
59309
|
+
function makeGraph(n, edges, weighted) {
|
|
59310
|
+
const fields = /* @__PURE__ */ new Map();
|
|
59311
|
+
fields.set("_n", n);
|
|
59312
|
+
fields.set("_A", buildSymAdj(n, edges));
|
|
59313
|
+
fields.set("_weighted", weighted);
|
|
59314
|
+
return new RuntimeClassInstance("graph", fields, false);
|
|
59315
|
+
}
|
|
59316
|
+
function eachNeighbor(A, c, cb) {
|
|
59317
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) {
|
|
59318
|
+
const r = A.ir[k];
|
|
59319
|
+
if (r !== c) cb(r, A.pr[k]);
|
|
59320
|
+
}
|
|
59321
|
+
}
|
|
59322
|
+
function edgesFromAdj(A) {
|
|
59323
|
+
const edges = [];
|
|
59324
|
+
for (let c = 0; c < A.n; c++) {
|
|
59325
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) {
|
|
59326
|
+
const r = A.ir[k];
|
|
59327
|
+
if (r < c) edges.push({ u: r + 1, v: c + 1, w: A.pr[k] });
|
|
59328
|
+
else if (r === c) edges.push({ u: r + 1, v: r + 1, w: A.pr[k] });
|
|
59329
|
+
}
|
|
59330
|
+
}
|
|
59331
|
+
return edges;
|
|
59332
|
+
}
|
|
59333
|
+
function squareDim(A, fn) {
|
|
59334
|
+
if (isRuntimeNumber(A) || isRuntimeLogical(A)) return 1;
|
|
59335
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
59336
|
+
if (A.m !== A.n) throw new RuntimeError(`${fn}: adjacency must be square`);
|
|
59337
|
+
return A.n;
|
|
59338
|
+
}
|
|
59339
|
+
if (isRuntimeTensor(A)) {
|
|
59340
|
+
const rows = A.shape[0] ?? 1;
|
|
59341
|
+
const cols = A.shape[1] ?? 1;
|
|
59342
|
+
if (rows !== cols)
|
|
59343
|
+
throw new RuntimeError(`${fn}: adjacency must be square`);
|
|
59344
|
+
return rows;
|
|
59345
|
+
}
|
|
59346
|
+
throw new RuntimeError(`${fn}: adjacency must be a numeric matrix`);
|
|
59347
|
+
}
|
|
59348
|
+
function takeEntry(r, c, triangle) {
|
|
59349
|
+
if (r === c) return true;
|
|
59350
|
+
if (triangle === "lower") return r > c;
|
|
59351
|
+
return r < c;
|
|
59352
|
+
}
|
|
59353
|
+
function adjToEdges(A, omitSelfLoops, triangle, fn) {
|
|
59354
|
+
const n = squareDim(A, fn);
|
|
59355
|
+
const weighted = !(isRuntimeTensor(A) && A._isLogical);
|
|
59356
|
+
const edges = [];
|
|
59357
|
+
const push = (r, c, val) => {
|
|
59358
|
+
if (val === 0) return;
|
|
59359
|
+
if (r === c) {
|
|
59360
|
+
if (!omitSelfLoops) edges.push({ u: r + 1, v: r + 1, w: val });
|
|
59361
|
+
} else if (takeEntry(r, c, triangle)) {
|
|
59362
|
+
edges.push({ u: Math.min(r, c) + 1, v: Math.max(r, c) + 1, w: val });
|
|
59363
|
+
}
|
|
59364
|
+
};
|
|
59365
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
59366
|
+
for (let c = 0; c < A.n; c++) {
|
|
59367
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) push(A.ir[k], c, A.pr[k]);
|
|
59368
|
+
}
|
|
59369
|
+
} else if (isRuntimeTensor(A)) {
|
|
59370
|
+
const m = A.shape[0] ?? 1;
|
|
59371
|
+
for (let c = 0; c < n; c++) {
|
|
59372
|
+
for (let r = 0; r < n; r++) {
|
|
59373
|
+
const val = A.data[c * m + r];
|
|
59374
|
+
if (val !== 0) push(r, c, val);
|
|
59375
|
+
}
|
|
59376
|
+
}
|
|
59377
|
+
} else if (isRuntimeNumber(A) || isRuntimeLogical(A)) {
|
|
59378
|
+
const val = isRuntimeNumber(A) ? A : A ? 1 : 0;
|
|
59379
|
+
if (val !== 0) push(0, 0, val);
|
|
59380
|
+
}
|
|
59381
|
+
return { n, edges, weighted };
|
|
59382
|
+
}
|
|
59383
|
+
function isNumericArg3(v) {
|
|
59384
|
+
return isRuntimeNumber(v) || isRuntimeLogical(v) || isRuntimeTensor(v) || isRuntimeSparseMatrix(v);
|
|
59385
|
+
}
|
|
59386
|
+
function toNumArray2(v) {
|
|
59387
|
+
if (isRuntimeNumber(v)) return [v];
|
|
59388
|
+
if (isRuntimeLogical(v)) return [v ? 1 : 0];
|
|
59389
|
+
if (isRuntimeTensor(v)) return Array.from(v.data);
|
|
59390
|
+
throw new RuntimeError("graph: node/weight arguments must be numeric");
|
|
59391
|
+
}
|
|
59392
|
+
function argString(v) {
|
|
59393
|
+
if (isRuntimeString(v)) return v;
|
|
59394
|
+
if (isRuntimeChar(v)) return v.value;
|
|
59395
|
+
return null;
|
|
59396
|
+
}
|
|
59397
|
+
registerIBuiltin({
|
|
59398
|
+
name: "graph",
|
|
59399
|
+
help: {
|
|
59400
|
+
signatures: [
|
|
59401
|
+
"G = graph(A)",
|
|
59402
|
+
"G = graph(A, 'omitselfloops')",
|
|
59403
|
+
"G = graph(A, 'upper' | 'lower')",
|
|
59404
|
+
"G = graph(s, t)",
|
|
59405
|
+
"G = graph(s, t, w)",
|
|
59406
|
+
"G = graph(s, t, w, num)"
|
|
59407
|
+
],
|
|
59408
|
+
description: "Create an undirected graph from an adjacency matrix A (which must be symmetric) or from edge endpoint lists s and t with optional weights w."
|
|
59409
|
+
},
|
|
59410
|
+
resolve: () => ({
|
|
59411
|
+
outputTypes: [
|
|
59412
|
+
{
|
|
59413
|
+
kind: "class_instance",
|
|
59414
|
+
className: "graph",
|
|
59415
|
+
isHandleClass: false,
|
|
59416
|
+
fields: {}
|
|
59417
|
+
}
|
|
59418
|
+
],
|
|
59419
|
+
apply: (args) => {
|
|
59420
|
+
if (args.length === 0) return makeGraph(0, [], false);
|
|
59421
|
+
if (args.length >= 2 && isNumericArg3(args[1])) {
|
|
59422
|
+
const s = toNumArray2(args[0]);
|
|
59423
|
+
const t = toNumArray2(args[1]);
|
|
59424
|
+
if (s.length !== t.length) {
|
|
59425
|
+
throw new RuntimeError("graph: s and t must have the same length");
|
|
59426
|
+
}
|
|
59427
|
+
let weighted2 = false;
|
|
59428
|
+
let w = null;
|
|
59429
|
+
let num = null;
|
|
59430
|
+
let omitSelfLoops2 = false;
|
|
59431
|
+
if (args.length >= 3 && isNumericArg3(args[2])) {
|
|
59432
|
+
w = toNumArray2(args[2]);
|
|
59433
|
+
weighted2 = true;
|
|
59434
|
+
if (args.length >= 4 && isNumericArg3(args[3])) {
|
|
59435
|
+
num = Math.floor(toNumber(args[3]));
|
|
59436
|
+
}
|
|
59437
|
+
}
|
|
59438
|
+
for (let i = 2; i < args.length; i++) {
|
|
59439
|
+
const str = argString(args[i]);
|
|
59440
|
+
if (str && str.toLowerCase() === "omitselfloops")
|
|
59441
|
+
omitSelfLoops2 = true;
|
|
59442
|
+
}
|
|
59443
|
+
let n2 = num ?? 0;
|
|
59444
|
+
for (let i = 0; i < s.length; i++) n2 = Math.max(n2, s[i], t[i]);
|
|
59445
|
+
const edges2 = [];
|
|
59446
|
+
for (let i = 0; i < s.length; i++) {
|
|
59447
|
+
const u = Math.min(s[i], t[i]);
|
|
59448
|
+
const v = Math.max(s[i], t[i]);
|
|
59449
|
+
if (omitSelfLoops2 && u === v) continue;
|
|
59450
|
+
edges2.push({ u, v, w: w ? w[w.length === 1 ? 0 : i] : 1 });
|
|
59451
|
+
}
|
|
59452
|
+
return makeGraph(n2, edges2, weighted2);
|
|
59453
|
+
}
|
|
59454
|
+
let omitSelfLoops = false;
|
|
59455
|
+
let triangle = "sym";
|
|
59456
|
+
for (let i = 1; i < args.length; i++) {
|
|
59457
|
+
const str = argString(args[i]);
|
|
59458
|
+
if (!str) continue;
|
|
59459
|
+
const lc = str.toLowerCase();
|
|
59460
|
+
if (lc === "omitselfloops") omitSelfLoops = true;
|
|
59461
|
+
else if (lc === "upper") triangle = "upper";
|
|
59462
|
+
else if (lc === "lower") triangle = "lower";
|
|
59463
|
+
}
|
|
59464
|
+
const { n, edges, weighted } = adjToEdges(
|
|
59465
|
+
args[0],
|
|
59466
|
+
omitSelfLoops,
|
|
59467
|
+
triangle,
|
|
59468
|
+
"graph"
|
|
59469
|
+
);
|
|
59470
|
+
return makeGraph(n, edges, weighted);
|
|
59471
|
+
}
|
|
59472
|
+
})
|
|
59473
|
+
});
|
|
59474
|
+
registerIBuiltin({
|
|
59475
|
+
name: "conncomp",
|
|
59476
|
+
help: {
|
|
59477
|
+
signatures: ["bins = conncomp(G)", "[bins, binsizes] = conncomp(G)"],
|
|
59478
|
+
description: "Connected components of an undirected graph G. Returns a row vector labeling each node with its component index, and optionally the size of each component."
|
|
59479
|
+
},
|
|
59480
|
+
resolve: () => ({
|
|
59481
|
+
outputTypes: [{ kind: "unknown" }, { kind: "unknown" }],
|
|
59482
|
+
apply: (args, nargout) => {
|
|
59483
|
+
const g = requireGraph(args[0], "conncomp");
|
|
59484
|
+
const n = graphN(g);
|
|
59485
|
+
const A = graphAdj(g);
|
|
59486
|
+
const bins = new Float64Array(n);
|
|
59487
|
+
const sizes = [];
|
|
59488
|
+
let comp = 0;
|
|
59489
|
+
const stack = [];
|
|
59490
|
+
for (let start = 0; start < n; start++) {
|
|
59491
|
+
if (bins[start] !== 0) continue;
|
|
59492
|
+
comp++;
|
|
59493
|
+
let count = 0;
|
|
59494
|
+
bins[start] = comp;
|
|
59495
|
+
stack.length = 0;
|
|
59496
|
+
stack.push(start);
|
|
59497
|
+
while (stack.length > 0) {
|
|
59498
|
+
const node = stack.pop();
|
|
59499
|
+
count++;
|
|
59500
|
+
eachNeighbor(A, node, (r) => {
|
|
59501
|
+
if (bins[r] === 0) {
|
|
59502
|
+
bins[r] = comp;
|
|
59503
|
+
stack.push(r);
|
|
59504
|
+
}
|
|
59505
|
+
});
|
|
59506
|
+
}
|
|
59507
|
+
sizes.push(count);
|
|
59508
|
+
}
|
|
59509
|
+
const binsT = RTV.tensor(bins, [1, n]);
|
|
59510
|
+
if (nargout >= 2) {
|
|
59511
|
+
return [binsT, RTV.tensor(allocFloat64Array(sizes), [1, sizes.length])];
|
|
59512
|
+
}
|
|
59513
|
+
return binsT;
|
|
59514
|
+
}
|
|
59515
|
+
})
|
|
59516
|
+
});
|
|
59517
|
+
registerIBuiltin({
|
|
59518
|
+
name: "laplacian",
|
|
59519
|
+
help: {
|
|
59520
|
+
signatures: ["L = laplacian(G)"],
|
|
59521
|
+
description: "Graph Laplacian matrix L = D - A of an undirected graph G, where A is the (binary, unweighted) adjacency matrix and D the diagonal node-degree matrix. Returns a sparse matrix."
|
|
59522
|
+
},
|
|
59523
|
+
resolve: () => ({
|
|
59524
|
+
outputTypes: [{ kind: "unknown" }],
|
|
59525
|
+
apply: (args) => {
|
|
59526
|
+
const g = requireGraph(args[0], "laplacian");
|
|
59527
|
+
const n = graphN(g);
|
|
59528
|
+
const A = graphAdj(g);
|
|
59529
|
+
const edges = [];
|
|
59530
|
+
for (let c = 0; c < n; c++) {
|
|
59531
|
+
let degree = 0;
|
|
59532
|
+
eachNeighbor(A, c, (r) => {
|
|
59533
|
+
degree++;
|
|
59534
|
+
if (r < c) edges.push({ u: r + 1, v: c + 1, w: -1 });
|
|
59535
|
+
});
|
|
59536
|
+
edges.push({ u: c + 1, v: c + 1, w: degree });
|
|
59537
|
+
}
|
|
59538
|
+
return buildSymAdj(n, edges);
|
|
59539
|
+
}
|
|
59540
|
+
})
|
|
59541
|
+
});
|
|
59542
|
+
registerIBuiltin({
|
|
59543
|
+
name: "addedge",
|
|
59544
|
+
help: {
|
|
59545
|
+
signatures: ["H = addedge(G, s, t)", "H = addedge(G, s, t, w)"],
|
|
59546
|
+
description: "Add one or more edges between nodes s and t to graph G, returning a new graph. Weights w are required when G is a weighted graph."
|
|
59547
|
+
},
|
|
59548
|
+
resolve: () => ({
|
|
59549
|
+
outputTypes: [
|
|
59550
|
+
{
|
|
59551
|
+
kind: "class_instance",
|
|
59552
|
+
className: "graph",
|
|
59553
|
+
isHandleClass: false,
|
|
59554
|
+
fields: {}
|
|
59555
|
+
}
|
|
59556
|
+
],
|
|
59557
|
+
apply: (args) => {
|
|
59558
|
+
const g = requireGraph(args[0], "addedge");
|
|
59559
|
+
if (args.length < 3) {
|
|
59560
|
+
throw new RuntimeError("addedge: requires nodes s and t");
|
|
59561
|
+
}
|
|
59562
|
+
const weighted = graphWeighted(g);
|
|
59563
|
+
const s = toNumArray2(args[1]);
|
|
59564
|
+
const t = toNumArray2(args[2]);
|
|
59565
|
+
if (s.length !== t.length) {
|
|
59566
|
+
throw new RuntimeError("addedge: s and t must have the same length");
|
|
59567
|
+
}
|
|
59568
|
+
let w = null;
|
|
59569
|
+
if (args.length >= 4) {
|
|
59570
|
+
w = toNumArray2(args[3]);
|
|
59571
|
+
} else if (weighted) {
|
|
59572
|
+
throw new RuntimeError(
|
|
59573
|
+
"addedge: Must specify weights when adding an edge to a weighted graph."
|
|
59574
|
+
);
|
|
59575
|
+
}
|
|
59576
|
+
const edges = edgesFromAdj(graphAdj(g));
|
|
59577
|
+
let n = graphN(g);
|
|
59578
|
+
for (let i = 0; i < s.length; i++) {
|
|
59579
|
+
const u = Math.min(s[i], t[i]);
|
|
59580
|
+
const v = Math.max(s[i], t[i]);
|
|
59581
|
+
n = Math.max(n, u, v);
|
|
59582
|
+
edges.push({ u, v, w: w ? w[w.length === 1 ? 0 : i] : 1 });
|
|
59583
|
+
}
|
|
59584
|
+
return makeGraph(n, edges, weighted);
|
|
59585
|
+
}
|
|
59586
|
+
})
|
|
59587
|
+
});
|
|
59588
|
+
registerIBuiltin({
|
|
59589
|
+
name: "numnodes",
|
|
59590
|
+
help: {
|
|
59591
|
+
signatures: ["n = numnodes(G)"],
|
|
59592
|
+
description: "Number of nodes in graph G."
|
|
59593
|
+
},
|
|
59594
|
+
resolve: () => ({
|
|
59595
|
+
outputTypes: [{ kind: "number" }],
|
|
59596
|
+
apply: (args) => RTV.num(graphN(requireGraph(args[0], "numnodes")))
|
|
59597
|
+
})
|
|
59598
|
+
});
|
|
59599
|
+
registerIBuiltin({
|
|
59600
|
+
name: "numedges",
|
|
59601
|
+
help: {
|
|
59602
|
+
signatures: ["m = numedges(G)"],
|
|
59603
|
+
description: "Number of edges in graph G."
|
|
59604
|
+
},
|
|
59605
|
+
resolve: () => ({
|
|
59606
|
+
outputTypes: [{ kind: "number" }],
|
|
59607
|
+
apply: (args) => {
|
|
59608
|
+
const g = requireGraph(args[0], "numedges");
|
|
59609
|
+
return RTV.num(edgesFromAdj(graphAdj(g)).length);
|
|
59610
|
+
}
|
|
59611
|
+
})
|
|
59612
|
+
});
|
|
59613
|
+
registerIBuiltin({
|
|
59614
|
+
name: "degree",
|
|
59615
|
+
help: {
|
|
59616
|
+
signatures: ["d = degree(G)"],
|
|
59617
|
+
description: "Degree of each node in graph G, returned as a column vector of edge counts (self-loops excluded)."
|
|
59618
|
+
},
|
|
59619
|
+
resolve: () => ({
|
|
59620
|
+
outputTypes: [{ kind: "unknown" }],
|
|
59621
|
+
apply: (args) => {
|
|
59622
|
+
const g = requireGraph(args[0], "degree");
|
|
59623
|
+
const n = graphN(g);
|
|
59624
|
+
const A = graphAdj(g);
|
|
59625
|
+
const d = new Float64Array(n);
|
|
59626
|
+
for (let c = 0; c < n; c++) eachNeighbor(A, c, () => d[c] += 1);
|
|
59627
|
+
return RTV.tensor(d, [n, 1]);
|
|
59628
|
+
}
|
|
59629
|
+
})
|
|
59630
|
+
});
|
|
59631
|
+
|
|
59632
|
+
// src/numbl-core/interpreter/builtins/gallery.ts
|
|
59633
|
+
function toNumArray3(v, what) {
|
|
59634
|
+
if (isRuntimeNumber(v)) return [v];
|
|
59635
|
+
if (isRuntimeLogical(v)) return [v ? 1 : 0];
|
|
59636
|
+
if (isRuntimeTensor(v)) return Array.from(v.data);
|
|
59637
|
+
if (isRuntimeComplexNumber(v)) return [v.re];
|
|
59638
|
+
throw new RuntimeError(`gallery: ${what} must be numeric`);
|
|
59639
|
+
}
|
|
59640
|
+
function buildTridiag(sub2, diag2, sup) {
|
|
59641
|
+
const n = diag2.length;
|
|
59642
|
+
if (sub2.length !== n - 1 || sup.length !== n - 1) {
|
|
59643
|
+
throw new RuntimeError(
|
|
59644
|
+
"gallery: tridiag sub/superdiagonal must have length one less than the diagonal"
|
|
59645
|
+
);
|
|
59646
|
+
}
|
|
59647
|
+
const ir = [];
|
|
59648
|
+
const pr = [];
|
|
59649
|
+
const jc = new Int32Array(n + 1);
|
|
59650
|
+
for (let c = 0; c < n; c++) {
|
|
59651
|
+
jc[c] = ir.length;
|
|
59652
|
+
if (c >= 1 && sup[c - 1] !== 0) {
|
|
59653
|
+
ir.push(c - 1);
|
|
59654
|
+
pr.push(sup[c - 1]);
|
|
59655
|
+
}
|
|
59656
|
+
if (diag2[c] !== 0) {
|
|
59657
|
+
ir.push(c);
|
|
59658
|
+
pr.push(diag2[c]);
|
|
59659
|
+
}
|
|
59660
|
+
if (c <= n - 2 && sub2[c] !== 0) {
|
|
59661
|
+
ir.push(c + 1);
|
|
59662
|
+
pr.push(sub2[c]);
|
|
59663
|
+
}
|
|
59664
|
+
}
|
|
59665
|
+
jc[n] = ir.length;
|
|
59666
|
+
return RTV.sparseMatrix(n, n, new Int32Array(ir), jc, allocFloat64Array(pr));
|
|
59667
|
+
}
|
|
59668
|
+
function buildTridiagToeplitz(n, c, d, e) {
|
|
59669
|
+
const off = Math.max(0, n - 1);
|
|
59670
|
+
return buildTridiag(
|
|
59671
|
+
new Array(off).fill(c),
|
|
59672
|
+
new Array(n).fill(d),
|
|
59673
|
+
new Array(off).fill(e)
|
|
59674
|
+
);
|
|
59675
|
+
}
|
|
59676
|
+
function galleryTridiag(rest) {
|
|
59677
|
+
if (rest.length === 1) {
|
|
59678
|
+
return buildTridiagToeplitz(Math.round(toNumber(rest[0])), -1, 2, -1);
|
|
59679
|
+
}
|
|
59680
|
+
if (rest.length === 4) {
|
|
59681
|
+
return buildTridiagToeplitz(
|
|
59682
|
+
Math.round(toNumber(rest[0])),
|
|
59683
|
+
toNumber(rest[1]),
|
|
59684
|
+
toNumber(rest[2]),
|
|
59685
|
+
toNumber(rest[3])
|
|
59686
|
+
);
|
|
59687
|
+
}
|
|
59688
|
+
if (rest.length === 3) {
|
|
59689
|
+
const sub2 = toNumArray3(rest[0], "subdiagonal");
|
|
59690
|
+
const diag2 = toNumArray3(rest[1], "diagonal");
|
|
59691
|
+
const sup = toNumArray3(rest[2], "superdiagonal");
|
|
59692
|
+
if (sub2.length === 1 && diag2.length === 1 && sup.length === 1) {
|
|
59693
|
+
return buildTridiag([], diag2, []);
|
|
59694
|
+
}
|
|
59695
|
+
return buildTridiag(sub2, diag2, sup);
|
|
59696
|
+
}
|
|
59697
|
+
throw new RuntimeError("gallery: tridiag expects (n), (n,c,d,e), or (x,y,z)");
|
|
59698
|
+
}
|
|
59699
|
+
registerIBuiltin({
|
|
59700
|
+
name: "gallery",
|
|
59701
|
+
help: {
|
|
59702
|
+
signatures: [
|
|
59703
|
+
"A = gallery('tridiag', n)",
|
|
59704
|
+
"A = gallery('tridiag', n, c, d, e)",
|
|
59705
|
+
"A = gallery('tridiag', x, y, z)"
|
|
59706
|
+
],
|
|
59707
|
+
description: "Test matrices. gallery('tridiag', ...) returns a sparse tridiagonal matrix: gallery('tridiag', n) is the order-n matrix with -1 on the sub/superdiagonals and 2 on the diagonal (the negative second-difference matrix); gallery('tridiag', n, c, d, e) is the order-n Toeplitz tridiagonal with scalar sub c, diagonal d, super e; gallery('tridiag', x, y, z) uses vectors x (subdiagonal), y (diagonal), z (superdiagonal), where x and z have length one less than y."
|
|
59708
|
+
},
|
|
59709
|
+
resolve: () => ({
|
|
59710
|
+
outputTypes: [{ kind: "unknown" }],
|
|
59711
|
+
apply: (args) => {
|
|
59712
|
+
if (args.length < 1) {
|
|
59713
|
+
throw new RuntimeError("gallery: not enough input arguments");
|
|
59714
|
+
}
|
|
59715
|
+
const name = parseStringArgLower(args[0]);
|
|
59716
|
+
let rest = args.slice(1);
|
|
59717
|
+
if (rest.length >= 1) {
|
|
59718
|
+
const last = rest[rest.length - 1];
|
|
59719
|
+
if (isRuntimeString(last) || isRuntimeChar(last)) {
|
|
59720
|
+
const cn = parseStringArgLower(last);
|
|
59721
|
+
if (cn === "single" || cn === "double") rest = rest.slice(0, -1);
|
|
59722
|
+
}
|
|
59723
|
+
}
|
|
59724
|
+
switch (name) {
|
|
59725
|
+
case "tridiag":
|
|
59726
|
+
return galleryTridiag(rest);
|
|
59727
|
+
default:
|
|
59728
|
+
throw new RuntimeError(
|
|
59729
|
+
`gallery: matrix family '${name}' is not supported`
|
|
59730
|
+
);
|
|
59731
|
+
}
|
|
59732
|
+
}
|
|
59733
|
+
})
|
|
59734
|
+
});
|
|
58131
59735
|
|
|
58132
59736
|
// src/numbl-core/interpreter/builtins/special-math.ts
|
|
58133
59737
|
function binaryApply(a, b, fn) {
|
|
@@ -58611,12 +60215,19 @@ registerIBuiltin({
|
|
|
58611
60215
|
|
|
58612
60216
|
// src/numbl-core/native/geometry-bridge.ts
|
|
58613
60217
|
var backend = null;
|
|
60218
|
+
var hullBackend = null;
|
|
58614
60219
|
function setDelaunayBackend(fn) {
|
|
58615
60220
|
backend = fn;
|
|
58616
60221
|
}
|
|
58617
60222
|
function getDelaunayBackend() {
|
|
58618
60223
|
return backend;
|
|
58619
60224
|
}
|
|
60225
|
+
function setConvexHullBackend(fn) {
|
|
60226
|
+
hullBackend = fn;
|
|
60227
|
+
}
|
|
60228
|
+
function getConvexHullBackend() {
|
|
60229
|
+
return hullBackend;
|
|
60230
|
+
}
|
|
58620
60231
|
|
|
58621
60232
|
// src/numbl-core/interpreter/builtins/geometry.ts
|
|
58622
60233
|
function toFlatArray(v, name) {
|
|
@@ -58669,7 +60280,7 @@ function simplexVolume(points, cell, dim) {
|
|
|
58669
60280
|
for (let k = 2; k <= dim; k++) fact *= k;
|
|
58670
60281
|
return Math.abs(det) / fact;
|
|
58671
60282
|
}
|
|
58672
|
-
function triangulateToTensor(points, dim) {
|
|
60283
|
+
function triangulateToTensor(points, dim, orientCCW = false) {
|
|
58673
60284
|
const backend2 = getDelaunayBackend();
|
|
58674
60285
|
if (!backend2)
|
|
58675
60286
|
throw new RuntimeError(
|
|
@@ -58689,6 +60300,16 @@ function triangulateToTensor(points, dim) {
|
|
|
58689
60300
|
const cells = volTol > 0 ? raw.filter((cell) => simplexVolume(points, cell, dim) > volTol) : raw;
|
|
58690
60301
|
const numCells = cells.length;
|
|
58691
60302
|
const cols = dim + 1;
|
|
60303
|
+
if (orientCCW && dim === 2) {
|
|
60304
|
+
for (const cell of cells) {
|
|
60305
|
+
const [a, b, c] = cell;
|
|
60306
|
+
const signedArea2 = (points[b][0] - points[a][0]) * (points[c][1] - points[a][1]) - (points[c][0] - points[a][0]) * (points[b][1] - points[a][1]);
|
|
60307
|
+
if (signedArea2 < 0) {
|
|
60308
|
+
cell[1] = c;
|
|
60309
|
+
cell[2] = b;
|
|
60310
|
+
}
|
|
60311
|
+
}
|
|
60312
|
+
}
|
|
58692
60313
|
const out = allocFloat64Array(numCells * cols);
|
|
58693
60314
|
for (let i = 0; i < numCells; i++) {
|
|
58694
60315
|
const cell = cells[i];
|
|
@@ -58742,7 +60363,7 @@ defineBuiltin({
|
|
|
58742
60363
|
throw new RuntimeError(
|
|
58743
60364
|
`delaunay: need at least ${dim + 1} points for a ${dim}-D triangulation`
|
|
58744
60365
|
);
|
|
58745
|
-
return triangulateToTensor(points, dim);
|
|
60366
|
+
return triangulateToTensor(points, dim, true);
|
|
58746
60367
|
}
|
|
58747
60368
|
}
|
|
58748
60369
|
]
|
|
@@ -58785,6 +60406,203 @@ defineBuiltin({
|
|
|
58785
60406
|
}
|
|
58786
60407
|
]
|
|
58787
60408
|
});
|
|
60409
|
+
var CONVHULLN_MAX_DIM = 3;
|
|
60410
|
+
function convexHullFacets(points, dim, name) {
|
|
60411
|
+
const backend2 = getConvexHullBackend();
|
|
60412
|
+
if (!backend2)
|
|
60413
|
+
throw new RuntimeError(
|
|
60414
|
+
`${name}: convex-hull backend not initialized. In Node call loadQhullNodeBackend() (the CLI and library do this automatically); in the browser worker it loads on startup.`
|
|
60415
|
+
);
|
|
60416
|
+
return backend2(points, dim);
|
|
60417
|
+
}
|
|
60418
|
+
function hullInteriorPoint(points, facets, dim) {
|
|
60419
|
+
const used = /* @__PURE__ */ new Set();
|
|
60420
|
+
for (const f of facets) for (const idx of f) used.add(idx);
|
|
60421
|
+
const c = new Array(dim).fill(0);
|
|
60422
|
+
for (const idx of used) {
|
|
60423
|
+
const p2 = points[idx];
|
|
60424
|
+
for (let k = 0; k < dim; k++) c[k] += p2[k];
|
|
60425
|
+
}
|
|
60426
|
+
const m = used.size || 1;
|
|
60427
|
+
for (let k = 0; k < dim; k++) c[k] /= m;
|
|
60428
|
+
return c;
|
|
60429
|
+
}
|
|
60430
|
+
function hullMeasure(points, facets, dim) {
|
|
60431
|
+
const c = hullInteriorPoint(points, facets, dim);
|
|
60432
|
+
let total = 0;
|
|
60433
|
+
if (dim === 2) {
|
|
60434
|
+
for (const f of facets) {
|
|
60435
|
+
const a = points[f[0]];
|
|
60436
|
+
const b = points[f[1]];
|
|
60437
|
+
const ax = a[0] - c[0], ay = a[1] - c[1];
|
|
60438
|
+
const bx = b[0] - c[0], by = b[1] - c[1];
|
|
60439
|
+
total += Math.abs(ax * by - ay * bx) / 2;
|
|
60440
|
+
}
|
|
60441
|
+
} else {
|
|
60442
|
+
for (const f of facets) {
|
|
60443
|
+
const a = points[f[0]];
|
|
60444
|
+
const b = points[f[1]];
|
|
60445
|
+
const d = points[f[2]];
|
|
60446
|
+
const ax = a[0] - c[0], ay = a[1] - c[1], az = a[2] - c[2];
|
|
60447
|
+
const bx = b[0] - c[0], by = b[1] - c[1], bz = b[2] - c[2];
|
|
60448
|
+
const dx = d[0] - c[0], dy = d[1] - c[1], dz = d[2] - c[2];
|
|
60449
|
+
const det = ax * (by * dz - bz * dy) - ay * (bx * dz - bz * dx) + az * (bx * dy - by * dx);
|
|
60450
|
+
total += Math.abs(det) / 6;
|
|
60451
|
+
}
|
|
60452
|
+
}
|
|
60453
|
+
return total;
|
|
60454
|
+
}
|
|
60455
|
+
function facetsToTensor(facets, cols) {
|
|
60456
|
+
const n = facets.length;
|
|
60457
|
+
const out = allocFloat64Array(n * cols);
|
|
60458
|
+
for (let i = 0; i < n; i++) {
|
|
60459
|
+
const f = facets[i];
|
|
60460
|
+
for (let j = 0; j < cols; j++) out[j * n + i] = f[j] + 1;
|
|
60461
|
+
}
|
|
60462
|
+
return RTV.tensor(out, [n, cols]);
|
|
60463
|
+
}
|
|
60464
|
+
function orderHull2D(facets, points) {
|
|
60465
|
+
const adj = /* @__PURE__ */ new Map();
|
|
60466
|
+
for (const [a, b] of facets) {
|
|
60467
|
+
(adj.get(a) ?? adj.set(a, []).get(a)).push(b);
|
|
60468
|
+
(adj.get(b) ?? adj.set(b, []).get(b)).push(a);
|
|
60469
|
+
}
|
|
60470
|
+
const start = facets[0][0];
|
|
60471
|
+
const loop = [start];
|
|
60472
|
+
let prev = -1;
|
|
60473
|
+
let cur = start;
|
|
60474
|
+
for (let guard = 0; guard <= facets.length; guard++) {
|
|
60475
|
+
const nbrs = adj.get(cur);
|
|
60476
|
+
const next = nbrs[0] === prev ? nbrs[1] : nbrs[0];
|
|
60477
|
+
if (next === void 0 || next === start) break;
|
|
60478
|
+
loop.push(next);
|
|
60479
|
+
prev = cur;
|
|
60480
|
+
cur = next;
|
|
60481
|
+
}
|
|
60482
|
+
let signed = 0;
|
|
60483
|
+
for (let i = 0; i < loop.length; i++) {
|
|
60484
|
+
const p2 = points[loop[i]];
|
|
60485
|
+
const q = points[loop[(i + 1) % loop.length]];
|
|
60486
|
+
signed += p2[0] * q[1] - q[0] * p2[1];
|
|
60487
|
+
}
|
|
60488
|
+
if (signed < 0) loop.reverse();
|
|
60489
|
+
loop.push(loop[0]);
|
|
60490
|
+
const out = allocFloat64Array(loop.length);
|
|
60491
|
+
for (let i = 0; i < loop.length; i++) out[i] = loop[i] + 1;
|
|
60492
|
+
return RTV.tensor(out, [loop.length, 1]);
|
|
60493
|
+
}
|
|
60494
|
+
defineBuiltin({
|
|
60495
|
+
name: "convhull",
|
|
60496
|
+
help: {
|
|
60497
|
+
signatures: [
|
|
60498
|
+
"k = convhull(P)",
|
|
60499
|
+
"k = convhull(x,y)",
|
|
60500
|
+
"k = convhull(x,y,z)",
|
|
60501
|
+
"k = convhull(___,'Simplify',tf)",
|
|
60502
|
+
"[k,av] = convhull(___)"
|
|
60503
|
+
],
|
|
60504
|
+
description: "Convex hull of a set of 2-D or 3-D points. With a single matrix P (N-by-2 or N-by-3), or coordinate vectors x,y (2-D) or x,y,z (3-D). For 2-D input, k is a column vector of 1-based point indices tracing the hull boundary counter-clockwise (closed: k(1)==k(end)). For 3-D input, k is a numFacets-by-3 matrix of triangle vertex indices. The second output av is the area (2-D) or volume (3-D). The 'Simplify' name-value pair is accepted for compatibility; the hull is always returned in minimal (simplified) form."
|
|
60505
|
+
},
|
|
60506
|
+
cases: [
|
|
60507
|
+
{
|
|
60508
|
+
match: (argTypes, nargout) => {
|
|
60509
|
+
if (nargout > 2) return null;
|
|
60510
|
+
if (argTypes.length < 1 || argTypes.length > 5) return null;
|
|
60511
|
+
const ok = (t) => t.kind === "number" || t.kind === "boolean" || t.kind === "tensor" || t.kind === "string" || t.kind === "char";
|
|
60512
|
+
if (!argTypes.every(ok)) return null;
|
|
60513
|
+
const k = { kind: "tensor", isComplex: false };
|
|
60514
|
+
return nargout > 1 ? [k, { kind: "number" }] : [k];
|
|
60515
|
+
},
|
|
60516
|
+
apply: (args, nargout) => {
|
|
60517
|
+
let coordArgs = args;
|
|
60518
|
+
const tail = args[args.length - 2];
|
|
60519
|
+
const isSimplifyName = (v) => typeof v === "string" && v.toLowerCase() === "simplify" || isRuntimeChar(v) && v.value.toLowerCase() === "simplify";
|
|
60520
|
+
if (args.length >= 3 && isSimplifyName(tail)) {
|
|
60521
|
+
coordArgs = args.slice(0, args.length - 2);
|
|
60522
|
+
}
|
|
60523
|
+
let points;
|
|
60524
|
+
let dim;
|
|
60525
|
+
if (coordArgs.length === 1) {
|
|
60526
|
+
const P = coordArgs[0];
|
|
60527
|
+
if (!isRuntimeTensor(P))
|
|
60528
|
+
throw new RuntimeError(
|
|
60529
|
+
"convhull: P must be an N-by-2 or N-by-3 matrix"
|
|
60530
|
+
);
|
|
60531
|
+
const [, d] = tensorSize2D(P);
|
|
60532
|
+
if (d !== 2 && d !== 3)
|
|
60533
|
+
throw new RuntimeError("convhull: P must have 2 or 3 columns");
|
|
60534
|
+
points = matrixToPoints(P, "convhull");
|
|
60535
|
+
dim = d;
|
|
60536
|
+
} else if (coordArgs.length === 2 || coordArgs.length === 3) {
|
|
60537
|
+
const coords = coordArgs.map((a) => toFlatArray(a, "convhull"));
|
|
60538
|
+
const n = coords[0].length;
|
|
60539
|
+
if (coords.some((c) => c.length !== n))
|
|
60540
|
+
throw new RuntimeError(
|
|
60541
|
+
"convhull: coordinate vectors must have the same length"
|
|
60542
|
+
);
|
|
60543
|
+
points = new Array(n);
|
|
60544
|
+
for (let i = 0; i < n; i++) points[i] = coords.map((c) => c[i]);
|
|
60545
|
+
dim = coordArgs.length;
|
|
60546
|
+
} else {
|
|
60547
|
+
throw new RuntimeError("convhull: invalid arguments");
|
|
60548
|
+
}
|
|
60549
|
+
if (points.length < dim + 1)
|
|
60550
|
+
throw new RuntimeError(
|
|
60551
|
+
`convhull: need at least ${dim + 1} points for a ${dim}-D hull`
|
|
60552
|
+
);
|
|
60553
|
+
const facets = convexHullFacets(points, dim, "convhull");
|
|
60554
|
+
const k = dim === 2 ? orderHull2D(facets, points) : facetsToTensor(facets, 3);
|
|
60555
|
+
if (nargout > 1) return [k, hullMeasure(points, facets, dim)];
|
|
60556
|
+
return k;
|
|
60557
|
+
}
|
|
60558
|
+
}
|
|
60559
|
+
]
|
|
60560
|
+
});
|
|
60561
|
+
defineBuiltin({
|
|
60562
|
+
name: "convhulln",
|
|
60563
|
+
help: {
|
|
60564
|
+
signatures: [
|
|
60565
|
+
"k = convhulln(P)",
|
|
60566
|
+
"k = convhulln(P,opts)",
|
|
60567
|
+
"[k,vol] = convhulln(___)"
|
|
60568
|
+
],
|
|
60569
|
+
description: "N-D convex hull. P is an m-by-n matrix of m points in n-dimensional space. Returns a numFacets-by-n matrix where each row holds the 1-based point indices of one simplicial facet (edges for n=2, triangles for n=3). The second output is the area (n=2) or volume (n=3). The opts argument (Qhull options) is accepted for MATLAB compatibility but ignored. Note: only n = 2 and n = 3 are supported (see source comments)."
|
|
60570
|
+
},
|
|
60571
|
+
cases: [
|
|
60572
|
+
{
|
|
60573
|
+
match: (argTypes, nargout) => {
|
|
60574
|
+
if (nargout > 2) return null;
|
|
60575
|
+
if (argTypes.length < 1 || argTypes.length > 2) return null;
|
|
60576
|
+
const x = argTypes[0];
|
|
60577
|
+
if (x.kind !== "tensor" && x.kind !== "number" && x.kind !== "boolean")
|
|
60578
|
+
return null;
|
|
60579
|
+
const k = { kind: "tensor", isComplex: false };
|
|
60580
|
+
return nargout > 1 ? [k, { kind: "number" }] : [k];
|
|
60581
|
+
},
|
|
60582
|
+
apply: (args, nargout) => {
|
|
60583
|
+
const P = args[0];
|
|
60584
|
+
if (!isRuntimeTensor(P))
|
|
60585
|
+
throw new RuntimeError("convhulln: P must be an m-by-n matrix");
|
|
60586
|
+
const [m, n] = tensorSize2D(P);
|
|
60587
|
+
if (n < 2)
|
|
60588
|
+
throw new RuntimeError("convhulln: P must have at least 2 columns");
|
|
60589
|
+
if (n > CONVHULLN_MAX_DIM)
|
|
60590
|
+
throw new RuntimeError(
|
|
60591
|
+
`convhulln: only 2-D and 3-D hulls are supported (got ${n}-D); higher dimensions are not yet validated`
|
|
60592
|
+
);
|
|
60593
|
+
if (m < n + 1)
|
|
60594
|
+
throw new RuntimeError(
|
|
60595
|
+
`convhulln: need at least ${n + 1} points for a ${n}-D hull`
|
|
60596
|
+
);
|
|
60597
|
+
const points = matrixToPoints(P, "convhulln");
|
|
60598
|
+
const facets = convexHullFacets(points, n, "convhulln");
|
|
60599
|
+
const k = facetsToTensor(facets, n);
|
|
60600
|
+
if (nargout > 1) return [k, hullMeasure(points, facets, n)];
|
|
60601
|
+
return k;
|
|
60602
|
+
}
|
|
60603
|
+
}
|
|
60604
|
+
]
|
|
60605
|
+
});
|
|
58788
60606
|
function getQueryValues(v, name) {
|
|
58789
60607
|
if (typeof v === "number") return { data: [v], shape: null };
|
|
58790
60608
|
if (typeof v === "boolean") return { data: [v ? 1 : 0], shape: null };
|
|
@@ -59268,6 +61086,10 @@ var H = {
|
|
|
59268
61086
|
signatures: ["C = class(A)"],
|
|
59269
61087
|
description: "Returns the class name of A as a character vector."
|
|
59270
61088
|
},
|
|
61089
|
+
superclasses: {
|
|
61090
|
+
signatures: ["S = superclasses(ClassName)", "S = superclasses(obj)"],
|
|
61091
|
+
description: "Names of the superclasses of a class, returned as a column cell array of character vectors. Accepts a class name (char/string) or an object. Returns an empty cell for built-in types or classes with no superclasses."
|
|
61092
|
+
},
|
|
59271
61093
|
fieldnames: {
|
|
59272
61094
|
signatures: ["F = fieldnames(S)"],
|
|
59273
61095
|
description: "Returns cell array of field names of struct or object S."
|
|
@@ -59671,6 +61493,14 @@ var H = {
|
|
|
59671
61493
|
signatures: ["B = pinv(A)", "B = pinv(A, TOL)"],
|
|
59672
61494
|
description: "Moore-Penrose pseudoinverse."
|
|
59673
61495
|
},
|
|
61496
|
+
null: {
|
|
61497
|
+
signatures: ["Z = null(A)", "Z = null(A, TOL)"],
|
|
61498
|
+
description: "Orthonormal basis for the null space of A (columns of Z), computed via the SVD. TOL overrides the singular-value tolerance."
|
|
61499
|
+
},
|
|
61500
|
+
bandwidth: {
|
|
61501
|
+
signatures: ["[lower, upper] = bandwidth(A)", "B = bandwidth(A, TYPE)"],
|
|
61502
|
+
description: "Lower and upper matrix bandwidth. TYPE is 'lower' or 'upper'; a single output without TYPE returns the lower bandwidth."
|
|
61503
|
+
},
|
|
59674
61504
|
cond: {
|
|
59675
61505
|
signatures: ["C = cond(A)", "C = cond(A, P)"],
|
|
59676
61506
|
description: "Condition number of matrix."
|
|
@@ -59900,6 +61730,10 @@ var H = {
|
|
|
59900
61730
|
signatures: ["Y = double(X)"],
|
|
59901
61731
|
description: "Convert to double precision."
|
|
59902
61732
|
},
|
|
61733
|
+
single: {
|
|
61734
|
+
signatures: ["Y = single(X)"],
|
|
61735
|
+
description: "Round to single precision. numbl stores all numerics as double, so the result reports class 'double', but the low-order bits are dropped as in MATLAB."
|
|
61736
|
+
},
|
|
59903
61737
|
logical: {
|
|
59904
61738
|
signatures: ["Y = logical(X)"],
|
|
59905
61739
|
description: "Convert to logical (boolean) array."
|
|
@@ -60270,6 +62104,18 @@ var H = {
|
|
|
60270
62104
|
],
|
|
60271
62105
|
description: "Extract or create sparse banded/diagonal matrices."
|
|
60272
62106
|
},
|
|
62107
|
+
spparms: {
|
|
62108
|
+
signatures: [
|
|
62109
|
+
"spparms",
|
|
62110
|
+
"values = spparms",
|
|
62111
|
+
"[keys, values] = spparms",
|
|
62112
|
+
"value = spparms(KEY)",
|
|
62113
|
+
"spparms(KEY, VALUE)",
|
|
62114
|
+
"spparms('default')",
|
|
62115
|
+
"spparms(values)"
|
|
62116
|
+
],
|
|
62117
|
+
description: "Get/set sparse direct-solver parameters. numbl's sparse solver ignores these knobs; values are stored so they round-trip through get/set/restore but have no effect."
|
|
62118
|
+
},
|
|
60273
62119
|
// ── Linear algebra extras ─────────────────────────────────────────────
|
|
60274
62120
|
qz: {
|
|
60275
62121
|
signatures: [
|
|
@@ -61071,7 +62917,7 @@ function getSourceLine(getSource, file, line) {
|
|
|
61071
62917
|
}
|
|
61072
62918
|
|
|
61073
62919
|
// src/numbl-core/version.ts
|
|
61074
|
-
var NUMBL_VERSION = "0.4.
|
|
62920
|
+
var NUMBL_VERSION = "0.4.8";
|
|
61075
62921
|
|
|
61076
62922
|
// src/cli-repl.ts
|
|
61077
62923
|
import { createInterface } from "readline";
|
|
@@ -61087,6 +62933,13 @@ import { join as join4 } from "path";
|
|
|
61087
62933
|
import { homedir as homedir2 } from "os";
|
|
61088
62934
|
|
|
61089
62935
|
// src/numbl-core/jsUserFunctions.ts
|
|
62936
|
+
function callHandle(handle, args, nargout = 1) {
|
|
62937
|
+
const rt = getCurrentRuntime();
|
|
62938
|
+
if (!rt) {
|
|
62939
|
+
throw new RuntimeError("callHandle: no active runtime to invoke handle");
|
|
62940
|
+
}
|
|
62941
|
+
return rt.index(handle, args, nargout);
|
|
62942
|
+
}
|
|
61090
62943
|
function funcNameFromFile(fileName) {
|
|
61091
62944
|
const base = fileName.split("/").pop();
|
|
61092
62945
|
return base.replace(/\.numbl\.js$/, "");
|
|
@@ -61132,6 +62985,8 @@ function instantiateWasm(wasmData) {
|
|
|
61132
62985
|
const moduleImports = WebAssembly.Module.imports(wasmModule);
|
|
61133
62986
|
const importObject = {};
|
|
61134
62987
|
const neededModules = new Set(moduleImports.map((i) => i.module));
|
|
62988
|
+
const callbacks = /* @__PURE__ */ new Map();
|
|
62989
|
+
let nextCbId = 1;
|
|
61135
62990
|
if (neededModules.has("wasi_snapshot_preview1")) {
|
|
61136
62991
|
importObject.wasi_snapshot_preview1 = {
|
|
61137
62992
|
fd_write: () => 0,
|
|
@@ -61151,10 +63006,36 @@ function instantiateWasm(wasmData) {
|
|
|
61151
63006
|
if (neededModules.has("env")) {
|
|
61152
63007
|
importObject.env = {
|
|
61153
63008
|
emscripten_notify_memory_growth: () => {
|
|
63009
|
+
},
|
|
63010
|
+
// Scalar callback: WASM calls back into a registered handle with one
|
|
63011
|
+
// f64 and receives an f64. Exceptions thrown here (incl. a missing id)
|
|
63012
|
+
// propagate out through the WASM call into the apply.
|
|
63013
|
+
numbl_cb_d: (id, x) => {
|
|
63014
|
+
const fn = callbacks.get(id);
|
|
63015
|
+
if (!fn) {
|
|
63016
|
+
throw new RuntimeError(
|
|
63017
|
+
`numbl_cb_d: no callback registered for id ${id}`
|
|
63018
|
+
);
|
|
63019
|
+
}
|
|
63020
|
+
return fn(x);
|
|
61154
63021
|
}
|
|
61155
63022
|
};
|
|
61156
63023
|
}
|
|
61157
|
-
|
|
63024
|
+
const instance = new WebAssembly.Instance(
|
|
63025
|
+
wasmModule,
|
|
63026
|
+
importObject
|
|
63027
|
+
);
|
|
63028
|
+
instance.callbacks = {
|
|
63029
|
+
add(fn) {
|
|
63030
|
+
const id = nextCbId++;
|
|
63031
|
+
callbacks.set(id, fn);
|
|
63032
|
+
return id;
|
|
63033
|
+
},
|
|
63034
|
+
remove(id) {
|
|
63035
|
+
callbacks.delete(id);
|
|
63036
|
+
}
|
|
63037
|
+
};
|
|
63038
|
+
return instance;
|
|
61158
63039
|
}
|
|
61159
63040
|
function resolveBindings(file, directives, getWasmInstance, nativeBridge2) {
|
|
61160
63041
|
const wasmInstance = directives.wasm ? getWasmInstance(directives.wasm) : void 0;
|
|
@@ -61229,6 +63110,8 @@ function loadJsUserFunctions(jsFiles, wasmFiles, nativeBridge2) {
|
|
|
61229
63110
|
"wasm",
|
|
61230
63111
|
"native",
|
|
61231
63112
|
"importJS",
|
|
63113
|
+
"callHandle",
|
|
63114
|
+
"toNumber",
|
|
61232
63115
|
libFile.source
|
|
61233
63116
|
);
|
|
61234
63117
|
const exports = factory(
|
|
@@ -61238,7 +63121,9 @@ function loadJsUserFunctions(jsFiles, wasmFiles, nativeBridge2) {
|
|
|
61238
63121
|
dummyRegister,
|
|
61239
63122
|
wasmInstance,
|
|
61240
63123
|
nativeLib,
|
|
61241
|
-
importJS
|
|
63124
|
+
importJS,
|
|
63125
|
+
callHandle,
|
|
63126
|
+
toNumber
|
|
61242
63127
|
);
|
|
61243
63128
|
libCache.set(name, exports);
|
|
61244
63129
|
return exports;
|
|
@@ -61276,6 +63161,8 @@ function loadJsUserFunctions(jsFiles, wasmFiles, nativeBridge2) {
|
|
|
61276
63161
|
"wasm",
|
|
61277
63162
|
"native",
|
|
61278
63163
|
"importJS",
|
|
63164
|
+
"callHandle",
|
|
63165
|
+
"toNumber",
|
|
61279
63166
|
file.source
|
|
61280
63167
|
);
|
|
61281
63168
|
factory(
|
|
@@ -61285,7 +63172,9 @@ function loadJsUserFunctions(jsFiles, wasmFiles, nativeBridge2) {
|
|
|
61285
63172
|
registerFn,
|
|
61286
63173
|
wasmInstance,
|
|
61287
63174
|
nativeLib,
|
|
61288
|
-
importJS
|
|
63175
|
+
importJS,
|
|
63176
|
+
callHandle,
|
|
63177
|
+
toNumber
|
|
61289
63178
|
);
|
|
61290
63179
|
if (!builtin) {
|
|
61291
63180
|
throw new Error(
|
|
@@ -61537,6 +63426,7 @@ function resolveFunctionImpl(name, argTypes, callSite, index2) {
|
|
|
61537
63426
|
for (const argType of argTypes) {
|
|
61538
63427
|
if (argType?.kind === "ClassInstance") {
|
|
61539
63428
|
const className = argType.className;
|
|
63429
|
+
if (index2.classConstructors.get(className) === name) continue;
|
|
61540
63430
|
if (!candidates.includes(className) && (index2.classInstanceMethods.get(className)?.has(name) || index2.classStaticMethods.get(className)?.has(name))) {
|
|
61541
63431
|
candidates.push(className);
|
|
61542
63432
|
}
|
|
@@ -61645,12 +63535,25 @@ var Environment = class _Environment {
|
|
|
61645
63535
|
}
|
|
61646
63536
|
/** Function ID for persistent variable storage */
|
|
61647
63537
|
persistentFuncId;
|
|
63538
|
+
/** Call-site variable names of this frame's arguments, for `inputname`.
|
|
63539
|
+
* Entry i is the name of the variable passed as argument i+1, or '' if
|
|
63540
|
+
* that argument was not a plain variable. Undefined when the call did
|
|
63541
|
+
* not originate from an interpreted call expression (e.g. feval, JIT).
|
|
63542
|
+
* Read directly off the executing frame — the interpreter has only
|
|
63543
|
+
* function-level scoping, so `this.env` is the frame while a body runs. */
|
|
63544
|
+
inputArgNames;
|
|
61648
63545
|
/** Back-reference to the runtime (needed for global/persistent access) */
|
|
61649
63546
|
rt = null;
|
|
61650
63547
|
/** Set when a `@nestedFn` handle has been created that captures this env
|
|
61651
63548
|
* (or an ancestor). Tells the function-exit cleanup that clearing this
|
|
61652
63549
|
* env would strand the handle's closure, so locals must be left alive. */
|
|
61653
63550
|
nestedHandleCreated = false;
|
|
63551
|
+
/** For a nested-function frame: the names of this function's own formal
|
|
63552
|
+
* input/output arguments. These are always local — a write must never be
|
|
63553
|
+
* redirected to a same-named variable in the parent, even before the
|
|
63554
|
+
* output has been assigned. (MATLAB scopes a nested function's formal
|
|
63555
|
+
* arguments to that function; only other variables are shared.) */
|
|
63556
|
+
nestedLocalNames;
|
|
61654
63557
|
get(name) {
|
|
61655
63558
|
if (this._globalNames !== void 0 && this._globalNames.has(name) && this.rt) {
|
|
61656
63559
|
const v = this.rt.$g[name];
|
|
@@ -61669,7 +63572,7 @@ var Environment = class _Environment {
|
|
|
61669
63572
|
if (old !== void 0) decref(this.rt, old);
|
|
61670
63573
|
return;
|
|
61671
63574
|
}
|
|
61672
|
-
if (this.isNested && !this.vars.has(name) && this.parent) {
|
|
63575
|
+
if (this.isNested && !this.vars.has(name) && this.parent && !this.nestedLocalNames?.has(name)) {
|
|
61673
63576
|
const owner = this.findOwner(name);
|
|
61674
63577
|
if (owner) {
|
|
61675
63578
|
owner.setLocal(name, value);
|
|
@@ -62864,6 +64767,7 @@ function makeRootContext(interp, registry3) {
|
|
|
62864
64767
|
var interpreterExec_exports = {};
|
|
62865
64768
|
__export(interpreterExec_exports, {
|
|
62866
64769
|
assignLValue: () => assignLValue,
|
|
64770
|
+
computeInputNames: () => computeInputNames,
|
|
62867
64771
|
evalAnonFunc: () => evalAnonFunc,
|
|
62868
64772
|
evalArgs: () => evalArgs,
|
|
62869
64773
|
evalBinary: () => evalBinary,
|
|
@@ -62890,6 +64794,15 @@ __export(interpreterExec_exports, {
|
|
|
62890
64794
|
writeLValueBase: () => writeLValueBase
|
|
62891
64795
|
});
|
|
62892
64796
|
|
|
64797
|
+
// src/numbl-core/jitDeclineDiagnostics.ts
|
|
64798
|
+
var lastDecline = null;
|
|
64799
|
+
function recordJitDecline(d) {
|
|
64800
|
+
lastDecline = d;
|
|
64801
|
+
}
|
|
64802
|
+
function getLastJitDecline() {
|
|
64803
|
+
return lastDecline;
|
|
64804
|
+
}
|
|
64805
|
+
|
|
62893
64806
|
// src/numbl-core/runtime/cow.ts
|
|
62894
64807
|
function cowCopy(v) {
|
|
62895
64808
|
if (isRuntimeTensor(v)) {
|
|
@@ -63166,6 +65079,11 @@ function execStmtInner(stmt) {
|
|
|
63166
65079
|
case "Global": {
|
|
63167
65080
|
for (const name of stmt.names) {
|
|
63168
65081
|
this.env.globalNames.add(name);
|
|
65082
|
+
if (this.rt && !(name in this.rt.$g)) {
|
|
65083
|
+
const empty = RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
65084
|
+
incref(empty);
|
|
65085
|
+
this.rt.$g[name] = empty;
|
|
65086
|
+
}
|
|
63169
65087
|
}
|
|
63170
65088
|
return null;
|
|
63171
65089
|
}
|
|
@@ -63187,14 +65105,16 @@ function execStmtInner(stmt) {
|
|
|
63187
65105
|
case "Directive": {
|
|
63188
65106
|
if (stmt.directive === "assert_jit") {
|
|
63189
65107
|
const wantC = stmt.args.includes("c");
|
|
65108
|
+
const decline = getLastJitDecline();
|
|
65109
|
+
const why = decline ? ` Most recent JIT decline (${decline.where}, ${decline.kind}): ${decline.message}` : ` (no JIT decline reason was recorded \u2014 the unit may have been declined before lowering, e.g. an unsupported input type.)`;
|
|
63190
65110
|
if (this.optimization === "1") {
|
|
63191
65111
|
throw new RuntimeError(
|
|
63192
|
-
`%!numbl:assert_jit: expected the enclosing loop/function/script to be JS-JIT-compiled at --opt 1, but it ran in the interpreter
|
|
65112
|
+
`%!numbl:assert_jit: expected the enclosing loop/function/script to be JS-JIT-compiled at --opt 1, but it ran in the interpreter.${why} (Run with --opt 0 to silence.)`
|
|
63193
65113
|
);
|
|
63194
65114
|
}
|
|
63195
65115
|
if (this.optimization === "2" && wantC) {
|
|
63196
65116
|
throw new RuntimeError(
|
|
63197
|
-
`%!numbl:assert_jit c: expected the enclosing loop/function/script to be C-JIT-compiled at --opt 2, but it ran in the interpreter
|
|
65117
|
+
`%!numbl:assert_jit c: expected the enclosing loop/function/script to be C-JIT-compiled at --opt 2, but it ran in the interpreter.${why} (Run with --opt 0 to silence.)`
|
|
63198
65118
|
);
|
|
63199
65119
|
}
|
|
63200
65120
|
}
|
|
@@ -63277,6 +65197,10 @@ function evalExprNargout(expr, nargout) {
|
|
|
63277
65197
|
if (isRuntimeStructArray(rv)) {
|
|
63278
65198
|
return rv.elements.length;
|
|
63279
65199
|
}
|
|
65200
|
+
if (isRuntimeClassInstanceArray(rv)) {
|
|
65201
|
+
if (ctx.numIndices === 1) return rv.elements.length;
|
|
65202
|
+
return ctx.dimIndex < rv.shape.length ? rv.shape[ctx.dimIndex] : 1;
|
|
65203
|
+
}
|
|
63280
65204
|
if (isRuntimeSparseMatrix(rv)) {
|
|
63281
65205
|
if (ctx.numIndices === 1) return rv.m * rv.n;
|
|
63282
65206
|
return ctx.dimIndex === 0 ? rv.m : ctx.dimIndex === 1 ? rv.n : 1;
|
|
@@ -63437,6 +65361,23 @@ function evalExprNargout(expr, nargout) {
|
|
|
63437
65361
|
throw new RuntimeError("Interpreter does not yet support meta.class");
|
|
63438
65362
|
}
|
|
63439
65363
|
}
|
|
65364
|
+
function computeInputNames(argExprs, callerEnv) {
|
|
65365
|
+
const names = [];
|
|
65366
|
+
let blanked = false;
|
|
65367
|
+
for (const a of argExprs) {
|
|
65368
|
+
if (blanked) {
|
|
65369
|
+
names.push("");
|
|
65370
|
+
} else if (a.type === "Ident" && callerEnv.has(a.name)) {
|
|
65371
|
+
names.push(a.name);
|
|
65372
|
+
} else if (a.type === "IndexCell" || a.type === "Member" || a.type === "MemberDynamic") {
|
|
65373
|
+
names.push("");
|
|
65374
|
+
blanked = true;
|
|
65375
|
+
} else {
|
|
65376
|
+
names.push("");
|
|
65377
|
+
}
|
|
65378
|
+
}
|
|
65379
|
+
return names;
|
|
65380
|
+
}
|
|
63440
65381
|
function evalArgs(argExprs) {
|
|
63441
65382
|
const args = [];
|
|
63442
65383
|
for (const a of argExprs) {
|
|
@@ -63566,6 +65507,7 @@ function evalFuncCall(expr, nargout) {
|
|
|
63566
65507
|
const c = getConstant(expr.name);
|
|
63567
65508
|
if (c !== void 0) return c;
|
|
63568
65509
|
}
|
|
65510
|
+
this.pendingInputNames = expr.args.length > 0 ? computeInputNames(expr.args, this.env) : void 0;
|
|
63569
65511
|
return this.callFunction(expr.name, args, nargout);
|
|
63570
65512
|
}
|
|
63571
65513
|
function evalMember(expr, nargout) {
|
|
@@ -63745,7 +65687,14 @@ function makeFuncHandle(name) {
|
|
|
63745
65687
|
);
|
|
63746
65688
|
};
|
|
63747
65689
|
fn.jsFnExpectsNargout = true;
|
|
63748
|
-
|
|
65690
|
+
let narg = getIBuiltinNargin(name);
|
|
65691
|
+
if (narg === void 0) {
|
|
65692
|
+
try {
|
|
65693
|
+
narg = this.declaredNargin(name);
|
|
65694
|
+
} catch {
|
|
65695
|
+
narg = void 0;
|
|
65696
|
+
}
|
|
65697
|
+
}
|
|
63749
65698
|
if (narg !== void 0) fn.nargin = narg;
|
|
63750
65699
|
if (isNested) {
|
|
63751
65700
|
fn.releaseExtra = () => capturedEnv.clearLocals();
|
|
@@ -64034,6 +65983,7 @@ __export(interpreterFunctions_exports, {
|
|
|
64034
65983
|
callNestedFunction: () => callNestedFunction,
|
|
64035
65984
|
callUserFunction: () => callUserFunction,
|
|
64036
65985
|
collectClassProperties: () => collectClassProperties,
|
|
65986
|
+
declaredNargin: () => declaredNargin,
|
|
64037
65987
|
evalInLocalScope: () => evalInLocalScope,
|
|
64038
65988
|
findExternalMethod: () => findExternalMethod,
|
|
64039
65989
|
findFunctionInClassFile: () => findFunctionInClassFile,
|
|
@@ -64336,6 +66286,30 @@ register("isa", (ctx, args) => {
|
|
|
64336
66286
|
if (args.length !== 2) return FALL_THROUGH;
|
|
64337
66287
|
return ctx.rt.isa(args[0], args[1]);
|
|
64338
66288
|
});
|
|
66289
|
+
register("superclasses", (ctx, args) => {
|
|
66290
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
66291
|
+
const v = ensureRuntimeValue(args[0]);
|
|
66292
|
+
let className;
|
|
66293
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v)) {
|
|
66294
|
+
className = v.className;
|
|
66295
|
+
} else if (isRuntimeChar(v) || isRuntimeString(v)) {
|
|
66296
|
+
className = toString(v);
|
|
66297
|
+
}
|
|
66298
|
+
const names = [];
|
|
66299
|
+
if (className) {
|
|
66300
|
+
const seen = /* @__PURE__ */ new Set([className]);
|
|
66301
|
+
let current = ctx.rt.getClassParentName(className);
|
|
66302
|
+
while (current && !seen.has(current)) {
|
|
66303
|
+
names.push(current);
|
|
66304
|
+
seen.add(current);
|
|
66305
|
+
current = ctx.rt.getClassParentName(current);
|
|
66306
|
+
}
|
|
66307
|
+
}
|
|
66308
|
+
return RTV.cell(
|
|
66309
|
+
names.map((n) => RTV.string(n)),
|
|
66310
|
+
[names.length, 1]
|
|
66311
|
+
);
|
|
66312
|
+
});
|
|
64339
66313
|
register("__inferred_type_str", (_ctx, args) => {
|
|
64340
66314
|
if (args.length !== 1) return FALL_THROUGH;
|
|
64341
66315
|
const rv = ensureRuntimeValue(args[0]);
|
|
@@ -64360,6 +66334,44 @@ register("nargout", (ctx, args) => {
|
|
|
64360
66334
|
const v = ctx.env.get("$nargout");
|
|
64361
66335
|
return v !== void 0 ? v : 0;
|
|
64362
66336
|
});
|
|
66337
|
+
register("inputname", (ctx, args) => {
|
|
66338
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
66339
|
+
const narginVal = ctx.env.get("$nargin");
|
|
66340
|
+
if (typeof narginVal !== "number") {
|
|
66341
|
+
throw new RuntimeError(
|
|
66342
|
+
"You can only call 'inputname' from within a MATLAB function."
|
|
66343
|
+
);
|
|
66344
|
+
}
|
|
66345
|
+
const k = toNumber(ensureRuntimeValue(args[0]));
|
|
66346
|
+
if (!Number.isInteger(k) || k < 1) {
|
|
66347
|
+
throw new RuntimeError(
|
|
66348
|
+
"Argument number must be a positive integer scalar."
|
|
66349
|
+
);
|
|
66350
|
+
}
|
|
66351
|
+
if (k > narginVal) {
|
|
66352
|
+
throw new RuntimeError(
|
|
66353
|
+
"Argument number exceeds number of function input arguments."
|
|
66354
|
+
);
|
|
66355
|
+
}
|
|
66356
|
+
const names = ctx.env.inputArgNames;
|
|
66357
|
+
const name = names && k <= names.length ? names[k - 1] : "";
|
|
66358
|
+
return RTV.char(name);
|
|
66359
|
+
});
|
|
66360
|
+
register("properties", (ctx, args) => {
|
|
66361
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
66362
|
+
const v = ensureRuntimeValue(args[0]);
|
|
66363
|
+
let names;
|
|
66364
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v)) {
|
|
66365
|
+
names = ctx.classPublicProperties(v.className);
|
|
66366
|
+
} else if (isRuntimeChar(v) || isRuntimeString(v)) {
|
|
66367
|
+
names = ctx.classPublicProperties(toString(v));
|
|
66368
|
+
}
|
|
66369
|
+
if (!names) return RTV.cell([], [0, 1]);
|
|
66370
|
+
return RTV.cell(
|
|
66371
|
+
names.map((n) => RTV.string(n)),
|
|
66372
|
+
[names.length, 1]
|
|
66373
|
+
);
|
|
66374
|
+
});
|
|
64363
66375
|
register("narginchk", (ctx, args) => {
|
|
64364
66376
|
if (args.length !== 2) return FALL_THROUGH;
|
|
64365
66377
|
const narginVal = ctx.env.get("$nargin");
|
|
@@ -64464,10 +66476,14 @@ function callFunction(name, args, nargout) {
|
|
|
64464
66476
|
source: ""
|
|
64465
66477
|
};
|
|
64466
66478
|
return void 0;
|
|
64467
|
-
}
|
|
66479
|
+
},
|
|
66480
|
+
classPublicProperties: (n) => classPublicProperties(this, n)
|
|
64468
66481
|
};
|
|
64469
66482
|
const result = specialHandler(ctx, args, nargout);
|
|
64470
|
-
if (result !== FALL_THROUGH)
|
|
66483
|
+
if (result !== FALL_THROUGH) {
|
|
66484
|
+
this.pendingInputNames = void 0;
|
|
66485
|
+
return result;
|
|
66486
|
+
}
|
|
64471
66487
|
}
|
|
64472
66488
|
const nested = this.env.getNestedFunction(name);
|
|
64473
66489
|
if (nested) {
|
|
@@ -64487,6 +66503,75 @@ function callFunction(name, args, nargout) {
|
|
|
64487
66503
|
}
|
|
64488
66504
|
throw new RuntimeError(`Undefined function or variable '${name}'`);
|
|
64489
66505
|
}
|
|
66506
|
+
function narginFromParams(params) {
|
|
66507
|
+
const hasVarargin = params.length > 0 && params[params.length - 1] === "varargin";
|
|
66508
|
+
return hasVarargin ? -params.length : params.length;
|
|
66509
|
+
}
|
|
66510
|
+
function paramsInFile(interp, fileName, funcName) {
|
|
66511
|
+
const ast = interp.ctx.getCachedAST(fileName);
|
|
66512
|
+
for (const stmt of ast.body) {
|
|
66513
|
+
if (stmt.type === "Function" && stmt.name === funcName) return stmt.params;
|
|
66514
|
+
}
|
|
66515
|
+
return void 0;
|
|
66516
|
+
}
|
|
66517
|
+
function declaredNargin(name) {
|
|
66518
|
+
const nested = this.env.getNestedFunction(name);
|
|
66519
|
+
if (nested) return narginFromParams(nested.fn.params);
|
|
66520
|
+
const callSite = {
|
|
66521
|
+
file: this.currentFile,
|
|
66522
|
+
...this.currentClassName ? { className: this.currentClassName } : {},
|
|
66523
|
+
...this.currentMethodName ? { methodName: this.currentMethodName } : {}
|
|
66524
|
+
};
|
|
66525
|
+
const target = resolveFunction(name, [], callSite, this.functionIndex);
|
|
66526
|
+
if (!target) return void 0;
|
|
66527
|
+
let params;
|
|
66528
|
+
switch (target.kind) {
|
|
66529
|
+
case "localFunction": {
|
|
66530
|
+
const { source } = target;
|
|
66531
|
+
if (source.from === "main") {
|
|
66532
|
+
params = this.mainLocalFunctions.get(target.name)?.params;
|
|
66533
|
+
} else if (source.from === "workspaceFile") {
|
|
66534
|
+
params = this.findFunctionInWorkspaceFile(source.wsName, target.name)?.params ?? void 0;
|
|
66535
|
+
} else if (source.from === "classFile") {
|
|
66536
|
+
params = this.findFunctionInClassFile(
|
|
66537
|
+
source.className,
|
|
66538
|
+
target.name,
|
|
66539
|
+
source.methodScope
|
|
66540
|
+
)?.params ?? void 0;
|
|
66541
|
+
} else if (source.from === "privateFile") {
|
|
66542
|
+
params = paramsInFile(this, source.callerFile, target.name);
|
|
66543
|
+
}
|
|
66544
|
+
break;
|
|
66545
|
+
}
|
|
66546
|
+
case "workspaceFunction": {
|
|
66547
|
+
const dotIdx = target.name.lastIndexOf(".");
|
|
66548
|
+
const primaryName = dotIdx >= 0 ? target.name.slice(dotIdx + 1) : target.name;
|
|
66549
|
+
params = this.findFunctionInWorkspaceFile(target.name, primaryName)?.params ?? void 0;
|
|
66550
|
+
if (params === void 0) {
|
|
66551
|
+
const entry = this.ctx.registry.filesByFuncName.get(target.name);
|
|
66552
|
+
if (entry) {
|
|
66553
|
+
const ast = this.ctx.getCachedAST(entry.fileName);
|
|
66554
|
+
for (const stmt of ast.body) {
|
|
66555
|
+
if (stmt.type === "Function") {
|
|
66556
|
+
params = stmt.params;
|
|
66557
|
+
break;
|
|
66558
|
+
}
|
|
66559
|
+
}
|
|
66560
|
+
}
|
|
66561
|
+
}
|
|
66562
|
+
break;
|
|
66563
|
+
}
|
|
66564
|
+
case "privateFunction": {
|
|
66565
|
+
const entry = this.ctx.getPrivateFileEntry(
|
|
66566
|
+
target.callerFile,
|
|
66567
|
+
target.name
|
|
66568
|
+
);
|
|
66569
|
+
if (entry) params = paramsInFile(this, entry.fileName, target.name);
|
|
66570
|
+
break;
|
|
66571
|
+
}
|
|
66572
|
+
}
|
|
66573
|
+
return params !== void 0 ? narginFromParams(params) : void 0;
|
|
66574
|
+
}
|
|
64490
66575
|
function interpretTarget(target, args, nargout) {
|
|
64491
66576
|
switch (target.kind) {
|
|
64492
66577
|
case "builtin": {
|
|
@@ -64655,18 +66740,12 @@ function interpretWorkspaceFunction(target, args, nargout) {
|
|
|
64655
66740
|
if (entry) {
|
|
64656
66741
|
const ast = this.ctx.getCachedAST(entry.fileName);
|
|
64657
66742
|
return this.withFileContext(entry.fileName, void 0, void 0, () => {
|
|
64658
|
-
const
|
|
64659
|
-
|
|
64660
|
-
|
|
64661
|
-
|
|
64662
|
-
if (stmt.type === "Function") continue;
|
|
64663
|
-
const signal = this.execStmt(stmt);
|
|
64664
|
-
if (signal instanceof ReturnSignal) break;
|
|
64665
|
-
}
|
|
64666
|
-
return this.ans;
|
|
64667
|
-
} finally {
|
|
64668
|
-
this.env = savedEnv;
|
|
66743
|
+
for (const stmt of ast.body) {
|
|
66744
|
+
if (stmt.type === "Function") continue;
|
|
66745
|
+
const signal = this.execStmt(stmt);
|
|
66746
|
+
if (signal instanceof ReturnSignal) break;
|
|
64669
66747
|
}
|
|
66748
|
+
return this.ans;
|
|
64670
66749
|
});
|
|
64671
66750
|
}
|
|
64672
66751
|
throw new RuntimeError(`Workspace function '${target.name}' not found`);
|
|
@@ -64733,6 +66812,21 @@ function instantiateClass(className, args, nargout) {
|
|
|
64733
66812
|
if (!classInfo) {
|
|
64734
66813
|
return this.rt.callClassMethod(className, className, nargout, args);
|
|
64735
66814
|
}
|
|
66815
|
+
if (classInfo.isOldStyle) {
|
|
66816
|
+
const ctorName = classInfo.constructorName ?? className;
|
|
66817
|
+
const ctorFn = this.findExternalMethod(classInfo, ctorName);
|
|
66818
|
+
if (!ctorFn)
|
|
66819
|
+
throw new RuntimeError(
|
|
66820
|
+
`Constructor for old-style class '${className}' not found`
|
|
66821
|
+
);
|
|
66822
|
+
const fileName = classInfo.externalMethodFiles.get(ctorName)?.fileName ?? classInfo.fileName;
|
|
66823
|
+
return this.withFileContext(
|
|
66824
|
+
fileName,
|
|
66825
|
+
className,
|
|
66826
|
+
ctorName,
|
|
66827
|
+
() => this.callUserFunction(ctorFn, args, nargout)
|
|
66828
|
+
);
|
|
66829
|
+
}
|
|
64736
66830
|
const { propertyNames, propertyDefaults } = this.collectClassProperties(classInfo);
|
|
64737
66831
|
const defaults = /* @__PURE__ */ new Map();
|
|
64738
66832
|
for (const [propName, defaultExpr] of propertyDefaults) {
|
|
@@ -64756,7 +66850,7 @@ function instantiateClass(className, args, nargout) {
|
|
|
64756
66850
|
function interpretConstructor(classInfo, args, nargout) {
|
|
64757
66851
|
const constructorName = classInfo.constructorName;
|
|
64758
66852
|
if (!constructorName) return args[0];
|
|
64759
|
-
for (const member of classInfo.ast
|
|
66853
|
+
for (const member of classInfo.ast?.members ?? []) {
|
|
64760
66854
|
if (member.type !== "Methods") continue;
|
|
64761
66855
|
for (const methodStmt of member.body) {
|
|
64762
66856
|
if (methodStmt.type === "Function" && methodStmt.name === constructorName) {
|
|
@@ -64798,6 +66892,8 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
64798
66892
|
if (!hasVarargoutDecl && nargout > declaredRegularOutputs) {
|
|
64799
66893
|
throw new RuntimeError("Too many output arguments.");
|
|
64800
66894
|
}
|
|
66895
|
+
const callInputNames = this.pendingInputNames;
|
|
66896
|
+
this.pendingInputNames = void 0;
|
|
64801
66897
|
const sharedArgs = args;
|
|
64802
66898
|
if (narginOverride === void 0 && this.registry.size > 0) {
|
|
64803
66899
|
const r = this.registry.dispatchCall(fn, sharedArgs, nargout, this);
|
|
@@ -64831,6 +66927,7 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
64831
66927
|
}
|
|
64832
66928
|
fnEnv.set("$nargin", narginOverride ?? args.length);
|
|
64833
66929
|
fnEnv.set("$nargout", nargout);
|
|
66930
|
+
fnEnv.inputArgNames = callInputNames;
|
|
64834
66931
|
for (const stmt of fn.body) {
|
|
64835
66932
|
if (stmt.type === "Function") {
|
|
64836
66933
|
fnEnv.nestedFunctions.set(stmt.name, {
|
|
@@ -64907,10 +67004,13 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
64907
67004
|
}
|
|
64908
67005
|
}
|
|
64909
67006
|
function callNestedFunction(fn, parentEnv, args, nargout) {
|
|
67007
|
+
const callInputNames = this.pendingInputNames;
|
|
67008
|
+
this.pendingInputNames = void 0;
|
|
64910
67009
|
const fnEnv = new Environment(parentEnv);
|
|
64911
67010
|
fnEnv.isNested = true;
|
|
64912
67011
|
fnEnv.rt = this.rt;
|
|
64913
67012
|
fnEnv.persistentFuncId = `${this.currentFile}:${fn.name}`;
|
|
67013
|
+
fnEnv.nestedLocalNames = /* @__PURE__ */ new Set([...fn.params, ...fn.outputs]);
|
|
64914
67014
|
const hasVarargin = fn.params.length > 0 && fn.params[fn.params.length - 1] === "varargin";
|
|
64915
67015
|
const regularParams = hasVarargin ? fn.params.slice(0, -1) : fn.params;
|
|
64916
67016
|
for (let i = 0; i < regularParams.length; i++) {
|
|
@@ -64924,6 +67024,15 @@ function callNestedFunction(fn, parentEnv, args, nargout) {
|
|
|
64924
67024
|
}
|
|
64925
67025
|
fnEnv.setLocal("$nargin", args.length);
|
|
64926
67026
|
fnEnv.setLocal("$nargout", nargout);
|
|
67027
|
+
fnEnv.inputArgNames = callInputNames;
|
|
67028
|
+
for (const stmt of fn.body) {
|
|
67029
|
+
if (stmt.type === "Function") {
|
|
67030
|
+
fnEnv.nestedFunctions.set(stmt.name, {
|
|
67031
|
+
fn: funcDefFromStmt(stmt),
|
|
67032
|
+
env: fnEnv
|
|
67033
|
+
});
|
|
67034
|
+
}
|
|
67035
|
+
}
|
|
64927
67036
|
const savedEnv = this.env;
|
|
64928
67037
|
this.env = fnEnv;
|
|
64929
67038
|
this.rt.pushCleanupScope();
|
|
@@ -65062,7 +67171,7 @@ function findMethodInClass(classInfo, methodName) {
|
|
|
65062
67171
|
const cacheKey = `method:${classInfo.name}:${methodName}`;
|
|
65063
67172
|
const cached = this.functionDefCache.get(cacheKey);
|
|
65064
67173
|
if (cached) return cached;
|
|
65065
|
-
for (const member of classInfo.ast
|
|
67174
|
+
for (const member of classInfo.ast?.members ?? []) {
|
|
65066
67175
|
if (member.type !== "Methods") continue;
|
|
65067
67176
|
for (const methodStmt of member.body) {
|
|
65068
67177
|
if (methodStmt.type === "Function" && methodStmt.name === methodName) {
|
|
@@ -65119,6 +67228,36 @@ function collectClassProperties(classInfo) {
|
|
|
65119
67228
|
}
|
|
65120
67229
|
return { propertyNames, propertyDefaults };
|
|
65121
67230
|
}
|
|
67231
|
+
function classPublicProperties(interp, className) {
|
|
67232
|
+
let info = interp.ctx.getClassInfo(className);
|
|
67233
|
+
if (!info) return void 0;
|
|
67234
|
+
const out = [];
|
|
67235
|
+
const seen = /* @__PURE__ */ new Set();
|
|
67236
|
+
while (info) {
|
|
67237
|
+
const ast = info.ast;
|
|
67238
|
+
if (ast) {
|
|
67239
|
+
for (const member of ast.members) {
|
|
67240
|
+
if (member.type !== "Properties") continue;
|
|
67241
|
+
const hidden = member.attributes.some((a) => {
|
|
67242
|
+
const n = a.name.toLowerCase();
|
|
67243
|
+
if (n !== "access" && n !== "getaccess") return false;
|
|
67244
|
+
const val = (a.value ?? "").toLowerCase();
|
|
67245
|
+
return val === "private" || val === "protected";
|
|
67246
|
+
});
|
|
67247
|
+
if (hidden) continue;
|
|
67248
|
+
for (const pn of member.names) {
|
|
67249
|
+
if (!seen.has(pn)) {
|
|
67250
|
+
seen.add(pn);
|
|
67251
|
+
out.push(pn);
|
|
67252
|
+
}
|
|
67253
|
+
}
|
|
67254
|
+
}
|
|
67255
|
+
}
|
|
67256
|
+
if (!info.superClass || info.superClass === "handle") break;
|
|
67257
|
+
info = interp.ctx.getClassInfo(info.superClass);
|
|
67258
|
+
}
|
|
67259
|
+
return out;
|
|
67260
|
+
}
|
|
65122
67261
|
function isHandleClass(classInfo) {
|
|
65123
67262
|
let parentName = classInfo.superClass;
|
|
65124
67263
|
while (parentName) {
|
|
@@ -65237,6 +67376,10 @@ var Interpreter = class {
|
|
|
65237
67376
|
workspaceEnv;
|
|
65238
67377
|
/** @internal The caller's environment — for evalin/assignin('caller', ...) */
|
|
65239
67378
|
callerEnv;
|
|
67379
|
+
/** @internal Call-site variable names for the next user-function call, set
|
|
67380
|
+
* by `evalFuncCall` and consumed by `callUserFunction` to support
|
|
67381
|
+
* `inputname`. One-shot: cleared as soon as it is consumed. */
|
|
67382
|
+
pendingInputNames;
|
|
65240
67383
|
/** @internal Stack of [base, dimIndex, numIndices] for resolving `end` keyword in indexing. */
|
|
65241
67384
|
endContextStack = [];
|
|
65242
67385
|
/** @internal Number of enclosing `for` / `while` loop bodies the
|
|
@@ -65498,6 +67641,37 @@ function extractClassInfo(classDef, qualifiedName, fileName, source) {
|
|
|
65498
67641
|
externalMethodFiles: /* @__PURE__ */ new Map()
|
|
65499
67642
|
};
|
|
65500
67643
|
}
|
|
67644
|
+
function makeOldStyleClassInfo(qualifiedName, baseName, constructorFile, methodFiles) {
|
|
67645
|
+
const externalMethodFiles = /* @__PURE__ */ new Map();
|
|
67646
|
+
externalMethodFiles.set(baseName, {
|
|
67647
|
+
fileName: constructorFile.fileName,
|
|
67648
|
+
source: constructorFile.source
|
|
67649
|
+
});
|
|
67650
|
+
const methodNames = /* @__PURE__ */ new Set();
|
|
67651
|
+
for (const mf of methodFiles) {
|
|
67652
|
+
externalMethodFiles.set(mf.name, {
|
|
67653
|
+
fileName: mf.fileName,
|
|
67654
|
+
source: mf.source
|
|
67655
|
+
});
|
|
67656
|
+
methodNames.add(mf.name);
|
|
67657
|
+
}
|
|
67658
|
+
return {
|
|
67659
|
+
name: baseName,
|
|
67660
|
+
qualifiedName,
|
|
67661
|
+
fileName: constructorFile.fileName,
|
|
67662
|
+
source: constructorFile.source,
|
|
67663
|
+
superClass: null,
|
|
67664
|
+
propertyNames: [],
|
|
67665
|
+
propertyDefaults: /* @__PURE__ */ new Map(),
|
|
67666
|
+
methodNames,
|
|
67667
|
+
staticMethodNames: /* @__PURE__ */ new Set(),
|
|
67668
|
+
constructorName: baseName,
|
|
67669
|
+
inferiorClasses: [],
|
|
67670
|
+
ast: null,
|
|
67671
|
+
isOldStyle: true,
|
|
67672
|
+
externalMethodFiles
|
|
67673
|
+
};
|
|
67674
|
+
}
|
|
65501
67675
|
|
|
65502
67676
|
// src/numbl-core/lowering/loweringContext.ts
|
|
65503
67677
|
function createWorkspaceRegistry() {
|
|
@@ -65690,8 +67864,41 @@ var LoweringContext = class _LoweringContext {
|
|
|
65690
67864
|
}
|
|
65691
67865
|
}
|
|
65692
67866
|
}
|
|
67867
|
+
const startsWithClassdef = (source) => {
|
|
67868
|
+
let t = source.trimStart();
|
|
67869
|
+
while (t.startsWith("%")) {
|
|
67870
|
+
const nl = t.indexOf("\n");
|
|
67871
|
+
if (nl < 0) return false;
|
|
67872
|
+
t = t.slice(nl + 1).trimStart();
|
|
67873
|
+
}
|
|
67874
|
+
return t.startsWith("classdef");
|
|
67875
|
+
};
|
|
65693
67876
|
for (const [className, group] of classFolderGroups) {
|
|
65694
|
-
|
|
67877
|
+
const hasRealClassdef = !!group.classDefFile && startsWithClassdef(group.classDefFile.source);
|
|
67878
|
+
if (!hasRealClassdef) {
|
|
67879
|
+
const dotIdx = className.lastIndexOf(".");
|
|
67880
|
+
const baseName = dotIdx >= 0 ? className.slice(dotIdx + 1) : className;
|
|
67881
|
+
const methodBase = (f) => f.name.split("/").pop().replace(/\.m$/, "");
|
|
67882
|
+
const ctorFile = group.classDefFile ?? group.methodFiles.find((f) => methodBase(f) === baseName);
|
|
67883
|
+
if (!ctorFile) {
|
|
67884
|
+
continue;
|
|
67885
|
+
}
|
|
67886
|
+
const methodFiles = group.methodFiles.filter((f) => f !== ctorFile).map((f) => ({
|
|
67887
|
+
name: methodBase(f),
|
|
67888
|
+
fileName: f.name,
|
|
67889
|
+
source: f.source
|
|
67890
|
+
}));
|
|
67891
|
+
if (!this.registry.classesByName.has(className)) {
|
|
67892
|
+
this.registry.classesByName.set(
|
|
67893
|
+
className,
|
|
67894
|
+
makeOldStyleClassInfo(
|
|
67895
|
+
className,
|
|
67896
|
+
baseName,
|
|
67897
|
+
{ fileName: ctorFile.name, source: ctorFile.source },
|
|
67898
|
+
methodFiles
|
|
67899
|
+
)
|
|
67900
|
+
);
|
|
67901
|
+
}
|
|
65695
67902
|
continue;
|
|
65696
67903
|
}
|
|
65697
67904
|
this.registerWorkspaceClass(className, group.classDefFile);
|
|
@@ -65927,7 +68134,7 @@ var LoweringContext = class _LoweringContext {
|
|
|
65927
68134
|
if (!info) return null;
|
|
65928
68135
|
if (info.ctx) return info.ctx;
|
|
65929
68136
|
const ctx = new _LoweringContext(info.source, info.fileName);
|
|
65930
|
-
for (const member of info.ast
|
|
68137
|
+
for (const member of info.ast?.members ?? []) {
|
|
65931
68138
|
if (member.type !== "Methods") continue;
|
|
65932
68139
|
for (const methodStmt of member.body) {
|
|
65933
68140
|
if (methodStmt.type !== "Function") continue;
|
|
@@ -66086,6 +68293,7 @@ var LoweringContext = class _LoweringContext {
|
|
|
66086
68293
|
for (const m of info.methodNames) instanceMethods.add(m);
|
|
66087
68294
|
for (const m of info.staticMethodNames) staticMethods.add(m);
|
|
66088
68295
|
for (const m of info.externalMethodFiles.keys()) {
|
|
68296
|
+
if (info.isOldStyle && m === info.constructorName) continue;
|
|
66089
68297
|
if (!info.staticMethodNames.has(m)) {
|
|
66090
68298
|
instanceMethods.add(m);
|
|
66091
68299
|
}
|
|
@@ -66129,10 +68337,43 @@ var LoweringContext = class _LoweringContext {
|
|
|
66129
68337
|
}
|
|
66130
68338
|
}
|
|
66131
68339
|
const fileImports = /* @__PURE__ */ new Map();
|
|
68340
|
+
const gatherImports = (body, out) => {
|
|
68341
|
+
for (const stmt of body) {
|
|
68342
|
+
switch (stmt.type) {
|
|
68343
|
+
case "Import":
|
|
68344
|
+
out.push(stmt);
|
|
68345
|
+
break;
|
|
68346
|
+
case "Function":
|
|
68347
|
+
case "While":
|
|
68348
|
+
case "For":
|
|
68349
|
+
gatherImports(stmt.body, out);
|
|
68350
|
+
break;
|
|
68351
|
+
case "If":
|
|
68352
|
+
gatherImports(stmt.thenBody, out);
|
|
68353
|
+
for (const b of stmt.elseifBlocks) gatherImports(b.body, out);
|
|
68354
|
+
if (stmt.elseBody) gatherImports(stmt.elseBody, out);
|
|
68355
|
+
break;
|
|
68356
|
+
case "Switch":
|
|
68357
|
+
for (const c of stmt.cases) gatherImports(c.body, out);
|
|
68358
|
+
if (stmt.otherwise) gatherImports(stmt.otherwise, out);
|
|
68359
|
+
break;
|
|
68360
|
+
case "TryCatch":
|
|
68361
|
+
gatherImports(stmt.tryBody, out);
|
|
68362
|
+
gatherImports(stmt.catchBody, out);
|
|
68363
|
+
break;
|
|
68364
|
+
case "ClassDef":
|
|
68365
|
+
for (const member of stmt.members) {
|
|
68366
|
+
if (member.type === "Methods") gatherImports(member.body, out);
|
|
68367
|
+
}
|
|
68368
|
+
break;
|
|
68369
|
+
}
|
|
68370
|
+
}
|
|
68371
|
+
};
|
|
66132
68372
|
const collectImportsFromBody = (body, fileName) => {
|
|
66133
68373
|
const entries = [];
|
|
66134
|
-
|
|
66135
|
-
|
|
68374
|
+
const importStmts = [];
|
|
68375
|
+
gatherImports(body, importStmts);
|
|
68376
|
+
for (const stmt of importStmts) {
|
|
66136
68377
|
if (stmt.wildcard) {
|
|
66137
68378
|
entries.push({ wildcard: true, namespace: stmt.path.join(".") });
|
|
66138
68379
|
} else {
|
|
@@ -66207,6 +68448,10 @@ var LoweringContext = class _LoweringContext {
|
|
|
66207
68448
|
|
|
66208
68449
|
// src/numbl-core/stdlib-bundle.ts
|
|
66209
68450
|
var stdlibFiles = [
|
|
68451
|
+
{
|
|
68452
|
+
name: "TriRep.m",
|
|
68453
|
+
source: "classdef TriRep < triangulation\n % (Not recommended) Triangulation representation. Provided for legacy\n % code; use triangulation instead. TriRep inherits freeBoundary,\n % vertexAttachments, etc. from triangulation and exposes the legacy\n % property names X (vertex coordinates) and Triangulation (connectivity).\n %\n % TR = TriRep(tri, x, y)\n % TR = TriRep(tri, x, y, z)\n % TR = TriRep(tri, P)\n properties\n X\n Triangulation\n end\n methods\n function obj = TriRep(tri, varargin)\n obj = obj@triangulation(tri, varargin{:});\n obj.X = obj.Points;\n obj.Triangulation = obj.ConnectivityList;\n end\n end\nend\n"
|
|
68454
|
+
},
|
|
66210
68455
|
{
|
|
66211
68456
|
name: "addOptional.m",
|
|
66212
68457
|
source: "function addOptional(obj, name, default, validator)\n if nargin < 4\n obj.addOptional(name, default);\n else\n obj.addOptional(name, default, validator);\n end\nend\n"
|
|
@@ -66234,6 +68479,10 @@ var stdlibFiles = [
|
|
|
66234
68479
|
{
|
|
66235
68480
|
name: "readmatrix.m",
|
|
66236
68481
|
source: "function A = readmatrix(filename, varargin)\n % Parse name-value pairs\n delimiter = '';\n numHeaderLines = -1; % -1 means auto-detect\n\n i = 1;\n while i <= length(varargin)\n if ischar(varargin{i}) || isstring(varargin{i})\n key = lower(char(varargin{i}));\n if strcmp(key, 'delimiter')\n delimiter = char(varargin{i+1});\n i = i + 2;\n elseif strcmp(key, 'numheaderlines')\n numHeaderLines = varargin{i+1};\n i = i + 2;\n else\n % Skip unknown name-value pairs\n i = i + 2;\n end\n else\n i = i + 1;\n end\n end\n\n % Auto-detect delimiter from extension if not specified\n if isempty(delimiter)\n [~, ~, ext] = fileparts(filename);\n if strcmp(ext, '.csv')\n delimiter = ',';\n else\n delimiter = ''; % will split on whitespace\n end\n end\n\n % Read the entire file\n txt = fileread(filename);\n\n % Split into lines\n lines = strsplit(txt, sprintf('\\n'));\n\n % Remove trailing empty line (from trailing newline)\n if ~isempty(lines) && strcmp(strtrim(char(lines{end})), '')\n lines = lines(1:end-1);\n end\n\n if isempty(lines)\n A = [];\n return;\n end\n\n % Auto-detect header lines: skip lines that can't be fully parsed as numbers\n if numHeaderLines < 0\n numHeaderLines = 0;\n for k = 1:length(lines)\n line = strtrim(char(lines{k}));\n if strcmp(line, '')\n numHeaderLines = numHeaderLines + 1;\n continue;\n end\n if ~isempty(delimiter)\n parts = strsplit(line, delimiter);\n else\n parts = strsplit(line);\n end\n allNumeric = true;\n for j = 1:length(parts)\n val = str2double(strtrim(char(parts{j})));\n if isnan(val)\n token = strtrim(char(parts{j}));\n % Allow NaN, Inf, -Inf as valid numeric tokens\n if ~strcmpi(token, 'nan') && ~strcmpi(token, 'inf') && ~strcmpi(token, '-inf')\n allNumeric = false;\n break;\n end\n end\n end\n if allNumeric\n break;\n else\n numHeaderLines = numHeaderLines + 1;\n end\n end\n end\n\n % Parse data lines\n dataLines = lines(numHeaderLines+1:end);\n nRows = length(dataLines);\n if nRows == 0\n A = [];\n return;\n end\n\n % First pass: determine number of columns from first data line\n firstLine = strtrim(char(dataLines{1}));\n if ~isempty(delimiter)\n parts = strsplit(firstLine, delimiter);\n else\n parts = strsplit(firstLine);\n end\n nCols = length(parts);\n\n A = zeros(nRows, nCols);\n for r = 1:nRows\n line = strtrim(char(dataLines{r}));\n if strcmp(line, '')\n A(r, :) = NaN;\n continue;\n end\n if ~isempty(delimiter)\n parts = strsplit(line, delimiter);\n else\n parts = strsplit(line);\n end\n for c = 1:min(length(parts), nCols)\n val = str2double(strtrim(char(parts{c})));\n if isnan(val)\n token = strtrim(char(parts{c}));\n if strcmpi(token, 'nan')\n A(r, c) = NaN;\n elseif strcmpi(token, 'inf')\n A(r, c) = Inf;\n elseif strcmpi(token, '-inf')\n A(r, c) = -Inf;\n else\n A(r, c) = NaN; % non-numeric data becomes NaN\n end\n else\n A(r, c) = val;\n end\n end\n % Fill missing columns with NaN\n if length(parts) < nCols\n A(r, length(parts)+1:nCols) = NaN;\n end\n end\nend\n"
|
|
68482
|
+
},
|
|
68483
|
+
{
|
|
68484
|
+
name: "triangulation.m",
|
|
68485
|
+
source: "classdef triangulation\n % Triangulation representation providing topological queries over a\n % triangle (or tetrahedron) mesh. Mirrors a subset of MATLAB's\n % triangulation class.\n %\n % TR = triangulation(tri, P) % P is an n-by-d coordinate matrix\n % TR = triangulation(tri, x, y) % 2-D vertex coordinate columns\n % TR = triangulation(tri, x, y, z) % 3-D vertex coordinate columns\n properties\n Points\n ConnectivityList\n end\n methods\n function obj = triangulation(tri, varargin)\n if nargin == 0\n return;\n end\n obj.ConnectivityList = tri;\n if numel(varargin) == 1\n obj.Points = varargin{1};\n elseif numel(varargin) >= 2\n obj.Points = [varargin{:}];\n else\n error('triangulation: vertex coordinates are required');\n end\n end\n\n function [F, P] = freeBoundary(obj)\n % Free boundary facets: the edges referenced by exactly one\n % triangle, ordered into connected, consistently oriented loops.\n tri = obj.ConnectivityList;\n E = [tri(:, [1 2]); tri(:, [2 3]); tri(:, [3 1])];\n Es = sort(E, 2);\n [~, ~, ic] = unique(Es, 'rows');\n counts = accumarray(ic, 1);\n isB = counts(ic) == 1;\n bedges = E(isB, :);\n\n n = size(bedges, 1);\n F = zeros(n, 2);\n used = false(n, 1);\n pos = 1;\n while pos <= n\n startRow = find(~used, 1);\n if isempty(startRow)\n break;\n end\n cur = startRow;\n loopStart = bedges(cur, 1);\n while true\n F(pos, :) = bedges(cur, :);\n used(cur) = true;\n pos = pos + 1;\n nextv = bedges(cur, 2);\n if nextv == loopStart\n break;\n end\n cand = find(~used & bedges(:, 1) == nextv, 1);\n if isempty(cand)\n break;\n end\n cur = cand;\n end\n end\n\n if nargout > 1\n vid = unique(F(:));\n P = obj.Points(vid, :);\n remap = zeros(max(vid), 1);\n remap(vid) = 1:numel(vid);\n F = remap(F);\n end\n end\n\n function V = vertexAttachments(obj, id)\n % IDs of the triangles attached to each vertex, returned as a\n % cell array with one row vector of triangle IDs per vertex.\n tri = obj.ConnectivityList;\n nv = size(obj.Points, 1);\n if nargin < 2\n id = (1:nv)';\n end\n id = id(:);\n V = cell(numel(id), 1);\n for k = 1:numel(id)\n V{k} = find(any(tri == id(k), 2))';\n end\n end\n end\nend\n"
|
|
66237
68486
|
}
|
|
66238
68487
|
];
|
|
66239
68488
|
var shimFiles = [
|
|
@@ -75877,6 +78126,30 @@ var sin = defineUnaryRealMath({
|
|
|
75877
78126
|
complex: { cFnComplex: "mtoc2_csin", jsFnComplex: cSin }
|
|
75878
78127
|
});
|
|
75879
78128
|
|
|
78129
|
+
// src/numbl-core/jit/builtins/defs/math/rand.ts
|
|
78130
|
+
var rand = {
|
|
78131
|
+
name: "rand",
|
|
78132
|
+
transfer(argTypes, nargout) {
|
|
78133
|
+
if (nargout > 1) {
|
|
78134
|
+
throw new UnsupportedConstruct(
|
|
78135
|
+
`'rand' does not support multi-output (nargout=${nargout})`
|
|
78136
|
+
);
|
|
78137
|
+
}
|
|
78138
|
+
if (argTypes.length !== 0) {
|
|
78139
|
+
throw new UnsupportedConstruct(
|
|
78140
|
+
`JS-JIT 'rand' supports only the scalar form rand() so far (got ${argTypes.length} arg(s)); matrix/seed forms run in the interpreter`
|
|
78141
|
+
);
|
|
78142
|
+
}
|
|
78143
|
+
return [scalarDouble("nonneg")];
|
|
78144
|
+
},
|
|
78145
|
+
emitJs() {
|
|
78146
|
+
return "$rand()";
|
|
78147
|
+
},
|
|
78148
|
+
call() {
|
|
78149
|
+
return [rngRandom()];
|
|
78150
|
+
}
|
|
78151
|
+
};
|
|
78152
|
+
|
|
75880
78153
|
// src/numbl-core/jit/builtins/defs/math/tan.ts
|
|
75881
78154
|
var tan = defineUnaryRealMath({
|
|
75882
78155
|
name: "tan",
|
|
@@ -81260,6 +83533,7 @@ for (const b of [
|
|
|
81260
83533
|
stdBuiltin,
|
|
81261
83534
|
min,
|
|
81262
83535
|
max,
|
|
83536
|
+
rand,
|
|
81263
83537
|
any,
|
|
81264
83538
|
all,
|
|
81265
83539
|
zeros,
|
|
@@ -87099,12 +89373,13 @@ function emitJsProgram(prog, opts = {}) {
|
|
|
87099
89373
|
const wrapperLines = [];
|
|
87100
89374
|
if (opts.exposeSpec !== void 0) {
|
|
87101
89375
|
wrapperLines.push(
|
|
87102
|
-
`return function ($h) { globalThis.$write = $h.write; globalThis.$plotDispatch = $h.plotDispatch; return ${opts.exposeSpec}; };`
|
|
89376
|
+
`return function ($h) { globalThis.$write = $h.write; globalThis.$plotDispatch = $h.plotDispatch; globalThis.$rand = $h.rand; return ${opts.exposeSpec}; };`
|
|
87103
89377
|
);
|
|
87104
89378
|
} else {
|
|
87105
89379
|
wrapperLines.push("function run($h) {");
|
|
87106
89380
|
wrapperLines.push(" globalThis.$write = $h.write;");
|
|
87107
89381
|
wrapperLines.push(" globalThis.$plotDispatch = $h.plotDispatch;");
|
|
89382
|
+
wrapperLines.push(" globalThis.$rand = $h.rand;");
|
|
87108
89383
|
const locals = collectAssignedLocals(prog.topLevelStmts);
|
|
87109
89384
|
if (locals.length > 0) {
|
|
87110
89385
|
wrapperLines.push(` let ${locals.join(", ")};`);
|
|
@@ -91810,6 +94085,7 @@ var Workspace = class _Workspace {
|
|
|
91810
94085
|
}
|
|
91811
94086
|
};
|
|
91812
94087
|
for (const [name, info] of this.ctx.registry.classesByName) {
|
|
94088
|
+
if (info.isOldStyle) continue;
|
|
91813
94089
|
registerOrDefer(
|
|
91814
94090
|
name,
|
|
91815
94091
|
() => registerClassDef(
|
|
@@ -91823,7 +94099,7 @@ var Workspace = class _Workspace {
|
|
|
91823
94099
|
if (this.classes.has(name) || this.failedClassValidations.has(name)) {
|
|
91824
94100
|
throw new UnsupportedConstruct(
|
|
91825
94101
|
`class '${name}' is defined both locally and as a workspace class`,
|
|
91826
|
-
info.ast
|
|
94102
|
+
info.ast?.span
|
|
91827
94103
|
);
|
|
91828
94104
|
}
|
|
91829
94105
|
registerOrDefer(name, () => registerClassDef(info.ast, info.fileName));
|
|
@@ -91917,7 +94193,7 @@ var Workspace = class _Workspace {
|
|
|
91917
94193
|
if (!ast) {
|
|
91918
94194
|
throw new UnsupportedConstruct(
|
|
91919
94195
|
`internal: external method file '${mf.fileName}' for '${info.qualifiedName}.${methodName}' was not parsed`,
|
|
91920
|
-
info.ast
|
|
94196
|
+
info.ast?.span
|
|
91921
94197
|
);
|
|
91922
94198
|
}
|
|
91923
94199
|
let primary = null;
|
|
@@ -91933,7 +94209,7 @@ var Workspace = class _Workspace {
|
|
|
91933
94209
|
if (!primary) {
|
|
91934
94210
|
throw new UnsupportedConstruct(
|
|
91935
94211
|
`external method file '${mf.fileName}' has no function`,
|
|
91936
|
-
info.ast
|
|
94212
|
+
info.ast?.span
|
|
91937
94213
|
);
|
|
91938
94214
|
}
|
|
91939
94215
|
out.set(methodName, primary);
|
|
@@ -92298,6 +94574,7 @@ function getOrCreateSession(interp) {
|
|
|
92298
94574
|
function buildHostHelpers(rt) {
|
|
92299
94575
|
return {
|
|
92300
94576
|
write: (s) => rt.output(s),
|
|
94577
|
+
rand: () => rngRandom(),
|
|
92301
94578
|
plotDispatch: (name, args) => {
|
|
92302
94579
|
const runtimeArgs = args.map((a) => jitToNumbl(a));
|
|
92303
94580
|
const handled = dispatchPlotBuiltin(
|
|
@@ -92390,6 +94667,11 @@ var jitCallExecutor = {
|
|
|
92390
94667
|
return { specFn };
|
|
92391
94668
|
} catch (e) {
|
|
92392
94669
|
if (e instanceof UnsupportedConstruct || e instanceof TypeError2) {
|
|
94670
|
+
recordJitDecline({
|
|
94671
|
+
message: e.message,
|
|
94672
|
+
kind: e.constructor.name,
|
|
94673
|
+
where: "jit-call"
|
|
94674
|
+
});
|
|
92393
94675
|
return null;
|
|
92394
94676
|
}
|
|
92395
94677
|
throw e;
|
|
@@ -92516,6 +94798,11 @@ var jitLoopExecutor = {
|
|
|
92516
94798
|
return { specFn };
|
|
92517
94799
|
} catch (e) {
|
|
92518
94800
|
if (e instanceof UnsupportedConstruct || e instanceof TypeError2) {
|
|
94801
|
+
recordJitDecline({
|
|
94802
|
+
message: e.message,
|
|
94803
|
+
kind: e.constructor.name,
|
|
94804
|
+
where: "jit-loop"
|
|
94805
|
+
});
|
|
92519
94806
|
return null;
|
|
92520
94807
|
}
|
|
92521
94808
|
throw e;
|
|
@@ -92656,6 +94943,11 @@ var jitTopLevelExecutor = {
|
|
|
92656
94943
|
return { specFn, nargout };
|
|
92657
94944
|
} catch (e) {
|
|
92658
94945
|
if (e instanceof UnsupportedConstruct || e instanceof TypeError2) {
|
|
94946
|
+
recordJitDecline({
|
|
94947
|
+
message: e.message,
|
|
94948
|
+
kind: e.constructor.name,
|
|
94949
|
+
where: "jit-top-level"
|
|
94950
|
+
});
|
|
92659
94951
|
return null;
|
|
92660
94952
|
}
|
|
92661
94953
|
throw e;
|
|
@@ -93330,7 +95622,8 @@ import {
|
|
|
93330
95622
|
rmSync,
|
|
93331
95623
|
rmdirSync,
|
|
93332
95624
|
renameSync,
|
|
93333
|
-
chmodSync
|
|
95625
|
+
chmodSync,
|
|
95626
|
+
realpathSync
|
|
93334
95627
|
} from "fs";
|
|
93335
95628
|
import { unzipSync } from "fflate";
|
|
93336
95629
|
import { execFileSync } from "child_process";
|
|
@@ -93722,6 +96015,51 @@ var NodeFileIOAdapter = class {
|
|
|
93722
96015
|
return false;
|
|
93723
96016
|
}
|
|
93724
96017
|
}
|
|
96018
|
+
copyfile(source, destination, force) {
|
|
96019
|
+
try {
|
|
96020
|
+
const src = expandTilde(source);
|
|
96021
|
+
const srcStat = statSync2(src);
|
|
96022
|
+
let dst = expandTilde(destination);
|
|
96023
|
+
try {
|
|
96024
|
+
if (statSync2(dst).isDirectory()) dst = join3(dst, basename(src));
|
|
96025
|
+
} catch {
|
|
96026
|
+
}
|
|
96027
|
+
if (srcStat.isDirectory()) {
|
|
96028
|
+
copyDirRecursive(src, dst);
|
|
96029
|
+
return true;
|
|
96030
|
+
}
|
|
96031
|
+
const parent = dirname(dst);
|
|
96032
|
+
if (parent && parent !== "." && parent !== "/") {
|
|
96033
|
+
mkdirSync(parent, { recursive: true });
|
|
96034
|
+
}
|
|
96035
|
+
if (force) {
|
|
96036
|
+
try {
|
|
96037
|
+
chmodSync(dst, 438);
|
|
96038
|
+
} catch {
|
|
96039
|
+
}
|
|
96040
|
+
}
|
|
96041
|
+
writeFileSync(dst, readFileSync3(src));
|
|
96042
|
+
return true;
|
|
96043
|
+
} catch {
|
|
96044
|
+
return false;
|
|
96045
|
+
}
|
|
96046
|
+
}
|
|
96047
|
+
fileattrib(path) {
|
|
96048
|
+
try {
|
|
96049
|
+
const p2 = expandTilde(path);
|
|
96050
|
+
const st2 = statSync2(p2);
|
|
96051
|
+
const mode = st2.mode;
|
|
96052
|
+
return {
|
|
96053
|
+
Name: realpathSync(p2),
|
|
96054
|
+
directory: st2.isDirectory(),
|
|
96055
|
+
UserRead: (mode & 256) !== 0,
|
|
96056
|
+
UserWrite: (mode & 128) !== 0,
|
|
96057
|
+
UserExecute: (mode & 64) !== 0
|
|
96058
|
+
};
|
|
96059
|
+
} catch {
|
|
96060
|
+
return null;
|
|
96061
|
+
}
|
|
96062
|
+
}
|
|
93725
96063
|
deleteFile(pattern) {
|
|
93726
96064
|
const p2 = expandTilde(pattern);
|
|
93727
96065
|
if (p2.includes("*") || p2.includes("?")) {
|
|
@@ -96365,6 +98703,7 @@ async function load() {
|
|
|
96365
98703
|
const { loadQhull } = await import("qhull-wasm");
|
|
96366
98704
|
const qhull = await loadQhull();
|
|
96367
98705
|
setDelaunayBackend((points, dim) => qhull.delaunay(points, dim).facets);
|
|
98706
|
+
setConvexHullBackend((points, dim) => qhull.convexHull(points, dim).facets);
|
|
96368
98707
|
}
|
|
96369
98708
|
|
|
96370
98709
|
// src/cli.ts
|
|
@@ -96504,6 +98843,7 @@ function findTestFiles(dir) {
|
|
|
96504
98843
|
}
|
|
96505
98844
|
async function runTests(dir, optimization, fastMath) {
|
|
96506
98845
|
loadNativeAddon(fastMath ?? false);
|
|
98846
|
+
await loadQhullBackend();
|
|
96507
98847
|
const absDir = resolve2(process.cwd(), dir);
|
|
96508
98848
|
const testFiles = findTestFiles(absDir);
|
|
96509
98849
|
if (testFiles.length === 0) {
|
|
@@ -96599,6 +98939,11 @@ Options (for build-site):
|
|
|
96599
98939
|
--title <text> Site title (default: from numbl-project.json or dir name)
|
|
96600
98940
|
--entry <file> Default file to open, e.g. main.m (default: README.md or
|
|
96601
98941
|
the first script)
|
|
98942
|
+
--repo-url <url> Source repository URL, shown as a link in the deployed
|
|
98943
|
+
site (default: from numbl-project.json)
|
|
98944
|
+
--max-initial-output-panel-height <px>
|
|
98945
|
+
Cap the initial height (px) of the output panel so the
|
|
98946
|
+
figure panel below it starts larger (desktop layout)
|
|
96602
98947
|
|
|
96603
98948
|
Options (for parse):
|
|
96604
98949
|
--dump-ast <file> Write the AST as indented JSON to <file> (default: stdout)
|
|
@@ -97128,6 +99473,9 @@ async function cmdBuildAddon(args) {
|
|
|
97128
99473
|
}
|
|
97129
99474
|
var SITE_DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([".git", ".github", "node_modules"]);
|
|
97130
99475
|
var SITE_MAX_FILE_BYTES = 25 * 1024 * 1024;
|
|
99476
|
+
function isAgentInstructionFile(name) {
|
|
99477
|
+
return name === "GEMINI.md" || /^(CLAUDE|AGENT)[^/]*\.md$/i.test(name);
|
|
99478
|
+
}
|
|
97131
99479
|
function readNumblIgnore(projectDir) {
|
|
97132
99480
|
const p2 = join7(projectDir, ".numblignore");
|
|
97133
99481
|
if (!existsSync3(p2)) return [];
|
|
@@ -97176,6 +99524,7 @@ function collectSiteFiles(projectDir, outDirAbs, ignore) {
|
|
|
97176
99524
|
walk2(full);
|
|
97177
99525
|
} else if (e.isFile()) {
|
|
97178
99526
|
if (e.name === ".numblignore" || e.name === ".DS_Store") continue;
|
|
99527
|
+
if (isAgentInstructionFile(e.name)) continue;
|
|
97179
99528
|
const st2 = statSync3(full);
|
|
97180
99529
|
if (st2.size > SITE_MAX_FILE_BYTES) {
|
|
97181
99530
|
console.error(
|
|
@@ -97196,6 +99545,8 @@ async function cmdBuildSite(args) {
|
|
|
97196
99545
|
let base;
|
|
97197
99546
|
let title;
|
|
97198
99547
|
let entry;
|
|
99548
|
+
let repoUrl;
|
|
99549
|
+
let maxInitialOutputPanelHeight;
|
|
97199
99550
|
const positional = [];
|
|
97200
99551
|
for (let i = 0; i < args.length; i++) {
|
|
97201
99552
|
const a = args[i];
|
|
@@ -97203,7 +99554,17 @@ async function cmdBuildSite(args) {
|
|
|
97203
99554
|
else if (a === "--base") base = args[++i];
|
|
97204
99555
|
else if (a === "--title") title = args[++i];
|
|
97205
99556
|
else if (a === "--entry") entry = args[++i];
|
|
97206
|
-
else if (a
|
|
99557
|
+
else if (a === "--repo-url") repoUrl = args[++i];
|
|
99558
|
+
else if (a === "--max-initial-output-panel-height") {
|
|
99559
|
+
const n = Number(args[++i]);
|
|
99560
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
99561
|
+
console.error(
|
|
99562
|
+
"Error: --max-initial-output-panel-height must be a positive number"
|
|
99563
|
+
);
|
|
99564
|
+
process.exit(1);
|
|
99565
|
+
}
|
|
99566
|
+
maxInitialOutputPanelHeight = n;
|
|
99567
|
+
} else if (a.startsWith("-")) {
|
|
97207
99568
|
console.error(`Unknown option: ${a}`);
|
|
97208
99569
|
process.exit(1);
|
|
97209
99570
|
} else positional.push(a);
|
|
@@ -97255,6 +99616,9 @@ async function cmdBuildSite(args) {
|
|
|
97255
99616
|
}
|
|
97256
99617
|
if (title !== void 0) manifest.title = title;
|
|
97257
99618
|
if (entry !== void 0) manifest.entry = entry;
|
|
99619
|
+
if (repoUrl !== void 0) manifest.repository = repoUrl;
|
|
99620
|
+
if (maxInitialOutputPanelHeight !== void 0)
|
|
99621
|
+
manifest.maxInitialOutputPanelHeight = maxInitialOutputPanelHeight;
|
|
97258
99622
|
if (!manifest.title) manifest.title = basename2(projectDirAbs);
|
|
97259
99623
|
const zipEntries = {};
|
|
97260
99624
|
for (const f of collected) {
|
|
@@ -97275,14 +99639,22 @@ async function cmdBuildSite(args) {
|
|
|
97275
99639
|
"warning: project bundle exceeds 50 MB; GitHub Pages may be slow or reject it"
|
|
97276
99640
|
);
|
|
97277
99641
|
}
|
|
99642
|
+
const buildId = createHash2("sha256").update(zip).digest("hex").slice(0, 16);
|
|
97278
99643
|
const indexPath = join7(outDirAbs, "index.html");
|
|
99644
|
+
let injectJs = `window.__NUMBL_BUILD_ID__=${JSON.stringify(buildId)};`;
|
|
97279
99645
|
if (normBase) {
|
|
97280
|
-
|
|
97281
|
-
const inject = `<script>window.__NUMBL_BASE__=${JSON.stringify(normBase)};</script>`;
|
|
97282
|
-
indexHtml = indexHtml.includes("<!-- numbl:base -->") ? indexHtml.replace("<!-- numbl:base -->", inject) : indexHtml.replace("</head>", ` ${inject}
|
|
97283
|
-
</head>`);
|
|
97284
|
-
writeFileSync4(indexPath, indexHtml);
|
|
99646
|
+
injectJs += `window.__NUMBL_BASE__=${JSON.stringify(normBase)};`;
|
|
97285
99647
|
}
|
|
99648
|
+
const inject = `<script>${injectJs}</script>`;
|
|
99649
|
+
let indexHtml = readFileSync6(indexPath, "utf-8");
|
|
99650
|
+
indexHtml = indexHtml.includes("<!-- numbl:base -->") ? indexHtml.replace("<!-- numbl:base -->", inject) : indexHtml.replace("</head>", ` ${inject}
|
|
99651
|
+
</head>`);
|
|
99652
|
+
const escapeHtml = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
99653
|
+
indexHtml = indexHtml.replace(
|
|
99654
|
+
/<title>.*?<\/title>/,
|
|
99655
|
+
`<title>${escapeHtml(manifest.title)}</title>`
|
|
99656
|
+
);
|
|
99657
|
+
writeFileSync4(indexPath, indexHtml);
|
|
97286
99658
|
const redirectTarget = normBase ?? "/";
|
|
97287
99659
|
writeFileSync4(
|
|
97288
99660
|
join7(outDirAbs, "404.html"),
|