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-lib/lib.js
CHANGED
|
@@ -1141,6 +1141,9 @@ var RTV = {
|
|
|
1141
1141
|
}
|
|
1142
1142
|
return new RuntimeClassInstance(className, fields, isHandleClass2);
|
|
1143
1143
|
},
|
|
1144
|
+
classInstanceArray(className, elements, shape) {
|
|
1145
|
+
return new RuntimeClassInstanceArray(className, elements, shape);
|
|
1146
|
+
},
|
|
1144
1147
|
complex(re, im) {
|
|
1145
1148
|
return new RuntimeComplexNumber(re, im);
|
|
1146
1149
|
},
|
|
@@ -18426,6 +18429,24 @@ function lu(data, m, n) {
|
|
|
18426
18429
|
}
|
|
18427
18430
|
function svd(data, m, n, econ, computeUV) {
|
|
18428
18431
|
const k = Math.min(m, n);
|
|
18432
|
+
let finite = true;
|
|
18433
|
+
for (let i = 0; i < data.length; i++) {
|
|
18434
|
+
if (!Number.isFinite(data[i])) {
|
|
18435
|
+
finite = false;
|
|
18436
|
+
break;
|
|
18437
|
+
}
|
|
18438
|
+
}
|
|
18439
|
+
if (!finite) {
|
|
18440
|
+
const sNan = allocFloat64Array(k).fill(NaN);
|
|
18441
|
+
if (!computeUV) return { S: sNan };
|
|
18442
|
+
const uCols2 = econ ? k : m;
|
|
18443
|
+
const vCols2 = econ ? k : n;
|
|
18444
|
+
return {
|
|
18445
|
+
U: allocFloat64Array(m * uCols2).fill(NaN),
|
|
18446
|
+
S: sNan,
|
|
18447
|
+
V: allocFloat64Array(n * vCols2).fill(NaN)
|
|
18448
|
+
};
|
|
18449
|
+
}
|
|
18429
18450
|
const a = allocFloat64Array(data);
|
|
18430
18451
|
const s = allocFloat64Array(k);
|
|
18431
18452
|
const JOBU_A2 = 0;
|
|
@@ -22299,6 +22320,24 @@ function sprintfFormat(fmt, args) {
|
|
|
22299
22320
|
case "t":
|
|
22300
22321
|
result += " ";
|
|
22301
22322
|
break;
|
|
22323
|
+
case "r":
|
|
22324
|
+
result += "\r";
|
|
22325
|
+
break;
|
|
22326
|
+
case "a":
|
|
22327
|
+
result += "\x07";
|
|
22328
|
+
break;
|
|
22329
|
+
case "b":
|
|
22330
|
+
result += "\b";
|
|
22331
|
+
break;
|
|
22332
|
+
case "f":
|
|
22333
|
+
result += "\f";
|
|
22334
|
+
break;
|
|
22335
|
+
case "v":
|
|
22336
|
+
result += "\v";
|
|
22337
|
+
break;
|
|
22338
|
+
case "0":
|
|
22339
|
+
result += "\0";
|
|
22340
|
+
break;
|
|
22302
22341
|
case "\\":
|
|
22303
22342
|
result += "\\";
|
|
22304
22343
|
break;
|
|
@@ -24235,8 +24274,8 @@ function indexIntoScalar(base, indices) {
|
|
|
24235
24274
|
const idx = indices[0];
|
|
24236
24275
|
if (isRuntimeTensor(idx)) {
|
|
24237
24276
|
const is0x0 = idx.shape.length === 2 && idx.shape[0] === 0 && idx.shape[1] === 0;
|
|
24238
|
-
const
|
|
24239
|
-
return RTV.tensor(allocFloat64Array(0),
|
|
24277
|
+
const outShape2 = is0x0 ? [0, 0] : [...idx.shape];
|
|
24278
|
+
return RTV.tensor(allocFloat64Array(0), outShape2);
|
|
24240
24279
|
}
|
|
24241
24280
|
}
|
|
24242
24281
|
if (indices.length === 1) {
|
|
@@ -24266,22 +24305,46 @@ function indexIntoScalar(base, indices) {
|
|
|
24266
24305
|
if (k !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
24267
24306
|
}
|
|
24268
24307
|
const n = idx.data.length;
|
|
24269
|
-
const
|
|
24270
|
-
const
|
|
24271
|
-
|
|
24308
|
+
const scalarRe2 = isRuntimeNumber(base) ? base : base.re;
|
|
24309
|
+
const data2 = allocFloat64Array(n);
|
|
24310
|
+
data2.fill(scalarRe2);
|
|
24272
24311
|
if (isRuntimeComplexNumber(base) && base.im !== 0) {
|
|
24273
24312
|
const im = allocFloat64Array(n);
|
|
24274
24313
|
im.fill(base.im);
|
|
24275
|
-
return RTV.tensor(
|
|
24314
|
+
return RTV.tensor(data2, [...idx.shape], im);
|
|
24276
24315
|
}
|
|
24277
|
-
return RTV.tensor(
|
|
24316
|
+
return RTV.tensor(data2, [...idx.shape]);
|
|
24278
24317
|
}
|
|
24318
|
+
const dimLengths = [];
|
|
24319
|
+
let anyTensor = false;
|
|
24279
24320
|
for (const idx of indices) {
|
|
24280
|
-
if (isColonIndex(idx))
|
|
24281
|
-
|
|
24282
|
-
if (
|
|
24321
|
+
if (isColonIndex(idx)) {
|
|
24322
|
+
dimLengths.push(1);
|
|
24323
|
+
} else if (isRuntimeTensor(idx)) {
|
|
24324
|
+
anyTensor = true;
|
|
24325
|
+
for (let i = 0; i < idx.data.length; i++) {
|
|
24326
|
+
if (Math.round(idx.data[i]) !== 1)
|
|
24327
|
+
throw new RuntimeError("Index exceeds array bounds");
|
|
24328
|
+
}
|
|
24329
|
+
dimLengths.push(idx.data.length);
|
|
24330
|
+
} else {
|
|
24331
|
+
if (Math.round(toNumber(idx)) !== 1)
|
|
24332
|
+
throw new RuntimeError("Index exceeds array bounds");
|
|
24333
|
+
dimLengths.push(1);
|
|
24334
|
+
}
|
|
24283
24335
|
}
|
|
24284
|
-
return base;
|
|
24336
|
+
if (!anyTensor) return base;
|
|
24337
|
+
const total = dimLengths.reduce((a, b) => a * b, 1);
|
|
24338
|
+
const scalarRe = isRuntimeNumber(base) ? base : base.re;
|
|
24339
|
+
const data = allocFloat64Array(total);
|
|
24340
|
+
data.fill(scalarRe);
|
|
24341
|
+
const outShape = dimLengths.length >= 2 ? dimLengths : [dimLengths[0], 1];
|
|
24342
|
+
if (isRuntimeComplexNumber(base) && base.im !== 0) {
|
|
24343
|
+
const im = allocFloat64Array(total);
|
|
24344
|
+
im.fill(base.im);
|
|
24345
|
+
return RTV.tensor(data, outShape, im);
|
|
24346
|
+
}
|
|
24347
|
+
return RTV.tensor(data, outShape);
|
|
24285
24348
|
}
|
|
24286
24349
|
function indexIntoTensor(base, indices) {
|
|
24287
24350
|
if (indices.length === 1) {
|
|
@@ -24316,11 +24379,13 @@ function indexIntoTensor(base, indices) {
|
|
|
24316
24379
|
function indexIntoTensor1D(base, idx) {
|
|
24317
24380
|
if (isColonIndex(idx)) {
|
|
24318
24381
|
const imag2 = base.imag ? allocFloat64Array(base.imag) : void 0;
|
|
24319
|
-
|
|
24382
|
+
const result = RTV.tensor(
|
|
24320
24383
|
allocFloat64Array(base.data),
|
|
24321
24384
|
[base.data.length, 1],
|
|
24322
24385
|
imag2
|
|
24323
24386
|
);
|
|
24387
|
+
if (base._isLogical === true) result._isLogical = true;
|
|
24388
|
+
return result;
|
|
24324
24389
|
}
|
|
24325
24390
|
if (isRuntimeLogical(idx)) {
|
|
24326
24391
|
if (!idx) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
@@ -24518,6 +24583,17 @@ function indexIntoChar(base, indices) {
|
|
|
24518
24583
|
if (indices.length === 1) {
|
|
24519
24584
|
const idx = indices[0];
|
|
24520
24585
|
if (isColonIndex(idx)) return base;
|
|
24586
|
+
if (isRuntimeTensor(idx) && idx._isLogical) {
|
|
24587
|
+
let result = "";
|
|
24588
|
+
for (let k = 0; k < idx.data.length; k++) {
|
|
24589
|
+
if (idx.data[k] !== 0) {
|
|
24590
|
+
if (k >= base.value.length)
|
|
24591
|
+
throw new RuntimeError("Index exceeds char array length");
|
|
24592
|
+
result += base.value[k];
|
|
24593
|
+
}
|
|
24594
|
+
}
|
|
24595
|
+
return RTV.char(result);
|
|
24596
|
+
}
|
|
24521
24597
|
if (isRuntimeTensor(idx)) {
|
|
24522
24598
|
let result = "";
|
|
24523
24599
|
for (let k = 0; k < idx.data.length; k++) {
|
|
@@ -24536,22 +24612,19 @@ function indexIntoChar(base, indices) {
|
|
|
24536
24612
|
if (indices.length === 2) {
|
|
24537
24613
|
const rowIdx = indices[0];
|
|
24538
24614
|
const colIdx = indices[1];
|
|
24539
|
-
|
|
24540
|
-
|
|
24541
|
-
|
|
24542
|
-
|
|
24543
|
-
|
|
24544
|
-
|
|
24545
|
-
|
|
24546
|
-
|
|
24547
|
-
|
|
24548
|
-
|
|
24549
|
-
|
|
24550
|
-
|
|
24551
|
-
|
|
24552
|
-
} else {
|
|
24553
|
-
cols = [Math.round(toNumber(colIdx)) - 1];
|
|
24554
|
-
}
|
|
24615
|
+
const toPositions = (idx) => {
|
|
24616
|
+
if (isRuntimeTensor(idx) && idx._isLogical) {
|
|
24617
|
+
const out = [];
|
|
24618
|
+
for (let i = 0; i < idx.data.length; i++)
|
|
24619
|
+
if (idx.data[i] !== 0) out.push(i);
|
|
24620
|
+
return out;
|
|
24621
|
+
}
|
|
24622
|
+
if (isRuntimeTensor(idx))
|
|
24623
|
+
return Array.from(idx.data, (v) => Math.round(v) - 1);
|
|
24624
|
+
return [Math.round(toNumber(idx)) - 1];
|
|
24625
|
+
};
|
|
24626
|
+
const rows = isColonIndex(rowIdx) ? Array.from({ length: nRows }, (_, i) => i) : toPositions(rowIdx);
|
|
24627
|
+
const cols = isColonIndex(colIdx) ? Array.from({ length: nCols }, (_, i) => i) : toPositions(colIdx);
|
|
24555
24628
|
let result = "";
|
|
24556
24629
|
for (const r of rows) {
|
|
24557
24630
|
for (const c of cols) {
|
|
@@ -24577,11 +24650,11 @@ function indexIntoLogical(base, indices) {
|
|
|
24577
24650
|
const vi = Math.round(idx.data[i2]);
|
|
24578
24651
|
if (vi !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
24579
24652
|
}
|
|
24580
|
-
const
|
|
24581
|
-
|
|
24582
|
-
const
|
|
24583
|
-
|
|
24584
|
-
return
|
|
24653
|
+
const data2 = allocFloat64Array(idx.data.length);
|
|
24654
|
+
data2.fill(base ? 1 : 0);
|
|
24655
|
+
const result2 = RTV.tensor(data2, [...idx.shape]);
|
|
24656
|
+
result2._isLogical = true;
|
|
24657
|
+
return result2;
|
|
24585
24658
|
}
|
|
24586
24659
|
if (isRuntimeLogical(idx)) {
|
|
24587
24660
|
if (!idx) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
@@ -24591,16 +24664,35 @@ function indexIntoLogical(base, indices) {
|
|
|
24591
24664
|
if (i !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
24592
24665
|
return base;
|
|
24593
24666
|
}
|
|
24667
|
+
const dimLengths = [];
|
|
24668
|
+
let anyTensor = false;
|
|
24594
24669
|
for (const idx of indices) {
|
|
24595
|
-
if (isColonIndex(idx))
|
|
24596
|
-
|
|
24670
|
+
if (isColonIndex(idx)) {
|
|
24671
|
+
dimLengths.push(1);
|
|
24672
|
+
} else if (isRuntimeLogical(idx)) {
|
|
24597
24673
|
if (!idx) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
24598
|
-
|
|
24674
|
+
dimLengths.push(1);
|
|
24675
|
+
} else if (isRuntimeTensor(idx)) {
|
|
24676
|
+
anyTensor = true;
|
|
24677
|
+
for (let i = 0; i < idx.data.length; i++) {
|
|
24678
|
+
if (Math.round(idx.data[i]) !== 1)
|
|
24679
|
+
throw new RuntimeError("Index exceeds array bounds");
|
|
24680
|
+
}
|
|
24681
|
+
dimLengths.push(idx.data.length);
|
|
24682
|
+
} else {
|
|
24683
|
+
if (Math.round(toNumber(idx)) !== 1)
|
|
24684
|
+
throw new RuntimeError("Index exceeds array bounds");
|
|
24685
|
+
dimLengths.push(1);
|
|
24599
24686
|
}
|
|
24600
|
-
const i = Math.round(toNumber(idx));
|
|
24601
|
-
if (i !== 1) throw new RuntimeError("Index exceeds array bounds");
|
|
24602
24687
|
}
|
|
24603
|
-
return base;
|
|
24688
|
+
if (!anyTensor) return base;
|
|
24689
|
+
const total = dimLengths.reduce((a, b) => a * b, 1);
|
|
24690
|
+
const data = allocFloat64Array(total);
|
|
24691
|
+
data.fill(base ? 1 : 0);
|
|
24692
|
+
const outShape = dimLengths.length >= 2 ? dimLengths : [dimLengths[0], 1];
|
|
24693
|
+
const result = RTV.tensor(data, outShape);
|
|
24694
|
+
result._isLogical = true;
|
|
24695
|
+
return result;
|
|
24604
24696
|
}
|
|
24605
24697
|
function indexIntoTensorWithTensor(base, idx) {
|
|
24606
24698
|
const baseLogical = base._isLogical === true;
|
|
@@ -24680,11 +24772,15 @@ function indexIntoRTValue(base, indices) {
|
|
|
24680
24772
|
return indexIntoLogical(base, indices);
|
|
24681
24773
|
}
|
|
24682
24774
|
if (isRuntimeStruct(base) || isRuntimeClassInstance(base)) {
|
|
24683
|
-
|
|
24684
|
-
|
|
24685
|
-
if (
|
|
24686
|
-
|
|
24687
|
-
|
|
24775
|
+
const allOnes = indices.length >= 1 && indices.every((idx) => {
|
|
24776
|
+
if (isRuntimeNumber(idx)) return Math.round(idx) === 1;
|
|
24777
|
+
if (isRuntimeLogical(idx)) return idx === true;
|
|
24778
|
+
if (isRuntimeTensor(idx))
|
|
24779
|
+
return idx.data.length === 1 && Math.round(idx.data[0]) === 1;
|
|
24780
|
+
return false;
|
|
24781
|
+
});
|
|
24782
|
+
if (allOnes) return base;
|
|
24783
|
+
throw new RuntimeError("Index exceeds struct dimensions");
|
|
24688
24784
|
}
|
|
24689
24785
|
if (isRuntimeSparseMatrix(base)) {
|
|
24690
24786
|
return indexIntoSparse(base, indices);
|
|
@@ -24734,7 +24830,13 @@ function storeIntoTensor(base, indices, rhs, _rt) {
|
|
|
24734
24830
|
}
|
|
24735
24831
|
if (isShared(base)) {
|
|
24736
24832
|
const cowImag = base.imag ? allocFloat64Array(base.imag) : void 0;
|
|
24737
|
-
|
|
24833
|
+
const copy = RTV.tensor(
|
|
24834
|
+
allocFloat64Array(base.data),
|
|
24835
|
+
[...base.shape],
|
|
24836
|
+
cowImag
|
|
24837
|
+
);
|
|
24838
|
+
copy._isLogical = base._isLogical;
|
|
24839
|
+
base = copy;
|
|
24738
24840
|
}
|
|
24739
24841
|
if (indices.length === 1) {
|
|
24740
24842
|
return storeIntoTensor1D(base, indices[0], rhs);
|
|
@@ -24762,7 +24864,9 @@ function deleteTensorElements(base, idx) {
|
|
|
24762
24864
|
toDelete.add(Math.round(idx.data[i]) - 1);
|
|
24763
24865
|
}
|
|
24764
24866
|
} else if (isColonIndex(idx)) {
|
|
24765
|
-
|
|
24867
|
+
const empty = RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
24868
|
+
empty._isLogical = base._isLogical;
|
|
24869
|
+
return empty;
|
|
24766
24870
|
}
|
|
24767
24871
|
if (toDelete.size === 0) return base;
|
|
24768
24872
|
const newData = [];
|
|
@@ -24777,7 +24881,9 @@ function deleteTensorElements(base, idx) {
|
|
|
24777
24881
|
const baseIsColVec = base.shape.length >= 2 && base.shape[1] === 1 && base.shape[0] !== 1;
|
|
24778
24882
|
const outShape = baseIsColVec ? [newData.length, 1] : [1, newData.length];
|
|
24779
24883
|
const imOut = hasImag && newIm.some((x) => x !== 0) ? allocFloat64Array(newIm) : void 0;
|
|
24780
|
-
|
|
24884
|
+
const result = RTV.tensor(allocFloat64Array(newData), outShape, imOut);
|
|
24885
|
+
result._isLogical = base._isLogical;
|
|
24886
|
+
return result;
|
|
24781
24887
|
}
|
|
24782
24888
|
function collectDelIndices(idx, dimLen) {
|
|
24783
24889
|
const s = /* @__PURE__ */ new Set();
|
|
@@ -24817,7 +24923,9 @@ function deleteTensorRowsOrCols(base, indices) {
|
|
|
24817
24923
|
if (newIm && base.imag) newIm[dstIdx] = base.imag[srcIdx];
|
|
24818
24924
|
}
|
|
24819
24925
|
}
|
|
24820
|
-
|
|
24926
|
+
const result = RTV.tensor(newData, [newNrows, ncols], newIm);
|
|
24927
|
+
result._isLogical = base._isLogical;
|
|
24928
|
+
return result;
|
|
24821
24929
|
}
|
|
24822
24930
|
if (isColonIndex(indices[0])) {
|
|
24823
24931
|
const delCols = collectDelIndices(indices[1], ncols);
|
|
@@ -24836,7 +24944,9 @@ function deleteTensorRowsOrCols(base, indices) {
|
|
|
24836
24944
|
if (newIm && base.imag) newIm[dstIdx] = base.imag[srcIdx];
|
|
24837
24945
|
}
|
|
24838
24946
|
}
|
|
24839
|
-
|
|
24947
|
+
const result = RTV.tensor(newData, [nrows, newNcols], newIm);
|
|
24948
|
+
result._isLogical = base._isLogical;
|
|
24949
|
+
return result;
|
|
24840
24950
|
}
|
|
24841
24951
|
throw new RuntimeError("Cannot delete from both row and column dimensions");
|
|
24842
24952
|
}
|
|
@@ -24906,6 +25016,9 @@ function storeIntoTensor1D(base, idx, rhs) {
|
|
|
24906
25016
|
}
|
|
24907
25017
|
function storeIntoTensorByVector(base, idx, rhs) {
|
|
24908
25018
|
if (idx._isLogical) {
|
|
25019
|
+
if (isRuntimeTensor(rhs) && rhs.data.length === 1) {
|
|
25020
|
+
rhs = rhs.imag && rhs.imag[0] !== 0 ? RTV.complex(rhs.data[0], rhs.imag[0]) : RTV.num(rhs.data[0]);
|
|
25021
|
+
}
|
|
24909
25022
|
const { re: rhsRe, im: rhsIm } = isRuntimeTensor(rhs) ? { re: null, im: null } : toReIm(rhs);
|
|
24910
25023
|
let maxTruthy = -1;
|
|
24911
25024
|
for (let i = 0; i < idx.data.length; i++) {
|
|
@@ -25155,7 +25268,8 @@ function storeIntoTensorND(base, indices, rhs) {
|
|
|
25155
25268
|
const dimIndices = indices.map((idx, dim) => {
|
|
25156
25269
|
const dimSize = dim < shape.length ? shape[dim] : 1;
|
|
25157
25270
|
if (isColonIndex(idx)) {
|
|
25158
|
-
|
|
25271
|
+
const dimSizeUnknown = dimSize === 0 || dim >= shape.length;
|
|
25272
|
+
if (dimSizeUnknown && rhsShape) {
|
|
25159
25273
|
const rDim = rhsDimCursor < rhsShape.length ? rhsShape[rhsDimCursor] : 1;
|
|
25160
25274
|
rhsDimCursor++;
|
|
25161
25275
|
return Array.from({ length: rDim }, (_, i) => i);
|
|
@@ -25472,6 +25586,9 @@ function horzcat(...values) {
|
|
|
25472
25586
|
if (values.some((v) => isRuntimeSparseMatrix(v))) {
|
|
25473
25587
|
return sparseCatAlongDim(values, 1);
|
|
25474
25588
|
}
|
|
25589
|
+
if (values.some((v) => isRuntimeCell(v))) {
|
|
25590
|
+
return cellCatAlongDim(values, 1);
|
|
25591
|
+
}
|
|
25475
25592
|
if (values.some((v) => isRuntimeChar(v))) {
|
|
25476
25593
|
let result = "";
|
|
25477
25594
|
for (const v of values) {
|
|
@@ -25492,9 +25609,6 @@ function horzcat(...values) {
|
|
|
25492
25609
|
}
|
|
25493
25610
|
return RTV.string(result);
|
|
25494
25611
|
}
|
|
25495
|
-
if (values.some((v) => isRuntimeCell(v))) {
|
|
25496
|
-
return cellCatAlongDim(values, 1);
|
|
25497
|
-
}
|
|
25498
25612
|
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
25499
25613
|
return structCat(values);
|
|
25500
25614
|
}
|
|
@@ -25506,12 +25620,12 @@ function vertcat(...values) {
|
|
|
25506
25620
|
if (values.some((v) => isRuntimeSparseMatrix(v))) {
|
|
25507
25621
|
return sparseCatAlongDim(values, 0);
|
|
25508
25622
|
}
|
|
25509
|
-
if (values.some((v) => isRuntimeChar(v))) {
|
|
25510
|
-
return vertcatChars(values);
|
|
25511
|
-
}
|
|
25512
25623
|
if (values.some((v) => isRuntimeCell(v))) {
|
|
25513
25624
|
return cellCatAlongDim(values, 0);
|
|
25514
25625
|
}
|
|
25626
|
+
if (values.some((v) => isRuntimeChar(v))) {
|
|
25627
|
+
return vertcatChars(values);
|
|
25628
|
+
}
|
|
25515
25629
|
if (values.some((v) => isRuntimeStruct(v) || isRuntimeStructArray(v))) {
|
|
25516
25630
|
return structCat(values);
|
|
25517
25631
|
}
|
|
@@ -25857,11 +25971,22 @@ function catAlongDim(values, dimIdx) {
|
|
|
25857
25971
|
if (allLogical) result._isLogical = true;
|
|
25858
25972
|
return result;
|
|
25859
25973
|
}
|
|
25974
|
+
function isEmptyNonCellOperand(v) {
|
|
25975
|
+
if (isRuntimeChar(v)) return v.value.length === 0;
|
|
25976
|
+
if (isRuntimeTensor(v)) return v.data.length === 0;
|
|
25977
|
+
return false;
|
|
25978
|
+
}
|
|
25860
25979
|
function cellCatAlongDim(values, dimIdx) {
|
|
25861
|
-
let cells =
|
|
25862
|
-
|
|
25863
|
-
|
|
25864
|
-
|
|
25980
|
+
let cells = [];
|
|
25981
|
+
for (const v of values) {
|
|
25982
|
+
if (isRuntimeCell(v)) {
|
|
25983
|
+
cells.push(v);
|
|
25984
|
+
} else if (isEmptyNonCellOperand(v)) {
|
|
25985
|
+
continue;
|
|
25986
|
+
} else {
|
|
25987
|
+
cells.push(RTV.cell([v], [1, 1]));
|
|
25988
|
+
}
|
|
25989
|
+
}
|
|
25865
25990
|
cells = cells.filter((c) => c.data.length > 0);
|
|
25866
25991
|
if (cells.length === 0) return RTV.cell([], [0, 0]);
|
|
25867
25992
|
if (cells.length === 1) return cells[0];
|
|
@@ -29760,7 +29885,7 @@ var ExpressionParser = class extends ParserBase {
|
|
|
29760
29885
|
}
|
|
29761
29886
|
} else if (expr.type === "Ident" && this.peekToken() === 41 /* At */ && this.peekTokenAt(1) === 4 /* Ident */) {
|
|
29762
29887
|
this.pos++;
|
|
29763
|
-
const className = this.
|
|
29888
|
+
const className = this.parseQualifiedName();
|
|
29764
29889
|
if (!this.consume(50 /* LParen */)) {
|
|
29765
29890
|
throw this.error("expected '(' after superclass name in super call");
|
|
29766
29891
|
}
|
|
@@ -30361,7 +30486,10 @@ var ControlFlowParser = class extends CommandParser {
|
|
|
30361
30486
|
let catchBody = [];
|
|
30362
30487
|
if (this.consume(27 /* Catch */)) {
|
|
30363
30488
|
if (this.peekToken() === 4 /* Ident */) {
|
|
30364
|
-
|
|
30489
|
+
const after = this.peekTokenAt(1);
|
|
30490
|
+
if (after === void 0 || after === 68 /* Newline */ || after === 49 /* Semicolon */ || after === 47 /* Comma */ || after === 15 /* End */) {
|
|
30491
|
+
catchVar = this.expectIdent();
|
|
30492
|
+
}
|
|
30365
30493
|
}
|
|
30366
30494
|
catchBody = this.parseBlock((t) => t === 15 /* End */);
|
|
30367
30495
|
}
|
|
@@ -30486,8 +30614,12 @@ var ArgumentsParser = class extends ControlFlowParser {
|
|
|
30486
30614
|
dimensions = this.parseArgDimensions();
|
|
30487
30615
|
}
|
|
30488
30616
|
let className = null;
|
|
30489
|
-
if (this.peekToken() === 4 /* Ident */
|
|
30617
|
+
if (this.peekToken() === 4 /* Ident */) {
|
|
30490
30618
|
className = this.next().lexeme;
|
|
30619
|
+
while (this.peekToken() === 45 /* Dot */) {
|
|
30620
|
+
this.consume(45 /* Dot */);
|
|
30621
|
+
className += "." + this.expectIdent();
|
|
30622
|
+
}
|
|
30491
30623
|
}
|
|
30492
30624
|
let validators = [];
|
|
30493
30625
|
if (this.peekToken() === 54 /* LBrace */) {
|
|
@@ -30523,18 +30655,28 @@ var ArgumentsParser = class extends ControlFlowParser {
|
|
|
30523
30655
|
return dims;
|
|
30524
30656
|
}
|
|
30525
30657
|
/**
|
|
30526
|
-
* Parse validator list: {mustBeNumeric, mustBePositive}
|
|
30658
|
+
* Parse validator list: {mustBeNumeric, mustBePositive}. Validators may be
|
|
30659
|
+
* full function calls with arguments, e.g.
|
|
30660
|
+
* `{mustBeMember(x,["a","b"]), mustBeInRange(x,0,7)}`. The validator bodies
|
|
30661
|
+
* are not enforced at runtime, so we capture the top-level validator name
|
|
30662
|
+
* tokens and skip past any nested `(...)`, `[...]`, `{...}` so parsing
|
|
30663
|
+
* resumes correctly at the default value (`= expr`) or end of line.
|
|
30527
30664
|
*/
|
|
30528
30665
|
parseArgValidators() {
|
|
30529
30666
|
this.consume(54 /* LBrace */);
|
|
30530
30667
|
const validators = [];
|
|
30531
|
-
|
|
30532
|
-
|
|
30533
|
-
|
|
30534
|
-
|
|
30535
|
-
|
|
30536
|
-
|
|
30668
|
+
let depth = 0;
|
|
30669
|
+
while (this.peekToken() !== void 0) {
|
|
30670
|
+
const tok = this.peekToken();
|
|
30671
|
+
if (depth === 0 && tok === 55 /* RBrace */) break;
|
|
30672
|
+
if (tok === 50 /* LParen */ || tok === 52 /* LBracket */ || tok === 54 /* LBrace */) {
|
|
30673
|
+
depth++;
|
|
30674
|
+
} else if (tok === 51 /* RParen */ || tok === 53 /* RBracket */ || tok === 55 /* RBrace */) {
|
|
30675
|
+
depth--;
|
|
30676
|
+
} else if (depth === 0 && tok === 4 /* Ident */) {
|
|
30677
|
+
validators.push(this.peek().lexeme);
|
|
30537
30678
|
}
|
|
30679
|
+
this.next();
|
|
30538
30680
|
}
|
|
30539
30681
|
this.consume(55 /* RBrace */);
|
|
30540
30682
|
return validators;
|
|
@@ -30565,7 +30707,8 @@ var FunctionParser = class extends ArgumentsParser {
|
|
|
30565
30707
|
if (this.consume(52 /* LBracket */)) {
|
|
30566
30708
|
if (this.peekToken() !== 53 /* RBracket */) {
|
|
30567
30709
|
outputs.push(this.expectIdentOrTilde());
|
|
30568
|
-
while (this.
|
|
30710
|
+
while (this.peekToken() === 47 /* Comma */ || this.peekToken() === 4 /* Ident */ || this.peekToken() === 40 /* Tilde */) {
|
|
30711
|
+
this.consume(47 /* Comma */);
|
|
30569
30712
|
outputs.push(this.expectIdentOrTilde());
|
|
30570
30713
|
}
|
|
30571
30714
|
}
|
|
@@ -30673,6 +30816,14 @@ var FunctionParser = class extends ArgumentsParser {
|
|
|
30673
30816
|
};
|
|
30674
30817
|
|
|
30675
30818
|
// src/numbl-core/parser/ClassParser.ts
|
|
30819
|
+
var HANDLE_BASE_CLASSES = /* @__PURE__ */ new Set([
|
|
30820
|
+
"handle",
|
|
30821
|
+
"dynamicprops",
|
|
30822
|
+
"matlab.mixin.Copyable",
|
|
30823
|
+
"matlab.mixin.SetGet",
|
|
30824
|
+
"matlab.mixin.SetGetExactNames",
|
|
30825
|
+
"hgsetget"
|
|
30826
|
+
]);
|
|
30676
30827
|
var ClassParser = class extends FunctionParser {
|
|
30677
30828
|
// ── Imports & ClassDef ───────────────────────────────────────────────
|
|
30678
30829
|
parseImport() {
|
|
@@ -30707,7 +30858,11 @@ var ClassParser = class extends FunctionParser {
|
|
|
30707
30858
|
const name = this.parseQualifiedName();
|
|
30708
30859
|
let superClass = null;
|
|
30709
30860
|
if (this.consume(43 /* Less */)) {
|
|
30710
|
-
|
|
30861
|
+
const supers = [this.parseQualifiedName()];
|
|
30862
|
+
while (this.consume(38 /* And */)) {
|
|
30863
|
+
supers.push(this.parseQualifiedName());
|
|
30864
|
+
}
|
|
30865
|
+
superClass = supers.some((s) => HANDLE_BASE_CLASSES.has(s)) ? "handle" : supers[0];
|
|
30711
30866
|
}
|
|
30712
30867
|
const members = [];
|
|
30713
30868
|
while (true) {
|
|
@@ -31582,7 +31737,7 @@ function insertFunctionEndTokens(tokens) {
|
|
|
31582
31737
|
}
|
|
31583
31738
|
if (BLOCK_OPENERS.has(tok.token)) {
|
|
31584
31739
|
depth++;
|
|
31585
|
-
} else if (tok.token === 15 /* End */ && groupDepth === 0) {
|
|
31740
|
+
} else if (tok.token === 15 /* End */ && groupDepth === 0 && tokens[i - 1]?.token !== 45 /* Dot */) {
|
|
31586
31741
|
depth--;
|
|
31587
31742
|
if (depth === 0 && inFunction) {
|
|
31588
31743
|
inFunction = false;
|
|
@@ -34294,6 +34449,8 @@ defineBuiltin({
|
|
|
34294
34449
|
if (isRuntimeComplexNumber(v)) return v.im === 0;
|
|
34295
34450
|
if (isRuntimeTensor(v)) return imagAllZero(v.imag);
|
|
34296
34451
|
if (isRuntimeSparseMatrix(v)) return !v.pi || imagAllZero(v.pi);
|
|
34452
|
+
if (isRuntimeCell(v) || isRuntimeStruct(v) || isRuntimeStructArray(v) || isRuntimeString(v) || isRuntimeFunction(v))
|
|
34453
|
+
return false;
|
|
34297
34454
|
return true;
|
|
34298
34455
|
}
|
|
34299
34456
|
}
|
|
@@ -34765,10 +34922,79 @@ defineBuiltin({
|
|
|
34765
34922
|
name: "ischar",
|
|
34766
34923
|
cases: [anyToLogicalCase((args) => isRuntimeChar(args[0]))]
|
|
34767
34924
|
});
|
|
34925
|
+
defineBuiltin({
|
|
34926
|
+
name: "isstr",
|
|
34927
|
+
cases: [anyToLogicalCase((args) => isRuntimeChar(args[0]))]
|
|
34928
|
+
});
|
|
34768
34929
|
defineBuiltin({
|
|
34769
34930
|
name: "isstring",
|
|
34770
34931
|
cases: [anyToLogicalCase((args) => isRuntimeString(args[0]))]
|
|
34771
34932
|
});
|
|
34933
|
+
var MATLAB_KEYWORDS = /* @__PURE__ */ new Set([
|
|
34934
|
+
"break",
|
|
34935
|
+
"case",
|
|
34936
|
+
"catch",
|
|
34937
|
+
"classdef",
|
|
34938
|
+
"continue",
|
|
34939
|
+
"else",
|
|
34940
|
+
"elseif",
|
|
34941
|
+
"end",
|
|
34942
|
+
"for",
|
|
34943
|
+
"function",
|
|
34944
|
+
"global",
|
|
34945
|
+
"if",
|
|
34946
|
+
"otherwise",
|
|
34947
|
+
"parfor",
|
|
34948
|
+
"persistent",
|
|
34949
|
+
"return",
|
|
34950
|
+
"spmd",
|
|
34951
|
+
"switch",
|
|
34952
|
+
"try",
|
|
34953
|
+
"while"
|
|
34954
|
+
]);
|
|
34955
|
+
function singleRowText(v) {
|
|
34956
|
+
if (isRuntimeChar(v)) {
|
|
34957
|
+
if (v.shape && v.shape.length >= 1 && v.shape[0] > 1) return null;
|
|
34958
|
+
return v.value;
|
|
34959
|
+
}
|
|
34960
|
+
if (isRuntimeString(v)) return v;
|
|
34961
|
+
return null;
|
|
34962
|
+
}
|
|
34963
|
+
defineBuiltin({
|
|
34964
|
+
name: "isvarname",
|
|
34965
|
+
cases: [
|
|
34966
|
+
anyToLogicalCase((args) => {
|
|
34967
|
+
const s = singleRowText(args[0]);
|
|
34968
|
+
if (s === null || s.length === 0 || s.length > 63) return false;
|
|
34969
|
+
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(s)) return false;
|
|
34970
|
+
return !MATLAB_KEYWORDS.has(s);
|
|
34971
|
+
})
|
|
34972
|
+
]
|
|
34973
|
+
});
|
|
34974
|
+
defineBuiltin({
|
|
34975
|
+
name: "iskeyword",
|
|
34976
|
+
cases: [
|
|
34977
|
+
{
|
|
34978
|
+
// iskeyword() with no args returns the list of keywords (column cell).
|
|
34979
|
+
match: (argTypes) => {
|
|
34980
|
+
if (argTypes.length === 0) return [{ kind: "cell" }];
|
|
34981
|
+
if (argTypes.length === 1) return [{ kind: "boolean" }];
|
|
34982
|
+
return null;
|
|
34983
|
+
},
|
|
34984
|
+
apply: (args) => {
|
|
34985
|
+
if (args.length === 0) {
|
|
34986
|
+
const names = [...MATLAB_KEYWORDS].sort();
|
|
34987
|
+
return RTV.cell(
|
|
34988
|
+
names.map((n) => RTV.char(n)),
|
|
34989
|
+
[names.length, 1]
|
|
34990
|
+
);
|
|
34991
|
+
}
|
|
34992
|
+
const s = singleRowText(args[0]);
|
|
34993
|
+
return RTV.logical(s !== null && MATLAB_KEYWORDS.has(s));
|
|
34994
|
+
}
|
|
34995
|
+
}
|
|
34996
|
+
]
|
|
34997
|
+
});
|
|
34772
34998
|
defineBuiltin({
|
|
34773
34999
|
name: "iscell",
|
|
34774
35000
|
cases: [anyToLogicalCase((args) => isRuntimeCell(args[0]))]
|
|
@@ -34785,6 +35011,82 @@ defineBuiltin({
|
|
|
34785
35011
|
name: "issparse",
|
|
34786
35012
|
cases: [anyToLogicalCase((args) => isRuntimeSparseMatrix(args[0]))]
|
|
34787
35013
|
});
|
|
35014
|
+
defineBuiltin({
|
|
35015
|
+
name: "isobject",
|
|
35016
|
+
cases: [
|
|
35017
|
+
anyToLogicalCase(
|
|
35018
|
+
(args) => isRuntimeClassInstance(args[0]) || isRuntimeClassInstanceArray(args[0])
|
|
35019
|
+
)
|
|
35020
|
+
]
|
|
35021
|
+
});
|
|
35022
|
+
defineBuiltin({
|
|
35023
|
+
name: "isprop",
|
|
35024
|
+
help: {
|
|
35025
|
+
signatures: ["tf = isprop(obj, PropertyName)"],
|
|
35026
|
+
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."
|
|
35027
|
+
},
|
|
35028
|
+
cases: [
|
|
35029
|
+
{
|
|
35030
|
+
match: (argTypes) => {
|
|
35031
|
+
if (argTypes.length !== 2) return null;
|
|
35032
|
+
return [{ kind: "boolean" }];
|
|
35033
|
+
},
|
|
35034
|
+
apply: (args) => {
|
|
35035
|
+
const v = args[0];
|
|
35036
|
+
const nameArg = args[1];
|
|
35037
|
+
let propName = null;
|
|
35038
|
+
if (isRuntimeChar(nameArg)) propName = nameArg.value;
|
|
35039
|
+
else if (isRuntimeString(nameArg)) propName = nameArg;
|
|
35040
|
+
let answer = false;
|
|
35041
|
+
if (propName !== null) {
|
|
35042
|
+
if (isRuntimeClassInstance(v)) answer = v.fields.has(propName);
|
|
35043
|
+
else if (isRuntimeClassInstanceArray(v))
|
|
35044
|
+
answer = v.elements.length > 0 && v.elements[0].fields.has(propName);
|
|
35045
|
+
}
|
|
35046
|
+
const shape = getShape(v);
|
|
35047
|
+
const n = shape.reduce((a, b) => a * b, 1);
|
|
35048
|
+
if (n === 1) return RTV.logical(answer);
|
|
35049
|
+
const data = allocFloat64Array(n);
|
|
35050
|
+
if (answer) data.fill(1);
|
|
35051
|
+
return new RuntimeTensor(data, shape, void 0, true);
|
|
35052
|
+
}
|
|
35053
|
+
}
|
|
35054
|
+
]
|
|
35055
|
+
});
|
|
35056
|
+
defineBuiltin({
|
|
35057
|
+
name: "addprop",
|
|
35058
|
+
help: {
|
|
35059
|
+
signatures: ["p = addprop(obj, PropertyName)"],
|
|
35060
|
+
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."
|
|
35061
|
+
},
|
|
35062
|
+
cases: [
|
|
35063
|
+
{
|
|
35064
|
+
match: (argTypes) => {
|
|
35065
|
+
if (argTypes.length !== 2) return null;
|
|
35066
|
+
return [{ kind: "unknown" }];
|
|
35067
|
+
},
|
|
35068
|
+
apply: (args) => {
|
|
35069
|
+
const obj = args[0];
|
|
35070
|
+
if (!isRuntimeClassInstance(obj))
|
|
35071
|
+
throw new RuntimeError(
|
|
35072
|
+
"addprop: first argument must be a dynamicprops object"
|
|
35073
|
+
);
|
|
35074
|
+
const name = toString(args[1]);
|
|
35075
|
+
if (!obj.fields.has(name)) {
|
|
35076
|
+
const empty = RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
35077
|
+
incref(empty);
|
|
35078
|
+
obj.fields.set(name, empty);
|
|
35079
|
+
}
|
|
35080
|
+
return RTV.classInstance(
|
|
35081
|
+
"meta.DynamicProperty",
|
|
35082
|
+
["Name"],
|
|
35083
|
+
true,
|
|
35084
|
+
/* @__PURE__ */ new Map([["Name", RTV.char(name)]])
|
|
35085
|
+
);
|
|
35086
|
+
}
|
|
35087
|
+
}
|
|
35088
|
+
]
|
|
35089
|
+
});
|
|
34788
35090
|
defineBuiltin({
|
|
34789
35091
|
name: "isscalar",
|
|
34790
35092
|
cases: [
|
|
@@ -34982,6 +35284,30 @@ function mkChar(value) {
|
|
|
34982
35284
|
defineBuiltin({
|
|
34983
35285
|
name: "class",
|
|
34984
35286
|
cases: [
|
|
35287
|
+
// Old-style (pre-classdef) constructor form: class(structData, 'ClassName')
|
|
35288
|
+
// builds a value-type instance whose fields are the struct's fields. The
|
|
35289
|
+
// optional class(s,'Name',parent,...) inheritance form is not supported
|
|
35290
|
+
// (returns null → "unsupported argument types").
|
|
35291
|
+
{
|
|
35292
|
+
match: (argTypes) => {
|
|
35293
|
+
if (argTypes.length !== 2) return null;
|
|
35294
|
+
if (argTypes[0].kind !== "struct") return null;
|
|
35295
|
+
const k = argTypes[1].kind;
|
|
35296
|
+
if (k !== "char" && k !== "string") return null;
|
|
35297
|
+
return [{ kind: "unknown" }];
|
|
35298
|
+
},
|
|
35299
|
+
apply: (args) => {
|
|
35300
|
+
const s = args[0];
|
|
35301
|
+
if (!isRuntimeStruct(s))
|
|
35302
|
+
throw new RuntimeError(
|
|
35303
|
+
"class: first argument must be a scalar struct"
|
|
35304
|
+
);
|
|
35305
|
+
const nameVal = args[1];
|
|
35306
|
+
const className = isRuntimeChar(nameVal) ? nameVal.value : isRuntimeString(nameVal) ? nameVal : String(nameVal);
|
|
35307
|
+
const fieldNames = [...s.fields.keys()];
|
|
35308
|
+
return RTV.classInstance(className, fieldNames, false, s.fields);
|
|
35309
|
+
}
|
|
35310
|
+
},
|
|
34985
35311
|
{
|
|
34986
35312
|
match: (argTypes) => {
|
|
34987
35313
|
if (argTypes.length !== 1) return null;
|
|
@@ -35019,6 +35345,26 @@ defineBuiltin({
|
|
|
35019
35345
|
}
|
|
35020
35346
|
]
|
|
35021
35347
|
});
|
|
35348
|
+
for (const name of ["superiorto", "inferiorto"]) {
|
|
35349
|
+
defineBuiltin({
|
|
35350
|
+
name,
|
|
35351
|
+
help: {
|
|
35352
|
+
signatures: [`${name}('Class1', 'Class2', ...)`],
|
|
35353
|
+
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."
|
|
35354
|
+
},
|
|
35355
|
+
cases: [
|
|
35356
|
+
{
|
|
35357
|
+
match: (argTypes) => {
|
|
35358
|
+
for (const t of argTypes) {
|
|
35359
|
+
if (t.kind !== "char" && t.kind !== "string") return null;
|
|
35360
|
+
}
|
|
35361
|
+
return [];
|
|
35362
|
+
},
|
|
35363
|
+
apply: () => void 0
|
|
35364
|
+
}
|
|
35365
|
+
]
|
|
35366
|
+
});
|
|
35367
|
+
}
|
|
35022
35368
|
function fieldnamesApply(args) {
|
|
35023
35369
|
if (args.length !== 1)
|
|
35024
35370
|
throw new RuntimeError("fieldnames requires 1 argument");
|
|
@@ -35134,6 +35480,11 @@ function validateDim(x) {
|
|
|
35134
35480
|
throw new RuntimeError("Size inputs must be nonnegative integers.");
|
|
35135
35481
|
return Math.max(0, x);
|
|
35136
35482
|
}
|
|
35483
|
+
function toScalarDim(v) {
|
|
35484
|
+
if (isRuntimeTensor(v) && v.data.length !== 1)
|
|
35485
|
+
throw new RuntimeError("Size inputs must be scalar.");
|
|
35486
|
+
return validateDim(toNumber(v));
|
|
35487
|
+
}
|
|
35137
35488
|
function parseShapeArgs(args) {
|
|
35138
35489
|
if (args.length === 1 && isRuntimeTensor(args[0])) {
|
|
35139
35490
|
const t = args[0];
|
|
@@ -35141,7 +35492,7 @@ function parseShapeArgs(args) {
|
|
|
35141
35492
|
for (let i = 0; i < t.data.length; i++) shape.push(validateDim(t.data[i]));
|
|
35142
35493
|
return shape;
|
|
35143
35494
|
}
|
|
35144
|
-
return args.map(
|
|
35495
|
+
return args.map(toScalarDim);
|
|
35145
35496
|
}
|
|
35146
35497
|
function arrayConstructorCases(fillFn, scalarValue, opts) {
|
|
35147
35498
|
const cases = [
|
|
@@ -35182,12 +35533,14 @@ function arrayConstructorCases(fillFn, scalarValue, opts) {
|
|
|
35182
35533
|
return fillFn(shape);
|
|
35183
35534
|
}
|
|
35184
35535
|
},
|
|
35185
|
-
// Multiple scalar args
|
|
35536
|
+
// Multiple scalar args. A 1×1 array counts as a scalar dimension, so
|
|
35537
|
+
// accept `tensor` here too (apply-time validates each is scalar).
|
|
35186
35538
|
{
|
|
35187
35539
|
match: (argTypes) => {
|
|
35188
35540
|
if (argTypes.length <= 1) return null;
|
|
35189
35541
|
for (const a of argTypes) {
|
|
35190
|
-
if (a.kind !== "number" && a.kind !== "boolean"
|
|
35542
|
+
if (a.kind !== "number" && a.kind !== "boolean" && a.kind !== "tensor")
|
|
35543
|
+
return null;
|
|
35191
35544
|
}
|
|
35192
35545
|
const shape = argTypes.map(
|
|
35193
35546
|
(a) => a.kind === "number" && typeof a.exact === "number" ? a.exact : -1
|
|
@@ -35852,7 +36205,6 @@ function anyAllApply(name, mode) {
|
|
|
35852
36205
|
if (isRuntimeComplexNumber(v)) return RTV.logical(v.re !== 0 || v.im !== 0);
|
|
35853
36206
|
if (isRuntimeTensor(v)) {
|
|
35854
36207
|
if (args.length === 1) {
|
|
35855
|
-
if (v.data.length === 0) return RTV.logical(mode === "all");
|
|
35856
36208
|
const d = firstReduceDim(v.shape);
|
|
35857
36209
|
if (d === 0) return RTV.logical(scanLogical(v.data, v.imag, mode));
|
|
35858
36210
|
return logicalAlongDim(v, d, mode);
|
|
@@ -36122,7 +36474,12 @@ function applyTextFn(v, fn) {
|
|
|
36122
36474
|
}
|
|
36123
36475
|
return RTV.cell(out, [...v.shape]);
|
|
36124
36476
|
}
|
|
36125
|
-
if (isRuntimeChar(v))
|
|
36477
|
+
if (isRuntimeChar(v)) {
|
|
36478
|
+
if (v.shape && (v.shape[0] ?? 1) > 1) {
|
|
36479
|
+
return charRowsToMatrix(valueToCharRows(v).map(fn));
|
|
36480
|
+
}
|
|
36481
|
+
return RTV.char(fn(v.value));
|
|
36482
|
+
}
|
|
36126
36483
|
if (isRuntimeString(v)) return RTV.string(fn(toString(v)));
|
|
36127
36484
|
return v;
|
|
36128
36485
|
}
|
|
@@ -36274,7 +36631,7 @@ registerIBuiltin({
|
|
|
36274
36631
|
const str = toString(args[0]);
|
|
36275
36632
|
const pat = toString(args[1]);
|
|
36276
36633
|
const rep = toString(args[2]);
|
|
36277
|
-
let flags = "
|
|
36634
|
+
let flags = "gs";
|
|
36278
36635
|
for (let i = 3; i < args.length; i++) {
|
|
36279
36636
|
const opt = toString(args[i]).toLowerCase();
|
|
36280
36637
|
if (opt === "ignorecase") flags += "i";
|
|
@@ -36638,6 +36995,38 @@ registerIBuiltin({
|
|
|
36638
36995
|
};
|
|
36639
36996
|
}
|
|
36640
36997
|
});
|
|
36998
|
+
registerIBuiltin({
|
|
36999
|
+
name: "isspace",
|
|
37000
|
+
help: {
|
|
37001
|
+
signatures: ["TF = isspace(str)"],
|
|
37002
|
+
description: "Return a logical array the same size as str, true where the character is whitespace. Numeric input is treated as Unicode code points."
|
|
37003
|
+
},
|
|
37004
|
+
resolve: (argTypes) => {
|
|
37005
|
+
if (argTypes.length !== 1) return null;
|
|
37006
|
+
const k = argTypes[0].kind;
|
|
37007
|
+
if (k !== "char" && k !== "string" && k !== "number" && k !== "boolean" && k !== "tensor") {
|
|
37008
|
+
return null;
|
|
37009
|
+
}
|
|
37010
|
+
const pred = (cp) => RE_WSPACE.test(String.fromCodePoint(cp));
|
|
37011
|
+
return {
|
|
37012
|
+
outputTypes: [{ kind: "tensor", isComplex: false, isLogical: true }],
|
|
37013
|
+
apply: (args) => {
|
|
37014
|
+
const v = args[0];
|
|
37015
|
+
if (isRuntimeChar(v)) {
|
|
37016
|
+
return logicalRowFromString(
|
|
37017
|
+
v.value,
|
|
37018
|
+
pred,
|
|
37019
|
+
v.shape ? [...v.shape] : void 0
|
|
37020
|
+
);
|
|
37021
|
+
}
|
|
37022
|
+
if (isRuntimeString(v)) return logicalRowFromString(toString(v), pred);
|
|
37023
|
+
if (isRuntimeTensor(v))
|
|
37024
|
+
return logicalFromNumericTensor(v.data, v.shape, pred);
|
|
37025
|
+
return logicalFromNumericTensor([toNumber(v)], [1, 1], pred);
|
|
37026
|
+
}
|
|
37027
|
+
};
|
|
37028
|
+
}
|
|
37029
|
+
});
|
|
36641
37030
|
registerIBuiltin({
|
|
36642
37031
|
name: "contains",
|
|
36643
37032
|
resolve: (argTypes) => {
|
|
@@ -37085,12 +37474,102 @@ registerIBuiltin({
|
|
|
37085
37474
|
};
|
|
37086
37475
|
}
|
|
37087
37476
|
});
|
|
37477
|
+
function collectRows(v) {
|
|
37478
|
+
if (isRuntimeCell(v)) {
|
|
37479
|
+
const rows = [];
|
|
37480
|
+
for (const el of v.data) rows.push(...valueToCharRows(el));
|
|
37481
|
+
return rows;
|
|
37482
|
+
}
|
|
37483
|
+
return valueToCharRows(v);
|
|
37484
|
+
}
|
|
37485
|
+
registerIBuiltin({
|
|
37486
|
+
name: "strmatch",
|
|
37487
|
+
help: {
|
|
37488
|
+
signatures: [
|
|
37489
|
+
"x = strmatch(str, strarray)",
|
|
37490
|
+
"x = strmatch(str, strarray, 'exact')"
|
|
37491
|
+
],
|
|
37492
|
+
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."
|
|
37493
|
+
},
|
|
37494
|
+
resolve: (argTypes) => {
|
|
37495
|
+
if (argTypes.length < 2 || argTypes.length > 3) return null;
|
|
37496
|
+
if (!isTextType(argTypes[0])) return null;
|
|
37497
|
+
const sa = argTypes[1];
|
|
37498
|
+
if (sa.kind !== "char" && sa.kind !== "string" && sa.kind !== "cell")
|
|
37499
|
+
return null;
|
|
37500
|
+
return {
|
|
37501
|
+
outputTypes: [{ kind: "tensor", isComplex: false }],
|
|
37502
|
+
apply: (args) => {
|
|
37503
|
+
const str = toString(args[0]);
|
|
37504
|
+
let rows = collectRows(args[1]);
|
|
37505
|
+
const n = rows.length === 0 ? 0 : Math.max(...rows.map((r) => r.length));
|
|
37506
|
+
rows = rows.map((r) => r.padEnd(n, " "));
|
|
37507
|
+
const exactMatch = args.length === 3;
|
|
37508
|
+
let s = str;
|
|
37509
|
+
let len = s.length;
|
|
37510
|
+
if (len > n) {
|
|
37511
|
+
return RTV.tensor(allocFloat64Array(0), [0, 1]);
|
|
37512
|
+
}
|
|
37513
|
+
if (exactMatch && len < n) {
|
|
37514
|
+
const useNull = rows.some((r) => r.charCodeAt(n - 1) === 0);
|
|
37515
|
+
s = s.padEnd(n, useNull ? "\0" : " ");
|
|
37516
|
+
len = n;
|
|
37517
|
+
}
|
|
37518
|
+
const matches2 = [];
|
|
37519
|
+
for (let r = 0; r < rows.length; r++) {
|
|
37520
|
+
let ok = true;
|
|
37521
|
+
for (let i = 0; i < len; i++) {
|
|
37522
|
+
if (rows[r][i] !== s[i]) {
|
|
37523
|
+
ok = false;
|
|
37524
|
+
break;
|
|
37525
|
+
}
|
|
37526
|
+
}
|
|
37527
|
+
if (ok) matches2.push(r + 1);
|
|
37528
|
+
}
|
|
37529
|
+
return RTV.tensor(allocFloat64Array(matches2), [matches2.length, 1]);
|
|
37530
|
+
}
|
|
37531
|
+
};
|
|
37532
|
+
}
|
|
37533
|
+
});
|
|
37534
|
+
function valueToCharRows(v) {
|
|
37535
|
+
if (isRuntimeChar(v)) {
|
|
37536
|
+
const cols = v.shape ? v.shape[1] ?? v.value.length : v.value.length;
|
|
37537
|
+
const numRows = v.shape ? v.shape[0] ?? 1 : 1;
|
|
37538
|
+
if (numRows <= 1) return [v.value];
|
|
37539
|
+
const out = [];
|
|
37540
|
+
for (let r = 0; r < numRows; r++)
|
|
37541
|
+
out.push(v.value.slice(r * cols, (r + 1) * cols));
|
|
37542
|
+
return out;
|
|
37543
|
+
}
|
|
37544
|
+
if (isRuntimeString(v)) return [v];
|
|
37545
|
+
if (isRuntimeNumber(v)) return [String.fromCharCode(Math.round(v))];
|
|
37546
|
+
if (isRuntimeTensor(v)) {
|
|
37547
|
+
const rows = v.shape.length >= 2 ? v.shape[0] ?? 1 : 1;
|
|
37548
|
+
const cols = v.shape.length >= 2 ? v.shape[1] ?? 0 : v.data.length;
|
|
37549
|
+
const out = [];
|
|
37550
|
+
for (let r = 0; r < rows; r++) {
|
|
37551
|
+
let s = "";
|
|
37552
|
+
for (let c = 0; c < cols; c++)
|
|
37553
|
+
s += String.fromCharCode(Math.round(v.data[c * rows + r]));
|
|
37554
|
+
out.push(s);
|
|
37555
|
+
}
|
|
37556
|
+
return out;
|
|
37557
|
+
}
|
|
37558
|
+
throw new RuntimeError("char: unsupported cell element type");
|
|
37559
|
+
}
|
|
37560
|
+
function charRowsToMatrix(rows) {
|
|
37561
|
+
if (rows.length === 0) return RTV.char("");
|
|
37562
|
+
const width = Math.max(...rows.map((r) => r.length));
|
|
37563
|
+
const padded = rows.map((r) => r.padEnd(width, " "));
|
|
37564
|
+
if (rows.length === 1) return RTV.char(padded[0]);
|
|
37565
|
+
return new RuntimeChar(padded.join(""), [rows.length, width]);
|
|
37566
|
+
}
|
|
37088
37567
|
registerIBuiltin({
|
|
37089
37568
|
name: "char",
|
|
37090
37569
|
resolve: (argTypes) => {
|
|
37091
37570
|
if (argTypes.length !== 1) return null;
|
|
37092
37571
|
const a = argTypes[0];
|
|
37093
|
-
if (a.kind !== "char" && a.kind !== "string" && a.kind !== "number" && a.kind !== "tensor")
|
|
37572
|
+
if (a.kind !== "char" && a.kind !== "string" && a.kind !== "number" && a.kind !== "tensor" && a.kind !== "cell")
|
|
37094
37573
|
return null;
|
|
37095
37574
|
return {
|
|
37096
37575
|
outputTypes: [{ kind: "char" }],
|
|
@@ -37107,6 +37586,11 @@ registerIBuiltin({
|
|
|
37107
37586
|
}
|
|
37108
37587
|
return RTV.char(chars.join(""));
|
|
37109
37588
|
}
|
|
37589
|
+
if (isRuntimeCell(v)) {
|
|
37590
|
+
const rows = [];
|
|
37591
|
+
for (const el of v.data) rows.push(...valueToCharRows(el));
|
|
37592
|
+
return charRowsToMatrix(rows);
|
|
37593
|
+
}
|
|
37110
37594
|
throw new RuntimeError("char: unsupported arguments");
|
|
37111
37595
|
}
|
|
37112
37596
|
};
|
|
@@ -37174,6 +37658,8 @@ registerIBuiltin({
|
|
|
37174
37658
|
if (!isTextType(argTypes[0]) || !isTextType(argTypes[1])) return null;
|
|
37175
37659
|
const outputTypes = [{ kind: "number" }];
|
|
37176
37660
|
if (nargout >= 2) outputTypes.push({ kind: "number" });
|
|
37661
|
+
if (nargout >= 3) outputTypes.push({ kind: "char" });
|
|
37662
|
+
if (nargout >= 4) outputTypes.push({ kind: "number" });
|
|
37177
37663
|
return {
|
|
37178
37664
|
outputTypes,
|
|
37179
37665
|
apply: (args, nout) => {
|
|
@@ -37183,6 +37669,7 @@ registerIBuiltin({
|
|
|
37183
37669
|
const results = [];
|
|
37184
37670
|
let strPos = 0;
|
|
37185
37671
|
let fmtPos = 0;
|
|
37672
|
+
let matchFailure = false;
|
|
37186
37673
|
while (fmtPos < fmt.length && strPos < str.length && results.length < maxCount) {
|
|
37187
37674
|
if (fmt[fmtPos] === "%") {
|
|
37188
37675
|
fmtPos++;
|
|
@@ -37194,22 +37681,34 @@ registerIBuiltin({
|
|
|
37194
37681
|
}
|
|
37195
37682
|
if (spec === "d" || spec === "i") {
|
|
37196
37683
|
const m = str.slice(strPos).match(/^[+-]?\d+/);
|
|
37197
|
-
if (!m)
|
|
37684
|
+
if (!m) {
|
|
37685
|
+
matchFailure = true;
|
|
37686
|
+
break;
|
|
37687
|
+
}
|
|
37198
37688
|
results.push(parseInt(m[0], 10));
|
|
37199
37689
|
strPos += m[0].length;
|
|
37200
37690
|
} else if (spec === "f" || spec === "e" || spec === "g") {
|
|
37201
37691
|
const m = str.slice(strPos).match(/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/);
|
|
37202
|
-
if (!m)
|
|
37692
|
+
if (!m) {
|
|
37693
|
+
matchFailure = true;
|
|
37694
|
+
break;
|
|
37695
|
+
}
|
|
37203
37696
|
results.push(parseFloat(m[0]));
|
|
37204
37697
|
strPos += m[0].length;
|
|
37205
37698
|
} else if (spec === "x") {
|
|
37206
37699
|
const m = str.slice(strPos).match(/^[+-]?[0-9a-fA-F]+/);
|
|
37207
|
-
if (!m)
|
|
37700
|
+
if (!m) {
|
|
37701
|
+
matchFailure = true;
|
|
37702
|
+
break;
|
|
37703
|
+
}
|
|
37208
37704
|
results.push(parseInt(m[0], 16));
|
|
37209
37705
|
strPos += m[0].length;
|
|
37210
37706
|
} else if (spec === "o") {
|
|
37211
37707
|
const m = str.slice(strPos).match(/^[+-]?[0-7]+/);
|
|
37212
|
-
if (!m)
|
|
37708
|
+
if (!m) {
|
|
37709
|
+
matchFailure = true;
|
|
37710
|
+
break;
|
|
37711
|
+
}
|
|
37213
37712
|
results.push(parseInt(m[0], 8));
|
|
37214
37713
|
strPos += m[0].length;
|
|
37215
37714
|
} else if (spec === "c") {
|
|
@@ -37217,7 +37716,10 @@ registerIBuiltin({
|
|
|
37217
37716
|
strPos++;
|
|
37218
37717
|
} else if (spec === "s") {
|
|
37219
37718
|
const m = str.slice(strPos).match(/^\S+/);
|
|
37220
|
-
if (!m)
|
|
37719
|
+
if (!m) {
|
|
37720
|
+
matchFailure = true;
|
|
37721
|
+
break;
|
|
37722
|
+
}
|
|
37221
37723
|
for (let ci = 0; ci < m[0].length && results.length < maxCount; ci++) {
|
|
37222
37724
|
results.push(m[0].charCodeAt(ci));
|
|
37223
37725
|
}
|
|
@@ -37227,7 +37729,10 @@ registerIBuiltin({
|
|
|
37227
37729
|
fmtPos++;
|
|
37228
37730
|
while (strPos < str.length && /\s/.test(str[strPos])) strPos++;
|
|
37229
37731
|
} else {
|
|
37230
|
-
if (str[strPos] !== fmt[fmtPos])
|
|
37732
|
+
if (str[strPos] !== fmt[fmtPos]) {
|
|
37733
|
+
matchFailure = true;
|
|
37734
|
+
break;
|
|
37735
|
+
}
|
|
37231
37736
|
strPos++;
|
|
37232
37737
|
fmtPos++;
|
|
37233
37738
|
}
|
|
@@ -37237,7 +37742,16 @@ registerIBuiltin({
|
|
|
37237
37742
|
}
|
|
37238
37743
|
const vals = results.length === 1 ? RTV.num(results[0]) : RTV.tensor(allocFloat64Array(results), [results.length, 1]);
|
|
37239
37744
|
if (nout >= 2) {
|
|
37240
|
-
|
|
37745
|
+
const out = [vals, RTV.num(results.length)];
|
|
37746
|
+
if (nout >= 3) {
|
|
37747
|
+
out.push(
|
|
37748
|
+
RTV.char(matchFailure ? "Matching failure in format." : "")
|
|
37749
|
+
);
|
|
37750
|
+
}
|
|
37751
|
+
if (nout >= 4) {
|
|
37752
|
+
out.push(RTV.num(strPos + 1));
|
|
37753
|
+
}
|
|
37754
|
+
return out;
|
|
37241
37755
|
}
|
|
37242
37756
|
return vals;
|
|
37243
37757
|
}
|
|
@@ -38648,8 +39162,34 @@ function normImplTensor(v, args) {
|
|
|
38648
39162
|
return RTV.num(maxRowSum);
|
|
38649
39163
|
}
|
|
38650
39164
|
if (p2 === 2) {
|
|
39165
|
+
let anyNaN = false;
|
|
39166
|
+
let anyInf = false;
|
|
39167
|
+
for (let i = 0; i < v.data.length; i++) {
|
|
39168
|
+
const re = v.data[i];
|
|
39169
|
+
const im = imag2 ? imag2[i] : 0;
|
|
39170
|
+
if (Number.isNaN(re) || Number.isNaN(im)) anyNaN = true;
|
|
39171
|
+
else if (!isFinite(re) || !isFinite(im)) anyInf = true;
|
|
39172
|
+
}
|
|
39173
|
+
if (anyNaN) return RTV.num(NaN);
|
|
39174
|
+
if (anyInf) return RTV.num(Infinity);
|
|
38651
39175
|
const bridge = getEffectiveBridge("norm", "svd");
|
|
38652
39176
|
if (bridge && bridge.svd) {
|
|
39177
|
+
if (imag2) {
|
|
39178
|
+
const R = allocFloat64Array(4 * rows * cols);
|
|
39179
|
+
const tm = 2 * rows;
|
|
39180
|
+
for (let j = 0; j < cols; j++) {
|
|
39181
|
+
for (let i = 0; i < rows; i++) {
|
|
39182
|
+
const a = v.data[j * rows + i];
|
|
39183
|
+
const b = imag2[j * rows + i];
|
|
39184
|
+
R[j * tm + i] = a;
|
|
39185
|
+
R[j * tm + (rows + i)] = b;
|
|
39186
|
+
R[(cols + j) * tm + i] = -b;
|
|
39187
|
+
R[(cols + j) * tm + (rows + i)] = a;
|
|
39188
|
+
}
|
|
39189
|
+
}
|
|
39190
|
+
const result2 = bridge.svd(R, tm, 2 * cols, false, false);
|
|
39191
|
+
return RTV.num(result2.S[0]);
|
|
39192
|
+
}
|
|
38653
39193
|
const f64 = v.data instanceof Float64Array ? v.data : allocFloat64Array(v.data);
|
|
38654
39194
|
const result = bridge.svd(f64, rows, cols, false, false);
|
|
38655
39195
|
return RTV.num(result.S[0]);
|
|
@@ -39409,6 +39949,100 @@ function svdApply(args, nargout) {
|
|
|
39409
39949
|
[k, 1]
|
|
39410
39950
|
);
|
|
39411
39951
|
}
|
|
39952
|
+
function nullApply(args) {
|
|
39953
|
+
let A = args[0];
|
|
39954
|
+
if (isRuntimeNumber(A) || isRuntimeComplexNumber(A)) {
|
|
39955
|
+
A = isRuntimeNumber(A) ? RTV.tensor(allocFloat64Array([A]), [1, 1]) : RTV.tensor(
|
|
39956
|
+
allocFloat64Array([A.re]),
|
|
39957
|
+
[1, 1],
|
|
39958
|
+
allocFloat64Array([A.im])
|
|
39959
|
+
);
|
|
39960
|
+
}
|
|
39961
|
+
if (!isRuntimeTensor(A))
|
|
39962
|
+
throw new RuntimeError("null: argument must be a numeric matrix");
|
|
39963
|
+
const [m, n] = tensorSize2D(A);
|
|
39964
|
+
const [, Sdiag, V] = svdApply([A], 3);
|
|
39965
|
+
const k = Math.min(m, n);
|
|
39966
|
+
const s = [];
|
|
39967
|
+
for (let i = 0; i < k; i++) s.push(Sdiag.data[colMajorIndex(i, i, m)]);
|
|
39968
|
+
const maxS = s.length > 0 ? Math.max(...s) : 0;
|
|
39969
|
+
const tol = args.length > 1 && args[1] !== void 0 ? toNumber(args[1]) : Math.max(m, n) * epsOf(maxS);
|
|
39970
|
+
let r = 0;
|
|
39971
|
+
for (const sv of s) if (sv > tol) r++;
|
|
39972
|
+
const cols = n - r;
|
|
39973
|
+
const out = allocFloat64Array(n * cols);
|
|
39974
|
+
const outImag = V.imag ? allocFloat64Array(n * cols) : void 0;
|
|
39975
|
+
for (let c = 0; c < cols; c++) {
|
|
39976
|
+
for (let i = 0; i < n; i++) {
|
|
39977
|
+
const src = colMajorIndex(i, r + c, n);
|
|
39978
|
+
out[colMajorIndex(i, c, n)] = V.data[src];
|
|
39979
|
+
if (outImag) outImag[colMajorIndex(i, c, n)] = V.imag[src];
|
|
39980
|
+
}
|
|
39981
|
+
}
|
|
39982
|
+
return RTV.tensor(out, [n, cols], outImag);
|
|
39983
|
+
}
|
|
39984
|
+
registerIBuiltin({
|
|
39985
|
+
name: "null",
|
|
39986
|
+
resolve: (argTypes, nargout) => {
|
|
39987
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2) return null;
|
|
39988
|
+
if (!isNumericJitType(argTypes[0])) return null;
|
|
39989
|
+
const isComplex = argTypes[0].kind === "tensor" && argTypes[0].isComplex;
|
|
39990
|
+
return {
|
|
39991
|
+
outputTypes: [tensorType(isComplex || void 0)],
|
|
39992
|
+
apply: (args) => nullApply(args)
|
|
39993
|
+
};
|
|
39994
|
+
}
|
|
39995
|
+
});
|
|
39996
|
+
function computeBandwidth(A) {
|
|
39997
|
+
let lower = 0;
|
|
39998
|
+
let upper = 0;
|
|
39999
|
+
const note = (i, j) => {
|
|
40000
|
+
if (i > j) lower = Math.max(lower, i - j);
|
|
40001
|
+
else if (j > i) upper = Math.max(upper, j - i);
|
|
40002
|
+
};
|
|
40003
|
+
if (isRuntimeNumber(A) || isRuntimeComplexNumber(A)) return [0, 0];
|
|
40004
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
40005
|
+
for (let j = 0; j < A.n; j++) {
|
|
40006
|
+
for (let k = A.jc[j]; k < A.jc[j + 1]; k++) {
|
|
40007
|
+
if (A.pr[k] === 0 && (!A.pi || A.pi[k] === 0)) continue;
|
|
40008
|
+
note(A.ir[k], j);
|
|
40009
|
+
}
|
|
40010
|
+
}
|
|
40011
|
+
return [lower, upper];
|
|
40012
|
+
}
|
|
40013
|
+
if (isRuntimeTensor(A)) {
|
|
40014
|
+
const [m, n] = tensorSize2D(A);
|
|
40015
|
+
for (let j = 0; j < n; j++) {
|
|
40016
|
+
for (let i = 0; i < m; i++) {
|
|
40017
|
+
const idx = colMajorIndex(i, j, m);
|
|
40018
|
+
if (A.data[idx] === 0 && (!A.imag || A.imag[idx] === 0)) continue;
|
|
40019
|
+
note(i, j);
|
|
40020
|
+
}
|
|
40021
|
+
}
|
|
40022
|
+
return [lower, upper];
|
|
40023
|
+
}
|
|
40024
|
+
throw new RuntimeError("bandwidth: first argument must be a numeric matrix");
|
|
40025
|
+
}
|
|
40026
|
+
function bandwidthApply(args, nargout) {
|
|
40027
|
+
const [lower, upper] = computeBandwidth(args[0]);
|
|
40028
|
+
if (args.length >= 2 && args[1] !== void 0) {
|
|
40029
|
+
const type = parseStringArgLower(args[1]);
|
|
40030
|
+
if (type === "lower") return RTV.num(lower);
|
|
40031
|
+
if (type === "upper") return RTV.num(upper);
|
|
40032
|
+
throw new RuntimeError("bandwidth: TYPE must be 'lower' or 'upper'");
|
|
40033
|
+
}
|
|
40034
|
+
if (nargout >= 2) return [RTV.num(lower), RTV.num(upper)];
|
|
40035
|
+
return RTV.num(lower);
|
|
40036
|
+
}
|
|
40037
|
+
registerIBuiltin({
|
|
40038
|
+
name: "bandwidth",
|
|
40039
|
+
resolve: (argTypes, nargout) => {
|
|
40040
|
+
if (nargout > 2 || argTypes.length < 1 || argTypes.length > 2) return null;
|
|
40041
|
+
if (!isNumericJitType(argTypes[0])) return null;
|
|
40042
|
+
const outs = nargout >= 2 ? [NUM, NUM] : [NUM];
|
|
40043
|
+
return { outputTypes: outs, apply: (args, n) => bandwidthApply(args, n) };
|
|
40044
|
+
}
|
|
40045
|
+
});
|
|
39412
40046
|
function computeATA(A_data, m, n) {
|
|
39413
40047
|
const result = allocFloat64Array(n * n);
|
|
39414
40048
|
for (let j = 0; j < n; j++)
|
|
@@ -41279,6 +41913,33 @@ function validateSizeArg(x) {
|
|
|
41279
41913
|
}
|
|
41280
41914
|
return x < 0 ? 0 : x;
|
|
41281
41915
|
}
|
|
41916
|
+
function parseReshapeDims(args, total) {
|
|
41917
|
+
let rawDims;
|
|
41918
|
+
if (args.length === 2 && isRuntimeTensor(args[1]) && args[1].data.length > 1) {
|
|
41919
|
+
rawDims = Array.from(args[1].data).map((x) => validateSizeArg(x));
|
|
41920
|
+
} else {
|
|
41921
|
+
rawDims = args.slice(1).map((a) => {
|
|
41922
|
+
if (isRuntimeTensor(a) && a.data.length === 0) return null;
|
|
41923
|
+
return validateSizeArg(toNumber(a));
|
|
41924
|
+
});
|
|
41925
|
+
}
|
|
41926
|
+
const autoCount = rawDims.filter((d) => d === null).length;
|
|
41927
|
+
if (autoCount > 1)
|
|
41928
|
+
throw new RuntimeError("reshape: only one dimension size can be []");
|
|
41929
|
+
let shape;
|
|
41930
|
+
if (autoCount === 1) {
|
|
41931
|
+
const known = rawDims.filter((d) => d !== null);
|
|
41932
|
+
const knownProduct = known.reduce((a, b) => a * b, 1);
|
|
41933
|
+
if (knownProduct === 0 || total % knownProduct !== 0)
|
|
41934
|
+
throw new RuntimeError("reshape: number of elements must not change");
|
|
41935
|
+
shape = rawDims.map((d) => d === null ? total / knownProduct : d);
|
|
41936
|
+
} else {
|
|
41937
|
+
shape = rawDims;
|
|
41938
|
+
}
|
|
41939
|
+
if (numel(shape) !== total)
|
|
41940
|
+
throw new RuntimeError("reshape: number of elements must not change");
|
|
41941
|
+
return shape;
|
|
41942
|
+
}
|
|
41282
41943
|
defineBuiltin({
|
|
41283
41944
|
name: "reshape",
|
|
41284
41945
|
cases: [
|
|
@@ -41290,31 +41951,31 @@ defineBuiltin({
|
|
|
41290
41951
|
const v = args[0];
|
|
41291
41952
|
if (isRuntimeSparseMatrix(v)) {
|
|
41292
41953
|
const totalEl = v.m * v.n;
|
|
41293
|
-
let
|
|
41954
|
+
let rawDims;
|
|
41294
41955
|
if (args.length === 2 && isRuntimeTensor(args[1]) && args[1].data.length > 1) {
|
|
41295
|
-
|
|
41956
|
+
rawDims = Array.from(args[1].data).map((x) => Math.round(x));
|
|
41296
41957
|
} else {
|
|
41297
|
-
|
|
41958
|
+
rawDims = args.slice(1).map((a) => {
|
|
41298
41959
|
if (isRuntimeTensor(a) && a.data.length === 0) return null;
|
|
41299
41960
|
return Math.round(toNumber(a));
|
|
41300
41961
|
});
|
|
41301
41962
|
}
|
|
41302
|
-
const
|
|
41303
|
-
if (
|
|
41963
|
+
const autoCount = rawDims.filter((d) => d === null).length;
|
|
41964
|
+
if (autoCount > 1)
|
|
41304
41965
|
throw new RuntimeError(
|
|
41305
41966
|
"reshape: only one dimension size can be []"
|
|
41306
41967
|
);
|
|
41307
41968
|
let shape2;
|
|
41308
|
-
if (
|
|
41309
|
-
const known =
|
|
41969
|
+
if (autoCount === 1) {
|
|
41970
|
+
const known = rawDims.filter((d) => d !== null);
|
|
41310
41971
|
const knownProduct = known.reduce((a, b) => a * b, 1);
|
|
41311
41972
|
if (totalEl % knownProduct !== 0)
|
|
41312
41973
|
throw new RuntimeError(
|
|
41313
41974
|
"reshape: number of elements must not change"
|
|
41314
41975
|
);
|
|
41315
|
-
shape2 =
|
|
41976
|
+
shape2 = rawDims.map((d) => d === null ? totalEl / knownProduct : d);
|
|
41316
41977
|
} else {
|
|
41317
|
-
shape2 =
|
|
41978
|
+
shape2 = rawDims;
|
|
41318
41979
|
}
|
|
41319
41980
|
if (shape2.length !== 2)
|
|
41320
41981
|
throw new RuntimeError("reshape: sparse matrices must be 2-D");
|
|
@@ -41352,40 +42013,32 @@ defineBuiltin({
|
|
|
41352
42013
|
jc[newN] = ti;
|
|
41353
42014
|
return RTV.sparseMatrix(newM, newN, ir, jc, pr, pi2);
|
|
41354
42015
|
}
|
|
42016
|
+
if (isRuntimeChar(v)) {
|
|
42017
|
+
const srcRows = v.shape ? v.shape[0] : 1;
|
|
42018
|
+
const srcCols = v.shape ? v.shape[1] ?? 0 : v.value.length;
|
|
42019
|
+
const total = v.value.length;
|
|
42020
|
+
const reqShape = parseReshapeDims(args, total);
|
|
42021
|
+
const s = [...reqShape];
|
|
42022
|
+
while (s.length > 2 && s[s.length - 1] === 1) s.pop();
|
|
42023
|
+
if (s.length > 2)
|
|
42024
|
+
throw new RuntimeError("reshape: char arrays must be 2-D");
|
|
42025
|
+
const nr = s[0];
|
|
42026
|
+
const nc = s.length >= 2 ? s[1] : 1;
|
|
42027
|
+
const linear = new Array(total);
|
|
42028
|
+
for (let j = 0; j < srcCols; j++)
|
|
42029
|
+
for (let i = 0; i < srcRows; i++)
|
|
42030
|
+
linear[j * srcRows + i] = v.value[i * srcCols + j];
|
|
42031
|
+
const chars = new Array(total);
|
|
42032
|
+
for (let j2 = 0; j2 < nc; j2++)
|
|
42033
|
+
for (let i2 = 0; i2 < nr; i2++)
|
|
42034
|
+
chars[i2 * nc + j2] = linear[j2 * nr + i2];
|
|
42035
|
+
return new RuntimeChar(chars.join(""), [nr, nc]);
|
|
42036
|
+
}
|
|
41355
42037
|
if (!isRuntimeTensor(v) && !isRuntimeNumber(v) && !isRuntimeComplexNumber(v))
|
|
41356
42038
|
throw new RuntimeError("reshape: first argument must be numeric");
|
|
41357
42039
|
const data = isRuntimeTensor(v) ? v.data : isRuntimeComplexNumber(v) ? allocFloat64Array([v.re]) : allocFloat64Array([v]);
|
|
41358
42040
|
const imag2 = isRuntimeTensor(v) ? v.imag : isRuntimeComplexNumber(v) ? allocFloat64Array([v.im]) : void 0;
|
|
41359
|
-
|
|
41360
|
-
if (args.length === 2 && isRuntimeTensor(args[1]) && args[1].data.length > 1) {
|
|
41361
|
-
rawDims = Array.from(args[1].data).map((x) => validateSizeArg(x));
|
|
41362
|
-
} else {
|
|
41363
|
-
rawDims = args.slice(1).map((a) => {
|
|
41364
|
-
if (isRuntimeTensor(a) && a.data.length === 0) return null;
|
|
41365
|
-
return validateSizeArg(toNumber(a));
|
|
41366
|
-
});
|
|
41367
|
-
}
|
|
41368
|
-
const autoCount = rawDims.filter((d) => d === null).length;
|
|
41369
|
-
if (autoCount > 1)
|
|
41370
|
-
throw new RuntimeError("reshape: only one dimension size can be []");
|
|
41371
|
-
let shape;
|
|
41372
|
-
if (autoCount === 1) {
|
|
41373
|
-
const known = rawDims.filter((d) => d !== null);
|
|
41374
|
-
const knownProduct = known.reduce((a, b) => a * b, 1);
|
|
41375
|
-
if (data.length % knownProduct !== 0)
|
|
41376
|
-
throw new RuntimeError(
|
|
41377
|
-
"reshape: number of elements must not change"
|
|
41378
|
-
);
|
|
41379
|
-
shape = rawDims.map(
|
|
41380
|
-
(d) => d === null ? data.length / knownProduct : d
|
|
41381
|
-
);
|
|
41382
|
-
} else {
|
|
41383
|
-
shape = rawDims;
|
|
41384
|
-
}
|
|
41385
|
-
const n = numel(shape);
|
|
41386
|
-
if (n !== data.length) {
|
|
41387
|
-
throw new RuntimeError("reshape: number of elements must not change");
|
|
41388
|
-
}
|
|
42041
|
+
const shape = parseReshapeDims(args, data.length);
|
|
41389
42042
|
if (isRuntimeTensor(v)) {
|
|
41390
42043
|
const dataCopy = allocFloat64Array(data);
|
|
41391
42044
|
const imagCopy = imag2 ? allocFloat64Array(imag2) : void 0;
|
|
@@ -41797,6 +42450,35 @@ defineBuiltin({
|
|
|
41797
42450
|
}
|
|
41798
42451
|
]
|
|
41799
42452
|
});
|
|
42453
|
+
function repmatObjects(v, repArgs) {
|
|
42454
|
+
const srcElements = isRuntimeClassInstanceArray(v) ? v.elements : [v];
|
|
42455
|
+
const [rows, cols] = isRuntimeClassInstanceArray(v) ? v.shape : [1, 1];
|
|
42456
|
+
const className = v.className;
|
|
42457
|
+
let reps;
|
|
42458
|
+
if (repArgs.length === 1) {
|
|
42459
|
+
const arg1 = repArgs[0];
|
|
42460
|
+
if (isRuntimeTensor(arg1)) {
|
|
42461
|
+
reps = Array.from(arg1.data).map((x) => validateSizeArg(x));
|
|
42462
|
+
} else {
|
|
42463
|
+
const n = validateSizeArg(toNumber(arg1));
|
|
42464
|
+
reps = [n, n];
|
|
42465
|
+
}
|
|
42466
|
+
} else {
|
|
42467
|
+
reps = repArgs.map((a) => validateSizeArg(toNumber(a)));
|
|
42468
|
+
}
|
|
42469
|
+
const rRep = reps[0] ?? 1;
|
|
42470
|
+
const cRep = reps.length >= 2 ? reps[1] : reps[0] ?? 1;
|
|
42471
|
+
const newRows = rows * rRep;
|
|
42472
|
+
const newCols = cols * cRep;
|
|
42473
|
+
const out = new Array(Math.max(0, newRows * newCols));
|
|
42474
|
+
for (let J = 0; J < newCols; J++) {
|
|
42475
|
+
for (let I = 0; I < newRows; I++) {
|
|
42476
|
+
const src = srcElements[I % rows + J % cols * rows];
|
|
42477
|
+
out[I + J * newRows] = copyClassInstance(src);
|
|
42478
|
+
}
|
|
42479
|
+
}
|
|
42480
|
+
return out.length === 1 ? out[0] : RTV.classInstanceArray(className, out, [newRows, newCols]);
|
|
42481
|
+
}
|
|
41800
42482
|
defineBuiltin({
|
|
41801
42483
|
name: "repmat",
|
|
41802
42484
|
cases: [
|
|
@@ -41821,6 +42503,8 @@ defineBuiltin({
|
|
|
41821
42503
|
if (args.length < 2)
|
|
41822
42504
|
throw new RuntimeError("repmat requires at least 2 arguments");
|
|
41823
42505
|
let v = args[0];
|
|
42506
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v))
|
|
42507
|
+
return repmatObjects(v, args.slice(1));
|
|
41824
42508
|
if (isRuntimeSparseMatrix(v)) v = sparseToDense(v);
|
|
41825
42509
|
let reps;
|
|
41826
42510
|
if (args.length === 2) {
|
|
@@ -41985,6 +42669,62 @@ defineBuiltin({
|
|
|
41985
42669
|
}
|
|
41986
42670
|
]
|
|
41987
42671
|
});
|
|
42672
|
+
function copyClassInstance(inst) {
|
|
42673
|
+
if (inst.isHandleClass) return inst;
|
|
42674
|
+
return new RuntimeClassInstance(
|
|
42675
|
+
inst.className,
|
|
42676
|
+
new Map(inst.fields),
|
|
42677
|
+
inst.isHandleClass,
|
|
42678
|
+
inst._builtinData
|
|
42679
|
+
);
|
|
42680
|
+
}
|
|
42681
|
+
function repelemObjects(v, repArgs) {
|
|
42682
|
+
const srcElements = isRuntimeClassInstanceArray(v) ? v.elements : [v];
|
|
42683
|
+
const [rows, cols] = isRuntimeClassInstanceArray(v) ? v.shape : [1, 1];
|
|
42684
|
+
const className = v.className;
|
|
42685
|
+
const wrap = (elements, shape) => elements.length === 1 ? elements[0] : RTV.classInstanceArray(className, elements, shape);
|
|
42686
|
+
if (repArgs.length === 1) {
|
|
42687
|
+
const repArg = repArgs[0];
|
|
42688
|
+
if (isRuntimeTensor(repArg) && repArg.data.length > 1) {
|
|
42689
|
+
const counts = repArg.data;
|
|
42690
|
+
if (counts.length !== srcElements.length)
|
|
42691
|
+
throw new RuntimeError(
|
|
42692
|
+
`repelem: counts vector length (${counts.length}) must match the number of elements (${srcElements.length})`
|
|
42693
|
+
);
|
|
42694
|
+
const out3 = [];
|
|
42695
|
+
for (let i = 0; i < srcElements.length; i++) {
|
|
42696
|
+
const c = Math.max(0, Math.round(counts[i]));
|
|
42697
|
+
for (let j = 0; j < c; j++) out3.push(copyClassInstance(srcElements[i]));
|
|
42698
|
+
}
|
|
42699
|
+
const isCol2 = cols === 1 && rows !== 1;
|
|
42700
|
+
return wrap(out3, isCol2 ? [out3.length, 1] : [1, out3.length]);
|
|
42701
|
+
}
|
|
42702
|
+
const n = Math.max(0, Math.round(toNumber(repArg)));
|
|
42703
|
+
const out2 = [];
|
|
42704
|
+
for (const el of srcElements)
|
|
42705
|
+
for (let j = 0; j < n; j++) out2.push(copyClassInstance(el));
|
|
42706
|
+
const isCol = cols === 1 && rows !== 1;
|
|
42707
|
+
return wrap(out2, isCol ? [out2.length, 1] : [1, out2.length]);
|
|
42708
|
+
}
|
|
42709
|
+
const rRep = Math.max(0, Math.round(toNumber(repArgs[0])));
|
|
42710
|
+
const cRep = Math.max(0, Math.round(toNumber(repArgs[1])));
|
|
42711
|
+
const newRows = rows * rRep;
|
|
42712
|
+
const newCols = cols * cRep;
|
|
42713
|
+
const out = new Array(newRows * newCols);
|
|
42714
|
+
for (let c = 0; c < cols; c++) {
|
|
42715
|
+
for (let r = 0; r < rows; r++) {
|
|
42716
|
+
const src = srcElements[c * rows + r];
|
|
42717
|
+
for (let dc = 0; dc < cRep; dc++) {
|
|
42718
|
+
for (let dr = 0; dr < rRep; dr++) {
|
|
42719
|
+
const dstRow = r * rRep + dr;
|
|
42720
|
+
const dstCol = c * cRep + dc;
|
|
42721
|
+
out[dstCol * newRows + dstRow] = copyClassInstance(src);
|
|
42722
|
+
}
|
|
42723
|
+
}
|
|
42724
|
+
}
|
|
42725
|
+
}
|
|
42726
|
+
return wrap(out, [newRows, newCols]);
|
|
42727
|
+
}
|
|
41988
42728
|
defineBuiltin({
|
|
41989
42729
|
name: "repelem",
|
|
41990
42730
|
cases: [
|
|
@@ -41994,6 +42734,8 @@ defineBuiltin({
|
|
|
41994
42734
|
if (args.length < 2)
|
|
41995
42735
|
throw new RuntimeError("repelem requires at least 2 arguments");
|
|
41996
42736
|
const v = args[0];
|
|
42737
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v))
|
|
42738
|
+
return repelemObjects(v, args.slice(1));
|
|
41997
42739
|
if (args.length === 2) {
|
|
41998
42740
|
const repArg = args[1];
|
|
41999
42741
|
if (isRuntimeTensor(repArg) && repArg.data.length > 1) {
|
|
@@ -42116,7 +42858,15 @@ defineBuiltin({
|
|
|
42116
42858
|
}
|
|
42117
42859
|
return RTV.tensor(dataCopy, newShape, imagCopy);
|
|
42118
42860
|
}
|
|
42119
|
-
|
|
42861
|
+
if (isRuntimeCell(v)) {
|
|
42862
|
+
const shape = [...v.shape];
|
|
42863
|
+
while (shape.length > 2 && shape[shape.length - 1] === 1) shape.pop();
|
|
42864
|
+
if (shape.length <= 2) return RTV.cell(v.data, shape);
|
|
42865
|
+
const newShape = shape.filter((d) => d !== 1);
|
|
42866
|
+
while (newShape.length < 2) newShape.push(1);
|
|
42867
|
+
return RTV.cell(v.data, newShape);
|
|
42868
|
+
}
|
|
42869
|
+
return v;
|
|
42120
42870
|
}
|
|
42121
42871
|
}
|
|
42122
42872
|
]
|
|
@@ -42786,6 +43536,8 @@ defineBuiltin({
|
|
|
42786
43536
|
]
|
|
42787
43537
|
});
|
|
42788
43538
|
function bitwiseOp(a, b, op, name) {
|
|
43539
|
+
if (typeof a === "boolean") a = a ? 1 : 0;
|
|
43540
|
+
if (typeof b === "boolean") b = b ? 1 : 0;
|
|
42789
43541
|
if (isRuntimeNumber(a) && isRuntimeNumber(b)) {
|
|
42790
43542
|
return RTV.num(op(Math.round(a), Math.round(b)));
|
|
42791
43543
|
}
|
|
@@ -45053,6 +45805,56 @@ defineBuiltin({
|
|
|
45053
45805
|
}
|
|
45054
45806
|
]
|
|
45055
45807
|
});
|
|
45808
|
+
function froundArray(src) {
|
|
45809
|
+
const out = allocFloat64Array(src.length);
|
|
45810
|
+
for (let i = 0; i < src.length; i++) out[i] = Math.fround(src[i]);
|
|
45811
|
+
return out;
|
|
45812
|
+
}
|
|
45813
|
+
function singleApply(v) {
|
|
45814
|
+
if (isRuntimeChar(v)) {
|
|
45815
|
+
if (v.value.length === 0) return RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
45816
|
+
if (v.value.length === 1)
|
|
45817
|
+
return RTV.num(Math.fround(v.value.charCodeAt(0)));
|
|
45818
|
+
return RTV.row(Array.from(v.value).map((c) => Math.fround(c.charCodeAt(0))));
|
|
45819
|
+
}
|
|
45820
|
+
if (isRuntimeLogical(v)) return RTV.num(v ? 1 : 0);
|
|
45821
|
+
if (isRuntimeNumber(v)) return RTV.num(Math.fround(v));
|
|
45822
|
+
if (isRuntimeComplexNumber(v))
|
|
45823
|
+
return RTV.complex(Math.fround(v.re), Math.fround(v.im));
|
|
45824
|
+
if (isRuntimeTensor(v)) {
|
|
45825
|
+
const imag2 = v.imag ? froundArray(v.imag) : void 0;
|
|
45826
|
+
return RTV.tensor(froundArray(v.data), v.shape.slice(), imag2);
|
|
45827
|
+
}
|
|
45828
|
+
if (isRuntimeClassInstance(v) && v._builtinData !== void 0)
|
|
45829
|
+
return singleApply(v._builtinData);
|
|
45830
|
+
return RTV.num(Math.fround(toNumber(v)));
|
|
45831
|
+
}
|
|
45832
|
+
defineBuiltin({
|
|
45833
|
+
name: "single",
|
|
45834
|
+
cases: [
|
|
45835
|
+
{
|
|
45836
|
+
match: (argTypes) => {
|
|
45837
|
+
if (argTypes.length !== 1) return null;
|
|
45838
|
+
const a = argTypes[0];
|
|
45839
|
+
if (a.kind === "number" || a.kind === "boolean" || a.kind === "char" || a.kind === "class_instance")
|
|
45840
|
+
return [{ kind: "number" }];
|
|
45841
|
+
if (a.kind === "complex_or_number")
|
|
45842
|
+
return [{ kind: "complex_or_number" }];
|
|
45843
|
+
if (a.kind === "tensor")
|
|
45844
|
+
return [
|
|
45845
|
+
{
|
|
45846
|
+
kind: "tensor",
|
|
45847
|
+
isComplex: a.isComplex,
|
|
45848
|
+
shape: a.shape,
|
|
45849
|
+
ndim: a.ndim
|
|
45850
|
+
}
|
|
45851
|
+
];
|
|
45852
|
+
return null;
|
|
45853
|
+
},
|
|
45854
|
+
apply: (args) => singleApply(args[0])
|
|
45855
|
+
}
|
|
45856
|
+
]
|
|
45857
|
+
});
|
|
45056
45858
|
var INT_RANGES = [
|
|
45057
45859
|
{ name: "int8", min: -128, max: 127 },
|
|
45058
45860
|
{ name: "int16", min: -32768, max: 32767 },
|
|
@@ -45607,11 +46409,20 @@ defineBuiltin({
|
|
|
45607
46409
|
},
|
|
45608
46410
|
apply: (args) => {
|
|
45609
46411
|
const v = args[0];
|
|
45610
|
-
|
|
45611
|
-
|
|
45612
|
-
|
|
45613
|
-
return
|
|
45614
|
-
|
|
46412
|
+
const hasField = (name) => {
|
|
46413
|
+
if (isRuntimeStructArray(v)) return v.fieldNames.includes(name);
|
|
46414
|
+
if (!isRuntimeStruct(v) && !isRuntimeClassInstance(v)) return false;
|
|
46415
|
+
return v.fields.has(name);
|
|
46416
|
+
};
|
|
46417
|
+
if (isRuntimeCell(args[1])) {
|
|
46418
|
+
const cell = args[1];
|
|
46419
|
+
const result = allocFloat64Array(cell.data.length);
|
|
46420
|
+
for (let i = 0; i < cell.data.length; i++) {
|
|
46421
|
+
result[i] = hasField(toString(cell.data[i])) ? 1 : 0;
|
|
46422
|
+
}
|
|
46423
|
+
return new RuntimeTensor(result, cell.shape.slice(), void 0, true);
|
|
46424
|
+
}
|
|
46425
|
+
return RTV.logical(hasField(toString(args[1])));
|
|
45615
46426
|
}
|
|
45616
46427
|
}
|
|
45617
46428
|
]
|
|
@@ -45728,7 +46539,7 @@ function regexpImpl(caseSensitive, name, args, nargout) {
|
|
|
45728
46539
|
if (outModes.length === 0) {
|
|
45729
46540
|
outModes.push("start", "end", "tokenextents", "match", "tokens", "names");
|
|
45730
46541
|
}
|
|
45731
|
-
const flags = caseSensitive ? "
|
|
46542
|
+
const flags = caseSensitive ? "gs" : "gis";
|
|
45732
46543
|
const re = new RegExp(pat, flags);
|
|
45733
46544
|
const starts = [];
|
|
45734
46545
|
const ends = [];
|
|
@@ -46448,6 +47259,13 @@ registerIBuiltin({
|
|
|
46448
47259
|
if (args.length === 1) return RTV.cell([A], [1, 1]);
|
|
46449
47260
|
A = RTV.tensor(allocFloat64Array([A ? 1 : 0]), [1, 1]);
|
|
46450
47261
|
}
|
|
47262
|
+
if (isRuntimeStruct(A)) {
|
|
47263
|
+
return RTV.cell([A], [1, 1]);
|
|
47264
|
+
}
|
|
47265
|
+
if (isRuntimeStructArray(A)) {
|
|
47266
|
+
const elems = A.elements;
|
|
47267
|
+
return RTV.cell([...elems], [1, elems.length]);
|
|
47268
|
+
}
|
|
46451
47269
|
if (!isRuntimeTensor(A))
|
|
46452
47270
|
throw new RuntimeError(
|
|
46453
47271
|
"num2cell: first argument must be a numeric array"
|
|
@@ -46571,6 +47389,69 @@ registerIBuiltin({
|
|
|
46571
47389
|
};
|
|
46572
47390
|
}
|
|
46573
47391
|
});
|
|
47392
|
+
registerIBuiltin({
|
|
47393
|
+
name: "getfield",
|
|
47394
|
+
resolve: (argTypes) => {
|
|
47395
|
+
if (argTypes.length < 2) return null;
|
|
47396
|
+
return {
|
|
47397
|
+
outputTypes: [{ kind: "unknown" }],
|
|
47398
|
+
apply: (args) => {
|
|
47399
|
+
let v = args[0];
|
|
47400
|
+
for (let i = 1; i < args.length; i++) {
|
|
47401
|
+
if (isRuntimeCell(args[i]))
|
|
47402
|
+
throw new RuntimeError(
|
|
47403
|
+
"getfield: index ({}) subscripts are not supported"
|
|
47404
|
+
);
|
|
47405
|
+
if (!isRuntimeStruct(v))
|
|
47406
|
+
throw new RuntimeError("getfield: argument must be a structure");
|
|
47407
|
+
const name = toString(args[i]);
|
|
47408
|
+
if (!v.fields.has(name))
|
|
47409
|
+
throw new RuntimeError(
|
|
47410
|
+
`Reference to non-existent field '${name}'.`
|
|
47411
|
+
);
|
|
47412
|
+
v = v.fields.get(name);
|
|
47413
|
+
}
|
|
47414
|
+
return v;
|
|
47415
|
+
}
|
|
47416
|
+
};
|
|
47417
|
+
}
|
|
47418
|
+
});
|
|
47419
|
+
registerIBuiltin({
|
|
47420
|
+
name: "setfield",
|
|
47421
|
+
resolve: (argTypes) => {
|
|
47422
|
+
if (argTypes.length < 3) return null;
|
|
47423
|
+
return {
|
|
47424
|
+
outputTypes: [{ kind: "struct", fields: {} }],
|
|
47425
|
+
apply: (args) => {
|
|
47426
|
+
const value = args[args.length - 1];
|
|
47427
|
+
const fieldArgs = args.slice(1, args.length - 1);
|
|
47428
|
+
const setChain = (s, depth) => {
|
|
47429
|
+
const fa = fieldArgs[depth];
|
|
47430
|
+
if (isRuntimeCell(fa))
|
|
47431
|
+
throw new RuntimeError(
|
|
47432
|
+
"setfield: index ({}) subscripts are not supported"
|
|
47433
|
+
);
|
|
47434
|
+
const name = toString(fa);
|
|
47435
|
+
const base = isRuntimeStruct(s) ? s.fields : /* @__PURE__ */ new Map();
|
|
47436
|
+
if (!isRuntimeStruct(s) && !(isRuntimeTensor(s) && s.data.length === 0))
|
|
47437
|
+
throw new RuntimeError("setfield: argument must be a structure");
|
|
47438
|
+
const newFields = new Map(base);
|
|
47439
|
+
if (depth === fieldArgs.length - 1) {
|
|
47440
|
+
newFields.set(name, value);
|
|
47441
|
+
} else {
|
|
47442
|
+
const child = newFields.get(name);
|
|
47443
|
+
newFields.set(
|
|
47444
|
+
name,
|
|
47445
|
+
setChain(child ?? RTV.struct(/* @__PURE__ */ new Map()), depth + 1)
|
|
47446
|
+
);
|
|
47447
|
+
}
|
|
47448
|
+
return RTV.struct(newFields);
|
|
47449
|
+
};
|
|
47450
|
+
return setChain(args[0], 0);
|
|
47451
|
+
}
|
|
47452
|
+
};
|
|
47453
|
+
}
|
|
47454
|
+
});
|
|
46574
47455
|
registerIBuiltin({
|
|
46575
47456
|
name: "namedargs2cell",
|
|
46576
47457
|
resolve: (argTypes) => {
|
|
@@ -46592,6 +47473,10 @@ registerIBuiltin({
|
|
|
46592
47473
|
};
|
|
46593
47474
|
}
|
|
46594
47475
|
});
|
|
47476
|
+
function rmfieldNames(arg) {
|
|
47477
|
+
if (isRuntimeCell(arg)) return arg.data.map(toString);
|
|
47478
|
+
return [toString(arg)];
|
|
47479
|
+
}
|
|
46595
47480
|
registerIBuiltin({
|
|
46596
47481
|
name: "rmfield",
|
|
46597
47482
|
resolve: (argTypes) => {
|
|
@@ -46600,25 +47485,26 @@ registerIBuiltin({
|
|
|
46600
47485
|
outputTypes: [{ kind: "struct", fields: {} }],
|
|
46601
47486
|
apply: (args) => {
|
|
46602
47487
|
const v = args[0];
|
|
47488
|
+
const names = rmfieldNames(args[1]);
|
|
46603
47489
|
if (isRuntimeStructArray(v)) {
|
|
46604
|
-
const
|
|
46605
|
-
|
|
46606
|
-
|
|
46607
|
-
const newFieldNames = v.fieldNames.filter((n) => n
|
|
47490
|
+
for (const name of names)
|
|
47491
|
+
if (!v.fieldNames.includes(name))
|
|
47492
|
+
throw new RuntimeError(`rmfield: field '${name}' does not exist`);
|
|
47493
|
+
const newFieldNames = v.fieldNames.filter((n) => !names.includes(n));
|
|
46608
47494
|
const newElements = v.elements.map((el) => {
|
|
46609
47495
|
const newFields2 = new Map(el.fields);
|
|
46610
|
-
newFields2.delete(
|
|
47496
|
+
for (const name of names) newFields2.delete(name);
|
|
46611
47497
|
return RTV.struct(newFields2);
|
|
46612
47498
|
});
|
|
46613
47499
|
return RTV.structArray(newFieldNames, newElements);
|
|
46614
47500
|
}
|
|
46615
47501
|
if (!isRuntimeStruct(v))
|
|
46616
47502
|
throw new RuntimeError("rmfield: first argument must be a struct");
|
|
46617
|
-
const name
|
|
46618
|
-
|
|
46619
|
-
|
|
47503
|
+
for (const name of names)
|
|
47504
|
+
if (!v.fields.has(name))
|
|
47505
|
+
throw new RuntimeError(`rmfield: field '${name}' does not exist`);
|
|
46620
47506
|
const newFields = new Map(v.fields);
|
|
46621
|
-
newFields.delete(name);
|
|
47507
|
+
for (const name of names) newFields.delete(name);
|
|
46622
47508
|
return RTV.struct(newFields);
|
|
46623
47509
|
}
|
|
46624
47510
|
};
|
|
@@ -47259,6 +48145,23 @@ registerIBuiltin({
|
|
|
47259
48145
|
}
|
|
47260
48146
|
})
|
|
47261
48147
|
});
|
|
48148
|
+
registerIBuiltin({
|
|
48149
|
+
name: "spalloc",
|
|
48150
|
+
resolve: () => ({
|
|
48151
|
+
outputTypes: [{ kind: "unknown" }],
|
|
48152
|
+
apply: (args) => {
|
|
48153
|
+
const m = args.length >= 1 ? Math.round(toNumber(args[0])) : 0;
|
|
48154
|
+
const n = args.length >= 2 ? Math.round(toNumber(args[1])) : 0;
|
|
48155
|
+
return RTV.sparseMatrix(
|
|
48156
|
+
m,
|
|
48157
|
+
n,
|
|
48158
|
+
new Int32Array(0),
|
|
48159
|
+
new Int32Array(n + 1),
|
|
48160
|
+
allocFloat64Array(0)
|
|
48161
|
+
);
|
|
48162
|
+
}
|
|
48163
|
+
})
|
|
48164
|
+
});
|
|
47262
48165
|
registerIBuiltin({
|
|
47263
48166
|
name: "speye",
|
|
47264
48167
|
resolve: () => ({
|
|
@@ -47544,6 +48447,598 @@ registerIBuiltin({
|
|
|
47544
48447
|
}
|
|
47545
48448
|
})
|
|
47546
48449
|
});
|
|
48450
|
+
var SPPARMS_KEYS = [
|
|
48451
|
+
"spumoni",
|
|
48452
|
+
"thr_rel",
|
|
48453
|
+
"thr_abs",
|
|
48454
|
+
"exact_d",
|
|
48455
|
+
"supernd",
|
|
48456
|
+
"rreduce",
|
|
48457
|
+
"wh_frac",
|
|
48458
|
+
"autommd",
|
|
48459
|
+
"autoamd",
|
|
48460
|
+
"piv_tol",
|
|
48461
|
+
"bandden",
|
|
48462
|
+
"umfpack",
|
|
48463
|
+
"sym_tol",
|
|
48464
|
+
"ldl_tol",
|
|
48465
|
+
"usema57",
|
|
48466
|
+
"spqrtol",
|
|
48467
|
+
"sp_ctor",
|
|
48468
|
+
"reorder",
|
|
48469
|
+
"no_redo"
|
|
48470
|
+
];
|
|
48471
|
+
var SPPARMS_DEFAULTS = [
|
|
48472
|
+
0,
|
|
48473
|
+
1.1,
|
|
48474
|
+
1,
|
|
48475
|
+
0,
|
|
48476
|
+
3,
|
|
48477
|
+
3,
|
|
48478
|
+
0.5,
|
|
48479
|
+
1,
|
|
48480
|
+
1,
|
|
48481
|
+
0.1,
|
|
48482
|
+
0.5,
|
|
48483
|
+
1,
|
|
48484
|
+
1e-3,
|
|
48485
|
+
0.01,
|
|
48486
|
+
1,
|
|
48487
|
+
-2,
|
|
48488
|
+
0,
|
|
48489
|
+
0,
|
|
48490
|
+
0
|
|
48491
|
+
];
|
|
48492
|
+
var spparmsState = Float64Array.from(SPPARMS_DEFAULTS);
|
|
48493
|
+
function spparmsVector() {
|
|
48494
|
+
return RTV.tensor(allocFloat64Array(Array.from(spparmsState)), [
|
|
48495
|
+
spparmsState.length,
|
|
48496
|
+
1
|
|
48497
|
+
]);
|
|
48498
|
+
}
|
|
48499
|
+
registerIBuiltin({
|
|
48500
|
+
name: "spparms",
|
|
48501
|
+
resolve: (argTypes, nargout) => {
|
|
48502
|
+
if (argTypes.length > 2) return null;
|
|
48503
|
+
const tensorOut = { kind: "tensor", isComplex: false };
|
|
48504
|
+
const outputTypes = nargout >= 2 ? [{ kind: "char" }, tensorOut] : [tensorOut];
|
|
48505
|
+
return {
|
|
48506
|
+
outputTypes,
|
|
48507
|
+
apply: (args, n) => {
|
|
48508
|
+
if (args.length === 0) {
|
|
48509
|
+
if (n >= 2) {
|
|
48510
|
+
const width = Math.max(...SPPARMS_KEYS.map((k) => k.length));
|
|
48511
|
+
const padded = SPPARMS_KEYS.map((k) => k.padEnd(width)).join("");
|
|
48512
|
+
return [
|
|
48513
|
+
new RuntimeChar(padded, [SPPARMS_KEYS.length, width]),
|
|
48514
|
+
spparmsVector()
|
|
48515
|
+
];
|
|
48516
|
+
}
|
|
48517
|
+
return spparmsVector();
|
|
48518
|
+
}
|
|
48519
|
+
const first = args[0];
|
|
48520
|
+
if (isRuntimeChar(first) || isRuntimeString(first)) {
|
|
48521
|
+
const key = parseStringArgLower(first);
|
|
48522
|
+
if (args.length >= 2) {
|
|
48523
|
+
const idx2 = SPPARMS_KEYS.indexOf(key);
|
|
48524
|
+
if (idx2 >= 0) spparmsState[idx2] = toNumber(args[1]);
|
|
48525
|
+
return RTV.num(0);
|
|
48526
|
+
}
|
|
48527
|
+
if (key === "default") {
|
|
48528
|
+
spparmsState = Float64Array.from(SPPARMS_DEFAULTS);
|
|
48529
|
+
return RTV.num(0);
|
|
48530
|
+
}
|
|
48531
|
+
if (key === "tight") {
|
|
48532
|
+
return RTV.num(0);
|
|
48533
|
+
}
|
|
48534
|
+
const idx = SPPARMS_KEYS.indexOf(key);
|
|
48535
|
+
if (idx >= 0) return RTV.num(spparmsState[idx]);
|
|
48536
|
+
throw new RuntimeError(`spparms: unknown parameter '${key}'`);
|
|
48537
|
+
}
|
|
48538
|
+
const vals = isRuntimeNumber(first) ? [first] : isRuntimeTensor(first) ? Array.from(first.data) : null;
|
|
48539
|
+
if (vals === null)
|
|
48540
|
+
throw new RuntimeError(
|
|
48541
|
+
"spparms: argument must be a parameter name or value vector"
|
|
48542
|
+
);
|
|
48543
|
+
const next = Float64Array.from(spparmsState);
|
|
48544
|
+
for (let i = 0; i < Math.min(vals.length, next.length); i++)
|
|
48545
|
+
next[i] = vals[i];
|
|
48546
|
+
spparmsState = next;
|
|
48547
|
+
return RTV.num(0);
|
|
48548
|
+
}
|
|
48549
|
+
};
|
|
48550
|
+
}
|
|
48551
|
+
});
|
|
48552
|
+
|
|
48553
|
+
// src/numbl-core/interpreter/builtins/graph.ts
|
|
48554
|
+
function isGraph(v) {
|
|
48555
|
+
return isRuntimeClassInstance(v) && v.className === "graph";
|
|
48556
|
+
}
|
|
48557
|
+
function requireGraph(v, fn) {
|
|
48558
|
+
if (!isGraph(v)) {
|
|
48559
|
+
throw new RuntimeError(`${fn}: first argument must be a graph`);
|
|
48560
|
+
}
|
|
48561
|
+
return v;
|
|
48562
|
+
}
|
|
48563
|
+
function graphN(g) {
|
|
48564
|
+
return toNumber(g.fields.get("_n") ?? 0);
|
|
48565
|
+
}
|
|
48566
|
+
function graphWeighted(g) {
|
|
48567
|
+
const w = g.fields.get("_weighted");
|
|
48568
|
+
return w === true;
|
|
48569
|
+
}
|
|
48570
|
+
function graphAdj(g) {
|
|
48571
|
+
const a = g.fields.get("_A");
|
|
48572
|
+
if (a === void 0 || !isRuntimeSparseMatrix(a)) {
|
|
48573
|
+
throw new RuntimeError("graph: corrupt internal adjacency");
|
|
48574
|
+
}
|
|
48575
|
+
return a;
|
|
48576
|
+
}
|
|
48577
|
+
function buildSymAdj(n, edges) {
|
|
48578
|
+
const triplets = [];
|
|
48579
|
+
for (const e of edges) {
|
|
48580
|
+
if (e.w === 0) continue;
|
|
48581
|
+
const u = e.u - 1;
|
|
48582
|
+
const v = e.v - 1;
|
|
48583
|
+
if (u === v) {
|
|
48584
|
+
triplets.push({ col: u, row: u, val: e.w });
|
|
48585
|
+
} else {
|
|
48586
|
+
triplets.push({ col: v, row: u, val: e.w });
|
|
48587
|
+
triplets.push({ col: u, row: v, val: e.w });
|
|
48588
|
+
}
|
|
48589
|
+
}
|
|
48590
|
+
triplets.sort((a, b) => a.col - b.col || a.row - b.row);
|
|
48591
|
+
const ir = [];
|
|
48592
|
+
const pr = [];
|
|
48593
|
+
const cols = [];
|
|
48594
|
+
let prevCol = -1;
|
|
48595
|
+
let prevRow = -1;
|
|
48596
|
+
for (const t of triplets) {
|
|
48597
|
+
if (t.col === prevCol && t.row === prevRow) {
|
|
48598
|
+
pr[pr.length - 1] += t.val;
|
|
48599
|
+
} else {
|
|
48600
|
+
ir.push(t.row);
|
|
48601
|
+
pr.push(t.val);
|
|
48602
|
+
cols.push(t.col);
|
|
48603
|
+
prevCol = t.col;
|
|
48604
|
+
prevRow = t.row;
|
|
48605
|
+
}
|
|
48606
|
+
}
|
|
48607
|
+
const jc = new Int32Array(n + 1);
|
|
48608
|
+
let ci = 0;
|
|
48609
|
+
for (let c = 0; c < n; c++) {
|
|
48610
|
+
jc[c] = ci;
|
|
48611
|
+
while (ci < cols.length && cols[ci] === c) ci++;
|
|
48612
|
+
}
|
|
48613
|
+
jc[n] = ci;
|
|
48614
|
+
return RTV.sparseMatrix(n, n, new Int32Array(ir), jc, allocFloat64Array(pr));
|
|
48615
|
+
}
|
|
48616
|
+
function makeGraph(n, edges, weighted) {
|
|
48617
|
+
const fields = /* @__PURE__ */ new Map();
|
|
48618
|
+
fields.set("_n", n);
|
|
48619
|
+
fields.set("_A", buildSymAdj(n, edges));
|
|
48620
|
+
fields.set("_weighted", weighted);
|
|
48621
|
+
return new RuntimeClassInstance("graph", fields, false);
|
|
48622
|
+
}
|
|
48623
|
+
function eachNeighbor(A, c, cb) {
|
|
48624
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) {
|
|
48625
|
+
const r = A.ir[k];
|
|
48626
|
+
if (r !== c) cb(r, A.pr[k]);
|
|
48627
|
+
}
|
|
48628
|
+
}
|
|
48629
|
+
function edgesFromAdj(A) {
|
|
48630
|
+
const edges = [];
|
|
48631
|
+
for (let c = 0; c < A.n; c++) {
|
|
48632
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) {
|
|
48633
|
+
const r = A.ir[k];
|
|
48634
|
+
if (r < c) edges.push({ u: r + 1, v: c + 1, w: A.pr[k] });
|
|
48635
|
+
else if (r === c) edges.push({ u: r + 1, v: r + 1, w: A.pr[k] });
|
|
48636
|
+
}
|
|
48637
|
+
}
|
|
48638
|
+
return edges;
|
|
48639
|
+
}
|
|
48640
|
+
function squareDim(A, fn) {
|
|
48641
|
+
if (isRuntimeNumber(A) || isRuntimeLogical(A)) return 1;
|
|
48642
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
48643
|
+
if (A.m !== A.n) throw new RuntimeError(`${fn}: adjacency must be square`);
|
|
48644
|
+
return A.n;
|
|
48645
|
+
}
|
|
48646
|
+
if (isRuntimeTensor(A)) {
|
|
48647
|
+
const rows = A.shape[0] ?? 1;
|
|
48648
|
+
const cols = A.shape[1] ?? 1;
|
|
48649
|
+
if (rows !== cols)
|
|
48650
|
+
throw new RuntimeError(`${fn}: adjacency must be square`);
|
|
48651
|
+
return rows;
|
|
48652
|
+
}
|
|
48653
|
+
throw new RuntimeError(`${fn}: adjacency must be a numeric matrix`);
|
|
48654
|
+
}
|
|
48655
|
+
function takeEntry(r, c, triangle) {
|
|
48656
|
+
if (r === c) return true;
|
|
48657
|
+
if (triangle === "lower") return r > c;
|
|
48658
|
+
return r < c;
|
|
48659
|
+
}
|
|
48660
|
+
function adjToEdges(A, omitSelfLoops, triangle, fn) {
|
|
48661
|
+
const n = squareDim(A, fn);
|
|
48662
|
+
const weighted = !(isRuntimeTensor(A) && A._isLogical);
|
|
48663
|
+
const edges = [];
|
|
48664
|
+
const push = (r, c, val) => {
|
|
48665
|
+
if (val === 0) return;
|
|
48666
|
+
if (r === c) {
|
|
48667
|
+
if (!omitSelfLoops) edges.push({ u: r + 1, v: r + 1, w: val });
|
|
48668
|
+
} else if (takeEntry(r, c, triangle)) {
|
|
48669
|
+
edges.push({ u: Math.min(r, c) + 1, v: Math.max(r, c) + 1, w: val });
|
|
48670
|
+
}
|
|
48671
|
+
};
|
|
48672
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
48673
|
+
for (let c = 0; c < A.n; c++) {
|
|
48674
|
+
for (let k = A.jc[c]; k < A.jc[c + 1]; k++) push(A.ir[k], c, A.pr[k]);
|
|
48675
|
+
}
|
|
48676
|
+
} else if (isRuntimeTensor(A)) {
|
|
48677
|
+
const m = A.shape[0] ?? 1;
|
|
48678
|
+
for (let c = 0; c < n; c++) {
|
|
48679
|
+
for (let r = 0; r < n; r++) {
|
|
48680
|
+
const val = A.data[c * m + r];
|
|
48681
|
+
if (val !== 0) push(r, c, val);
|
|
48682
|
+
}
|
|
48683
|
+
}
|
|
48684
|
+
} else if (isRuntimeNumber(A) || isRuntimeLogical(A)) {
|
|
48685
|
+
const val = isRuntimeNumber(A) ? A : A ? 1 : 0;
|
|
48686
|
+
if (val !== 0) push(0, 0, val);
|
|
48687
|
+
}
|
|
48688
|
+
return { n, edges, weighted };
|
|
48689
|
+
}
|
|
48690
|
+
function isNumericArg2(v) {
|
|
48691
|
+
return isRuntimeNumber(v) || isRuntimeLogical(v) || isRuntimeTensor(v) || isRuntimeSparseMatrix(v);
|
|
48692
|
+
}
|
|
48693
|
+
function toNumArray2(v) {
|
|
48694
|
+
if (isRuntimeNumber(v)) return [v];
|
|
48695
|
+
if (isRuntimeLogical(v)) return [v ? 1 : 0];
|
|
48696
|
+
if (isRuntimeTensor(v)) return Array.from(v.data);
|
|
48697
|
+
throw new RuntimeError("graph: node/weight arguments must be numeric");
|
|
48698
|
+
}
|
|
48699
|
+
function argString(v) {
|
|
48700
|
+
if (isRuntimeString(v)) return v;
|
|
48701
|
+
if (isRuntimeChar(v)) return v.value;
|
|
48702
|
+
return null;
|
|
48703
|
+
}
|
|
48704
|
+
registerIBuiltin({
|
|
48705
|
+
name: "graph",
|
|
48706
|
+
help: {
|
|
48707
|
+
signatures: [
|
|
48708
|
+
"G = graph(A)",
|
|
48709
|
+
"G = graph(A, 'omitselfloops')",
|
|
48710
|
+
"G = graph(A, 'upper' | 'lower')",
|
|
48711
|
+
"G = graph(s, t)",
|
|
48712
|
+
"G = graph(s, t, w)",
|
|
48713
|
+
"G = graph(s, t, w, num)"
|
|
48714
|
+
],
|
|
48715
|
+
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."
|
|
48716
|
+
},
|
|
48717
|
+
resolve: () => ({
|
|
48718
|
+
outputTypes: [
|
|
48719
|
+
{
|
|
48720
|
+
kind: "class_instance",
|
|
48721
|
+
className: "graph",
|
|
48722
|
+
isHandleClass: false,
|
|
48723
|
+
fields: {}
|
|
48724
|
+
}
|
|
48725
|
+
],
|
|
48726
|
+
apply: (args) => {
|
|
48727
|
+
if (args.length === 0) return makeGraph(0, [], false);
|
|
48728
|
+
if (args.length >= 2 && isNumericArg2(args[1])) {
|
|
48729
|
+
const s = toNumArray2(args[0]);
|
|
48730
|
+
const t = toNumArray2(args[1]);
|
|
48731
|
+
if (s.length !== t.length) {
|
|
48732
|
+
throw new RuntimeError("graph: s and t must have the same length");
|
|
48733
|
+
}
|
|
48734
|
+
let weighted2 = false;
|
|
48735
|
+
let w = null;
|
|
48736
|
+
let num = null;
|
|
48737
|
+
let omitSelfLoops2 = false;
|
|
48738
|
+
if (args.length >= 3 && isNumericArg2(args[2])) {
|
|
48739
|
+
w = toNumArray2(args[2]);
|
|
48740
|
+
weighted2 = true;
|
|
48741
|
+
if (args.length >= 4 && isNumericArg2(args[3])) {
|
|
48742
|
+
num = Math.floor(toNumber(args[3]));
|
|
48743
|
+
}
|
|
48744
|
+
}
|
|
48745
|
+
for (let i = 2; i < args.length; i++) {
|
|
48746
|
+
const str = argString(args[i]);
|
|
48747
|
+
if (str && str.toLowerCase() === "omitselfloops")
|
|
48748
|
+
omitSelfLoops2 = true;
|
|
48749
|
+
}
|
|
48750
|
+
let n2 = num ?? 0;
|
|
48751
|
+
for (let i = 0; i < s.length; i++) n2 = Math.max(n2, s[i], t[i]);
|
|
48752
|
+
const edges2 = [];
|
|
48753
|
+
for (let i = 0; i < s.length; i++) {
|
|
48754
|
+
const u = Math.min(s[i], t[i]);
|
|
48755
|
+
const v = Math.max(s[i], t[i]);
|
|
48756
|
+
if (omitSelfLoops2 && u === v) continue;
|
|
48757
|
+
edges2.push({ u, v, w: w ? w[w.length === 1 ? 0 : i] : 1 });
|
|
48758
|
+
}
|
|
48759
|
+
return makeGraph(n2, edges2, weighted2);
|
|
48760
|
+
}
|
|
48761
|
+
let omitSelfLoops = false;
|
|
48762
|
+
let triangle = "sym";
|
|
48763
|
+
for (let i = 1; i < args.length; i++) {
|
|
48764
|
+
const str = argString(args[i]);
|
|
48765
|
+
if (!str) continue;
|
|
48766
|
+
const lc = str.toLowerCase();
|
|
48767
|
+
if (lc === "omitselfloops") omitSelfLoops = true;
|
|
48768
|
+
else if (lc === "upper") triangle = "upper";
|
|
48769
|
+
else if (lc === "lower") triangle = "lower";
|
|
48770
|
+
}
|
|
48771
|
+
const { n, edges, weighted } = adjToEdges(
|
|
48772
|
+
args[0],
|
|
48773
|
+
omitSelfLoops,
|
|
48774
|
+
triangle,
|
|
48775
|
+
"graph"
|
|
48776
|
+
);
|
|
48777
|
+
return makeGraph(n, edges, weighted);
|
|
48778
|
+
}
|
|
48779
|
+
})
|
|
48780
|
+
});
|
|
48781
|
+
registerIBuiltin({
|
|
48782
|
+
name: "conncomp",
|
|
48783
|
+
help: {
|
|
48784
|
+
signatures: ["bins = conncomp(G)", "[bins, binsizes] = conncomp(G)"],
|
|
48785
|
+
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."
|
|
48786
|
+
},
|
|
48787
|
+
resolve: () => ({
|
|
48788
|
+
outputTypes: [{ kind: "unknown" }, { kind: "unknown" }],
|
|
48789
|
+
apply: (args, nargout) => {
|
|
48790
|
+
const g = requireGraph(args[0], "conncomp");
|
|
48791
|
+
const n = graphN(g);
|
|
48792
|
+
const A = graphAdj(g);
|
|
48793
|
+
const bins = new Float64Array(n);
|
|
48794
|
+
const sizes = [];
|
|
48795
|
+
let comp = 0;
|
|
48796
|
+
const stack = [];
|
|
48797
|
+
for (let start = 0; start < n; start++) {
|
|
48798
|
+
if (bins[start] !== 0) continue;
|
|
48799
|
+
comp++;
|
|
48800
|
+
let count = 0;
|
|
48801
|
+
bins[start] = comp;
|
|
48802
|
+
stack.length = 0;
|
|
48803
|
+
stack.push(start);
|
|
48804
|
+
while (stack.length > 0) {
|
|
48805
|
+
const node = stack.pop();
|
|
48806
|
+
count++;
|
|
48807
|
+
eachNeighbor(A, node, (r) => {
|
|
48808
|
+
if (bins[r] === 0) {
|
|
48809
|
+
bins[r] = comp;
|
|
48810
|
+
stack.push(r);
|
|
48811
|
+
}
|
|
48812
|
+
});
|
|
48813
|
+
}
|
|
48814
|
+
sizes.push(count);
|
|
48815
|
+
}
|
|
48816
|
+
const binsT = RTV.tensor(bins, [1, n]);
|
|
48817
|
+
if (nargout >= 2) {
|
|
48818
|
+
return [binsT, RTV.tensor(allocFloat64Array(sizes), [1, sizes.length])];
|
|
48819
|
+
}
|
|
48820
|
+
return binsT;
|
|
48821
|
+
}
|
|
48822
|
+
})
|
|
48823
|
+
});
|
|
48824
|
+
registerIBuiltin({
|
|
48825
|
+
name: "laplacian",
|
|
48826
|
+
help: {
|
|
48827
|
+
signatures: ["L = laplacian(G)"],
|
|
48828
|
+
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."
|
|
48829
|
+
},
|
|
48830
|
+
resolve: () => ({
|
|
48831
|
+
outputTypes: [{ kind: "unknown" }],
|
|
48832
|
+
apply: (args) => {
|
|
48833
|
+
const g = requireGraph(args[0], "laplacian");
|
|
48834
|
+
const n = graphN(g);
|
|
48835
|
+
const A = graphAdj(g);
|
|
48836
|
+
const edges = [];
|
|
48837
|
+
for (let c = 0; c < n; c++) {
|
|
48838
|
+
let degree = 0;
|
|
48839
|
+
eachNeighbor(A, c, (r) => {
|
|
48840
|
+
degree++;
|
|
48841
|
+
if (r < c) edges.push({ u: r + 1, v: c + 1, w: -1 });
|
|
48842
|
+
});
|
|
48843
|
+
edges.push({ u: c + 1, v: c + 1, w: degree });
|
|
48844
|
+
}
|
|
48845
|
+
return buildSymAdj(n, edges);
|
|
48846
|
+
}
|
|
48847
|
+
})
|
|
48848
|
+
});
|
|
48849
|
+
registerIBuiltin({
|
|
48850
|
+
name: "addedge",
|
|
48851
|
+
help: {
|
|
48852
|
+
signatures: ["H = addedge(G, s, t)", "H = addedge(G, s, t, w)"],
|
|
48853
|
+
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."
|
|
48854
|
+
},
|
|
48855
|
+
resolve: () => ({
|
|
48856
|
+
outputTypes: [
|
|
48857
|
+
{
|
|
48858
|
+
kind: "class_instance",
|
|
48859
|
+
className: "graph",
|
|
48860
|
+
isHandleClass: false,
|
|
48861
|
+
fields: {}
|
|
48862
|
+
}
|
|
48863
|
+
],
|
|
48864
|
+
apply: (args) => {
|
|
48865
|
+
const g = requireGraph(args[0], "addedge");
|
|
48866
|
+
if (args.length < 3) {
|
|
48867
|
+
throw new RuntimeError("addedge: requires nodes s and t");
|
|
48868
|
+
}
|
|
48869
|
+
const weighted = graphWeighted(g);
|
|
48870
|
+
const s = toNumArray2(args[1]);
|
|
48871
|
+
const t = toNumArray2(args[2]);
|
|
48872
|
+
if (s.length !== t.length) {
|
|
48873
|
+
throw new RuntimeError("addedge: s and t must have the same length");
|
|
48874
|
+
}
|
|
48875
|
+
let w = null;
|
|
48876
|
+
if (args.length >= 4) {
|
|
48877
|
+
w = toNumArray2(args[3]);
|
|
48878
|
+
} else if (weighted) {
|
|
48879
|
+
throw new RuntimeError(
|
|
48880
|
+
"addedge: Must specify weights when adding an edge to a weighted graph."
|
|
48881
|
+
);
|
|
48882
|
+
}
|
|
48883
|
+
const edges = edgesFromAdj(graphAdj(g));
|
|
48884
|
+
let n = graphN(g);
|
|
48885
|
+
for (let i = 0; i < s.length; i++) {
|
|
48886
|
+
const u = Math.min(s[i], t[i]);
|
|
48887
|
+
const v = Math.max(s[i], t[i]);
|
|
48888
|
+
n = Math.max(n, u, v);
|
|
48889
|
+
edges.push({ u, v, w: w ? w[w.length === 1 ? 0 : i] : 1 });
|
|
48890
|
+
}
|
|
48891
|
+
return makeGraph(n, edges, weighted);
|
|
48892
|
+
}
|
|
48893
|
+
})
|
|
48894
|
+
});
|
|
48895
|
+
registerIBuiltin({
|
|
48896
|
+
name: "numnodes",
|
|
48897
|
+
help: {
|
|
48898
|
+
signatures: ["n = numnodes(G)"],
|
|
48899
|
+
description: "Number of nodes in graph G."
|
|
48900
|
+
},
|
|
48901
|
+
resolve: () => ({
|
|
48902
|
+
outputTypes: [{ kind: "number" }],
|
|
48903
|
+
apply: (args) => RTV.num(graphN(requireGraph(args[0], "numnodes")))
|
|
48904
|
+
})
|
|
48905
|
+
});
|
|
48906
|
+
registerIBuiltin({
|
|
48907
|
+
name: "numedges",
|
|
48908
|
+
help: {
|
|
48909
|
+
signatures: ["m = numedges(G)"],
|
|
48910
|
+
description: "Number of edges in graph G."
|
|
48911
|
+
},
|
|
48912
|
+
resolve: () => ({
|
|
48913
|
+
outputTypes: [{ kind: "number" }],
|
|
48914
|
+
apply: (args) => {
|
|
48915
|
+
const g = requireGraph(args[0], "numedges");
|
|
48916
|
+
return RTV.num(edgesFromAdj(graphAdj(g)).length);
|
|
48917
|
+
}
|
|
48918
|
+
})
|
|
48919
|
+
});
|
|
48920
|
+
registerIBuiltin({
|
|
48921
|
+
name: "degree",
|
|
48922
|
+
help: {
|
|
48923
|
+
signatures: ["d = degree(G)"],
|
|
48924
|
+
description: "Degree of each node in graph G, returned as a column vector of edge counts (self-loops excluded)."
|
|
48925
|
+
},
|
|
48926
|
+
resolve: () => ({
|
|
48927
|
+
outputTypes: [{ kind: "unknown" }],
|
|
48928
|
+
apply: (args) => {
|
|
48929
|
+
const g = requireGraph(args[0], "degree");
|
|
48930
|
+
const n = graphN(g);
|
|
48931
|
+
const A = graphAdj(g);
|
|
48932
|
+
const d = new Float64Array(n);
|
|
48933
|
+
for (let c = 0; c < n; c++) eachNeighbor(A, c, () => d[c] += 1);
|
|
48934
|
+
return RTV.tensor(d, [n, 1]);
|
|
48935
|
+
}
|
|
48936
|
+
})
|
|
48937
|
+
});
|
|
48938
|
+
|
|
48939
|
+
// src/numbl-core/interpreter/builtins/gallery.ts
|
|
48940
|
+
function toNumArray3(v, what) {
|
|
48941
|
+
if (isRuntimeNumber(v)) return [v];
|
|
48942
|
+
if (isRuntimeLogical(v)) return [v ? 1 : 0];
|
|
48943
|
+
if (isRuntimeTensor(v)) return Array.from(v.data);
|
|
48944
|
+
if (isRuntimeComplexNumber(v)) return [v.re];
|
|
48945
|
+
throw new RuntimeError(`gallery: ${what} must be numeric`);
|
|
48946
|
+
}
|
|
48947
|
+
function buildTridiag(sub2, diag2, sup) {
|
|
48948
|
+
const n = diag2.length;
|
|
48949
|
+
if (sub2.length !== n - 1 || sup.length !== n - 1) {
|
|
48950
|
+
throw new RuntimeError(
|
|
48951
|
+
"gallery: tridiag sub/superdiagonal must have length one less than the diagonal"
|
|
48952
|
+
);
|
|
48953
|
+
}
|
|
48954
|
+
const ir = [];
|
|
48955
|
+
const pr = [];
|
|
48956
|
+
const jc = new Int32Array(n + 1);
|
|
48957
|
+
for (let c = 0; c < n; c++) {
|
|
48958
|
+
jc[c] = ir.length;
|
|
48959
|
+
if (c >= 1 && sup[c - 1] !== 0) {
|
|
48960
|
+
ir.push(c - 1);
|
|
48961
|
+
pr.push(sup[c - 1]);
|
|
48962
|
+
}
|
|
48963
|
+
if (diag2[c] !== 0) {
|
|
48964
|
+
ir.push(c);
|
|
48965
|
+
pr.push(diag2[c]);
|
|
48966
|
+
}
|
|
48967
|
+
if (c <= n - 2 && sub2[c] !== 0) {
|
|
48968
|
+
ir.push(c + 1);
|
|
48969
|
+
pr.push(sub2[c]);
|
|
48970
|
+
}
|
|
48971
|
+
}
|
|
48972
|
+
jc[n] = ir.length;
|
|
48973
|
+
return RTV.sparseMatrix(n, n, new Int32Array(ir), jc, allocFloat64Array(pr));
|
|
48974
|
+
}
|
|
48975
|
+
function buildTridiagToeplitz(n, c, d, e) {
|
|
48976
|
+
const off = Math.max(0, n - 1);
|
|
48977
|
+
return buildTridiag(
|
|
48978
|
+
new Array(off).fill(c),
|
|
48979
|
+
new Array(n).fill(d),
|
|
48980
|
+
new Array(off).fill(e)
|
|
48981
|
+
);
|
|
48982
|
+
}
|
|
48983
|
+
function galleryTridiag(rest) {
|
|
48984
|
+
if (rest.length === 1) {
|
|
48985
|
+
return buildTridiagToeplitz(Math.round(toNumber(rest[0])), -1, 2, -1);
|
|
48986
|
+
}
|
|
48987
|
+
if (rest.length === 4) {
|
|
48988
|
+
return buildTridiagToeplitz(
|
|
48989
|
+
Math.round(toNumber(rest[0])),
|
|
48990
|
+
toNumber(rest[1]),
|
|
48991
|
+
toNumber(rest[2]),
|
|
48992
|
+
toNumber(rest[3])
|
|
48993
|
+
);
|
|
48994
|
+
}
|
|
48995
|
+
if (rest.length === 3) {
|
|
48996
|
+
const sub2 = toNumArray3(rest[0], "subdiagonal");
|
|
48997
|
+
const diag2 = toNumArray3(rest[1], "diagonal");
|
|
48998
|
+
const sup = toNumArray3(rest[2], "superdiagonal");
|
|
48999
|
+
if (sub2.length === 1 && diag2.length === 1 && sup.length === 1) {
|
|
49000
|
+
return buildTridiag([], diag2, []);
|
|
49001
|
+
}
|
|
49002
|
+
return buildTridiag(sub2, diag2, sup);
|
|
49003
|
+
}
|
|
49004
|
+
throw new RuntimeError("gallery: tridiag expects (n), (n,c,d,e), or (x,y,z)");
|
|
49005
|
+
}
|
|
49006
|
+
registerIBuiltin({
|
|
49007
|
+
name: "gallery",
|
|
49008
|
+
help: {
|
|
49009
|
+
signatures: [
|
|
49010
|
+
"A = gallery('tridiag', n)",
|
|
49011
|
+
"A = gallery('tridiag', n, c, d, e)",
|
|
49012
|
+
"A = gallery('tridiag', x, y, z)"
|
|
49013
|
+
],
|
|
49014
|
+
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."
|
|
49015
|
+
},
|
|
49016
|
+
resolve: () => ({
|
|
49017
|
+
outputTypes: [{ kind: "unknown" }],
|
|
49018
|
+
apply: (args) => {
|
|
49019
|
+
if (args.length < 1) {
|
|
49020
|
+
throw new RuntimeError("gallery: not enough input arguments");
|
|
49021
|
+
}
|
|
49022
|
+
const name = parseStringArgLower(args[0]);
|
|
49023
|
+
let rest = args.slice(1);
|
|
49024
|
+
if (rest.length >= 1) {
|
|
49025
|
+
const last = rest[rest.length - 1];
|
|
49026
|
+
if (isRuntimeString(last) || isRuntimeChar(last)) {
|
|
49027
|
+
const cn = parseStringArgLower(last);
|
|
49028
|
+
if (cn === "single" || cn === "double") rest = rest.slice(0, -1);
|
|
49029
|
+
}
|
|
49030
|
+
}
|
|
49031
|
+
switch (name) {
|
|
49032
|
+
case "tridiag":
|
|
49033
|
+
return galleryTridiag(rest);
|
|
49034
|
+
default:
|
|
49035
|
+
throw new RuntimeError(
|
|
49036
|
+
`gallery: matrix family '${name}' is not supported`
|
|
49037
|
+
);
|
|
49038
|
+
}
|
|
49039
|
+
}
|
|
49040
|
+
})
|
|
49041
|
+
});
|
|
47547
49042
|
|
|
47548
49043
|
// src/numbl-core/interpreter/builtins/special-math.ts
|
|
47549
49044
|
function binaryApply(a, b, fn) {
|
|
@@ -48027,12 +49522,19 @@ registerIBuiltin({
|
|
|
48027
49522
|
|
|
48028
49523
|
// src/numbl-core/native/geometry-bridge.ts
|
|
48029
49524
|
var backend = null;
|
|
49525
|
+
var hullBackend = null;
|
|
48030
49526
|
function setDelaunayBackend(fn) {
|
|
48031
49527
|
backend = fn;
|
|
48032
49528
|
}
|
|
48033
49529
|
function getDelaunayBackend() {
|
|
48034
49530
|
return backend;
|
|
48035
49531
|
}
|
|
49532
|
+
function setConvexHullBackend(fn) {
|
|
49533
|
+
hullBackend = fn;
|
|
49534
|
+
}
|
|
49535
|
+
function getConvexHullBackend() {
|
|
49536
|
+
return hullBackend;
|
|
49537
|
+
}
|
|
48036
49538
|
|
|
48037
49539
|
// src/numbl-core/interpreter/builtins/geometry.ts
|
|
48038
49540
|
function toFlatArray(v, name) {
|
|
@@ -48085,7 +49587,7 @@ function simplexVolume(points, cell, dim) {
|
|
|
48085
49587
|
for (let k = 2; k <= dim; k++) fact *= k;
|
|
48086
49588
|
return Math.abs(det) / fact;
|
|
48087
49589
|
}
|
|
48088
|
-
function triangulateToTensor(points, dim) {
|
|
49590
|
+
function triangulateToTensor(points, dim, orientCCW = false) {
|
|
48089
49591
|
const backend2 = getDelaunayBackend();
|
|
48090
49592
|
if (!backend2)
|
|
48091
49593
|
throw new RuntimeError(
|
|
@@ -48105,6 +49607,16 @@ function triangulateToTensor(points, dim) {
|
|
|
48105
49607
|
const cells = volTol > 0 ? raw.filter((cell) => simplexVolume(points, cell, dim) > volTol) : raw;
|
|
48106
49608
|
const numCells = cells.length;
|
|
48107
49609
|
const cols = dim + 1;
|
|
49610
|
+
if (orientCCW && dim === 2) {
|
|
49611
|
+
for (const cell of cells) {
|
|
49612
|
+
const [a, b, c] = cell;
|
|
49613
|
+
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]);
|
|
49614
|
+
if (signedArea2 < 0) {
|
|
49615
|
+
cell[1] = c;
|
|
49616
|
+
cell[2] = b;
|
|
49617
|
+
}
|
|
49618
|
+
}
|
|
49619
|
+
}
|
|
48108
49620
|
const out = allocFloat64Array(numCells * cols);
|
|
48109
49621
|
for (let i = 0; i < numCells; i++) {
|
|
48110
49622
|
const cell = cells[i];
|
|
@@ -48158,7 +49670,7 @@ defineBuiltin({
|
|
|
48158
49670
|
throw new RuntimeError(
|
|
48159
49671
|
`delaunay: need at least ${dim + 1} points for a ${dim}-D triangulation`
|
|
48160
49672
|
);
|
|
48161
|
-
return triangulateToTensor(points, dim);
|
|
49673
|
+
return triangulateToTensor(points, dim, true);
|
|
48162
49674
|
}
|
|
48163
49675
|
}
|
|
48164
49676
|
]
|
|
@@ -48201,6 +49713,203 @@ defineBuiltin({
|
|
|
48201
49713
|
}
|
|
48202
49714
|
]
|
|
48203
49715
|
});
|
|
49716
|
+
var CONVHULLN_MAX_DIM = 3;
|
|
49717
|
+
function convexHullFacets(points, dim, name) {
|
|
49718
|
+
const backend2 = getConvexHullBackend();
|
|
49719
|
+
if (!backend2)
|
|
49720
|
+
throw new RuntimeError(
|
|
49721
|
+
`${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.`
|
|
49722
|
+
);
|
|
49723
|
+
return backend2(points, dim);
|
|
49724
|
+
}
|
|
49725
|
+
function hullInteriorPoint(points, facets, dim) {
|
|
49726
|
+
const used = /* @__PURE__ */ new Set();
|
|
49727
|
+
for (const f of facets) for (const idx of f) used.add(idx);
|
|
49728
|
+
const c = new Array(dim).fill(0);
|
|
49729
|
+
for (const idx of used) {
|
|
49730
|
+
const p2 = points[idx];
|
|
49731
|
+
for (let k = 0; k < dim; k++) c[k] += p2[k];
|
|
49732
|
+
}
|
|
49733
|
+
const m = used.size || 1;
|
|
49734
|
+
for (let k = 0; k < dim; k++) c[k] /= m;
|
|
49735
|
+
return c;
|
|
49736
|
+
}
|
|
49737
|
+
function hullMeasure(points, facets, dim) {
|
|
49738
|
+
const c = hullInteriorPoint(points, facets, dim);
|
|
49739
|
+
let total = 0;
|
|
49740
|
+
if (dim === 2) {
|
|
49741
|
+
for (const f of facets) {
|
|
49742
|
+
const a = points[f[0]];
|
|
49743
|
+
const b = points[f[1]];
|
|
49744
|
+
const ax = a[0] - c[0], ay = a[1] - c[1];
|
|
49745
|
+
const bx = b[0] - c[0], by = b[1] - c[1];
|
|
49746
|
+
total += Math.abs(ax * by - ay * bx) / 2;
|
|
49747
|
+
}
|
|
49748
|
+
} else {
|
|
49749
|
+
for (const f of facets) {
|
|
49750
|
+
const a = points[f[0]];
|
|
49751
|
+
const b = points[f[1]];
|
|
49752
|
+
const d = points[f[2]];
|
|
49753
|
+
const ax = a[0] - c[0], ay = a[1] - c[1], az = a[2] - c[2];
|
|
49754
|
+
const bx = b[0] - c[0], by = b[1] - c[1], bz = b[2] - c[2];
|
|
49755
|
+
const dx = d[0] - c[0], dy = d[1] - c[1], dz = d[2] - c[2];
|
|
49756
|
+
const det = ax * (by * dz - bz * dy) - ay * (bx * dz - bz * dx) + az * (bx * dy - by * dx);
|
|
49757
|
+
total += Math.abs(det) / 6;
|
|
49758
|
+
}
|
|
49759
|
+
}
|
|
49760
|
+
return total;
|
|
49761
|
+
}
|
|
49762
|
+
function facetsToTensor(facets, cols) {
|
|
49763
|
+
const n = facets.length;
|
|
49764
|
+
const out = allocFloat64Array(n * cols);
|
|
49765
|
+
for (let i = 0; i < n; i++) {
|
|
49766
|
+
const f = facets[i];
|
|
49767
|
+
for (let j = 0; j < cols; j++) out[j * n + i] = f[j] + 1;
|
|
49768
|
+
}
|
|
49769
|
+
return RTV.tensor(out, [n, cols]);
|
|
49770
|
+
}
|
|
49771
|
+
function orderHull2D(facets, points) {
|
|
49772
|
+
const adj = /* @__PURE__ */ new Map();
|
|
49773
|
+
for (const [a, b] of facets) {
|
|
49774
|
+
(adj.get(a) ?? adj.set(a, []).get(a)).push(b);
|
|
49775
|
+
(adj.get(b) ?? adj.set(b, []).get(b)).push(a);
|
|
49776
|
+
}
|
|
49777
|
+
const start = facets[0][0];
|
|
49778
|
+
const loop = [start];
|
|
49779
|
+
let prev = -1;
|
|
49780
|
+
let cur = start;
|
|
49781
|
+
for (let guard = 0; guard <= facets.length; guard++) {
|
|
49782
|
+
const nbrs = adj.get(cur);
|
|
49783
|
+
const next = nbrs[0] === prev ? nbrs[1] : nbrs[0];
|
|
49784
|
+
if (next === void 0 || next === start) break;
|
|
49785
|
+
loop.push(next);
|
|
49786
|
+
prev = cur;
|
|
49787
|
+
cur = next;
|
|
49788
|
+
}
|
|
49789
|
+
let signed = 0;
|
|
49790
|
+
for (let i = 0; i < loop.length; i++) {
|
|
49791
|
+
const p2 = points[loop[i]];
|
|
49792
|
+
const q = points[loop[(i + 1) % loop.length]];
|
|
49793
|
+
signed += p2[0] * q[1] - q[0] * p2[1];
|
|
49794
|
+
}
|
|
49795
|
+
if (signed < 0) loop.reverse();
|
|
49796
|
+
loop.push(loop[0]);
|
|
49797
|
+
const out = allocFloat64Array(loop.length);
|
|
49798
|
+
for (let i = 0; i < loop.length; i++) out[i] = loop[i] + 1;
|
|
49799
|
+
return RTV.tensor(out, [loop.length, 1]);
|
|
49800
|
+
}
|
|
49801
|
+
defineBuiltin({
|
|
49802
|
+
name: "convhull",
|
|
49803
|
+
help: {
|
|
49804
|
+
signatures: [
|
|
49805
|
+
"k = convhull(P)",
|
|
49806
|
+
"k = convhull(x,y)",
|
|
49807
|
+
"k = convhull(x,y,z)",
|
|
49808
|
+
"k = convhull(___,'Simplify',tf)",
|
|
49809
|
+
"[k,av] = convhull(___)"
|
|
49810
|
+
],
|
|
49811
|
+
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."
|
|
49812
|
+
},
|
|
49813
|
+
cases: [
|
|
49814
|
+
{
|
|
49815
|
+
match: (argTypes, nargout) => {
|
|
49816
|
+
if (nargout > 2) return null;
|
|
49817
|
+
if (argTypes.length < 1 || argTypes.length > 5) return null;
|
|
49818
|
+
const ok = (t) => t.kind === "number" || t.kind === "boolean" || t.kind === "tensor" || t.kind === "string" || t.kind === "char";
|
|
49819
|
+
if (!argTypes.every(ok)) return null;
|
|
49820
|
+
const k = { kind: "tensor", isComplex: false };
|
|
49821
|
+
return nargout > 1 ? [k, { kind: "number" }] : [k];
|
|
49822
|
+
},
|
|
49823
|
+
apply: (args, nargout) => {
|
|
49824
|
+
let coordArgs = args;
|
|
49825
|
+
const tail = args[args.length - 2];
|
|
49826
|
+
const isSimplifyName = (v) => typeof v === "string" && v.toLowerCase() === "simplify" || isRuntimeChar(v) && v.value.toLowerCase() === "simplify";
|
|
49827
|
+
if (args.length >= 3 && isSimplifyName(tail)) {
|
|
49828
|
+
coordArgs = args.slice(0, args.length - 2);
|
|
49829
|
+
}
|
|
49830
|
+
let points;
|
|
49831
|
+
let dim;
|
|
49832
|
+
if (coordArgs.length === 1) {
|
|
49833
|
+
const P = coordArgs[0];
|
|
49834
|
+
if (!isRuntimeTensor(P))
|
|
49835
|
+
throw new RuntimeError(
|
|
49836
|
+
"convhull: P must be an N-by-2 or N-by-3 matrix"
|
|
49837
|
+
);
|
|
49838
|
+
const [, d] = tensorSize2D(P);
|
|
49839
|
+
if (d !== 2 && d !== 3)
|
|
49840
|
+
throw new RuntimeError("convhull: P must have 2 or 3 columns");
|
|
49841
|
+
points = matrixToPoints(P, "convhull");
|
|
49842
|
+
dim = d;
|
|
49843
|
+
} else if (coordArgs.length === 2 || coordArgs.length === 3) {
|
|
49844
|
+
const coords = coordArgs.map((a) => toFlatArray(a, "convhull"));
|
|
49845
|
+
const n = coords[0].length;
|
|
49846
|
+
if (coords.some((c) => c.length !== n))
|
|
49847
|
+
throw new RuntimeError(
|
|
49848
|
+
"convhull: coordinate vectors must have the same length"
|
|
49849
|
+
);
|
|
49850
|
+
points = new Array(n);
|
|
49851
|
+
for (let i = 0; i < n; i++) points[i] = coords.map((c) => c[i]);
|
|
49852
|
+
dim = coordArgs.length;
|
|
49853
|
+
} else {
|
|
49854
|
+
throw new RuntimeError("convhull: invalid arguments");
|
|
49855
|
+
}
|
|
49856
|
+
if (points.length < dim + 1)
|
|
49857
|
+
throw new RuntimeError(
|
|
49858
|
+
`convhull: need at least ${dim + 1} points for a ${dim}-D hull`
|
|
49859
|
+
);
|
|
49860
|
+
const facets = convexHullFacets(points, dim, "convhull");
|
|
49861
|
+
const k = dim === 2 ? orderHull2D(facets, points) : facetsToTensor(facets, 3);
|
|
49862
|
+
if (nargout > 1) return [k, hullMeasure(points, facets, dim)];
|
|
49863
|
+
return k;
|
|
49864
|
+
}
|
|
49865
|
+
}
|
|
49866
|
+
]
|
|
49867
|
+
});
|
|
49868
|
+
defineBuiltin({
|
|
49869
|
+
name: "convhulln",
|
|
49870
|
+
help: {
|
|
49871
|
+
signatures: [
|
|
49872
|
+
"k = convhulln(P)",
|
|
49873
|
+
"k = convhulln(P,opts)",
|
|
49874
|
+
"[k,vol] = convhulln(___)"
|
|
49875
|
+
],
|
|
49876
|
+
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)."
|
|
49877
|
+
},
|
|
49878
|
+
cases: [
|
|
49879
|
+
{
|
|
49880
|
+
match: (argTypes, nargout) => {
|
|
49881
|
+
if (nargout > 2) return null;
|
|
49882
|
+
if (argTypes.length < 1 || argTypes.length > 2) return null;
|
|
49883
|
+
const x = argTypes[0];
|
|
49884
|
+
if (x.kind !== "tensor" && x.kind !== "number" && x.kind !== "boolean")
|
|
49885
|
+
return null;
|
|
49886
|
+
const k = { kind: "tensor", isComplex: false };
|
|
49887
|
+
return nargout > 1 ? [k, { kind: "number" }] : [k];
|
|
49888
|
+
},
|
|
49889
|
+
apply: (args, nargout) => {
|
|
49890
|
+
const P = args[0];
|
|
49891
|
+
if (!isRuntimeTensor(P))
|
|
49892
|
+
throw new RuntimeError("convhulln: P must be an m-by-n matrix");
|
|
49893
|
+
const [m, n] = tensorSize2D(P);
|
|
49894
|
+
if (n < 2)
|
|
49895
|
+
throw new RuntimeError("convhulln: P must have at least 2 columns");
|
|
49896
|
+
if (n > CONVHULLN_MAX_DIM)
|
|
49897
|
+
throw new RuntimeError(
|
|
49898
|
+
`convhulln: only 2-D and 3-D hulls are supported (got ${n}-D); higher dimensions are not yet validated`
|
|
49899
|
+
);
|
|
49900
|
+
if (m < n + 1)
|
|
49901
|
+
throw new RuntimeError(
|
|
49902
|
+
`convhulln: need at least ${n + 1} points for a ${n}-D hull`
|
|
49903
|
+
);
|
|
49904
|
+
const points = matrixToPoints(P, "convhulln");
|
|
49905
|
+
const facets = convexHullFacets(points, n, "convhulln");
|
|
49906
|
+
const k = facetsToTensor(facets, n);
|
|
49907
|
+
if (nargout > 1) return [k, hullMeasure(points, facets, n)];
|
|
49908
|
+
return k;
|
|
49909
|
+
}
|
|
49910
|
+
}
|
|
49911
|
+
]
|
|
49912
|
+
});
|
|
48204
49913
|
function getQueryValues(v, name) {
|
|
48205
49914
|
if (typeof v === "number") return { data: [v], shape: null };
|
|
48206
49915
|
if (typeof v === "boolean") return { data: [v ? 1 : 0], shape: null };
|
|
@@ -48698,6 +50407,13 @@ registerIBuiltin({
|
|
|
48698
50407
|
apply: (_args, nargout) => nargout >= 1 ? RTV.dummyHandle() : void 0
|
|
48699
50408
|
})
|
|
48700
50409
|
});
|
|
50410
|
+
registerIBuiltin({
|
|
50411
|
+
name: "waitbar",
|
|
50412
|
+
resolve: () => ({
|
|
50413
|
+
outputTypes: [{ kind: "unknown" }],
|
|
50414
|
+
apply: (_args, nargout) => nargout >= 1 ? RTV.dummyHandle() : void 0
|
|
50415
|
+
})
|
|
50416
|
+
});
|
|
48701
50417
|
registerIBuiltin({
|
|
48702
50418
|
name: "get",
|
|
48703
50419
|
resolve: () => ({
|
|
@@ -49836,6 +51552,10 @@ var H = {
|
|
|
49836
51552
|
signatures: ["C = class(A)"],
|
|
49837
51553
|
description: "Returns the class name of A as a character vector."
|
|
49838
51554
|
},
|
|
51555
|
+
superclasses: {
|
|
51556
|
+
signatures: ["S = superclasses(ClassName)", "S = superclasses(obj)"],
|
|
51557
|
+
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."
|
|
51558
|
+
},
|
|
49839
51559
|
fieldnames: {
|
|
49840
51560
|
signatures: ["F = fieldnames(S)"],
|
|
49841
51561
|
description: "Returns cell array of field names of struct or object S."
|
|
@@ -50239,6 +51959,14 @@ var H = {
|
|
|
50239
51959
|
signatures: ["B = pinv(A)", "B = pinv(A, TOL)"],
|
|
50240
51960
|
description: "Moore-Penrose pseudoinverse."
|
|
50241
51961
|
},
|
|
51962
|
+
null: {
|
|
51963
|
+
signatures: ["Z = null(A)", "Z = null(A, TOL)"],
|
|
51964
|
+
description: "Orthonormal basis for the null space of A (columns of Z), computed via the SVD. TOL overrides the singular-value tolerance."
|
|
51965
|
+
},
|
|
51966
|
+
bandwidth: {
|
|
51967
|
+
signatures: ["[lower, upper] = bandwidth(A)", "B = bandwidth(A, TYPE)"],
|
|
51968
|
+
description: "Lower and upper matrix bandwidth. TYPE is 'lower' or 'upper'; a single output without TYPE returns the lower bandwidth."
|
|
51969
|
+
},
|
|
50242
51970
|
cond: {
|
|
50243
51971
|
signatures: ["C = cond(A)", "C = cond(A, P)"],
|
|
50244
51972
|
description: "Condition number of matrix."
|
|
@@ -50468,6 +52196,10 @@ var H = {
|
|
|
50468
52196
|
signatures: ["Y = double(X)"],
|
|
50469
52197
|
description: "Convert to double precision."
|
|
50470
52198
|
},
|
|
52199
|
+
single: {
|
|
52200
|
+
signatures: ["Y = single(X)"],
|
|
52201
|
+
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."
|
|
52202
|
+
},
|
|
50471
52203
|
logical: {
|
|
50472
52204
|
signatures: ["Y = logical(X)"],
|
|
50473
52205
|
description: "Convert to logical (boolean) array."
|
|
@@ -50838,6 +52570,18 @@ var H = {
|
|
|
50838
52570
|
],
|
|
50839
52571
|
description: "Extract or create sparse banded/diagonal matrices."
|
|
50840
52572
|
},
|
|
52573
|
+
spparms: {
|
|
52574
|
+
signatures: [
|
|
52575
|
+
"spparms",
|
|
52576
|
+
"values = spparms",
|
|
52577
|
+
"[keys, values] = spparms",
|
|
52578
|
+
"value = spparms(KEY)",
|
|
52579
|
+
"spparms(KEY, VALUE)",
|
|
52580
|
+
"spparms('default')",
|
|
52581
|
+
"spparms(values)"
|
|
52582
|
+
],
|
|
52583
|
+
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."
|
|
52584
|
+
},
|
|
50841
52585
|
// ── Linear algebra extras ─────────────────────────────────────────────
|
|
50842
52586
|
qz: {
|
|
50843
52587
|
signatures: [
|
|
@@ -52459,7 +54203,9 @@ function dispatchPlotBuiltin(name, args, instructions, state) {
|
|
|
52459
54203
|
return true;
|
|
52460
54204
|
}
|
|
52461
54205
|
case "close": {
|
|
52462
|
-
|
|
54206
|
+
const a0 = args[0];
|
|
54207
|
+
const isText3 = a0 !== void 0 && (isRuntimeChar(a0) || isRuntimeString(a0));
|
|
54208
|
+
if (isText3 && toString(a0) === "all") {
|
|
52463
54209
|
plotInstr(instructions, { type: "close_all" });
|
|
52464
54210
|
} else {
|
|
52465
54211
|
plotInstr(instructions, { type: "close" });
|
|
@@ -53502,8 +55248,8 @@ function registerSpecialBuiltins(rt) {
|
|
|
53502
55248
|
if (args.length === 0) return nargout >= 1 ? RTV.num(0) : void 0;
|
|
53503
55249
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
53504
55250
|
if (margs.length === 2 && isRuntimeChar(margs[0]) && isRuntimeChar(margs[1])) {
|
|
53505
|
-
const
|
|
53506
|
-
if (
|
|
55251
|
+
const mode = toString(margs[0]);
|
|
55252
|
+
if (mode === "on" || mode === "off") {
|
|
53507
55253
|
if (nargout === 0) return void 0;
|
|
53508
55254
|
return RTV.struct(
|
|
53509
55255
|
/* @__PURE__ */ new Map([
|
|
@@ -53512,6 +55258,14 @@ function registerSpecialBuiltins(rt) {
|
|
|
53512
55258
|
])
|
|
53513
55259
|
);
|
|
53514
55260
|
}
|
|
55261
|
+
if (mode === "query") {
|
|
55262
|
+
return RTV.struct(
|
|
55263
|
+
/* @__PURE__ */ new Map([
|
|
55264
|
+
["state", RTV.char("on")],
|
|
55265
|
+
["identifier", margs[1]]
|
|
55266
|
+
])
|
|
55267
|
+
);
|
|
55268
|
+
}
|
|
53515
55269
|
}
|
|
53516
55270
|
let fmtIdx = 0;
|
|
53517
55271
|
if (margs.length >= 2 && isRuntimeChar(margs[0]) && toString(margs[0]).includes(":")) {
|
|
@@ -55034,6 +56788,10 @@ function _eigsImpl(rt, nargout, args) {
|
|
|
55034
56788
|
const margs = args.map((a) => ensureRuntimeValue(a));
|
|
55035
56789
|
if (margs.length < 1)
|
|
55036
56790
|
throw new RuntimeError("eigs requires at least 1 argument");
|
|
56791
|
+
for (let i = 0; i < margs.length; i++) {
|
|
56792
|
+
const mi = margs[i];
|
|
56793
|
+
if (isRuntimeSparseMatrix(mi)) margs[i] = sparseToDense(mi);
|
|
56794
|
+
}
|
|
55037
56795
|
let afun = null;
|
|
55038
56796
|
let A = null;
|
|
55039
56797
|
let n;
|
|
@@ -56258,43 +58016,40 @@ function methodDispatch(rt, name, nargout, args) {
|
|
|
56258
58016
|
}
|
|
56259
58017
|
}
|
|
56260
58018
|
}
|
|
56261
|
-
|
|
56262
|
-
|
|
56263
|
-
|
|
56264
|
-
if (
|
|
56265
|
-
const
|
|
56266
|
-
|
|
56267
|
-
|
|
56268
|
-
|
|
56269
|
-
|
|
56270
|
-
);
|
|
56271
|
-
|
|
56272
|
-
|
|
56273
|
-
|
|
56274
|
-
RTV.
|
|
56275
|
-
|
|
56276
|
-
|
|
56277
|
-
|
|
56278
|
-
RTV.
|
|
56279
|
-
|
|
56280
|
-
|
|
56281
|
-
|
|
56282
|
-
|
|
56283
|
-
|
|
56284
|
-
|
|
56285
|
-
|
|
56286
|
-
|
|
56287
|
-
|
|
56288
|
-
|
|
56289
|
-
|
|
56290
|
-
} finally {
|
|
56291
|
-
rt.activeAccessors.delete(guardKey);
|
|
56292
|
-
}
|
|
58019
|
+
const methodExists = rt.cachedResolveClassMethod(firstRV.className, name) !== null;
|
|
58020
|
+
if (!methodExists) {
|
|
58021
|
+
const guardKey = `${firstRV.className}.subsref`;
|
|
58022
|
+
if (!rt.activeAccessors.has(guardKey)) {
|
|
58023
|
+
const subsrefFn = rt.cachedResolveClassMethod(
|
|
58024
|
+
firstRV.className,
|
|
58025
|
+
"subsref"
|
|
58026
|
+
);
|
|
58027
|
+
if (subsrefFn) {
|
|
58028
|
+
const remaining = args.slice(1);
|
|
58029
|
+
const sEntries = [
|
|
58030
|
+
RTV.struct({
|
|
58031
|
+
type: RTV.char("."),
|
|
58032
|
+
subs: RTV.char(name)
|
|
58033
|
+
}),
|
|
58034
|
+
RTV.struct({
|
|
58035
|
+
type: RTV.char("()"),
|
|
58036
|
+
subs: RTV.cell(
|
|
58037
|
+
remaining.map((a) => ensureRuntimeValue(a)),
|
|
58038
|
+
[1, remaining.length]
|
|
58039
|
+
)
|
|
58040
|
+
})
|
|
58041
|
+
];
|
|
58042
|
+
const S = RTV.structArray(["type", "subs"], sEntries);
|
|
58043
|
+
rt.activeAccessors.add(guardKey);
|
|
58044
|
+
try {
|
|
58045
|
+
return subsrefFn(nargout, first, S);
|
|
58046
|
+
} finally {
|
|
58047
|
+
rt.activeAccessors.delete(guardKey);
|
|
56293
58048
|
}
|
|
56294
58049
|
}
|
|
56295
58050
|
}
|
|
56296
|
-
throw e;
|
|
56297
58051
|
}
|
|
58052
|
+
return callClassMethod(rt, firstRV.className, name, nargout, args);
|
|
56298
58053
|
}
|
|
56299
58054
|
}
|
|
56300
58055
|
const builtin = rt.builtins[name];
|
|
@@ -56351,11 +58106,13 @@ function arrayfunCellfunImpl(rt, name, nargout, args) {
|
|
|
56351
58106
|
const getElem = (arr, i) => {
|
|
56352
58107
|
if (isRuntimeCell(arr)) return arr.data[i];
|
|
56353
58108
|
if (isRuntimeTensor(arr)) return arr.data[i];
|
|
58109
|
+
if (isRuntimeStructArray(arr)) return arr.elements[i];
|
|
56354
58110
|
return arr;
|
|
56355
58111
|
};
|
|
56356
58112
|
const getLen = (arr) => {
|
|
56357
58113
|
if (isRuntimeCell(arr)) return arr.data.length;
|
|
56358
58114
|
if (isRuntimeTensor(arr)) return arr.data.length;
|
|
58115
|
+
if (isRuntimeStructArray(arr)) return arr.elements.length;
|
|
56359
58116
|
return 1;
|
|
56360
58117
|
};
|
|
56361
58118
|
const collectArgs = (i) => {
|
|
@@ -56391,9 +58148,9 @@ function arrayfunCellfunImpl(rt, name, nargout, args) {
|
|
|
56391
58148
|
if (allLogical && arrArg.data.length > 0) result._isLogical = true;
|
|
56392
58149
|
return result;
|
|
56393
58150
|
}
|
|
56394
|
-
if (isRuntimeCell(arrArg) || extraInputs.length > 0 || nargout > 1) {
|
|
58151
|
+
if (isRuntimeCell(arrArg) || isRuntimeStructArray(arrArg) || extraInputs.length > 0 || nargout > 1) {
|
|
56395
58152
|
const len = getLen(arrArg);
|
|
56396
|
-
const shape = isRuntimeCell(arrArg)
|
|
58153
|
+
const shape = isRuntimeCell(arrArg) || isRuntimeTensor(arrArg) ? [...arrArg.shape] : [1, len];
|
|
56397
58154
|
if (nargout > 1) {
|
|
56398
58155
|
const allResults = Array.from(
|
|
56399
58156
|
{ length: nargout },
|
|
@@ -57228,6 +58985,28 @@ function indexStore(rt, base, indices, rhs, skipSubsasgn = false) {
|
|
|
57228
58985
|
if (isRuntimeStruct(mv)) {
|
|
57229
58986
|
return ensureRuntimeValue(rhs);
|
|
57230
58987
|
}
|
|
58988
|
+
if (indices.length === 1 && isRuntimeClassInstance(ensureRuntimeValue(rhs)) && // Object-array growth uses a numeric position. A char/string index (e.g. a
|
|
58989
|
+
// key into a containers.Map whose value happens to be a class instance)
|
|
58990
|
+
// must fall through to the subsasgn dispatch below, not be coerced to a
|
|
58991
|
+
// number — `toNumber` on a multi-char value throws.
|
|
58992
|
+
!isRuntimeChar(ensureRuntimeValue(indices[0]))) {
|
|
58993
|
+
const k = Math.round(toNumber(ensureRuntimeValue(indices[0]))) - 1;
|
|
58994
|
+
const growsArray = isRuntimeClassInstanceArray(mv) || isRuntimeTensor(mv) && mv.data.length === 0 || isRuntimeClassInstance(mv) && k >= 1;
|
|
58995
|
+
if (growsArray) {
|
|
58996
|
+
if (k < 0) throw new RuntimeError("Index must be a positive integer");
|
|
58997
|
+
const rhsInst = ensureRuntimeValue(rhs);
|
|
58998
|
+
const existing = isRuntimeClassInstanceArray(mv) ? [...mv.elements] : isRuntimeClassInstance(mv) ? [mv] : [];
|
|
58999
|
+
const className = isRuntimeClassInstanceArray(mv) ? mv.className : isRuntimeClassInstance(mv) ? mv.className : rhsInst.className;
|
|
59000
|
+
while (existing.length < k) {
|
|
59001
|
+
existing.push(
|
|
59002
|
+
RTV.classInstance(className, [...rhsInst.fields.keys()], false)
|
|
59003
|
+
);
|
|
59004
|
+
}
|
|
59005
|
+
existing[k] = rhsInst;
|
|
59006
|
+
if (existing.length === 1) return existing[0];
|
|
59007
|
+
return RTV.classInstanceArray(className, existing, [1, existing.length]);
|
|
59008
|
+
}
|
|
59009
|
+
}
|
|
57231
59010
|
if (isRuntimeClassInstance(mv)) {
|
|
57232
59011
|
const guardKey = `${mv.className}.subsasgn`;
|
|
57233
59012
|
if (!skipSubsasgn && !rt.activeAccessors.has(guardKey)) {
|
|
@@ -57385,12 +59164,17 @@ function getMember(rt, base, name) {
|
|
|
57385
59164
|
`No property or method '${name}' for class '${mv.className}'`
|
|
57386
59165
|
);
|
|
57387
59166
|
}
|
|
59167
|
+
if (isRuntimeClassInstanceArray(mv)) {
|
|
59168
|
+
const values = mv.elements.map(
|
|
59169
|
+
(el) => ensureRuntimeValue(getMember(rt, el, name))
|
|
59170
|
+
);
|
|
59171
|
+
return horzcat(...values);
|
|
59172
|
+
}
|
|
57388
59173
|
return getRTValueField(mv, name);
|
|
57389
59174
|
}
|
|
57390
|
-
function getMemberDynamic(base, nameExpr) {
|
|
57391
|
-
const mv = ensureRuntimeValue(base);
|
|
59175
|
+
function getMemberDynamic(rt, base, nameExpr) {
|
|
57392
59176
|
const name = toString(ensureRuntimeValue(nameExpr));
|
|
57393
|
-
return
|
|
59177
|
+
return ensureRuntimeValue(getMember(rt, base, name));
|
|
57394
59178
|
}
|
|
57395
59179
|
function getMemberOrEmpty(base, name) {
|
|
57396
59180
|
try {
|
|
@@ -57412,7 +59196,7 @@ function setMemberReturn(rt, base, name, rhs) {
|
|
|
57412
59196
|
if (setter) {
|
|
57413
59197
|
rt.activeAccessors.add(accessorKey);
|
|
57414
59198
|
try {
|
|
57415
|
-
const result = setter(
|
|
59199
|
+
const result = setter(0, base, rhs);
|
|
57416
59200
|
return result !== void 0 ? result : base;
|
|
57417
59201
|
} finally {
|
|
57418
59202
|
rt.activeAccessors.delete(accessorKey);
|
|
@@ -57424,10 +59208,8 @@ function setMemberReturn(rt, base, name, rhs) {
|
|
|
57424
59208
|
return setRTValueField(mv, name, rhsMv, rt);
|
|
57425
59209
|
}
|
|
57426
59210
|
function setMemberDynamicReturn(rt, base, nameExpr, rhs) {
|
|
57427
|
-
const mv = ensureRuntimeValue(base);
|
|
57428
59211
|
const name = toString(ensureRuntimeValue(nameExpr));
|
|
57429
|
-
|
|
57430
|
-
return setRTValueField(mv, name, rhsMv, rt);
|
|
59212
|
+
return ensureRuntimeValue(setMemberReturn(rt, base, name, rhs));
|
|
57431
59213
|
}
|
|
57432
59214
|
function subsrefCall(rt, base, names) {
|
|
57433
59215
|
const mv = ensureRuntimeValue(base);
|
|
@@ -58722,7 +60504,7 @@ function marchingCubes(dims, getVal, getCoord, iso, opts) {
|
|
|
58722
60504
|
}
|
|
58723
60505
|
return { vertices, faces, colors };
|
|
58724
60506
|
}
|
|
58725
|
-
function
|
|
60507
|
+
function isNumericArg3(v) {
|
|
58726
60508
|
return typeof v === "number" || typeof v === "boolean" || isRuntimeTensor(v);
|
|
58727
60509
|
}
|
|
58728
60510
|
function dims3(v) {
|
|
@@ -58739,7 +60521,7 @@ function isosurfaceFromArgs(args) {
|
|
|
58739
60521
|
if (isRuntimeChar(a) || isRuntimeString(a)) {
|
|
58740
60522
|
const s = toString(a).toLowerCase();
|
|
58741
60523
|
if (s === "noshare") share = false;
|
|
58742
|
-
} else if (
|
|
60524
|
+
} else if (isNumericArg3(a)) {
|
|
58743
60525
|
nums.push(a);
|
|
58744
60526
|
}
|
|
58745
60527
|
}
|
|
@@ -60076,7 +61858,7 @@ var Runtime = class _Runtime {
|
|
|
60076
61858
|
return getMember(this, base, name);
|
|
60077
61859
|
}
|
|
60078
61860
|
getMemberDynamic(base, nameExpr) {
|
|
60079
|
-
return getMemberDynamic(base, nameExpr);
|
|
61861
|
+
return getMemberDynamic(this, base, nameExpr);
|
|
60080
61862
|
}
|
|
60081
61863
|
getMemberOrEmpty(base, name) {
|
|
60082
61864
|
return getMemberOrEmpty(base, name);
|
|
@@ -60724,6 +62506,7 @@ function resolveFunctionImpl(name, argTypes, callSite, index2) {
|
|
|
60724
62506
|
for (const argType of argTypes) {
|
|
60725
62507
|
if (argType?.kind === "ClassInstance") {
|
|
60726
62508
|
const className = argType.className;
|
|
62509
|
+
if (index2.classConstructors.get(className) === name) continue;
|
|
60727
62510
|
if (!candidates.includes(className) && (index2.classInstanceMethods.get(className)?.has(name) || index2.classStaticMethods.get(className)?.has(name))) {
|
|
60728
62511
|
candidates.push(className);
|
|
60729
62512
|
}
|
|
@@ -60832,12 +62615,25 @@ var Environment = class _Environment {
|
|
|
60832
62615
|
}
|
|
60833
62616
|
/** Function ID for persistent variable storage */
|
|
60834
62617
|
persistentFuncId;
|
|
62618
|
+
/** Call-site variable names of this frame's arguments, for `inputname`.
|
|
62619
|
+
* Entry i is the name of the variable passed as argument i+1, or '' if
|
|
62620
|
+
* that argument was not a plain variable. Undefined when the call did
|
|
62621
|
+
* not originate from an interpreted call expression (e.g. feval, JIT).
|
|
62622
|
+
* Read directly off the executing frame — the interpreter has only
|
|
62623
|
+
* function-level scoping, so `this.env` is the frame while a body runs. */
|
|
62624
|
+
inputArgNames;
|
|
60835
62625
|
/** Back-reference to the runtime (needed for global/persistent access) */
|
|
60836
62626
|
rt = null;
|
|
60837
62627
|
/** Set when a `@nestedFn` handle has been created that captures this env
|
|
60838
62628
|
* (or an ancestor). Tells the function-exit cleanup that clearing this
|
|
60839
62629
|
* env would strand the handle's closure, so locals must be left alive. */
|
|
60840
62630
|
nestedHandleCreated = false;
|
|
62631
|
+
/** For a nested-function frame: the names of this function's own formal
|
|
62632
|
+
* input/output arguments. These are always local — a write must never be
|
|
62633
|
+
* redirected to a same-named variable in the parent, even before the
|
|
62634
|
+
* output has been assigned. (MATLAB scopes a nested function's formal
|
|
62635
|
+
* arguments to that function; only other variables are shared.) */
|
|
62636
|
+
nestedLocalNames;
|
|
60841
62637
|
get(name) {
|
|
60842
62638
|
if (this._globalNames !== void 0 && this._globalNames.has(name) && this.rt) {
|
|
60843
62639
|
const v = this.rt.$g[name];
|
|
@@ -60856,7 +62652,7 @@ var Environment = class _Environment {
|
|
|
60856
62652
|
if (old !== void 0) decref(this.rt, old);
|
|
60857
62653
|
return;
|
|
60858
62654
|
}
|
|
60859
|
-
if (this.isNested && !this.vars.has(name) && this.parent) {
|
|
62655
|
+
if (this.isNested && !this.vars.has(name) && this.parent && !this.nestedLocalNames?.has(name)) {
|
|
60860
62656
|
const owner = this.findOwner(name);
|
|
60861
62657
|
if (owner) {
|
|
60862
62658
|
owner.setLocal(name, value);
|
|
@@ -62051,6 +63847,7 @@ function makeRootContext(interp, registry3) {
|
|
|
62051
63847
|
var interpreterExec_exports = {};
|
|
62052
63848
|
__export(interpreterExec_exports, {
|
|
62053
63849
|
assignLValue: () => assignLValue,
|
|
63850
|
+
computeInputNames: () => computeInputNames,
|
|
62054
63851
|
evalAnonFunc: () => evalAnonFunc,
|
|
62055
63852
|
evalArgs: () => evalArgs,
|
|
62056
63853
|
evalBinary: () => evalBinary,
|
|
@@ -62353,6 +64150,11 @@ function execStmtInner(stmt) {
|
|
|
62353
64150
|
case "Global": {
|
|
62354
64151
|
for (const name of stmt.names) {
|
|
62355
64152
|
this.env.globalNames.add(name);
|
|
64153
|
+
if (this.rt && !(name in this.rt.$g)) {
|
|
64154
|
+
const empty = RTV.tensor(allocFloat64Array(0), [0, 0]);
|
|
64155
|
+
incref(empty);
|
|
64156
|
+
this.rt.$g[name] = empty;
|
|
64157
|
+
}
|
|
62356
64158
|
}
|
|
62357
64159
|
return null;
|
|
62358
64160
|
}
|
|
@@ -62464,6 +64266,10 @@ function evalExprNargout(expr, nargout) {
|
|
|
62464
64266
|
if (isRuntimeStructArray(rv)) {
|
|
62465
64267
|
return rv.elements.length;
|
|
62466
64268
|
}
|
|
64269
|
+
if (isRuntimeClassInstanceArray(rv)) {
|
|
64270
|
+
if (ctx.numIndices === 1) return rv.elements.length;
|
|
64271
|
+
return ctx.dimIndex < rv.shape.length ? rv.shape[ctx.dimIndex] : 1;
|
|
64272
|
+
}
|
|
62467
64273
|
if (isRuntimeSparseMatrix(rv)) {
|
|
62468
64274
|
if (ctx.numIndices === 1) return rv.m * rv.n;
|
|
62469
64275
|
return ctx.dimIndex === 0 ? rv.m : ctx.dimIndex === 1 ? rv.n : 1;
|
|
@@ -62624,6 +64430,23 @@ function evalExprNargout(expr, nargout) {
|
|
|
62624
64430
|
throw new RuntimeError("Interpreter does not yet support meta.class");
|
|
62625
64431
|
}
|
|
62626
64432
|
}
|
|
64433
|
+
function computeInputNames(argExprs, callerEnv) {
|
|
64434
|
+
const names = [];
|
|
64435
|
+
let blanked = false;
|
|
64436
|
+
for (const a of argExprs) {
|
|
64437
|
+
if (blanked) {
|
|
64438
|
+
names.push("");
|
|
64439
|
+
} else if (a.type === "Ident" && callerEnv.has(a.name)) {
|
|
64440
|
+
names.push(a.name);
|
|
64441
|
+
} else if (a.type === "IndexCell" || a.type === "Member" || a.type === "MemberDynamic") {
|
|
64442
|
+
names.push("");
|
|
64443
|
+
blanked = true;
|
|
64444
|
+
} else {
|
|
64445
|
+
names.push("");
|
|
64446
|
+
}
|
|
64447
|
+
}
|
|
64448
|
+
return names;
|
|
64449
|
+
}
|
|
62627
64450
|
function evalArgs(argExprs) {
|
|
62628
64451
|
const args = [];
|
|
62629
64452
|
for (const a of argExprs) {
|
|
@@ -62753,6 +64576,7 @@ function evalFuncCall(expr, nargout) {
|
|
|
62753
64576
|
const c = getConstant(expr.name);
|
|
62754
64577
|
if (c !== void 0) return c;
|
|
62755
64578
|
}
|
|
64579
|
+
this.pendingInputNames = expr.args.length > 0 ? computeInputNames(expr.args, this.env) : void 0;
|
|
62756
64580
|
return this.callFunction(expr.name, args, nargout);
|
|
62757
64581
|
}
|
|
62758
64582
|
function evalMember(expr, nargout) {
|
|
@@ -62932,7 +64756,14 @@ function makeFuncHandle(name) {
|
|
|
62932
64756
|
);
|
|
62933
64757
|
};
|
|
62934
64758
|
fn.jsFnExpectsNargout = true;
|
|
62935
|
-
|
|
64759
|
+
let narg = getIBuiltinNargin(name);
|
|
64760
|
+
if (narg === void 0) {
|
|
64761
|
+
try {
|
|
64762
|
+
narg = this.declaredNargin(name);
|
|
64763
|
+
} catch {
|
|
64764
|
+
narg = void 0;
|
|
64765
|
+
}
|
|
64766
|
+
}
|
|
62936
64767
|
if (narg !== void 0) fn.nargin = narg;
|
|
62937
64768
|
if (isNested) {
|
|
62938
64769
|
fn.releaseExtra = () => capturedEnv.clearLocals();
|
|
@@ -63221,6 +65052,7 @@ __export(interpreterFunctions_exports, {
|
|
|
63221
65052
|
callNestedFunction: () => callNestedFunction,
|
|
63222
65053
|
callUserFunction: () => callUserFunction,
|
|
63223
65054
|
collectClassProperties: () => collectClassProperties,
|
|
65055
|
+
declaredNargin: () => declaredNargin,
|
|
63224
65056
|
evalInLocalScope: () => evalInLocalScope,
|
|
63225
65057
|
findExternalMethod: () => findExternalMethod,
|
|
63226
65058
|
findFunctionInClassFile: () => findFunctionInClassFile,
|
|
@@ -63523,6 +65355,30 @@ register("isa", (ctx, args) => {
|
|
|
63523
65355
|
if (args.length !== 2) return FALL_THROUGH;
|
|
63524
65356
|
return ctx.rt.isa(args[0], args[1]);
|
|
63525
65357
|
});
|
|
65358
|
+
register("superclasses", (ctx, args) => {
|
|
65359
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
65360
|
+
const v = ensureRuntimeValue(args[0]);
|
|
65361
|
+
let className;
|
|
65362
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v)) {
|
|
65363
|
+
className = v.className;
|
|
65364
|
+
} else if (isRuntimeChar(v) || isRuntimeString(v)) {
|
|
65365
|
+
className = toString(v);
|
|
65366
|
+
}
|
|
65367
|
+
const names = [];
|
|
65368
|
+
if (className) {
|
|
65369
|
+
const seen = /* @__PURE__ */ new Set([className]);
|
|
65370
|
+
let current = ctx.rt.getClassParentName(className);
|
|
65371
|
+
while (current && !seen.has(current)) {
|
|
65372
|
+
names.push(current);
|
|
65373
|
+
seen.add(current);
|
|
65374
|
+
current = ctx.rt.getClassParentName(current);
|
|
65375
|
+
}
|
|
65376
|
+
}
|
|
65377
|
+
return RTV.cell(
|
|
65378
|
+
names.map((n) => RTV.string(n)),
|
|
65379
|
+
[names.length, 1]
|
|
65380
|
+
);
|
|
65381
|
+
});
|
|
63526
65382
|
register("__inferred_type_str", (_ctx, args) => {
|
|
63527
65383
|
if (args.length !== 1) return FALL_THROUGH;
|
|
63528
65384
|
const rv = ensureRuntimeValue(args[0]);
|
|
@@ -63547,6 +65403,44 @@ register("nargout", (ctx, args) => {
|
|
|
63547
65403
|
const v = ctx.env.get("$nargout");
|
|
63548
65404
|
return v !== void 0 ? v : 0;
|
|
63549
65405
|
});
|
|
65406
|
+
register("inputname", (ctx, args) => {
|
|
65407
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
65408
|
+
const narginVal = ctx.env.get("$nargin");
|
|
65409
|
+
if (typeof narginVal !== "number") {
|
|
65410
|
+
throw new RuntimeError(
|
|
65411
|
+
"You can only call 'inputname' from within a MATLAB function."
|
|
65412
|
+
);
|
|
65413
|
+
}
|
|
65414
|
+
const k = toNumber(ensureRuntimeValue(args[0]));
|
|
65415
|
+
if (!Number.isInteger(k) || k < 1) {
|
|
65416
|
+
throw new RuntimeError(
|
|
65417
|
+
"Argument number must be a positive integer scalar."
|
|
65418
|
+
);
|
|
65419
|
+
}
|
|
65420
|
+
if (k > narginVal) {
|
|
65421
|
+
throw new RuntimeError(
|
|
65422
|
+
"Argument number exceeds number of function input arguments."
|
|
65423
|
+
);
|
|
65424
|
+
}
|
|
65425
|
+
const names = ctx.env.inputArgNames;
|
|
65426
|
+
const name = names && k <= names.length ? names[k - 1] : "";
|
|
65427
|
+
return RTV.char(name);
|
|
65428
|
+
});
|
|
65429
|
+
register("properties", (ctx, args) => {
|
|
65430
|
+
if (args.length !== 1) return FALL_THROUGH;
|
|
65431
|
+
const v = ensureRuntimeValue(args[0]);
|
|
65432
|
+
let names;
|
|
65433
|
+
if (isRuntimeClassInstance(v) || isRuntimeClassInstanceArray(v)) {
|
|
65434
|
+
names = ctx.classPublicProperties(v.className);
|
|
65435
|
+
} else if (isRuntimeChar(v) || isRuntimeString(v)) {
|
|
65436
|
+
names = ctx.classPublicProperties(toString(v));
|
|
65437
|
+
}
|
|
65438
|
+
if (!names) return RTV.cell([], [0, 1]);
|
|
65439
|
+
return RTV.cell(
|
|
65440
|
+
names.map((n) => RTV.string(n)),
|
|
65441
|
+
[names.length, 1]
|
|
65442
|
+
);
|
|
65443
|
+
});
|
|
63550
65444
|
register("narginchk", (ctx, args) => {
|
|
63551
65445
|
if (args.length !== 2) return FALL_THROUGH;
|
|
63552
65446
|
const narginVal = ctx.env.get("$nargin");
|
|
@@ -63651,10 +65545,14 @@ function callFunction(name, args, nargout) {
|
|
|
63651
65545
|
source: ""
|
|
63652
65546
|
};
|
|
63653
65547
|
return void 0;
|
|
63654
|
-
}
|
|
65548
|
+
},
|
|
65549
|
+
classPublicProperties: (n) => classPublicProperties(this, n)
|
|
63655
65550
|
};
|
|
63656
65551
|
const result = specialHandler(ctx, args, nargout);
|
|
63657
|
-
if (result !== FALL_THROUGH)
|
|
65552
|
+
if (result !== FALL_THROUGH) {
|
|
65553
|
+
this.pendingInputNames = void 0;
|
|
65554
|
+
return result;
|
|
65555
|
+
}
|
|
63658
65556
|
}
|
|
63659
65557
|
const nested = this.env.getNestedFunction(name);
|
|
63660
65558
|
if (nested) {
|
|
@@ -63674,6 +65572,75 @@ function callFunction(name, args, nargout) {
|
|
|
63674
65572
|
}
|
|
63675
65573
|
throw new RuntimeError(`Undefined function or variable '${name}'`);
|
|
63676
65574
|
}
|
|
65575
|
+
function narginFromParams(params) {
|
|
65576
|
+
const hasVarargin = params.length > 0 && params[params.length - 1] === "varargin";
|
|
65577
|
+
return hasVarargin ? -params.length : params.length;
|
|
65578
|
+
}
|
|
65579
|
+
function paramsInFile(interp, fileName, funcName) {
|
|
65580
|
+
const ast = interp.ctx.getCachedAST(fileName);
|
|
65581
|
+
for (const stmt of ast.body) {
|
|
65582
|
+
if (stmt.type === "Function" && stmt.name === funcName) return stmt.params;
|
|
65583
|
+
}
|
|
65584
|
+
return void 0;
|
|
65585
|
+
}
|
|
65586
|
+
function declaredNargin(name) {
|
|
65587
|
+
const nested = this.env.getNestedFunction(name);
|
|
65588
|
+
if (nested) return narginFromParams(nested.fn.params);
|
|
65589
|
+
const callSite = {
|
|
65590
|
+
file: this.currentFile,
|
|
65591
|
+
...this.currentClassName ? { className: this.currentClassName } : {},
|
|
65592
|
+
...this.currentMethodName ? { methodName: this.currentMethodName } : {}
|
|
65593
|
+
};
|
|
65594
|
+
const target = resolveFunction(name, [], callSite, this.functionIndex);
|
|
65595
|
+
if (!target) return void 0;
|
|
65596
|
+
let params;
|
|
65597
|
+
switch (target.kind) {
|
|
65598
|
+
case "localFunction": {
|
|
65599
|
+
const { source } = target;
|
|
65600
|
+
if (source.from === "main") {
|
|
65601
|
+
params = this.mainLocalFunctions.get(target.name)?.params;
|
|
65602
|
+
} else if (source.from === "workspaceFile") {
|
|
65603
|
+
params = this.findFunctionInWorkspaceFile(source.wsName, target.name)?.params ?? void 0;
|
|
65604
|
+
} else if (source.from === "classFile") {
|
|
65605
|
+
params = this.findFunctionInClassFile(
|
|
65606
|
+
source.className,
|
|
65607
|
+
target.name,
|
|
65608
|
+
source.methodScope
|
|
65609
|
+
)?.params ?? void 0;
|
|
65610
|
+
} else if (source.from === "privateFile") {
|
|
65611
|
+
params = paramsInFile(this, source.callerFile, target.name);
|
|
65612
|
+
}
|
|
65613
|
+
break;
|
|
65614
|
+
}
|
|
65615
|
+
case "workspaceFunction": {
|
|
65616
|
+
const dotIdx = target.name.lastIndexOf(".");
|
|
65617
|
+
const primaryName = dotIdx >= 0 ? target.name.slice(dotIdx + 1) : target.name;
|
|
65618
|
+
params = this.findFunctionInWorkspaceFile(target.name, primaryName)?.params ?? void 0;
|
|
65619
|
+
if (params === void 0) {
|
|
65620
|
+
const entry = this.ctx.registry.filesByFuncName.get(target.name);
|
|
65621
|
+
if (entry) {
|
|
65622
|
+
const ast = this.ctx.getCachedAST(entry.fileName);
|
|
65623
|
+
for (const stmt of ast.body) {
|
|
65624
|
+
if (stmt.type === "Function") {
|
|
65625
|
+
params = stmt.params;
|
|
65626
|
+
break;
|
|
65627
|
+
}
|
|
65628
|
+
}
|
|
65629
|
+
}
|
|
65630
|
+
}
|
|
65631
|
+
break;
|
|
65632
|
+
}
|
|
65633
|
+
case "privateFunction": {
|
|
65634
|
+
const entry = this.ctx.getPrivateFileEntry(
|
|
65635
|
+
target.callerFile,
|
|
65636
|
+
target.name
|
|
65637
|
+
);
|
|
65638
|
+
if (entry) params = paramsInFile(this, entry.fileName, target.name);
|
|
65639
|
+
break;
|
|
65640
|
+
}
|
|
65641
|
+
}
|
|
65642
|
+
return params !== void 0 ? narginFromParams(params) : void 0;
|
|
65643
|
+
}
|
|
63677
65644
|
function interpretTarget(target, args, nargout) {
|
|
63678
65645
|
switch (target.kind) {
|
|
63679
65646
|
case "builtin": {
|
|
@@ -63842,18 +65809,12 @@ function interpretWorkspaceFunction(target, args, nargout) {
|
|
|
63842
65809
|
if (entry) {
|
|
63843
65810
|
const ast = this.ctx.getCachedAST(entry.fileName);
|
|
63844
65811
|
return this.withFileContext(entry.fileName, void 0, void 0, () => {
|
|
63845
|
-
const
|
|
63846
|
-
|
|
63847
|
-
|
|
63848
|
-
|
|
63849
|
-
if (stmt.type === "Function") continue;
|
|
63850
|
-
const signal = this.execStmt(stmt);
|
|
63851
|
-
if (signal instanceof ReturnSignal) break;
|
|
63852
|
-
}
|
|
63853
|
-
return this.ans;
|
|
63854
|
-
} finally {
|
|
63855
|
-
this.env = savedEnv;
|
|
65812
|
+
for (const stmt of ast.body) {
|
|
65813
|
+
if (stmt.type === "Function") continue;
|
|
65814
|
+
const signal = this.execStmt(stmt);
|
|
65815
|
+
if (signal instanceof ReturnSignal) break;
|
|
63856
65816
|
}
|
|
65817
|
+
return this.ans;
|
|
63857
65818
|
});
|
|
63858
65819
|
}
|
|
63859
65820
|
throw new RuntimeError(`Workspace function '${target.name}' not found`);
|
|
@@ -63920,6 +65881,21 @@ function instantiateClass(className, args, nargout) {
|
|
|
63920
65881
|
if (!classInfo) {
|
|
63921
65882
|
return this.rt.callClassMethod(className, className, nargout, args);
|
|
63922
65883
|
}
|
|
65884
|
+
if (classInfo.isOldStyle) {
|
|
65885
|
+
const ctorName = classInfo.constructorName ?? className;
|
|
65886
|
+
const ctorFn = this.findExternalMethod(classInfo, ctorName);
|
|
65887
|
+
if (!ctorFn)
|
|
65888
|
+
throw new RuntimeError(
|
|
65889
|
+
`Constructor for old-style class '${className}' not found`
|
|
65890
|
+
);
|
|
65891
|
+
const fileName = classInfo.externalMethodFiles.get(ctorName)?.fileName ?? classInfo.fileName;
|
|
65892
|
+
return this.withFileContext(
|
|
65893
|
+
fileName,
|
|
65894
|
+
className,
|
|
65895
|
+
ctorName,
|
|
65896
|
+
() => this.callUserFunction(ctorFn, args, nargout)
|
|
65897
|
+
);
|
|
65898
|
+
}
|
|
63923
65899
|
const { propertyNames, propertyDefaults } = this.collectClassProperties(classInfo);
|
|
63924
65900
|
const defaults = /* @__PURE__ */ new Map();
|
|
63925
65901
|
for (const [propName, defaultExpr] of propertyDefaults) {
|
|
@@ -63943,7 +65919,7 @@ function instantiateClass(className, args, nargout) {
|
|
|
63943
65919
|
function interpretConstructor(classInfo, args, nargout) {
|
|
63944
65920
|
const constructorName = classInfo.constructorName;
|
|
63945
65921
|
if (!constructorName) return args[0];
|
|
63946
|
-
for (const member of classInfo.ast
|
|
65922
|
+
for (const member of classInfo.ast?.members ?? []) {
|
|
63947
65923
|
if (member.type !== "Methods") continue;
|
|
63948
65924
|
for (const methodStmt of member.body) {
|
|
63949
65925
|
if (methodStmt.type === "Function" && methodStmt.name === constructorName) {
|
|
@@ -63985,6 +65961,8 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
63985
65961
|
if (!hasVarargoutDecl && nargout > declaredRegularOutputs) {
|
|
63986
65962
|
throw new RuntimeError("Too many output arguments.");
|
|
63987
65963
|
}
|
|
65964
|
+
const callInputNames = this.pendingInputNames;
|
|
65965
|
+
this.pendingInputNames = void 0;
|
|
63988
65966
|
const sharedArgs = args;
|
|
63989
65967
|
if (narginOverride === void 0 && this.registry.size > 0) {
|
|
63990
65968
|
const r = this.registry.dispatchCall(fn, sharedArgs, nargout, this);
|
|
@@ -64018,6 +65996,7 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
64018
65996
|
}
|
|
64019
65997
|
fnEnv.set("$nargin", narginOverride ?? args.length);
|
|
64020
65998
|
fnEnv.set("$nargout", nargout);
|
|
65999
|
+
fnEnv.inputArgNames = callInputNames;
|
|
64021
66000
|
for (const stmt of fn.body) {
|
|
64022
66001
|
if (stmt.type === "Function") {
|
|
64023
66002
|
fnEnv.nestedFunctions.set(stmt.name, {
|
|
@@ -64094,10 +66073,13 @@ function callUserFunction(fn, args, nargout, narginOverride) {
|
|
|
64094
66073
|
}
|
|
64095
66074
|
}
|
|
64096
66075
|
function callNestedFunction(fn, parentEnv, args, nargout) {
|
|
66076
|
+
const callInputNames = this.pendingInputNames;
|
|
66077
|
+
this.pendingInputNames = void 0;
|
|
64097
66078
|
const fnEnv = new Environment(parentEnv);
|
|
64098
66079
|
fnEnv.isNested = true;
|
|
64099
66080
|
fnEnv.rt = this.rt;
|
|
64100
66081
|
fnEnv.persistentFuncId = `${this.currentFile}:${fn.name}`;
|
|
66082
|
+
fnEnv.nestedLocalNames = /* @__PURE__ */ new Set([...fn.params, ...fn.outputs]);
|
|
64101
66083
|
const hasVarargin = fn.params.length > 0 && fn.params[fn.params.length - 1] === "varargin";
|
|
64102
66084
|
const regularParams = hasVarargin ? fn.params.slice(0, -1) : fn.params;
|
|
64103
66085
|
for (let i = 0; i < regularParams.length; i++) {
|
|
@@ -64111,6 +66093,15 @@ function callNestedFunction(fn, parentEnv, args, nargout) {
|
|
|
64111
66093
|
}
|
|
64112
66094
|
fnEnv.setLocal("$nargin", args.length);
|
|
64113
66095
|
fnEnv.setLocal("$nargout", nargout);
|
|
66096
|
+
fnEnv.inputArgNames = callInputNames;
|
|
66097
|
+
for (const stmt of fn.body) {
|
|
66098
|
+
if (stmt.type === "Function") {
|
|
66099
|
+
fnEnv.nestedFunctions.set(stmt.name, {
|
|
66100
|
+
fn: funcDefFromStmt(stmt),
|
|
66101
|
+
env: fnEnv
|
|
66102
|
+
});
|
|
66103
|
+
}
|
|
66104
|
+
}
|
|
64114
66105
|
const savedEnv = this.env;
|
|
64115
66106
|
this.env = fnEnv;
|
|
64116
66107
|
this.rt.pushCleanupScope();
|
|
@@ -64249,7 +66240,7 @@ function findMethodInClass(classInfo, methodName) {
|
|
|
64249
66240
|
const cacheKey = `method:${classInfo.name}:${methodName}`;
|
|
64250
66241
|
const cached = this.functionDefCache.get(cacheKey);
|
|
64251
66242
|
if (cached) return cached;
|
|
64252
|
-
for (const member of classInfo.ast
|
|
66243
|
+
for (const member of classInfo.ast?.members ?? []) {
|
|
64253
66244
|
if (member.type !== "Methods") continue;
|
|
64254
66245
|
for (const methodStmt of member.body) {
|
|
64255
66246
|
if (methodStmt.type === "Function" && methodStmt.name === methodName) {
|
|
@@ -64306,6 +66297,36 @@ function collectClassProperties(classInfo) {
|
|
|
64306
66297
|
}
|
|
64307
66298
|
return { propertyNames, propertyDefaults };
|
|
64308
66299
|
}
|
|
66300
|
+
function classPublicProperties(interp, className) {
|
|
66301
|
+
let info = interp.ctx.getClassInfo(className);
|
|
66302
|
+
if (!info) return void 0;
|
|
66303
|
+
const out = [];
|
|
66304
|
+
const seen = /* @__PURE__ */ new Set();
|
|
66305
|
+
while (info) {
|
|
66306
|
+
const ast = info.ast;
|
|
66307
|
+
if (ast) {
|
|
66308
|
+
for (const member of ast.members) {
|
|
66309
|
+
if (member.type !== "Properties") continue;
|
|
66310
|
+
const hidden = member.attributes.some((a) => {
|
|
66311
|
+
const n = a.name.toLowerCase();
|
|
66312
|
+
if (n !== "access" && n !== "getaccess") return false;
|
|
66313
|
+
const val = (a.value ?? "").toLowerCase();
|
|
66314
|
+
return val === "private" || val === "protected";
|
|
66315
|
+
});
|
|
66316
|
+
if (hidden) continue;
|
|
66317
|
+
for (const pn of member.names) {
|
|
66318
|
+
if (!seen.has(pn)) {
|
|
66319
|
+
seen.add(pn);
|
|
66320
|
+
out.push(pn);
|
|
66321
|
+
}
|
|
66322
|
+
}
|
|
66323
|
+
}
|
|
66324
|
+
}
|
|
66325
|
+
if (!info.superClass || info.superClass === "handle") break;
|
|
66326
|
+
info = interp.ctx.getClassInfo(info.superClass);
|
|
66327
|
+
}
|
|
66328
|
+
return out;
|
|
66329
|
+
}
|
|
64309
66330
|
function isHandleClass(classInfo) {
|
|
64310
66331
|
let parentName = classInfo.superClass;
|
|
64311
66332
|
while (parentName) {
|
|
@@ -64424,6 +66445,10 @@ var Interpreter = class {
|
|
|
64424
66445
|
workspaceEnv;
|
|
64425
66446
|
/** @internal The caller's environment — for evalin/assignin('caller', ...) */
|
|
64426
66447
|
callerEnv;
|
|
66448
|
+
/** @internal Call-site variable names for the next user-function call, set
|
|
66449
|
+
* by `evalFuncCall` and consumed by `callUserFunction` to support
|
|
66450
|
+
* `inputname`. One-shot: cleared as soon as it is consumed. */
|
|
66451
|
+
pendingInputNames;
|
|
64427
66452
|
/** @internal Stack of [base, dimIndex, numIndices] for resolving `end` keyword in indexing. */
|
|
64428
66453
|
endContextStack = [];
|
|
64429
66454
|
/** @internal Number of enclosing `for` / `while` loop bodies the
|
|
@@ -64685,6 +66710,37 @@ function extractClassInfo(classDef, qualifiedName, fileName, source) {
|
|
|
64685
66710
|
externalMethodFiles: /* @__PURE__ */ new Map()
|
|
64686
66711
|
};
|
|
64687
66712
|
}
|
|
66713
|
+
function makeOldStyleClassInfo(qualifiedName, baseName, constructorFile, methodFiles) {
|
|
66714
|
+
const externalMethodFiles = /* @__PURE__ */ new Map();
|
|
66715
|
+
externalMethodFiles.set(baseName, {
|
|
66716
|
+
fileName: constructorFile.fileName,
|
|
66717
|
+
source: constructorFile.source
|
|
66718
|
+
});
|
|
66719
|
+
const methodNames = /* @__PURE__ */ new Set();
|
|
66720
|
+
for (const mf of methodFiles) {
|
|
66721
|
+
externalMethodFiles.set(mf.name, {
|
|
66722
|
+
fileName: mf.fileName,
|
|
66723
|
+
source: mf.source
|
|
66724
|
+
});
|
|
66725
|
+
methodNames.add(mf.name);
|
|
66726
|
+
}
|
|
66727
|
+
return {
|
|
66728
|
+
name: baseName,
|
|
66729
|
+
qualifiedName,
|
|
66730
|
+
fileName: constructorFile.fileName,
|
|
66731
|
+
source: constructorFile.source,
|
|
66732
|
+
superClass: null,
|
|
66733
|
+
propertyNames: [],
|
|
66734
|
+
propertyDefaults: /* @__PURE__ */ new Map(),
|
|
66735
|
+
methodNames,
|
|
66736
|
+
staticMethodNames: /* @__PURE__ */ new Set(),
|
|
66737
|
+
constructorName: baseName,
|
|
66738
|
+
inferiorClasses: [],
|
|
66739
|
+
ast: null,
|
|
66740
|
+
isOldStyle: true,
|
|
66741
|
+
externalMethodFiles
|
|
66742
|
+
};
|
|
66743
|
+
}
|
|
64688
66744
|
|
|
64689
66745
|
// src/numbl-core/lowering/loweringContext.ts
|
|
64690
66746
|
function createWorkspaceRegistry() {
|
|
@@ -64877,8 +66933,41 @@ var LoweringContext = class _LoweringContext {
|
|
|
64877
66933
|
}
|
|
64878
66934
|
}
|
|
64879
66935
|
}
|
|
66936
|
+
const startsWithClassdef = (source) => {
|
|
66937
|
+
let t = source.trimStart();
|
|
66938
|
+
while (t.startsWith("%")) {
|
|
66939
|
+
const nl = t.indexOf("\n");
|
|
66940
|
+
if (nl < 0) return false;
|
|
66941
|
+
t = t.slice(nl + 1).trimStart();
|
|
66942
|
+
}
|
|
66943
|
+
return t.startsWith("classdef");
|
|
66944
|
+
};
|
|
64880
66945
|
for (const [className, group] of classFolderGroups) {
|
|
64881
|
-
|
|
66946
|
+
const hasRealClassdef = !!group.classDefFile && startsWithClassdef(group.classDefFile.source);
|
|
66947
|
+
if (!hasRealClassdef) {
|
|
66948
|
+
const dotIdx = className.lastIndexOf(".");
|
|
66949
|
+
const baseName = dotIdx >= 0 ? className.slice(dotIdx + 1) : className;
|
|
66950
|
+
const methodBase = (f) => f.name.split("/").pop().replace(/\.m$/, "");
|
|
66951
|
+
const ctorFile = group.classDefFile ?? group.methodFiles.find((f) => methodBase(f) === baseName);
|
|
66952
|
+
if (!ctorFile) {
|
|
66953
|
+
continue;
|
|
66954
|
+
}
|
|
66955
|
+
const methodFiles = group.methodFiles.filter((f) => f !== ctorFile).map((f) => ({
|
|
66956
|
+
name: methodBase(f),
|
|
66957
|
+
fileName: f.name,
|
|
66958
|
+
source: f.source
|
|
66959
|
+
}));
|
|
66960
|
+
if (!this.registry.classesByName.has(className)) {
|
|
66961
|
+
this.registry.classesByName.set(
|
|
66962
|
+
className,
|
|
66963
|
+
makeOldStyleClassInfo(
|
|
66964
|
+
className,
|
|
66965
|
+
baseName,
|
|
66966
|
+
{ fileName: ctorFile.name, source: ctorFile.source },
|
|
66967
|
+
methodFiles
|
|
66968
|
+
)
|
|
66969
|
+
);
|
|
66970
|
+
}
|
|
64882
66971
|
continue;
|
|
64883
66972
|
}
|
|
64884
66973
|
this.registerWorkspaceClass(className, group.classDefFile);
|
|
@@ -65114,7 +67203,7 @@ var LoweringContext = class _LoweringContext {
|
|
|
65114
67203
|
if (!info) return null;
|
|
65115
67204
|
if (info.ctx) return info.ctx;
|
|
65116
67205
|
const ctx = new _LoweringContext(info.source, info.fileName);
|
|
65117
|
-
for (const member of info.ast
|
|
67206
|
+
for (const member of info.ast?.members ?? []) {
|
|
65118
67207
|
if (member.type !== "Methods") continue;
|
|
65119
67208
|
for (const methodStmt of member.body) {
|
|
65120
67209
|
if (methodStmt.type !== "Function") continue;
|
|
@@ -65273,6 +67362,7 @@ var LoweringContext = class _LoweringContext {
|
|
|
65273
67362
|
for (const m of info.methodNames) instanceMethods.add(m);
|
|
65274
67363
|
for (const m of info.staticMethodNames) staticMethods.add(m);
|
|
65275
67364
|
for (const m of info.externalMethodFiles.keys()) {
|
|
67365
|
+
if (info.isOldStyle && m === info.constructorName) continue;
|
|
65276
67366
|
if (!info.staticMethodNames.has(m)) {
|
|
65277
67367
|
instanceMethods.add(m);
|
|
65278
67368
|
}
|
|
@@ -65316,10 +67406,43 @@ var LoweringContext = class _LoweringContext {
|
|
|
65316
67406
|
}
|
|
65317
67407
|
}
|
|
65318
67408
|
const fileImports = /* @__PURE__ */ new Map();
|
|
67409
|
+
const gatherImports = (body, out) => {
|
|
67410
|
+
for (const stmt of body) {
|
|
67411
|
+
switch (stmt.type) {
|
|
67412
|
+
case "Import":
|
|
67413
|
+
out.push(stmt);
|
|
67414
|
+
break;
|
|
67415
|
+
case "Function":
|
|
67416
|
+
case "While":
|
|
67417
|
+
case "For":
|
|
67418
|
+
gatherImports(stmt.body, out);
|
|
67419
|
+
break;
|
|
67420
|
+
case "If":
|
|
67421
|
+
gatherImports(stmt.thenBody, out);
|
|
67422
|
+
for (const b of stmt.elseifBlocks) gatherImports(b.body, out);
|
|
67423
|
+
if (stmt.elseBody) gatherImports(stmt.elseBody, out);
|
|
67424
|
+
break;
|
|
67425
|
+
case "Switch":
|
|
67426
|
+
for (const c of stmt.cases) gatherImports(c.body, out);
|
|
67427
|
+
if (stmt.otherwise) gatherImports(stmt.otherwise, out);
|
|
67428
|
+
break;
|
|
67429
|
+
case "TryCatch":
|
|
67430
|
+
gatherImports(stmt.tryBody, out);
|
|
67431
|
+
gatherImports(stmt.catchBody, out);
|
|
67432
|
+
break;
|
|
67433
|
+
case "ClassDef":
|
|
67434
|
+
for (const member of stmt.members) {
|
|
67435
|
+
if (member.type === "Methods") gatherImports(member.body, out);
|
|
67436
|
+
}
|
|
67437
|
+
break;
|
|
67438
|
+
}
|
|
67439
|
+
}
|
|
67440
|
+
};
|
|
65319
67441
|
const collectImportsFromBody = (body, fileName) => {
|
|
65320
67442
|
const entries = [];
|
|
65321
|
-
|
|
65322
|
-
|
|
67443
|
+
const importStmts = [];
|
|
67444
|
+
gatherImports(body, importStmts);
|
|
67445
|
+
for (const stmt of importStmts) {
|
|
65323
67446
|
if (stmt.wildcard) {
|
|
65324
67447
|
entries.push({ wildcard: true, namespace: stmt.path.join(".") });
|
|
65325
67448
|
} else {
|
|
@@ -65394,6 +67517,10 @@ var LoweringContext = class _LoweringContext {
|
|
|
65394
67517
|
|
|
65395
67518
|
// src/numbl-core/stdlib-bundle.ts
|
|
65396
67519
|
var stdlibFiles = [
|
|
67520
|
+
{
|
|
67521
|
+
name: "TriRep.m",
|
|
67522
|
+
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"
|
|
67523
|
+
},
|
|
65397
67524
|
{
|
|
65398
67525
|
name: "addOptional.m",
|
|
65399
67526
|
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"
|
|
@@ -65421,6 +67548,10 @@ var stdlibFiles = [
|
|
|
65421
67548
|
{
|
|
65422
67549
|
name: "readmatrix.m",
|
|
65423
67550
|
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"
|
|
67551
|
+
},
|
|
67552
|
+
{
|
|
67553
|
+
name: "triangulation.m",
|
|
67554
|
+
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"
|
|
65424
67555
|
}
|
|
65425
67556
|
];
|
|
65426
67557
|
var shimFiles = [
|
|
@@ -87684,6 +89815,7 @@ var Workspace = class _Workspace {
|
|
|
87684
89815
|
}
|
|
87685
89816
|
};
|
|
87686
89817
|
for (const [name, info] of this.ctx.registry.classesByName) {
|
|
89818
|
+
if (info.isOldStyle) continue;
|
|
87687
89819
|
registerOrDefer(
|
|
87688
89820
|
name,
|
|
87689
89821
|
() => registerClassDef(
|
|
@@ -87697,7 +89829,7 @@ var Workspace = class _Workspace {
|
|
|
87697
89829
|
if (this.classes.has(name) || this.failedClassValidations.has(name)) {
|
|
87698
89830
|
throw new UnsupportedConstruct(
|
|
87699
89831
|
`class '${name}' is defined both locally and as a workspace class`,
|
|
87700
|
-
info.ast
|
|
89832
|
+
info.ast?.span
|
|
87701
89833
|
);
|
|
87702
89834
|
}
|
|
87703
89835
|
registerOrDefer(name, () => registerClassDef(info.ast, info.fileName));
|
|
@@ -87791,7 +89923,7 @@ var Workspace = class _Workspace {
|
|
|
87791
89923
|
if (!ast) {
|
|
87792
89924
|
throw new UnsupportedConstruct(
|
|
87793
89925
|
`internal: external method file '${mf.fileName}' for '${info.qualifiedName}.${methodName}' was not parsed`,
|
|
87794
|
-
info.ast
|
|
89926
|
+
info.ast?.span
|
|
87795
89927
|
);
|
|
87796
89928
|
}
|
|
87797
89929
|
let primary = null;
|
|
@@ -87807,7 +89939,7 @@ var Workspace = class _Workspace {
|
|
|
87807
89939
|
if (!primary) {
|
|
87808
89940
|
throw new UnsupportedConstruct(
|
|
87809
89941
|
`external method file '${mf.fileName}' has no function`,
|
|
87810
|
-
info.ast
|
|
89942
|
+
info.ast?.span
|
|
87811
89943
|
);
|
|
87812
89944
|
}
|
|
87813
89945
|
out.set(methodName, primary);
|
|
@@ -89191,6 +91323,7 @@ async function load() {
|
|
|
89191
91323
|
const { loadQhull } = await import("qhull-wasm");
|
|
89192
91324
|
const qhull = await loadQhull();
|
|
89193
91325
|
setDelaunayBackend((points, dim) => qhull.delaunay(points, dim).facets);
|
|
91326
|
+
setConvexHullBackend((points, dim) => qhull.convexHull(points, dim).facets);
|
|
89194
91327
|
}
|
|
89195
91328
|
export {
|
|
89196
91329
|
RTV,
|