numbl 0.4.15 → 0.4.17

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) {
@@ -36810,14 +36814,20 @@ function dictRemove(d, keysArg) {
36810
36814
  }
36811
36815
  return RTV.dictionary(entries, d.keyType, d.valueType);
36812
36816
  }
36813
- function dictLookup(d, keysArg) {
36817
+ function dictLookup(d, keysArg, fallbackValue) {
36814
36818
  const keys = expandKeys(keysArg);
36815
36819
  const results = [];
36816
36820
  for (const k of keys) {
36817
36821
  const coerced = d.keyType ? coerceKey(k, d.keyType) : k;
36818
36822
  const h = hashKey(coerced);
36819
36823
  const entry = d.entries.get(h);
36820
- if (!entry) throw new RuntimeError("Key not found in dictionary");
36824
+ if (!entry) {
36825
+ if (fallbackValue !== void 0) {
36826
+ results.push(fallbackValue);
36827
+ continue;
36828
+ }
36829
+ throw new RuntimeError("Key not found in dictionary");
36830
+ }
36821
36831
  results.push(entry.value);
36822
36832
  }
36823
36833
  if (results.length === 1) return results[0];
@@ -37052,11 +37062,21 @@ registerIBuiltin({
37052
37062
  registerIBuiltin({
37053
37063
  name: "lookup",
37054
37064
  resolve: (argTypes) => {
37055
- if (argTypes.length !== 2 || argTypes[0].kind !== "dictionary") return null;
37065
+ if (argTypes.length !== 2 && argTypes.length !== 4 || argTypes[0].kind !== "dictionary")
37066
+ return null;
37056
37067
  return {
37057
37068
  outputTypes: [{ kind: "unknown" }],
37058
37069
  apply: (args) => {
37059
37070
  const d = args[0];
37071
+ if (args.length === 4) {
37072
+ const optName = isRuntimeChar(args[2]) ? args[2].value : isRuntimeString(args[2]) ? args[2] : "";
37073
+ if (String(optName).toLowerCase() !== "fallbackvalue") {
37074
+ throw new RuntimeError(
37075
+ `Unrecognized option '${String(optName)}' for lookup`
37076
+ );
37077
+ }
37078
+ return dictLookup(d, args[1], args[3]);
37079
+ }
37060
37080
  return dictLookup(d, args[1]);
37061
37081
  }
37062
37082
  };
@@ -40184,33 +40204,66 @@ function registerSpecialBuiltins(rt) {
40184
40204
  };
40185
40205
  }
40186
40206
  });
40207
+ const warningStateOff = /* @__PURE__ */ new Set();
40187
40208
  registerSpecial("warning", (nargout, args) => {
40188
40209
  if (args.length === 0) return nargout >= 1 ? RTV.num(0) : void 0;
40189
40210
  const margs = args.map((a) => ensureRuntimeValue(a));
40211
+ const isOff = (id) => warningStateOff.has(id) || warningStateOff.has("all");
40212
+ const stateStruct = (id) => RTV.struct(
40213
+ /* @__PURE__ */ new Map([
40214
+ ["identifier", RTV.char(id)],
40215
+ ["state", RTV.char(isOff(id) ? "off" : "on")]
40216
+ ])
40217
+ );
40218
+ const setState = (mode, id) => {
40219
+ if (mode === "off") warningStateOff.add(id);
40220
+ else {
40221
+ warningStateOff.delete(id);
40222
+ if (id === "all") warningStateOff.clear();
40223
+ }
40224
+ };
40225
+ const restoreFrom = (s) => {
40226
+ if (!isRuntimeStruct(s)) return false;
40227
+ const idField = s.fields.get("identifier");
40228
+ const stField = s.fields.get("state");
40229
+ if (idField === void 0 || stField === void 0) return false;
40230
+ setState(toString(stField), toString(idField));
40231
+ return true;
40232
+ };
40233
+ if (margs.length === 1 && isRuntimeStruct(margs[0])) {
40234
+ if (restoreFrom(margs[0])) return nargout >= 1 ? RTV.num(0) : void 0;
40235
+ }
40236
+ if (margs.length === 1 && isRuntimeStructArray(margs[0])) {
40237
+ for (const el of margs[0].elements) restoreFrom(el);
40238
+ return nargout >= 1 ? RTV.num(0) : void 0;
40239
+ }
40240
+ if (margs.length === 1 && isRuntimeChar(margs[0])) {
40241
+ const mode = toString(margs[0]);
40242
+ if (mode === "on" || mode === "off") {
40243
+ const prev = stateStruct("all");
40244
+ setState(mode, "all");
40245
+ return nargout >= 1 ? prev : void 0;
40246
+ }
40247
+ }
40190
40248
  if (margs.length === 2 && isRuntimeChar(margs[0]) && isRuntimeChar(margs[1])) {
40191
40249
  const mode = toString(margs[0]);
40250
+ const id = toString(margs[1]);
40192
40251
  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
- );
40252
+ const prev = stateStruct(id);
40253
+ setState(mode, id);
40254
+ return nargout >= 1 ? prev : void 0;
40200
40255
  }
40201
40256
  if (mode === "query") {
40202
- return RTV.struct(
40203
- /* @__PURE__ */ new Map([
40204
- ["state", RTV.char("on")],
40205
- ["identifier", margs[1]]
40206
- ])
40207
- );
40257
+ return stateStruct(id);
40208
40258
  }
40209
40259
  }
40210
40260
  let fmtIdx = 0;
40211
40261
  if (margs.length >= 2 && isRuntimeChar(margs[0]) && toString(margs[0]).includes(":")) {
40212
40262
  fmtIdx = 1;
40213
40263
  }
40264
+ if (isOff(fmtIdx === 1 ? toString(margs[0]) : "all")) {
40265
+ return nargout >= 1 ? RTV.num(0) : void 0;
40266
+ }
40214
40267
  const fmt = toString(margs[fmtIdx]);
40215
40268
  const fmtArgs = [];
40216
40269
  for (let i = fmtIdx + 1; i < margs.length; i++) {
@@ -42747,7 +42800,7 @@ function _complexLuFactor(n, re, im, ipiv) {
42747
42800
  }
42748
42801
 
42749
42802
  // src/numbl-core/runtime/runtimeMemberAccess.ts
42750
- function getMember(rt, base, name) {
42803
+ function getMember(rt, base, name, nargout = 1) {
42751
42804
  const mv = ensureRuntimeValue(base);
42752
42805
  if (isRuntimeClassInstance(mv)) {
42753
42806
  const accessorKey = `${mv.className}.get.${name}`;
@@ -42766,7 +42819,7 @@ function getMember(rt, base, name) {
42766
42819
  if (field !== void 0) return field;
42767
42820
  const method = rt.cachedResolveClassMethod(mv.className, name);
42768
42821
  if (method) {
42769
- return method(1, base);
42822
+ return method(nargout, base);
42770
42823
  }
42771
42824
  const guardKey = `${mv.className}.subsref`;
42772
42825
  if (!rt.activeAccessors.has(guardKey)) {
@@ -45470,8 +45523,8 @@ var Runtime = class _Runtime {
45470
45523
  return multiOutputCellAssign(base, indices, results, this);
45471
45524
  }
45472
45525
  // ── Member access ───────────────────────────────────────────────────
45473
- getMember(base, name) {
45474
- return getMember(this, base, name);
45526
+ getMember(base, name, nargout = 1) {
45527
+ return getMember(this, base, name, nargout);
45475
45528
  }
45476
45529
  getMemberDynamic(base, nameExpr) {
45477
45530
  return getMemberDynamic(this, base, nameExpr);
@@ -51363,6 +51416,46 @@ function uniquetolElements(v, nargout, tol) {
51363
51416
  if (nargout === 2) return [C, ia];
51364
51417
  return [C, ia, icTensor];
51365
51418
  }
51419
+ defineBuiltin({
51420
+ name: "ismembc2",
51421
+ cases: [
51422
+ {
51423
+ match: (argTypes) => {
51424
+ if (argTypes.length !== 2) return null;
51425
+ return [{ kind: "tensor", isComplex: false }];
51426
+ },
51427
+ apply: (args) => {
51428
+ const toFlat = (v) => {
51429
+ if (isRuntimeNumber(v)) return [v];
51430
+ if (isRuntimeLogical(v)) return [v ? 1 : 0];
51431
+ if (isRuntimeTensor(v)) return v.data;
51432
+ throw new RuntimeError("ismembc2: arguments must be numeric");
51433
+ };
51434
+ const a = toFlat(args[0]);
51435
+ const s = toFlat(args[1]);
51436
+ const out = allocFloat64Array(a.length);
51437
+ for (let i = 0; i < a.length; i++) {
51438
+ const x = a[i];
51439
+ let lo = 0;
51440
+ let hi = s.length - 1;
51441
+ let res = 0;
51442
+ while (lo <= hi) {
51443
+ const mid = lo + hi >> 1;
51444
+ if (s[mid] <= x) {
51445
+ if (s[mid] === x) res = mid + 1;
51446
+ lo = mid + 1;
51447
+ } else {
51448
+ hi = mid - 1;
51449
+ }
51450
+ }
51451
+ out[i] = res;
51452
+ }
51453
+ const shape = isRuntimeTensor(args[0]) ? [...args[0].shape] : [1, 1];
51454
+ return RTV.tensor(out, shape);
51455
+ }
51456
+ }
51457
+ ]
51458
+ });
51366
51459
 
51367
51460
  // src/numbl-core/interpreter/builtins/linear-algebra.ts
51368
51461
  function isNumericJitType(t) {
@@ -57541,6 +57634,45 @@ defineBuiltin({
57541
57634
  },
57542
57635
  apply: (args) => {
57543
57636
  const xArr = toFloatArray(args[0]);
57637
+ if (args.length === 4 && isRuntimeChar(args[2]) && isRuntimeChar(args[3]) && args[3].value.toLowerCase() === "pp") {
57638
+ const method2 = args[2].value.toLowerCase();
57639
+ if (method2 !== "linear")
57640
+ throw new RuntimeError(
57641
+ `interp1: 'pp' output is only supported for 'linear' method (got '${method2}')`
57642
+ );
57643
+ const yArr = toFloatArray(args[1]);
57644
+ const n = xArr.length;
57645
+ if (yArr.length !== n)
57646
+ throw new RuntimeError(
57647
+ "interp1: x and y must have the same length"
57648
+ );
57649
+ if (n < 2)
57650
+ throw new RuntimeError(
57651
+ "interp1: at least 2 sample points are required"
57652
+ );
57653
+ for (let i = 0; i + 1 < n; i++) {
57654
+ if (!(xArr[i] < xArr[i + 1]))
57655
+ throw new RuntimeError(
57656
+ "interp1: sample points must be unique and sorted for 'pp' output"
57657
+ );
57658
+ }
57659
+ const L = n - 1;
57660
+ const breaksOut = allocFloat64Array(n);
57661
+ for (let i = 0; i < n; i++) breaksOut[i] = xArr[i];
57662
+ const coefs = allocFloat64Array(L * 2);
57663
+ for (let i = 0; i < L; i++) {
57664
+ coefs[i] = (yArr[i + 1] - yArr[i]) / (xArr[i + 1] - xArr[i]);
57665
+ coefs[L + i] = yArr[i];
57666
+ }
57667
+ const fields = /* @__PURE__ */ new Map();
57668
+ fields.set("form", "pp");
57669
+ fields.set("breaks", RTV.tensor(breaksOut, [1, n]));
57670
+ fields.set("coefs", RTV.tensor(coefs, [L, 2]));
57671
+ fields.set("pieces", L);
57672
+ fields.set("order", 2);
57673
+ fields.set("dim", 1);
57674
+ return RTV.struct(fields);
57675
+ }
57544
57676
  const xqArg = args[2];
57545
57677
  const nn = xArr.length;
57546
57678
  const yVal = args[1];
@@ -57569,6 +57701,7 @@ defineBuiltin({
57569
57701
  throw new RuntimeError("interp1: x and y must have the same length");
57570
57702
  let method = "linear";
57571
57703
  let doExtrap = false;
57704
+ let fillValue = NaN;
57572
57705
  for (let i = 3; i < args.length; i++) {
57573
57706
  const a = args[i];
57574
57707
  if (isRuntimeChar(a)) {
@@ -57579,11 +57712,13 @@ defineBuiltin({
57579
57712
  const s = a.toLowerCase();
57580
57713
  if (s === "extrap") doExtrap = true;
57581
57714
  else method = s;
57715
+ } else if (isRuntimeNumber(a) || isRuntimeTensor(a)) {
57716
+ fillValue = toNumber(a);
57582
57717
  }
57583
57718
  }
57584
57719
  const interpOne = (yArr, xq) => {
57585
57720
  if (xq < xArr[0] || xq > xArr[nn - 1]) {
57586
- if (!doExtrap) return NaN;
57721
+ if (!doExtrap) return fillValue;
57587
57722
  if (method === "linear") {
57588
57723
  if (xq < xArr[0]) {
57589
57724
  const slope = (yArr[1] - yArr[0]) / (xArr[1] - xArr[0]);
@@ -58014,6 +58149,63 @@ function dimArgToVec(v) {
58014
58149
  }
58015
58150
  throw new RuntimeError("mkpp: dim must be a numeric scalar or vector");
58016
58151
  }
58152
+ var ppIntApply = (fname) => (args) => {
58153
+ const pp = args[0];
58154
+ if (!isRuntimeStruct(pp))
58155
+ throw new RuntimeError(`${fname}: argument must be a pp struct`);
58156
+ const breaksRT = pp.fields.get("breaks");
58157
+ const coefsRT = pp.fields.get("coefs");
58158
+ const piecesRT = pp.fields.get("pieces");
58159
+ const orderRT = pp.fields.get("order");
58160
+ const dimRT = pp.fields.get("dim");
58161
+ if (breaksRT === void 0 || coefsRT === void 0 || piecesRT === void 0 || orderRT === void 0)
58162
+ throw new RuntimeError(`${fname}: pp struct missing required fields`);
58163
+ const breaks = toFloatArray(breaksRT);
58164
+ const L = Math.round(toNumber(piecesRT));
58165
+ const k = Math.round(toNumber(orderRT));
58166
+ const dim = dimRT === void 0 ? [1] : dimArgToVec(dimRT);
58167
+ if (dim.reduce((a, b) => a * b, 1) !== 1)
58168
+ throw new RuntimeError(`${fname}: only scalar-valued pp is supported`);
58169
+ if (!isRuntimeTensor(coefsRT))
58170
+ throw new RuntimeError(`${fname}: pp.coefs must be a matrix`);
58171
+ const coefs = coefsRT.data;
58172
+ const out = allocFloat64Array(L * (k + 1));
58173
+ for (let c = 0; c < k; c++) {
58174
+ for (let i = 0; i < L; i++) out[c * L + i] = coefs[c * L + i] / (k - c);
58175
+ }
58176
+ let A = 0;
58177
+ for (let i = 0; i < L; i++) {
58178
+ out[k * L + i] = A;
58179
+ const h = breaks[i + 1] - breaks[i];
58180
+ let v = out[0 * L + i];
58181
+ for (let c = 1; c <= k; c++) v = v * h + out[c * L + i];
58182
+ A = v;
58183
+ }
58184
+ const fields = /* @__PURE__ */ new Map();
58185
+ fields.set("form", "pp");
58186
+ const breaksOut = allocFloat64Array(breaks.length);
58187
+ for (let i = 0; i < breaks.length; i++) breaksOut[i] = breaks[i];
58188
+ fields.set("breaks", RTV.tensor(breaksOut, [1, breaks.length]));
58189
+ fields.set("coefs", RTV.tensor(out, [L, k + 1]));
58190
+ fields.set("pieces", L);
58191
+ fields.set("order", k + 1);
58192
+ fields.set("dim", 1);
58193
+ return RTV.struct(fields);
58194
+ };
58195
+ for (const fname of ["fnint", "ppint"]) {
58196
+ defineBuiltin({
58197
+ name: fname,
58198
+ cases: [
58199
+ {
58200
+ match: (argTypes) => {
58201
+ if (argTypes.length !== 1) return null;
58202
+ return [{ kind: "struct", fields: {} }];
58203
+ },
58204
+ apply: ppIntApply(fname)
58205
+ }
58206
+ ]
58207
+ });
58208
+ }
58017
58209
  defineBuiltin({
58018
58210
  name: "mkpp",
58019
58211
  cases: [
@@ -58755,6 +58947,8 @@ defineBuiltin({
58755
58947
  {
58756
58948
  match: (argTypes) => {
58757
58949
  if (argTypes.length === 0) return [{ kind: "struct", fields: {} }];
58950
+ if (argTypes.length === 1 && argTypes[0].kind === "tensor")
58951
+ return [{ kind: "struct", fields: {} }];
58758
58952
  if (argTypes.length % 2 !== 0) return null;
58759
58953
  for (let i = 0; i < argTypes.length; i += 2) {
58760
58954
  const k = argTypes[i].kind;
@@ -58764,6 +58958,13 @@ defineBuiltin({
58764
58958
  },
58765
58959
  apply: (args) => {
58766
58960
  if (args.length === 0) return RTV.struct(/* @__PURE__ */ new Map());
58961
+ if (args.length === 1 && isRuntimeTensor(args[0])) {
58962
+ if (args[0].data.length !== 0)
58963
+ throw new RuntimeError(
58964
+ "struct: single non-empty numeric argument is not supported"
58965
+ );
58966
+ return RTV.structArray([], []);
58967
+ }
58767
58968
  if (args.length % 2 !== 0)
58768
58969
  throw new RuntimeError("struct: requires field-value pairs");
58769
58970
  const fieldNames = [];
@@ -59556,13 +59757,48 @@ registerIBuiltin({
59556
59757
  resolve: (argTypes) => {
59557
59758
  if (argTypes.length !== 1) return null;
59558
59759
  return {
59559
- outputTypes: [{ kind: "tensor", isComplex: false }],
59760
+ outputTypes: [{ kind: "unknown" }],
59560
59761
  apply: (args) => {
59561
59762
  const C = args[0];
59562
59763
  if (!isRuntimeCell(C))
59563
59764
  throw new RuntimeError("cell2mat: argument must be a cell array");
59564
59765
  const cellRows = C.shape[0];
59565
59766
  const cellCols = C.shape.length >= 2 ? C.shape[1] : 1;
59767
+ if (C.data.length > 0 && C.data.some((v) => isRuntimeChar(v))) {
59768
+ const asCharBlock = (v) => {
59769
+ if (!isRuntimeChar(v))
59770
+ throw new RuntimeError(
59771
+ "cell2mat: cannot mix char and non-char cell contents"
59772
+ );
59773
+ const rows = v.shape ? v.shape[0] : v.value.length === 0 ? 0 : 1;
59774
+ const cols = v.shape ? v.shape[1] : v.value.length;
59775
+ const rowStrings = [];
59776
+ for (let r = 0; r < rows; r++)
59777
+ rowStrings.push(v.value.slice(r * cols, (r + 1) * cols));
59778
+ return { rows, cols, rowStrings };
59779
+ };
59780
+ const outRows = [];
59781
+ for (let ci = 0; ci < cellRows; ci++) {
59782
+ const blockHeight = asCharBlock(C.data[ci]).rows;
59783
+ const lines = new Array(blockHeight).fill("");
59784
+ for (let cj = 0; cj < cellCols; cj++) {
59785
+ const b = asCharBlock(C.data[cj * cellRows + ci]);
59786
+ if (b.rows !== blockHeight)
59787
+ throw new RuntimeError(
59788
+ "cell2mat: inconsistent cell content sizes"
59789
+ );
59790
+ for (let r = 0; r < blockHeight; r++) lines[r] += b.rowStrings[r];
59791
+ }
59792
+ outRows.push(...lines);
59793
+ }
59794
+ const width = outRows.length > 0 ? outRows[0].length : 0;
59795
+ if (outRows.some((r) => r.length !== width))
59796
+ throw new RuntimeError("cell2mat: inconsistent cell content sizes");
59797
+ if (outRows.length <= 1) return RTV.char(outRows[0] ?? "");
59798
+ const rc = RTV.char(outRows.join(""));
59799
+ rc.shape = [outRows.length, width];
59800
+ return rc;
59801
+ }
59566
59802
  const asTensor = (v) => {
59567
59803
  if (isRuntimeNumber(v))
59568
59804
  return {
@@ -62085,6 +62321,288 @@ defineBuiltin({
62085
62321
  ]
62086
62322
  });
62087
62323
 
62324
+ // src/numbl-core/interpreter/builtins/hash.ts
62325
+ function valueToByteString(v) {
62326
+ if (isRuntimeChar(v)) return v.value;
62327
+ if (isRuntimeString(v)) return String(v);
62328
+ throw new RuntimeError("hash: STR must be a char array or string");
62329
+ }
62330
+ function md5Hex(input) {
62331
+ const bytes = [];
62332
+ for (let i = 0; i < input.length; i++) bytes.push(input.charCodeAt(i) & 255);
62333
+ const origLenBits = bytes.length * 8;
62334
+ bytes.push(128);
62335
+ while (bytes.length % 64 !== 56) bytes.push(0);
62336
+ let len = origLenBits;
62337
+ for (let i = 0; i < 8; i++) {
62338
+ bytes.push(len & 255);
62339
+ len = Math.floor(len / 256);
62340
+ }
62341
+ const S = [
62342
+ 7,
62343
+ 12,
62344
+ 17,
62345
+ 22,
62346
+ 7,
62347
+ 12,
62348
+ 17,
62349
+ 22,
62350
+ 7,
62351
+ 12,
62352
+ 17,
62353
+ 22,
62354
+ 7,
62355
+ 12,
62356
+ 17,
62357
+ 22,
62358
+ 5,
62359
+ 9,
62360
+ 14,
62361
+ 20,
62362
+ 5,
62363
+ 9,
62364
+ 14,
62365
+ 20,
62366
+ 5,
62367
+ 9,
62368
+ 14,
62369
+ 20,
62370
+ 5,
62371
+ 9,
62372
+ 14,
62373
+ 20,
62374
+ 4,
62375
+ 11,
62376
+ 16,
62377
+ 23,
62378
+ 4,
62379
+ 11,
62380
+ 16,
62381
+ 23,
62382
+ 4,
62383
+ 11,
62384
+ 16,
62385
+ 23,
62386
+ 4,
62387
+ 11,
62388
+ 16,
62389
+ 23,
62390
+ 6,
62391
+ 10,
62392
+ 15,
62393
+ 21,
62394
+ 6,
62395
+ 10,
62396
+ 15,
62397
+ 21,
62398
+ 6,
62399
+ 10,
62400
+ 15,
62401
+ 21,
62402
+ 6,
62403
+ 10,
62404
+ 15,
62405
+ 21
62406
+ ];
62407
+ const K = new Array(64);
62408
+ for (let i = 0; i < 64; i++)
62409
+ K[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 4294967296) >>> 0;
62410
+ let a0 = 1732584193;
62411
+ let b0 = 4023233417;
62412
+ let c0 = 2562383102;
62413
+ let d0 = 271733878;
62414
+ const rotl2 = (x, c) => (x << c | x >>> 32 - c) >>> 0;
62415
+ for (let chunk = 0; chunk < bytes.length; chunk += 64) {
62416
+ const M = new Array(16);
62417
+ for (let j = 0; j < 16; j++) {
62418
+ const o = chunk + j * 4;
62419
+ M[j] = (bytes[o] | bytes[o + 1] << 8 | bytes[o + 2] << 16 | bytes[o + 3] << 24) >>> 0;
62420
+ }
62421
+ let A = a0;
62422
+ let B = b0;
62423
+ let C = c0;
62424
+ let D = d0;
62425
+ for (let i = 0; i < 64; i++) {
62426
+ let F;
62427
+ let g;
62428
+ if (i < 16) {
62429
+ F = B & C | ~B & D;
62430
+ g = i;
62431
+ } else if (i < 32) {
62432
+ F = D & B | ~D & C;
62433
+ g = (5 * i + 1) % 16;
62434
+ } else if (i < 48) {
62435
+ F = B ^ C ^ D;
62436
+ g = (3 * i + 5) % 16;
62437
+ } else {
62438
+ F = C ^ (B | ~D);
62439
+ g = 7 * i % 16;
62440
+ }
62441
+ F = F + A + K[i] + M[g] >>> 0;
62442
+ A = D;
62443
+ D = C;
62444
+ C = B;
62445
+ B = B + rotl2(F, S[i]) >>> 0;
62446
+ }
62447
+ a0 = a0 + A >>> 0;
62448
+ b0 = b0 + B >>> 0;
62449
+ c0 = c0 + C >>> 0;
62450
+ d0 = d0 + D >>> 0;
62451
+ }
62452
+ const le2 = (w) => {
62453
+ let s = "";
62454
+ for (let i = 0; i < 4; i++)
62455
+ s += (w >>> i * 8 & 255).toString(16).padStart(2, "0");
62456
+ return s;
62457
+ };
62458
+ return le2(a0) + le2(b0) + le2(c0) + le2(d0);
62459
+ }
62460
+ function sha256Hex(input) {
62461
+ const bytes = [];
62462
+ for (let i = 0; i < input.length; i++) bytes.push(input.charCodeAt(i) & 255);
62463
+ const origLenBits = bytes.length * 8;
62464
+ bytes.push(128);
62465
+ while (bytes.length % 64 !== 56) bytes.push(0);
62466
+ const hi = Math.floor(origLenBits / 4294967296);
62467
+ const lo = origLenBits >>> 0;
62468
+ for (let i = 3; i >= 0; i--) bytes.push(hi >>> i * 8 & 255);
62469
+ for (let i = 3; i >= 0; i--) bytes.push(lo >>> i * 8 & 255);
62470
+ const K = [
62471
+ 1116352408,
62472
+ 1899447441,
62473
+ 3049323471,
62474
+ 3921009573,
62475
+ 961987163,
62476
+ 1508970993,
62477
+ 2453635748,
62478
+ 2870763221,
62479
+ 3624381080,
62480
+ 310598401,
62481
+ 607225278,
62482
+ 1426881987,
62483
+ 1925078388,
62484
+ 2162078206,
62485
+ 2614888103,
62486
+ 3248222580,
62487
+ 3835390401,
62488
+ 4022224774,
62489
+ 264347078,
62490
+ 604807628,
62491
+ 770255983,
62492
+ 1249150122,
62493
+ 1555081692,
62494
+ 1996064986,
62495
+ 2554220882,
62496
+ 2821834349,
62497
+ 2952996808,
62498
+ 3210313671,
62499
+ 3336571891,
62500
+ 3584528711,
62501
+ 113926993,
62502
+ 338241895,
62503
+ 666307205,
62504
+ 773529912,
62505
+ 1294757372,
62506
+ 1396182291,
62507
+ 1695183700,
62508
+ 1986661051,
62509
+ 2177026350,
62510
+ 2456956037,
62511
+ 2730485921,
62512
+ 2820302411,
62513
+ 3259730800,
62514
+ 3345764771,
62515
+ 3516065817,
62516
+ 3600352804,
62517
+ 4094571909,
62518
+ 275423344,
62519
+ 430227734,
62520
+ 506948616,
62521
+ 659060556,
62522
+ 883997877,
62523
+ 958139571,
62524
+ 1322822218,
62525
+ 1537002063,
62526
+ 1747873779,
62527
+ 1955562222,
62528
+ 2024104815,
62529
+ 2227730452,
62530
+ 2361852424,
62531
+ 2428436474,
62532
+ 2756734187,
62533
+ 3204031479,
62534
+ 3329325298
62535
+ ];
62536
+ const H2 = [
62537
+ 1779033703,
62538
+ 3144134277,
62539
+ 1013904242,
62540
+ 2773480762,
62541
+ 1359893119,
62542
+ 2600822924,
62543
+ 528734635,
62544
+ 1541459225
62545
+ ];
62546
+ const rotr = (x, c) => (x >>> c | x << 32 - c) >>> 0;
62547
+ for (let chunk = 0; chunk < bytes.length; chunk += 64) {
62548
+ const W = new Array(64);
62549
+ for (let j = 0; j < 16; j++) {
62550
+ const o = chunk + j * 4;
62551
+ W[j] = (bytes[o] << 24 | bytes[o + 1] << 16 | bytes[o + 2] << 8 | bytes[o + 3]) >>> 0;
62552
+ }
62553
+ for (let j = 16; j < 64; j++) {
62554
+ const s0 = rotr(W[j - 15], 7) ^ rotr(W[j - 15], 18) ^ W[j - 15] >>> 3;
62555
+ const s1 = rotr(W[j - 2], 17) ^ rotr(W[j - 2], 19) ^ W[j - 2] >>> 10;
62556
+ W[j] = W[j - 16] + s0 + W[j - 7] + s1 >>> 0;
62557
+ }
62558
+ let [a, b, c, d, e, f, g, h] = H2;
62559
+ for (let j = 0; j < 64; j++) {
62560
+ const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
62561
+ const ch = e & f ^ ~e & g;
62562
+ const t1 = h + S1 + ch + K[j] + W[j] >>> 0;
62563
+ const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
62564
+ const maj = a & b ^ a & c ^ b & c;
62565
+ const t2 = S0 + maj >>> 0;
62566
+ h = g;
62567
+ g = f;
62568
+ f = e;
62569
+ e = d + t1 >>> 0;
62570
+ d = c;
62571
+ c = b;
62572
+ b = a;
62573
+ a = t1 + t2 >>> 0;
62574
+ }
62575
+ H2[0] = H2[0] + a >>> 0;
62576
+ H2[1] = H2[1] + b >>> 0;
62577
+ H2[2] = H2[2] + c >>> 0;
62578
+ H2[3] = H2[3] + d >>> 0;
62579
+ H2[4] = H2[4] + e >>> 0;
62580
+ H2[5] = H2[5] + f >>> 0;
62581
+ H2[6] = H2[6] + g >>> 0;
62582
+ H2[7] = H2[7] + h >>> 0;
62583
+ }
62584
+ return H2.map((w) => (w >>> 0).toString(16).padStart(8, "0")).join("");
62585
+ }
62586
+ registerIBuiltin({
62587
+ name: "hash",
62588
+ resolve: (argTypes) => {
62589
+ if (argTypes.length !== 2) return null;
62590
+ return {
62591
+ outputTypes: [{ kind: "char" }],
62592
+ apply: (args) => {
62593
+ const algoRaw = valueToByteString(args[0]);
62594
+ const algo = algoRaw.toUpperCase().replace(/-/g, "");
62595
+ const msg = valueToByteString(args[1]);
62596
+ if (algo === "MD5") return RTV.char(md5Hex(msg));
62597
+ if (algo === "SHA256") return RTV.char(sha256Hex(msg));
62598
+ throw new RuntimeError(
62599
+ `hash: unsupported hash function '${algoRaw}' (supported: MD5, SHA256)`
62600
+ );
62601
+ }
62602
+ };
62603
+ }
62604
+ });
62605
+
62088
62606
  // src/numbl-core/interpreter/builtins/help-text.ts
62089
62607
  var H = {
62090
62608
  // ── Math ──────────────────────────────────────────────────────────────
@@ -64277,7 +64795,7 @@ function getSourceLine(getSource, file, line) {
64277
64795
  }
64278
64796
 
64279
64797
  // src/numbl-core/version.ts
64280
- var NUMBL_VERSION = "0.4.15";
64798
+ var NUMBL_VERSION = "0.4.17";
64281
64799
 
64282
64800
  // src/cli-repl.ts
64283
64801
  import { createInterface } from "readline";
@@ -66920,7 +67438,7 @@ function evalMember(expr, nargout) {
66920
67438
  (el) => ensureRuntimeValue(this.rt.getMember(el, expr.name))
66921
67439
  );
66922
67440
  }
66923
- return this.rt.getMember(base, expr.name);
67441
+ return this.rt.getMember(base, expr.name, nargout);
66924
67442
  }
66925
67443
  function tryExtractDottedName(expr) {
66926
67444
  if (expr.type === "Ident") return expr.name;
@@ -66931,7 +67449,14 @@ function tryExtractDottedName(expr) {
66931
67449
  return null;
66932
67450
  }
66933
67451
  function evalIndex(expr) {
66934
- const base = this.evalExpr(expr.base);
67452
+ let base = this.evalExpr(expr.base);
67453
+ if (Array.isArray(base)) {
67454
+ if (base.length === 1) base = base[0];
67455
+ else
67456
+ throw new RuntimeError(
67457
+ `Expression produced ${base.length} values where one was expected`
67458
+ );
67459
+ }
66935
67460
  const indices = this.evalIndicesWithEnd(base, expr.indices);
66936
67461
  let skipSubsref = false;
66937
67462
  if (this.currentClassName) {
@@ -70016,7 +70541,11 @@ var stdlibFiles = [
70016
70541
  },
70017
70542
  {
70018
70543
  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"
70544
+ 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"
70545
+ },
70546
+ {
70547
+ name: "normalize.m",
70548
+ 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
70549
  },
70021
70550
  {
70022
70551
  name: "parse.m",
@@ -70207,6 +70736,7 @@ var shimFiles = [
70207
70736
  end
70208
70737
 
70209
70738
  function result = keys(obj)
70739
+ % MATLAB's containers.Map returns keys in sorted order
70210
70740
  if obj.Count == 0
70211
70741
  result = {};
70212
70742
  return;
@@ -70222,6 +70752,8 @@ var shimFiles = [
70222
70752
  for i = 1:numel(k)
70223
70753
  result{i} = char(k{i});
70224
70754
  end
70755
+ % MATLAB returns a sorted 1xN row cell
70756
+ result = reshape(sort(result), 1, []);
70225
70757
  else
70226
70758
  % Numeric keys: parse back from string
70227
70759
  if iscell(k)
@@ -70232,17 +70764,27 @@ var shimFiles = [
70232
70764
  else
70233
70765
  result = {str2double(k)};
70234
70766
  end
70767
+ result = reshape(num2cell(sort(cell2mat(result))), 1, []);
70235
70768
  end
70236
70769
  end
70237
70770
 
70238
70771
  function result = values(obj)
70772
+ % Ordered to correspond with keys() (i.e. key-sorted)
70239
70773
  if obj.Count == 0
70240
70774
  result = {};
70241
70775
  return;
70242
70776
  end
70243
- v = values(obj.data_);
70777
+ sortedKeys = keys(obj);
70778
+ v = cell(1, obj.Count);
70779
+ for i = 1:obj.Count
70780
+ v{i} = obj.data_(makeKey(sortedKeys{i}, obj.KeyType));
70781
+ end
70244
70782
  if strcmp(obj.ValueType, 'any')
70245
- result = v;
70783
+ % Values are stored cell-wrapped (see subsasgn); unwrap each
70784
+ result = cell(1, obj.Count);
70785
+ for i = 1:obj.Count
70786
+ result{i} = v{i}{1};
70787
+ end
70246
70788
  else
70247
70789
  if iscell(v)
70248
70790
  result = v;
@@ -88440,7 +88982,9 @@ var Lowerer = class {
88440
88982
  }
88441
88983
  }
88442
88984
  const expr = this.lowerExpr(s.expr);
88443
- if (expr.kind === "NumLit" || expr.kind === "ImagLit") return null;
88985
+ if ((expr.kind === "NumLit" || expr.kind === "ImagLit") && s.suppressed) {
88986
+ return null;
88987
+ }
88444
88988
  if (isVoid(expr.ty)) {
88445
88989
  const hoists2 = [];
88446
88990
  const hoisted2 = this.anfChildren(expr, hoists2);