numbl 0.4.6 → 0.4.7
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 +2363 -220
- 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.js +2349 -216
- 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/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-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-RucHpf4b.js +4826 -0
- package/dist-site-viewer/assets/numbl-worker-IO39kohI.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: () => ({
|
|
@@ -39117,8 +39310,8 @@ function registerSpecialBuiltins(rt) {
|
|
|
39117
39310
|
if (args.length === 0) return nargout >= 1 ? RTV.num(0) : void 0;
|
|
39118
39311
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
39119
39312
|
if (margs.length === 2 && isRuntimeChar(margs[0]) && isRuntimeChar(margs[1])) {
|
|
39120
|
-
const
|
|
39121
|
-
if (
|
|
39313
|
+
const mode = toString(margs[0]);
|
|
39314
|
+
if (mode === "on" || mode === "off") {
|
|
39122
39315
|
if (nargout === 0) return void 0;
|
|
39123
39316
|
return RTV.struct(
|
|
39124
39317
|
/* @__PURE__ */ new Map([
|
|
@@ -39127,6 +39320,14 @@ function registerSpecialBuiltins(rt) {
|
|
|
39127
39320
|
])
|
|
39128
39321
|
);
|
|
39129
39322
|
}
|
|
39323
|
+
if (mode === "query") {
|
|
39324
|
+
return RTV.struct(
|
|
39325
|
+
/* @__PURE__ */ new Map([
|
|
39326
|
+
["state", RTV.char("on")],
|
|
39327
|
+
["identifier", margs[1]]
|
|
39328
|
+
])
|
|
39329
|
+
);
|
|
39330
|
+
}
|
|
39130
39331
|
}
|
|
39131
39332
|
let fmtIdx = 0;
|
|
39132
39333
|
if (margs.length >= 2 && isRuntimeChar(margs[0]) && toString(margs[0]).includes(":")) {
|
|
@@ -40649,6 +40850,10 @@ function _eigsImpl(rt, nargout, args) {
|
|
|
40649
40850
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
40650
40851
|
if (margs.length < 1)
|
|
40651
40852
|
throw new RuntimeError("eigs requires at least 1 argument");
|
|
40853
|
+
for (let i = 0; i < margs.length; i++) {
|
|
40854
|
+
const mi = margs[i];
|
|
40855
|
+
if (isRuntimeSparseMatrix(mi)) margs[i] = sparseToDense(mi);
|
|
40856
|
+
}
|
|
40652
40857
|
let afun = null;
|
|
40653
40858
|
let A = null;
|
|
40654
40859
|
let n;
|
|
@@ -41566,12 +41771,17 @@ function getMember(rt, base, name) {
|
|
|
41566
41771
|
`No property or method '${name}' for class '${mv.className}'`
|
|
41567
41772
|
);
|
|
41568
41773
|
}
|
|
41774
|
+
if (isRuntimeClassInstanceArray(mv)) {
|
|
41775
|
+
const values = mv.elements.map(
|
|
41776
|
+
(el) => ensureRuntimeValue(getMember(rt, el, name))
|
|
41777
|
+
);
|
|
41778
|
+
return horzcat(...values);
|
|
41779
|
+
}
|
|
41569
41780
|
return getRTValueField(mv, name);
|
|
41570
41781
|
}
|
|
41571
|
-
function getMemberDynamic(base, nameExpr) {
|
|
41572
|
-
const mv = ensureRuntimeValue(base);
|
|
41782
|
+
function getMemberDynamic(rt, base, nameExpr) {
|
|
41573
41783
|
const name = toString(ensureRuntimeValue(nameExpr));
|
|
41574
|
-
return
|
|
41784
|
+
return ensureRuntimeValue(getMember(rt, base, name));
|
|
41575
41785
|
}
|
|
41576
41786
|
function getMemberOrEmpty(base, name) {
|
|
41577
41787
|
try {
|
|
@@ -41593,7 +41803,7 @@ function setMemberReturn(rt, base, name, rhs) {
|
|
|
41593
41803
|
if (setter) {
|
|
41594
41804
|
rt.activeAccessors.add(accessorKey);
|
|
41595
41805
|
try {
|
|
41596
|
-
const result = setter(
|
|
41806
|
+
const result = setter(0, base, rhs);
|
|
41597
41807
|
return result !== void 0 ? result : base;
|
|
41598
41808
|
} finally {
|
|
41599
41809
|
rt.activeAccessors.delete(accessorKey);
|
|
@@ -41605,10 +41815,8 @@ function setMemberReturn(rt, base, name, rhs) {
|
|
|
41605
41815
|
return setRTValueField(mv, name, rhsMv, rt);
|
|
41606
41816
|
}
|
|
41607
41817
|
function setMemberDynamicReturn(rt, base, nameExpr, rhs) {
|
|
41608
|
-
const mv = ensureRuntimeValue(base);
|
|
41609
41818
|
const name = toString(ensureRuntimeValue(nameExpr));
|
|
41610
|
-
|
|
41611
|
-
return setRTValueField(mv, name, rhsMv, rt);
|
|
41819
|
+
return ensureRuntimeValue(setMemberReturn(rt, base, name, rhs));
|
|
41612
41820
|
}
|
|
41613
41821
|
function subsrefCall(rt, base, names) {
|
|
41614
41822
|
const mv = ensureRuntimeValue(base);
|
|
@@ -44257,7 +44465,7 @@ var Runtime = class _Runtime {
|
|
|
44257
44465
|
return getMember(this, base, name);
|
|
44258
44466
|
}
|
|
44259
44467
|
getMemberDynamic(base, nameExpr) {
|
|
44260
|
-
return getMemberDynamic(base, nameExpr);
|
|
44468
|
+
return getMemberDynamic(this, base, nameExpr);
|
|
44261
44469
|
}
|
|
44262
44470
|
getMemberOrEmpty(base, name) {
|
|
44263
44471
|
return getMemberOrEmpty(base, name);
|
|
@@ -45564,6 +45772,8 @@ defineBuiltin({
|
|
|
45564
45772
|
if (isRuntimeComplexNumber(v)) return v.im === 0;
|
|
45565
45773
|
if (isRuntimeTensor(v)) return imagAllZero(v.imag);
|
|
45566
45774
|
if (isRuntimeSparseMatrix(v)) return !v.pi || imagAllZero(v.pi);
|
|
45775
|
+
if (isRuntimeCell(v) || isRuntimeStruct(v) || isRuntimeStructArray(v) || isRuntimeString(v) || isRuntimeFunction(v))
|
|
45776
|
+
return false;
|
|
45567
45777
|
return true;
|
|
45568
45778
|
}
|
|
45569
45779
|
}
|
|
@@ -46035,10 +46245,79 @@ defineBuiltin({
|
|
|
46035
46245
|
name: "ischar",
|
|
46036
46246
|
cases: [anyToLogicalCase((args) => isRuntimeChar(args[0]))]
|
|
46037
46247
|
});
|
|
46248
|
+
defineBuiltin({
|
|
46249
|
+
name: "isstr",
|
|
46250
|
+
cases: [anyToLogicalCase((args) => isRuntimeChar(args[0]))]
|
|
46251
|
+
});
|
|
46038
46252
|
defineBuiltin({
|
|
46039
46253
|
name: "isstring",
|
|
46040
46254
|
cases: [anyToLogicalCase((args) => isRuntimeString(args[0]))]
|
|
46041
46255
|
});
|
|
46256
|
+
var MATLAB_KEYWORDS = /* @__PURE__ */ new Set([
|
|
46257
|
+
"break",
|
|
46258
|
+
"case",
|
|
46259
|
+
"catch",
|
|
46260
|
+
"classdef",
|
|
46261
|
+
"continue",
|
|
46262
|
+
"else",
|
|
46263
|
+
"elseif",
|
|
46264
|
+
"end",
|
|
46265
|
+
"for",
|
|
46266
|
+
"function",
|
|
46267
|
+
"global",
|
|
46268
|
+
"if",
|
|
46269
|
+
"otherwise",
|
|
46270
|
+
"parfor",
|
|
46271
|
+
"persistent",
|
|
46272
|
+
"return",
|
|
46273
|
+
"spmd",
|
|
46274
|
+
"switch",
|
|
46275
|
+
"try",
|
|
46276
|
+
"while"
|
|
46277
|
+
]);
|
|
46278
|
+
function singleRowText(v) {
|
|
46279
|
+
if (isRuntimeChar(v)) {
|
|
46280
|
+
if (v.shape && v.shape.length >= 1 && v.shape[0] > 1) return null;
|
|
46281
|
+
return v.value;
|
|
46282
|
+
}
|
|
46283
|
+
if (isRuntimeString(v)) return v;
|
|
46284
|
+
return null;
|
|
46285
|
+
}
|
|
46286
|
+
defineBuiltin({
|
|
46287
|
+
name: "isvarname",
|
|
46288
|
+
cases: [
|
|
46289
|
+
anyToLogicalCase((args) => {
|
|
46290
|
+
const s = singleRowText(args[0]);
|
|
46291
|
+
if (s === null || s.length === 0 || s.length > 63) return false;
|
|
46292
|
+
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(s)) return false;
|
|
46293
|
+
return !MATLAB_KEYWORDS.has(s);
|
|
46294
|
+
})
|
|
46295
|
+
]
|
|
46296
|
+
});
|
|
46297
|
+
defineBuiltin({
|
|
46298
|
+
name: "iskeyword",
|
|
46299
|
+
cases: [
|
|
46300
|
+
{
|
|
46301
|
+
// iskeyword() with no args returns the list of keywords (column cell).
|
|
46302
|
+
match: (argTypes) => {
|
|
46303
|
+
if (argTypes.length === 0) return [{ kind: "cell" }];
|
|
46304
|
+
if (argTypes.length === 1) return [{ kind: "boolean" }];
|
|
46305
|
+
return null;
|
|
46306
|
+
},
|
|
46307
|
+
apply: (args) => {
|
|
46308
|
+
if (args.length === 0) {
|
|
46309
|
+
const names = [...MATLAB_KEYWORDS].sort();
|
|
46310
|
+
return RTV.cell(
|
|
46311
|
+
names.map((n) => RTV.char(n)),
|
|
46312
|
+
[names.length, 1]
|
|
46313
|
+
);
|
|
46314
|
+
}
|
|
46315
|
+
const s = singleRowText(args[0]);
|
|
46316
|
+
return RTV.logical(s !== null && MATLAB_KEYWORDS.has(s));
|
|
46317
|
+
}
|
|
46318
|
+
}
|
|
46319
|
+
]
|
|
46320
|
+
});
|
|
46042
46321
|
defineBuiltin({
|
|
46043
46322
|
name: "iscell",
|
|
46044
46323
|
cases: [anyToLogicalCase((args) => isRuntimeCell(args[0]))]
|
|
@@ -46055,6 +46334,82 @@ defineBuiltin({
|
|
|
46055
46334
|
name: "issparse",
|
|
46056
46335
|
cases: [anyToLogicalCase((args) => isRuntimeSparseMatrix(args[0]))]
|
|
46057
46336
|
});
|
|
46337
|
+
defineBuiltin({
|
|
46338
|
+
name: "isobject",
|
|
46339
|
+
cases: [
|
|
46340
|
+
anyToLogicalCase(
|
|
46341
|
+
(args) => isRuntimeClassInstance(args[0]) || isRuntimeClassInstanceArray(args[0])
|
|
46342
|
+
)
|
|
46343
|
+
]
|
|
46344
|
+
});
|
|
46345
|
+
defineBuiltin({
|
|
46346
|
+
name: "isprop",
|
|
46347
|
+
help: {
|
|
46348
|
+
signatures: ["tf = isprop(obj, PropertyName)"],
|
|
46349
|
+
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."
|
|
46350
|
+
},
|
|
46351
|
+
cases: [
|
|
46352
|
+
{
|
|
46353
|
+
match: (argTypes) => {
|
|
46354
|
+
if (argTypes.length !== 2) return null;
|
|
46355
|
+
return [{ kind: "boolean" }];
|
|
46356
|
+
},
|
|
46357
|
+
apply: (args) => {
|
|
46358
|
+
const v = args[0];
|
|
46359
|
+
const nameArg = args[1];
|
|
46360
|
+
let propName = null;
|
|
46361
|
+
if (isRuntimeChar(nameArg)) propName = nameArg.value;
|
|
46362
|
+
else if (isRuntimeString(nameArg)) propName = nameArg;
|
|
46363
|
+
let answer = false;
|
|
46364
|
+
if (propName !== null) {
|
|
46365
|
+
if (isRuntimeClassInstance(v)) answer = v.fields.has(propName);
|
|
46366
|
+
else if (isRuntimeClassInstanceArray(v))
|
|
46367
|
+
answer = v.elements.length > 0 && v.elements[0].fields.has(propName);
|
|
46368
|
+
}
|
|
46369
|
+
const shape = getShape(v);
|
|
46370
|
+
const n = shape.reduce((a, b) => a * b, 1);
|
|
46371
|
+
if (n === 1) return RTV.logical(answer);
|
|
46372
|
+
const data = allocFloat64Array(n);
|
|
46373
|
+
if (answer) data.fill(1);
|
|
46374
|
+
return new RuntimeTensor(data, shape, void 0, true);
|
|
46375
|
+
}
|
|
46376
|
+
}
|
|
46377
|
+
]
|
|
46378
|
+
});
|
|
46379
|
+
defineBuiltin({
|
|
46380
|
+
name: "addprop",
|
|
46381
|
+
help: {
|
|
46382
|
+
signatures: ["p = addprop(obj, PropertyName)"],
|
|
46383
|
+
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."
|
|
46384
|
+
},
|
|
46385
|
+
cases: [
|
|
46386
|
+
{
|
|
46387
|
+
match: (argTypes) => {
|
|
46388
|
+
if (argTypes.length !== 2) return null;
|
|
46389
|
+
return [{ kind: "unknown" }];
|
|
46390
|
+
},
|
|
46391
|
+
apply: (args) => {
|
|
46392
|
+
const obj = args[0];
|
|
46393
|
+
if (!isRuntimeClassInstance(obj))
|
|
46394
|
+
throw new RuntimeError(
|
|
46395
|
+
"addprop: first argument must be a dynamicprops object"
|
|
46396
|
+
);
|
|
46397
|
+
const name = toString(args[1]);
|
|
46398
|
+
if (!obj.fields.has(name)) {
|
|
46399
|
+
const empty = RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
46400
|
+
incref(empty);
|
|
46401
|
+
obj.fields.set(name, empty);
|
|
46402
|
+
}
|
|
46403
|
+
return RTV.classInstance(
|
|
46404
|
+
"meta.DynamicProperty",
|
|
46405
|
+
["Name"],
|
|
46406
|
+
true,
|
|
46407
|
+
/* @__PURE__ */ new Map([["Name", RTV.char(name)]])
|
|
46408
|
+
);
|
|
46409
|
+
}
|
|
46410
|
+
}
|
|
46411
|
+
]
|
|
46412
|
+
});
|
|
46058
46413
|
defineBuiltin({
|
|
46059
46414
|
name: "isscalar",
|
|
46060
46415
|
cases: [
|
|
@@ -46252,6 +46607,30 @@ function mkChar(value) {
|
|
|
46252
46607
|
defineBuiltin({
|
|
46253
46608
|
name: "class",
|
|
46254
46609
|
cases: [
|
|
46610
|
+
// Old-style (pre-classdef) constructor form: class(structData, 'ClassName')
|
|
46611
|
+
// builds a value-type instance whose fields are the struct's fields. The
|
|
46612
|
+
// optional class(s,'Name',parent,...) inheritance form is not supported
|
|
46613
|
+
// (returns null → "unsupported argument types").
|
|
46614
|
+
{
|
|
46615
|
+
match: (argTypes) => {
|
|
46616
|
+
if (argTypes.length !== 2) return null;
|
|
46617
|
+
if (argTypes[0].kind !== "struct") return null;
|
|
46618
|
+
const k = argTypes[1].kind;
|
|
46619
|
+
if (k !== "char" && k !== "string") return null;
|
|
46620
|
+
return [{ kind: "unknown" }];
|
|
46621
|
+
},
|
|
46622
|
+
apply: (args) => {
|
|
46623
|
+
const s = args[0];
|
|
46624
|
+
if (!isRuntimeStruct(s))
|
|
46625
|
+
throw new RuntimeError(
|
|
46626
|
+
"class: first argument must be a scalar struct"
|
|
46627
|
+
);
|
|
46628
|
+
const nameVal = args[1];
|
|
46629
|
+
const className = isRuntimeChar(nameVal) ? nameVal.value : isRuntimeString(nameVal) ? nameVal : String(nameVal);
|
|
46630
|
+
const fieldNames = [...s.fields.keys()];
|
|
46631
|
+
return RTV.classInstance(className, fieldNames, false, s.fields);
|
|
46632
|
+
}
|
|
46633
|
+
},
|
|
46255
46634
|
{
|
|
46256
46635
|
match: (argTypes) => {
|
|
46257
46636
|
if (argTypes.length !== 1) return null;
|
|
@@ -46289,6 +46668,26 @@ defineBuiltin({
|
|
|
46289
46668
|
}
|
|
46290
46669
|
]
|
|
46291
46670
|
});
|
|
46671
|
+
for (const name of ["superiorto", "inferiorto"]) {
|
|
46672
|
+
defineBuiltin({
|
|
46673
|
+
name,
|
|
46674
|
+
help: {
|
|
46675
|
+
signatures: [`${name}('Class1', 'Class2', ...)`],
|
|
46676
|
+
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."
|
|
46677
|
+
},
|
|
46678
|
+
cases: [
|
|
46679
|
+
{
|
|
46680
|
+
match: (argTypes) => {
|
|
46681
|
+
for (const t of argTypes) {
|
|
46682
|
+
if (t.kind !== "char" && t.kind !== "string") return null;
|
|
46683
|
+
}
|
|
46684
|
+
return [];
|
|
46685
|
+
},
|
|
46686
|
+
apply: () => void 0
|
|
46687
|
+
}
|
|
46688
|
+
]
|
|
46689
|
+
});
|
|
46690
|
+
}
|
|
46292
46691
|
function fieldnamesApply(args) {
|
|
46293
46692
|
if (args.length !== 1)
|
|
46294
46693
|
throw new RuntimeError("fieldnames requires 1 argument");
|
|
@@ -46856,7 +47255,6 @@ function anyAllApply(name, mode) {
|
|
|
46856
47255
|
if (isRuntimeComplexNumber(v)) return RTV.logical(v.re !== 0 || v.im !== 0);
|
|
46857
47256
|
if (isRuntimeTensor(v)) {
|
|
46858
47257
|
if (args.length === 1) {
|
|
46859
|
-
if (v.data.length === 0) return RTV.logical(mode === "all");
|
|
46860
47258
|
const d = firstReduceDim(v.shape);
|
|
46861
47259
|
if (d === 0) return RTV.logical(scanLogical(v.data, v.imag, mode));
|
|
46862
47260
|
return logicalAlongDim(v, d, mode);
|
|
@@ -47126,7 +47524,12 @@ function applyTextFn(v, fn) {
|
|
|
47126
47524
|
}
|
|
47127
47525
|
return RTV.cell(out, [...v.shape]);
|
|
47128
47526
|
}
|
|
47129
|
-
if (isRuntimeChar(v))
|
|
47527
|
+
if (isRuntimeChar(v)) {
|
|
47528
|
+
if (v.shape && (v.shape[0] ?? 1) > 1) {
|
|
47529
|
+
return charRowsToMatrix(valueToCharRows(v).map(fn));
|
|
47530
|
+
}
|
|
47531
|
+
return RTV.char(fn(v.value));
|
|
47532
|
+
}
|
|
47130
47533
|
if (isRuntimeString(v)) return RTV.string(fn(toString(v)));
|
|
47131
47534
|
return v;
|
|
47132
47535
|
}
|
|
@@ -47278,7 +47681,7 @@ registerIBuiltin({
|
|
|
47278
47681
|
const str = toString(args[0]);
|
|
47279
47682
|
const pat = toString(args[1]);
|
|
47280
47683
|
const rep = toString(args[2]);
|
|
47281
|
-
let flags = "
|
|
47684
|
+
let flags = "gs";
|
|
47282
47685
|
for (let i = 3; i < args.length; i++) {
|
|
47283
47686
|
const opt = toString(args[i]).toLowerCase();
|
|
47284
47687
|
if (opt === "ignorecase") flags += "i";
|
|
@@ -47642,6 +48045,38 @@ registerIBuiltin({
|
|
|
47642
48045
|
};
|
|
47643
48046
|
}
|
|
47644
48047
|
});
|
|
48048
|
+
registerIBuiltin({
|
|
48049
|
+
name: "isspace",
|
|
48050
|
+
help: {
|
|
48051
|
+
signatures: ["TF = isspace(str)"],
|
|
48052
|
+
description: "Return a logical array the same size as str, true where the character is whitespace. Numeric input is treated as Unicode code points."
|
|
48053
|
+
},
|
|
48054
|
+
resolve: (argTypes) => {
|
|
48055
|
+
if (argTypes.length !== 1) return null;
|
|
48056
|
+
const k = argTypes[0].kind;
|
|
48057
|
+
if (k !== "char" && k !== "string" && k !== "number" && k !== "boolean" && k !== "tensor") {
|
|
48058
|
+
return null;
|
|
48059
|
+
}
|
|
48060
|
+
const pred = (cp) => RE_WSPACE.test(String.fromCodePoint(cp));
|
|
48061
|
+
return {
|
|
48062
|
+
outputTypes: [{ kind: "tensor", isComplex: false, isLogical: true }],
|
|
48063
|
+
apply: (args) => {
|
|
48064
|
+
const v = args[0];
|
|
48065
|
+
if (isRuntimeChar(v)) {
|
|
48066
|
+
return logicalRowFromString(
|
|
48067
|
+
v.value,
|
|
48068
|
+
pred,
|
|
48069
|
+
v.shape ? [...v.shape] : void 0
|
|
48070
|
+
);
|
|
48071
|
+
}
|
|
48072
|
+
if (isRuntimeString(v)) return logicalRowFromString(toString(v), pred);
|
|
48073
|
+
if (isRuntimeTensor(v))
|
|
48074
|
+
return logicalFromNumericTensor(v.data, v.shape, pred);
|
|
48075
|
+
return logicalFromNumericTensor([toNumber(v)], [1, 1], pred);
|
|
48076
|
+
}
|
|
48077
|
+
};
|
|
48078
|
+
}
|
|
48079
|
+
});
|
|
47645
48080
|
registerIBuiltin({
|
|
47646
48081
|
name: "contains",
|
|
47647
48082
|
resolve: (argTypes) => {
|
|
@@ -48089,12 +48524,102 @@ registerIBuiltin({
|
|
|
48089
48524
|
};
|
|
48090
48525
|
}
|
|
48091
48526
|
});
|
|
48527
|
+
function collectRows(v) {
|
|
48528
|
+
if (isRuntimeCell(v)) {
|
|
48529
|
+
const rows = [];
|
|
48530
|
+
for (const el of v.data) rows.push(...valueToCharRows(el));
|
|
48531
|
+
return rows;
|
|
48532
|
+
}
|
|
48533
|
+
return valueToCharRows(v);
|
|
48534
|
+
}
|
|
48535
|
+
registerIBuiltin({
|
|
48536
|
+
name: "strmatch",
|
|
48537
|
+
help: {
|
|
48538
|
+
signatures: [
|
|
48539
|
+
"x = strmatch(str, strarray)",
|
|
48540
|
+
"x = strmatch(str, strarray, 'exact')"
|
|
48541
|
+
],
|
|
48542
|
+
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."
|
|
48543
|
+
},
|
|
48544
|
+
resolve: (argTypes) => {
|
|
48545
|
+
if (argTypes.length < 2 || argTypes.length > 3) return null;
|
|
48546
|
+
if (!isTextType(argTypes[0])) return null;
|
|
48547
|
+
const sa = argTypes[1];
|
|
48548
|
+
if (sa.kind !== "char" && sa.kind !== "string" && sa.kind !== "cell")
|
|
48549
|
+
return null;
|
|
48550
|
+
return {
|
|
48551
|
+
outputTypes: [{ kind: "tensor", isComplex: false }],
|
|
48552
|
+
apply: (args) => {
|
|
48553
|
+
const str = toString(args[0]);
|
|
48554
|
+
let rows = collectRows(args[1]);
|
|
48555
|
+
const n = rows.length === 0 ? 0 : Math.max(...rows.map((r) => r.length));
|
|
48556
|
+
rows = rows.map((r) => r.padEnd(n, " "));
|
|
48557
|
+
const exactMatch = args.length === 3;
|
|
48558
|
+
let s = str;
|
|
48559
|
+
let len = s.length;
|
|
48560
|
+
if (len > n) {
|
|
48561
|
+
return RTV.tensor(allocFloat64Array(0), [0, 1]);
|
|
48562
|
+
}
|
|
48563
|
+
if (exactMatch && len < n) {
|
|
48564
|
+
const useNull = rows.some((r) => r.charCodeAt(n - 1) === 0);
|
|
48565
|
+
s = s.padEnd(n, useNull ? "\0" : " ");
|
|
48566
|
+
len = n;
|
|
48567
|
+
}
|
|
48568
|
+
const matches2 = [];
|
|
48569
|
+
for (let r = 0; r < rows.length; r++) {
|
|
48570
|
+
let ok = true;
|
|
48571
|
+
for (let i = 0; i < len; i++) {
|
|
48572
|
+
if (rows[r][i] !== s[i]) {
|
|
48573
|
+
ok = false;
|
|
48574
|
+
break;
|
|
48575
|
+
}
|
|
48576
|
+
}
|
|
48577
|
+
if (ok) matches2.push(r + 1);
|
|
48578
|
+
}
|
|
48579
|
+
return RTV.tensor(allocFloat64Array(matches2), [matches2.length, 1]);
|
|
48580
|
+
}
|
|
48581
|
+
};
|
|
48582
|
+
}
|
|
48583
|
+
});
|
|
48584
|
+
function valueToCharRows(v) {
|
|
48585
|
+
if (isRuntimeChar(v)) {
|
|
48586
|
+
const cols = v.shape ? v.shape[1] ?? v.value.length : v.value.length;
|
|
48587
|
+
const numRows = v.shape ? v.shape[0] ?? 1 : 1;
|
|
48588
|
+
if (numRows <= 1) return [v.value];
|
|
48589
|
+
const out = [];
|
|
48590
|
+
for (let r = 0; r < numRows; r++)
|
|
48591
|
+
out.push(v.value.slice(r * cols, (r + 1) * cols));
|
|
48592
|
+
return out;
|
|
48593
|
+
}
|
|
48594
|
+
if (isRuntimeString(v)) return [v];
|
|
48595
|
+
if (isRuntimeNumber(v)) return [String.fromCharCode(Math.round(v))];
|
|
48596
|
+
if (isRuntimeTensor(v)) {
|
|
48597
|
+
const rows = v.shape.length >= 2 ? v.shape[0] ?? 1 : 1;
|
|
48598
|
+
const cols = v.shape.length >= 2 ? v.shape[1] ?? 0 : v.data.length;
|
|
48599
|
+
const out = [];
|
|
48600
|
+
for (let r = 0; r < rows; r++) {
|
|
48601
|
+
let s = "";
|
|
48602
|
+
for (let c = 0; c < cols; c++)
|
|
48603
|
+
s += String.fromCharCode(Math.round(v.data[c * rows + r]));
|
|
48604
|
+
out.push(s);
|
|
48605
|
+
}
|
|
48606
|
+
return out;
|
|
48607
|
+
}
|
|
48608
|
+
throw new RuntimeError("char: unsupported cell element type");
|
|
48609
|
+
}
|
|
48610
|
+
function charRowsToMatrix(rows) {
|
|
48611
|
+
if (rows.length === 0) return RTV.char("");
|
|
48612
|
+
const width = Math.max(...rows.map((r) => r.length));
|
|
48613
|
+
const padded = rows.map((r) => r.padEnd(width, " "));
|
|
48614
|
+
if (rows.length === 1) return RTV.char(padded[0]);
|
|
48615
|
+
return new RuntimeChar(padded.join(""), [rows.length, width]);
|
|
48616
|
+
}
|
|
48092
48617
|
registerIBuiltin({
|
|
48093
48618
|
name: "char",
|
|
48094
48619
|
resolve: (argTypes) => {
|
|
48095
48620
|
if (argTypes.length !== 1) return null;
|
|
48096
48621
|
const a = argTypes[0];
|
|
48097
|
-
if (a.kind !== "char" && a.kind !== "string" && a.kind !== "number" && a.kind !== "tensor")
|
|
48622
|
+
if (a.kind !== "char" && a.kind !== "string" && a.kind !== "number" && a.kind !== "tensor" && a.kind !== "cell")
|
|
48098
48623
|
return null;
|
|
48099
48624
|
return {
|
|
48100
48625
|
outputTypes: [{ kind: "char" }],
|
|
@@ -48111,6 +48636,11 @@ registerIBuiltin({
|
|
|
48111
48636
|
}
|
|
48112
48637
|
return RTV.char(chars.join(""));
|
|
48113
48638
|
}
|
|
48639
|
+
if (isRuntimeCell(v)) {
|
|
48640
|
+
const rows = [];
|
|
48641
|
+
for (const el of v.data) rows.push(...valueToCharRows(el));
|
|
48642
|
+
return charRowsToMatrix(rows);
|
|
48643
|
+
}
|
|
48114
48644
|
throw new RuntimeError("char: unsupported arguments");
|
|
48115
48645
|
}
|
|
48116
48646
|
};
|
|
@@ -48178,6 +48708,8 @@ registerIBuiltin({
|
|
|
48178
48708
|
if (!isTextType(argTypes[0]) || !isTextType(argTypes[1])) return null;
|
|
48179
48709
|
const outputTypes = [{ kind: "number" }];
|
|
48180
48710
|
if (nargout >= 2) outputTypes.push({ kind: "number" });
|
|
48711
|
+
if (nargout >= 3) outputTypes.push({ kind: "char" });
|
|
48712
|
+
if (nargout >= 4) outputTypes.push({ kind: "number" });
|
|
48181
48713
|
return {
|
|
48182
48714
|
outputTypes,
|
|
48183
48715
|
apply: (args, nout) => {
|
|
@@ -48187,6 +48719,7 @@ registerIBuiltin({
|
|
|
48187
48719
|
const results = [];
|
|
48188
48720
|
let strPos = 0;
|
|
48189
48721
|
let fmtPos = 0;
|
|
48722
|
+
let matchFailure = false;
|
|
48190
48723
|
while (fmtPos < fmt.length && strPos < str.length && results.length < maxCount) {
|
|
48191
48724
|
if (fmt[fmtPos] === "%") {
|
|
48192
48725
|
fmtPos++;
|
|
@@ -48198,22 +48731,34 @@ registerIBuiltin({
|
|
|
48198
48731
|
}
|
|
48199
48732
|
if (spec === "d" || spec === "i") {
|
|
48200
48733
|
const m = str.slice(strPos).match(/^[+-]?\d+/);
|
|
48201
|
-
if (!m)
|
|
48734
|
+
if (!m) {
|
|
48735
|
+
matchFailure = true;
|
|
48736
|
+
break;
|
|
48737
|
+
}
|
|
48202
48738
|
results.push(parseInt(m[0], 10));
|
|
48203
48739
|
strPos += m[0].length;
|
|
48204
48740
|
} else if (spec === "f" || spec === "e" || spec === "g") {
|
|
48205
48741
|
const m = str.slice(strPos).match(/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/);
|
|
48206
|
-
if (!m)
|
|
48742
|
+
if (!m) {
|
|
48743
|
+
matchFailure = true;
|
|
48744
|
+
break;
|
|
48745
|
+
}
|
|
48207
48746
|
results.push(parseFloat(m[0]));
|
|
48208
48747
|
strPos += m[0].length;
|
|
48209
48748
|
} else if (spec === "x") {
|
|
48210
48749
|
const m = str.slice(strPos).match(/^[+-]?[0-9a-fA-F]+/);
|
|
48211
|
-
if (!m)
|
|
48750
|
+
if (!m) {
|
|
48751
|
+
matchFailure = true;
|
|
48752
|
+
break;
|
|
48753
|
+
}
|
|
48212
48754
|
results.push(parseInt(m[0], 16));
|
|
48213
48755
|
strPos += m[0].length;
|
|
48214
48756
|
} else if (spec === "o") {
|
|
48215
48757
|
const m = str.slice(strPos).match(/^[+-]?[0-7]+/);
|
|
48216
|
-
if (!m)
|
|
48758
|
+
if (!m) {
|
|
48759
|
+
matchFailure = true;
|
|
48760
|
+
break;
|
|
48761
|
+
}
|
|
48217
48762
|
results.push(parseInt(m[0], 8));
|
|
48218
48763
|
strPos += m[0].length;
|
|
48219
48764
|
} else if (spec === "c") {
|
|
@@ -48221,7 +48766,10 @@ registerIBuiltin({
|
|
|
48221
48766
|
strPos++;
|
|
48222
48767
|
} else if (spec === "s") {
|
|
48223
48768
|
const m = str.slice(strPos).match(/^\S+/);
|
|
48224
|
-
if (!m)
|
|
48769
|
+
if (!m) {
|
|
48770
|
+
matchFailure = true;
|
|
48771
|
+
break;
|
|
48772
|
+
}
|
|
48225
48773
|
for (let ci = 0; ci < m[0].length && results.length < maxCount; ci++) {
|
|
48226
48774
|
results.push(m[0].charCodeAt(ci));
|
|
48227
48775
|
}
|
|
@@ -48231,7 +48779,10 @@ registerIBuiltin({
|
|
|
48231
48779
|
fmtPos++;
|
|
48232
48780
|
while (strPos < str.length && /\s/.test(str[strPos])) strPos++;
|
|
48233
48781
|
} else {
|
|
48234
|
-
if (str[strPos] !== fmt[fmtPos])
|
|
48782
|
+
if (str[strPos] !== fmt[fmtPos]) {
|
|
48783
|
+
matchFailure = true;
|
|
48784
|
+
break;
|
|
48785
|
+
}
|
|
48235
48786
|
strPos++;
|
|
48236
48787
|
fmtPos++;
|
|
48237
48788
|
}
|
|
@@ -48241,7 +48792,16 @@ registerIBuiltin({
|
|
|
48241
48792
|
}
|
|
48242
48793
|
const vals = results.length === 1 ? RTV.num(results[0]) : RTV.tensor(allocFloat64Array(results), [results.length, 1]);
|
|
48243
48794
|
if (nout >= 2) {
|
|
48244
|
-
|
|
48795
|
+
const out = [vals, RTV.num(results.length)];
|
|
48796
|
+
if (nout >= 3) {
|
|
48797
|
+
out.push(
|
|
48798
|
+
RTV.char(matchFailure ? "Matching failure in format." : "")
|
|
48799
|
+
);
|
|
48800
|
+
}
|
|
48801
|
+
if (nout >= 4) {
|
|
48802
|
+
out.push(RTV.num(strPos + 1));
|
|
48803
|
+
}
|
|
48804
|
+
return out;
|
|
48245
48805
|
}
|
|
48246
48806
|
return vals;
|
|
48247
48807
|
}
|
|
@@ -49652,8 +50212,34 @@ function normImplTensor(v, args) {
|
|
|
49652
50212
|
return RTV.num(maxRowSum);
|
|
49653
50213
|
}
|
|
49654
50214
|
if (p2 === 2) {
|
|
50215
|
+
let anyNaN = false;
|
|
50216
|
+
let anyInf = false;
|
|
50217
|
+
for (let i = 0; i < v.data.length; i++) {
|
|
50218
|
+
const re = v.data[i];
|
|
50219
|
+
const im = imag2 ? imag2[i] : 0;
|
|
50220
|
+
if (Number.isNaN(re) || Number.isNaN(im)) anyNaN = true;
|
|
50221
|
+
else if (!isFinite(re) || !isFinite(im)) anyInf = true;
|
|
50222
|
+
}
|
|
50223
|
+
if (anyNaN) return RTV.num(NaN);
|
|
50224
|
+
if (anyInf) return RTV.num(Infinity);
|
|
49655
50225
|
const bridge = getEffectiveBridge("norm", "svd");
|
|
49656
50226
|
if (bridge && bridge.svd) {
|
|
50227
|
+
if (imag2) {
|
|
50228
|
+
const R = allocFloat64Array(4 * rows * cols);
|
|
50229
|
+
const tm = 2 * rows;
|
|
50230
|
+
for (let j = 0; j < cols; j++) {
|
|
50231
|
+
for (let i = 0; i < rows; i++) {
|
|
50232
|
+
const a = v.data[j * rows + i];
|
|
50233
|
+
const b = imag2[j * rows + i];
|
|
50234
|
+
R[j * tm + i] = a;
|
|
50235
|
+
R[j * tm + (rows + i)] = b;
|
|
50236
|
+
R[(cols + j) * tm + i] = -b;
|
|
50237
|
+
R[(cols + j) * tm + (rows + i)] = a;
|
|
50238
|
+
}
|
|
50239
|
+
}
|
|
50240
|
+
const result2 = bridge.svd(R, tm, 2 * cols, false, false);
|
|
50241
|
+
return RTV.num(result2.S[0]);
|
|
50242
|
+
}
|
|
49657
50243
|
const f64 = v.data instanceof Float64Array ? v.data : allocFloat64Array(v.data);
|
|
49658
50244
|
const result = bridge.svd(f64, rows, cols, false, false);
|
|
49659
50245
|
return RTV.num(result.S[0]);
|
|
@@ -50413,6 +50999,100 @@ function svdApply(args, nargout) {
|
|
|
50413
50999
|
[k, 1]
|
|
50414
51000
|
);
|
|
50415
51001
|
}
|
|
51002
|
+
function nullApply(args) {
|
|
51003
|
+
let A = args[0];
|
|
51004
|
+
if (isRuntimeNumber(A) || isRuntimeComplexNumber(A)) {
|
|
51005
|
+
A = isRuntimeNumber(A) ? RTV.tensor(allocFloat64Array([A]), [1, 1]) : RTV.tensor(
|
|
51006
|
+
allocFloat64Array([A.re]),
|
|
51007
|
+
[1, 1],
|
|
51008
|
+
allocFloat64Array([A.im])
|
|
51009
|
+
);
|
|
51010
|
+
}
|
|
51011
|
+
if (!isRuntimeTensor(A))
|
|
51012
|
+
throw new RuntimeError("null: argument must be a numeric matrix");
|
|
51013
|
+
const [m, n] = tensorSize2D(A);
|
|
51014
|
+
const [, Sdiag, V] = svdApply([A], 3);
|
|
51015
|
+
const k = Math.min(m, n);
|
|
51016
|
+
const s = [];
|
|
51017
|
+
for (let i = 0; i < k; i++) s.push(Sdiag.data[colMajorIndex(i, i, m)]);
|
|
51018
|
+
const maxS = s.length > 0 ? Math.max(...s) : 0;
|
|
51019
|
+
const tol = args.length > 1 && args[1] !== void 0 ? toNumber(args[1]) : Math.max(m, n) * epsOf(maxS);
|
|
51020
|
+
let r = 0;
|
|
51021
|
+
for (const sv of s) if (sv > tol) r++;
|
|
51022
|
+
const cols = n - r;
|
|
51023
|
+
const out = allocFloat64Array(n * cols);
|
|
51024
|
+
const outImag = V.imag ? allocFloat64Array(n * cols) : void 0;
|
|
51025
|
+
for (let c = 0; c < cols; c++) {
|
|
51026
|
+
for (let i = 0; i < n; i++) {
|
|
51027
|
+
const src = colMajorIndex(i, r + c, n);
|
|
51028
|
+
out[colMajorIndex(i, c, n)] = V.data[src];
|
|
51029
|
+
if (outImag) outImag[colMajorIndex(i, c, n)] = V.imag[src];
|
|
51030
|
+
}
|
|
51031
|
+
}
|
|
51032
|
+
return RTV.tensor(out, [n, cols], outImag);
|
|
51033
|
+
}
|
|
51034
|
+
registerIBuiltin({
|
|
51035
|
+
name: "null",
|
|
51036
|
+
resolve: (argTypes, nargout) => {
|
|
51037
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2) return null;
|
|
51038
|
+
if (!isNumericJitType(argTypes[0])) return null;
|
|
51039
|
+
const isComplex = argTypes[0].kind === "tensor" && argTypes[0].isComplex;
|
|
51040
|
+
return {
|
|
51041
|
+
outputTypes: [tensorType(isComplex || void 0)],
|
|
51042
|
+
apply: (args) => nullApply(args)
|
|
51043
|
+
};
|
|
51044
|
+
}
|
|
51045
|
+
});
|
|
51046
|
+
function computeBandwidth(A) {
|
|
51047
|
+
let lower = 0;
|
|
51048
|
+
let upper = 0;
|
|
51049
|
+
const note = (i, j) => {
|
|
51050
|
+
if (i > j) lower = Math.max(lower, i - j);
|
|
51051
|
+
else if (j > i) upper = Math.max(upper, j - i);
|
|
51052
|
+
};
|
|
51053
|
+
if (isRuntimeNumber(A) || isRuntimeComplexNumber(A)) return [0, 0];
|
|
51054
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
51055
|
+
for (let j = 0; j < A.n; j++) {
|
|
51056
|
+
for (let k = A.jc[j]; k < A.jc[j + 1]; k++) {
|
|
51057
|
+
if (A.pr[k] === 0 && (!A.pi || A.pi[k] === 0)) continue;
|
|
51058
|
+
note(A.ir[k], j);
|
|
51059
|
+
}
|
|
51060
|
+
}
|
|
51061
|
+
return [lower, upper];
|
|
51062
|
+
}
|
|
51063
|
+
if (isRuntimeTensor(A)) {
|
|
51064
|
+
const [m, n] = tensorSize2D(A);
|
|
51065
|
+
for (let j = 0; j < n; j++) {
|
|
51066
|
+
for (let i = 0; i < m; i++) {
|
|
51067
|
+
const idx = colMajorIndex(i, j, m);
|
|
51068
|
+
if (A.data[idx] === 0 && (!A.imag || A.imag[idx] === 0)) continue;
|
|
51069
|
+
note(i, j);
|
|
51070
|
+
}
|
|
51071
|
+
}
|
|
51072
|
+
return [lower, upper];
|
|
51073
|
+
}
|
|
51074
|
+
throw new RuntimeError("bandwidth: first argument must be a numeric matrix");
|
|
51075
|
+
}
|
|
51076
|
+
function bandwidthApply(args, nargout) {
|
|
51077
|
+
const [lower, upper] = computeBandwidth(args[0]);
|
|
51078
|
+
if (args.length >= 2 && args[1] !== void 0) {
|
|
51079
|
+
const type = parseStringArgLower(args[1]);
|
|
51080
|
+
if (type === "lower") return RTV.num(lower);
|
|
51081
|
+
if (type === "upper") return RTV.num(upper);
|
|
51082
|
+
throw new RuntimeError("bandwidth: TYPE must be 'lower' or 'upper'");
|
|
51083
|
+
}
|
|
51084
|
+
if (nargout >= 2) return [RTV.num(lower), RTV.num(upper)];
|
|
51085
|
+
return RTV.num(lower);
|
|
51086
|
+
}
|
|
51087
|
+
registerIBuiltin({
|
|
51088
|
+
name: "bandwidth",
|
|
51089
|
+
resolve: (argTypes, nargout) => {
|
|
51090
|
+
if (nargout > 2 || argTypes.length < 1 || argTypes.length > 2) return null;
|
|
51091
|
+
if (!isNumericJitType(argTypes[0])) return null;
|
|
51092
|
+
const outs = nargout >= 2 ? [NUM, NUM] : [NUM];
|
|
51093
|
+
return { outputTypes: outs, apply: (args, n) => bandwidthApply(args, n) };
|
|
51094
|
+
}
|
|
51095
|
+
});
|
|
50416
51096
|
function computeATA(A_data, m, n) {
|
|
50417
51097
|
const result = allocFloat64Array(n * n);
|
|
50418
51098
|
for (let j = 0; j < n; j++)
|
|
@@ -52283,6 +52963,33 @@ function validateSizeArg(x) {
|
|
|
52283
52963
|
}
|
|
52284
52964
|
return x < 0 ? 0 : x;
|
|
52285
52965
|
}
|
|
52966
|
+
function parseReshapeDims(args, total) {
|
|
52967
|
+
let rawDims;
|
|
52968
|
+
if (args.length === 2 && isRuntimeTensor(args[1]) && args[1].data.length > 1) {
|
|
52969
|
+
rawDims = Array.from(args[1].data).map((x) => validateSizeArg(x));
|
|
52970
|
+
} else {
|
|
52971
|
+
rawDims = args.slice(1).map((a) => {
|
|
52972
|
+
if (isRuntimeTensor(a) && a.data.length === 0) return null;
|
|
52973
|
+
return validateSizeArg(toNumber(a));
|
|
52974
|
+
});
|
|
52975
|
+
}
|
|
52976
|
+
const autoCount = rawDims.filter((d) => d === null).length;
|
|
52977
|
+
if (autoCount > 1)
|
|
52978
|
+
throw new RuntimeError("reshape: only one dimension size can be []");
|
|
52979
|
+
let shape;
|
|
52980
|
+
if (autoCount === 1) {
|
|
52981
|
+
const known = rawDims.filter((d) => d !== null);
|
|
52982
|
+
const knownProduct = known.reduce((a, b) => a * b, 1);
|
|
52983
|
+
if (knownProduct === 0 || total % knownProduct !== 0)
|
|
52984
|
+
throw new RuntimeError("reshape: number of elements must not change");
|
|
52985
|
+
shape = rawDims.map((d) => d === null ? total / knownProduct : d);
|
|
52986
|
+
} else {
|
|
52987
|
+
shape = rawDims;
|
|
52988
|
+
}
|
|
52989
|
+
if (numel(shape) !== total)
|
|
52990
|
+
throw new RuntimeError("reshape: number of elements must not change");
|
|
52991
|
+
return shape;
|
|
52992
|
+
}
|
|
52286
52993
|
defineBuiltin({
|
|
52287
52994
|
name: "reshape",
|
|
52288
52995
|
cases: [
|
|
@@ -52294,31 +53001,31 @@ defineBuiltin({
|
|
|
52294
53001
|
const v = args[0];
|
|
52295
53002
|
if (isRuntimeSparseMatrix(v)) {
|
|
52296
53003
|
const totalEl = v.m * v.n;
|
|
52297
|
-
let
|
|
53004
|
+
let rawDims;
|
|
52298
53005
|
if (args.length === 2 && isRuntimeTensor(args[1]) && args[1].data.length > 1) {
|
|
52299
|
-
|
|
53006
|
+
rawDims = Array.from(args[1].data).map((x) => Math.round(x));
|
|
52300
53007
|
} else {
|
|
52301
|
-
|
|
53008
|
+
rawDims = args.slice(1).map((a) => {
|
|
52302
53009
|
if (isRuntimeTensor(a) && a.data.length === 0) return null;
|
|
52303
53010
|
return Math.round(toNumber(a));
|
|
52304
53011
|
});
|
|
52305
53012
|
}
|
|
52306
|
-
const
|
|
52307
|
-
if (
|
|
53013
|
+
const autoCount = rawDims.filter((d) => d === null).length;
|
|
53014
|
+
if (autoCount > 1)
|
|
52308
53015
|
throw new RuntimeError(
|
|
52309
53016
|
"reshape: only one dimension size can be []"
|
|
52310
53017
|
);
|
|
52311
53018
|
let shape2;
|
|
52312
|
-
if (
|
|
52313
|
-
const known =
|
|
53019
|
+
if (autoCount === 1) {
|
|
53020
|
+
const known = rawDims.filter((d) => d !== null);
|
|
52314
53021
|
const knownProduct = known.reduce((a, b) => a * b, 1);
|
|
52315
53022
|
if (totalEl % knownProduct !== 0)
|
|
52316
53023
|
throw new RuntimeError(
|
|
52317
53024
|
"reshape: number of elements must not change"
|
|
52318
53025
|
);
|
|
52319
|
-
shape2 =
|
|
53026
|
+
shape2 = rawDims.map((d) => d === null ? totalEl / knownProduct : d);
|
|
52320
53027
|
} else {
|
|
52321
|
-
shape2 =
|
|
53028
|
+
shape2 = rawDims;
|
|
52322
53029
|
}
|
|
52323
53030
|
if (shape2.length !== 2)
|
|
52324
53031
|
throw new RuntimeError("reshape: sparse matrices must be 2-D");
|
|
@@ -52356,40 +53063,32 @@ defineBuiltin({
|
|
|
52356
53063
|
jc[newN] = ti;
|
|
52357
53064
|
return RTV.sparseMatrix(newM, newN, ir, jc, pr, pi2);
|
|
52358
53065
|
}
|
|
53066
|
+
if (isRuntimeChar(v)) {
|
|
53067
|
+
const srcRows = v.shape ? v.shape[0] : 1;
|
|
53068
|
+
const srcCols = v.shape ? v.shape[1] ?? 0 : v.value.length;
|
|
53069
|
+
const total = v.value.length;
|
|
53070
|
+
const reqShape = parseReshapeDims(args, total);
|
|
53071
|
+
const s = [...reqShape];
|
|
53072
|
+
while (s.length > 2 && s[s.length - 1] === 1) s.pop();
|
|
53073
|
+
if (s.length > 2)
|
|
53074
|
+
throw new RuntimeError("reshape: char arrays must be 2-D");
|
|
53075
|
+
const nr = s[0];
|
|
53076
|
+
const nc = s.length >= 2 ? s[1] : 1;
|
|
53077
|
+
const linear = new Array(total);
|
|
53078
|
+
for (let j = 0; j < srcCols; j++)
|
|
53079
|
+
for (let i = 0; i < srcRows; i++)
|
|
53080
|
+
linear[j * srcRows + i] = v.value[i * srcCols + j];
|
|
53081
|
+
const chars = new Array(total);
|
|
53082
|
+
for (let j2 = 0; j2 < nc; j2++)
|
|
53083
|
+
for (let i2 = 0; i2 < nr; i2++)
|
|
53084
|
+
chars[i2 * nc + j2] = linear[j2 * nr + i2];
|
|
53085
|
+
return new RuntimeChar(chars.join(""), [nr, nc]);
|
|
53086
|
+
}
|
|
52359
53087
|
if (!isRuntimeTensor(v) && !isRuntimeNumber(v) && !isRuntimeComplexNumber(v))
|
|
52360
53088
|
throw new RuntimeError("reshape: first argument must be numeric");
|
|
52361
53089
|
const data = isRuntimeTensor(v) ? v.data : isRuntimeComplexNumber(v) ? allocFloat64Array([v.re]) : allocFloat64Array([v]);
|
|
52362
53090
|
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
|
-
}
|
|
53091
|
+
const shape = parseReshapeDims(args, data.length);
|
|
52393
53092
|
if (isRuntimeTensor(v)) {
|
|
52394
53093
|
const dataCopy = allocFloat64Array(data);
|
|
52395
53094
|
const imagCopy = imag2 ? allocFloat64Array(imag2) : void 0;
|
|
@@ -52801,6 +53500,35 @@ defineBuiltin({
|
|
|
52801
53500
|
}
|
|
52802
53501
|
]
|
|
52803
53502
|
});
|
|
53503
|
+
function repmatObjects(v, repArgs) {
|
|
53504
|
+
const srcElements = isRuntimeClassInstanceArray(v) ? v.elements : [v];
|
|
53505
|
+
const [rows, cols] = isRuntimeClassInstanceArray(v) ? v.shape : [1, 1];
|
|
53506
|
+
const className = v.className;
|
|
53507
|
+
let reps;
|
|
53508
|
+
if (repArgs.length === 1) {
|
|
53509
|
+
const arg1 = repArgs[0];
|
|
53510
|
+
if (isRuntimeTensor(arg1)) {
|
|
53511
|
+
reps = Array.from(arg1.data).map((x) => validateSizeArg(x));
|
|
53512
|
+
} else {
|
|
53513
|
+
const n = validateSizeArg(toNumber(arg1));
|
|
53514
|
+
reps = [n, n];
|
|
53515
|
+
}
|
|
53516
|
+
} else {
|
|
53517
|
+
reps = repArgs.map((a) => validateSizeArg(toNumber(a)));
|
|
53518
|
+
}
|
|
53519
|
+
const rRep = reps[0] ?? 1;
|
|
53520
|
+
const cRep = reps.length >= 2 ? reps[1] : reps[0] ?? 1;
|
|
53521
|
+
const newRows = rows * rRep;
|
|
53522
|
+
const newCols = cols * cRep;
|
|
53523
|
+
const out = new Array(Math.max(0, newRows * newCols));
|
|
53524
|
+
for (let J = 0; J < newCols; J++) {
|
|
53525
|
+
for (let I = 0; I < newRows; I++) {
|
|
53526
|
+
const src = srcElements[I % rows + J % cols * rows];
|
|
53527
|
+
out[I + J * newRows] = copyClassInstance(src);
|
|
53528
|
+
}
|
|
53529
|
+
}
|
|
53530
|
+
return out.length === 1 ? out[0] : RTV.classInstanceArray(className, out, [newRows, newCols]);
|
|
53531
|
+
}
|
|
52804
53532
|
defineBuiltin({
|
|
52805
53533
|
name: "repmat",
|
|
52806
53534
|
cases: [
|
|
@@ -52825,6 +53553,8 @@ defineBuiltin({
|
|
|
52825
53553
|
if (args.length < 2)
|
|
52826
53554
|
throw new RuntimeError("repmat requires at least 2 arguments");
|
|
52827
53555
|
let v = args[0];
|
|
53556
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v))
|
|
53557
|
+
return repmatObjects(v, args.slice(1));
|
|
52828
53558
|
if (isRuntimeSparseMatrix(v)) v = sparseToDense(v);
|
|
52829
53559
|
let reps;
|
|
52830
53560
|
if (args.length === 2) {
|
|
@@ -52989,6 +53719,62 @@ defineBuiltin({
|
|
|
52989
53719
|
}
|
|
52990
53720
|
]
|
|
52991
53721
|
});
|
|
53722
|
+
function copyClassInstance(inst) {
|
|
53723
|
+
if (inst.isHandleClass) return inst;
|
|
53724
|
+
return new RuntimeClassInstance(
|
|
53725
|
+
inst.className,
|
|
53726
|
+
new Map(inst.fields),
|
|
53727
|
+
inst.isHandleClass,
|
|
53728
|
+
inst._builtinData
|
|
53729
|
+
);
|
|
53730
|
+
}
|
|
53731
|
+
function repelemObjects(v, repArgs) {
|
|
53732
|
+
const srcElements = isRuntimeClassInstanceArray(v) ? v.elements : [v];
|
|
53733
|
+
const [rows, cols] = isRuntimeClassInstanceArray(v) ? v.shape : [1, 1];
|
|
53734
|
+
const className = v.className;
|
|
53735
|
+
const wrap = (elements, shape) => elements.length === 1 ? elements[0] : RTV.classInstanceArray(className, elements, shape);
|
|
53736
|
+
if (repArgs.length === 1) {
|
|
53737
|
+
const repArg = repArgs[0];
|
|
53738
|
+
if (isRuntimeTensor(repArg) && repArg.data.length > 1) {
|
|
53739
|
+
const counts = repArg.data;
|
|
53740
|
+
if (counts.length !== srcElements.length)
|
|
53741
|
+
throw new RuntimeError(
|
|
53742
|
+
`repelem: counts vector length (${counts.length}) must match the number of elements (${srcElements.length})`
|
|
53743
|
+
);
|
|
53744
|
+
const out3 = [];
|
|
53745
|
+
for (let i = 0; i < srcElements.length; i++) {
|
|
53746
|
+
const c = Math.max(0, Math.round(counts[i]));
|
|
53747
|
+
for (let j = 0; j < c; j++) out3.push(copyClassInstance(srcElements[i]));
|
|
53748
|
+
}
|
|
53749
|
+
const isCol2 = cols === 1 && rows !== 1;
|
|
53750
|
+
return wrap(out3, isCol2 ? [out3.length, 1] : [1, out3.length]);
|
|
53751
|
+
}
|
|
53752
|
+
const n = Math.max(0, Math.round(toNumber(repArg)));
|
|
53753
|
+
const out2 = [];
|
|
53754
|
+
for (const el of srcElements)
|
|
53755
|
+
for (let j = 0; j < n; j++) out2.push(copyClassInstance(el));
|
|
53756
|
+
const isCol = cols === 1 && rows !== 1;
|
|
53757
|
+
return wrap(out2, isCol ? [out2.length, 1] : [1, out2.length]);
|
|
53758
|
+
}
|
|
53759
|
+
const rRep = Math.max(0, Math.round(toNumber(repArgs[0])));
|
|
53760
|
+
const cRep = Math.max(0, Math.round(toNumber(repArgs[1])));
|
|
53761
|
+
const newRows = rows * rRep;
|
|
53762
|
+
const newCols = cols * cRep;
|
|
53763
|
+
const out = new Array(newRows * newCols);
|
|
53764
|
+
for (let c = 0; c < cols; c++) {
|
|
53765
|
+
for (let r = 0; r < rows; r++) {
|
|
53766
|
+
const src = srcElements[c * rows + r];
|
|
53767
|
+
for (let dc = 0; dc < cRep; dc++) {
|
|
53768
|
+
for (let dr = 0; dr < rRep; dr++) {
|
|
53769
|
+
const dstRow = r * rRep + dr;
|
|
53770
|
+
const dstCol = c * cRep + dc;
|
|
53771
|
+
out[dstCol * newRows + dstRow] = copyClassInstance(src);
|
|
53772
|
+
}
|
|
53773
|
+
}
|
|
53774
|
+
}
|
|
53775
|
+
}
|
|
53776
|
+
return wrap(out, [newRows, newCols]);
|
|
53777
|
+
}
|
|
52992
53778
|
defineBuiltin({
|
|
52993
53779
|
name: "repelem",
|
|
52994
53780
|
cases: [
|
|
@@ -52998,6 +53784,8 @@ defineBuiltin({
|
|
|
52998
53784
|
if (args.length < 2)
|
|
52999
53785
|
throw new RuntimeError("repelem requires at least 2 arguments");
|
|
53000
53786
|
const v = args[0];
|
|
53787
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v))
|
|
53788
|
+
return repelemObjects(v, args.slice(1));
|
|
53001
53789
|
if (args.length === 2) {
|
|
53002
53790
|
const repArg = args[1];
|
|
53003
53791
|
if (isRuntimeTensor(repArg) && repArg.data.length > 1) {
|
|
@@ -53120,7 +53908,15 @@ defineBuiltin({
|
|
|
53120
53908
|
}
|
|
53121
53909
|
return RTV.tensor(dataCopy, newShape, imagCopy);
|
|
53122
53910
|
}
|
|
53123
|
-
|
|
53911
|
+
if (isRuntimeCell(v)) {
|
|
53912
|
+
const shape = [...v.shape];
|
|
53913
|
+
while (shape.length > 2 && shape[shape.length - 1] === 1) shape.pop();
|
|
53914
|
+
if (shape.length <= 2) return RTV.cell(v.data, shape);
|
|
53915
|
+
const newShape = shape.filter((d) => d !== 1);
|
|
53916
|
+
while (newShape.length < 2) newShape.push(1);
|
|
53917
|
+
return RTV.cell(v.data, newShape);
|
|
53918
|
+
}
|
|
53919
|
+
return v;
|
|
53124
53920
|
}
|
|
53125
53921
|
}
|
|
53126
53922
|
]
|
|
@@ -53790,6 +54586,8 @@ defineBuiltin({
|
|
|
53790
54586
|
]
|
|
53791
54587
|
});
|
|
53792
54588
|
function bitwiseOp(a, b, op, name) {
|
|
54589
|
+
if (typeof a === "boolean") a = a ? 1 : 0;
|
|
54590
|
+
if (typeof b === "boolean") b = b ? 1 : 0;
|
|
53793
54591
|
if (isRuntimeNumber(a) && isRuntimeNumber(b)) {
|
|
53794
54592
|
return RTV.num(op(Math.round(a), Math.round(b)));
|
|
53795
54593
|
}
|
|
@@ -56057,6 +56855,56 @@ defineBuiltin({
|
|
|
56057
56855
|
}
|
|
56058
56856
|
]
|
|
56059
56857
|
});
|
|
56858
|
+
function froundArray(src) {
|
|
56859
|
+
const out = allocFloat64Array(src.length);
|
|
56860
|
+
for (let i = 0; i < src.length; i++) out[i] = Math.fround(src[i]);
|
|
56861
|
+
return out;
|
|
56862
|
+
}
|
|
56863
|
+
function singleApply(v) {
|
|
56864
|
+
if (isRuntimeChar(v)) {
|
|
56865
|
+
if (v.value.length === 0) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
56866
|
+
if (v.value.length === 1)
|
|
56867
|
+
return RTV.num(Math.fround(v.value.charCodeAt(0)));
|
|
56868
|
+
return RTV.row(Array.from(v.value).map((c) => Math.fround(c.charCodeAt(0))));
|
|
56869
|
+
}
|
|
56870
|
+
if (isRuntimeLogical(v)) return RTV.num(v ? 1 : 0);
|
|
56871
|
+
if (isRuntimeNumber(v)) return RTV.num(Math.fround(v));
|
|
56872
|
+
if (isRuntimeComplexNumber(v))
|
|
56873
|
+
return RTV.complex(Math.fround(v.re), Math.fround(v.im));
|
|
56874
|
+
if (isRuntimeTensor(v)) {
|
|
56875
|
+
const imag2 = v.imag ? froundArray(v.imag) : void 0;
|
|
56876
|
+
return RTV.tensor(froundArray(v.data), v.shape.slice(), imag2);
|
|
56877
|
+
}
|
|
56878
|
+
if (isRuntimeClassInstance(v) && v._builtinData !== void 0)
|
|
56879
|
+
return singleApply(v._builtinData);
|
|
56880
|
+
return RTV.num(Math.fround(toNumber(v)));
|
|
56881
|
+
}
|
|
56882
|
+
defineBuiltin({
|
|
56883
|
+
name: "single",
|
|
56884
|
+
cases: [
|
|
56885
|
+
{
|
|
56886
|
+
match: (argTypes) => {
|
|
56887
|
+
if (argTypes.length !== 1) return null;
|
|
56888
|
+
const a = argTypes[0];
|
|
56889
|
+
if (a.kind === "number" || a.kind === "boolean" || a.kind === "char" || a.kind === "class_instance")
|
|
56890
|
+
return [{ kind: "number" }];
|
|
56891
|
+
if (a.kind === "complex_or_number")
|
|
56892
|
+
return [{ kind: "complex_or_number" }];
|
|
56893
|
+
if (a.kind === "tensor")
|
|
56894
|
+
return [
|
|
56895
|
+
{
|
|
56896
|
+
kind: "tensor",
|
|
56897
|
+
isComplex: a.isComplex,
|
|
56898
|
+
shape: a.shape,
|
|
56899
|
+
ndim: a.ndim
|
|
56900
|
+
}
|
|
56901
|
+
];
|
|
56902
|
+
return null;
|
|
56903
|
+
},
|
|
56904
|
+
apply: (args) => singleApply(args[0])
|
|
56905
|
+
}
|
|
56906
|
+
]
|
|
56907
|
+
});
|
|
56060
56908
|
var INT_RANGES = [
|
|
56061
56909
|
{ name: "int8", min: -128, max: 127 },
|
|
56062
56910
|
{ name: "int16", min: -32768, max: 32767 },
|
|
@@ -56611,11 +57459,20 @@ defineBuiltin({
|
|
|
56611
57459
|
},
|
|
56612
57460
|
apply: (args) => {
|
|
56613
57461
|
const v = args[0];
|
|
56614
|
-
|
|
56615
|
-
|
|
56616
|
-
|
|
56617
|
-
return
|
|
56618
|
-
|
|
57462
|
+
const hasField = (name) => {
|
|
57463
|
+
if (isRuntimeStructArray(v)) return v.fieldNames.includes(name);
|
|
57464
|
+
if (!isRuntimeStruct(v) && !isRuntimeClassInstance(v)) return false;
|
|
57465
|
+
return v.fields.has(name);
|
|
57466
|
+
};
|
|
57467
|
+
if (isRuntimeCell(args[1])) {
|
|
57468
|
+
const cell = args[1];
|
|
57469
|
+
const result = allocFloat64Array(cell.data.length);
|
|
57470
|
+
for (let i = 0; i < cell.data.length; i++) {
|
|
57471
|
+
result[i] = hasField(toString(cell.data[i])) ? 1 : 0;
|
|
57472
|
+
}
|
|
57473
|
+
return new RuntimeTensor(result, cell.shape.slice(), void 0, true);
|
|
57474
|
+
}
|
|
57475
|
+
return RTV.logical(hasField(toString(args[1])));
|
|
56619
57476
|
}
|
|
56620
57477
|
}
|
|
56621
57478
|
]
|
|
@@ -56732,7 +57589,7 @@ function regexpImpl(caseSensitive, name, args, nargout) {
|
|
|
56732
57589
|
if (outModes.length === 0) {
|
|
56733
57590
|
outModes.push("start", "end", "tokenextents", "match", "tokens", "names");
|
|
56734
57591
|
}
|
|
56735
|
-
const flags = caseSensitive ? "
|
|
57592
|
+
const flags = caseSensitive ? "gs" : "gis";
|
|
56736
57593
|
const re = new RegExp(pat, flags);
|
|
56737
57594
|
const starts = [];
|
|
56738
57595
|
const ends = [];
|
|
@@ -57452,6 +58309,13 @@ registerIBuiltin({
|
|
|
57452
58309
|
if (args.length === 1) return RTV.cell([A], [1, 1]);
|
|
57453
58310
|
A = RTV.tensor(allocFloat64Array([A ? 1 : 0]), [1, 1]);
|
|
57454
58311
|
}
|
|
58312
|
+
if (isRuntimeStruct(A)) {
|
|
58313
|
+
return RTV.cell([A], [1, 1]);
|
|
58314
|
+
}
|
|
58315
|
+
if (isRuntimeStructArray(A)) {
|
|
58316
|
+
const elems = A.elements;
|
|
58317
|
+
return RTV.cell([...elems], [1, elems.length]);
|
|
58318
|
+
}
|
|
57455
58319
|
if (!isRuntimeTensor(A))
|
|
57456
58320
|
throw new RuntimeError(
|
|
57457
58321
|
"num2cell: first argument must be a numeric array"
|
|
@@ -57575,6 +58439,69 @@ registerIBuiltin({
|
|
|
57575
58439
|
};
|
|
57576
58440
|
}
|
|
57577
58441
|
});
|
|
58442
|
+
registerIBuiltin({
|
|
58443
|
+
name: "getfield",
|
|
58444
|
+
resolve: (argTypes) => {
|
|
58445
|
+
if (argTypes.length < 2) return null;
|
|
58446
|
+
return {
|
|
58447
|
+
outputTypes: [{ kind: "unknown" }],
|
|
58448
|
+
apply: (args) => {
|
|
58449
|
+
let v = args[0];
|
|
58450
|
+
for (let i = 1; i < args.length; i++) {
|
|
58451
|
+
if (isRuntimeCell(args[i]))
|
|
58452
|
+
throw new RuntimeError(
|
|
58453
|
+
"getfield: index ({}) subscripts are not supported"
|
|
58454
|
+
);
|
|
58455
|
+
if (!isRuntimeStruct(v))
|
|
58456
|
+
throw new RuntimeError("getfield: argument must be a structure");
|
|
58457
|
+
const name = toString(args[i]);
|
|
58458
|
+
if (!v.fields.has(name))
|
|
58459
|
+
throw new RuntimeError(
|
|
58460
|
+
`Reference to non-existent field '${name}'.`
|
|
58461
|
+
);
|
|
58462
|
+
v = v.fields.get(name);
|
|
58463
|
+
}
|
|
58464
|
+
return v;
|
|
58465
|
+
}
|
|
58466
|
+
};
|
|
58467
|
+
}
|
|
58468
|
+
});
|
|
58469
|
+
registerIBuiltin({
|
|
58470
|
+
name: "setfield",
|
|
58471
|
+
resolve: (argTypes) => {
|
|
58472
|
+
if (argTypes.length < 3) return null;
|
|
58473
|
+
return {
|
|
58474
|
+
outputTypes: [{ kind: "struct", fields: {} }],
|
|
58475
|
+
apply: (args) => {
|
|
58476
|
+
const value = args[args.length - 1];
|
|
58477
|
+
const fieldArgs = args.slice(1, args.length - 1);
|
|
58478
|
+
const setChain = (s, depth) => {
|
|
58479
|
+
const fa = fieldArgs[depth];
|
|
58480
|
+
if (isRuntimeCell(fa))
|
|
58481
|
+
throw new RuntimeError(
|
|
58482
|
+
"setfield: index ({}) subscripts are not supported"
|
|
58483
|
+
);
|
|
58484
|
+
const name = toString(fa);
|
|
58485
|
+
const base = isRuntimeStruct(s) ? s.fields : /* @__PURE__ */ new Map();
|
|
58486
|
+
if (!isRuntimeStruct(s) && !(isRuntimeTensor(s) && s.data.length === 0))
|
|
58487
|
+
throw new RuntimeError("setfield: argument must be a structure");
|
|
58488
|
+
const newFields = new Map(base);
|
|
58489
|
+
if (depth === fieldArgs.length - 1) {
|
|
58490
|
+
newFields.set(name, value);
|
|
58491
|
+
} else {
|
|
58492
|
+
const child = newFields.get(name);
|
|
58493
|
+
newFields.set(
|
|
58494
|
+
name,
|
|
58495
|
+
setChain(child ?? RTV.struct(/* @__PURE__ */ new Map()), depth + 1)
|
|
58496
|
+
);
|
|
58497
|
+
}
|
|
58498
|
+
return RTV.struct(newFields);
|
|
58499
|
+
};
|
|
58500
|
+
return setChain(args[0], 0);
|
|
58501
|
+
}
|
|
58502
|
+
};
|
|
58503
|
+
}
|
|
58504
|
+
});
|
|
57578
58505
|
registerIBuiltin({
|
|
57579
58506
|
name: "namedargs2cell",
|
|
57580
58507
|
resolve: (argTypes) => {
|
|
@@ -57596,6 +58523,10 @@ registerIBuiltin({
|
|
|
57596
58523
|
};
|
|
57597
58524
|
}
|
|
57598
58525
|
});
|
|
58526
|
+
function rmfieldNames(arg) {
|
|
58527
|
+
if (isRuntimeCell(arg)) return arg.data.map(toString);
|
|
58528
|
+
return [toString(arg)];
|
|
58529
|
+
}
|
|
57599
58530
|
registerIBuiltin({
|
|
57600
58531
|
name: "rmfield",
|
|
57601
58532
|
resolve: (argTypes) => {
|
|
@@ -57604,25 +58535,26 @@ registerIBuiltin({
|
|
|
57604
58535
|
outputTypes: [{ kind: "struct", fields: {} }],
|
|
57605
58536
|
apply: (args) => {
|
|
57606
58537
|
const v = args[0];
|
|
58538
|
+
const names = rmfieldNames(args[1]);
|
|
57607
58539
|
if (isRuntimeStructArray(v)) {
|
|
57608
|
-
const
|
|
57609
|
-
|
|
57610
|
-
|
|
57611
|
-
const newFieldNames = v.fieldNames.filter((n) => n
|
|
58540
|
+
for (const name of names)
|
|
58541
|
+
if (!v.fieldNames.includes(name))
|
|
58542
|
+
throw new RuntimeError(`rmfield: field '${name}' does not exist`);
|
|
58543
|
+
const newFieldNames = v.fieldNames.filter((n) => !names.includes(n));
|
|
57612
58544
|
const newElements = v.elements.map((el) => {
|
|
57613
58545
|
const newFields2 = new Map(el.fields);
|
|
57614
|
-
newFields2.delete(
|
|
58546
|
+
for (const name of names) newFields2.delete(name);
|
|
57615
58547
|
return RTV.struct(newFields2);
|
|
57616
58548
|
});
|
|
57617
58549
|
return RTV.structArray(newFieldNames, newElements);
|
|
57618
58550
|
}
|
|
57619
58551
|
if (!isRuntimeStruct(v))
|
|
57620
58552
|
throw new RuntimeError("rmfield: first argument must be a struct");
|
|
57621
|
-
const name
|
|
57622
|
-
|
|
57623
|
-
|
|
58553
|
+
for (const name of names)
|
|
58554
|
+
if (!v.fields.has(name))
|
|
58555
|
+
throw new RuntimeError(`rmfield: field '${name}' does not exist`);
|
|
57624
58556
|
const newFields = new Map(v.fields);
|
|
57625
|
-
newFields.delete(name);
|
|
58557
|
+
for (const name of names) newFields.delete(name);
|
|
57626
58558
|
return RTV.struct(newFields);
|
|
57627
58559
|
}
|
|
57628
58560
|
};
|
|
@@ -57843,6 +58775,23 @@ registerIBuiltin({
|
|
|
57843
58775
|
}
|
|
57844
58776
|
})
|
|
57845
58777
|
});
|
|
58778
|
+
registerIBuiltin({
|
|
58779
|
+
name: "spalloc",
|
|
58780
|
+
resolve: () => ({
|
|
58781
|
+
outputTypes: [{ kind: "unknown" }],
|
|
58782
|
+
apply: (args) => {
|
|
58783
|
+
const m = args.length >= 1 ? Math.round(toNumber(args[0])) : 0;
|
|
58784
|
+
const n = args.length >= 2 ? Math.round(toNumber(args[1])) : 0;
|
|
58785
|
+
return RTV.sparseMatrix(
|
|
58786
|
+
m,
|
|
58787
|
+
n,
|
|
58788
|
+
new Int32Array(0),
|
|
58789
|
+
new Int32Array(n + 1),
|
|
58790
|
+
allocFloat64Array(0)
|
|
58791
|
+
);
|
|
58792
|
+
}
|
|
58793
|
+
})
|
|
58794
|
+
});
|
|
57846
58795
|
registerIBuiltin({
|
|
57847
58796
|
name: "speye",
|
|
57848
58797
|
resolve: () => ({
|
|
@@ -58128,6 +59077,598 @@ registerIBuiltin({
|
|
|
58128
59077
|
}
|
|
58129
59078
|
})
|
|
58130
59079
|
});
|
|
59080
|
+
var SPPARMS_KEYS = [
|
|
59081
|
+
"spumoni",
|
|
59082
|
+
"thr_rel",
|
|
59083
|
+
"thr_abs",
|
|
59084
|
+
"exact_d",
|
|
59085
|
+
"supernd",
|
|
59086
|
+
"rreduce",
|
|
59087
|
+
"wh_frac",
|
|
59088
|
+
"autommd",
|
|
59089
|
+
"autoamd",
|
|
59090
|
+
"piv_tol",
|
|
59091
|
+
"bandden",
|
|
59092
|
+
"umfpack",
|
|
59093
|
+
"sym_tol",
|
|
59094
|
+
"ldl_tol",
|
|
59095
|
+
"usema57",
|
|
59096
|
+
"spqrtol",
|
|
59097
|
+
"sp_ctor",
|
|
59098
|
+
"reorder",
|
|
59099
|
+
"no_redo"
|
|
59100
|
+
];
|
|
59101
|
+
var SPPARMS_DEFAULTS = [
|
|
59102
|
+
0,
|
|
59103
|
+
1.1,
|
|
59104
|
+
1,
|
|
59105
|
+
0,
|
|
59106
|
+
3,
|
|
59107
|
+
3,
|
|
59108
|
+
0.5,
|
|
59109
|
+
1,
|
|
59110
|
+
1,
|
|
59111
|
+
0.1,
|
|
59112
|
+
0.5,
|
|
59113
|
+
1,
|
|
59114
|
+
1e-3,
|
|
59115
|
+
0.01,
|
|
59116
|
+
1,
|
|
59117
|
+
-2,
|
|
59118
|
+
0,
|
|
59119
|
+
0,
|
|
59120
|
+
0
|
|
59121
|
+
];
|
|
59122
|
+
var spparmsState = Float64Array.from(SPPARMS_DEFAULTS);
|
|
59123
|
+
function spparmsVector() {
|
|
59124
|
+
return RTV.tensor(allocFloat64Array(Array.from(spparmsState)), [
|
|
59125
|
+
spparmsState.length,
|
|
59126
|
+
1
|
|
59127
|
+
]);
|
|
59128
|
+
}
|
|
59129
|
+
registerIBuiltin({
|
|
59130
|
+
name: "spparms",
|
|
59131
|
+
resolve: (argTypes, nargout) => {
|
|
59132
|
+
if (argTypes.length > 2) return null;
|
|
59133
|
+
const tensorOut = { kind: "tensor", isComplex: false };
|
|
59134
|
+
const outputTypes = nargout >= 2 ? [{ kind: "char" }, tensorOut] : [tensorOut];
|
|
59135
|
+
return {
|
|
59136
|
+
outputTypes,
|
|
59137
|
+
apply: (args, n) => {
|
|
59138
|
+
if (args.length === 0) {
|
|
59139
|
+
if (n >= 2) {
|
|
59140
|
+
const width = Math.max(...SPPARMS_KEYS.map((k) => k.length));
|
|
59141
|
+
const padded = SPPARMS_KEYS.map((k) => k.padEnd(width)).join("");
|
|
59142
|
+
return [
|
|
59143
|
+
new RuntimeChar(padded, [SPPARMS_KEYS.length, width]),
|
|
59144
|
+
spparmsVector()
|
|
59145
|
+
];
|
|
59146
|
+
}
|
|
59147
|
+
return spparmsVector();
|
|
59148
|
+
}
|
|
59149
|
+
const first = args[0];
|
|
59150
|
+
if (isRuntimeChar(first) || isRuntimeString(first)) {
|
|
59151
|
+
const key = parseStringArgLower(first);
|
|
59152
|
+
if (args.length >= 2) {
|
|
59153
|
+
const idx2 = SPPARMS_KEYS.indexOf(key);
|
|
59154
|
+
if (idx2 >= 0) spparmsState[idx2] = toNumber(args[1]);
|
|
59155
|
+
return RTV.num(0);
|
|
59156
|
+
}
|
|
59157
|
+
if (key === "default") {
|
|
59158
|
+
spparmsState = Float64Array.from(SPPARMS_DEFAULTS);
|
|
59159
|
+
return RTV.num(0);
|
|
59160
|
+
}
|
|
59161
|
+
if (key === "tight") {
|
|
59162
|
+
return RTV.num(0);
|
|
59163
|
+
}
|
|
59164
|
+
const idx = SPPARMS_KEYS.indexOf(key);
|
|
59165
|
+
if (idx >= 0) return RTV.num(spparmsState[idx]);
|
|
59166
|
+
throw new RuntimeError(`spparms: unknown parameter '${key}'`);
|
|
59167
|
+
}
|
|
59168
|
+
const vals = isRuntimeNumber(first) ? [first] : isRuntimeTensor(first) ? Array.from(first.data) : null;
|
|
59169
|
+
if (vals === null)
|
|
59170
|
+
throw new RuntimeError(
|
|
59171
|
+
"spparms: argument must be a parameter name or value vector"
|
|
59172
|
+
);
|
|
59173
|
+
const next = Float64Array.from(spparmsState);
|
|
59174
|
+
for (let i = 0; i < Math.min(vals.length, next.length); i++)
|
|
59175
|
+
next[i] = vals[i];
|
|
59176
|
+
spparmsState = next;
|
|
59177
|
+
return RTV.num(0);
|
|
59178
|
+
}
|
|
59179
|
+
};
|
|
59180
|
+
}
|
|
59181
|
+
});
|
|
59182
|
+
|
|
59183
|
+
// src/numbl-core/interpreter/builtins/graph.ts
|
|
59184
|
+
function isGraph(v) {
|
|
59185
|
+
return isRuntimeClassInstance(v) && v.className === "graph";
|
|
59186
|
+
}
|
|
59187
|
+
function requireGraph(v, fn) {
|
|
59188
|
+
if (!isGraph(v)) {
|
|
59189
|
+
throw new RuntimeError(`${fn}: first argument must be a graph`);
|
|
59190
|
+
}
|
|
59191
|
+
return v;
|
|
59192
|
+
}
|
|
59193
|
+
function graphN(g) {
|
|
59194
|
+
return toNumber(g.fields.get("_n") ?? 0);
|
|
59195
|
+
}
|
|
59196
|
+
function graphWeighted(g) {
|
|
59197
|
+
const w = g.fields.get("_weighted");
|
|
59198
|
+
return w === true;
|
|
59199
|
+
}
|
|
59200
|
+
function graphAdj(g) {
|
|
59201
|
+
const a = g.fields.get("_A");
|
|
59202
|
+
if (a === void 0 || !isRuntimeSparseMatrix(a)) {
|
|
59203
|
+
throw new RuntimeError("graph: corrupt internal adjacency");
|
|
59204
|
+
}
|
|
59205
|
+
return a;
|
|
59206
|
+
}
|
|
59207
|
+
function buildSymAdj(n, edges) {
|
|
59208
|
+
const triplets = [];
|
|
59209
|
+
for (const e of edges) {
|
|
59210
|
+
if (e.w === 0) continue;
|
|
59211
|
+
const u = e.u - 1;
|
|
59212
|
+
const v = e.v - 1;
|
|
59213
|
+
if (u === v) {
|
|
59214
|
+
triplets.push({ col: u, row: u, val: e.w });
|
|
59215
|
+
} else {
|
|
59216
|
+
triplets.push({ col: v, row: u, val: e.w });
|
|
59217
|
+
triplets.push({ col: u, row: v, val: e.w });
|
|
59218
|
+
}
|
|
59219
|
+
}
|
|
59220
|
+
triplets.sort((a, b) => a.col - b.col || a.row - b.row);
|
|
59221
|
+
const ir = [];
|
|
59222
|
+
const pr = [];
|
|
59223
|
+
const cols = [];
|
|
59224
|
+
let prevCol = -1;
|
|
59225
|
+
let prevRow = -1;
|
|
59226
|
+
for (const t of triplets) {
|
|
59227
|
+
if (t.col === prevCol && t.row === prevRow) {
|
|
59228
|
+
pr[pr.length - 1] += t.val;
|
|
59229
|
+
} else {
|
|
59230
|
+
ir.push(t.row);
|
|
59231
|
+
pr.push(t.val);
|
|
59232
|
+
cols.push(t.col);
|
|
59233
|
+
prevCol = t.col;
|
|
59234
|
+
prevRow = t.row;
|
|
59235
|
+
}
|
|
59236
|
+
}
|
|
59237
|
+
const jc = new Int32Array(n + 1);
|
|
59238
|
+
let ci = 0;
|
|
59239
|
+
for (let c = 0; c < n; c++) {
|
|
59240
|
+
jc[c] = ci;
|
|
59241
|
+
while (ci < cols.length && cols[ci] === c) ci++;
|
|
59242
|
+
}
|
|
59243
|
+
jc[n] = ci;
|
|
59244
|
+
return RTV.sparseMatrix(n, n, new Int32Array(ir), jc, allocFloat64Array(pr));
|
|
59245
|
+
}
|
|
59246
|
+
function makeGraph(n, edges, weighted) {
|
|
59247
|
+
const fields = /* @__PURE__ */ new Map();
|
|
59248
|
+
fields.set("_n", n);
|
|
59249
|
+
fields.set("_A", buildSymAdj(n, edges));
|
|
59250
|
+
fields.set("_weighted", weighted);
|
|
59251
|
+
return new RuntimeClassInstance("graph", fields, false);
|
|
59252
|
+
}
|
|
59253
|
+
function eachNeighbor(A, c, cb) {
|
|
59254
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) {
|
|
59255
|
+
const r = A.ir[k];
|
|
59256
|
+
if (r !== c) cb(r, A.pr[k]);
|
|
59257
|
+
}
|
|
59258
|
+
}
|
|
59259
|
+
function edgesFromAdj(A) {
|
|
59260
|
+
const edges = [];
|
|
59261
|
+
for (let c = 0; c < A.n; c++) {
|
|
59262
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) {
|
|
59263
|
+
const r = A.ir[k];
|
|
59264
|
+
if (r < c) edges.push({ u: r + 1, v: c + 1, w: A.pr[k] });
|
|
59265
|
+
else if (r === c) edges.push({ u: r + 1, v: r + 1, w: A.pr[k] });
|
|
59266
|
+
}
|
|
59267
|
+
}
|
|
59268
|
+
return edges;
|
|
59269
|
+
}
|
|
59270
|
+
function squareDim(A, fn) {
|
|
59271
|
+
if (isRuntimeNumber(A) || isRuntimeLogical(A)) return 1;
|
|
59272
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
59273
|
+
if (A.m !== A.n) throw new RuntimeError(`${fn}: adjacency must be square`);
|
|
59274
|
+
return A.n;
|
|
59275
|
+
}
|
|
59276
|
+
if (isRuntimeTensor(A)) {
|
|
59277
|
+
const rows = A.shape[0] ?? 1;
|
|
59278
|
+
const cols = A.shape[1] ?? 1;
|
|
59279
|
+
if (rows !== cols)
|
|
59280
|
+
throw new RuntimeError(`${fn}: adjacency must be square`);
|
|
59281
|
+
return rows;
|
|
59282
|
+
}
|
|
59283
|
+
throw new RuntimeError(`${fn}: adjacency must be a numeric matrix`);
|
|
59284
|
+
}
|
|
59285
|
+
function takeEntry(r, c, triangle) {
|
|
59286
|
+
if (r === c) return true;
|
|
59287
|
+
if (triangle === "lower") return r > c;
|
|
59288
|
+
return r < c;
|
|
59289
|
+
}
|
|
59290
|
+
function adjToEdges(A, omitSelfLoops, triangle, fn) {
|
|
59291
|
+
const n = squareDim(A, fn);
|
|
59292
|
+
const weighted = !(isRuntimeTensor(A) && A._isLogical);
|
|
59293
|
+
const edges = [];
|
|
59294
|
+
const push = (r, c, val) => {
|
|
59295
|
+
if (val === 0) return;
|
|
59296
|
+
if (r === c) {
|
|
59297
|
+
if (!omitSelfLoops) edges.push({ u: r + 1, v: r + 1, w: val });
|
|
59298
|
+
} else if (takeEntry(r, c, triangle)) {
|
|
59299
|
+
edges.push({ u: Math.min(r, c) + 1, v: Math.max(r, c) + 1, w: val });
|
|
59300
|
+
}
|
|
59301
|
+
};
|
|
59302
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
59303
|
+
for (let c = 0; c < A.n; c++) {
|
|
59304
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) push(A.ir[k], c, A.pr[k]);
|
|
59305
|
+
}
|
|
59306
|
+
} else if (isRuntimeTensor(A)) {
|
|
59307
|
+
const m = A.shape[0] ?? 1;
|
|
59308
|
+
for (let c = 0; c < n; c++) {
|
|
59309
|
+
for (let r = 0; r < n; r++) {
|
|
59310
|
+
const val = A.data[c * m + r];
|
|
59311
|
+
if (val !== 0) push(r, c, val);
|
|
59312
|
+
}
|
|
59313
|
+
}
|
|
59314
|
+
} else if (isRuntimeNumber(A) || isRuntimeLogical(A)) {
|
|
59315
|
+
const val = isRuntimeNumber(A) ? A : A ? 1 : 0;
|
|
59316
|
+
if (val !== 0) push(0, 0, val);
|
|
59317
|
+
}
|
|
59318
|
+
return { n, edges, weighted };
|
|
59319
|
+
}
|
|
59320
|
+
function isNumericArg3(v) {
|
|
59321
|
+
return isRuntimeNumber(v) || isRuntimeLogical(v) || isRuntimeTensor(v) || isRuntimeSparseMatrix(v);
|
|
59322
|
+
}
|
|
59323
|
+
function toNumArray2(v) {
|
|
59324
|
+
if (isRuntimeNumber(v)) return [v];
|
|
59325
|
+
if (isRuntimeLogical(v)) return [v ? 1 : 0];
|
|
59326
|
+
if (isRuntimeTensor(v)) return Array.from(v.data);
|
|
59327
|
+
throw new RuntimeError("graph: node/weight arguments must be numeric");
|
|
59328
|
+
}
|
|
59329
|
+
function argString(v) {
|
|
59330
|
+
if (isRuntimeString(v)) return v;
|
|
59331
|
+
if (isRuntimeChar(v)) return v.value;
|
|
59332
|
+
return null;
|
|
59333
|
+
}
|
|
59334
|
+
registerIBuiltin({
|
|
59335
|
+
name: "graph",
|
|
59336
|
+
help: {
|
|
59337
|
+
signatures: [
|
|
59338
|
+
"G = graph(A)",
|
|
59339
|
+
"G = graph(A, 'omitselfloops')",
|
|
59340
|
+
"G = graph(A, 'upper' | 'lower')",
|
|
59341
|
+
"G = graph(s, t)",
|
|
59342
|
+
"G = graph(s, t, w)",
|
|
59343
|
+
"G = graph(s, t, w, num)"
|
|
59344
|
+
],
|
|
59345
|
+
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."
|
|
59346
|
+
},
|
|
59347
|
+
resolve: () => ({
|
|
59348
|
+
outputTypes: [
|
|
59349
|
+
{
|
|
59350
|
+
kind: "class_instance",
|
|
59351
|
+
className: "graph",
|
|
59352
|
+
isHandleClass: false,
|
|
59353
|
+
fields: {}
|
|
59354
|
+
}
|
|
59355
|
+
],
|
|
59356
|
+
apply: (args) => {
|
|
59357
|
+
if (args.length === 0) return makeGraph(0, [], false);
|
|
59358
|
+
if (args.length >= 2 && isNumericArg3(args[1])) {
|
|
59359
|
+
const s = toNumArray2(args[0]);
|
|
59360
|
+
const t = toNumArray2(args[1]);
|
|
59361
|
+
if (s.length !== t.length) {
|
|
59362
|
+
throw new RuntimeError("graph: s and t must have the same length");
|
|
59363
|
+
}
|
|
59364
|
+
let weighted2 = false;
|
|
59365
|
+
let w = null;
|
|
59366
|
+
let num = null;
|
|
59367
|
+
let omitSelfLoops2 = false;
|
|
59368
|
+
if (args.length >= 3 && isNumericArg3(args[2])) {
|
|
59369
|
+
w = toNumArray2(args[2]);
|
|
59370
|
+
weighted2 = true;
|
|
59371
|
+
if (args.length >= 4 && isNumericArg3(args[3])) {
|
|
59372
|
+
num = Math.floor(toNumber(args[3]));
|
|
59373
|
+
}
|
|
59374
|
+
}
|
|
59375
|
+
for (let i = 2; i < args.length; i++) {
|
|
59376
|
+
const str = argString(args[i]);
|
|
59377
|
+
if (str && str.toLowerCase() === "omitselfloops")
|
|
59378
|
+
omitSelfLoops2 = true;
|
|
59379
|
+
}
|
|
59380
|
+
let n2 = num ?? 0;
|
|
59381
|
+
for (let i = 0; i < s.length; i++) n2 = Math.max(n2, s[i], t[i]);
|
|
59382
|
+
const edges2 = [];
|
|
59383
|
+
for (let i = 0; i < s.length; i++) {
|
|
59384
|
+
const u = Math.min(s[i], t[i]);
|
|
59385
|
+
const v = Math.max(s[i], t[i]);
|
|
59386
|
+
if (omitSelfLoops2 && u === v) continue;
|
|
59387
|
+
edges2.push({ u, v, w: w ? w[w.length === 1 ? 0 : i] : 1 });
|
|
59388
|
+
}
|
|
59389
|
+
return makeGraph(n2, edges2, weighted2);
|
|
59390
|
+
}
|
|
59391
|
+
let omitSelfLoops = false;
|
|
59392
|
+
let triangle = "sym";
|
|
59393
|
+
for (let i = 1; i < args.length; i++) {
|
|
59394
|
+
const str = argString(args[i]);
|
|
59395
|
+
if (!str) continue;
|
|
59396
|
+
const lc = str.toLowerCase();
|
|
59397
|
+
if (lc === "omitselfloops") omitSelfLoops = true;
|
|
59398
|
+
else if (lc === "upper") triangle = "upper";
|
|
59399
|
+
else if (lc === "lower") triangle = "lower";
|
|
59400
|
+
}
|
|
59401
|
+
const { n, edges, weighted } = adjToEdges(
|
|
59402
|
+
args[0],
|
|
59403
|
+
omitSelfLoops,
|
|
59404
|
+
triangle,
|
|
59405
|
+
"graph"
|
|
59406
|
+
);
|
|
59407
|
+
return makeGraph(n, edges, weighted);
|
|
59408
|
+
}
|
|
59409
|
+
})
|
|
59410
|
+
});
|
|
59411
|
+
registerIBuiltin({
|
|
59412
|
+
name: "conncomp",
|
|
59413
|
+
help: {
|
|
59414
|
+
signatures: ["bins = conncomp(G)", "[bins, binsizes] = conncomp(G)"],
|
|
59415
|
+
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."
|
|
59416
|
+
},
|
|
59417
|
+
resolve: () => ({
|
|
59418
|
+
outputTypes: [{ kind: "unknown" }, { kind: "unknown" }],
|
|
59419
|
+
apply: (args, nargout) => {
|
|
59420
|
+
const g = requireGraph(args[0], "conncomp");
|
|
59421
|
+
const n = graphN(g);
|
|
59422
|
+
const A = graphAdj(g);
|
|
59423
|
+
const bins = new Float64Array(n);
|
|
59424
|
+
const sizes = [];
|
|
59425
|
+
let comp = 0;
|
|
59426
|
+
const stack = [];
|
|
59427
|
+
for (let start = 0; start < n; start++) {
|
|
59428
|
+
if (bins[start] !== 0) continue;
|
|
59429
|
+
comp++;
|
|
59430
|
+
let count = 0;
|
|
59431
|
+
bins[start] = comp;
|
|
59432
|
+
stack.length = 0;
|
|
59433
|
+
stack.push(start);
|
|
59434
|
+
while (stack.length > 0) {
|
|
59435
|
+
const node = stack.pop();
|
|
59436
|
+
count++;
|
|
59437
|
+
eachNeighbor(A, node, (r) => {
|
|
59438
|
+
if (bins[r] === 0) {
|
|
59439
|
+
bins[r] = comp;
|
|
59440
|
+
stack.push(r);
|
|
59441
|
+
}
|
|
59442
|
+
});
|
|
59443
|
+
}
|
|
59444
|
+
sizes.push(count);
|
|
59445
|
+
}
|
|
59446
|
+
const binsT = RTV.tensor(bins, [1, n]);
|
|
59447
|
+
if (nargout >= 2) {
|
|
59448
|
+
return [binsT, RTV.tensor(allocFloat64Array(sizes), [1, sizes.length])];
|
|
59449
|
+
}
|
|
59450
|
+
return binsT;
|
|
59451
|
+
}
|
|
59452
|
+
})
|
|
59453
|
+
});
|
|
59454
|
+
registerIBuiltin({
|
|
59455
|
+
name: "laplacian",
|
|
59456
|
+
help: {
|
|
59457
|
+
signatures: ["L = laplacian(G)"],
|
|
59458
|
+
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."
|
|
59459
|
+
},
|
|
59460
|
+
resolve: () => ({
|
|
59461
|
+
outputTypes: [{ kind: "unknown" }],
|
|
59462
|
+
apply: (args) => {
|
|
59463
|
+
const g = requireGraph(args[0], "laplacian");
|
|
59464
|
+
const n = graphN(g);
|
|
59465
|
+
const A = graphAdj(g);
|
|
59466
|
+
const edges = [];
|
|
59467
|
+
for (let c = 0; c < n; c++) {
|
|
59468
|
+
let degree = 0;
|
|
59469
|
+
eachNeighbor(A, c, (r) => {
|
|
59470
|
+
degree++;
|
|
59471
|
+
if (r < c) edges.push({ u: r + 1, v: c + 1, w: -1 });
|
|
59472
|
+
});
|
|
59473
|
+
edges.push({ u: c + 1, v: c + 1, w: degree });
|
|
59474
|
+
}
|
|
59475
|
+
return buildSymAdj(n, edges);
|
|
59476
|
+
}
|
|
59477
|
+
})
|
|
59478
|
+
});
|
|
59479
|
+
registerIBuiltin({
|
|
59480
|
+
name: "addedge",
|
|
59481
|
+
help: {
|
|
59482
|
+
signatures: ["H = addedge(G, s, t)", "H = addedge(G, s, t, w)"],
|
|
59483
|
+
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."
|
|
59484
|
+
},
|
|
59485
|
+
resolve: () => ({
|
|
59486
|
+
outputTypes: [
|
|
59487
|
+
{
|
|
59488
|
+
kind: "class_instance",
|
|
59489
|
+
className: "graph",
|
|
59490
|
+
isHandleClass: false,
|
|
59491
|
+
fields: {}
|
|
59492
|
+
}
|
|
59493
|
+
],
|
|
59494
|
+
apply: (args) => {
|
|
59495
|
+
const g = requireGraph(args[0], "addedge");
|
|
59496
|
+
if (args.length < 3) {
|
|
59497
|
+
throw new RuntimeError("addedge: requires nodes s and t");
|
|
59498
|
+
}
|
|
59499
|
+
const weighted = graphWeighted(g);
|
|
59500
|
+
const s = toNumArray2(args[1]);
|
|
59501
|
+
const t = toNumArray2(args[2]);
|
|
59502
|
+
if (s.length !== t.length) {
|
|
59503
|
+
throw new RuntimeError("addedge: s and t must have the same length");
|
|
59504
|
+
}
|
|
59505
|
+
let w = null;
|
|
59506
|
+
if (args.length >= 4) {
|
|
59507
|
+
w = toNumArray2(args[3]);
|
|
59508
|
+
} else if (weighted) {
|
|
59509
|
+
throw new RuntimeError(
|
|
59510
|
+
"addedge: Must specify weights when adding an edge to a weighted graph."
|
|
59511
|
+
);
|
|
59512
|
+
}
|
|
59513
|
+
const edges = edgesFromAdj(graphAdj(g));
|
|
59514
|
+
let n = graphN(g);
|
|
59515
|
+
for (let i = 0; i < s.length; i++) {
|
|
59516
|
+
const u = Math.min(s[i], t[i]);
|
|
59517
|
+
const v = Math.max(s[i], t[i]);
|
|
59518
|
+
n = Math.max(n, u, v);
|
|
59519
|
+
edges.push({ u, v, w: w ? w[w.length === 1 ? 0 : i] : 1 });
|
|
59520
|
+
}
|
|
59521
|
+
return makeGraph(n, edges, weighted);
|
|
59522
|
+
}
|
|
59523
|
+
})
|
|
59524
|
+
});
|
|
59525
|
+
registerIBuiltin({
|
|
59526
|
+
name: "numnodes",
|
|
59527
|
+
help: {
|
|
59528
|
+
signatures: ["n = numnodes(G)"],
|
|
59529
|
+
description: "Number of nodes in graph G."
|
|
59530
|
+
},
|
|
59531
|
+
resolve: () => ({
|
|
59532
|
+
outputTypes: [{ kind: "number" }],
|
|
59533
|
+
apply: (args) => RTV.num(graphN(requireGraph(args[0], "numnodes")))
|
|
59534
|
+
})
|
|
59535
|
+
});
|
|
59536
|
+
registerIBuiltin({
|
|
59537
|
+
name: "numedges",
|
|
59538
|
+
help: {
|
|
59539
|
+
signatures: ["m = numedges(G)"],
|
|
59540
|
+
description: "Number of edges in graph G."
|
|
59541
|
+
},
|
|
59542
|
+
resolve: () => ({
|
|
59543
|
+
outputTypes: [{ kind: "number" }],
|
|
59544
|
+
apply: (args) => {
|
|
59545
|
+
const g = requireGraph(args[0], "numedges");
|
|
59546
|
+
return RTV.num(edgesFromAdj(graphAdj(g)).length);
|
|
59547
|
+
}
|
|
59548
|
+
})
|
|
59549
|
+
});
|
|
59550
|
+
registerIBuiltin({
|
|
59551
|
+
name: "degree",
|
|
59552
|
+
help: {
|
|
59553
|
+
signatures: ["d = degree(G)"],
|
|
59554
|
+
description: "Degree of each node in graph G, returned as a column vector of edge counts (self-loops excluded)."
|
|
59555
|
+
},
|
|
59556
|
+
resolve: () => ({
|
|
59557
|
+
outputTypes: [{ kind: "unknown" }],
|
|
59558
|
+
apply: (args) => {
|
|
59559
|
+
const g = requireGraph(args[0], "degree");
|
|
59560
|
+
const n = graphN(g);
|
|
59561
|
+
const A = graphAdj(g);
|
|
59562
|
+
const d = new Float64Array(n);
|
|
59563
|
+
for (let c = 0; c < n; c++) eachNeighbor(A, c, () => d[c] += 1);
|
|
59564
|
+
return RTV.tensor(d, [n, 1]);
|
|
59565
|
+
}
|
|
59566
|
+
})
|
|
59567
|
+
});
|
|
59568
|
+
|
|
59569
|
+
// src/numbl-core/interpreter/builtins/gallery.ts
|
|
59570
|
+
function toNumArray3(v, what) {
|
|
59571
|
+
if (isRuntimeNumber(v)) return [v];
|
|
59572
|
+
if (isRuntimeLogical(v)) return [v ? 1 : 0];
|
|
59573
|
+
if (isRuntimeTensor(v)) return Array.from(v.data);
|
|
59574
|
+
if (isRuntimeComplexNumber(v)) return [v.re];
|
|
59575
|
+
throw new RuntimeError(`gallery: ${what} must be numeric`);
|
|
59576
|
+
}
|
|
59577
|
+
function buildTridiag(sub2, diag2, sup) {
|
|
59578
|
+
const n = diag2.length;
|
|
59579
|
+
if (sub2.length !== n - 1 || sup.length !== n - 1) {
|
|
59580
|
+
throw new RuntimeError(
|
|
59581
|
+
"gallery: tridiag sub/superdiagonal must have length one less than the diagonal"
|
|
59582
|
+
);
|
|
59583
|
+
}
|
|
59584
|
+
const ir = [];
|
|
59585
|
+
const pr = [];
|
|
59586
|
+
const jc = new Int32Array(n + 1);
|
|
59587
|
+
for (let c = 0; c < n; c++) {
|
|
59588
|
+
jc[c] = ir.length;
|
|
59589
|
+
if (c >= 1 && sup[c - 1] !== 0) {
|
|
59590
|
+
ir.push(c - 1);
|
|
59591
|
+
pr.push(sup[c - 1]);
|
|
59592
|
+
}
|
|
59593
|
+
if (diag2[c] !== 0) {
|
|
59594
|
+
ir.push(c);
|
|
59595
|
+
pr.push(diag2[c]);
|
|
59596
|
+
}
|
|
59597
|
+
if (c <= n - 2 && sub2[c] !== 0) {
|
|
59598
|
+
ir.push(c + 1);
|
|
59599
|
+
pr.push(sub2[c]);
|
|
59600
|
+
}
|
|
59601
|
+
}
|
|
59602
|
+
jc[n] = ir.length;
|
|
59603
|
+
return RTV.sparseMatrix(n, n, new Int32Array(ir), jc, allocFloat64Array(pr));
|
|
59604
|
+
}
|
|
59605
|
+
function buildTridiagToeplitz(n, c, d, e) {
|
|
59606
|
+
const off = Math.max(0, n - 1);
|
|
59607
|
+
return buildTridiag(
|
|
59608
|
+
new Array(off).fill(c),
|
|
59609
|
+
new Array(n).fill(d),
|
|
59610
|
+
new Array(off).fill(e)
|
|
59611
|
+
);
|
|
59612
|
+
}
|
|
59613
|
+
function galleryTridiag(rest) {
|
|
59614
|
+
if (rest.length === 1) {
|
|
59615
|
+
return buildTridiagToeplitz(Math.round(toNumber(rest[0])), -1, 2, -1);
|
|
59616
|
+
}
|
|
59617
|
+
if (rest.length === 4) {
|
|
59618
|
+
return buildTridiagToeplitz(
|
|
59619
|
+
Math.round(toNumber(rest[0])),
|
|
59620
|
+
toNumber(rest[1]),
|
|
59621
|
+
toNumber(rest[2]),
|
|
59622
|
+
toNumber(rest[3])
|
|
59623
|
+
);
|
|
59624
|
+
}
|
|
59625
|
+
if (rest.length === 3) {
|
|
59626
|
+
const sub2 = toNumArray3(rest[0], "subdiagonal");
|
|
59627
|
+
const diag2 = toNumArray3(rest[1], "diagonal");
|
|
59628
|
+
const sup = toNumArray3(rest[2], "superdiagonal");
|
|
59629
|
+
if (sub2.length === 1 && diag2.length === 1 && sup.length === 1) {
|
|
59630
|
+
return buildTridiag([], diag2, []);
|
|
59631
|
+
}
|
|
59632
|
+
return buildTridiag(sub2, diag2, sup);
|
|
59633
|
+
}
|
|
59634
|
+
throw new RuntimeError("gallery: tridiag expects (n), (n,c,d,e), or (x,y,z)");
|
|
59635
|
+
}
|
|
59636
|
+
registerIBuiltin({
|
|
59637
|
+
name: "gallery",
|
|
59638
|
+
help: {
|
|
59639
|
+
signatures: [
|
|
59640
|
+
"A = gallery('tridiag', n)",
|
|
59641
|
+
"A = gallery('tridiag', n, c, d, e)",
|
|
59642
|
+
"A = gallery('tridiag', x, y, z)"
|
|
59643
|
+
],
|
|
59644
|
+
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."
|
|
59645
|
+
},
|
|
59646
|
+
resolve: () => ({
|
|
59647
|
+
outputTypes: [{ kind: "unknown" }],
|
|
59648
|
+
apply: (args) => {
|
|
59649
|
+
if (args.length < 1) {
|
|
59650
|
+
throw new RuntimeError("gallery: not enough input arguments");
|
|
59651
|
+
}
|
|
59652
|
+
const name = parseStringArgLower(args[0]);
|
|
59653
|
+
let rest = args.slice(1);
|
|
59654
|
+
if (rest.length >= 1) {
|
|
59655
|
+
const last = rest[rest.length - 1];
|
|
59656
|
+
if (isRuntimeString(last) || isRuntimeChar(last)) {
|
|
59657
|
+
const cn = parseStringArgLower(last);
|
|
59658
|
+
if (cn === "single" || cn === "double") rest = rest.slice(0, -1);
|
|
59659
|
+
}
|
|
59660
|
+
}
|
|
59661
|
+
switch (name) {
|
|
59662
|
+
case "tridiag":
|
|
59663
|
+
return galleryTridiag(rest);
|
|
59664
|
+
default:
|
|
59665
|
+
throw new RuntimeError(
|
|
59666
|
+
`gallery: matrix family '${name}' is not supported`
|
|
59667
|
+
);
|
|
59668
|
+
}
|
|
59669
|
+
}
|
|
59670
|
+
})
|
|
59671
|
+
});
|
|
58131
59672
|
|
|
58132
59673
|
// src/numbl-core/interpreter/builtins/special-math.ts
|
|
58133
59674
|
function binaryApply(a, b, fn) {
|
|
@@ -58611,12 +60152,19 @@ registerIBuiltin({
|
|
|
58611
60152
|
|
|
58612
60153
|
// src/numbl-core/native/geometry-bridge.ts
|
|
58613
60154
|
var backend = null;
|
|
60155
|
+
var hullBackend = null;
|
|
58614
60156
|
function setDelaunayBackend(fn) {
|
|
58615
60157
|
backend = fn;
|
|
58616
60158
|
}
|
|
58617
60159
|
function getDelaunayBackend() {
|
|
58618
60160
|
return backend;
|
|
58619
60161
|
}
|
|
60162
|
+
function setConvexHullBackend(fn) {
|
|
60163
|
+
hullBackend = fn;
|
|
60164
|
+
}
|
|
60165
|
+
function getConvexHullBackend() {
|
|
60166
|
+
return hullBackend;
|
|
60167
|
+
}
|
|
58620
60168
|
|
|
58621
60169
|
// src/numbl-core/interpreter/builtins/geometry.ts
|
|
58622
60170
|
function toFlatArray(v, name) {
|
|
@@ -58669,7 +60217,7 @@ function simplexVolume(points, cell, dim) {
|
|
|
58669
60217
|
for (let k = 2; k <= dim; k++) fact *= k;
|
|
58670
60218
|
return Math.abs(det) / fact;
|
|
58671
60219
|
}
|
|
58672
|
-
function triangulateToTensor(points, dim) {
|
|
60220
|
+
function triangulateToTensor(points, dim, orientCCW = false) {
|
|
58673
60221
|
const backend2 = getDelaunayBackend();
|
|
58674
60222
|
if (!backend2)
|
|
58675
60223
|
throw new RuntimeError(
|
|
@@ -58689,6 +60237,16 @@ function triangulateToTensor(points, dim) {
|
|
|
58689
60237
|
const cells = volTol > 0 ? raw.filter((cell) => simplexVolume(points, cell, dim) > volTol) : raw;
|
|
58690
60238
|
const numCells = cells.length;
|
|
58691
60239
|
const cols = dim + 1;
|
|
60240
|
+
if (orientCCW && dim === 2) {
|
|
60241
|
+
for (const cell of cells) {
|
|
60242
|
+
const [a, b, c] = cell;
|
|
60243
|
+
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]);
|
|
60244
|
+
if (signedArea2 < 0) {
|
|
60245
|
+
cell[1] = c;
|
|
60246
|
+
cell[2] = b;
|
|
60247
|
+
}
|
|
60248
|
+
}
|
|
60249
|
+
}
|
|
58692
60250
|
const out = allocFloat64Array(numCells * cols);
|
|
58693
60251
|
for (let i = 0; i < numCells; i++) {
|
|
58694
60252
|
const cell = cells[i];
|
|
@@ -58742,7 +60300,7 @@ defineBuiltin({
|
|
|
58742
60300
|
throw new RuntimeError(
|
|
58743
60301
|
`delaunay: need at least ${dim + 1} points for a ${dim}-D triangulation`
|
|
58744
60302
|
);
|
|
58745
|
-
return triangulateToTensor(points, dim);
|
|
60303
|
+
return triangulateToTensor(points, dim, true);
|
|
58746
60304
|
}
|
|
58747
60305
|
}
|
|
58748
60306
|
]
|
|
@@ -58785,6 +60343,203 @@ defineBuiltin({
|
|
|
58785
60343
|
}
|
|
58786
60344
|
]
|
|
58787
60345
|
});
|
|
60346
|
+
var CONVHULLN_MAX_DIM = 3;
|
|
60347
|
+
function convexHullFacets(points, dim, name) {
|
|
60348
|
+
const backend2 = getConvexHullBackend();
|
|
60349
|
+
if (!backend2)
|
|
60350
|
+
throw new RuntimeError(
|
|
60351
|
+
`${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.`
|
|
60352
|
+
);
|
|
60353
|
+
return backend2(points, dim);
|
|
60354
|
+
}
|
|
60355
|
+
function hullInteriorPoint(points, facets, dim) {
|
|
60356
|
+
const used = /* @__PURE__ */ new Set();
|
|
60357
|
+
for (const f of facets) for (const idx of f) used.add(idx);
|
|
60358
|
+
const c = new Array(dim).fill(0);
|
|
60359
|
+
for (const idx of used) {
|
|
60360
|
+
const p2 = points[idx];
|
|
60361
|
+
for (let k = 0; k < dim; k++) c[k] += p2[k];
|
|
60362
|
+
}
|
|
60363
|
+
const m = used.size || 1;
|
|
60364
|
+
for (let k = 0; k < dim; k++) c[k] /= m;
|
|
60365
|
+
return c;
|
|
60366
|
+
}
|
|
60367
|
+
function hullMeasure(points, facets, dim) {
|
|
60368
|
+
const c = hullInteriorPoint(points, facets, dim);
|
|
60369
|
+
let total = 0;
|
|
60370
|
+
if (dim === 2) {
|
|
60371
|
+
for (const f of facets) {
|
|
60372
|
+
const a = points[f[0]];
|
|
60373
|
+
const b = points[f[1]];
|
|
60374
|
+
const ax = a[0] - c[0], ay = a[1] - c[1];
|
|
60375
|
+
const bx = b[0] - c[0], by = b[1] - c[1];
|
|
60376
|
+
total += Math.abs(ax * by - ay * bx) / 2;
|
|
60377
|
+
}
|
|
60378
|
+
} else {
|
|
60379
|
+
for (const f of facets) {
|
|
60380
|
+
const a = points[f[0]];
|
|
60381
|
+
const b = points[f[1]];
|
|
60382
|
+
const d = points[f[2]];
|
|
60383
|
+
const ax = a[0] - c[0], ay = a[1] - c[1], az = a[2] - c[2];
|
|
60384
|
+
const bx = b[0] - c[0], by = b[1] - c[1], bz = b[2] - c[2];
|
|
60385
|
+
const dx = d[0] - c[0], dy = d[1] - c[1], dz = d[2] - c[2];
|
|
60386
|
+
const det = ax * (by * dz - bz * dy) - ay * (bx * dz - bz * dx) + az * (bx * dy - by * dx);
|
|
60387
|
+
total += Math.abs(det) / 6;
|
|
60388
|
+
}
|
|
60389
|
+
}
|
|
60390
|
+
return total;
|
|
60391
|
+
}
|
|
60392
|
+
function facetsToTensor(facets, cols) {
|
|
60393
|
+
const n = facets.length;
|
|
60394
|
+
const out = allocFloat64Array(n * cols);
|
|
60395
|
+
for (let i = 0; i < n; i++) {
|
|
60396
|
+
const f = facets[i];
|
|
60397
|
+
for (let j = 0; j < cols; j++) out[j * n + i] = f[j] + 1;
|
|
60398
|
+
}
|
|
60399
|
+
return RTV.tensor(out, [n, cols]);
|
|
60400
|
+
}
|
|
60401
|
+
function orderHull2D(facets, points) {
|
|
60402
|
+
const adj = /* @__PURE__ */ new Map();
|
|
60403
|
+
for (const [a, b] of facets) {
|
|
60404
|
+
(adj.get(a) ?? adj.set(a, []).get(a)).push(b);
|
|
60405
|
+
(adj.get(b) ?? adj.set(b, []).get(b)).push(a);
|
|
60406
|
+
}
|
|
60407
|
+
const start = facets[0][0];
|
|
60408
|
+
const loop = [start];
|
|
60409
|
+
let prev = -1;
|
|
60410
|
+
let cur = start;
|
|
60411
|
+
for (let guard = 0; guard <= facets.length; guard++) {
|
|
60412
|
+
const nbrs = adj.get(cur);
|
|
60413
|
+
const next = nbrs[0] === prev ? nbrs[1] : nbrs[0];
|
|
60414
|
+
if (next === void 0 || next === start) break;
|
|
60415
|
+
loop.push(next);
|
|
60416
|
+
prev = cur;
|
|
60417
|
+
cur = next;
|
|
60418
|
+
}
|
|
60419
|
+
let signed = 0;
|
|
60420
|
+
for (let i = 0; i < loop.length; i++) {
|
|
60421
|
+
const p2 = points[loop[i]];
|
|
60422
|
+
const q = points[loop[(i + 1) % loop.length]];
|
|
60423
|
+
signed += p2[0] * q[1] - q[0] * p2[1];
|
|
60424
|
+
}
|
|
60425
|
+
if (signed < 0) loop.reverse();
|
|
60426
|
+
loop.push(loop[0]);
|
|
60427
|
+
const out = allocFloat64Array(loop.length);
|
|
60428
|
+
for (let i = 0; i < loop.length; i++) out[i] = loop[i] + 1;
|
|
60429
|
+
return RTV.tensor(out, [loop.length, 1]);
|
|
60430
|
+
}
|
|
60431
|
+
defineBuiltin({
|
|
60432
|
+
name: "convhull",
|
|
60433
|
+
help: {
|
|
60434
|
+
signatures: [
|
|
60435
|
+
"k = convhull(P)",
|
|
60436
|
+
"k = convhull(x,y)",
|
|
60437
|
+
"k = convhull(x,y,z)",
|
|
60438
|
+
"k = convhull(___,'Simplify',tf)",
|
|
60439
|
+
"[k,av] = convhull(___)"
|
|
60440
|
+
],
|
|
60441
|
+
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."
|
|
60442
|
+
},
|
|
60443
|
+
cases: [
|
|
60444
|
+
{
|
|
60445
|
+
match: (argTypes, nargout) => {
|
|
60446
|
+
if (nargout > 2) return null;
|
|
60447
|
+
if (argTypes.length < 1 || argTypes.length > 5) return null;
|
|
60448
|
+
const ok = (t) => t.kind === "number" || t.kind === "boolean" || t.kind === "tensor" || t.kind === "string" || t.kind === "char";
|
|
60449
|
+
if (!argTypes.every(ok)) return null;
|
|
60450
|
+
const k = { kind: "tensor", isComplex: false };
|
|
60451
|
+
return nargout > 1 ? [k, { kind: "number" }] : [k];
|
|
60452
|
+
},
|
|
60453
|
+
apply: (args, nargout) => {
|
|
60454
|
+
let coordArgs = args;
|
|
60455
|
+
const tail = args[args.length - 2];
|
|
60456
|
+
const isSimplifyName = (v) => typeof v === "string" && v.toLowerCase() === "simplify" || isRuntimeChar(v) && v.value.toLowerCase() === "simplify";
|
|
60457
|
+
if (args.length >= 3 && isSimplifyName(tail)) {
|
|
60458
|
+
coordArgs = args.slice(0, args.length - 2);
|
|
60459
|
+
}
|
|
60460
|
+
let points;
|
|
60461
|
+
let dim;
|
|
60462
|
+
if (coordArgs.length === 1) {
|
|
60463
|
+
const P = coordArgs[0];
|
|
60464
|
+
if (!isRuntimeTensor(P))
|
|
60465
|
+
throw new RuntimeError(
|
|
60466
|
+
"convhull: P must be an N-by-2 or N-by-3 matrix"
|
|
60467
|
+
);
|
|
60468
|
+
const [, d] = tensorSize2D(P);
|
|
60469
|
+
if (d !== 2 && d !== 3)
|
|
60470
|
+
throw new RuntimeError("convhull: P must have 2 or 3 columns");
|
|
60471
|
+
points = matrixToPoints(P, "convhull");
|
|
60472
|
+
dim = d;
|
|
60473
|
+
} else if (coordArgs.length === 2 || coordArgs.length === 3) {
|
|
60474
|
+
const coords = coordArgs.map((a) => toFlatArray(a, "convhull"));
|
|
60475
|
+
const n = coords[0].length;
|
|
60476
|
+
if (coords.some((c) => c.length !== n))
|
|
60477
|
+
throw new RuntimeError(
|
|
60478
|
+
"convhull: coordinate vectors must have the same length"
|
|
60479
|
+
);
|
|
60480
|
+
points = new Array(n);
|
|
60481
|
+
for (let i = 0; i < n; i++) points[i] = coords.map((c) => c[i]);
|
|
60482
|
+
dim = coordArgs.length;
|
|
60483
|
+
} else {
|
|
60484
|
+
throw new RuntimeError("convhull: invalid arguments");
|
|
60485
|
+
}
|
|
60486
|
+
if (points.length < dim + 1)
|
|
60487
|
+
throw new RuntimeError(
|
|
60488
|
+
`convhull: need at least ${dim + 1} points for a ${dim}-D hull`
|
|
60489
|
+
);
|
|
60490
|
+
const facets = convexHullFacets(points, dim, "convhull");
|
|
60491
|
+
const k = dim === 2 ? orderHull2D(facets, points) : facetsToTensor(facets, 3);
|
|
60492
|
+
if (nargout > 1) return [k, hullMeasure(points, facets, dim)];
|
|
60493
|
+
return k;
|
|
60494
|
+
}
|
|
60495
|
+
}
|
|
60496
|
+
]
|
|
60497
|
+
});
|
|
60498
|
+
defineBuiltin({
|
|
60499
|
+
name: "convhulln",
|
|
60500
|
+
help: {
|
|
60501
|
+
signatures: [
|
|
60502
|
+
"k = convhulln(P)",
|
|
60503
|
+
"k = convhulln(P,opts)",
|
|
60504
|
+
"[k,vol] = convhulln(___)"
|
|
60505
|
+
],
|
|
60506
|
+
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)."
|
|
60507
|
+
},
|
|
60508
|
+
cases: [
|
|
60509
|
+
{
|
|
60510
|
+
match: (argTypes, nargout) => {
|
|
60511
|
+
if (nargout > 2) return null;
|
|
60512
|
+
if (argTypes.length < 1 || argTypes.length > 2) return null;
|
|
60513
|
+
const x = argTypes[0];
|
|
60514
|
+
if (x.kind !== "tensor" && x.kind !== "number" && x.kind !== "boolean")
|
|
60515
|
+
return null;
|
|
60516
|
+
const k = { kind: "tensor", isComplex: false };
|
|
60517
|
+
return nargout > 1 ? [k, { kind: "number" }] : [k];
|
|
60518
|
+
},
|
|
60519
|
+
apply: (args, nargout) => {
|
|
60520
|
+
const P = args[0];
|
|
60521
|
+
if (!isRuntimeTensor(P))
|
|
60522
|
+
throw new RuntimeError("convhulln: P must be an m-by-n matrix");
|
|
60523
|
+
const [m, n] = tensorSize2D(P);
|
|
60524
|
+
if (n < 2)
|
|
60525
|
+
throw new RuntimeError("convhulln: P must have at least 2 columns");
|
|
60526
|
+
if (n > CONVHULLN_MAX_DIM)
|
|
60527
|
+
throw new RuntimeError(
|
|
60528
|
+
`convhulln: only 2-D and 3-D hulls are supported (got ${n}-D); higher dimensions are not yet validated`
|
|
60529
|
+
);
|
|
60530
|
+
if (m < n + 1)
|
|
60531
|
+
throw new RuntimeError(
|
|
60532
|
+
`convhulln: need at least ${n + 1} points for a ${n}-D hull`
|
|
60533
|
+
);
|
|
60534
|
+
const points = matrixToPoints(P, "convhulln");
|
|
60535
|
+
const facets = convexHullFacets(points, n, "convhulln");
|
|
60536
|
+
const k = facetsToTensor(facets, n);
|
|
60537
|
+
if (nargout > 1) return [k, hullMeasure(points, facets, n)];
|
|
60538
|
+
return k;
|
|
60539
|
+
}
|
|
60540
|
+
}
|
|
60541
|
+
]
|
|
60542
|
+
});
|
|
58788
60543
|
function getQueryValues(v, name) {
|
|
58789
60544
|
if (typeof v === "number") return { data: [v], shape: null };
|
|
58790
60545
|
if (typeof v === "boolean") return { data: [v ? 1 : 0], shape: null };
|
|
@@ -59268,6 +61023,10 @@ var H = {
|
|
|
59268
61023
|
signatures: ["C = class(A)"],
|
|
59269
61024
|
description: "Returns the class name of A as a character vector."
|
|
59270
61025
|
},
|
|
61026
|
+
superclasses: {
|
|
61027
|
+
signatures: ["S = superclasses(ClassName)", "S = superclasses(obj)"],
|
|
61028
|
+
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."
|
|
61029
|
+
},
|
|
59271
61030
|
fieldnames: {
|
|
59272
61031
|
signatures: ["F = fieldnames(S)"],
|
|
59273
61032
|
description: "Returns cell array of field names of struct or object S."
|
|
@@ -59671,6 +61430,14 @@ var H = {
|
|
|
59671
61430
|
signatures: ["B = pinv(A)", "B = pinv(A, TOL)"],
|
|
59672
61431
|
description: "Moore-Penrose pseudoinverse."
|
|
59673
61432
|
},
|
|
61433
|
+
null: {
|
|
61434
|
+
signatures: ["Z = null(A)", "Z = null(A, TOL)"],
|
|
61435
|
+
description: "Orthonormal basis for the null space of A (columns of Z), computed via the SVD. TOL overrides the singular-value tolerance."
|
|
61436
|
+
},
|
|
61437
|
+
bandwidth: {
|
|
61438
|
+
signatures: ["[lower, upper] = bandwidth(A)", "B = bandwidth(A, TYPE)"],
|
|
61439
|
+
description: "Lower and upper matrix bandwidth. TYPE is 'lower' or 'upper'; a single output without TYPE returns the lower bandwidth."
|
|
61440
|
+
},
|
|
59674
61441
|
cond: {
|
|
59675
61442
|
signatures: ["C = cond(A)", "C = cond(A, P)"],
|
|
59676
61443
|
description: "Condition number of matrix."
|
|
@@ -59900,6 +61667,10 @@ var H = {
|
|
|
59900
61667
|
signatures: ["Y = double(X)"],
|
|
59901
61668
|
description: "Convert to double precision."
|
|
59902
61669
|
},
|
|
61670
|
+
single: {
|
|
61671
|
+
signatures: ["Y = single(X)"],
|
|
61672
|
+
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."
|
|
61673
|
+
},
|
|
59903
61674
|
logical: {
|
|
59904
61675
|
signatures: ["Y = logical(X)"],
|
|
59905
61676
|
description: "Convert to logical (boolean) array."
|
|
@@ -60270,6 +62041,18 @@ var H = {
|
|
|
60270
62041
|
],
|
|
60271
62042
|
description: "Extract or create sparse banded/diagonal matrices."
|
|
60272
62043
|
},
|
|
62044
|
+
spparms: {
|
|
62045
|
+
signatures: [
|
|
62046
|
+
"spparms",
|
|
62047
|
+
"values = spparms",
|
|
62048
|
+
"[keys, values] = spparms",
|
|
62049
|
+
"value = spparms(KEY)",
|
|
62050
|
+
"spparms(KEY, VALUE)",
|
|
62051
|
+
"spparms('default')",
|
|
62052
|
+
"spparms(values)"
|
|
62053
|
+
],
|
|
62054
|
+
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."
|
|
62055
|
+
},
|
|
60273
62056
|
// ── Linear algebra extras ─────────────────────────────────────────────
|
|
60274
62057
|
qz: {
|
|
60275
62058
|
signatures: [
|
|
@@ -61071,7 +62854,7 @@ function getSourceLine(getSource, file, line) {
|
|
|
61071
62854
|
}
|
|
61072
62855
|
|
|
61073
62856
|
// src/numbl-core/version.ts
|
|
61074
|
-
var NUMBL_VERSION = "0.4.
|
|
62857
|
+
var NUMBL_VERSION = "0.4.7";
|
|
61075
62858
|
|
|
61076
62859
|
// src/cli-repl.ts
|
|
61077
62860
|
import { createInterface } from "readline";
|
|
@@ -61537,6 +63320,7 @@ function resolveFunctionImpl(name, argTypes, callSite, index2) {
|
|
|
61537
63320
|
for (const argType of argTypes) {
|
|
61538
63321
|
if (argType?.kind === "ClassInstance") {
|
|
61539
63322
|
const className = argType.className;
|
|
63323
|
+
if (index2.classConstructors.get(className) === name) continue;
|
|
61540
63324
|
if (!candidates.includes(className) && (index2.classInstanceMethods.get(className)?.has(name) || index2.classStaticMethods.get(className)?.has(name))) {
|
|
61541
63325
|
candidates.push(className);
|
|
61542
63326
|
}
|
|
@@ -61645,12 +63429,25 @@ var Environment = class _Environment {
|
|
|
61645
63429
|
}
|
|
61646
63430
|
/** Function ID for persistent variable storage */
|
|
61647
63431
|
persistentFuncId;
|
|
63432
|
+
/** Call-site variable names of this frame's arguments, for `inputname`.
|
|
63433
|
+
* Entry i is the name of the variable passed as argument i+1, or '' if
|
|
63434
|
+
* that argument was not a plain variable. Undefined when the call did
|
|
63435
|
+
* not originate from an interpreted call expression (e.g. feval, JIT).
|
|
63436
|
+
* Read directly off the executing frame — the interpreter has only
|
|
63437
|
+
* function-level scoping, so `this.env` is the frame while a body runs. */
|
|
63438
|
+
inputArgNames;
|
|
61648
63439
|
/** Back-reference to the runtime (needed for global/persistent access) */
|
|
61649
63440
|
rt = null;
|
|
61650
63441
|
/** Set when a `@nestedFn` handle has been created that captures this env
|
|
61651
63442
|
* (or an ancestor). Tells the function-exit cleanup that clearing this
|
|
61652
63443
|
* env would strand the handle's closure, so locals must be left alive. */
|
|
61653
63444
|
nestedHandleCreated = false;
|
|
63445
|
+
/** For a nested-function frame: the names of this function's own formal
|
|
63446
|
+
* input/output arguments. These are always local — a write must never be
|
|
63447
|
+
* redirected to a same-named variable in the parent, even before the
|
|
63448
|
+
* output has been assigned. (MATLAB scopes a nested function's formal
|
|
63449
|
+
* arguments to that function; only other variables are shared.) */
|
|
63450
|
+
nestedLocalNames;
|
|
61654
63451
|
get(name) {
|
|
61655
63452
|
if (this._globalNames !== void 0 && this._globalNames.has(name) && this.rt) {
|
|
61656
63453
|
const v = this.rt.$g[name];
|
|
@@ -61669,7 +63466,7 @@ var Environment = class _Environment {
|
|
|
61669
63466
|
if (old !== void 0) decref(this.rt, old);
|
|
61670
63467
|
return;
|
|
61671
63468
|
}
|
|
61672
|
-
if (this.isNested && !this.vars.has(name) && this.parent) {
|
|
63469
|
+
if (this.isNested && !this.vars.has(name) && this.parent && !this.nestedLocalNames?.has(name)) {
|
|
61673
63470
|
const owner = this.findOwner(name);
|
|
61674
63471
|
if (owner) {
|
|
61675
63472
|
owner.setLocal(name, value);
|
|
@@ -62864,6 +64661,7 @@ function makeRootContext(interp, registry3) {
|
|
|
62864
64661
|
var interpreterExec_exports = {};
|
|
62865
64662
|
__export(interpreterExec_exports, {
|
|
62866
64663
|
assignLValue: () => assignLValue,
|
|
64664
|
+
computeInputNames: () => computeInputNames,
|
|
62867
64665
|
evalAnonFunc: () => evalAnonFunc,
|
|
62868
64666
|
evalArgs: () => evalArgs,
|
|
62869
64667
|
evalBinary: () => evalBinary,
|
|
@@ -63166,6 +64964,11 @@ function execStmtInner(stmt) {
|
|
|
63166
64964
|
case "Global": {
|
|
63167
64965
|
for (const name of stmt.names) {
|
|
63168
64966
|
this.env.globalNames.add(name);
|
|
64967
|
+
if (this.rt && !(name in this.rt.$g)) {
|
|
64968
|
+
const empty = RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
64969
|
+
incref(empty);
|
|
64970
|
+
this.rt.$g[name] = empty;
|
|
64971
|
+
}
|
|
63169
64972
|
}
|
|
63170
64973
|
return null;
|
|
63171
64974
|
}
|
|
@@ -63277,6 +65080,10 @@ function evalExprNargout(expr, nargout) {
|
|
|
63277
65080
|
if (isRuntimeStructArray(rv)) {
|
|
63278
65081
|
return rv.elements.length;
|
|
63279
65082
|
}
|
|
65083
|
+
if (isRuntimeClassInstanceArray(rv)) {
|
|
65084
|
+
if (ctx.numIndices === 1) return rv.elements.length;
|
|
65085
|
+
return ctx.dimIndex < rv.shape.length ? rv.shape[ctx.dimIndex] : 1;
|
|
65086
|
+
}
|
|
63280
65087
|
if (isRuntimeSparseMatrix(rv)) {
|
|
63281
65088
|
if (ctx.numIndices === 1) return rv.m * rv.n;
|
|
63282
65089
|
return ctx.dimIndex === 0 ? rv.m : ctx.dimIndex === 1 ? rv.n : 1;
|
|
@@ -63437,6 +65244,23 @@ function evalExprNargout(expr, nargout) {
|
|
|
63437
65244
|
throw new RuntimeError("Interpreter does not yet support meta.class");
|
|
63438
65245
|
}
|
|
63439
65246
|
}
|
|
65247
|
+
function computeInputNames(argExprs, callerEnv) {
|
|
65248
|
+
const names = [];
|
|
65249
|
+
let blanked = false;
|
|
65250
|
+
for (const a of argExprs) {
|
|
65251
|
+
if (blanked) {
|
|
65252
|
+
names.push("");
|
|
65253
|
+
} else if (a.type === "Ident" && callerEnv.has(a.name)) {
|
|
65254
|
+
names.push(a.name);
|
|
65255
|
+
} else if (a.type === "IndexCell" || a.type === "Member" || a.type === "MemberDynamic") {
|
|
65256
|
+
names.push("");
|
|
65257
|
+
blanked = true;
|
|
65258
|
+
} else {
|
|
65259
|
+
names.push("");
|
|
65260
|
+
}
|
|
65261
|
+
}
|
|
65262
|
+
return names;
|
|
65263
|
+
}
|
|
63440
65264
|
function evalArgs(argExprs) {
|
|
63441
65265
|
const args = [];
|
|
63442
65266
|
for (const a of argExprs) {
|
|
@@ -63566,6 +65390,7 @@ function evalFuncCall(expr, nargout) {
|
|
|
63566
65390
|
const c = getConstant(expr.name);
|
|
63567
65391
|
if (c !== void 0) return c;
|
|
63568
65392
|
}
|
|
65393
|
+
this.pendingInputNames = expr.args.length > 0 ? computeInputNames(expr.args, this.env) : void 0;
|
|
63569
65394
|
return this.callFunction(expr.name, args, nargout);
|
|
63570
65395
|
}
|
|
63571
65396
|
function evalMember(expr, nargout) {
|
|
@@ -63745,7 +65570,14 @@ function makeFuncHandle(name) {
|
|
|
63745
65570
|
);
|
|
63746
65571
|
};
|
|
63747
65572
|
fn.jsFnExpectsNargout = true;
|
|
63748
|
-
|
|
65573
|
+
let narg = getIBuiltinNargin(name);
|
|
65574
|
+
if (narg === void 0) {
|
|
65575
|
+
try {
|
|
65576
|
+
narg = this.declaredNargin(name);
|
|
65577
|
+
} catch {
|
|
65578
|
+
narg = void 0;
|
|
65579
|
+
}
|
|
65580
|
+
}
|
|
63749
65581
|
if (narg !== void 0) fn.nargin = narg;
|
|
63750
65582
|
if (isNested) {
|
|
63751
65583
|
fn.releaseExtra = () => capturedEnv.clearLocals();
|
|
@@ -64034,6 +65866,7 @@ __export(interpreterFunctions_exports, {
|
|
|
64034
65866
|
callNestedFunction: () => callNestedFunction,
|
|
64035
65867
|
callUserFunction: () => callUserFunction,
|
|
64036
65868
|
collectClassProperties: () => collectClassProperties,
|
|
65869
|
+
declaredNargin: () => declaredNargin,
|
|
64037
65870
|
evalInLocalScope: () => evalInLocalScope,
|
|
64038
65871
|
findExternalMethod: () => findExternalMethod,
|
|
64039
65872
|
findFunctionInClassFile: () => findFunctionInClassFile,
|
|
@@ -64336,6 +66169,30 @@ register("isa", (ctx, args) => {
|
|
|
64336
66169
|
if (args.length !== 2) return FALL_THROUGH;
|
|
64337
66170
|
return ctx.rt.isa(args[0], args[1]);
|
|
64338
66171
|
});
|
|
66172
|
+
register("superclasses", (ctx, args) => {
|
|
66173
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
66174
|
+
const v = ensureRuntimeValue(args[0]);
|
|
66175
|
+
let className;
|
|
66176
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v)) {
|
|
66177
|
+
className = v.className;
|
|
66178
|
+
} else if (isRuntimeChar(v) || isRuntimeString(v)) {
|
|
66179
|
+
className = toString(v);
|
|
66180
|
+
}
|
|
66181
|
+
const names = [];
|
|
66182
|
+
if (className) {
|
|
66183
|
+
const seen = /* @__PURE__ */ new Set([className]);
|
|
66184
|
+
let current = ctx.rt.getClassParentName(className);
|
|
66185
|
+
while (current && !seen.has(current)) {
|
|
66186
|
+
names.push(current);
|
|
66187
|
+
seen.add(current);
|
|
66188
|
+
current = ctx.rt.getClassParentName(current);
|
|
66189
|
+
}
|
|
66190
|
+
}
|
|
66191
|
+
return RTV.cell(
|
|
66192
|
+
names.map((n) => RTV.string(n)),
|
|
66193
|
+
[names.length, 1]
|
|
66194
|
+
);
|
|
66195
|
+
});
|
|
64339
66196
|
register("__inferred_type_str", (_ctx, args) => {
|
|
64340
66197
|
if (args.length !== 1) return FALL_THROUGH;
|
|
64341
66198
|
const rv = ensureRuntimeValue(args[0]);
|
|
@@ -64360,6 +66217,44 @@ register("nargout", (ctx, args) => {
|
|
|
64360
66217
|
const v = ctx.env.get("$nargout");
|
|
64361
66218
|
return v !== void 0 ? v : 0;
|
|
64362
66219
|
});
|
|
66220
|
+
register("inputname", (ctx, args) => {
|
|
66221
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
66222
|
+
const narginVal = ctx.env.get("$nargin");
|
|
66223
|
+
if (typeof narginVal !== "number") {
|
|
66224
|
+
throw new RuntimeError(
|
|
66225
|
+
"You can only call 'inputname' from within a MATLAB function."
|
|
66226
|
+
);
|
|
66227
|
+
}
|
|
66228
|
+
const k = toNumber(ensureRuntimeValue(args[0]));
|
|
66229
|
+
if (!Number.isInteger(k) || k < 1) {
|
|
66230
|
+
throw new RuntimeError(
|
|
66231
|
+
"Argument number must be a positive integer scalar."
|
|
66232
|
+
);
|
|
66233
|
+
}
|
|
66234
|
+
if (k > narginVal) {
|
|
66235
|
+
throw new RuntimeError(
|
|
66236
|
+
"Argument number exceeds number of function input arguments."
|
|
66237
|
+
);
|
|
66238
|
+
}
|
|
66239
|
+
const names = ctx.env.inputArgNames;
|
|
66240
|
+
const name = names && k <= names.length ? names[k - 1] : "";
|
|
66241
|
+
return RTV.char(name);
|
|
66242
|
+
});
|
|
66243
|
+
register("properties", (ctx, args) => {
|
|
66244
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
66245
|
+
const v = ensureRuntimeValue(args[0]);
|
|
66246
|
+
let names;
|
|
66247
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v)) {
|
|
66248
|
+
names = ctx.classPublicProperties(v.className);
|
|
66249
|
+
} else if (isRuntimeChar(v) || isRuntimeString(v)) {
|
|
66250
|
+
names = ctx.classPublicProperties(toString(v));
|
|
66251
|
+
}
|
|
66252
|
+
if (!names) return RTV.cell([], [0, 1]);
|
|
66253
|
+
return RTV.cell(
|
|
66254
|
+
names.map((n) => RTV.string(n)),
|
|
66255
|
+
[names.length, 1]
|
|
66256
|
+
);
|
|
66257
|
+
});
|
|
64363
66258
|
register("narginchk", (ctx, args) => {
|
|
64364
66259
|
if (args.length !== 2) return FALL_THROUGH;
|
|
64365
66260
|
const narginVal = ctx.env.get("$nargin");
|
|
@@ -64464,10 +66359,14 @@ function callFunction(name, args, nargout) {
|
|
|
64464
66359
|
source: ""
|
|
64465
66360
|
};
|
|
64466
66361
|
return void 0;
|
|
64467
|
-
}
|
|
66362
|
+
},
|
|
66363
|
+
classPublicProperties: (n) => classPublicProperties(this, n)
|
|
64468
66364
|
};
|
|
64469
66365
|
const result = specialHandler(ctx, args, nargout);
|
|
64470
|
-
if (result !== FALL_THROUGH)
|
|
66366
|
+
if (result !== FALL_THROUGH) {
|
|
66367
|
+
this.pendingInputNames = void 0;
|
|
66368
|
+
return result;
|
|
66369
|
+
}
|
|
64471
66370
|
}
|
|
64472
66371
|
const nested = this.env.getNestedFunction(name);
|
|
64473
66372
|
if (nested) {
|
|
@@ -64487,6 +66386,75 @@ function callFunction(name, args, nargout) {
|
|
|
64487
66386
|
}
|
|
64488
66387
|
throw new RuntimeError(`Undefined function or variable '${name}'`);
|
|
64489
66388
|
}
|
|
66389
|
+
function narginFromParams(params) {
|
|
66390
|
+
const hasVarargin = params.length > 0 && params[params.length - 1] === "varargin";
|
|
66391
|
+
return hasVarargin ? -params.length : params.length;
|
|
66392
|
+
}
|
|
66393
|
+
function paramsInFile(interp, fileName, funcName) {
|
|
66394
|
+
const ast = interp.ctx.getCachedAST(fileName);
|
|
66395
|
+
for (const stmt of ast.body) {
|
|
66396
|
+
if (stmt.type === "Function" && stmt.name === funcName) return stmt.params;
|
|
66397
|
+
}
|
|
66398
|
+
return void 0;
|
|
66399
|
+
}
|
|
66400
|
+
function declaredNargin(name) {
|
|
66401
|
+
const nested = this.env.getNestedFunction(name);
|
|
66402
|
+
if (nested) return narginFromParams(nested.fn.params);
|
|
66403
|
+
const callSite = {
|
|
66404
|
+
file: this.currentFile,
|
|
66405
|
+
...this.currentClassName ? { className: this.currentClassName } : {},
|
|
66406
|
+
...this.currentMethodName ? { methodName: this.currentMethodName } : {}
|
|
66407
|
+
};
|
|
66408
|
+
const target = resolveFunction(name, [], callSite, this.functionIndex);
|
|
66409
|
+
if (!target) return void 0;
|
|
66410
|
+
let params;
|
|
66411
|
+
switch (target.kind) {
|
|
66412
|
+
case "localFunction": {
|
|
66413
|
+
const { source } = target;
|
|
66414
|
+
if (source.from === "main") {
|
|
66415
|
+
params = this.mainLocalFunctions.get(target.name)?.params;
|
|
66416
|
+
} else if (source.from === "workspaceFile") {
|
|
66417
|
+
params = this.findFunctionInWorkspaceFile(source.wsName, target.name)?.params ?? void 0;
|
|
66418
|
+
} else if (source.from === "classFile") {
|
|
66419
|
+
params = this.findFunctionInClassFile(
|
|
66420
|
+
source.className,
|
|
66421
|
+
target.name,
|
|
66422
|
+
source.methodScope
|
|
66423
|
+
)?.params ?? void 0;
|
|
66424
|
+
} else if (source.from === "privateFile") {
|
|
66425
|
+
params = paramsInFile(this, source.callerFile, target.name);
|
|
66426
|
+
}
|
|
66427
|
+
break;
|
|
66428
|
+
}
|
|
66429
|
+
case "workspaceFunction": {
|
|
66430
|
+
const dotIdx = target.name.lastIndexOf(".");
|
|
66431
|
+
const primaryName = dotIdx >= 0 ? target.name.slice(dotIdx + 1) : target.name;
|
|
66432
|
+
params = this.findFunctionInWorkspaceFile(target.name, primaryName)?.params ?? void 0;
|
|
66433
|
+
if (params === void 0) {
|
|
66434
|
+
const entry = this.ctx.registry.filesByFuncName.get(target.name);
|
|
66435
|
+
if (entry) {
|
|
66436
|
+
const ast = this.ctx.getCachedAST(entry.fileName);
|
|
66437
|
+
for (const stmt of ast.body) {
|
|
66438
|
+
if (stmt.type === "Function") {
|
|
66439
|
+
params = stmt.params;
|
|
66440
|
+
break;
|
|
66441
|
+
}
|
|
66442
|
+
}
|
|
66443
|
+
}
|
|
66444
|
+
}
|
|
66445
|
+
break;
|
|
66446
|
+
}
|
|
66447
|
+
case "privateFunction": {
|
|
66448
|
+
const entry = this.ctx.getPrivateFileEntry(
|
|
66449
|
+
target.callerFile,
|
|
66450
|
+
target.name
|
|
66451
|
+
);
|
|
66452
|
+
if (entry) params = paramsInFile(this, entry.fileName, target.name);
|
|
66453
|
+
break;
|
|
66454
|
+
}
|
|
66455
|
+
}
|
|
66456
|
+
return params !== void 0 ? narginFromParams(params) : void 0;
|
|
66457
|
+
}
|
|
64490
66458
|
function interpretTarget(target, args, nargout) {
|
|
64491
66459
|
switch (target.kind) {
|
|
64492
66460
|
case "builtin": {
|
|
@@ -64655,18 +66623,12 @@ function interpretWorkspaceFunction(target, args, nargout) {
|
|
|
64655
66623
|
if (entry) {
|
|
64656
66624
|
const ast = this.ctx.getCachedAST(entry.fileName);
|
|
64657
66625
|
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;
|
|
66626
|
+
for (const stmt of ast.body) {
|
|
66627
|
+
if (stmt.type === "Function") continue;
|
|
66628
|
+
const signal = this.execStmt(stmt);
|
|
66629
|
+
if (signal instanceof ReturnSignal) break;
|
|
64669
66630
|
}
|
|
66631
|
+
return this.ans;
|
|
64670
66632
|
});
|
|
64671
66633
|
}
|
|
64672
66634
|
throw new RuntimeError(`Workspace function '${target.name}' not found`);
|
|
@@ -64733,6 +66695,21 @@ function instantiateClass(className, args, nargout) {
|
|
|
64733
66695
|
if (!classInfo) {
|
|
64734
66696
|
return this.rt.callClassMethod(className, className, nargout, args);
|
|
64735
66697
|
}
|
|
66698
|
+
if (classInfo.isOldStyle) {
|
|
66699
|
+
const ctorName = classInfo.constructorName ?? className;
|
|
66700
|
+
const ctorFn = this.findExternalMethod(classInfo, ctorName);
|
|
66701
|
+
if (!ctorFn)
|
|
66702
|
+
throw new RuntimeError(
|
|
66703
|
+
`Constructor for old-style class '${className}' not found`
|
|
66704
|
+
);
|
|
66705
|
+
const fileName = classInfo.externalMethodFiles.get(ctorName)?.fileName ?? classInfo.fileName;
|
|
66706
|
+
return this.withFileContext(
|
|
66707
|
+
fileName,
|
|
66708
|
+
className,
|
|
66709
|
+
ctorName,
|
|
66710
|
+
() => this.callUserFunction(ctorFn, args, nargout)
|
|
66711
|
+
);
|
|
66712
|
+
}
|
|
64736
66713
|
const { propertyNames, propertyDefaults } = this.collectClassProperties(classInfo);
|
|
64737
66714
|
const defaults = /* @__PURE__ */ new Map();
|
|
64738
66715
|
for (const [propName, defaultExpr] of propertyDefaults) {
|
|
@@ -64756,7 +66733,7 @@ function instantiateClass(className, args, nargout) {
|
|
|
64756
66733
|
function interpretConstructor(classInfo, args, nargout) {
|
|
64757
66734
|
const constructorName = classInfo.constructorName;
|
|
64758
66735
|
if (!constructorName) return args[0];
|
|
64759
|
-
for (const member of classInfo.ast
|
|
66736
|
+
for (const member of classInfo.ast?.members ?? []) {
|
|
64760
66737
|
if (member.type !== "Methods") continue;
|
|
64761
66738
|
for (const methodStmt of member.body) {
|
|
64762
66739
|
if (methodStmt.type === "Function" && methodStmt.name === constructorName) {
|
|
@@ -64798,6 +66775,8 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
64798
66775
|
if (!hasVarargoutDecl && nargout > declaredRegularOutputs) {
|
|
64799
66776
|
throw new RuntimeError("Too many output arguments.");
|
|
64800
66777
|
}
|
|
66778
|
+
const callInputNames = this.pendingInputNames;
|
|
66779
|
+
this.pendingInputNames = void 0;
|
|
64801
66780
|
const sharedArgs = args;
|
|
64802
66781
|
if (narginOverride === void 0 && this.registry.size > 0) {
|
|
64803
66782
|
const r = this.registry.dispatchCall(fn, sharedArgs, nargout, this);
|
|
@@ -64831,6 +66810,7 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
64831
66810
|
}
|
|
64832
66811
|
fnEnv.set("$nargin", narginOverride ?? args.length);
|
|
64833
66812
|
fnEnv.set("$nargout", nargout);
|
|
66813
|
+
fnEnv.inputArgNames = callInputNames;
|
|
64834
66814
|
for (const stmt of fn.body) {
|
|
64835
66815
|
if (stmt.type === "Function") {
|
|
64836
66816
|
fnEnv.nestedFunctions.set(stmt.name, {
|
|
@@ -64907,10 +66887,13 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
64907
66887
|
}
|
|
64908
66888
|
}
|
|
64909
66889
|
function callNestedFunction(fn, parentEnv, args, nargout) {
|
|
66890
|
+
const callInputNames = this.pendingInputNames;
|
|
66891
|
+
this.pendingInputNames = void 0;
|
|
64910
66892
|
const fnEnv = new Environment(parentEnv);
|
|
64911
66893
|
fnEnv.isNested = true;
|
|
64912
66894
|
fnEnv.rt = this.rt;
|
|
64913
66895
|
fnEnv.persistentFuncId = `${this.currentFile}:${fn.name}`;
|
|
66896
|
+
fnEnv.nestedLocalNames = /* @__PURE__ */ new Set([...fn.params, ...fn.outputs]);
|
|
64914
66897
|
const hasVarargin = fn.params.length > 0 && fn.params[fn.params.length - 1] === "varargin";
|
|
64915
66898
|
const regularParams = hasVarargin ? fn.params.slice(0, -1) : fn.params;
|
|
64916
66899
|
for (let i = 0; i < regularParams.length; i++) {
|
|
@@ -64924,6 +66907,15 @@ function callNestedFunction(fn, parentEnv, args, nargout) {
|
|
|
64924
66907
|
}
|
|
64925
66908
|
fnEnv.setLocal("$nargin", args.length);
|
|
64926
66909
|
fnEnv.setLocal("$nargout", nargout);
|
|
66910
|
+
fnEnv.inputArgNames = callInputNames;
|
|
66911
|
+
for (const stmt of fn.body) {
|
|
66912
|
+
if (stmt.type === "Function") {
|
|
66913
|
+
fnEnv.nestedFunctions.set(stmt.name, {
|
|
66914
|
+
fn: funcDefFromStmt(stmt),
|
|
66915
|
+
env: fnEnv
|
|
66916
|
+
});
|
|
66917
|
+
}
|
|
66918
|
+
}
|
|
64927
66919
|
const savedEnv = this.env;
|
|
64928
66920
|
this.env = fnEnv;
|
|
64929
66921
|
this.rt.pushCleanupScope();
|
|
@@ -65062,7 +67054,7 @@ function findMethodInClass(classInfo, methodName) {
|
|
|
65062
67054
|
const cacheKey = `method:${classInfo.name}:${methodName}`;
|
|
65063
67055
|
const cached = this.functionDefCache.get(cacheKey);
|
|
65064
67056
|
if (cached) return cached;
|
|
65065
|
-
for (const member of classInfo.ast
|
|
67057
|
+
for (const member of classInfo.ast?.members ?? []) {
|
|
65066
67058
|
if (member.type !== "Methods") continue;
|
|
65067
67059
|
for (const methodStmt of member.body) {
|
|
65068
67060
|
if (methodStmt.type === "Function" && methodStmt.name === methodName) {
|
|
@@ -65119,6 +67111,36 @@ function collectClassProperties(classInfo) {
|
|
|
65119
67111
|
}
|
|
65120
67112
|
return { propertyNames, propertyDefaults };
|
|
65121
67113
|
}
|
|
67114
|
+
function classPublicProperties(interp, className) {
|
|
67115
|
+
let info = interp.ctx.getClassInfo(className);
|
|
67116
|
+
if (!info) return void 0;
|
|
67117
|
+
const out = [];
|
|
67118
|
+
const seen = /* @__PURE__ */ new Set();
|
|
67119
|
+
while (info) {
|
|
67120
|
+
const ast = info.ast;
|
|
67121
|
+
if (ast) {
|
|
67122
|
+
for (const member of ast.members) {
|
|
67123
|
+
if (member.type !== "Properties") continue;
|
|
67124
|
+
const hidden = member.attributes.some((a) => {
|
|
67125
|
+
const n = a.name.toLowerCase();
|
|
67126
|
+
if (n !== "access" && n !== "getaccess") return false;
|
|
67127
|
+
const val = (a.value ?? "").toLowerCase();
|
|
67128
|
+
return val === "private" || val === "protected";
|
|
67129
|
+
});
|
|
67130
|
+
if (hidden) continue;
|
|
67131
|
+
for (const pn of member.names) {
|
|
67132
|
+
if (!seen.has(pn)) {
|
|
67133
|
+
seen.add(pn);
|
|
67134
|
+
out.push(pn);
|
|
67135
|
+
}
|
|
67136
|
+
}
|
|
67137
|
+
}
|
|
67138
|
+
}
|
|
67139
|
+
if (!info.superClass || info.superClass === "handle") break;
|
|
67140
|
+
info = interp.ctx.getClassInfo(info.superClass);
|
|
67141
|
+
}
|
|
67142
|
+
return out;
|
|
67143
|
+
}
|
|
65122
67144
|
function isHandleClass(classInfo) {
|
|
65123
67145
|
let parentName = classInfo.superClass;
|
|
65124
67146
|
while (parentName) {
|
|
@@ -65237,6 +67259,10 @@ var Interpreter = class {
|
|
|
65237
67259
|
workspaceEnv;
|
|
65238
67260
|
/** @internal The caller's environment — for evalin/assignin('caller', ...) */
|
|
65239
67261
|
callerEnv;
|
|
67262
|
+
/** @internal Call-site variable names for the next user-function call, set
|
|
67263
|
+
* by `evalFuncCall` and consumed by `callUserFunction` to support
|
|
67264
|
+
* `inputname`. One-shot: cleared as soon as it is consumed. */
|
|
67265
|
+
pendingInputNames;
|
|
65240
67266
|
/** @internal Stack of [base, dimIndex, numIndices] for resolving `end` keyword in indexing. */
|
|
65241
67267
|
endContextStack = [];
|
|
65242
67268
|
/** @internal Number of enclosing `for` / `while` loop bodies the
|
|
@@ -65498,6 +67524,37 @@ function extractClassInfo(classDef, qualifiedName, fileName, source) {
|
|
|
65498
67524
|
externalMethodFiles: /* @__PURE__ */ new Map()
|
|
65499
67525
|
};
|
|
65500
67526
|
}
|
|
67527
|
+
function makeOldStyleClassInfo(qualifiedName, baseName, constructorFile, methodFiles) {
|
|
67528
|
+
const externalMethodFiles = /* @__PURE__ */ new Map();
|
|
67529
|
+
externalMethodFiles.set(baseName, {
|
|
67530
|
+
fileName: constructorFile.fileName,
|
|
67531
|
+
source: constructorFile.source
|
|
67532
|
+
});
|
|
67533
|
+
const methodNames = /* @__PURE__ */ new Set();
|
|
67534
|
+
for (const mf of methodFiles) {
|
|
67535
|
+
externalMethodFiles.set(mf.name, {
|
|
67536
|
+
fileName: mf.fileName,
|
|
67537
|
+
source: mf.source
|
|
67538
|
+
});
|
|
67539
|
+
methodNames.add(mf.name);
|
|
67540
|
+
}
|
|
67541
|
+
return {
|
|
67542
|
+
name: baseName,
|
|
67543
|
+
qualifiedName,
|
|
67544
|
+
fileName: constructorFile.fileName,
|
|
67545
|
+
source: constructorFile.source,
|
|
67546
|
+
superClass: null,
|
|
67547
|
+
propertyNames: [],
|
|
67548
|
+
propertyDefaults: /* @__PURE__ */ new Map(),
|
|
67549
|
+
methodNames,
|
|
67550
|
+
staticMethodNames: /* @__PURE__ */ new Set(),
|
|
67551
|
+
constructorName: baseName,
|
|
67552
|
+
inferiorClasses: [],
|
|
67553
|
+
ast: null,
|
|
67554
|
+
isOldStyle: true,
|
|
67555
|
+
externalMethodFiles
|
|
67556
|
+
};
|
|
67557
|
+
}
|
|
65501
67558
|
|
|
65502
67559
|
// src/numbl-core/lowering/loweringContext.ts
|
|
65503
67560
|
function createWorkspaceRegistry() {
|
|
@@ -65690,8 +67747,41 @@ var LoweringContext = class _LoweringContext {
|
|
|
65690
67747
|
}
|
|
65691
67748
|
}
|
|
65692
67749
|
}
|
|
67750
|
+
const startsWithClassdef = (source) => {
|
|
67751
|
+
let t = source.trimStart();
|
|
67752
|
+
while (t.startsWith("%")) {
|
|
67753
|
+
const nl = t.indexOf("\n");
|
|
67754
|
+
if (nl < 0) return false;
|
|
67755
|
+
t = t.slice(nl + 1).trimStart();
|
|
67756
|
+
}
|
|
67757
|
+
return t.startsWith("classdef");
|
|
67758
|
+
};
|
|
65693
67759
|
for (const [className, group] of classFolderGroups) {
|
|
65694
|
-
|
|
67760
|
+
const hasRealClassdef = !!group.classDefFile && startsWithClassdef(group.classDefFile.source);
|
|
67761
|
+
if (!hasRealClassdef) {
|
|
67762
|
+
const dotIdx = className.lastIndexOf(".");
|
|
67763
|
+
const baseName = dotIdx >= 0 ? className.slice(dotIdx + 1) : className;
|
|
67764
|
+
const methodBase = (f) => f.name.split("/").pop().replace(/\.m$/, "");
|
|
67765
|
+
const ctorFile = group.classDefFile ?? group.methodFiles.find((f) => methodBase(f) === baseName);
|
|
67766
|
+
if (!ctorFile) {
|
|
67767
|
+
continue;
|
|
67768
|
+
}
|
|
67769
|
+
const methodFiles = group.methodFiles.filter((f) => f !== ctorFile).map((f) => ({
|
|
67770
|
+
name: methodBase(f),
|
|
67771
|
+
fileName: f.name,
|
|
67772
|
+
source: f.source
|
|
67773
|
+
}));
|
|
67774
|
+
if (!this.registry.classesByName.has(className)) {
|
|
67775
|
+
this.registry.classesByName.set(
|
|
67776
|
+
className,
|
|
67777
|
+
makeOldStyleClassInfo(
|
|
67778
|
+
className,
|
|
67779
|
+
baseName,
|
|
67780
|
+
{ fileName: ctorFile.name, source: ctorFile.source },
|
|
67781
|
+
methodFiles
|
|
67782
|
+
)
|
|
67783
|
+
);
|
|
67784
|
+
}
|
|
65695
67785
|
continue;
|
|
65696
67786
|
}
|
|
65697
67787
|
this.registerWorkspaceClass(className, group.classDefFile);
|
|
@@ -65927,7 +68017,7 @@ var LoweringContext = class _LoweringContext {
|
|
|
65927
68017
|
if (!info) return null;
|
|
65928
68018
|
if (info.ctx) return info.ctx;
|
|
65929
68019
|
const ctx = new _LoweringContext(info.source, info.fileName);
|
|
65930
|
-
for (const member of info.ast
|
|
68020
|
+
for (const member of info.ast?.members ?? []) {
|
|
65931
68021
|
if (member.type !== "Methods") continue;
|
|
65932
68022
|
for (const methodStmt of member.body) {
|
|
65933
68023
|
if (methodStmt.type !== "Function") continue;
|
|
@@ -66086,6 +68176,7 @@ var LoweringContext = class _LoweringContext {
|
|
|
66086
68176
|
for (const m of info.methodNames) instanceMethods.add(m);
|
|
66087
68177
|
for (const m of info.staticMethodNames) staticMethods.add(m);
|
|
66088
68178
|
for (const m of info.externalMethodFiles.keys()) {
|
|
68179
|
+
if (info.isOldStyle && m === info.constructorName) continue;
|
|
66089
68180
|
if (!info.staticMethodNames.has(m)) {
|
|
66090
68181
|
instanceMethods.add(m);
|
|
66091
68182
|
}
|
|
@@ -66129,10 +68220,43 @@ var LoweringContext = class _LoweringContext {
|
|
|
66129
68220
|
}
|
|
66130
68221
|
}
|
|
66131
68222
|
const fileImports = /* @__PURE__ */ new Map();
|
|
68223
|
+
const gatherImports = (body, out) => {
|
|
68224
|
+
for (const stmt of body) {
|
|
68225
|
+
switch (stmt.type) {
|
|
68226
|
+
case "Import":
|
|
68227
|
+
out.push(stmt);
|
|
68228
|
+
break;
|
|
68229
|
+
case "Function":
|
|
68230
|
+
case "While":
|
|
68231
|
+
case "For":
|
|
68232
|
+
gatherImports(stmt.body, out);
|
|
68233
|
+
break;
|
|
68234
|
+
case "If":
|
|
68235
|
+
gatherImports(stmt.thenBody, out);
|
|
68236
|
+
for (const b of stmt.elseifBlocks) gatherImports(b.body, out);
|
|
68237
|
+
if (stmt.elseBody) gatherImports(stmt.elseBody, out);
|
|
68238
|
+
break;
|
|
68239
|
+
case "Switch":
|
|
68240
|
+
for (const c of stmt.cases) gatherImports(c.body, out);
|
|
68241
|
+
if (stmt.otherwise) gatherImports(stmt.otherwise, out);
|
|
68242
|
+
break;
|
|
68243
|
+
case "TryCatch":
|
|
68244
|
+
gatherImports(stmt.tryBody, out);
|
|
68245
|
+
gatherImports(stmt.catchBody, out);
|
|
68246
|
+
break;
|
|
68247
|
+
case "ClassDef":
|
|
68248
|
+
for (const member of stmt.members) {
|
|
68249
|
+
if (member.type === "Methods") gatherImports(member.body, out);
|
|
68250
|
+
}
|
|
68251
|
+
break;
|
|
68252
|
+
}
|
|
68253
|
+
}
|
|
68254
|
+
};
|
|
66132
68255
|
const collectImportsFromBody = (body, fileName) => {
|
|
66133
68256
|
const entries = [];
|
|
66134
|
-
|
|
66135
|
-
|
|
68257
|
+
const importStmts = [];
|
|
68258
|
+
gatherImports(body, importStmts);
|
|
68259
|
+
for (const stmt of importStmts) {
|
|
66136
68260
|
if (stmt.wildcard) {
|
|
66137
68261
|
entries.push({ wildcard: true, namespace: stmt.path.join(".") });
|
|
66138
68262
|
} else {
|
|
@@ -66207,6 +68331,10 @@ var LoweringContext = class _LoweringContext {
|
|
|
66207
68331
|
|
|
66208
68332
|
// src/numbl-core/stdlib-bundle.ts
|
|
66209
68333
|
var stdlibFiles = [
|
|
68334
|
+
{
|
|
68335
|
+
name: "TriRep.m",
|
|
68336
|
+
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"
|
|
68337
|
+
},
|
|
66210
68338
|
{
|
|
66211
68339
|
name: "addOptional.m",
|
|
66212
68340
|
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 +68362,10 @@ var stdlibFiles = [
|
|
|
66234
68362
|
{
|
|
66235
68363
|
name: "readmatrix.m",
|
|
66236
68364
|
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"
|
|
68365
|
+
},
|
|
68366
|
+
{
|
|
68367
|
+
name: "triangulation.m",
|
|
68368
|
+
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
68369
|
}
|
|
66238
68370
|
];
|
|
66239
68371
|
var shimFiles = [
|
|
@@ -91810,6 +93942,7 @@ var Workspace = class _Workspace {
|
|
|
91810
93942
|
}
|
|
91811
93943
|
};
|
|
91812
93944
|
for (const [name, info] of this.ctx.registry.classesByName) {
|
|
93945
|
+
if (info.isOldStyle) continue;
|
|
91813
93946
|
registerOrDefer(
|
|
91814
93947
|
name,
|
|
91815
93948
|
() => registerClassDef(
|
|
@@ -91823,7 +93956,7 @@ var Workspace = class _Workspace {
|
|
|
91823
93956
|
if (this.classes.has(name) || this.failedClassValidations.has(name)) {
|
|
91824
93957
|
throw new UnsupportedConstruct(
|
|
91825
93958
|
`class '${name}' is defined both locally and as a workspace class`,
|
|
91826
|
-
info.ast
|
|
93959
|
+
info.ast?.span
|
|
91827
93960
|
);
|
|
91828
93961
|
}
|
|
91829
93962
|
registerOrDefer(name, () => registerClassDef(info.ast, info.fileName));
|
|
@@ -91917,7 +94050,7 @@ var Workspace = class _Workspace {
|
|
|
91917
94050
|
if (!ast) {
|
|
91918
94051
|
throw new UnsupportedConstruct(
|
|
91919
94052
|
`internal: external method file '${mf.fileName}' for '${info.qualifiedName}.${methodName}' was not parsed`,
|
|
91920
|
-
info.ast
|
|
94053
|
+
info.ast?.span
|
|
91921
94054
|
);
|
|
91922
94055
|
}
|
|
91923
94056
|
let primary = null;
|
|
@@ -91933,7 +94066,7 @@ var Workspace = class _Workspace {
|
|
|
91933
94066
|
if (!primary) {
|
|
91934
94067
|
throw new UnsupportedConstruct(
|
|
91935
94068
|
`external method file '${mf.fileName}' has no function`,
|
|
91936
|
-
info.ast
|
|
94069
|
+
info.ast?.span
|
|
91937
94070
|
);
|
|
91938
94071
|
}
|
|
91939
94072
|
out.set(methodName, primary);
|
|
@@ -96365,6 +98498,7 @@ async function load() {
|
|
|
96365
98498
|
const { loadQhull } = await import("qhull-wasm");
|
|
96366
98499
|
const qhull = await loadQhull();
|
|
96367
98500
|
setDelaunayBackend((points, dim) => qhull.delaunay(points, dim).facets);
|
|
98501
|
+
setConvexHullBackend((points, dim) => qhull.convexHull(points, dim).facets);
|
|
96368
98502
|
}
|
|
96369
98503
|
|
|
96370
98504
|
// src/cli.ts
|
|
@@ -96504,6 +98638,7 @@ function findTestFiles(dir) {
|
|
|
96504
98638
|
}
|
|
96505
98639
|
async function runTests(dir, optimization, fastMath) {
|
|
96506
98640
|
loadNativeAddon(fastMath ?? false);
|
|
98641
|
+
await loadQhullBackend();
|
|
96507
98642
|
const absDir = resolve2(process.cwd(), dir);
|
|
96508
98643
|
const testFiles = findTestFiles(absDir);
|
|
96509
98644
|
if (testFiles.length === 0) {
|
|
@@ -96599,6 +98734,8 @@ Options (for build-site):
|
|
|
96599
98734
|
--title <text> Site title (default: from numbl-project.json or dir name)
|
|
96600
98735
|
--entry <file> Default file to open, e.g. main.m (default: README.md or
|
|
96601
98736
|
the first script)
|
|
98737
|
+
--repo-url <url> Source repository URL, shown as a link in the deployed
|
|
98738
|
+
site (default: from numbl-project.json)
|
|
96602
98739
|
|
|
96603
98740
|
Options (for parse):
|
|
96604
98741
|
--dump-ast <file> Write the AST as indented JSON to <file> (default: stdout)
|
|
@@ -97196,6 +99333,7 @@ async function cmdBuildSite(args) {
|
|
|
97196
99333
|
let base;
|
|
97197
99334
|
let title;
|
|
97198
99335
|
let entry;
|
|
99336
|
+
let repoUrl;
|
|
97199
99337
|
const positional = [];
|
|
97200
99338
|
for (let i = 0; i < args.length; i++) {
|
|
97201
99339
|
const a = args[i];
|
|
@@ -97203,6 +99341,7 @@ async function cmdBuildSite(args) {
|
|
|
97203
99341
|
else if (a === "--base") base = args[++i];
|
|
97204
99342
|
else if (a === "--title") title = args[++i];
|
|
97205
99343
|
else if (a === "--entry") entry = args[++i];
|
|
99344
|
+
else if (a === "--repo-url") repoUrl = args[++i];
|
|
97206
99345
|
else if (a.startsWith("-")) {
|
|
97207
99346
|
console.error(`Unknown option: ${a}`);
|
|
97208
99347
|
process.exit(1);
|
|
@@ -97255,6 +99394,7 @@ async function cmdBuildSite(args) {
|
|
|
97255
99394
|
}
|
|
97256
99395
|
if (title !== void 0) manifest.title = title;
|
|
97257
99396
|
if (entry !== void 0) manifest.entry = entry;
|
|
99397
|
+
if (repoUrl !== void 0) manifest.repository = repoUrl;
|
|
97258
99398
|
if (!manifest.title) manifest.title = basename2(projectDirAbs);
|
|
97259
99399
|
const zipEntries = {};
|
|
97260
99400
|
for (const f of collected) {
|
|
@@ -97275,14 +99415,17 @@ async function cmdBuildSite(args) {
|
|
|
97275
99415
|
"warning: project bundle exceeds 50 MB; GitHub Pages may be slow or reject it"
|
|
97276
99416
|
);
|
|
97277
99417
|
}
|
|
99418
|
+
const buildId = createHash2("sha256").update(zip).digest("hex").slice(0, 16);
|
|
97278
99419
|
const indexPath = join7(outDirAbs, "index.html");
|
|
99420
|
+
let injectJs = `window.__NUMBL_BUILD_ID__=${JSON.stringify(buildId)};`;
|
|
97279
99421
|
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);
|
|
99422
|
+
injectJs += `window.__NUMBL_BASE__=${JSON.stringify(normBase)};`;
|
|
97285
99423
|
}
|
|
99424
|
+
const inject = `<script>${injectJs}</script>`;
|
|
99425
|
+
let indexHtml = readFileSync6(indexPath, "utf-8");
|
|
99426
|
+
indexHtml = indexHtml.includes("<!-- numbl:base -->") ? indexHtml.replace("<!-- numbl:base -->", inject) : indexHtml.replace("</head>", ` ${inject}
|
|
99427
|
+
</head>`);
|
|
99428
|
+
writeFileSync4(indexPath, indexHtml);
|
|
97286
99429
|
const redirectTarget = normBase ?? "/";
|
|
97287
99430
|
writeFileSync4(
|
|
97288
99431
|
join7(outDirAbs, "404.html"),
|