numbl 0.4.16 → 0.4.18

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 CHANGED
@@ -23232,6 +23232,7 @@ function indexIntoRTValue(base, indices) {
23232
23232
  if (isRuntimeLogical(idx)) return idx === true;
23233
23233
  if (isRuntimeTensor(idx))
23234
23234
  return idx.data.length === 1 && Math.round(idx.data[0]) === 1;
23235
+ if (isColonIndex(idx)) return true;
23235
23236
  return false;
23236
23237
  });
23237
23238
  if (allOnes) return base;
@@ -23243,6 +23244,9 @@ function indexIntoRTValue(base, indices) {
23243
23244
  if (isRuntimeStructArray(base)) {
23244
23245
  if (indices.length === 1) {
23245
23246
  const idx = indices[0];
23247
+ if (isColonIndex(idx)) {
23248
+ return RTV.structArray(base.fieldNames, [...base.elements]);
23249
+ }
23246
23250
  if (isRuntimeNumber(idx)) {
23247
23251
  const i = Math.round(idx) - 1;
23248
23252
  if (i < 0 || i >= base.elements.length)
@@ -27570,7 +27574,7 @@ function sprintfFormat(fmt, args) {
27570
27574
  if (fmt[i] === "%" && i + 1 < fmt.length) {
27571
27575
  i++;
27572
27576
  let spec = "%";
27573
- while (i < fmt.length && !"dfigeEsoxXuc%".includes(fmt[i])) {
27577
+ while (i < fmt.length && !"dfigGeEsoxXuc%".includes(fmt[i])) {
27574
27578
  if (fmt[i] === "*") {
27575
27579
  if (argIdx >= flatArgs.length) {
27576
27580
  outOfArgs = true;
@@ -27660,7 +27664,7 @@ function sprintfFormat(fmt, args) {
27660
27664
  const gPrec = precMatch ? parseInt(precMatch[1]) : 6;
27661
27665
  let gStr;
27662
27666
  if (gVal === 0) {
27663
- gStr = "0";
27667
+ gStr = Object.is(gVal, -0) ? "-0" : "0";
27664
27668
  } else {
27665
27669
  const exp2 = Math.floor(Math.log10(Math.abs(gVal)));
27666
27670
  if (exp2 < -4 || exp2 >= gPrec) {
@@ -31936,6 +31940,9 @@ var ExpressionParser = class extends ParserBase {
31936
31940
  if (this.peekToken() === 50 /* LParen */ && this.inMatrixExpr && this.pos > 0 && !this.tokensAdjacent(this.pos - 1, this.pos)) {
31937
31941
  break;
31938
31942
  }
31943
+ if (this.peekToken() === 54 /* LBrace */ && this.inMatrixExpr && this.pos > 0 && !this.tokensAdjacent(this.pos - 1, this.pos)) {
31944
+ break;
31945
+ }
31939
31946
  if (this.consume(50 /* LParen */)) {
31940
31947
  const start = expr.span.start;
31941
31948
  const args = [];
@@ -36810,14 +36817,20 @@ function dictRemove(d, keysArg) {
36810
36817
  }
36811
36818
  return RTV.dictionary(entries, d.keyType, d.valueType);
36812
36819
  }
36813
- function dictLookup(d, keysArg) {
36820
+ function dictLookup(d, keysArg, fallbackValue) {
36814
36821
  const keys = expandKeys(keysArg);
36815
36822
  const results = [];
36816
36823
  for (const k of keys) {
36817
36824
  const coerced = d.keyType ? coerceKey(k, d.keyType) : k;
36818
36825
  const h = hashKey(coerced);
36819
36826
  const entry = d.entries.get(h);
36820
- if (!entry) throw new RuntimeError("Key not found in dictionary");
36827
+ if (!entry) {
36828
+ if (fallbackValue !== void 0) {
36829
+ results.push(fallbackValue);
36830
+ continue;
36831
+ }
36832
+ throw new RuntimeError("Key not found in dictionary");
36833
+ }
36821
36834
  results.push(entry.value);
36822
36835
  }
36823
36836
  if (results.length === 1) return results[0];
@@ -37052,11 +37065,21 @@ registerIBuiltin({
37052
37065
  registerIBuiltin({
37053
37066
  name: "lookup",
37054
37067
  resolve: (argTypes) => {
37055
- if (argTypes.length !== 2 || argTypes[0].kind !== "dictionary") return null;
37068
+ if (argTypes.length !== 2 && argTypes.length !== 4 || argTypes[0].kind !== "dictionary")
37069
+ return null;
37056
37070
  return {
37057
37071
  outputTypes: [{ kind: "unknown" }],
37058
37072
  apply: (args) => {
37059
37073
  const d = args[0];
37074
+ if (args.length === 4) {
37075
+ const optName = isRuntimeChar(args[2]) ? args[2].value : isRuntimeString(args[2]) ? args[2] : "";
37076
+ if (String(optName).toLowerCase() !== "fallbackvalue") {
37077
+ throw new RuntimeError(
37078
+ `Unrecognized option '${String(optName)}' for lookup`
37079
+ );
37080
+ }
37081
+ return dictLookup(d, args[1], args[3]);
37082
+ }
37060
37083
  return dictLookup(d, args[1]);
37061
37084
  }
37062
37085
  };
@@ -40184,33 +40207,66 @@ function registerSpecialBuiltins(rt) {
40184
40207
  };
40185
40208
  }
40186
40209
  });
40210
+ const warningStateOff = /* @__PURE__ */ new Set();
40187
40211
  registerSpecial("warning", (nargout, args) => {
40188
40212
  if (args.length === 0) return nargout >= 1 ? RTV.num(0) : void 0;
40189
40213
  const margs = args.map((a) => ensureRuntimeValue(a));
40214
+ const isOff = (id) => warningStateOff.has(id) || warningStateOff.has("all");
40215
+ const stateStruct = (id) => RTV.struct(
40216
+ /* @__PURE__ */ new Map([
40217
+ ["identifier", RTV.char(id)],
40218
+ ["state", RTV.char(isOff(id) ? "off" : "on")]
40219
+ ])
40220
+ );
40221
+ const setState = (mode, id) => {
40222
+ if (mode === "off") warningStateOff.add(id);
40223
+ else {
40224
+ warningStateOff.delete(id);
40225
+ if (id === "all") warningStateOff.clear();
40226
+ }
40227
+ };
40228
+ const restoreFrom = (s) => {
40229
+ if (!isRuntimeStruct(s)) return false;
40230
+ const idField = s.fields.get("identifier");
40231
+ const stField = s.fields.get("state");
40232
+ if (idField === void 0 || stField === void 0) return false;
40233
+ setState(toString(stField), toString(idField));
40234
+ return true;
40235
+ };
40236
+ if (margs.length === 1 && isRuntimeStruct(margs[0])) {
40237
+ if (restoreFrom(margs[0])) return nargout >= 1 ? RTV.num(0) : void 0;
40238
+ }
40239
+ if (margs.length === 1 && isRuntimeStructArray(margs[0])) {
40240
+ for (const el of margs[0].elements) restoreFrom(el);
40241
+ return nargout >= 1 ? RTV.num(0) : void 0;
40242
+ }
40243
+ if (margs.length === 1 && isRuntimeChar(margs[0])) {
40244
+ const mode = toString(margs[0]);
40245
+ if (mode === "on" || mode === "off") {
40246
+ const prev = stateStruct("all");
40247
+ setState(mode, "all");
40248
+ return nargout >= 1 ? prev : void 0;
40249
+ }
40250
+ }
40190
40251
  if (margs.length === 2 && isRuntimeChar(margs[0]) && isRuntimeChar(margs[1])) {
40191
40252
  const mode = toString(margs[0]);
40253
+ const id = toString(margs[1]);
40192
40254
  if (mode === "on" || mode === "off") {
40193
- if (nargout === 0) return void 0;
40194
- return RTV.struct(
40195
- /* @__PURE__ */ new Map([
40196
- ["state", RTV.char("on")],
40197
- ["identifier", margs[1]]
40198
- ])
40199
- );
40255
+ const prev = stateStruct(id);
40256
+ setState(mode, id);
40257
+ return nargout >= 1 ? prev : void 0;
40200
40258
  }
40201
40259
  if (mode === "query") {
40202
- return RTV.struct(
40203
- /* @__PURE__ */ new Map([
40204
- ["state", RTV.char("on")],
40205
- ["identifier", margs[1]]
40206
- ])
40207
- );
40260
+ return stateStruct(id);
40208
40261
  }
40209
40262
  }
40210
40263
  let fmtIdx = 0;
40211
40264
  if (margs.length >= 2 && isRuntimeChar(margs[0]) && toString(margs[0]).includes(":")) {
40212
40265
  fmtIdx = 1;
40213
40266
  }
40267
+ if (isOff(fmtIdx === 1 ? toString(margs[0]) : "all")) {
40268
+ return nargout >= 1 ? RTV.num(0) : void 0;
40269
+ }
40214
40270
  const fmt = toString(margs[fmtIdx]);
40215
40271
  const fmtArgs = [];
40216
40272
  for (let i = fmtIdx + 1; i < margs.length; i++) {
@@ -42747,7 +42803,7 @@ function _complexLuFactor(n, re, im, ipiv) {
42747
42803
  }
42748
42804
 
42749
42805
  // src/numbl-core/runtime/runtimeMemberAccess.ts
42750
- function getMember(rt, base, name) {
42806
+ function getMember(rt, base, name, nargout = 1) {
42751
42807
  const mv = ensureRuntimeValue(base);
42752
42808
  if (isRuntimeClassInstance(mv)) {
42753
42809
  const accessorKey = `${mv.className}.get.${name}`;
@@ -42766,7 +42822,7 @@ function getMember(rt, base, name) {
42766
42822
  if (field !== void 0) return field;
42767
42823
  const method = rt.cachedResolveClassMethod(mv.className, name);
42768
42824
  if (method) {
42769
- return method(1, base);
42825
+ return method(nargout, base);
42770
42826
  }
42771
42827
  const guardKey = `${mv.className}.subsref`;
42772
42828
  if (!rt.activeAccessors.has(guardKey)) {
@@ -45470,8 +45526,8 @@ var Runtime = class _Runtime {
45470
45526
  return multiOutputCellAssign(base, indices, results, this);
45471
45527
  }
45472
45528
  // ── Member access ───────────────────────────────────────────────────
45473
- getMember(base, name) {
45474
- return getMember(this, base, name);
45529
+ getMember(base, name, nargout = 1) {
45530
+ return getMember(this, base, name, nargout);
45475
45531
  }
45476
45532
  getMemberDynamic(base, nameExpr) {
45477
45533
  return getMemberDynamic(this, base, nameExpr);
@@ -51363,6 +51419,46 @@ function uniquetolElements(v, nargout, tol) {
51363
51419
  if (nargout === 2) return [C, ia];
51364
51420
  return [C, ia, icTensor];
51365
51421
  }
51422
+ defineBuiltin({
51423
+ name: "ismembc2",
51424
+ cases: [
51425
+ {
51426
+ match: (argTypes) => {
51427
+ if (argTypes.length !== 2) return null;
51428
+ return [{ kind: "tensor", isComplex: false }];
51429
+ },
51430
+ apply: (args) => {
51431
+ const toFlat = (v) => {
51432
+ if (isRuntimeNumber(v)) return [v];
51433
+ if (isRuntimeLogical(v)) return [v ? 1 : 0];
51434
+ if (isRuntimeTensor(v)) return v.data;
51435
+ throw new RuntimeError("ismembc2: arguments must be numeric");
51436
+ };
51437
+ const a = toFlat(args[0]);
51438
+ const s = toFlat(args[1]);
51439
+ const out = allocFloat64Array(a.length);
51440
+ for (let i = 0; i < a.length; i++) {
51441
+ const x = a[i];
51442
+ let lo = 0;
51443
+ let hi = s.length - 1;
51444
+ let res = 0;
51445
+ while (lo <= hi) {
51446
+ const mid = lo + hi >> 1;
51447
+ if (s[mid] <= x) {
51448
+ if (s[mid] === x) res = mid + 1;
51449
+ lo = mid + 1;
51450
+ } else {
51451
+ hi = mid - 1;
51452
+ }
51453
+ }
51454
+ out[i] = res;
51455
+ }
51456
+ const shape = isRuntimeTensor(args[0]) ? [...args[0].shape] : [1, 1];
51457
+ return RTV.tensor(out, shape);
51458
+ }
51459
+ }
51460
+ ]
51461
+ });
51366
51462
 
51367
51463
  // src/numbl-core/interpreter/builtins/linear-algebra.ts
51368
51464
  function isNumericJitType(t) {
@@ -57541,6 +57637,45 @@ defineBuiltin({
57541
57637
  },
57542
57638
  apply: (args) => {
57543
57639
  const xArr = toFloatArray(args[0]);
57640
+ if (args.length === 4 && isRuntimeChar(args[2]) && isRuntimeChar(args[3]) && args[3].value.toLowerCase() === "pp") {
57641
+ const method2 = args[2].value.toLowerCase();
57642
+ if (method2 !== "linear")
57643
+ throw new RuntimeError(
57644
+ `interp1: 'pp' output is only supported for 'linear' method (got '${method2}')`
57645
+ );
57646
+ const yArr = toFloatArray(args[1]);
57647
+ const n = xArr.length;
57648
+ if (yArr.length !== n)
57649
+ throw new RuntimeError(
57650
+ "interp1: x and y must have the same length"
57651
+ );
57652
+ if (n < 2)
57653
+ throw new RuntimeError(
57654
+ "interp1: at least 2 sample points are required"
57655
+ );
57656
+ for (let i = 0; i + 1 < n; i++) {
57657
+ if (!(xArr[i] < xArr[i + 1]))
57658
+ throw new RuntimeError(
57659
+ "interp1: sample points must be unique and sorted for 'pp' output"
57660
+ );
57661
+ }
57662
+ const L = n - 1;
57663
+ const breaksOut = allocFloat64Array(n);
57664
+ for (let i = 0; i < n; i++) breaksOut[i] = xArr[i];
57665
+ const coefs = allocFloat64Array(L * 2);
57666
+ for (let i = 0; i < L; i++) {
57667
+ coefs[i] = (yArr[i + 1] - yArr[i]) / (xArr[i + 1] - xArr[i]);
57668
+ coefs[L + i] = yArr[i];
57669
+ }
57670
+ const fields = /* @__PURE__ */ new Map();
57671
+ fields.set("form", "pp");
57672
+ fields.set("breaks", RTV.tensor(breaksOut, [1, n]));
57673
+ fields.set("coefs", RTV.tensor(coefs, [L, 2]));
57674
+ fields.set("pieces", L);
57675
+ fields.set("order", 2);
57676
+ fields.set("dim", 1);
57677
+ return RTV.struct(fields);
57678
+ }
57544
57679
  const xqArg = args[2];
57545
57680
  const nn = xArr.length;
57546
57681
  const yVal = args[1];
@@ -57569,6 +57704,7 @@ defineBuiltin({
57569
57704
  throw new RuntimeError("interp1: x and y must have the same length");
57570
57705
  let method = "linear";
57571
57706
  let doExtrap = false;
57707
+ let fillValue = NaN;
57572
57708
  for (let i = 3; i < args.length; i++) {
57573
57709
  const a = args[i];
57574
57710
  if (isRuntimeChar(a)) {
@@ -57579,11 +57715,13 @@ defineBuiltin({
57579
57715
  const s = a.toLowerCase();
57580
57716
  if (s === "extrap") doExtrap = true;
57581
57717
  else method = s;
57718
+ } else if (isRuntimeNumber(a) || isRuntimeTensor(a)) {
57719
+ fillValue = toNumber(a);
57582
57720
  }
57583
57721
  }
57584
57722
  const interpOne = (yArr, xq) => {
57585
57723
  if (xq < xArr[0] || xq > xArr[nn - 1]) {
57586
- if (!doExtrap) return NaN;
57724
+ if (!doExtrap) return fillValue;
57587
57725
  if (method === "linear") {
57588
57726
  if (xq < xArr[0]) {
57589
57727
  const slope = (yArr[1] - yArr[0]) / (xArr[1] - xArr[0]);
@@ -58014,6 +58152,63 @@ function dimArgToVec(v) {
58014
58152
  }
58015
58153
  throw new RuntimeError("mkpp: dim must be a numeric scalar or vector");
58016
58154
  }
58155
+ var ppIntApply = (fname) => (args) => {
58156
+ const pp = args[0];
58157
+ if (!isRuntimeStruct(pp))
58158
+ throw new RuntimeError(`${fname}: argument must be a pp struct`);
58159
+ const breaksRT = pp.fields.get("breaks");
58160
+ const coefsRT = pp.fields.get("coefs");
58161
+ const piecesRT = pp.fields.get("pieces");
58162
+ const orderRT = pp.fields.get("order");
58163
+ const dimRT = pp.fields.get("dim");
58164
+ if (breaksRT === void 0 || coefsRT === void 0 || piecesRT === void 0 || orderRT === void 0)
58165
+ throw new RuntimeError(`${fname}: pp struct missing required fields`);
58166
+ const breaks = toFloatArray(breaksRT);
58167
+ const L = Math.round(toNumber(piecesRT));
58168
+ const k = Math.round(toNumber(orderRT));
58169
+ const dim = dimRT === void 0 ? [1] : dimArgToVec(dimRT);
58170
+ if (dim.reduce((a, b) => a * b, 1) !== 1)
58171
+ throw new RuntimeError(`${fname}: only scalar-valued pp is supported`);
58172
+ if (!isRuntimeTensor(coefsRT))
58173
+ throw new RuntimeError(`${fname}: pp.coefs must be a matrix`);
58174
+ const coefs = coefsRT.data;
58175
+ const out = allocFloat64Array(L * (k + 1));
58176
+ for (let c = 0; c < k; c++) {
58177
+ for (let i = 0; i < L; i++) out[c * L + i] = coefs[c * L + i] / (k - c);
58178
+ }
58179
+ let A = 0;
58180
+ for (let i = 0; i < L; i++) {
58181
+ out[k * L + i] = A;
58182
+ const h = breaks[i + 1] - breaks[i];
58183
+ let v = out[0 * L + i];
58184
+ for (let c = 1; c <= k; c++) v = v * h + out[c * L + i];
58185
+ A = v;
58186
+ }
58187
+ const fields = /* @__PURE__ */ new Map();
58188
+ fields.set("form", "pp");
58189
+ const breaksOut = allocFloat64Array(breaks.length);
58190
+ for (let i = 0; i < breaks.length; i++) breaksOut[i] = breaks[i];
58191
+ fields.set("breaks", RTV.tensor(breaksOut, [1, breaks.length]));
58192
+ fields.set("coefs", RTV.tensor(out, [L, k + 1]));
58193
+ fields.set("pieces", L);
58194
+ fields.set("order", k + 1);
58195
+ fields.set("dim", 1);
58196
+ return RTV.struct(fields);
58197
+ };
58198
+ for (const fname of ["fnint", "ppint"]) {
58199
+ defineBuiltin({
58200
+ name: fname,
58201
+ cases: [
58202
+ {
58203
+ match: (argTypes) => {
58204
+ if (argTypes.length !== 1) return null;
58205
+ return [{ kind: "struct", fields: {} }];
58206
+ },
58207
+ apply: ppIntApply(fname)
58208
+ }
58209
+ ]
58210
+ });
58211
+ }
58017
58212
  defineBuiltin({
58018
58213
  name: "mkpp",
58019
58214
  cases: [
@@ -58755,6 +58950,8 @@ defineBuiltin({
58755
58950
  {
58756
58951
  match: (argTypes) => {
58757
58952
  if (argTypes.length === 0) return [{ kind: "struct", fields: {} }];
58953
+ if (argTypes.length === 1 && argTypes[0].kind === "tensor")
58954
+ return [{ kind: "struct", fields: {} }];
58758
58955
  if (argTypes.length % 2 !== 0) return null;
58759
58956
  for (let i = 0; i < argTypes.length; i += 2) {
58760
58957
  const k = argTypes[i].kind;
@@ -58764,6 +58961,13 @@ defineBuiltin({
58764
58961
  },
58765
58962
  apply: (args) => {
58766
58963
  if (args.length === 0) return RTV.struct(/* @__PURE__ */ new Map());
58964
+ if (args.length === 1 && isRuntimeTensor(args[0])) {
58965
+ if (args[0].data.length !== 0)
58966
+ throw new RuntimeError(
58967
+ "struct: single non-empty numeric argument is not supported"
58968
+ );
58969
+ return RTV.structArray([], []);
58970
+ }
58767
58971
  if (args.length % 2 !== 0)
58768
58972
  throw new RuntimeError("struct: requires field-value pairs");
58769
58973
  const fieldNames = [];
@@ -59556,13 +59760,48 @@ registerIBuiltin({
59556
59760
  resolve: (argTypes) => {
59557
59761
  if (argTypes.length !== 1) return null;
59558
59762
  return {
59559
- outputTypes: [{ kind: "tensor", isComplex: false }],
59763
+ outputTypes: [{ kind: "unknown" }],
59560
59764
  apply: (args) => {
59561
59765
  const C = args[0];
59562
59766
  if (!isRuntimeCell(C))
59563
59767
  throw new RuntimeError("cell2mat: argument must be a cell array");
59564
59768
  const cellRows = C.shape[0];
59565
59769
  const cellCols = C.shape.length >= 2 ? C.shape[1] : 1;
59770
+ if (C.data.length > 0 && C.data.some((v) => isRuntimeChar(v))) {
59771
+ const asCharBlock = (v) => {
59772
+ if (!isRuntimeChar(v))
59773
+ throw new RuntimeError(
59774
+ "cell2mat: cannot mix char and non-char cell contents"
59775
+ );
59776
+ const rows = v.shape ? v.shape[0] : v.value.length === 0 ? 0 : 1;
59777
+ const cols = v.shape ? v.shape[1] : v.value.length;
59778
+ const rowStrings = [];
59779
+ for (let r = 0; r < rows; r++)
59780
+ rowStrings.push(v.value.slice(r * cols, (r + 1) * cols));
59781
+ return { rows, cols, rowStrings };
59782
+ };
59783
+ const outRows = [];
59784
+ for (let ci = 0; ci < cellRows; ci++) {
59785
+ const blockHeight = asCharBlock(C.data[ci]).rows;
59786
+ const lines = new Array(blockHeight).fill("");
59787
+ for (let cj = 0; cj < cellCols; cj++) {
59788
+ const b = asCharBlock(C.data[cj * cellRows + ci]);
59789
+ if (b.rows !== blockHeight)
59790
+ throw new RuntimeError(
59791
+ "cell2mat: inconsistent cell content sizes"
59792
+ );
59793
+ for (let r = 0; r < blockHeight; r++) lines[r] += b.rowStrings[r];
59794
+ }
59795
+ outRows.push(...lines);
59796
+ }
59797
+ const width = outRows.length > 0 ? outRows[0].length : 0;
59798
+ if (outRows.some((r) => r.length !== width))
59799
+ throw new RuntimeError("cell2mat: inconsistent cell content sizes");
59800
+ if (outRows.length <= 1) return RTV.char(outRows[0] ?? "");
59801
+ const rc = RTV.char(outRows.join(""));
59802
+ rc.shape = [outRows.length, width];
59803
+ return rc;
59804
+ }
59566
59805
  const asTensor = (v) => {
59567
59806
  if (isRuntimeNumber(v))
59568
59807
  return {
@@ -62085,6 +62324,288 @@ defineBuiltin({
62085
62324
  ]
62086
62325
  });
62087
62326
 
62327
+ // src/numbl-core/interpreter/builtins/hash.ts
62328
+ function valueToByteString(v) {
62329
+ if (isRuntimeChar(v)) return v.value;
62330
+ if (isRuntimeString(v)) return String(v);
62331
+ throw new RuntimeError("hash: STR must be a char array or string");
62332
+ }
62333
+ function md5Hex(input) {
62334
+ const bytes = [];
62335
+ for (let i = 0; i < input.length; i++) bytes.push(input.charCodeAt(i) & 255);
62336
+ const origLenBits = bytes.length * 8;
62337
+ bytes.push(128);
62338
+ while (bytes.length % 64 !== 56) bytes.push(0);
62339
+ let len = origLenBits;
62340
+ for (let i = 0; i < 8; i++) {
62341
+ bytes.push(len & 255);
62342
+ len = Math.floor(len / 256);
62343
+ }
62344
+ const S = [
62345
+ 7,
62346
+ 12,
62347
+ 17,
62348
+ 22,
62349
+ 7,
62350
+ 12,
62351
+ 17,
62352
+ 22,
62353
+ 7,
62354
+ 12,
62355
+ 17,
62356
+ 22,
62357
+ 7,
62358
+ 12,
62359
+ 17,
62360
+ 22,
62361
+ 5,
62362
+ 9,
62363
+ 14,
62364
+ 20,
62365
+ 5,
62366
+ 9,
62367
+ 14,
62368
+ 20,
62369
+ 5,
62370
+ 9,
62371
+ 14,
62372
+ 20,
62373
+ 5,
62374
+ 9,
62375
+ 14,
62376
+ 20,
62377
+ 4,
62378
+ 11,
62379
+ 16,
62380
+ 23,
62381
+ 4,
62382
+ 11,
62383
+ 16,
62384
+ 23,
62385
+ 4,
62386
+ 11,
62387
+ 16,
62388
+ 23,
62389
+ 4,
62390
+ 11,
62391
+ 16,
62392
+ 23,
62393
+ 6,
62394
+ 10,
62395
+ 15,
62396
+ 21,
62397
+ 6,
62398
+ 10,
62399
+ 15,
62400
+ 21,
62401
+ 6,
62402
+ 10,
62403
+ 15,
62404
+ 21,
62405
+ 6,
62406
+ 10,
62407
+ 15,
62408
+ 21
62409
+ ];
62410
+ const K = new Array(64);
62411
+ for (let i = 0; i < 64; i++)
62412
+ K[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 4294967296) >>> 0;
62413
+ let a0 = 1732584193;
62414
+ let b0 = 4023233417;
62415
+ let c0 = 2562383102;
62416
+ let d0 = 271733878;
62417
+ const rotl2 = (x, c) => (x << c | x >>> 32 - c) >>> 0;
62418
+ for (let chunk = 0; chunk < bytes.length; chunk += 64) {
62419
+ const M = new Array(16);
62420
+ for (let j = 0; j < 16; j++) {
62421
+ const o = chunk + j * 4;
62422
+ M[j] = (bytes[o] | bytes[o + 1] << 8 | bytes[o + 2] << 16 | bytes[o + 3] << 24) >>> 0;
62423
+ }
62424
+ let A = a0;
62425
+ let B = b0;
62426
+ let C = c0;
62427
+ let D = d0;
62428
+ for (let i = 0; i < 64; i++) {
62429
+ let F;
62430
+ let g;
62431
+ if (i < 16) {
62432
+ F = B & C | ~B & D;
62433
+ g = i;
62434
+ } else if (i < 32) {
62435
+ F = D & B | ~D & C;
62436
+ g = (5 * i + 1) % 16;
62437
+ } else if (i < 48) {
62438
+ F = B ^ C ^ D;
62439
+ g = (3 * i + 5) % 16;
62440
+ } else {
62441
+ F = C ^ (B | ~D);
62442
+ g = 7 * i % 16;
62443
+ }
62444
+ F = F + A + K[i] + M[g] >>> 0;
62445
+ A = D;
62446
+ D = C;
62447
+ C = B;
62448
+ B = B + rotl2(F, S[i]) >>> 0;
62449
+ }
62450
+ a0 = a0 + A >>> 0;
62451
+ b0 = b0 + B >>> 0;
62452
+ c0 = c0 + C >>> 0;
62453
+ d0 = d0 + D >>> 0;
62454
+ }
62455
+ const le2 = (w) => {
62456
+ let s = "";
62457
+ for (let i = 0; i < 4; i++)
62458
+ s += (w >>> i * 8 & 255).toString(16).padStart(2, "0");
62459
+ return s;
62460
+ };
62461
+ return le2(a0) + le2(b0) + le2(c0) + le2(d0);
62462
+ }
62463
+ function sha256Hex(input) {
62464
+ const bytes = [];
62465
+ for (let i = 0; i < input.length; i++) bytes.push(input.charCodeAt(i) & 255);
62466
+ const origLenBits = bytes.length * 8;
62467
+ bytes.push(128);
62468
+ while (bytes.length % 64 !== 56) bytes.push(0);
62469
+ const hi = Math.floor(origLenBits / 4294967296);
62470
+ const lo = origLenBits >>> 0;
62471
+ for (let i = 3; i >= 0; i--) bytes.push(hi >>> i * 8 & 255);
62472
+ for (let i = 3; i >= 0; i--) bytes.push(lo >>> i * 8 & 255);
62473
+ const K = [
62474
+ 1116352408,
62475
+ 1899447441,
62476
+ 3049323471,
62477
+ 3921009573,
62478
+ 961987163,
62479
+ 1508970993,
62480
+ 2453635748,
62481
+ 2870763221,
62482
+ 3624381080,
62483
+ 310598401,
62484
+ 607225278,
62485
+ 1426881987,
62486
+ 1925078388,
62487
+ 2162078206,
62488
+ 2614888103,
62489
+ 3248222580,
62490
+ 3835390401,
62491
+ 4022224774,
62492
+ 264347078,
62493
+ 604807628,
62494
+ 770255983,
62495
+ 1249150122,
62496
+ 1555081692,
62497
+ 1996064986,
62498
+ 2554220882,
62499
+ 2821834349,
62500
+ 2952996808,
62501
+ 3210313671,
62502
+ 3336571891,
62503
+ 3584528711,
62504
+ 113926993,
62505
+ 338241895,
62506
+ 666307205,
62507
+ 773529912,
62508
+ 1294757372,
62509
+ 1396182291,
62510
+ 1695183700,
62511
+ 1986661051,
62512
+ 2177026350,
62513
+ 2456956037,
62514
+ 2730485921,
62515
+ 2820302411,
62516
+ 3259730800,
62517
+ 3345764771,
62518
+ 3516065817,
62519
+ 3600352804,
62520
+ 4094571909,
62521
+ 275423344,
62522
+ 430227734,
62523
+ 506948616,
62524
+ 659060556,
62525
+ 883997877,
62526
+ 958139571,
62527
+ 1322822218,
62528
+ 1537002063,
62529
+ 1747873779,
62530
+ 1955562222,
62531
+ 2024104815,
62532
+ 2227730452,
62533
+ 2361852424,
62534
+ 2428436474,
62535
+ 2756734187,
62536
+ 3204031479,
62537
+ 3329325298
62538
+ ];
62539
+ const H2 = [
62540
+ 1779033703,
62541
+ 3144134277,
62542
+ 1013904242,
62543
+ 2773480762,
62544
+ 1359893119,
62545
+ 2600822924,
62546
+ 528734635,
62547
+ 1541459225
62548
+ ];
62549
+ const rotr = (x, c) => (x >>> c | x << 32 - c) >>> 0;
62550
+ for (let chunk = 0; chunk < bytes.length; chunk += 64) {
62551
+ const W = new Array(64);
62552
+ for (let j = 0; j < 16; j++) {
62553
+ const o = chunk + j * 4;
62554
+ W[j] = (bytes[o] << 24 | bytes[o + 1] << 16 | bytes[o + 2] << 8 | bytes[o + 3]) >>> 0;
62555
+ }
62556
+ for (let j = 16; j < 64; j++) {
62557
+ const s0 = rotr(W[j - 15], 7) ^ rotr(W[j - 15], 18) ^ W[j - 15] >>> 3;
62558
+ const s1 = rotr(W[j - 2], 17) ^ rotr(W[j - 2], 19) ^ W[j - 2] >>> 10;
62559
+ W[j] = W[j - 16] + s0 + W[j - 7] + s1 >>> 0;
62560
+ }
62561
+ let [a, b, c, d, e, f, g, h] = H2;
62562
+ for (let j = 0; j < 64; j++) {
62563
+ const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
62564
+ const ch = e & f ^ ~e & g;
62565
+ const t1 = h + S1 + ch + K[j] + W[j] >>> 0;
62566
+ const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
62567
+ const maj = a & b ^ a & c ^ b & c;
62568
+ const t2 = S0 + maj >>> 0;
62569
+ h = g;
62570
+ g = f;
62571
+ f = e;
62572
+ e = d + t1 >>> 0;
62573
+ d = c;
62574
+ c = b;
62575
+ b = a;
62576
+ a = t1 + t2 >>> 0;
62577
+ }
62578
+ H2[0] = H2[0] + a >>> 0;
62579
+ H2[1] = H2[1] + b >>> 0;
62580
+ H2[2] = H2[2] + c >>> 0;
62581
+ H2[3] = H2[3] + d >>> 0;
62582
+ H2[4] = H2[4] + e >>> 0;
62583
+ H2[5] = H2[5] + f >>> 0;
62584
+ H2[6] = H2[6] + g >>> 0;
62585
+ H2[7] = H2[7] + h >>> 0;
62586
+ }
62587
+ return H2.map((w) => (w >>> 0).toString(16).padStart(8, "0")).join("");
62588
+ }
62589
+ registerIBuiltin({
62590
+ name: "hash",
62591
+ resolve: (argTypes) => {
62592
+ if (argTypes.length !== 2) return null;
62593
+ return {
62594
+ outputTypes: [{ kind: "char" }],
62595
+ apply: (args) => {
62596
+ const algoRaw = valueToByteString(args[0]);
62597
+ const algo = algoRaw.toUpperCase().replace(/-/g, "");
62598
+ const msg = valueToByteString(args[1]);
62599
+ if (algo === "MD5") return RTV.char(md5Hex(msg));
62600
+ if (algo === "SHA256") return RTV.char(sha256Hex(msg));
62601
+ throw new RuntimeError(
62602
+ `hash: unsupported hash function '${algoRaw}' (supported: MD5, SHA256)`
62603
+ );
62604
+ }
62605
+ };
62606
+ }
62607
+ });
62608
+
62088
62609
  // src/numbl-core/interpreter/builtins/help-text.ts
62089
62610
  var H = {
62090
62611
  // ── Math ──────────────────────────────────────────────────────────────
@@ -64277,7 +64798,7 @@ function getSourceLine(getSource, file, line) {
64277
64798
  }
64278
64799
 
64279
64800
  // src/numbl-core/version.ts
64280
- var NUMBL_VERSION = "0.4.16";
64801
+ var NUMBL_VERSION = "0.4.18";
64281
64802
 
64282
64803
  // src/cli-repl.ts
64283
64804
  import { createInterface } from "readline";
@@ -66920,7 +67441,7 @@ function evalMember(expr, nargout) {
66920
67441
  (el) => ensureRuntimeValue(this.rt.getMember(el, expr.name))
66921
67442
  );
66922
67443
  }
66923
- return this.rt.getMember(base, expr.name);
67444
+ return this.rt.getMember(base, expr.name, nargout);
66924
67445
  }
66925
67446
  function tryExtractDottedName(expr) {
66926
67447
  if (expr.type === "Ident") return expr.name;
@@ -66931,7 +67452,14 @@ function tryExtractDottedName(expr) {
66931
67452
  return null;
66932
67453
  }
66933
67454
  function evalIndex(expr) {
66934
- const base = this.evalExpr(expr.base);
67455
+ let base = this.evalExpr(expr.base);
67456
+ if (Array.isArray(base)) {
67457
+ if (base.length === 1) base = base[0];
67458
+ else
67459
+ throw new RuntimeError(
67460
+ `Expression produced ${base.length} values where one was expected`
67461
+ );
67462
+ }
66935
67463
  const indices = this.evalIndicesWithEnd(base, expr.indices);
66936
67464
  let skipSubsref = false;
66937
67465
  if (this.currentClassName) {
@@ -67317,7 +67845,12 @@ function evalLValueBase(base, defaultVal) {
67317
67845
  }
67318
67846
  const indices = this.evalIndicesWithEnd(baseVal, base.indices);
67319
67847
  try {
67320
- return this.rt.indexCell(baseVal, indices);
67848
+ const result = this.rt.indexCell(baseVal, indices);
67849
+ if (Array.isArray(result)) {
67850
+ if (result.length === 1) return result[0];
67851
+ if (result.length === 0) return defaultVal;
67852
+ }
67853
+ return result;
67321
67854
  } catch {
67322
67855
  return defaultVal;
67323
67856
  }
@@ -70016,7 +70549,11 @@ var stdlibFiles = [
70016
70549
  },
70017
70550
  {
70018
70551
  name: "inputParser.m",
70019
- source: "classdef inputParser < handle\n properties\n CaseSensitive = false\n FunctionName = ''\n KeepUnmatched = false\n PartialMatching = true\n StructExpand = true\n Results = struct()\n Unmatched = struct()\n UsingDefaults = {}\n Parameters = {}\n end\n properties\n required_ = {}\n optional_ = {}\n params_ = {}\n end\n methods\n function addRequired(obj, name, validator)\n if nargin < 3\n validator = [];\n end\n entry = struct('name', name, 'default', {[]}, 'validator', {{}});\n if ~isempty(validator)\n entry.validator = validator;\n end\n obj.required_{end+1} = entry;\n obj.Parameters{end+1} = name;\n end\n\n function addOptional(obj, name, default, validator)\n if nargin < 4\n validator = [];\n end\n entry = struct('name', name, 'default', {default}, 'validator', {{}});\n if ~isempty(validator)\n entry.validator = validator;\n end\n obj.optional_{end+1} = entry;\n obj.Parameters{end+1} = name;\n end\n\n function addParameter(obj, name, default, validator)\n if nargin < 4\n validator = [];\n end\n entry = struct('name', name, 'default', {default}, 'validator', {{}});\n if ~isempty(validator)\n entry.validator = validator;\n end\n obj.params_{end+1} = entry;\n obj.Parameters{end+1} = name;\n end\n\n function addParamValue(obj, name, default, validator)\n addParameter(obj, name, default, validator);\n end\n\n function parse(obj, varargin)\n s = struct();\n usingDefaults = {};\n pos = 1;\n nargs = numel(varargin);\n\n % Parse required arguments\n for i = 1:numel(obj.required_)\n entry = obj.required_{i};\n if pos > nargs\n error('Not enough input arguments. Missing required argument ''%s''.', entry.name);\n end\n val = varargin{pos};\n pos = pos + 1;\n s.(entry.name) = val;\n end\n\n % Parse optional positional arguments\n % An optional arg is consumed only if it is NOT a string matching a parameter name\n for i = 1:numel(obj.optional_)\n entry = obj.optional_{i};\n if pos <= nargs\n nextVal = varargin{pos};\n isParamName = false;\n if ischar(nextVal) || isstring(nextVal)\n paramName = char(nextVal);\n for k = 1:numel(obj.params_)\n pentry = obj.params_{k};\n if inputParser.namesMatch(paramName, pentry.name, obj.CaseSensitive)\n isParamName = true;\n break;\n end\n end\n end\n if ~isParamName\n s.(entry.name) = nextVal;\n pos = pos + 1;\n else\n s.(entry.name) = entry.default;\n usingDefaults{end+1} = entry.name;\n end\n else\n s.(entry.name) = entry.default;\n usingDefaults{end+1} = entry.name;\n end\n end\n\n % Set defaults for all parameters\n for i = 1:numel(obj.params_)\n entry = obj.params_{i};\n s.(entry.name) = entry.default;\n usingDefaults{end+1} = entry.name;\n end\n\n % Parse name-value pairs from remaining arguments\n unmatched = struct();\n while pos <= nargs\n if pos + 1 > nargs\n error('Expected name-value pair argument.');\n end\n name = varargin{pos};\n val = varargin{pos + 1};\n pos = pos + 2;\n\n if ~ischar(name) && ~isstring(name)\n error('Expected parameter name to be a string.');\n end\n name = char(name);\n\n found = false;\n for i = 1:numel(obj.params_)\n entry = obj.params_{i};\n if inputParser.namesMatch(name, entry.name, obj.CaseSensitive)\n s.(entry.name) = val;\n % Remove from usingDefaults\n newDefaults = {};\n for j = 1:numel(usingDefaults)\n if ~strcmp(usingDefaults{j}, entry.name)\n newDefaults{end+1} = usingDefaults{j};\n end\n end\n usingDefaults = newDefaults;\n found = true;\n break;\n end\n end\n if ~found\n if obj.KeepUnmatched\n unmatched.(name) = val;\n else\n error('''%s'' is not a recognized parameter.', name);\n end\n end\n end\n\n obj.Results = s;\n obj.UsingDefaults = usingDefaults;\n obj.Unmatched = unmatched;\n end\n end\n\n methods (Static)\n function tf = namesMatch(input, expected, caseSensitive)\n if caseSensitive\n tf = strcmp(input, expected);\n else\n tf = strcmpi(input, expected);\n end\n end\n end\nend\n"
70552
+ source: "classdef inputParser < handle\n properties\n CaseSensitive = false\n FunctionName = ''\n KeepUnmatched = false\n PartialMatching = true\n StructExpand = true\n Results = struct()\n Unmatched = struct()\n UsingDefaults = {}\n Parameters = {}\n end\n properties\n required_ = {}\n optional_ = {}\n params_ = {}\n end\n methods\n function addRequired(obj, name, validator)\n if nargin < 3\n validator = [];\n end\n entry = struct('name', name, 'default', {[]}, 'validator', {{}});\n if ~isempty(validator)\n entry.validator = validator;\n end\n obj.required_{end+1} = entry;\n obj.Parameters{end+1} = name;\n end\n\n function addOptional(obj, name, default, validator)\n if nargin < 4\n validator = [];\n end\n entry = struct('name', name, 'default', {default}, 'validator', {{}});\n if ~isempty(validator)\n entry.validator = validator;\n end\n obj.optional_{end+1} = entry;\n obj.Parameters{end+1} = name;\n end\n\n function addParameter(obj, name, default, validator)\n if nargin < 4\n validator = [];\n end\n entry = struct('name', name, 'default', {default}, 'validator', {{}});\n if ~isempty(validator)\n entry.validator = validator;\n end\n obj.params_{end+1} = entry;\n obj.Parameters{end+1} = name;\n end\n\n function addParamValue(obj, name, default, validator)\n if nargin < 4\n addParameter(obj, name, default);\n else\n addParameter(obj, name, default, validator);\n end\n end\n\n function parse(obj, varargin)\n s = struct();\n usingDefaults = {};\n pos = 1;\n nargs = numel(varargin);\n\n % Parse required arguments\n for i = 1:numel(obj.required_)\n entry = obj.required_{i};\n if pos > nargs\n error('Not enough input arguments. Missing required argument ''%s''.', entry.name);\n end\n val = varargin{pos};\n pos = pos + 1;\n s.(entry.name) = val;\n end\n\n % Parse optional positional arguments\n % An optional arg is consumed only if it is NOT a string matching a\n % parameter or optional name (MATLAB also accepts optionals as\n % name-value pairs, so their names terminate positional parsing)\n for i = 1:numel(obj.optional_)\n entry = obj.optional_{i};\n if pos <= nargs\n nextVal = varargin{pos};\n isParamName = false;\n if ischar(nextVal) || isstring(nextVal)\n paramName = char(nextVal);\n for k = 1:numel(obj.params_)\n pentry = obj.params_{k};\n if inputParser.namesMatch(paramName, pentry.name, obj.CaseSensitive)\n isParamName = true;\n break;\n end\n end\n if ~isParamName\n for k = 1:numel(obj.optional_)\n oentry = obj.optional_{k};\n if inputParser.namesMatch(paramName, oentry.name, obj.CaseSensitive)\n isParamName = true;\n break;\n end\n end\n end\n end\n if ~isParamName\n s.(entry.name) = nextVal;\n pos = pos + 1;\n else\n s.(entry.name) = entry.default;\n usingDefaults{end+1} = entry.name;\n end\n else\n s.(entry.name) = entry.default;\n usingDefaults{end+1} = entry.name;\n end\n end\n\n % Set defaults for all parameters\n for i = 1:numel(obj.params_)\n entry = obj.params_{i};\n s.(entry.name) = entry.default;\n usingDefaults{end+1} = entry.name;\n end\n\n % Parse name-value pairs from remaining arguments\n unmatched = struct();\n while pos <= nargs\n if pos + 1 > nargs\n error('Expected name-value pair argument.');\n end\n name = varargin{pos};\n val = varargin{pos + 1};\n pos = pos + 2;\n\n if ~ischar(name) && ~isstring(name)\n error('Expected parameter name to be a string.');\n end\n name = char(name);\n\n found = false;\n % Optionals may also be passed by name (undocumented MATLAB\n % behavior relied on by real-world code)\n candidates = [obj.params_, obj.optional_];\n for i = 1:numel(candidates)\n entry = candidates{i};\n if inputParser.namesMatch(name, entry.name, obj.CaseSensitive)\n s.(entry.name) = val;\n % Remove from usingDefaults\n newDefaults = {};\n for j = 1:numel(usingDefaults)\n if ~strcmp(usingDefaults{j}, entry.name)\n newDefaults{end+1} = usingDefaults{j};\n end\n end\n usingDefaults = newDefaults;\n found = true;\n break;\n end\n end\n if ~found\n if obj.KeepUnmatched\n unmatched.(name) = val;\n else\n error('''%s'' is not a recognized parameter.', name);\n end\n end\n end\n\n obj.Results = s;\n obj.UsingDefaults = usingDefaults;\n obj.Unmatched = unmatched;\n end\n end\n\n methods (Static)\n function tf = namesMatch(input, expected, caseSensitive)\n if caseSensitive\n tf = strcmp(input, expected);\n else\n tf = strcmpi(input, expected);\n end\n end\n end\nend\n"
70553
+ },
70554
+ {
70555
+ name: "normalize.m",
70556
+ source: "function Y = normalize(X, method, p)\n % normalize(X) z-score along the first non-singleton dimension\n % normalize(X, 'zscore') same as above\n % normalize(X, 'norm') divide by the 2-norm along that dimension\n % normalize(X, 'norm', p) divide by the p-norm (p = Inf -> max abs)\n if nargin < 2\n method = 'zscore';\n end\n if size(X, 1) == 1\n dim = 2;\n else\n dim = 1;\n end\n switch lower(method)\n case 'zscore'\n mu = mean(X, dim);\n sigma = std(X, 0, dim);\n Y = (X - mu) ./ sigma;\n case 'norm'\n if nargin < 3\n p = 2;\n end\n if isinf(p)\n n = max(abs(X), [], dim);\n else\n n = sum(abs(X) .^ p, dim) .^ (1 / p);\n end\n Y = X ./ n;\n otherwise\n error('normalize: unsupported method ''%s''', method);\n end\nend\n"
70020
70557
  },
70021
70558
  {
70022
70559
  name: "parse.m",
@@ -70207,6 +70744,7 @@ var shimFiles = [
70207
70744
  end
70208
70745
 
70209
70746
  function result = keys(obj)
70747
+ % MATLAB's containers.Map returns keys in sorted order
70210
70748
  if obj.Count == 0
70211
70749
  result = {};
70212
70750
  return;
@@ -70222,6 +70760,8 @@ var shimFiles = [
70222
70760
  for i = 1:numel(k)
70223
70761
  result{i} = char(k{i});
70224
70762
  end
70763
+ % MATLAB returns a sorted 1xN row cell
70764
+ result = reshape(sort(result), 1, []);
70225
70765
  else
70226
70766
  % Numeric keys: parse back from string
70227
70767
  if iscell(k)
@@ -70232,17 +70772,27 @@ var shimFiles = [
70232
70772
  else
70233
70773
  result = {str2double(k)};
70234
70774
  end
70775
+ result = reshape(num2cell(sort(cell2mat(result))), 1, []);
70235
70776
  end
70236
70777
  end
70237
70778
 
70238
70779
  function result = values(obj)
70780
+ % Ordered to correspond with keys() (i.e. key-sorted)
70239
70781
  if obj.Count == 0
70240
70782
  result = {};
70241
70783
  return;
70242
70784
  end
70243
- v = values(obj.data_);
70785
+ sortedKeys = keys(obj);
70786
+ v = cell(1, obj.Count);
70787
+ for i = 1:obj.Count
70788
+ v{i} = obj.data_(makeKey(sortedKeys{i}, obj.KeyType));
70789
+ end
70244
70790
  if strcmp(obj.ValueType, 'any')
70245
- result = v;
70791
+ % Values are stored cell-wrapped (see subsasgn); unwrap each
70792
+ result = cell(1, obj.Count);
70793
+ for i = 1:obj.Count
70794
+ result{i} = v{i}{1};
70795
+ end
70246
70796
  else
70247
70797
  if iscell(v)
70248
70798
  result = v;