linny-r 2.0.11 → 2.1.0

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.
@@ -319,7 +319,7 @@ function compareTailFirst(a, b, tail) {
319
319
  }
320
320
 
321
321
  function endsWithDigits(str) {
322
- // Returns trailing digts of `str` (empty string will evaluate as FALSE)
322
+ // Return trailing digts of `str` (empty string will evaluate as FALSE).
323
323
  let i = str.length - 1,
324
324
  c = str[i],
325
325
  d = '';
@@ -332,8 +332,8 @@ function endsWithDigits(str) {
332
332
  }
333
333
 
334
334
  function indexOfMatchingBracket(str, offset) {
335
- // Returns index of closing bracket, ignoring matched [...] inside
336
- // NOTE: starts at offset + 1, assuming that character at offset = '['
335
+ // Return index of closing bracket, ignoring matched [...] inside.
336
+ // NOTE: Start at offset + 1, assuming that character at offset = '['.
337
337
  let ob = 0, c;
338
338
  for(let i = offset + 1; i < str.length; i++) {
339
339
  c = str.charAt(i);
@@ -347,12 +347,12 @@ function indexOfMatchingBracket(str, offset) {
347
347
  }
348
348
  }
349
349
  }
350
- // No matching bracket => return -1
350
+ // No matching bracket => return -1.
351
351
  return -1;
352
352
  }
353
353
 
354
354
  function monoSpaced(vbl) {
355
- // Removes all non-essential spaces from variable reference `vbl`.
355
+ // Remove all non-essential spaces from variable reference `vbl`.
356
356
  // First reduce all whitespace to a single space.
357
357
  return vbl.replace(/\s+/g, ' ')
358
358
  // Then remove spaces after the opening bracket.
@@ -834,13 +834,11 @@ function customizeXML(str) {
834
834
  // and then load it again for the customization to be performed.
835
835
  if(str.indexOf('!!CUSTOMIZE</name><author>') >= 0) {
836
836
  // Modify `str` -- by default, do nothing, but typical modifications
837
- // will replace RexEx patterns by other strings.
838
-
839
- /*
837
+ // will replace RexEx patterns by other strings.
838
+
840
839
  const
841
- re = /xyz/gi,
842
- r = 'abc';
843
- */
840
+ re = /pattern/g,
841
+ r = 'replacement';
844
842
 
845
843
  // Trace the changes to the console.
846
844
  console.log('Customizing:', re, r);
@@ -7204,7 +7204,13 @@ function VMI_push_run_result(x, args) {
7204
7204
  let xp = rrspec.x,
7205
7205
  rn = rrspec.r,
7206
7206
  rri = rrspec.v;
7207
- if(xp === false) xp = MODEL.running_experiment;
7207
+ if(xp === false) {
7208
+ // If no experiment is specified, use the running experiment.
7209
+ // NOTE: To facilitate testing a "single run" without using the
7210
+ // Experiment manager, default to the experiment that is selected
7211
+ // in the Experiment manager (but not "running").
7212
+ xp = MODEL.running_experiment || EXPERIMENT_MANAGER.selected_experiment;
7213
+ }
7208
7214
  if(xp instanceof Experiment) {
7209
7215
  if(Array.isArray(rn)) {
7210
7216
  // Let the running experiment infer run number from selector list `rn`
@@ -7212,7 +7218,22 @@ function VMI_push_run_result(x, args) {
7212
7218
  rn = xp.matchingCombinationIndex(rn);
7213
7219
  } else if(rn < 0) {
7214
7220
  // Relative run number: use current run # + r (first run has number 0).
7215
- rn += xp.active_combination_index;
7221
+ if(xp === MODEL.running_experiment) {
7222
+ rn += xp.active_combination_index;
7223
+ } else if(xp.chart_combinations.length) {
7224
+ // Modeler has selected one or more runs in the viewer table.
7225
+ // FInd the highest number of a selected run that has been performed.
7226
+ let last = -1;
7227
+ for(const ccn of xp.chart_combinations) {
7228
+ if(ccn > last && ccn < xp.runs.length) last = ccn;
7229
+ }
7230
+ // If no performed runs are selected, use the last performed run.
7231
+ if(last < 0) last = xp.runs.length - 1;
7232
+ rn += last;
7233
+ } else {
7234
+ // Choose the run relative to the total number of completed runs.
7235
+ rn += xp.runs.length - 1;
7236
+ }
7216
7237
  } else if(rrspec.nr !== false) {
7217
7238
  // Run number inferred from local time step of expression.
7218
7239
  const
@@ -7654,7 +7675,13 @@ function VMI_add(x) {
7654
7675
  const d = x.pop();
7655
7676
  if(d !== false) {
7656
7677
  if(DEBUGGING) console.log('ADD (' + d.join(', ') + ')');
7657
- x.retop(d[0] + d[1]);
7678
+ if(Math.abs(d[0]) === VM.PLUS_INFINITY) {
7679
+ x.retop(d[0]);
7680
+ } else if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
7681
+ x.retop(d[1]);
7682
+ } else {
7683
+ x.retop(d[0] + d[1]);
7684
+ }
7658
7685
  }
7659
7686
  }
7660
7687
 
@@ -7664,17 +7691,27 @@ function VMI_sub(x) {
7664
7691
  const d = x.pop();
7665
7692
  if(d !== false) {
7666
7693
  if(DEBUGGING) console.log('SUB (' + d.join(', ') + ')');
7667
- x.retop(d[0] - d[1]);
7694
+ if(d[0] === VM.PLUS_INFINITY || d[1] === VM.MINUS_INFINITY) {
7695
+ x.retop(VM.PLUS_INFINITY);
7696
+ } else if(d[0] === VM.MINUS_INFINITY || d[1] === VM.PLUS_INFINITY) {
7697
+ x.retop(VM.MINUS_INFINITY);
7698
+ } else {
7699
+ x.retop(d[0] + d[1]);
7700
+ }
7668
7701
  }
7669
7702
  }
7670
7703
 
7671
7704
  function VMI_mul(x) {
7672
7705
  // Pop the top number on the stack, and multiply it with the new
7673
- // top number
7706
+ // top number.
7674
7707
  const d = x.pop();
7675
7708
  if(d !== false) {
7676
7709
  if(DEBUGGING) console.log('MUL (' + d.join(', ') + ')');
7677
- x.retop(d[0] * d[1]);
7710
+ if(Math.abs(d[0]) === VM.PLUS_INFINITY || Math.abs(d[1]) === VM.PLUS_INFINITY) {
7711
+ x.retop(VM.PLUS_INFINITY * Math.sign(d[0] * d[1]));
7712
+ } else {
7713
+ x.retop(d[0] * d[1]);
7714
+ }
7678
7715
  }
7679
7716
  }
7680
7717
 
@@ -7686,7 +7723,19 @@ function VMI_div(x) {
7686
7723
  if(DEBUGGING) console.log('DIV (' + d.join(', ') + ')');
7687
7724
  if(Math.abs(d[1]) <= VM.NEAR_ZERO) {
7688
7725
  x.retop(VM.DIV_ZERO);
7726
+ } else if(Math.abs(d[0]) === VM.PLUS_INFINITY) {
7727
+ if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
7728
+ // Treat INF / INF as 1.
7729
+ x.retop(Math.sign(d[0]) * Math.sign(d[1]));
7730
+ } else {
7731
+ // Push the + or - infinity value.
7732
+ x.retop(d[0]);
7733
+ }
7734
+ } else if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
7735
+ // Treat N / Infinity as 0 for any non-infinite value of N.
7736
+ x.retop(0);
7689
7737
  } else {
7738
+ // Standard division.
7690
7739
  x.retop(d[0] / d[1]);
7691
7740
  }
7692
7741
  }
@@ -7701,7 +7750,19 @@ function VMI_div_zero(x) {
7701
7750
  if(DEBUGGING) console.log('DIV-ZERO (' + d.join(', ') + ')');
7702
7751
  if(Math.abs(d[1]) <= VM.NEAR_ZERO) {
7703
7752
  x.retop(d[0]);
7753
+ } else if(Math.abs(d[0]) === VM.PLUS_INFINITY) {
7754
+ if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
7755
+ // Treat INF / INF as 1.
7756
+ x.retop(Math.sign(d[0]) * Math.sign(d[1]));
7757
+ } else {
7758
+ // Push the + or - infinity value.
7759
+ x.retop(d[0]);
7760
+ }
7761
+ } else if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
7762
+ // Treat N / Infinity as 0 for any non-infinite value of N.
7763
+ x.retop(0);
7704
7764
  } else {
7765
+ // Standard division.
7705
7766
  x.retop(d[0] / d[1]);
7706
7767
  }
7707
7768
  }
@@ -7717,6 +7778,9 @@ function VMI_mod(x) {
7717
7778
  if(DEBUGGING) console.log('DIV (' + d.join(', ') + ')');
7718
7779
  if(Math.abs(d[1]) <= VM.NEAR_ZERO) {
7719
7780
  x.retop(VM.DIV_ZERO);
7781
+ } else if(Math.abs(d[0]) === VM.PLUS_INFINITY || Math.abs(d[1]) === VM.PLUS_INFINITY) {
7782
+ // If either operand is infinite, return 0 as remainder.
7783
+ x.retop(0);
7720
7784
  } else {
7721
7785
  x.retop(d[0] % d[1]); // % is the modulo operator in JavaScript.
7722
7786
  }
@@ -7738,7 +7802,16 @@ function VMI_power(x) {
7738
7802
  const d = x.pop();
7739
7803
  if(d !== false) {
7740
7804
  if(DEBUGGING) console.log('POWER (' + d.join(', ') + ')');
7741
- x.retop(Math.pow(d[0], d[1]));
7805
+ const r = Math.pow(d[0], d[1]);
7806
+ if(isNaN(r)) {
7807
+ x.retop(VM.BAD_CALC);
7808
+ } else if(r >= VM.PLUS_INFINITY) {
7809
+ x.retop(VM.PLUS_INFINITY);
7810
+ } else if(r <= VM.MINUS_INFINITY) {
7811
+ x.retop(VM.MINUS_INFINITY);
7812
+ } else {
7813
+ x.retop(r);
7814
+ }
7742
7815
  }
7743
7816
  }
7744
7817
 
@@ -7750,6 +7823,8 @@ function VMI_sqrt(x) {
7750
7823
  if(DEBUGGING) console.log('SQRT ' + d);
7751
7824
  if(d < 0) {
7752
7825
  x.retop(VM.BAD_CALC);
7826
+ } else if (d === VM.PLUS_INFINITY) {
7827
+ x.retop(VM.PLUS_INFINITY);
7753
7828
  } else {
7754
7829
  x.retop(Math.sqrt(d));
7755
7830
  }
@@ -7761,7 +7836,12 @@ function VMI_sin(x) {
7761
7836
  const d = x.top();
7762
7837
  if(d !== false) {
7763
7838
  if(DEBUGGING) console.log('SIN ' + d);
7764
- x.retop(Math.sin(d));
7839
+ const r = Math.sin(d);
7840
+ if(isNaN(r) || Math.abs(d) === VM.PLUS_INFINITY) {
7841
+ x.retop(VM.BAD_CALC);
7842
+ } else {
7843
+ x.retop(r);
7844
+ }
7765
7845
  }
7766
7846
  }
7767
7847
 
@@ -7770,7 +7850,12 @@ function VMI_cos(x) {
7770
7850
  const d = x.top();
7771
7851
  if(d !== false) {
7772
7852
  if(DEBUGGING) console.log('COS ' + d);
7773
- x.retop(Math.cos(d));
7853
+ const r = Math.cos(d);
7854
+ if(isNaN(r) || Math.abs(d) === VM.PLUS_INFINITY) {
7855
+ x.retop(VM.BAD_CALC);
7856
+ } else {
7857
+ x.retop(r);
7858
+ }
7774
7859
  }
7775
7860
  }
7776
7861
 
@@ -7779,7 +7864,12 @@ function VMI_atan(x) {
7779
7864
  const d = x.top();
7780
7865
  if(d !== false) {
7781
7866
  if(DEBUGGING) console.log('ATAN ' + d);
7782
- x.retop(Math.atan(d));
7867
+ const r = Math.atan(d);
7868
+ if(isNaN(r) || Math.abs(d) === VM.PLUS_INFINITY) {
7869
+ x.retop(VM.BAD_CALC);
7870
+ } else {
7871
+ x.retop(r);
7872
+ }
7783
7873
  }
7784
7874
  }
7785
7875
 
@@ -7791,6 +7881,8 @@ function VMI_ln(x) {
7791
7881
  if(DEBUGGING) console.log('LN ' + d);
7792
7882
  if(d < 0) {
7793
7883
  x.retop(VM.BAD_CALC);
7884
+ } else if(d === VM.PLUS_INFINITY) {
7885
+ x.retop(VM.PLUS_INFINITY);
7794
7886
  } else {
7795
7887
  x.retop(Math.log(d));
7796
7888
  }
@@ -7802,7 +7894,13 @@ function VMI_exp(x) {
7802
7894
  const d = x.top();
7803
7895
  if(d !== false) {
7804
7896
  if(DEBUGGING) console.log('EXP ' + d);
7805
- x.retop(Math.exp(d));
7897
+ if(d === VM.PLUS_INFINITY) {
7898
+ x.retop(VM.PLUS_INFINITY);
7899
+ } else if(d === VM.MINUS_INFINITY) {
7900
+ x.retop(0);
7901
+ } else {
7902
+ x.retop(Math.exp(d));
7903
+ }
7806
7904
  }
7807
7905
  }
7808
7906
 
@@ -7812,12 +7910,16 @@ function VMI_log(x) {
7812
7910
  let d = x.pop();
7813
7911
  if(d !== false) {
7814
7912
  if(DEBUGGING) console.log('LOG (' + d.join(', ') + ')');
7815
- try {
7816
- d = Math.log(d[1]) / Math.log(d[0]);
7817
- } catch(err) {
7818
- d = VM.BAD_CALC;
7913
+ if(Math.abs(d[0]) === VM.PLUS_INFINITY || Math.abs(d[1]) === VM.PLUS_INFINITY) {
7914
+ x.retop(VM.BAD_CALC);
7915
+ } else {
7916
+ try {
7917
+ d = Math.log(d[1]) / Math.log(d[0]);
7918
+ } catch(err) {
7919
+ d = VM.BAD_CALC;
7920
+ }
7921
+ x.retop(d);
7819
7922
  }
7820
- x.retop(d);
7821
7923
  }
7822
7924
  }
7823
7925