@khanacademy/kas 0.2.7 → 0.3.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.
package/dist/es/index.js CHANGED
@@ -3,7 +3,6 @@ import _ from 'underscore';
3
3
  // this is a @generated file
4
4
 
5
5
  /* parser generated by jison 0.4.15 */
6
-
7
6
  /*
8
7
  Returns a Parser object of the following structure:
9
8
 
@@ -78,17 +77,15 @@ import _ from 'underscore';
78
77
  */
79
78
  var parser$1 = function () {
80
79
  var o = function o(k, v, _o, l) {
81
- for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v) {
82
- }
83
-
84
- return _o;
85
- },
86
- $V0 = [1, 11],
87
- $V1 = [1, 9],
88
- $V2 = [8, 17],
89
- $V3 = [6, 11],
90
- $V4 = [6, 11, 13, 17];
91
-
80
+ for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v) {
81
+ }
82
+ return _o;
83
+ },
84
+ $V0 = [1, 11],
85
+ $V1 = [1, 9],
86
+ $V2 = [8, 17],
87
+ $V3 = [6, 11],
88
+ $V4 = [6, 11, 13, 17];
92
89
  var parser = {
93
90
  trace: function trace() {},
94
91
  yy: {},
@@ -128,16 +125,10 @@ var parser$1 = function () {
128
125
  20: "NEG"
129
126
  },
130
127
  productions_: [0, [3, 3], [3, 2], [4, 3], [4, 1], [5, 3], [5, 1], [10, 3], [10, 2], [10, 1], [12, 3], [12, 1], [14, 1], [7, 1], [7, 1], [16, 1], [9, 2], [9, 1]],
131
- performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate
132
- /* action[1] */
133
- , $$
134
- /* vstack */
135
- , _$
136
- /* lstack */
137
- ) {
128
+ performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
138
129
  /* this == yyval */
139
- var $0 = $$.length - 1;
140
130
 
131
+ var $0 = $$.length - 1;
141
132
  switch (yystate) {
142
133
  case 1:
143
134
  return {
@@ -145,17 +136,14 @@ var parser$1 = function () {
145
136
  magnitude: $$[$0 - 2],
146
137
  unit: $$[$0 - 1]
147
138
  };
148
-
149
139
  case 2:
150
140
  return {
151
141
  type: "unitStandalone",
152
142
  unit: $$[$0 - 1]
153
143
  };
154
-
155
144
  case 3:
156
145
  this.$ = $$[$0 - 2] + "e" + $$[$0];
157
146
  break;
158
-
159
147
  case 4:
160
148
  case 13:
161
149
  case 14:
@@ -163,51 +151,42 @@ var parser$1 = function () {
163
151
  case 17:
164
152
  this.$ = $$[$0];
165
153
  break;
166
-
167
154
  case 5:
168
155
  this.$ = {
169
156
  num: $$[$0 - 2],
170
157
  denom: $$[$0]
171
158
  };
172
159
  break;
173
-
174
160
  case 6:
175
161
  this.$ = {
176
162
  num: $$[$0],
177
163
  denom: null
178
164
  };
179
165
  break;
180
-
181
166
  case 7:
182
167
  this.$ = [$$[$0 - 2]].concat($$[$0]);
183
168
  break;
184
-
185
169
  case 8:
186
170
  this.$ = [$$[$0 - 1]].concat($$[$0]);
187
171
  break;
188
-
189
172
  case 9:
190
173
  this.$ = [$$[$0]];
191
174
  break;
192
-
193
175
  case 10:
194
176
  this.$ = {
195
177
  name: $$[$0 - 2],
196
178
  pow: $$[$0]
197
179
  };
198
180
  break;
199
-
200
181
  case 11:
201
182
  this.$ = {
202
183
  name: $$[$0],
203
184
  pow: 1
204
185
  };
205
186
  break;
206
-
207
187
  case 12:
208
188
  this.$ = yytext;
209
189
  break;
210
-
211
190
  case 16:
212
191
  this.$ = "-" + $$[$0];
213
192
  break;
@@ -300,96 +279,80 @@ var parser$1 = function () {
300
279
  },
301
280
  parse: function parse(input) {
302
281
  var self = this,
303
- stack = [0],
304
- vstack = [null],
305
- lstack = [],
306
- table = this.table,
307
- yytext = '',
308
- yylineno = 0,
309
- yyleng = 0,
310
- TERROR = 2,
311
- EOF = 1;
282
+ stack = [0],
283
+ vstack = [null],
284
+ lstack = [],
285
+ table = this.table,
286
+ yytext = '',
287
+ yylineno = 0,
288
+ yyleng = 0,
289
+ TERROR = 2,
290
+ EOF = 1;
312
291
  var args = lstack.slice.call(arguments, 1);
313
292
  var lexer = Object.create(this.lexer);
314
293
  var sharedState = {
315
294
  yy: {}
316
295
  };
317
-
318
296
  for (var k in this.yy) {
319
297
  if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
320
298
  sharedState.yy[k] = this.yy[k];
321
299
  }
322
300
  }
323
-
324
301
  lexer.setInput(input, sharedState.yy);
325
302
  sharedState.yy.lexer = lexer;
326
303
  sharedState.yy.parser = this;
327
-
328
304
  if (typeof lexer.yylloc == 'undefined') {
329
305
  lexer.yylloc = {};
330
306
  }
331
-
332
307
  var yyloc = lexer.yylloc;
333
308
  lstack.push(yyloc);
334
309
  var ranges = lexer.options && lexer.options.ranges;
335
-
336
310
  if (typeof sharedState.yy.parseError === 'function') {
337
311
  this.parseError = sharedState.yy.parseError;
338
312
  } else {
339
313
  this.parseError = Object.getPrototypeOf(this).parseError;
340
314
  }
341
-
342
-
315
+ //_token_stack:
343
316
  function lex() {
344
317
  var token;
345
318
  token = lexer.lex() || EOF;
346
-
347
319
  if (typeof token !== 'number') {
348
320
  token = self.symbols_[token] || token;
349
321
  }
350
-
351
322
  return token;
352
323
  }
353
-
354
324
  var symbol,
355
- state,
356
- action,
357
- r,
358
- yyval = {},
359
- p,
360
- len,
361
- newState,
362
- expected;
363
-
325
+ state,
326
+ action,
327
+ r,
328
+ yyval = {},
329
+ p,
330
+ len,
331
+ newState,
332
+ expected;
364
333
  while (true) {
365
334
  state = stack[stack.length - 1];
366
-
367
335
  if (this.defaultActions[state]) {
368
336
  action = this.defaultActions[state];
369
337
  } else {
370
338
  if (symbol === null || typeof symbol == 'undefined') {
371
339
  symbol = lex();
372
340
  }
373
-
374
341
  action = table[state] && table[state][symbol];
375
342
  }
376
-
377
343
  if (typeof action === 'undefined' || !action.length || !action[0]) {
378
344
  var errStr = '';
379
345
  expected = [];
380
-
381
346
  for (p in table[state]) {
382
347
  if (this.terminals_[p] && p > TERROR) {
383
348
  expected.push('\'' + this.terminals_[p] + '\'');
384
349
  }
385
350
  }
386
-
387
351
  if (lexer.showPosition) {
388
352
  errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
389
353
  } else {
390
354
  errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
391
355
  }
392
-
393
356
  this.parseError(errStr, {
394
357
  text: lexer.match,
395
358
  token: this.terminals_[symbol] || symbol,
@@ -398,11 +361,9 @@ var parser$1 = function () {
398
361
  expected: expected
399
362
  });
400
363
  }
401
-
402
364
  if (action[0] instanceof Array && action.length > 1) {
403
365
  throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
404
366
  }
405
-
406
367
  switch (action[0]) {
407
368
  case 1:
408
369
  stack.push(symbol);
@@ -410,16 +371,13 @@ var parser$1 = function () {
410
371
  lstack.push(lexer.yylloc);
411
372
  stack.push(action[1]);
412
373
  symbol = null;
413
-
414
374
  {
415
375
  yyleng = lexer.yyleng;
416
376
  yytext = lexer.yytext;
417
377
  yylineno = lexer.yylineno;
418
378
  yyloc = lexer.yylloc;
419
379
  }
420
-
421
380
  break;
422
-
423
381
  case 2:
424
382
  len = this.productions_[action[1]][1];
425
383
  yyval.$ = vstack[vstack.length - len];
@@ -429,40 +387,32 @@ var parser$1 = function () {
429
387
  first_column: lstack[lstack.length - (len || 1)].first_column,
430
388
  last_column: lstack[lstack.length - 1].last_column
431
389
  };
432
-
433
390
  if (ranges) {
434
391
  yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
435
392
  }
436
-
437
393
  r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
438
-
439
394
  if (typeof r !== 'undefined') {
440
395
  return r;
441
396
  }
442
-
443
397
  if (len) {
444
398
  stack = stack.slice(0, -1 * len * 2);
445
399
  vstack = vstack.slice(0, -1 * len);
446
400
  lstack = lstack.slice(0, -1 * len);
447
401
  }
448
-
449
402
  stack.push(this.productions_[action[1]][0]);
450
403
  vstack.push(yyval.$);
451
404
  lstack.push(yyval._$);
452
405
  newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
453
406
  stack.push(newState);
454
407
  break;
455
-
456
408
  case 3:
457
409
  return true;
458
410
  }
459
411
  }
460
-
461
412
  return true;
462
413
  }
463
414
  };
464
415
  /* generated by jison-lex 0.3.4 */
465
-
466
416
  var lexer = function () {
467
417
  var lexer = {
468
418
  EOF: 1,
@@ -487,11 +437,9 @@ var parser$1 = function () {
487
437
  last_line: 1,
488
438
  last_column: 0
489
439
  };
490
-
491
440
  if (this.options.ranges) {
492
441
  this.yylloc.range = [0, 0];
493
442
  }
494
-
495
443
  this.offset = 0;
496
444
  return this;
497
445
  },
@@ -504,18 +452,15 @@ var parser$1 = function () {
504
452
  this.match += ch;
505
453
  this.matched += ch;
506
454
  var lines = ch.match(/(?:\r\n?|\n).*/g);
507
-
508
455
  if (lines) {
509
456
  this.yylineno++;
510
457
  this.yylloc.last_line++;
511
458
  } else {
512
459
  this.yylloc.last_column++;
513
460
  }
514
-
515
461
  if (this.options.ranges) {
516
462
  this.yylloc.range[1]++;
517
463
  }
518
-
519
464
  this._input = this._input.slice(1);
520
465
  return ch;
521
466
  },
@@ -524,17 +469,15 @@ var parser$1 = function () {
524
469
  var len = ch.length;
525
470
  var lines = ch.split(/(?:\r\n?|\n)/g);
526
471
  this._input = ch + this._input;
527
- this.yytext = this.yytext.substr(0, this.yytext.length - len); //this.yyleng -= len;
528
-
472
+ this.yytext = this.yytext.substr(0, this.yytext.length - len);
473
+ //this.yyleng -= len;
529
474
  this.offset -= len;
530
475
  var oldLines = this.match.split(/(?:\r\n?|\n)/g);
531
476
  this.match = this.match.substr(0, this.match.length - 1);
532
477
  this.matched = this.matched.substr(0, this.matched.length - 1);
533
-
534
478
  if (lines.length - 1) {
535
479
  this.yylineno -= lines.length - 1;
536
480
  }
537
-
538
481
  var r = this.yylloc.range;
539
482
  this.yylloc = {
540
483
  first_line: this.yylloc.first_line,
@@ -542,11 +485,9 @@ var parser$1 = function () {
542
485
  first_column: this.yylloc.first_column,
543
486
  last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
544
487
  };
545
-
546
488
  if (this.options.ranges) {
547
489
  this.yylloc.range = [r[0], r[0] + this.yyleng - len];
548
490
  }
549
-
550
491
  this.yyleng = this.yytext.length;
551
492
  return this;
552
493
  },
@@ -566,7 +507,6 @@ var parser$1 = function () {
566
507
  line: this.yylineno
567
508
  });
568
509
  }
569
-
570
510
  return this;
571
511
  },
572
512
  // retain first n characters of the match
@@ -581,11 +521,9 @@ var parser$1 = function () {
581
521
  // displays upcoming input, i.e. for error messages
582
522
  upcomingInput: function upcomingInput() {
583
523
  var next = this.match;
584
-
585
524
  if (next.length < 20) {
586
525
  next += this._input.substr(0, 20 - next.length);
587
526
  }
588
-
589
527
  return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
590
528
  },
591
529
  // displays the character position where the lexing error occurred, i.e. for error messages
@@ -597,7 +535,6 @@ var parser$1 = function () {
597
535
  // test the lexed token: return FALSE when not a match, otherwise return token
598
536
  test_match: function test_match(match, indexed_rule) {
599
537
  var token, lines, backup;
600
-
601
538
  if (this.options.backtrack_lexer) {
602
539
  // save context
603
540
  backup = {
@@ -620,18 +557,14 @@ var parser$1 = function () {
620
557
  conditionStack: this.conditionStack.slice(0),
621
558
  done: this.done
622
559
  };
623
-
624
560
  if (this.options.ranges) {
625
561
  backup.yylloc.range = this.yylloc.range.slice(0);
626
562
  }
627
563
  }
628
-
629
564
  lines = match[0].match(/(?:\r\n?|\n).*/g);
630
-
631
565
  if (lines) {
632
566
  this.yylineno += lines.length;
633
567
  }
634
-
635
568
  this.yylloc = {
636
569
  first_line: this.yylloc.last_line,
637
570
  last_line: this.yylineno + 1,
@@ -642,21 +575,17 @@ var parser$1 = function () {
642
575
  this.match += match[0];
643
576
  this.matches = match;
644
577
  this.yyleng = this.yytext.length;
645
-
646
578
  if (this.options.ranges) {
647
579
  this.yylloc.range = [this.offset, this.offset += this.yyleng];
648
580
  }
649
-
650
581
  this._more = false;
651
582
  this._backtrack = false;
652
583
  this._input = this._input.slice(match[0].length);
653
584
  this.matched += match[0];
654
585
  token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
655
-
656
586
  if (this.done && this._input) {
657
587
  this.done = false;
658
588
  }
659
-
660
589
  if (token) {
661
590
  return token;
662
591
  } else if (this._backtrack) {
@@ -664,7 +593,6 @@ var parser$1 = function () {
664
593
  for (var k in backup) {
665
594
  this[k] = backup[k];
666
595
  }
667
-
668
596
  return false; // rule action called reject() implying the next rule should be tested instead.
669
597
  }
670
598
 
@@ -675,30 +603,22 @@ var parser$1 = function () {
675
603
  if (this.done) {
676
604
  return this.EOF;
677
605
  }
678
-
679
606
  if (!this._input) {
680
607
  this.done = true;
681
608
  }
682
-
683
609
  var token, match, tempMatch, index;
684
-
685
610
  if (!this._more) {
686
611
  this.yytext = '';
687
612
  this.match = '';
688
613
  }
689
-
690
614
  var rules = this._currentRules();
691
-
692
615
  for (var i = 0; i < rules.length; i++) {
693
616
  tempMatch = this._input.match(this.rules[rules[i]]);
694
-
695
617
  if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
696
618
  match = tempMatch;
697
619
  index = i;
698
-
699
620
  if (this.options.backtrack_lexer) {
700
621
  token = this.test_match(tempMatch, rules[i]);
701
-
702
622
  if (token !== false) {
703
623
  return token;
704
624
  } else if (this._backtrack) {
@@ -713,18 +633,14 @@ var parser$1 = function () {
713
633
  }
714
634
  }
715
635
  }
716
-
717
636
  if (match) {
718
637
  token = this.test_match(match, rules[index]);
719
-
720
638
  if (token !== false) {
721
639
  return token;
722
- } // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
723
-
724
-
640
+ }
641
+ // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
725
642
  return false;
726
643
  }
727
-
728
644
  if (this._input === "") {
729
645
  return this.EOF;
730
646
  } else {
@@ -738,7 +654,6 @@ var parser$1 = function () {
738
654
  // return next match that has a token
739
655
  lex: function lex() {
740
656
  var r = this.next();
741
-
742
657
  if (r) {
743
658
  return r;
744
659
  } else {
@@ -752,7 +667,6 @@ var parser$1 = function () {
752
667
  // pop the previously active lexer condition state off the condition stack
753
668
  popState: function popState() {
754
669
  var n = this.conditionStack.length - 1;
755
-
756
670
  if (n > 0) {
757
671
  return this.conditionStack.pop();
758
672
  } else {
@@ -770,7 +684,6 @@ var parser$1 = function () {
770
684
  // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
771
685
  topState: function topState(n) {
772
686
  n = this.conditionStack.length - 1 - Math.abs(n || 0);
773
-
774
687
  if (n >= 0) {
775
688
  return this.conditionStack[n];
776
689
  } else {
@@ -787,48 +700,34 @@ var parser$1 = function () {
787
700
  },
788
701
  options: {},
789
702
  performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
790
-
791
703
  switch ($avoiding_name_collisions) {
792
704
  case 0:
793
705
  return 11;
794
-
795
706
  case 1:
796
707
  return '(';
797
-
798
708
  case 2:
799
709
  return ')';
800
-
801
710
  case 3:
802
711
  return 8;
803
-
804
712
  case 4:
805
713
  return 15;
806
-
807
714
  case 5:
808
715
  return 13;
809
-
810
716
  case 6:
811
717
  return 18;
812
-
813
718
  case 7:
814
719
  return 19;
815
-
816
720
  case 8:
817
721
  return 20;
818
-
819
722
  case 9:
820
723
  return 17;
821
-
822
724
  case 10:
823
725
  return 17;
824
-
825
726
  case 11:
826
727
  return 17;
827
-
828
728
  case 12:
829
729
  /* skip whitespace */
830
730
  break;
831
-
832
731
  case 13:
833
732
  return 6;
834
733
  }
@@ -843,23 +742,19 @@ var parser$1 = function () {
843
742
  };
844
743
  return lexer;
845
744
  }();
846
-
847
745
  parser.lexer = lexer;
848
-
849
746
  function Parser() {
850
747
  this.yy = {};
851
748
  }
852
-
853
749
  Parser.prototype = parser;
854
750
  parser.Parser = Parser;
855
751
  return new Parser();
856
752
  }();
857
-
858
753
  var unitParser = parser$1;
859
754
 
860
755
  // This is a @generated file
861
- /* parser generated by jison 0.4.15 */
862
756
 
757
+ /* parser generated by jison 0.4.15 */
863
758
  /*
864
759
  Returns a Parser object of the following structure:
865
760
 
@@ -932,40 +827,37 @@ var unitParser = parser$1;
932
827
  recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
933
828
  }
934
829
  */
935
-
936
830
  var parser = function () {
937
831
  var o = function o(k, v, _o, l) {
938
- for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v) {
939
- }
940
-
941
- return _o;
942
- },
943
- $V0 = [1, 7],
944
- $V1 = [1, 17],
945
- $V2 = [1, 13],
946
- $V3 = [1, 14],
947
- $V4 = [1, 15],
948
- $V5 = [1, 32],
949
- $V6 = [1, 22],
950
- $V7 = [1, 23],
951
- $V8 = [1, 24],
952
- $V9 = [1, 25],
953
- $Va = [1, 26],
954
- $Vb = [1, 33],
955
- $Vc = [1, 27],
956
- $Vd = [1, 28],
957
- $Ve = [1, 29],
958
- $Vf = [1, 30],
959
- $Vg = [1, 20],
960
- $Vh = [1, 36],
961
- $Vi = [1, 37],
962
- $Vj = [5, 6, 8, 10, 33, 35, 41, 43, 45],
963
- $Vk = [1, 39],
964
- $Vl = [1, 40],
965
- $Vm = [5, 6, 8, 10, 12, 14, 16, 19, 21, 22, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41, 42, 43, 44, 45, 46],
966
- $Vn = [10, 16, 19, 21, 22, 28, 29, 30, 31, 32, 34, 37, 39, 42, 43, 44, 46],
967
- $Vo = [5, 6, 8, 10, 12, 14, 16, 18, 19, 21, 22, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41, 42, 43, 44, 45, 46];
968
-
832
+ for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v) {
833
+ }
834
+ return _o;
835
+ },
836
+ $V0 = [1, 7],
837
+ $V1 = [1, 17],
838
+ $V2 = [1, 13],
839
+ $V3 = [1, 14],
840
+ $V4 = [1, 15],
841
+ $V5 = [1, 32],
842
+ $V6 = [1, 22],
843
+ $V7 = [1, 23],
844
+ $V8 = [1, 24],
845
+ $V9 = [1, 25],
846
+ $Va = [1, 26],
847
+ $Vb = [1, 33],
848
+ $Vc = [1, 27],
849
+ $Vd = [1, 28],
850
+ $Ve = [1, 29],
851
+ $Vf = [1, 30],
852
+ $Vg = [1, 20],
853
+ $Vh = [1, 36],
854
+ $Vi = [1, 37],
855
+ $Vj = [5, 6, 8, 10, 33, 35, 41, 43, 45],
856
+ $Vk = [1, 39],
857
+ $Vl = [1, 40],
858
+ $Vm = [5, 6, 8, 10, 12, 14, 16, 19, 21, 22, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41, 42, 43, 44, 45, 46],
859
+ $Vn = [10, 16, 19, 21, 22, 28, 29, 30, 31, 32, 34, 37, 39, 42, 43, 44, 46],
860
+ $Vo = [5, 6, 8, 10, 12, 14, 16, 18, 19, 21, 22, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41, 42, 43, 44, 45, 46];
969
861
  var parser = {
970
862
  trace: function trace() {},
971
863
  yy: {},
@@ -1051,26 +943,17 @@ var parser = function () {
1051
943
  46: "FRAC"
1052
944
  },
1053
945
  productions_: [0, [3, 4], [3, 2], [3, 1], [4, 1], [7, 3], [7, 3], [7, 1], [9, 2], [9, 3], [9, 3], [9, 1], [13, 2], [13, 1], [15, 1], [17, 1], [17, 3], [17, 1], [20, 1], [20, 1], [20, 3], [11, 2], [11, 2], [11, 1], [25, 3], [25, 1], [27, 1], [24, 3], [24, 1], [24, 1], [24, 1], [24, 1], [24, 3], [24, 3], [36, 1], [38, 4], [38, 4], [38, 7], [38, 4], [38, 3], [38, 3], [38, 4], [26, 1], [26, 1], [26, 7]],
1054
- performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate
1055
- /* action[1] */
1056
- , $$
1057
- /* vstack */
1058
- , _$
1059
- /* lstack */
1060
- ) {
946
+ performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
1061
947
  /* this == yyval */
1062
- var $0 = $$.length - 1;
1063
948
 
949
+ var $0 = $$.length - 1;
1064
950
  switch (yystate) {
1065
951
  case 1:
1066
952
  return new yy.Eq($$[$0 - 3], $$[$0 - 2], $$[$0 - 1]);
1067
-
1068
953
  case 2:
1069
954
  return $$[$0 - 1];
1070
-
1071
955
  case 3:
1072
956
  return new yy.Add([]);
1073
-
1074
957
  case 4:
1075
958
  case 7:
1076
959
  case 11:
@@ -1083,112 +966,86 @@ var parser = function () {
1083
966
  case 43:
1084
967
  this.$ = $$[$0];
1085
968
  break;
1086
-
1087
969
  case 5:
1088
970
  this.$ = yy.Add.createOrAppend($$[$0 - 2], $$[$0]);
1089
971
  break;
1090
-
1091
972
  case 6:
1092
973
  this.$ = yy.Add.createOrAppend($$[$0 - 2], yy.Mul.handleNegative($$[$0], "subtract"));
1093
974
  break;
1094
-
1095
975
  case 8:
1096
976
  this.$ = yy.Mul.fold(yy.Mul.createOrAppend($$[$0 - 1], $$[$0]));
1097
977
  break;
1098
-
1099
978
  case 9:
1100
979
  this.$ = yy.Mul.fold(yy.Mul.createOrAppend($$[$0 - 2], $$[$0]));
1101
980
  break;
1102
-
1103
981
  case 10:
1104
982
  this.$ = yy.Mul.fold(yy.Mul.handleDivide($$[$0 - 2], $$[$0]));
1105
983
  break;
1106
-
1107
984
  case 12:
1108
985
  this.$ = yy.Mul.handleNegative($$[$0]);
1109
986
  break;
1110
-
1111
987
  case 14:
1112
988
  case 17:
1113
989
  this.$ = [yytext];
1114
990
  break;
1115
-
1116
991
  case 16:
1117
992
  this.$ = $$[$0 - 2].concat($$[$0]);
1118
993
  break;
1119
-
1120
994
  case 18:
1121
995
  this.$ = yy.Log.natural();
1122
996
  break;
1123
-
1124
997
  case 19:
1125
998
  this.$ = yy.Log.common();
1126
999
  break;
1127
-
1128
1000
  case 21:
1129
1001
  this.$ = yy.Trig.create($$[$0 - 1], $$[$0]);
1130
1002
  break;
1131
-
1132
1003
  case 22:
1133
1004
  this.$ = yy.Log.create($$[$0 - 1], $$[$0]);
1134
1005
  break;
1135
-
1136
1006
  case 24:
1137
1007
  this.$ = new yy.Pow($$[$0 - 2], $$[$0]);
1138
1008
  break;
1139
-
1140
1009
  case 26:
1141
1010
  case 34:
1142
1011
  this.$ = yytext;
1143
1012
  break;
1144
-
1145
1013
  case 27:
1146
1014
  this.$ = new yy.Var($$[$0 - 2], $$[$0]);
1147
1015
  break;
1148
-
1149
1016
  case 28:
1150
1017
  this.$ = new yy.Var($$[$0]);
1151
1018
  break;
1152
-
1153
1019
  case 29:
1154
1020
  this.$ = new yy.Const(yytext.toLowerCase());
1155
1021
  break;
1156
-
1157
1022
  case 30:
1158
1023
  this.$ = yy.Int.create(Number(yytext));
1159
1024
  break;
1160
-
1161
1025
  case 31:
1162
1026
  this.$ = yy.Float.create(Number(yytext));
1163
1027
  break;
1164
-
1165
1028
  case 32:
1166
1029
  this.$ = $$[$0 - 1].completeParse();
1167
1030
  break;
1168
-
1169
1031
  case 33:
1170
1032
  this.$ = $$[$0 - 1].completeParse().addHint('parens');
1171
1033
  break;
1172
-
1173
1034
  case 35:
1174
1035
  case 36:
1175
1036
  this.$ = yy.Pow.sqrt($$[$0 - 1]);
1176
1037
  break;
1177
-
1178
1038
  case 37:
1179
1039
  this.$ = new yy.Pow.nthroot($$[$0 - 1], $$[$0 - 4]);
1180
1040
  break;
1181
-
1182
1041
  case 38:
1183
1042
  case 39:
1184
1043
  case 40:
1185
1044
  this.$ = new yy.Abs($$[$0 - 1]);
1186
1045
  break;
1187
-
1188
1046
  case 41:
1189
1047
  this.$ = new yy.Func($$[$0 - 3], $$[$0 - 1]);
1190
1048
  break;
1191
-
1192
1049
  case 44:
1193
1050
  this.$ = yy.Mul.handleDivide($$[$0 - 4], $$[$0 - 1]);
1194
1051
  break;
@@ -2101,96 +1958,80 @@ var parser = function () {
2101
1958
  },
2102
1959
  parse: function parse(input) {
2103
1960
  var self = this,
2104
- stack = [0],
2105
- vstack = [null],
2106
- lstack = [],
2107
- table = this.table,
2108
- yytext = '',
2109
- yylineno = 0,
2110
- yyleng = 0,
2111
- TERROR = 2,
2112
- EOF = 1;
1961
+ stack = [0],
1962
+ vstack = [null],
1963
+ lstack = [],
1964
+ table = this.table,
1965
+ yytext = '',
1966
+ yylineno = 0,
1967
+ yyleng = 0,
1968
+ TERROR = 2,
1969
+ EOF = 1;
2113
1970
  var args = lstack.slice.call(arguments, 1);
2114
1971
  var lexer = Object.create(this.lexer);
2115
1972
  var sharedState = {
2116
1973
  yy: {}
2117
1974
  };
2118
-
2119
1975
  for (var k in this.yy) {
2120
1976
  if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
2121
1977
  sharedState.yy[k] = this.yy[k];
2122
1978
  }
2123
1979
  }
2124
-
2125
1980
  lexer.setInput(input, sharedState.yy);
2126
1981
  sharedState.yy.lexer = lexer;
2127
1982
  sharedState.yy.parser = this;
2128
-
2129
1983
  if (typeof lexer.yylloc == 'undefined') {
2130
1984
  lexer.yylloc = {};
2131
1985
  }
2132
-
2133
1986
  var yyloc = lexer.yylloc;
2134
1987
  lstack.push(yyloc);
2135
1988
  var ranges = lexer.options && lexer.options.ranges;
2136
-
2137
1989
  if (typeof sharedState.yy.parseError === 'function') {
2138
1990
  this.parseError = sharedState.yy.parseError;
2139
1991
  } else {
2140
1992
  this.parseError = Object.getPrototypeOf(this).parseError;
2141
1993
  }
2142
-
2143
-
1994
+ //_token_stack:
2144
1995
  function lex() {
2145
1996
  var token;
2146
1997
  token = lexer.lex() || EOF;
2147
-
2148
1998
  if (typeof token !== 'number') {
2149
1999
  token = self.symbols_[token] || token;
2150
2000
  }
2151
-
2152
2001
  return token;
2153
2002
  }
2154
-
2155
2003
  var symbol,
2156
- state,
2157
- action,
2158
- r,
2159
- yyval = {},
2160
- p,
2161
- len,
2162
- newState,
2163
- expected;
2164
-
2004
+ state,
2005
+ action,
2006
+ r,
2007
+ yyval = {},
2008
+ p,
2009
+ len,
2010
+ newState,
2011
+ expected;
2165
2012
  while (true) {
2166
2013
  state = stack[stack.length - 1];
2167
-
2168
2014
  if (this.defaultActions[state]) {
2169
2015
  action = this.defaultActions[state];
2170
2016
  } else {
2171
2017
  if (symbol === null || typeof symbol == 'undefined') {
2172
2018
  symbol = lex();
2173
2019
  }
2174
-
2175
2020
  action = table[state] && table[state][symbol];
2176
2021
  }
2177
-
2178
2022
  if (typeof action === 'undefined' || !action.length || !action[0]) {
2179
2023
  var errStr = '';
2180
2024
  expected = [];
2181
-
2182
2025
  for (p in table[state]) {
2183
2026
  if (this.terminals_[p] && p > TERROR) {
2184
2027
  expected.push('\'' + this.terminals_[p] + '\'');
2185
2028
  }
2186
2029
  }
2187
-
2188
2030
  if (lexer.showPosition) {
2189
2031
  errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
2190
2032
  } else {
2191
2033
  errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
2192
2034
  }
2193
-
2194
2035
  this.parseError(errStr, {
2195
2036
  text: lexer.match,
2196
2037
  token: this.terminals_[symbol] || symbol,
@@ -2199,11 +2040,9 @@ var parser = function () {
2199
2040
  expected: expected
2200
2041
  });
2201
2042
  }
2202
-
2203
2043
  if (action[0] instanceof Array && action.length > 1) {
2204
2044
  throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
2205
2045
  }
2206
-
2207
2046
  switch (action[0]) {
2208
2047
  case 1:
2209
2048
  stack.push(symbol);
@@ -2211,16 +2050,13 @@ var parser = function () {
2211
2050
  lstack.push(lexer.yylloc);
2212
2051
  stack.push(action[1]);
2213
2052
  symbol = null;
2214
-
2215
2053
  {
2216
2054
  yyleng = lexer.yyleng;
2217
2055
  yytext = lexer.yytext;
2218
2056
  yylineno = lexer.yylineno;
2219
2057
  yyloc = lexer.yylloc;
2220
2058
  }
2221
-
2222
2059
  break;
2223
-
2224
2060
  case 2:
2225
2061
  len = this.productions_[action[1]][1];
2226
2062
  yyval.$ = vstack[vstack.length - len];
@@ -2230,40 +2066,32 @@ var parser = function () {
2230
2066
  first_column: lstack[lstack.length - (len || 1)].first_column,
2231
2067
  last_column: lstack[lstack.length - 1].last_column
2232
2068
  };
2233
-
2234
2069
  if (ranges) {
2235
2070
  yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
2236
2071
  }
2237
-
2238
2072
  r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
2239
-
2240
2073
  if (typeof r !== 'undefined') {
2241
2074
  return r;
2242
2075
  }
2243
-
2244
2076
  if (len) {
2245
2077
  stack = stack.slice(0, -1 * len * 2);
2246
2078
  vstack = vstack.slice(0, -1 * len);
2247
2079
  lstack = lstack.slice(0, -1 * len);
2248
2080
  }
2249
-
2250
2081
  stack.push(this.productions_[action[1]][0]);
2251
2082
  vstack.push(yyval.$);
2252
2083
  lstack.push(yyval._$);
2253
2084
  newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
2254
2085
  stack.push(newState);
2255
2086
  break;
2256
-
2257
2087
  case 3:
2258
2088
  return true;
2259
2089
  }
2260
2090
  }
2261
-
2262
2091
  return true;
2263
2092
  }
2264
2093
  };
2265
2094
  /* generated by jison-lex 0.3.4 */
2266
-
2267
2095
  var lexer = function () {
2268
2096
  var lexer = {
2269
2097
  EOF: 1,
@@ -2288,11 +2116,9 @@ var parser = function () {
2288
2116
  last_line: 1,
2289
2117
  last_column: 0
2290
2118
  };
2291
-
2292
2119
  if (this.options.ranges) {
2293
2120
  this.yylloc.range = [0, 0];
2294
2121
  }
2295
-
2296
2122
  this.offset = 0;
2297
2123
  return this;
2298
2124
  },
@@ -2305,18 +2131,15 @@ var parser = function () {
2305
2131
  this.match += ch;
2306
2132
  this.matched += ch;
2307
2133
  var lines = ch.match(/(?:\r\n?|\n).*/g);
2308
-
2309
2134
  if (lines) {
2310
2135
  this.yylineno++;
2311
2136
  this.yylloc.last_line++;
2312
2137
  } else {
2313
2138
  this.yylloc.last_column++;
2314
2139
  }
2315
-
2316
2140
  if (this.options.ranges) {
2317
2141
  this.yylloc.range[1]++;
2318
2142
  }
2319
-
2320
2143
  this._input = this._input.slice(1);
2321
2144
  return ch;
2322
2145
  },
@@ -2325,17 +2148,15 @@ var parser = function () {
2325
2148
  var len = ch.length;
2326
2149
  var lines = ch.split(/(?:\r\n?|\n)/g);
2327
2150
  this._input = ch + this._input;
2328
- this.yytext = this.yytext.substr(0, this.yytext.length - len); //this.yyleng -= len;
2329
-
2151
+ this.yytext = this.yytext.substr(0, this.yytext.length - len);
2152
+ //this.yyleng -= len;
2330
2153
  this.offset -= len;
2331
2154
  var oldLines = this.match.split(/(?:\r\n?|\n)/g);
2332
2155
  this.match = this.match.substr(0, this.match.length - 1);
2333
2156
  this.matched = this.matched.substr(0, this.matched.length - 1);
2334
-
2335
2157
  if (lines.length - 1) {
2336
2158
  this.yylineno -= lines.length - 1;
2337
2159
  }
2338
-
2339
2160
  var r = this.yylloc.range;
2340
2161
  this.yylloc = {
2341
2162
  first_line: this.yylloc.first_line,
@@ -2343,11 +2164,9 @@ var parser = function () {
2343
2164
  first_column: this.yylloc.first_column,
2344
2165
  last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
2345
2166
  };
2346
-
2347
2167
  if (this.options.ranges) {
2348
2168
  this.yylloc.range = [r[0], r[0] + this.yyleng - len];
2349
2169
  }
2350
-
2351
2170
  this.yyleng = this.yytext.length;
2352
2171
  return this;
2353
2172
  },
@@ -2367,7 +2186,6 @@ var parser = function () {
2367
2186
  line: this.yylineno
2368
2187
  });
2369
2188
  }
2370
-
2371
2189
  return this;
2372
2190
  },
2373
2191
  // retain first n characters of the match
@@ -2382,11 +2200,9 @@ var parser = function () {
2382
2200
  // displays upcoming input, i.e. for error messages
2383
2201
  upcomingInput: function upcomingInput() {
2384
2202
  var next = this.match;
2385
-
2386
2203
  if (next.length < 20) {
2387
2204
  next += this._input.substr(0, 20 - next.length);
2388
2205
  }
2389
-
2390
2206
  return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
2391
2207
  },
2392
2208
  // displays the character position where the lexing error occurred, i.e. for error messages
@@ -2398,7 +2214,6 @@ var parser = function () {
2398
2214
  // test the lexed token: return FALSE when not a match, otherwise return token
2399
2215
  test_match: function test_match(match, indexed_rule) {
2400
2216
  var token, lines, backup;
2401
-
2402
2217
  if (this.options.backtrack_lexer) {
2403
2218
  // save context
2404
2219
  backup = {
@@ -2421,18 +2236,14 @@ var parser = function () {
2421
2236
  conditionStack: this.conditionStack.slice(0),
2422
2237
  done: this.done
2423
2238
  };
2424
-
2425
2239
  if (this.options.ranges) {
2426
2240
  backup.yylloc.range = this.yylloc.range.slice(0);
2427
2241
  }
2428
2242
  }
2429
-
2430
2243
  lines = match[0].match(/(?:\r\n?|\n).*/g);
2431
-
2432
2244
  if (lines) {
2433
2245
  this.yylineno += lines.length;
2434
2246
  }
2435
-
2436
2247
  this.yylloc = {
2437
2248
  first_line: this.yylloc.last_line,
2438
2249
  last_line: this.yylineno + 1,
@@ -2443,21 +2254,17 @@ var parser = function () {
2443
2254
  this.match += match[0];
2444
2255
  this.matches = match;
2445
2256
  this.yyleng = this.yytext.length;
2446
-
2447
2257
  if (this.options.ranges) {
2448
2258
  this.yylloc.range = [this.offset, this.offset += this.yyleng];
2449
2259
  }
2450
-
2451
2260
  this._more = false;
2452
2261
  this._backtrack = false;
2453
2262
  this._input = this._input.slice(match[0].length);
2454
2263
  this.matched += match[0];
2455
2264
  token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
2456
-
2457
2265
  if (this.done && this._input) {
2458
2266
  this.done = false;
2459
2267
  }
2460
-
2461
2268
  if (token) {
2462
2269
  return token;
2463
2270
  } else if (this._backtrack) {
@@ -2465,7 +2272,6 @@ var parser = function () {
2465
2272
  for (var k in backup) {
2466
2273
  this[k] = backup[k];
2467
2274
  }
2468
-
2469
2275
  return false; // rule action called reject() implying the next rule should be tested instead.
2470
2276
  }
2471
2277
 
@@ -2476,30 +2282,22 @@ var parser = function () {
2476
2282
  if (this.done) {
2477
2283
  return this.EOF;
2478
2284
  }
2479
-
2480
2285
  if (!this._input) {
2481
2286
  this.done = true;
2482
2287
  }
2483
-
2484
2288
  var token, match, tempMatch, index;
2485
-
2486
2289
  if (!this._more) {
2487
2290
  this.yytext = '';
2488
2291
  this.match = '';
2489
2292
  }
2490
-
2491
2293
  var rules = this._currentRules();
2492
-
2493
2294
  for (var i = 0; i < rules.length; i++) {
2494
2295
  tempMatch = this._input.match(this.rules[rules[i]]);
2495
-
2496
2296
  if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
2497
2297
  match = tempMatch;
2498
2298
  index = i;
2499
-
2500
2299
  if (this.options.backtrack_lexer) {
2501
2300
  token = this.test_match(tempMatch, rules[i]);
2502
-
2503
2301
  if (token !== false) {
2504
2302
  return token;
2505
2303
  } else if (this._backtrack) {
@@ -2514,18 +2312,14 @@ var parser = function () {
2514
2312
  }
2515
2313
  }
2516
2314
  }
2517
-
2518
2315
  if (match) {
2519
2316
  token = this.test_match(match, rules[index]);
2520
-
2521
2317
  if (token !== false) {
2522
2318
  return token;
2523
- } // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
2524
-
2525
-
2319
+ }
2320
+ // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
2526
2321
  return false;
2527
2322
  }
2528
-
2529
2323
  if (this._input === "") {
2530
2324
  return this.EOF;
2531
2325
  } else {
@@ -2539,7 +2333,6 @@ var parser = function () {
2539
2333
  // return next match that has a token
2540
2334
  lex: function lex() {
2541
2335
  var r = this.next();
2542
-
2543
2336
  if (r) {
2544
2337
  return r;
2545
2338
  } else {
@@ -2553,7 +2346,6 @@ var parser = function () {
2553
2346
  // pop the previously active lexer condition state off the condition stack
2554
2347
  popState: function popState() {
2555
2348
  var n = this.conditionStack.length - 1;
2556
-
2557
2349
  if (n > 0) {
2558
2350
  return this.conditionStack.pop();
2559
2351
  } else {
@@ -2571,7 +2363,6 @@ var parser = function () {
2571
2363
  // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
2572
2364
  topState: function topState(n) {
2573
2365
  n = this.conditionStack.length - 1 - Math.abs(n || 0);
2574
-
2575
2366
  if (n >= 0) {
2576
2367
  return this.conditionStack[n];
2577
2368
  } else {
@@ -2590,297 +2381,212 @@ var parser = function () {
2590
2381
  "flex": true
2591
2382
  },
2592
2383
  performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
2593
-
2594
2384
  switch ($avoiding_name_collisions) {
2595
2385
  case 0:
2596
2386
  /* skip whitespace */
2597
2387
  break;
2598
-
2599
2388
  case 1:
2600
2389
  /* skip \space */
2601
2390
  break;
2602
-
2603
2391
  case 2:
2604
2392
  /* skip '\ ' */
2605
2393
  break;
2606
-
2607
2394
  case 3:
2608
2395
  return "INT";
2609
-
2610
2396
  case 4:
2611
2397
  return "FLOAT";
2612
-
2613
2398
  case 5:
2614
2399
  return "^";
2615
-
2616
2400
  case 6:
2617
2401
  return "*";
2618
-
2619
2402
  case 7:
2620
2403
  return "*";
2621
-
2622
2404
  case 8:
2623
2405
  return "*";
2624
-
2625
2406
  case 9:
2626
2407
  return "*";
2627
-
2628
2408
  case 10:
2629
2409
  return "/";
2630
-
2631
2410
  case 11:
2632
2411
  return "/";
2633
-
2634
2412
  case 12:
2635
2413
  return "-";
2636
-
2637
2414
  case 13:
2638
2415
  return "-";
2639
-
2640
2416
  case 14:
2641
2417
  return "+";
2642
-
2643
2418
  case 15:
2644
2419
  return "^";
2645
-
2646
2420
  case 16:
2647
2421
  return "(";
2648
-
2649
2422
  case 17:
2650
2423
  return ")";
2651
-
2652
2424
  case 18:
2653
2425
  return "(";
2654
-
2655
2426
  case 19:
2656
2427
  return ")";
2657
-
2658
2428
  case 20:
2659
2429
  return "[";
2660
-
2661
2430
  case 21:
2662
2431
  return "]";
2663
-
2664
2432
  case 22:
2665
2433
  return "{";
2666
-
2667
2434
  case 23:
2668
2435
  return "}";
2669
-
2670
2436
  case 24:
2671
2437
  return "{";
2672
-
2673
2438
  case 25:
2674
2439
  return "}";
2675
-
2676
2440
  case 26:
2677
2441
  return "_";
2678
-
2679
2442
  case 27:
2680
2443
  return "|";
2681
-
2682
2444
  case 28:
2683
2445
  return "LEFT|";
2684
-
2685
2446
  case 29:
2686
2447
  return "RIGHT|";
2687
-
2688
2448
  case 30:
2689
2449
  return "!";
2690
-
2691
2450
  case 31:
2692
2451
  return "SIGN";
2693
-
2694
2452
  case 32:
2695
2453
  yy_.yytext = "<=";
2696
2454
  return "SIGN";
2697
-
2698
2455
  case 33:
2699
2456
  yy_.yytext = ">=";
2700
2457
  return "SIGN";
2701
-
2702
2458
  case 34:
2703
2459
  yy_.yytext = "<=";
2704
2460
  return "SIGN";
2705
-
2706
2461
  case 35:
2707
2462
  yy_.yytext = ">=";
2708
2463
  return "SIGN";
2709
-
2710
2464
  case 36:
2711
2465
  yy_.yytext = "<>";
2712
2466
  return "SIGN";
2713
-
2714
2467
  case 37:
2715
2468
  yy_.yytext = "<>";
2716
2469
  return "SIGN";
2717
-
2718
2470
  case 38:
2719
2471
  yy_.yytext = "<>";
2720
2472
  return "SIGN";
2721
-
2722
2473
  case 39:
2723
2474
  yy_.yytext = "<>";
2724
2475
  return "SIGN";
2725
-
2726
2476
  case 40:
2727
2477
  yy_.yytext = "<=";
2728
2478
  return "SIGN";
2729
-
2730
2479
  case 41:
2731
2480
  yy_.yytext = ">=";
2732
2481
  return "SIGN";
2733
-
2734
2482
  case 42:
2735
2483
  return "FRAC";
2736
-
2737
2484
  case 43:
2738
2485
  return "FRAC";
2739
-
2740
2486
  case 44:
2741
2487
  return "sqrt";
2742
-
2743
2488
  case 45:
2744
2489
  return "abs";
2745
-
2746
2490
  case 46:
2747
2491
  return "ln";
2748
-
2749
2492
  case 47:
2750
2493
  return "log";
2751
-
2752
2494
  case 48:
2753
2495
  return "TRIG";
2754
-
2755
2496
  case 49:
2756
2497
  return "TRIG";
2757
-
2758
2498
  case 50:
2759
2499
  return "TRIG";
2760
-
2761
2500
  case 51:
2762
2501
  return "TRIG";
2763
-
2764
2502
  case 52:
2765
2503
  yy_.yytext = "sin";
2766
2504
  return "TRIG";
2767
-
2768
2505
  case 53:
2769
2506
  yy_.yytext = "cos";
2770
2507
  return "TRIG";
2771
-
2772
2508
  case 54:
2773
2509
  yy_.yytext = "tan";
2774
2510
  return "TRIG";
2775
-
2776
2511
  case 55:
2777
2512
  yy_.yytext = "csc";
2778
2513
  return "TRIG";
2779
-
2780
2514
  case 56:
2781
2515
  yy_.yytext = "sec";
2782
2516
  return "TRIG";
2783
-
2784
2517
  case 57:
2785
2518
  yy_.yytext = "cot";
2786
2519
  return "TRIG";
2787
-
2788
2520
  case 58:
2789
2521
  yy_.yytext = "arcsin";
2790
2522
  return "TRIG";
2791
-
2792
2523
  case 59:
2793
2524
  yy_.yytext = "arccos";
2794
2525
  return "TRIG";
2795
-
2796
2526
  case 60:
2797
2527
  yy_.yytext = "arctan";
2798
2528
  return "TRIG";
2799
-
2800
2529
  case 61:
2801
2530
  yy_.yytext = "arccsc";
2802
2531
  return "TRIG";
2803
-
2804
2532
  case 62:
2805
2533
  yy_.yytext = "arcsec";
2806
2534
  return "TRIG";
2807
-
2808
2535
  case 63:
2809
2536
  yy_.yytext = "arccot";
2810
2537
  return "TRIG";
2811
-
2812
2538
  case 64:
2813
2539
  return "TRIGINV";
2814
-
2815
2540
  case 65:
2816
2541
  return "TRIGINV";
2817
-
2818
2542
  case 66:
2819
2543
  yy_.yytext = "sinh";
2820
2544
  return "TRIG";
2821
-
2822
2545
  case 67:
2823
2546
  yy_.yytext = "cosh";
2824
2547
  return "TRIG";
2825
-
2826
2548
  case 68:
2827
2549
  yy_.yytext = "tanh";
2828
2550
  return "TRIG";
2829
-
2830
2551
  case 69:
2831
2552
  yy_.yytext = "csch";
2832
2553
  return "TRIG";
2833
-
2834
2554
  case 70:
2835
2555
  yy_.yytext = "sech";
2836
2556
  return "TRIG";
2837
-
2838
2557
  case 71:
2839
2558
  yy_.yytext = "tanh";
2840
2559
  return "TRIG";
2841
-
2842
2560
  case 72:
2843
2561
  return "CONST";
2844
-
2845
2562
  case 73:
2846
2563
  yy_.yytext = "pi";
2847
2564
  return "CONST";
2848
-
2849
2565
  case 74:
2850
2566
  yy_.yytext = "pi";
2851
2567
  return "CONST";
2852
-
2853
2568
  case 75:
2854
2569
  return "VAR";
2855
-
2856
2570
  case 76:
2857
2571
  yy_.yytext = "theta";
2858
2572
  return "VAR";
2859
-
2860
2573
  case 77:
2861
2574
  yy_.yytext = "theta";
2862
2575
  return "VAR";
2863
-
2864
2576
  case 78:
2865
2577
  return "VAR";
2866
-
2867
2578
  case 79:
2868
2579
  yy_.yytext = "phi";
2869
2580
  return "VAR";
2870
-
2871
2581
  case 80:
2872
2582
  yy_.yytext = "phi";
2873
2583
  return "VAR";
2874
-
2875
2584
  case 81:
2876
2585
  return yy.symbolLexer(yy_.yytext);
2877
-
2878
2586
  case 82:
2879
2587
  return "EOF";
2880
-
2881
2588
  case 83:
2882
2589
  return "INVALID";
2883
-
2884
2590
  case 84:
2885
2591
  console.log(yy_.yytext);
2886
2592
  break;
@@ -2896,19 +2602,17 @@ var parser = function () {
2896
2602
  };
2897
2603
  return lexer;
2898
2604
  }();
2899
-
2900
2605
  parser.lexer = lexer;
2901
-
2902
2606
  function Parser() {
2903
2607
  this.yy = {};
2904
2608
  }
2905
-
2906
2609
  Parser.prototype = parser;
2907
2610
  parser.Parser = Parser;
2908
2611
  return new Parser();
2909
2612
  }();
2910
2613
 
2911
2614
  /* eslint-disable prettier/prettier */
2615
+
2912
2616
  /* The node hierarcy is as follows:
2913
2617
 
2914
2618
  (Expr)
@@ -2939,40 +2643,38 @@ var parser = function () {
2939
2643
  */
2940
2644
 
2941
2645
  /* non user-facing functions */
2942
- // assert that all abstract methods have been overridden
2943
2646
 
2647
+ // assert that all abstract methods have been overridden
2944
2648
  var abstract = function abstract() {
2945
2649
  // Try to give people a bit of information when this happens
2946
- throw new Error("Abstract method - must override for expr: " + // eslint-disable-next-line @babel/no-invalid-this
2650
+ throw new Error("Abstract method - must override for expr: " +
2651
+ // eslint-disable-next-line @babel/no-invalid-this
2947
2652
  this.print());
2948
- }; // throw an error that is meant to be caught by the test suite (not user facing)
2949
-
2653
+ };
2950
2654
 
2655
+ // throw an error that is meant to be caught by the test suite (not user facing)
2951
2656
  var error = function error(message) {
2952
2657
  throw new Error(message);
2953
- }; // reliably detect NaN
2954
-
2658
+ };
2955
2659
 
2660
+ // reliably detect NaN
2956
2661
  var isNaN = function isNaN(object) {
2957
2662
  return object !== object;
2958
- }; // return a random float between min (inclusive) and max (exclusive),
2959
- // not that inclusivity means much, probabilistically, on floats
2960
-
2663
+ };
2961
2664
 
2665
+ // return a random float between min (inclusive) and max (exclusive),
2666
+ // not that inclusivity means much, probabilistically, on floats
2962
2667
  var randomFloat = function randomFloat(min, max) {
2963
2668
  var extent = max - min;
2964
2669
  return Math.random() * extent + min;
2965
2670
  };
2966
- /* constants */
2967
-
2968
2671
 
2672
+ /* constants */
2969
2673
  var ITERATIONS = 12;
2970
2674
  var TOLERANCE = 9; // decimal places
2971
2675
 
2972
2676
  /* abstract base expression node */
2973
-
2974
2677
  function Expr() {}
2975
-
2976
2678
  _.extend(Expr.prototype, {
2977
2679
  // this node's immediate constructor
2978
2680
  func: abstract,
@@ -2987,11 +2689,9 @@ _.extend(Expr.prototype, {
2987
2689
  // an abstraction for chainable, bottom-up recursion
2988
2690
  recurse: function recurse(method) {
2989
2691
  var passed = Array.prototype.slice.call(arguments, 1);
2990
-
2991
2692
  var args = _.map(this.args(), function (arg) {
2992
2693
  return _.isString(arg) ? arg : arg[method].apply(arg, passed);
2993
2694
  });
2994
-
2995
2695
  return this.construct(args);
2996
2696
  },
2997
2697
  // evaluate numerically with given variable mapping
@@ -2999,7 +2699,6 @@ _.extend(Expr.prototype, {
2999
2699
  codegen: abstract,
3000
2700
  compile: function compile() {
3001
2701
  var code = this.codegen();
3002
-
3003
2702
  try {
3004
2703
  return new Function("vars", "return " + code + ";");
3005
2704
  } catch (e) {
@@ -3015,28 +2714,22 @@ _.extend(Expr.prototype, {
3015
2714
  // returns a TeX string, modified by the given options
3016
2715
  asTex: function asTex(options) {
3017
2716
  options = options || {};
3018
-
3019
2717
  _.defaults(options, {
3020
2718
  display: true,
3021
2719
  dynamic: true,
3022
2720
  times: false
3023
2721
  });
3024
-
3025
2722
  var tex = this.tex();
3026
-
3027
2723
  if (options.display) {
3028
2724
  tex = "\\displaystyle " + tex;
3029
2725
  }
3030
-
3031
2726
  if (options.dynamic) {
3032
2727
  tex = tex.replace(/\(/g, "\\left(");
3033
2728
  tex = tex.replace(/\)/g, "\\right)");
3034
2729
  }
3035
-
3036
2730
  if (options.times) {
3037
2731
  tex = tex.replace(/\\cdot/g, "\\times");
3038
2732
  }
3039
-
3040
2733
  return tex;
3041
2734
  },
3042
2735
  // returns the name of this expression's constructor as a string
@@ -3082,26 +2775,28 @@ _.extend(Expr.prototype, {
3082
2775
  simplify: function simplify(options) {
3083
2776
  options = _.extend({
3084
2777
  once: false
3085
- }, options); // Attempt to factor and collect
2778
+ }, options);
3086
2779
 
2780
+ // Attempt to factor and collect
3087
2781
  var step1 = this.factor(options);
3088
- var step2 = step1.collect(options); // Rollback if collect didn't do anything
2782
+ var step2 = step1.collect(options);
3089
2783
 
2784
+ // Rollback if collect didn't do anything
3090
2785
  if (step1.equals(step2)) {
3091
2786
  step2 = this.collect(options);
3092
- } // Attempt to expand and collect
3093
-
2787
+ }
3094
2788
 
2789
+ // Attempt to expand and collect
3095
2790
  var step3 = step2.expand(options);
3096
- var step4 = step3.collect(options); // Rollback if collect didn't do anything
2791
+ var step4 = step3.collect(options);
3097
2792
 
2793
+ // Rollback if collect didn't do anything
3098
2794
  if (step3.equals(step4)) {
3099
2795
  step4 = step2.collect(options);
3100
- } // One round of simplification complete
3101
-
2796
+ }
3102
2797
 
2798
+ // One round of simplification complete
3103
2799
  var simplified = step4;
3104
-
3105
2800
  if (options.once || this.equals(simplified)) {
3106
2801
  return simplified;
3107
2802
  } else {
@@ -3137,7 +2832,6 @@ _.extend(Expr.prototype, {
3137
2832
  if (this instanceof func) {
3138
2833
  return true;
3139
2834
  }
3140
-
3141
2835
  return _.any(this.exprArgs(), function (arg) {
3142
2836
  return arg.has(func);
3143
2837
  });
@@ -3165,17 +2859,16 @@ _.extend(Expr.prototype, {
3165
2859
  // check that the variables in both expressions are the same
3166
2860
  sameVars: function sameVars(other) {
3167
2861
  var vars1 = this.getVars();
3168
- var vars2 = other.getVars(); // the other Expr can have more variables than this one
3169
- // this lets you multiply equations by other variables
2862
+ var vars2 = other.getVars();
3170
2863
 
2864
+ // the other Expr can have more variables than this one
2865
+ // this lets you multiply equations by other variables
3171
2866
  var same = function same(array1, array2) {
3172
2867
  return !_.difference(array1, array2).length;
3173
2868
  };
3174
-
3175
2869
  var lower = function lower(array) {
3176
2870
  return _.uniq(_.invoke(array, "toLowerCase")).sort();
3177
2871
  };
3178
-
3179
2872
  var equal = same(vars1, vars2);
3180
2873
  var equalIgnoringCase = same(lower(vars1), lower(vars2));
3181
2874
  return {
@@ -3191,16 +2884,11 @@ _.extend(Expr.prototype, {
3191
2884
  if (other instanceof Eq) {
3192
2885
  return false;
3193
2886
  }
2887
+ var varList = _.union(this.getVars( /* excludeFunc */true), other.getVars( /* excludeFunc */true));
3194
2888
 
3195
- var varList = _.union(this.getVars(
3196
- /* excludeFunc */
3197
- true), other.getVars(
3198
- /* excludeFunc */
3199
- true)); // If the numbers are large we would like to do a relative comparison
2889
+ // If the numbers are large we would like to do a relative comparison
3200
2890
  // rather than an absolute one, but if they're small enough then an
3201
2891
  // absolute comparison makes more sense
3202
-
3203
-
3204
2892
  var getDelta = function getDelta(num1, num2) {
3205
2893
  if (Math.abs(num1) < 1 || Math.abs(num2) < 1) {
3206
2894
  return Math.abs(num1 - num2);
@@ -3208,30 +2896,28 @@ _.extend(Expr.prototype, {
3208
2896
  return Math.abs(1 - num1 / num2);
3209
2897
  }
3210
2898
  };
3211
-
3212
2899
  var equalNumbers = function equalNumbers(num1, num2) {
3213
2900
  var delta = getDelta(num1, num2);
3214
- return num1 === num2 ||
3215
- /* needed if either is +/- Infinity */
3216
- isNaN(num1) && isNaN(num2) || delta < Math.pow(10, -TOLERANCE);
3217
- }; // if no variables, only need to evaluate once
3218
-
2901
+ return num1 === num2 /* needed if either is +/- Infinity */ || isNaN(num1) && isNaN(num2) || delta < Math.pow(10, -TOLERANCE);
2902
+ };
3219
2903
 
2904
+ // if no variables, only need to evaluate once
3220
2905
  if (!varList.length && !this.has(Unit) && !other.has(Unit)) {
3221
2906
  return equalNumbers(this.eval(), other.eval());
3222
- } // collect here to avoid sometimes dividing by zero, and sometimes not
2907
+ }
2908
+
2909
+ // collect here to avoid sometimes dividing by zero, and sometimes not
3223
2910
  // it is better to be deterministic, e.g. x/x -> 1
3224
2911
  // TODO(alex): may want to keep track of assumptions as they're made
3225
-
3226
-
3227
2912
  var expr1 = this.collect();
3228
2913
  var expr2 = other.collect();
3229
2914
  var unitList1 = this.getUnits();
3230
2915
  var unitList2 = other.getUnits();
3231
-
3232
2916
  if (!_.isEqual(unitList1, unitList2)) {
3233
2917
  return false;
3234
- } // Compare at a set number (currently 12) of points to determine
2918
+ }
2919
+
2920
+ // Compare at a set number (currently 12) of points to determine
3235
2921
  // equality.
3236
2922
  //
3237
2923
  // `range` (and `vars`) is the only variable that varies through the
@@ -3240,12 +2926,13 @@ _.extend(Expr.prototype, {
3240
2926
  //
3241
2927
  // Note that because there are 12 iterations and three ranges, each
3242
2928
  // range is checked four times.
3243
-
3244
-
3245
2929
  for (var i = 0; i < ITERATIONS; i++) {
3246
- var vars = {}; // One third total iterations each with range 10, 100, and 1000
2930
+ var vars = {};
3247
2931
 
3248
- var range = Math.pow(10, 1 + Math.floor(3 * i / ITERATIONS)); // Half of the iterations should only use integer values.
2932
+ // One third total iterations each with range 10, 100, and 1000
2933
+ var range = Math.pow(10, 1 + Math.floor(3 * i / ITERATIONS));
2934
+
2935
+ // Half of the iterations should only use integer values.
3249
2936
  // This is because expressions like (-2)^x are common but result
3250
2937
  // in NaN when evaluated in JS with non-integer values of x.
3251
2938
  // Without this, (-2)^x and (-2)^(x+1) both end up always being NaN
@@ -3259,15 +2946,11 @@ _.extend(Expr.prototype, {
3259
2946
  // Integrate a library for handling complex numbers.
3260
2947
  //
3261
2948
  // TODO(alex): Add support for complex numbers, then remove this.
3262
-
3263
2949
  var useFloats = i % 2 === 0;
3264
-
3265
2950
  _.each(varList, function (v) {
3266
2951
  vars[v] = useFloats ? randomFloat(-range, range) : _.random(-range, range);
3267
2952
  });
3268
-
3269
2953
  var equal;
3270
-
3271
2954
  if (expr1.has(Func) || expr2.has(Func) || expr1.has(Unit) || expr2.has(Unit)) {
3272
2955
  var result1 = expr1.partialEval(vars);
3273
2956
  var result2 = expr2.partialEval(vars);
@@ -3277,12 +2960,10 @@ _.extend(Expr.prototype, {
3277
2960
  var result2 = expr2.eval(vars);
3278
2961
  equal = equalNumbers(result1, result2);
3279
2962
  }
3280
-
3281
2963
  if (!equal) {
3282
2964
  return false;
3283
2965
  }
3284
2966
  }
3285
-
3286
2967
  return true;
3287
2968
  },
3288
2969
  // evaluate as much of the expression as possible
@@ -3333,7 +3014,6 @@ _.extend(Expr.prototype, {
3333
3014
  if (!hint) {
3334
3015
  return this;
3335
3016
  }
3336
-
3337
3017
  var expr = this.construct(this.args());
3338
3018
  expr.hints = _.clone(this.hints);
3339
3019
  expr.hints[hint] = true;
@@ -3355,13 +3035,10 @@ _.extend(Expr.prototype, {
3355
3035
  return new Mul(Num.Neg, this);
3356
3036
  }
3357
3037
  });
3358
- /* abstract sequence node */
3359
-
3360
3038
 
3039
+ /* abstract sequence node */
3361
3040
  function Seq() {}
3362
-
3363
3041
  Seq.prototype = new Expr();
3364
-
3365
3042
  _.extend(Seq.prototype, {
3366
3043
  args: function args() {
3367
3044
  return this.terms;
@@ -3370,7 +3047,6 @@ _.extend(Seq.prototype, {
3370
3047
  var terms = _.sortBy(_.invoke(this.terms, "normalize"), function (term) {
3371
3048
  return term.print();
3372
3049
  });
3373
-
3374
3050
  return new this.func(terms);
3375
3051
  },
3376
3052
  expand: function expand() {
@@ -3381,11 +3057,11 @@ _.extend(Seq.prototype, {
3381
3057
  partition: function partition() {
3382
3058
  var terms = _.groupBy(this.terms, function (term) {
3383
3059
  return term instanceof Num;
3384
- }); // XXX using a boolean as a key just converts it to a string. I don't
3060
+ });
3061
+
3062
+ // XXX using a boolean as a key just converts it to a string. I don't
3385
3063
  // think this code was written with that in mind. Probably doesn't
3386
3064
  // matter except for readability.
3387
-
3388
-
3389
3065
  var numbers = terms[true] || [];
3390
3066
  var others = terms[false] || [];
3391
3067
  return [new this.func(numbers), new this.func(others)];
@@ -3394,29 +3070,23 @@ _.extend(Seq.prototype, {
3394
3070
  // this is a shallow flattening and will return a non-Seq if terms.length <= 1
3395
3071
  flatten: function flatten() {
3396
3072
  var type = this;
3397
-
3398
3073
  var terms = _.reject(this.terms, function (term) {
3399
3074
  return term.equals(type.identity);
3400
3075
  });
3401
-
3402
3076
  if (terms.length === 0) {
3403
3077
  return type.identity;
3404
3078
  }
3405
-
3406
3079
  if (terms.length === 1) {
3407
3080
  return terms[0];
3408
3081
  }
3409
-
3410
3082
  var grouped = _.groupBy(terms, function (term) {
3411
3083
  return term instanceof type.func;
3412
- }); // same contains the children which are Seqs of the same type as this Seq
3413
-
3084
+ });
3414
3085
 
3086
+ // same contains the children which are Seqs of the same type as this Seq
3415
3087
  var same = grouped[true] || [];
3416
3088
  var others = grouped[false] || [];
3417
- var flattened = others.concat(_.flatten(_.pluck(same, "terms"),
3418
- /* shallow: */
3419
- true));
3089
+ var flattened = others.concat(_.flatten(_.pluck(same, "terms"), /* shallow: */true));
3420
3090
  return new type.func(flattened);
3421
3091
  },
3422
3092
  // the identity associated with the sequence
@@ -3425,7 +3095,6 @@ _.extend(Seq.prototype, {
3425
3095
  reduce: abstract,
3426
3096
  isPositive: function isPositive() {
3427
3097
  var terms = _.invoke(this.terms, "collect");
3428
-
3429
3098
  return _.all(_.invoke(terms, "isPositive"));
3430
3099
  },
3431
3100
  // return a new Seq with a given term replaced by a different term
@@ -3433,21 +3102,17 @@ _.extend(Seq.prototype, {
3433
3102
  // if no new term is provided, the old one is simply removed
3434
3103
  replace: function replace(oldTerm, newTerm) {
3435
3104
  var index;
3436
-
3437
3105
  if (oldTerm instanceof Expr) {
3438
3106
  index = _.indexOf(this.terms, oldTerm);
3439
3107
  } else {
3440
3108
  index = oldTerm;
3441
3109
  }
3442
-
3443
3110
  var newTerms = [];
3444
-
3445
3111
  if (_.isArray(newTerm)) {
3446
3112
  newTerms = newTerm;
3447
3113
  } else if (newTerm) {
3448
3114
  newTerms = [newTerm];
3449
3115
  }
3450
-
3451
3116
  var terms = this.terms.slice(0, index).concat(newTerms).concat(this.terms.slice(index + 1));
3452
3117
  return new this.func(terms);
3453
3118
  },
@@ -3460,9 +3125,8 @@ _.extend(Seq.prototype, {
3460
3125
  return new Mul(_.invoke(this.terms, "getDenominator")).flatten();
3461
3126
  }
3462
3127
  });
3463
- /* sequence of additive terms */
3464
-
3465
3128
 
3129
+ /* sequence of additive terms */
3466
3130
  function Add() {
3467
3131
  if (arguments.length === 1) {
3468
3132
  this.terms = arguments[0];
@@ -3471,7 +3135,6 @@ function Add() {
3471
3135
  }
3472
3136
  }
3473
3137
  Add.prototype = new Seq();
3474
-
3475
3138
  _.extend(Add.prototype, {
3476
3139
  func: Add,
3477
3140
  eval: function _eval(vars, options) {
@@ -3489,7 +3152,6 @@ _.extend(Add.prototype, {
3489
3152
  },
3490
3153
  tex: function tex() {
3491
3154
  var tex = "";
3492
-
3493
3155
  _.each(this.terms, function (term) {
3494
3156
  if (!tex || term.isSubtract()) {
3495
3157
  tex += term.tex();
@@ -3497,15 +3159,13 @@ _.extend(Add.prototype, {
3497
3159
  tex += "+" + term.tex();
3498
3160
  }
3499
3161
  });
3500
-
3501
3162
  return tex;
3502
3163
  },
3503
3164
  collect: function collect(options) {
3504
- var terms = _.invoke(this.terms, "collect", options); // [Expr expr, Num coefficient]
3505
-
3165
+ var terms = _.invoke(this.terms, "collect", options);
3506
3166
 
3167
+ // [Expr expr, Num coefficient]
3507
3168
  var pairs = [];
3508
-
3509
3169
  _.each(terms, function (term) {
3510
3170
  if (term instanceof Mul) {
3511
3171
  var muls = term.partition();
@@ -3515,21 +3175,21 @@ _.extend(Add.prototype, {
3515
3175
  } else {
3516
3176
  pairs.push([term, Num.One]);
3517
3177
  }
3518
- }); // { (Expr expr).print(): [[Expr expr, Num coefficient]] }
3519
-
3178
+ });
3520
3179
 
3180
+ // { (Expr expr).print(): [[Expr expr, Num coefficient]] }
3521
3181
  var grouped = _.groupBy(pairs, function (pair) {
3522
3182
  return pair[0].normalize().print();
3523
3183
  });
3524
-
3525
3184
  var collected = _.compact(_.map(grouped, function (pairs) {
3526
3185
  var expr = pairs[0][0];
3527
3186
  var sum = new Add(_.zip.apply(_, pairs)[1]);
3528
3187
  var coefficient = sum.reduce(options);
3529
3188
  return new Mul(coefficient, expr).collect(options);
3530
- })); // TODO(alex): use the Pythagorean identity here
3531
- // e.g. x*sin^2(y) + x*cos^2(y) -> x
3189
+ }));
3532
3190
 
3191
+ // TODO(alex): use the Pythagorean identity here
3192
+ // e.g. x*sin^2(y) + x*cos^2(y) -> x
3533
3193
 
3534
3194
  return new Add(collected).flatten();
3535
3195
  },
@@ -3539,33 +3199,25 @@ _.extend(Add.prototype, {
3539
3199
  options = _.extend({
3540
3200
  keepNegative: false
3541
3201
  }, options);
3542
-
3543
3202
  var terms = _.invoke(this.terms, "collect");
3544
-
3545
3203
  var factors;
3546
-
3547
3204
  if (terms[0] instanceof Mul) {
3548
3205
  factors = terms[0].terms;
3549
3206
  } else {
3550
3207
  factors = [terms[0]];
3551
3208
  }
3552
-
3553
3209
  _.each(_.rest(this.terms), function (term) {
3554
3210
  factors = _.map(factors, function (factor) {
3555
3211
  return term.findGCD(factor);
3556
3212
  });
3557
3213
  });
3558
-
3559
3214
  if (!options.keepNegative && this.isNegative()) {
3560
3215
  factors.push(Num.Neg);
3561
3216
  }
3562
-
3563
3217
  factors = new Mul(factors).flatten().collect();
3564
-
3565
3218
  var remainder = _.map(terms, function (term) {
3566
3219
  return Mul.handleDivide(term, factors).simplify();
3567
3220
  });
3568
-
3569
3221
  remainder = new Add(remainder).flatten();
3570
3222
  return Mul.createOrAppend(factors, remainder).flatten();
3571
3223
  },
@@ -3579,16 +3231,14 @@ _.extend(Add.prototype, {
3579
3231
  },
3580
3232
  isNegative: function isNegative() {
3581
3233
  var terms = _.invoke(this.terms, "collect");
3582
-
3583
3234
  return _.all(_.invoke(terms, "isNegative"));
3584
3235
  },
3585
3236
  negate: function negate() {
3586
3237
  return new Add(_.invoke(this.terms, "negate"));
3587
3238
  }
3588
3239
  });
3589
- /* sequence of multiplicative terms */
3590
-
3591
3240
 
3241
+ /* sequence of multiplicative terms */
3592
3242
  function Mul() {
3593
3243
  if (arguments.length === 1) {
3594
3244
  this.terms = arguments[0];
@@ -3597,7 +3247,6 @@ function Mul() {
3597
3247
  }
3598
3248
  }
3599
3249
  Mul.prototype = new Seq();
3600
-
3601
3250
  _.extend(Mul.prototype, {
3602
3251
  func: Mul,
3603
3252
  eval: function _eval(vars, options) {
@@ -3619,7 +3268,6 @@ _.extend(Mul.prototype, {
3619
3268
  var tmUnits = _(this.terms).chain().map(function (term) {
3620
3269
  return term.getUnits();
3621
3270
  }).flatten().value();
3622
-
3623
3271
  tmUnits.sort((a, b) => a.unit.localeCompare(b.unit));
3624
3272
  return tmUnits;
3625
3273
  },
@@ -3627,7 +3275,6 @@ _.extend(Mul.prototype, {
3627
3275
  // so we follow convention: first any negatives, then any numbers, then everything else
3628
3276
  tex: function tex() {
3629
3277
  var cdot = " \\cdot ";
3630
-
3631
3278
  var terms = _.groupBy(this.terms, function (term) {
3632
3279
  if (term.isDivide()) {
3633
3280
  return "inverse";
@@ -3637,18 +3284,17 @@ _.extend(Mul.prototype, {
3637
3284
  return "other";
3638
3285
  }
3639
3286
  });
3640
-
3641
3287
  var inverses = terms.inverse || [];
3642
3288
  var numbers = terms.number || [];
3643
3289
  var others = terms.other || [];
3644
3290
  var negatives = "";
3645
- var numerator; // check all the numbers to see if there is a rational we can extract,
3291
+ var numerator;
3292
+
3293
+ // check all the numbers to see if there is a rational we can extract,
3646
3294
  // since we would like 1/2x/y to come out as \frac{1}{2}\frac{x}{y},
3647
3295
  // and not \frac{1x}{2y}.
3648
-
3649
3296
  for (var i = 0; i < numbers.length; i++) {
3650
3297
  var isRational = numbers[i] instanceof Rational && !(numbers[i] instanceof Int);
3651
-
3652
3298
  if (isRational && others.length > 0 && inverses.length > 0) {
3653
3299
  var withThisRemoved = numbers.slice();
3654
3300
  withThisRemoved.splice(i, 1);
@@ -3656,11 +3302,9 @@ _.extend(Mul.prototype, {
3656
3302
  return numbers[i].tex() + new Mul(newTerms).tex();
3657
3303
  }
3658
3304
  }
3659
-
3660
3305
  numbers = _.compact(_.map(numbers, function (term) {
3661
3306
  var hasDenom = term instanceof Rational && !(term instanceof Int);
3662
3307
  var shouldPushDown = !term.hints.fraction || inverses.length > 0;
3663
-
3664
3308
  if (hasDenom && shouldPushDown) {
3665
3309
  // e.g. 3x/4 -> 3/4*x (internally) -> 3x/4 (rendered)
3666
3310
  inverses.push(new Pow(new Int(term.d), Num.Div));
@@ -3671,13 +3315,11 @@ _.extend(Mul.prototype, {
3671
3315
  return term;
3672
3316
  }
3673
3317
  }));
3674
-
3675
3318
  if (numbers.length === 0 && others.length === 1) {
3676
3319
  // e.g. (x+y)/z -> \frac{x+y}{z}
3677
3320
  numerator = others[0].tex();
3678
3321
  } else {
3679
3322
  var tex = "";
3680
-
3681
3323
  _.each(numbers, function (term) {
3682
3324
  if (term.hints.subtract && term.hints.entered) {
3683
3325
  negatives += "-";
@@ -3691,7 +3333,6 @@ _.extend(Mul.prototype, {
3691
3333
  tex += (tex ? cdot : "") + term.tex();
3692
3334
  }
3693
3335
  });
3694
-
3695
3336
  _.each(others, function (term) {
3696
3337
  if (term.needsExplicitMul()) {
3697
3338
  // e.g. 2*2^3 -> 2(dot)2^3
@@ -3704,10 +3345,8 @@ _.extend(Mul.prototype, {
3704
3345
  tex += term.tex();
3705
3346
  }
3706
3347
  });
3707
-
3708
3348
  numerator = tex ? tex : "1";
3709
3349
  }
3710
-
3711
3350
  if (!inverses.length) {
3712
3351
  return negatives + numerator;
3713
3352
  } else {
@@ -3719,7 +3358,6 @@ _.extend(Mul.prototype, {
3719
3358
  var terms = _.map(this.terms, function (term) {
3720
3359
  return term instanceof Num ? term.abs() : term.strip();
3721
3360
  });
3722
-
3723
3361
  return new Mul(terms).flatten();
3724
3362
  },
3725
3363
  // expand numerator and denominator separately
@@ -3727,36 +3365,27 @@ _.extend(Mul.prototype, {
3727
3365
  var isAdd = function isAdd(term) {
3728
3366
  return term instanceof Add;
3729
3367
  };
3730
-
3731
3368
  var isInverse = function isInverse(term) {
3732
3369
  return term instanceof Pow && term.exp.isNegative();
3733
3370
  };
3734
-
3735
3371
  var isInverseAdd = function isInverseAdd(term) {
3736
3372
  return isInverse(term) && isAdd(term.base);
3737
3373
  };
3738
-
3739
3374
  var mul = this.recurse("expand").flatten();
3740
-
3741
3375
  var hasAdd = _.any(mul.terms, isAdd);
3742
-
3743
3376
  var hasInverseAdd = _.any(mul.terms, isInverseAdd);
3744
-
3745
3377
  if (!(hasAdd || hasInverseAdd)) {
3746
3378
  return mul;
3747
3379
  }
3748
-
3749
3380
  var terms = _.groupBy(mul.terms, isInverse);
3750
-
3751
3381
  var normals = terms[false] || [];
3752
3382
  var inverses = terms[true] || [];
3753
-
3754
3383
  if (hasAdd) {
3755
3384
  var grouped = _.groupBy(normals, isAdd);
3756
-
3757
3385
  var adds = grouped[true] || [];
3758
- var others = grouped[false] || []; // loop over each additive sequence
3386
+ var others = grouped[false] || [];
3759
3387
 
3388
+ // loop over each additive sequence
3760
3389
  var expanded = _.reduce(adds, function (expanded, add) {
3761
3390
  // loop over each expanded array of terms
3762
3391
  return _.reduce(expanded, function (temp, array) {
@@ -3765,38 +3394,34 @@ _.extend(Mul.prototype, {
3765
3394
  return array.concat(term);
3766
3395
  }));
3767
3396
  }, []);
3768
- }, [[]]); // join each fully expanded array of factors with remaining multiplicative factors
3769
-
3397
+ }, [[]]);
3770
3398
 
3399
+ // join each fully expanded array of factors with remaining multiplicative factors
3771
3400
  var muls = _.map(expanded, function (array) {
3772
3401
  return new Mul(others.concat(array)).flatten();
3773
3402
  });
3774
-
3775
3403
  normals = [new Add(muls)];
3776
3404
  }
3777
-
3778
3405
  if (hasInverseAdd) {
3779
3406
  var denominator = new Mul(_.invoke(inverses, "getDenominator")).flatten();
3780
3407
  inverses = [new Pow(denominator.expand(), Num.Div)];
3781
3408
  }
3782
-
3783
3409
  return new Mul(normals.concat(inverses)).flatten();
3784
3410
  },
3785
3411
  factor: function factor(options) {
3786
3412
  var factored = this.recurse("factor", options).flatten();
3787
-
3788
3413
  if (!(factored instanceof Mul)) {
3789
3414
  return factored;
3790
- } // Combine any factored out Rationals into one, but don't collect
3791
-
3415
+ }
3792
3416
 
3417
+ // Combine any factored out Rationals into one, but don't collect
3793
3418
  var grouped = _.groupBy(factored.terms, function (term) {
3794
3419
  return term instanceof Rational;
3795
- }); // Could also accomplish this by passing a new option
3420
+ });
3421
+
3422
+ // Could also accomplish this by passing a new option
3796
3423
  // e.g. return memo.mul(term, {autocollect: false});
3797
3424
  // TODO(alex): Decide whether this is a good use of options or not
3798
-
3799
-
3800
3425
  var rational = _.reduce(grouped[true], function (memo, term) {
3801
3426
  return {
3802
3427
  n: memo.n * term.n,
@@ -3806,61 +3431,58 @@ _.extend(Mul.prototype, {
3806
3431
  n: 1,
3807
3432
  d: 1
3808
3433
  });
3809
-
3810
3434
  if (rational.d === 1) {
3811
3435
  rational = new Int(rational.n);
3812
3436
  } else {
3813
3437
  rational = new Rational(rational.n, rational.d);
3814
3438
  }
3815
-
3816
3439
  return new Mul((grouped[false] || []).concat(rational)).flatten();
3817
3440
  },
3818
3441
  collect: function collect(options) {
3819
3442
  var partitioned = this.recurse("collect", options).partition();
3820
- var number = partitioned[0].reduce(options); // e.g. 0*x -> 0
3443
+ var number = partitioned[0].reduce(options);
3821
3444
 
3445
+ // e.g. 0*x -> 0
3822
3446
  if (number.eval() === 0) {
3823
3447
  return Num.Zero;
3824
3448
  }
3449
+ var others = partitioned[1].flatten();
3825
3450
 
3826
- var others = partitioned[1].flatten(); // e.g. 2*2 -> 4
3451
+ // e.g. 2*2 -> 4
3827
3452
  // e.g. 2*2*x -> 4*x
3828
-
3829
3453
  if (!(others instanceof Mul)) {
3830
3454
  return new Mul(number, others).flatten();
3831
3455
  }
3456
+ others = others.terms;
3832
3457
 
3833
- others = others.terms; // [Expr base, Expr exp]
3834
-
3458
+ // [Expr base, Expr exp]
3835
3459
  var pairs = [];
3836
-
3837
3460
  _.each(others, function (term) {
3838
3461
  if (term instanceof Pow) {
3839
3462
  pairs.push([term.base, term.exp]);
3840
3463
  } else {
3841
3464
  pairs.push([term, Num.One]);
3842
3465
  }
3843
- }); // {(Expr base).print(): [[Expr base, Expr exp]]}
3844
-
3466
+ });
3845
3467
 
3468
+ // {(Expr base).print(): [[Expr base, Expr exp]]}
3846
3469
  var grouped = _.groupBy(pairs, function (pair) {
3847
3470
  return pair[0].normalize().print();
3848
- }); // [[Expr base, Expr exp]]
3849
-
3471
+ });
3850
3472
 
3473
+ // [[Expr base, Expr exp]]
3851
3474
  var summed = _.compact(_.map(grouped, function (pairs) {
3852
3475
  var base = pairs[0][0];
3853
3476
  var sum = new Add(_.zip.apply(_, pairs)[1]);
3854
3477
  var exp = sum.collect(options);
3855
-
3856
3478
  if (exp instanceof Num && exp.eval() === 0) {
3857
3479
  return null;
3858
3480
  } else {
3859
3481
  return [base, exp];
3860
3482
  }
3861
- })); // XXX `pairs` is shadowed four or five times in this function
3862
-
3483
+ }));
3863
3484
 
3485
+ // XXX `pairs` is shadowed four or five times in this function
3864
3486
  var pairs = _.groupBy(summed, function (pair) {
3865
3487
  if (pair[0] instanceof Trig && pair[0].isBasic()) {
3866
3488
  return "trig";
@@ -3870,32 +3492,28 @@ _.extend(Mul.prototype, {
3870
3492
  return "expr";
3871
3493
  }
3872
3494
  });
3873
-
3874
3495
  var trigs = pairs.trig || [];
3875
3496
  var logs = pairs.log || [];
3876
3497
  var exprs = pairs.expr || [];
3877
-
3878
3498
  if (trigs.length > 1) {
3879
3499
  // combine sines and cosines into other trig functions
3500
+
3880
3501
  // {Trig.arg.print(): [[Trig base, Expr exp]]}
3881
3502
  var byArg = _.groupBy(trigs, function (pair) {
3882
3503
  return pair[0].arg.normalize().print();
3883
3504
  });
3884
-
3885
3505
  trigs = [];
3886
-
3887
3506
  _.each(byArg, function (pairs) {
3888
- var arg = pairs[0][0].arg; // {Trig.type: Expr exp}
3507
+ var arg = pairs[0][0].arg;
3889
3508
 
3509
+ // {Trig.type: Expr exp}
3890
3510
  var funcs = {
3891
3511
  sin: Num.Zero,
3892
3512
  cos: Num.Zero
3893
3513
  };
3894
-
3895
3514
  _.each(pairs, function (pair) {
3896
3515
  funcs[pair[0].type] = pair[1];
3897
3516
  });
3898
-
3899
3517
  if (Mul.handleNegative(funcs.sin).collect(options).equals(funcs.cos)) {
3900
3518
  // e.g. sin^x(y)/cos^x(y) -> tan^x(y)
3901
3519
  if (funcs.cos.isNegative()) {
@@ -3907,25 +3525,24 @@ _.extend(Mul.prototype, {
3907
3525
  cot: funcs.cos
3908
3526
  };
3909
3527
  }
3910
- } // TODO(alex): combine even if exponents not a perfect match
3911
- // TODO(alex): transform 1/sin and 1/cos into csc and sec
3528
+ }
3912
3529
 
3530
+ // TODO(alex): combine even if exponents not a perfect match
3531
+ // TODO(alex): transform 1/sin and 1/cos into csc and sec
3913
3532
 
3914
3533
  _.each(funcs, function (exp, type) {
3915
3534
  trigs.push([new Trig(type, arg), exp]);
3916
3535
  });
3917
3536
  });
3918
3537
  }
3919
-
3920
3538
  if (logs.length > 1) {
3921
3539
  // combine logs with the same base
3540
+
3922
3541
  // {Log.base.print(): [[Log base, Expr exp]]}
3923
3542
  var byBase = _.groupBy(logs, function (pair) {
3924
3543
  return pair[0].base.normalize().print();
3925
3544
  });
3926
-
3927
3545
  logs = [];
3928
-
3929
3546
  _.each(byBase, function (pairs) {
3930
3547
  // only combine two logs of the same base, otherwise commutative
3931
3548
  // differences result in different equally valid output
@@ -3941,16 +3558,15 @@ _.extend(Mul.prototype, {
3941
3558
  } else {
3942
3559
  logs = logs.concat(pairs);
3943
3560
  }
3944
- }); // TODO(alex): combine if all inverses are the same e.g. ln(y)*ln(z)/ln(x)/ln(x)
3561
+ });
3945
3562
 
3563
+ // TODO(alex): combine if all inverses are the same e.g. ln(y)*ln(z)/ln(x)/ln(x)
3946
3564
  }
3947
3565
 
3948
3566
  pairs = trigs.concat(logs).concat(exprs);
3949
-
3950
3567
  var collected = _.map(pairs, function (pair) {
3951
3568
  return new Pow(pair[0], pair[1]).collect(options);
3952
3569
  });
3953
-
3954
3570
  return new Mul([number].concat(collected)).flatten();
3955
3571
  },
3956
3572
  isSubtract: function isSubtract() {
@@ -3963,11 +3579,9 @@ _.extend(Mul.prototype, {
3963
3579
  factorIn: function factorIn(hint) {
3964
3580
  var partitioned = this.partition();
3965
3581
  var numbers = partitioned[0].terms;
3966
-
3967
3582
  var fold = numbers.length && _.all(numbers, function (num) {
3968
3583
  return num.n > 0;
3969
3584
  });
3970
-
3971
3585
  if (fold) {
3972
3586
  // e.g. - x*2*3 -> x*-2*3
3973
3587
  var num = numbers[0].negate();
@@ -3983,7 +3597,6 @@ _.extend(Mul.prototype, {
3983
3597
  // TODO(alex): make more general or rename to be more specific
3984
3598
  factorOut: function factorOut() {
3985
3599
  var factored = false;
3986
-
3987
3600
  var terms = _.compact(_.map(this.terms, function (term, i, list) {
3988
3601
  if (!factored && term instanceof Num && term.hints.divide) {
3989
3602
  factored = true;
@@ -3992,7 +3605,6 @@ _.extend(Mul.prototype, {
3992
3605
  return term;
3993
3606
  }
3994
3607
  }));
3995
-
3996
3608
  if (terms.length === 1) {
3997
3609
  return terms[0];
3998
3610
  } else {
@@ -4015,7 +3627,6 @@ _.extend(Mul.prototype, {
4015
3627
  return this;
4016
3628
  } else {
4017
3629
  var terms = _.invoke(this.collect().terms, "asPositiveFactor");
4018
-
4019
3630
  return new Mul(terms).flatten();
4020
3631
  }
4021
3632
  },
@@ -4029,18 +3640,16 @@ _.extend(Mul.prototype, {
4029
3640
  var isNum = function isNum(expr) {
4030
3641
  return expr instanceof Num;
4031
3642
  };
4032
-
4033
3643
  if (_.any(this.terms, isNum)) {
4034
3644
  var num = _.find(this.terms, isNum);
4035
-
4036
3645
  return this.replace(num, num.negate());
4037
3646
  } else {
4038
3647
  return new Mul([Num.Neg].concat(this.terms));
4039
3648
  }
4040
3649
  }
4041
- }); // static methods for the sequence types
4042
-
3650
+ });
4043
3651
 
3652
+ // static methods for the sequence types
4044
3653
  _.each([Add, Mul], function (type) {
4045
3654
  _.extend(type, {
4046
3655
  // create a new sequence unless left is already one (returns a copy)
@@ -4053,7 +3662,6 @@ _.each([Add, Mul], function (type) {
4053
3662
  }
4054
3663
  });
4055
3664
  });
4056
-
4057
3665
  _.extend(Mul, {
4058
3666
  // negative signs should be folded into numbers whenever possible
4059
3667
  // never fold into a Num that's already negative or a Mul that has a negative Num
@@ -4062,8 +3670,8 @@ _.extend(Mul, {
4062
3670
  handleNegative: function handleNegative(expr, hint) {
4063
3671
  if (expr instanceof Num && expr.n > 0) {
4064
3672
  // e.g. - 2 -> -2
4065
- var negated = expr.negate(); // TODO(alex): rework hint system so that this isn't necessary
4066
-
3673
+ var negated = expr.negate();
3674
+ // TODO(alex): rework hint system so that this isn't necessary
4067
3675
  negated.hints = expr.hints;
4068
3676
  return negated.addHint(hint);
4069
3677
  } else if (expr instanceof Mul) {
@@ -4084,35 +3692,30 @@ _.extend(Mul, {
4084
3692
  var rest = new Mul(_.rest(right.terms)).flatten();
4085
3693
  return Mul.handleDivide(first, rest);
4086
3694
  }
4087
-
4088
3695
  var isInt = function isInt(expr) {
4089
3696
  return expr instanceof Int;
4090
3697
  };
4091
-
4092
3698
  var isRational = function isRational(expr) {
4093
3699
  return expr instanceof Rational;
4094
- }; // for simplification purposes, fold Ints into Rationals if possible
4095
- // e.g. 3x / 4 -> 3/4 * x (will still render as 3x/4)
4096
-
3700
+ };
4097
3701
 
3702
+ // for simplification purposes, fold Ints into Rationals if possible
3703
+ // e.g. 3x / 4 -> 3/4 * x (will still render as 3x/4)
4098
3704
  if (isInt(right) && left instanceof Mul && _.any(left.terms, isInt)) {
4099
3705
  // search from the right
4100
3706
  var reversed = left.terms.slice().reverse();
4101
-
4102
3707
  var num = _.find(reversed, isRational);
4103
-
4104
3708
  if (!isInt(num)) {
4105
3709
  return new Mul(left.terms.concat([new Rational(1, right.n).addHint("fraction")]));
4106
3710
  }
4107
-
4108
3711
  var rational = new Rational(num.n, right.n);
4109
- rational.hints = num.hints; // in the case of something like 1/3 * 6/8, we want the
4110
- // 6/8 to be considered a fraction, not just a division
3712
+ rational.hints = num.hints;
4111
3713
 
3714
+ // in the case of something like 1/3 * 6/8, we want the
3715
+ // 6/8 to be considered a fraction, not just a division
4112
3716
  if (num === reversed[0]) {
4113
3717
  rational = rational.addHint("fraction");
4114
3718
  }
4115
-
4116
3719
  if (num.n < 0 && right.n < 0) {
4117
3720
  rational.d = -rational.d;
4118
3721
  return left.replace(num, [Num.Neg, rational]);
@@ -4120,7 +3723,6 @@ _.extend(Mul, {
4120
3723
  return left.replace(num, rational);
4121
3724
  }
4122
3725
  }
4123
-
4124
3726
  var divide = function divide(a, b) {
4125
3727
  if (b instanceof Int) {
4126
3728
  if (a instanceof Int) {
@@ -4137,7 +3739,6 @@ _.extend(Mul, {
4137
3739
  // e.g. x / 3 -> x*1/3
4138
3740
  // e.g. x / -3 -> x*-1/3
4139
3741
  var inverse = new Rational(1, b.eval());
4140
-
4141
3742
  if (b.eval() < 0) {
4142
3743
  return [a, inverse.addHint("negate")];
4143
3744
  } else {
@@ -4146,14 +3747,12 @@ _.extend(Mul, {
4146
3747
  }
4147
3748
  } else {
4148
3749
  var pow;
4149
-
4150
3750
  if (b instanceof Trig && b.exp) {
4151
3751
  // e.g. sin^2(x) -> sin(x)^2
4152
3752
  var exp = b.exp;
4153
3753
  b.exp = undefined;
4154
3754
  b = new Pow(b, exp);
4155
3755
  }
4156
-
4157
3756
  if (b instanceof Pow) {
4158
3757
  // e.g. (x^2) ^ -1 -> x^-2
4159
3758
  // e.g. (x^y) ^ -1 -> x^(-1*y)
@@ -4163,7 +3762,6 @@ _.extend(Mul, {
4163
3762
  // e.g. x ^ -1 -> x^-1
4164
3763
  pow = new Pow(b, Num.Div);
4165
3764
  }
4166
-
4167
3765
  if (a instanceof Int && a.n === 1) {
4168
3766
  // e.g. 1 / x -> x^-1
4169
3767
  return [pow];
@@ -4173,7 +3771,6 @@ _.extend(Mul, {
4173
3771
  }
4174
3772
  }
4175
3773
  };
4176
-
4177
3774
  if (left instanceof Mul) {
4178
3775
  var divided = divide(_.last(left.terms), right);
4179
3776
  return new Mul(_.initial(left.terms).concat(divided));
@@ -4188,6 +3785,7 @@ _.extend(Mul, {
4188
3785
  // e.g. -2*x -> -2*x simplified
4189
3786
  // e.g. -x*2 -> -1*x*2 not simplified -> x*-2 simplified
4190
3787
  // e.g. -1*x*2 -> -1*x*2 not simplified
3788
+
4191
3789
  // also fold multiplicative terms into open Trig and Log nodes
4192
3790
  // e.g. (sin x)*x -> sin(x)*x
4193
3791
  // e.g. sin(x)*x -> sin(x)*x
@@ -4199,23 +3797,18 @@ _.extend(Mul, {
4199
3797
  var trigLog = _.find(_.initial(expr.terms), function (term) {
4200
3798
  return (term instanceof Trig || term instanceof Log) && term.hints.open;
4201
3799
  });
4202
-
4203
3800
  var index = _.indexOf(expr.terms, trigLog);
4204
-
4205
3801
  if (trigLog) {
4206
3802
  var last = _.last(expr.terms);
4207
-
4208
3803
  if (trigLog.hints.parens || last.hints.parens || last.has(Trig) || last.has(Log)) {
4209
3804
  trigLog.hints.open = false;
4210
3805
  } else {
4211
3806
  var newTrigLog;
4212
-
4213
3807
  if (trigLog instanceof Trig) {
4214
3808
  newTrigLog = Trig.create([trigLog.type, trigLog.exp], Mul.createOrAppend(trigLog.arg, last).fold());
4215
3809
  } else {
4216
3810
  newTrigLog = Log.create(trigLog.base, Mul.createOrAppend(trigLog.power, last).fold());
4217
3811
  }
4218
-
4219
3812
  if (index === 0) {
4220
3813
  return newTrigLog;
4221
3814
  } else {
@@ -4223,47 +3816,39 @@ _.extend(Mul, {
4223
3816
  }
4224
3817
  }
4225
3818
  }
4226
-
4227
3819
  var partitioned = expr.partition();
4228
3820
  var numbers = partitioned[0].terms;
4229
-
4230
3821
  var pos = function pos(num) {
4231
3822
  return num.n > 0;
4232
3823
  };
4233
-
4234
3824
  var neg = function neg(num) {
4235
3825
  return num.n === -1 && num.hints.negate;
4236
3826
  };
4237
-
4238
3827
  var posOrNeg = function posOrNeg(num) {
4239
3828
  return pos(num) || neg(num);
4240
3829
  };
4241
-
4242
3830
  if (numbers.length > 1 && _.some(numbers, neg) && _.some(numbers, pos) && _.every(numbers, posOrNeg)) {
4243
3831
  var firstNeg = _.indexOf(expr.terms, _.find(expr.terms, neg));
3832
+ var firstNum = _.indexOf(expr.terms, _.find(expr.terms, pos));
4244
3833
 
4245
- var firstNum = _.indexOf(expr.terms, _.find(expr.terms, pos)); // e.g. -x*2 -> x*-2
4246
-
4247
-
3834
+ // e.g. -x*2 -> x*-2
4248
3835
  if (firstNeg < firstNum) {
4249
3836
  return expr.replace(firstNum, expr.terms[firstNum].negate()).remove(firstNeg);
4250
3837
  }
4251
3838
  }
4252
- } // in all other cases, make no change
4253
-
3839
+ }
4254
3840
 
3841
+ // in all other cases, make no change
4255
3842
  return expr;
4256
3843
  }
4257
3844
  });
4258
- /* exponentiation */
4259
-
4260
3845
 
3846
+ /* exponentiation */
4261
3847
  function Pow(base, exp) {
4262
3848
  this.base = base;
4263
3849
  this.exp = exp;
4264
3850
  }
4265
3851
  Pow.prototype = new Expr();
4266
-
4267
3852
  _.extend(Pow.prototype, {
4268
3853
  func: Pow,
4269
3854
  args: function args() {
@@ -4271,7 +3856,9 @@ _.extend(Pow.prototype, {
4271
3856
  },
4272
3857
  eval: function _eval(vars, options) {
4273
3858
  var evaledBase = this.base.eval(vars, options);
4274
- var evaledExp = this.exp.eval(vars, options); // Math.pow unequivocally returns NaN when provided with both a
3859
+ var evaledExp = this.exp.eval(vars, options);
3860
+
3861
+ // Math.pow unequivocally returns NaN when provided with both a
4275
3862
  // negative base and a fractional exponent. However, in some cases, we
4276
3863
  // know that our exponent is actually valid for use with negative
4277
3864
  // bases (e.g., (-5)^(1/3)).
@@ -4280,10 +3867,10 @@ _.extend(Pow.prototype, {
4280
3867
  // limited subset (by requiring that the exponent is rational with an
4281
3868
  // odd denominator), but it's still useful.
4282
3869
  // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow
4283
-
4284
3870
  if (evaledBase < 0) {
4285
- var simplifiedExp = this.exp.simplify(); // If Float, convert to a Rational to enable the logic below
3871
+ var simplifiedExp = this.exp.simplify();
4286
3872
 
3873
+ // If Float, convert to a Rational to enable the logic below
4287
3874
  if (simplifiedExp instanceof Float) {
4288
3875
  var num = simplifiedExp.n;
4289
3876
  var decimals = (num - num.toFixed()).toString().length - 2;
@@ -4291,10 +3878,8 @@ _.extend(Pow.prototype, {
4291
3878
  var rationalExp = new Rational(num * denominator, denominator);
4292
3879
  simplifiedExp = rationalExp.simplify();
4293
3880
  }
4294
-
4295
3881
  if (simplifiedExp instanceof Rational) {
4296
3882
  var oddDenominator = Math.abs(simplifiedExp.d) % 2 === 1;
4297
-
4298
3883
  if (oddDenominator) {
4299
3884
  var oddNumerator = Math.abs(simplifiedExp.n) % 2 === 1;
4300
3885
  var sign = oddNumerator ? -1 : 1;
@@ -4302,7 +3887,6 @@ _.extend(Pow.prototype, {
4302
3887
  }
4303
3888
  }
4304
3889
  }
4305
-
4306
3890
  return Math.pow(evaledBase, evaledExp);
4307
3891
  },
4308
3892
  getUnits: function getUnits() {
@@ -4318,11 +3902,9 @@ _.extend(Pow.prototype, {
4318
3902
  },
4319
3903
  print: function print() {
4320
3904
  var base = this.base.print();
4321
-
4322
3905
  if (this.base instanceof Seq || this.base instanceof Pow) {
4323
3906
  base = "(" + base + ")";
4324
3907
  }
4325
-
4326
3908
  return base + "^(" + this.exp.print() + ")";
4327
3909
  },
4328
3910
  tex: function tex() {
@@ -4333,7 +3915,6 @@ _.extend(Pow.prototype, {
4333
3915
  if (this.exp.n !== 1) {
4334
3916
  error("Node marked with hint 'root' does not have exponent " + "of form 1/x.");
4335
3917
  }
4336
-
4337
3918
  if (this.exp.d === 2) {
4338
3919
  // e.g. x ^ 1/2 w/hint -> sqrt{x}
4339
3920
  return "\\sqrt{" + this.base.tex() + "}";
@@ -4350,7 +3931,6 @@ _.extend(Pow.prototype, {
4350
3931
  } else {
4351
3932
  // e.g. x ^ y -> x^y
4352
3933
  var base = this.base.tex();
4353
-
4354
3934
  if (this.base instanceof Seq || this.base instanceof Pow || this.base instanceof Num && !this.base.isSimple()) {
4355
3935
  // e.g. a+b ^ c -> (a+b)^c
4356
3936
  base = "(" + base + ")";
@@ -4358,7 +3938,6 @@ _.extend(Pow.prototype, {
4358
3938
  // e.g. ln(x) ^ 2 -> [ln(x)]^2
4359
3939
  base = "[" + base + "]";
4360
3940
  }
4361
-
4362
3941
  return base + "^{" + this.exp.tex() + "}";
4363
3942
  }
4364
3943
  },
@@ -4367,55 +3946,53 @@ _.extend(Pow.prototype, {
4367
3946
  },
4368
3947
  expand: function expand() {
4369
3948
  var pow = this.recurse("expand");
4370
-
4371
3949
  if (pow.base instanceof Mul) {
4372
3950
  // e.g. (ab)^c -> a^c*b^c
3951
+
4373
3952
  var terms = _.map(pow.base.terms, function (term) {
4374
3953
  return new Pow(term, pow.exp);
4375
3954
  });
4376
-
4377
3955
  return new Mul(terms).expand();
4378
3956
  } else if (pow.base instanceof Add && pow.exp instanceof Int && pow.exp.abs().eval() > 1) {
4379
3957
  // e.g. (a+b)^2 -> a*a+a*b+a*b+b*b
4380
3958
  // e.g. (a+b)^-2 -> (a*a+a*b+a*b+b*b)^-1
3959
+
4381
3960
  var positive = pow.exp.eval() > 0;
4382
3961
  var n = pow.exp.abs().eval();
4383
-
4384
3962
  var signed = function signed(mul) {
4385
3963
  return positive ? mul : new Pow(mul, Num.Div);
4386
- }; // compute and cache powers of 2 up to n
4387
-
3964
+ };
4388
3965
 
3966
+ // compute and cache powers of 2 up to n
4389
3967
  var cache = {
4390
3968
  1: pow.base
4391
3969
  };
4392
-
4393
3970
  for (var i = 2; i <= n; i *= 2) {
4394
3971
  var mul = new Mul(cache[i / 2], cache[i / 2]);
4395
3972
  cache[i] = mul.expand().collect();
4396
- } // if n is a power of 2, you're done!
4397
-
3973
+ }
4398
3974
 
3975
+ // if n is a power of 2, you're done!
4399
3976
  if (_.has(cache, n)) {
4400
3977
  return signed(cache[n]);
4401
- } // otherwise decompose n into powers of 2 ...
4402
-
3978
+ }
4403
3979
 
3980
+ // otherwise decompose n into powers of 2 ...
4404
3981
  var indices = _.map(n.toString(2).split(""), function (str, i, list) {
4405
3982
  return Number(str) * Math.pow(2, list.length - i - 1);
4406
3983
  });
3984
+ indices = _.without(indices, 0);
4407
3985
 
4408
- indices = _.without(indices, 0); // ... then combine
4409
-
3986
+ // ... then combine
4410
3987
  var mul = new Mul(_.pick(cache, indices)).expand().collect();
4411
3988
  return signed(mul);
4412
3989
  } else if (pow.exp instanceof Add) {
4413
3990
  // DEFINITELY want behind super-simplify() flag
4414
3991
  // e.g. x^(a+b) -> x^a*x^b
3992
+
4415
3993
  var terms = _.map(pow.exp.terms, function (term) {
4416
3994
  return new Pow(pow.base, term).expand();
4417
3995
  });
4418
-
4419
3996
  return new Mul(terms).expand();
4420
3997
  } else {
4421
3998
  return pow;
@@ -4423,7 +4000,6 @@ _.extend(Pow.prototype, {
4423
4000
  },
4424
4001
  factor: function factor() {
4425
4002
  var pow = this.recurse("factor");
4426
-
4427
4003
  if (pow.base instanceof Mul) {
4428
4004
  var terms = _.map(pow.base.terms, function (term) {
4429
4005
  if (term instanceof Int && pow.exp.equals(Num.Div)) {
@@ -4434,7 +4010,6 @@ _.extend(Pow.prototype, {
4434
4010
  return new Pow(term, pow.exp);
4435
4011
  }
4436
4012
  });
4437
-
4438
4013
  return new Mul(terms);
4439
4014
  } else {
4440
4015
  return pow;
@@ -4449,13 +4024,10 @@ _.extend(Pow.prototype, {
4449
4024
  var exp = Mul.createOrAppend(this.base.exp, this.exp);
4450
4025
  return new Pow(base, exp).collect(options);
4451
4026
  }
4452
-
4453
4027
  var pow = this.recurse("collect", options);
4454
-
4455
4028
  var isSimilarLog = function isSimilarLog(term) {
4456
4029
  return term instanceof Log && term.base.equals(pow.base);
4457
4030
  };
4458
-
4459
4031
  if (pow.exp instanceof Num && pow.exp.eval() === 0) {
4460
4032
  // e.g. x^0 -> 1
4461
4033
  return Num.One;
@@ -4468,7 +4040,6 @@ _.extend(Pow.prototype, {
4468
4040
  } else if (pow.exp instanceof Mul && _.any(pow.exp.terms, isSimilarLog)) {
4469
4041
  // e.g. b^(2*y*log_b(x)) -> x^(2*y)
4470
4042
  var log = _.find(pow.exp.terms, isSimilarLog);
4471
-
4472
4043
  var base = log.power;
4473
4044
  var exp = pow.exp.remove(log).flatten();
4474
4045
  return new Pow(base, exp).collect(options);
@@ -4478,6 +4049,7 @@ _.extend(Pow.prototype, {
4478
4049
  if (options && options.preciseFloats) {
4479
4050
  // Avoid creating an imprecise float
4480
4051
  // e.g. 23^1.5 -> 12167^0.5, not ~110.304
4052
+
4481
4053
  // If you take the root as specified by the denominator and
4482
4054
  // end up with more digits after the decimal point,
4483
4055
  // the result is imprecise. This works for rationals as well
@@ -4488,16 +4060,15 @@ _.extend(Pow.prototype, {
4488
4060
  var decimalsInBase = pow.base.getDecimalPlaces();
4489
4061
  var root = new Pow(pow.base, new Rational(1, exp.d));
4490
4062
  var decimalsInRoot = root.collect().getDecimalPlaces();
4491
-
4492
4063
  if (decimalsInRoot > decimalsInBase) {
4493
4064
  // Collecting over this denominator would result in an
4494
4065
  // imprecise float, so avoid doing so.
4495
4066
  var newBase = new Pow(pow.base, new Int(exp.n)).collect();
4496
4067
  return new Pow(newBase, new Rational(1, exp.d));
4497
4068
  }
4498
- } // e.g. 4^1.5 -> 8
4499
-
4069
+ }
4500
4070
 
4071
+ // e.g. 4^1.5 -> 8
4501
4072
  return pow.base.raiseToThe(pow.exp, options);
4502
4073
  } else {
4503
4074
  return pow;
@@ -4508,7 +4079,6 @@ _.extend(Pow.prototype, {
4508
4079
  var isDiv = function isDiv(arg) {
4509
4080
  return arg instanceof Num && arg.hints.divide;
4510
4081
  };
4511
-
4512
4082
  return isDiv(this.exp) || this.exp instanceof Mul && _.any(this.exp.terms, isDiv);
4513
4083
  },
4514
4084
  // assuming this Pow represents user-entered division, returns the denominator
@@ -4550,16 +4120,15 @@ _.extend(Pow.prototype, {
4550
4120
  },
4551
4121
  findGCD: function findGCD(factor) {
4552
4122
  var base, exp;
4553
-
4554
4123
  if (factor instanceof Pow) {
4555
4124
  base = factor.base;
4556
4125
  exp = factor.exp;
4557
4126
  } else {
4558
4127
  base = factor;
4559
4128
  exp = Num.One;
4560
- } // GCD is only relevant if same base
4561
-
4129
+ }
4562
4130
 
4131
+ // GCD is only relevant if same base
4563
4132
  if (this.base.equals(base)) {
4564
4133
  if (this.exp.equals(exp)) {
4565
4134
  // exact match
@@ -4574,10 +4143,8 @@ _.extend(Pow.prototype, {
4574
4143
  // e.g. GCD(x^2, x^y) -> 1
4575
4144
  return Num.One;
4576
4145
  }
4577
-
4578
4146
  var expA = this.exp.asMul().partition();
4579
4147
  var expB = exp.asMul().partition();
4580
-
4581
4148
  if (expA[1].equals(expB[1])) {
4582
4149
  // exponents match except for coefficient
4583
4150
  // e.g. GCD(x^3y, x^y) -> x^y
@@ -4586,14 +4153,12 @@ _.extend(Pow.prototype, {
4586
4153
  return new Pow(base, mul).collect();
4587
4154
  }
4588
4155
  }
4589
-
4590
4156
  return Num.One;
4591
4157
  },
4592
4158
  isPositive: function isPositive() {
4593
4159
  if (this.base.isPositive()) {
4594
4160
  return true;
4595
4161
  }
4596
-
4597
4162
  var exp = this.exp.simplify();
4598
4163
  return exp instanceof Int && exp.eval() % 2 === 0;
4599
4164
  },
@@ -4602,10 +4167,8 @@ _.extend(Pow.prototype, {
4602
4167
  return this;
4603
4168
  } else {
4604
4169
  var exp = this.exp.simplify();
4605
-
4606
4170
  if (exp instanceof Int) {
4607
4171
  var n = exp.eval();
4608
-
4609
4172
  if (n > 2) {
4610
4173
  // e.g. x^3 -> x^2
4611
4174
  return new Pow(this.base, new Int(n - 1));
@@ -4614,32 +4177,29 @@ _.extend(Pow.prototype, {
4614
4177
  return new Pow(this.base, new Int(n + 1));
4615
4178
  }
4616
4179
  }
4617
-
4618
4180
  return Num.One;
4619
4181
  }
4620
4182
  }
4621
4183
  });
4622
-
4623
4184
  _.extend(Pow, {
4624
4185
  sqrt: function sqrt(arg) {
4625
4186
  return new Pow(arg, Num.Sqrt);
4626
4187
  },
4627
4188
  nthroot: function nthroot(radicand, degree) {
4628
- var exp = Mul.fold(Mul.handleDivide(new Int(1), degree)); // FIXME(johnsullivan): If oneOverDegree ends up being a pow object,
4629
- // this "root" hint is lost between here and when tex() is called.
4189
+ var exp = Mul.fold(Mul.handleDivide(new Int(1), degree));
4630
4190
 
4191
+ // FIXME(johnsullivan): If oneOverDegree ends up being a pow object,
4192
+ // this "root" hint is lost between here and when tex() is called.
4631
4193
  return new Pow(radicand, exp.addHint("root"));
4632
4194
  }
4633
4195
  });
4634
- /* logarithm */
4635
-
4636
4196
 
4197
+ /* logarithm */
4637
4198
  function Log(base, power) {
4638
4199
  this.base = base;
4639
4200
  this.power = power;
4640
4201
  }
4641
4202
  Log.prototype = new Expr();
4642
-
4643
4203
  _.extend(Log.prototype, {
4644
4204
  func: Log,
4645
4205
  args: function args() {
@@ -4653,7 +4213,6 @@ _.extend(Log.prototype, {
4653
4213
  },
4654
4214
  print: function print() {
4655
4215
  var power = "(" + this.power.print() + ")";
4656
-
4657
4216
  if (this.isNatural()) {
4658
4217
  return "ln" + power;
4659
4218
  } else {
@@ -4662,7 +4221,6 @@ _.extend(Log.prototype, {
4662
4221
  },
4663
4222
  tex: function tex() {
4664
4223
  var power = "(" + this.power.tex() + ")";
4665
-
4666
4224
  if (this.isNatural()) {
4667
4225
  return "\\ln" + power;
4668
4226
  } else {
@@ -4671,7 +4229,6 @@ _.extend(Log.prototype, {
4671
4229
  },
4672
4230
  collect: function collect(options) {
4673
4231
  var log = this.recurse("collect", options);
4674
-
4675
4232
  if (log.power instanceof Num && log.power.eval() === 1) {
4676
4233
  // e.g. ln(1) -> 0
4677
4234
  return Num.Zero;
@@ -4687,21 +4244,22 @@ _.extend(Log.prototype, {
4687
4244
  },
4688
4245
  expand: function expand() {
4689
4246
  var log = this.recurse("expand");
4690
-
4691
4247
  if (log.power instanceof Mul) {
4692
4248
  // might want behind super-simplify() flag
4693
4249
  // e.g. ln(xy) -> ln(x) + ln(y)
4250
+
4694
4251
  var terms = _.map(log.power.terms, function (term) {
4695
4252
  // need to expand again in case new log powers are Pows
4696
4253
  return new Log(log.base, term).expand();
4697
4254
  });
4698
-
4699
4255
  return new Add(terms);
4700
4256
  } else if (log.power instanceof Pow) {
4701
4257
  // e.g. ln(x^y) -> y*ln(x)
4258
+
4702
4259
  return new Mul(log.power.exp, new Log(log.base, log.power.base).expand()).flatten();
4703
4260
  } else if (!log.isNatural()) {
4704
4261
  // e.g. log_b(x) -> ln(x)/ln(b)
4262
+
4705
4263
  return Mul.handleDivide(new Log(Const.e, log.power), new Log(Const.e, log.base));
4706
4264
  } else {
4707
4265
  return log;
@@ -4712,7 +4270,6 @@ _.extend(Log.prototype, {
4712
4270
  }),
4713
4271
  isPositive: function isPositive() {
4714
4272
  var log = this.collect();
4715
-
4716
4273
  if (log.base instanceof Num && log.power instanceof Num) {
4717
4274
  return this.eval() > 0;
4718
4275
  } else {
@@ -4726,7 +4283,6 @@ _.extend(Log.prototype, {
4726
4283
  return this.base.equals(Const.e);
4727
4284
  }
4728
4285
  });
4729
-
4730
4286
  _.extend(Log, {
4731
4287
  natural: function natural() {
4732
4288
  return Const.e;
@@ -4736,23 +4292,19 @@ _.extend(Log, {
4736
4292
  },
4737
4293
  create: function create(base, power) {
4738
4294
  var log = new Log(base, power);
4739
-
4740
4295
  if (!power.hints.parens) {
4741
4296
  log = log.addHint("open");
4742
4297
  }
4743
-
4744
4298
  return log;
4745
4299
  }
4746
4300
  });
4747
- /* trigonometric functions */
4748
-
4749
4301
 
4302
+ /* trigonometric functions */
4750
4303
  function Trig(type, arg) {
4751
4304
  this.type = type;
4752
4305
  this.arg = arg;
4753
4306
  }
4754
4307
  Trig.prototype = new Expr();
4755
-
4756
4308
  _.extend(Trig.prototype, {
4757
4309
  func: Trig,
4758
4310
  args: function args() {
@@ -4938,7 +4490,6 @@ _.extend(Trig.prototype, {
4938
4490
  },
4939
4491
  codegen: function codegen() {
4940
4492
  var func = this.functions[this.type].codegen;
4941
-
4942
4493
  if (typeof func === "function") {
4943
4494
  return func(this.arg.codegen());
4944
4495
  } else if (typeof func === "string") {
@@ -4960,7 +4511,6 @@ _.extend(Trig.prototype, {
4960
4511
  }),
4961
4512
  isPositive: function isPositive() {
4962
4513
  var trig = this.collect();
4963
-
4964
4514
  if (trig.arg instanceof Num) {
4965
4515
  return this.eval() > 0;
4966
4516
  } else {
@@ -4982,7 +4532,6 @@ _.extend(Trig.prototype, {
4982
4532
  },
4983
4533
  expand: function expand() {
4984
4534
  var trig = this.recurse("expand");
4985
-
4986
4535
  if (!trig.isInverse()) {
4987
4536
  // e.g. tan(x) -> sin(x)/cos(x)
4988
4537
  var expand = trig.functions[trig.type].expand;
@@ -4993,16 +4542,13 @@ _.extend(Trig.prototype, {
4993
4542
  },
4994
4543
  collect: function collect(options) {
4995
4544
  var trig = this.recurse("collect", options);
4996
-
4997
4545
  if (!trig.isInverse() && trig.arg.isNegative()) {
4998
4546
  var arg;
4999
-
5000
4547
  if (trig.arg instanceof Num) {
5001
4548
  arg = trig.arg.abs();
5002
4549
  } else {
5003
4550
  arg = Mul.handleDivide(trig.arg, Num.Neg).collect(options);
5004
4551
  }
5005
-
5006
4552
  if (trig.isEven()) {
5007
4553
  // e.g. cos(-x) -> cos(x)
5008
4554
  return new Trig(trig.type, arg);
@@ -5015,28 +4561,22 @@ _.extend(Trig.prototype, {
5015
4561
  }
5016
4562
  }
5017
4563
  });
5018
-
5019
4564
  _.extend(Trig, {
5020
4565
  create: function create(pair, arg) {
5021
4566
  var type = pair[0];
5022
4567
  var exp = pair[1];
5023
-
5024
4568
  if (exp && exp.equals(Num.Neg)) {
5025
4569
  // e.g. sin^-1(x) -> arcsin(x)
5026
4570
  type = "arc" + type;
5027
4571
  exp = undefined;
5028
4572
  }
5029
-
5030
4573
  var trig = new Trig(type, arg);
5031
-
5032
4574
  if (!arg.hints.parens) {
5033
4575
  trig = trig.addHint("open");
5034
4576
  }
5035
-
5036
4577
  if (exp) {
5037
4578
  trig.exp = exp;
5038
4579
  }
5039
-
5040
4580
  return trig;
5041
4581
  },
5042
4582
  sin: function sin(arg) {
@@ -5052,12 +4592,10 @@ _.extend(Trig, {
5052
4592
  return new Trig("cosh", arg);
5053
4593
  }
5054
4594
  });
5055
-
5056
4595
  function Abs(arg) {
5057
4596
  this.arg = arg;
5058
4597
  }
5059
4598
  Abs.prototype = new Expr();
5060
-
5061
4599
  _.extend(Abs.prototype, {
5062
4600
  func: Abs,
5063
4601
  args: function args() {
@@ -5077,7 +4615,6 @@ _.extend(Abs.prototype, {
5077
4615
  },
5078
4616
  collect: function collect(options) {
5079
4617
  var abs = this.recurse("collect", options);
5080
-
5081
4618
  if (abs.arg.isPositive()) {
5082
4619
  // e.g. |2^x| -> 2^x
5083
4620
  return abs.arg;
@@ -5095,13 +4632,10 @@ _.extend(Abs.prototype, {
5095
4632
  return "other";
5096
4633
  }
5097
4634
  });
5098
-
5099
4635
  var positives = terms.positive.concat(_.invoke(terms.number, "abs"));
5100
-
5101
4636
  if (terms.other.length) {
5102
4637
  positives.push(new Abs(new Mul(terms.other).flatten()));
5103
4638
  }
5104
-
5105
4639
  return new Mul(positives).flatten();
5106
4640
  } else {
5107
4641
  return abs;
@@ -5110,13 +4644,11 @@ _.extend(Abs.prototype, {
5110
4644
  // this should definitely be behind a super-simplify flag
5111
4645
  expand: function expand() {
5112
4646
  var abs = this.recurse("expand");
5113
-
5114
4647
  if (abs.arg instanceof Mul) {
5115
4648
  // e.g. |xyz| -> |x|*|y|*|z|
5116
4649
  var terms = _.map(abs.arg.terms, function (term) {
5117
4650
  return new Abs(term);
5118
4651
  });
5119
-
5120
4652
  return new Mul(terms);
5121
4653
  } else {
5122
4654
  return abs;
@@ -5126,16 +4658,14 @@ _.extend(Abs.prototype, {
5126
4658
  return true;
5127
4659
  }
5128
4660
  });
5129
- /* equation */
5130
-
5131
4661
 
4662
+ /* equation */
5132
4663
  function Eq(left, type, right) {
5133
4664
  this.left = left;
5134
4665
  this.type = type;
5135
4666
  this.right = right;
5136
4667
  }
5137
4668
  Eq.prototype = new Expr();
5138
-
5139
4669
  _.extend(Eq.prototype, {
5140
4670
  func: Eq,
5141
4671
  args: function args() {
@@ -5160,7 +4690,6 @@ _.extend(Eq.prototype, {
5160
4690
  },
5161
4691
  normalize: function normalize() {
5162
4692
  var eq = this.recurse("normalize");
5163
-
5164
4693
  if (_.contains([">", ">="], eq.type)) {
5165
4694
  // inequalities should have the smaller side on the left
5166
4695
  return new Eq(eq.right, eq.type.replace(">", "<"), eq.left);
@@ -5175,40 +4704,39 @@ _.extend(Eq.prototype, {
5175
4704
  asExpr: function asExpr(unfactored) {
5176
4705
  var isZero = function isZero(expr) {
5177
4706
  return expr instanceof Num && expr.isSimple() && expr.eval() === 0;
5178
- }; // first convert to a sequence of additive terms
5179
-
4707
+ };
5180
4708
 
4709
+ // first convert to a sequence of additive terms
5181
4710
  var terms = [];
5182
-
5183
4711
  if (this.left instanceof Add) {
5184
4712
  terms = _.clone(this.left.terms);
5185
4713
  } else if (!isZero(this.left)) {
5186
4714
  terms = [this.left];
5187
4715
  }
5188
-
5189
4716
  if (this.right instanceof Add) {
5190
4717
  terms = terms.concat(this.right.negate().terms);
5191
4718
  } else if (!isZero(this.right)) {
5192
4719
  terms.push(this.right.negate());
5193
4720
  }
4721
+ var isInequality = !this.isEquality();
5194
4722
 
5195
- var isInequality = !this.isEquality(); // Collect over each term individually to transform simple expressions
4723
+ // Collect over each term individually to transform simple expressions
5196
4724
  // into numbers that might have denominators, taking into account
5197
4725
  // float precision. We have to be very careful to not introduce any
5198
4726
  // irrational floats before asExpr() returns, because by definition
5199
4727
  // they do not have exact denominators...
5200
-
5201
4728
  terms = _.invoke(terms, "collect", {
5202
4729
  preciseFloats: true
5203
- }); // ...and we multiply through by every denominator.
4730
+ });
5204
4731
 
4732
+ // ...and we multiply through by every denominator.
5205
4733
  for (var i = 0; i < terms.length; i++) {
5206
- var denominator = terms[i].getDenominator(); // Can't multiply inequalities by non 100% positive factors
4734
+ var denominator = terms[i].getDenominator();
5207
4735
 
4736
+ // Can't multiply inequalities by non 100% positive factors
5208
4737
  if (isInequality && !denominator.isPositive()) {
5209
4738
  denominator = denominator.asPositiveFactor();
5210
4739
  }
5211
-
5212
4740
  if (!denominator.equals(Num.One)) {
5213
4741
  terms = _.map(terms, function (term) {
5214
4742
  return Mul.createOrAppend(term, denominator).simplify({
@@ -5218,7 +4746,6 @@ _.extend(Eq.prototype, {
5218
4746
  });
5219
4747
  }
5220
4748
  }
5221
-
5222
4749
  var add = new Add(terms).flatten();
5223
4750
  return unfactored ? add : this.divideThrough(add);
5224
4751
  },
@@ -5234,58 +4761,48 @@ _.extend(Eq.prototype, {
5234
4761
  var factored = simplified.factor({
5235
4762
  keepNegative: isInequality
5236
4763
  });
5237
-
5238
4764
  if (!(factored instanceof Mul)) {
5239
4765
  return expr;
5240
4766
  }
5241
-
5242
4767
  var terms = factored.terms;
5243
-
5244
4768
  var isAdd = function isAdd(term) {
5245
4769
  return term instanceof Add;
5246
4770
  };
5247
-
5248
4771
  var hasVar = function hasVar(term) {
5249
4772
  return !!term.getVars().length;
5250
4773
  };
5251
-
5252
4774
  var isOne = function isOne(term) {
5253
4775
  return term.equals(Num.One);
5254
4776
  };
5255
-
5256
4777
  var grouped = _.groupBy(terms, isAdd);
5257
-
5258
4778
  var adds = grouped[true] || [];
5259
4779
  var others = grouped[false] || [];
5260
-
5261
4780
  if (adds.length && this.isEquality()) {
5262
4781
  // keep only Adds
5263
4782
  // e.g. 2xy(z+1)(=0) -> z+1(=0)
5264
4783
  return new Mul(adds).flatten();
5265
4784
  }
5266
-
5267
4785
  var denominator = others;
5268
-
5269
4786
  if (!adds.length) {
5270
4787
  // if no Adds, keep all variable terms to preserve meaning
5271
4788
  // e.g. 42xyz(=0) -> xyz(=0)
5272
4789
  denominator = _.reject(denominator, hasVar);
5273
4790
  }
5274
-
5275
4791
  if (isInequality) {
5276
4792
  // can't divide inequalities by non 100% positive factors
5277
4793
  // e.g. 42x^2y(z+1)(=0) -> y(z+1)(=0)
5278
4794
  denominator = _.invoke(denominator, "asPositiveFactor");
5279
- } // don't need to divide by one
5280
-
4795
+ }
5281
4796
 
4797
+ // don't need to divide by one
5282
4798
  denominator = _.reject(denominator, isOne);
5283
4799
  denominator = _.map(denominator, function (term) {
5284
4800
  return new Pow(term, Num.Div);
5285
4801
  });
5286
- var dividedResult = new Mul(terms.concat(denominator)).collect(); // If the end result is the same as the original factoring,
5287
- // rollback the factoring and discard all intermediate steps.
4802
+ var dividedResult = new Mul(terms.concat(denominator)).collect();
5288
4803
 
4804
+ // If the end result is the same as the original factoring,
4805
+ // rollback the factoring and discard all intermediate steps.
5289
4806
  if (dividedResult.equals(factored)) {
5290
4807
  return simplified;
5291
4808
  } else {
@@ -5300,23 +4817,16 @@ _.extend(Eq.prototype, {
5300
4817
  if (!(other instanceof Eq)) {
5301
4818
  return false;
5302
4819
  }
5303
-
5304
4820
  var eq1 = this.normalize();
5305
4821
  var eq2 = other.normalize();
5306
-
5307
4822
  if (eq1.type !== eq2.type) {
5308
4823
  return false;
5309
- } // need to collect to properly factor out common factors
5310
- // e.g x+2x=6 -> 3x=6 -> 3x-6(=0) -> x-2(=0)
5311
-
5312
-
5313
- var expr1 = eq1.divideThrough(eq1.asExpr(
5314
- /* unfactored */
5315
- true).collect());
5316
- var expr2 = eq2.divideThrough(eq2.asExpr(
5317
- /* unfactored */
5318
- true).collect());
4824
+ }
5319
4825
 
4826
+ // need to collect to properly factor out common factors
4827
+ // e.g x+2x=6 -> 3x=6 -> 3x-6(=0) -> x-2(=0)
4828
+ var expr1 = eq1.divideThrough(eq1.asExpr( /* unfactored */true).collect());
4829
+ var expr2 = eq2.divideThrough(eq2.asExpr( /* unfactored */true).collect());
5320
4830
  if (eq1.isEquality()) {
5321
4831
  // equals and not-equals can be subtracted either way
5322
4832
  return expr1.compare(expr2) || expr1.compare(Mul.handleNegative(expr2));
@@ -5329,7 +4839,6 @@ _.extend(Eq.prototype, {
5329
4839
  var eq1 = this.normalize();
5330
4840
  var eq2 = other.normalize();
5331
4841
  var same = eq1.left.sameForm(eq2.left) && eq1.right.sameForm(eq2.right);
5332
-
5333
4842
  if (eq1.isEquality()) {
5334
4843
  // equals and not-equals can be commutative with respect to the sign
5335
4844
  return same || eq1.left.sameForm(eq2.right) && eq1.right.sameForm(eq2.left);
@@ -5340,29 +4849,22 @@ _.extend(Eq.prototype, {
5340
4849
  // we don't want to override collect because it would turn y=x into y-x(=0)
5341
4850
  // instead, we ask if the equation was in that form, would it be simplified?
5342
4851
  isSimplified: function isSimplified() {
5343
- var expr = this.asExpr(
5344
- /* unfactored */
5345
- true);
4852
+ var expr = this.asExpr( /* unfactored */true);
5346
4853
  var simplified = this.divideThrough(expr).simplify();
5347
4854
  return expr.equals(simplified) && this.left.isSimplified() && this.right.isSimplified();
5348
4855
  }
5349
4856
  });
5350
-
5351
4857
  _.extend(Eq.prototype, {
5352
4858
  // Assumptions: Expression is of the form a+bx, and we solve for x
5353
4859
  solveLinearEquationForVariable: function solveLinearEquationForVariable(variable) {
5354
4860
  var expr = this.asExpr();
5355
-
5356
4861
  if (!expr.is(Add) || expr.terms.length !== 2) {
5357
4862
  throw new Error("Can only handle linear equations of the form " + "a + bx (= 0)");
5358
4863
  }
5359
-
5360
4864
  var hasVar = function hasVar(term) {
5361
4865
  return term.has(Var) && _.contains(term.getVars(), variable.symbol);
5362
4866
  };
5363
-
5364
4867
  var a, b;
5365
-
5366
4868
  if (hasVar(expr.terms[0])) {
5367
4869
  a = Mul.handleNegative(expr.terms[1]);
5368
4870
  b = Mul.handleDivide(expr.terms[0], variable);
@@ -5370,17 +4872,13 @@ _.extend(Eq.prototype, {
5370
4872
  a = Mul.handleNegative(expr.terms[0]);
5371
4873
  b = Mul.handleDivide(expr.terms[1], variable);
5372
4874
  }
5373
-
5374
4875
  return Mul.handleDivide(a, b).simplify();
5375
4876
  }
5376
4877
  });
5377
- /* abstract symbol node */
5378
-
5379
4878
 
4879
+ /* abstract symbol node */
5380
4880
  function Symbol() {}
5381
-
5382
4881
  Symbol.prototype = new Expr();
5383
-
5384
4882
  _.extend(Symbol.prototype, {
5385
4883
  needsExplicitMul: function needsExplicitMul() {
5386
4884
  return false;
@@ -5393,15 +4891,13 @@ _.extend(Symbol.prototype, {
5393
4891
  }
5394
4892
  }
5395
4893
  });
5396
- /* function variable */
5397
-
5398
4894
 
4895
+ /* function variable */
5399
4896
  function Func(symbol, arg) {
5400
4897
  this.symbol = symbol;
5401
4898
  this.arg = arg;
5402
4899
  }
5403
4900
  Func.prototype = new Symbol();
5404
-
5405
4901
  _.extend(Func.prototype, {
5406
4902
  func: Func,
5407
4903
  args: function args() {
@@ -5416,22 +4912,18 @@ _.extend(Func.prototype, {
5416
4912
  eval: function _eval(vars, options) {
5417
4913
  var arg = this.arg;
5418
4914
  var func = vars[this.symbol];
5419
-
5420
4915
  var newVars = _.extend(_.clone(vars), {
5421
4916
  x: arg.eval(vars, options)
5422
4917
  });
5423
-
5424
4918
  var parsedFunc = parse(func, options);
5425
-
5426
4919
  if (parsedFunc.parsed) {
5427
4920
  return parsedFunc.expr.eval(newVars, options);
5428
- } // If parsedFunc isn't actually parsed, return its error
5429
-
5430
-
4921
+ }
4922
+ // If parsedFunc isn't actually parsed, return its error
5431
4923
  return parsedFunc;
5432
4924
  },
5433
4925
  codegen: function codegen() {
5434
- return 'vars["' + this.symbol + '"](' + this.arg.codegen() + ')';
4926
+ return 'vars["' + this.symbol + '"](' + this.arg.codegen() + ")";
5435
4927
  },
5436
4928
  getUnits: function getUnits() {
5437
4929
  return this.arg.getUnits();
@@ -5447,15 +4939,13 @@ _.extend(Func.prototype, {
5447
4939
  return this.arg.getConsts();
5448
4940
  }
5449
4941
  });
5450
- /* variable */
5451
-
5452
4942
 
4943
+ /* variable */
5453
4944
  function Var(symbol, subscript) {
5454
4945
  this.symbol = symbol;
5455
4946
  this.subscript = subscript;
5456
4947
  }
5457
4948
  Var.prototype = new Symbol();
5458
-
5459
4949
  _.extend(Var.prototype, {
5460
4950
  func: Var,
5461
4951
  args: function args() {
@@ -5469,18 +4959,15 @@ _.extend(Var.prototype, {
5469
4959
  },
5470
4960
  print: function print() {
5471
4961
  var sub = "";
5472
-
5473
4962
  if (this.subscript) {
5474
4963
  sub = "_(" + this.subscript.print() + ")";
5475
4964
  }
5476
-
5477
4965
  return this.symbol + sub;
5478
4966
  },
5479
4967
  // Provide a way to easily evalate expressions with the common case,
5480
4968
  // subscripts that consist of a single number or symbol e.g. x_a or x_42
5481
4969
  prettyPrint: function prettyPrint() {
5482
4970
  var sub = this.subscript;
5483
-
5484
4971
  if (sub && (sub instanceof Num || sub instanceof Symbol)) {
5485
4972
  return this.symbol + "_" + sub.print();
5486
4973
  } else {
@@ -5489,11 +4976,9 @@ _.extend(Var.prototype, {
5489
4976
  },
5490
4977
  tex: function tex() {
5491
4978
  var sub = "";
5492
-
5493
4979
  if (this.subscript) {
5494
4980
  sub = "_{" + this.subscript.tex() + "}";
5495
4981
  }
5496
-
5497
4982
  var prefix = this.symbol.length > 1 ? "\\" : "";
5498
4983
  return prefix + this.symbol + sub;
5499
4984
  },
@@ -5513,14 +4998,12 @@ _.extend(Var.prototype, {
5513
4998
  return false;
5514
4999
  }
5515
5000
  });
5516
- /* constant */
5517
-
5518
5001
 
5002
+ /* constant */
5519
5003
  function Const(symbol) {
5520
5004
  this.symbol = symbol;
5521
5005
  }
5522
5006
  Const.prototype = new Symbol();
5523
-
5524
5007
  _.extend(Const.prototype, {
5525
5008
  func: Const,
5526
5009
  args: function args() {
@@ -5567,15 +5050,12 @@ _.extend(Const.prototype, {
5567
5050
  return [this.print()];
5568
5051
  }
5569
5052
  });
5570
-
5571
5053
  Const.e = new Const("e");
5572
5054
  Const.pi = new Const("pi");
5573
- /* abstract number node */
5574
5055
 
5056
+ /* abstract number node */
5575
5057
  function Num() {}
5576
-
5577
5058
  Num.prototype = new Expr();
5578
-
5579
5059
  _.extend(Num.prototype, {
5580
5060
  repr: function repr() {
5581
5061
  return this.print();
@@ -5627,10 +5107,11 @@ _.extend(Num.prototype, {
5627
5107
  // Based on http://stackoverflow.com/a/10454560/2571482
5628
5108
  getDecimalPlaces: function getDecimalPlaces() {
5629
5109
  var match = ("" + this.n).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
5630
-
5631
5110
  if (match) {
5632
- return Math.max(0, // Number of digits right of decimal point
5633
- (match[1] ? match[1].length : 0) - ( // Adjust for scientific notation
5111
+ return Math.max(0,
5112
+ // Number of digits right of decimal point
5113
+ (match[1] ? match[1].length : 0) - (
5114
+ // Adjust for scientific notation
5634
5115
  match[2] ? +match[2] : 0));
5635
5116
  } else {
5636
5117
  return 0;
@@ -5638,23 +5119,19 @@ _.extend(Num.prototype, {
5638
5119
  },
5639
5120
  asRational: abstract
5640
5121
  });
5641
- /* rational number (n: numerator, d: denominator) */
5642
-
5643
5122
 
5123
+ /* rational number (n: numerator, d: denominator) */
5644
5124
  function Rational(numerator, denominator) {
5645
5125
  var n = numerator;
5646
5126
  var d = denominator;
5647
-
5648
5127
  if (d < 0) {
5649
5128
  n = -n;
5650
5129
  d = -d;
5651
5130
  }
5652
-
5653
5131
  this.n = n;
5654
5132
  this.d = d;
5655
5133
  }
5656
5134
  Rational.prototype = new Num();
5657
-
5658
5135
  _.extend(Rational.prototype, {
5659
5136
  func: Rational,
5660
5137
  args: function args() {
@@ -5688,7 +5165,6 @@ _.extend(Rational.prototype, {
5688
5165
  var gcd = Num.findGCD(this.n, this.d);
5689
5166
  var n = this.n / gcd;
5690
5167
  var d = this.d / gcd;
5691
-
5692
5168
  if (d === 1) {
5693
5169
  return new Int(n);
5694
5170
  } else {
@@ -5708,8 +5184,8 @@ _.extend(Rational.prototype, {
5708
5184
  // For more background, see
5709
5185
  // http://math.stackexchange.com/questions/151081/gcd-of-rationals
5710
5186
  var numerator = Num.findGCD(this.n * factor.d, factor.n * this.d);
5711
- var denominator = this.d * factor.d; // Create the rational, then call .collect() to simplify it
5712
-
5187
+ var denominator = this.d * factor.d;
5188
+ // Create the rational, then call .collect() to simplify it
5713
5189
  return new Rational(numerator, denominator).collect();
5714
5190
  } else if (factor instanceof Int) {
5715
5191
  return new Rational(Num.findGCD(this.n, factor.n), this.d);
@@ -5724,7 +5200,6 @@ _.extend(Rational.prototype, {
5724
5200
  var abs = exp.abs().eval();
5725
5201
  var n = Math.pow(this.n, abs);
5726
5202
  var d = Math.pow(this.d, abs);
5727
-
5728
5203
  if (positive) {
5729
5204
  return new Rational(n, d).collect();
5730
5205
  } else {
@@ -5744,14 +5219,12 @@ _.extend(Rational.prototype, {
5744
5219
  return this;
5745
5220
  }
5746
5221
  });
5747
- /* integer (n: numerator/number) */
5748
-
5749
5222
 
5223
+ /* integer (n: numerator/number) */
5750
5224
  function Int(number) {
5751
5225
  this.n = number;
5752
5226
  }
5753
5227
  Int.prototype = new Rational(0, 1);
5754
-
5755
5228
  _.extend(Int.prototype, {
5756
5229
  func: Int,
5757
5230
  args: function args() {
@@ -5780,20 +5253,17 @@ _.extend(Int.prototype, {
5780
5253
  }
5781
5254
  }
5782
5255
  });
5783
-
5784
5256
  _.extend(Int, {
5785
5257
  create: function create(n) {
5786
5258
  return new Int(n).addHint("entered");
5787
5259
  }
5788
5260
  });
5789
- /* float (n: number) */
5790
-
5791
5261
 
5262
+ /* float (n: number) */
5792
5263
  function Float(number) {
5793
5264
  this.n = number;
5794
5265
  }
5795
5266
  Float.prototype = new Num();
5796
-
5797
5267
  _.extend(Float.prototype, {
5798
5268
  func: Float,
5799
5269
  args: function args() {
@@ -5853,7 +5323,6 @@ _.extend(Float.prototype, {
5853
5323
  // only to be used on non-repeating decimals (e.g. user-provided)
5854
5324
  asRational: function asRational() {
5855
5325
  var parts = this.n.toString().split(".");
5856
-
5857
5326
  if (parts.length === 1) {
5858
5327
  return new Rational(this.n, 1);
5859
5328
  } else {
@@ -5869,7 +5338,6 @@ _.extend(Float.prototype, {
5869
5338
  return true;
5870
5339
  }
5871
5340
  });
5872
-
5873
5341
  _.extend(Float, {
5874
5342
  create: function create(n) {
5875
5343
  return new Float(n).addHint("entered");
@@ -5879,9 +5347,9 @@ _.extend(Float, {
5879
5347
  toDecimalPlaces: function toDecimalPlaces(n, places) {
5880
5348
  return new Float(+n.toFixed(Math.min(places, 20))).collect();
5881
5349
  }
5882
- }); // static methods and fields that are best defined on Num
5883
-
5350
+ });
5884
5351
 
5352
+ // static methods and fields that are best defined on Num
5885
5353
  _.extend(Num, {
5886
5354
  negativeOne: function negativeOne(hint) {
5887
5355
  if (hint === "subtract") {
@@ -5896,20 +5364,19 @@ _.extend(Num, {
5896
5364
  findGCD: function findGCD(a, b) {
5897
5365
  var mod;
5898
5366
  a = Math.abs(a);
5899
- b = Math.abs(b); // Euclid's method doesn't handle non-integers very well. For now
5367
+ b = Math.abs(b);
5368
+
5369
+ // Euclid's method doesn't handle non-integers very well. For now
5900
5370
  // we just say we can't pull out a common factor. It might be
5901
5371
  // reasonable to do better than this in the future.
5902
-
5903
5372
  if (a !== Math.floor(a) || b !== Math.floor(b)) {
5904
5373
  return 1;
5905
5374
  }
5906
-
5907
5375
  while (b) {
5908
5376
  mod = a % b;
5909
5377
  a = b;
5910
5378
  b = mod;
5911
5379
  }
5912
-
5913
5380
  return a;
5914
5381
  },
5915
5382
  min: function min() {
@@ -5923,25 +5390,24 @@ _.extend(Num, {
5923
5390
  });
5924
5391
  }
5925
5392
  });
5926
-
5927
5393
  Num.Neg = new Int(-1).addHint("negate");
5928
5394
  Num.Sub = new Int(-1).addHint("subtract");
5929
5395
  Num.Div = new Int(-1).addHint("divide");
5930
5396
  Num.Sqrt = new Rational(1, 2).addHint("root");
5931
5397
  Num.Zero = new Int(0);
5932
5398
  Num.One = new Int(1);
5933
- Num.Ten = new Int(10); // set identities here
5399
+ Num.Ten = new Int(10);
5934
5400
 
5401
+ // set identities here
5935
5402
  Add.prototype.identity = Num.Zero;
5936
5403
  Mul.prototype.identity = Num.One;
5937
-
5938
5404
  var parseError = function parseError(str, hash) {
5939
5405
  // return int location of parsing error
5940
5406
  throw new Error(hash.loc.first_column);
5941
- }; // expose concrete nodes to parser scope
5942
- // see http://zaach.github.io/jison/docs/#sharing-scope
5943
-
5407
+ };
5944
5408
 
5409
+ // expose concrete nodes to parser scope
5410
+ // see http://zaach.github.io/jison/docs/#sharing-scope
5945
5411
  parser.yy = {
5946
5412
  Add: Add,
5947
5413
  Mul: Mul,
@@ -5974,16 +5440,15 @@ var parse = function parse(input, options) {
5974
5440
  parser.yy.functions = _.without(options.functions, "i");
5975
5441
  } else {
5976
5442
  parser.yy.functions = [];
5977
- } // If ',' is the decimal dividor in your country, replace any ','s
5443
+ }
5444
+
5445
+ // If ',' is the decimal dividor in your country, replace any ','s
5978
5446
  // with '.'s.
5979
5447
  // This isn't perfect, since the output will all still have '.'s.
5980
5448
  // TODO(jack): Fix the output to have ','s in this case
5981
-
5982
-
5983
5449
  if (options && options.decimal_separator) {
5984
5450
  input = input.split(options.decimal_separator).join(".");
5985
5451
  }
5986
-
5987
5452
  var expr = parser.parse(input).completeParse();
5988
5453
  return {
5989
5454
  parsed: true,
@@ -5996,34 +5461,35 @@ var parse = function parse(input, options) {
5996
5461
  };
5997
5462
  }
5998
5463
  };
5999
- /* unit */
6000
5464
 
5465
+ /* unit */
6001
5466
  function Unit(symbol) {
6002
5467
  this.symbol = symbol;
6003
5468
  }
6004
- Unit.prototype = new Symbol(); // If possible, replace unit prefixes with a multiplication.
5469
+ Unit.prototype = new Symbol();
5470
+
5471
+ // If possible, replace unit prefixes with a multiplication.
6005
5472
  //
6006
5473
  // "g" -> Unit("g")
6007
5474
  // "kg" -> 1000 * Unit("g")
6008
-
6009
5475
  var unprefixify = function unprefixify(symbol) {
6010
5476
  if (_(baseUnits).has(symbol) || _(derivedUnits).has(symbol)) {
6011
5477
  return new Unit(symbol);
6012
- } // check for prefix
6013
-
5478
+ }
6014
5479
 
5480
+ // check for prefix
6015
5481
  var prefix = _(_(siPrefixes).keys()).find(function (testPrefix) {
6016
5482
  return new RegExp("^" + testPrefix).test(symbol);
6017
5483
  });
6018
-
6019
5484
  if (prefix) {
6020
- var base = symbol.replace(new RegExp("^" + prefix), ""); // It's okay to be here if either:
5485
+ var base = symbol.replace(new RegExp("^" + prefix), "");
5486
+
5487
+ // It's okay to be here if either:
6021
5488
  // * `base` is a base unit (the seven units listed in baseUnits)
6022
5489
  // * `base` is a derived unit which allows prefixes
6023
5490
  //
6024
5491
  // Otherwise, we're trying to parse a unit label which is not
6025
5492
  // allowed (mwk, mBTU, etc).
6026
-
6027
5493
  if (_(baseUnits).has(base) || derivedUnits[base] && derivedUnits[base].prefixes === hasPrefixes) {
6028
5494
  return new Mul(siPrefixes[prefix], new Unit(base));
6029
5495
  } else {
@@ -6033,10 +5499,11 @@ var unprefixify = function unprefixify(symbol) {
6033
5499
  return new Unit(symbol);
6034
5500
  }
6035
5501
  };
6036
-
6037
5502
  var unitParse = function unitParse(input) {
6038
5503
  try {
6039
- var parseResult = unitParser.parse(input); // parseResult looks like:
5504
+ var parseResult = unitParser.parse(input);
5505
+
5506
+ // parseResult looks like:
6040
5507
  // {
6041
5508
  // magnitude: "5",
6042
5509
  // unit: {
@@ -6052,17 +5519,13 @@ var unitParse = function unitParse(input) {
6052
5519
  // denom is optionally null
6053
5520
 
6054
5521
  var unitArray = [];
6055
-
6056
5522
  _(parseResult.unit.num).each(function (unitSpec) {
6057
5523
  unitArray.push(new Pow(unprefixify(unitSpec.name), new Int(unitSpec.pow)));
6058
5524
  });
6059
-
6060
5525
  _(parseResult.unit.denom).each(function (unitSpec) {
6061
5526
  unitArray.push(new Pow(unprefixify(unitSpec.name), new Int(-1 * unitSpec.pow)));
6062
5527
  });
6063
-
6064
5528
  var unit = new Mul(unitArray).flatten();
6065
-
6066
5529
  if (parseResult.type === "unitMagnitude") {
6067
5530
  // in the first case we have a magnitude coefficient as well as the
6068
5531
  // unit itself.
@@ -6090,7 +5553,6 @@ var unitParse = function unitParse(input) {
6090
5553
  };
6091
5554
  }
6092
5555
  };
6093
-
6094
5556
  _.extend(Unit.prototype, {
6095
5557
  func: Unit,
6096
5558
  args: function args() {
@@ -6135,7 +5597,6 @@ _.extend(Unit.prototype, {
6135
5597
  }
6136
5598
  }
6137
5599
  });
6138
-
6139
5600
  var baseUnits = {
6140
5601
  m: new Unit("m"),
6141
5602
  // Note: kg is the SI base unit but we use g for consistency
@@ -6165,24 +5626,21 @@ var siPrefixes = {
6165
5626
  E: new Pow(new Int(10), new Int(18)),
6166
5627
  // http://en.wikipedia.org/wiki/Metric_prefix#.22Hella.22_prefix_proposal
6167
5628
  hella: new Pow(new Int(10), new Int(27))
6168
- }; // Use these two values to mark a unit as either SI-prefixable or not.
5629
+ };
6169
5630
 
5631
+ // Use these two values to mark a unit as either SI-prefixable or not.
6170
5632
  var hasPrefixes = {};
6171
5633
  var hasntPrefixes = {};
6172
-
6173
5634
  var makeAlias = function makeAlias(str, prefixes) {
6174
5635
  var splits = str.split("|");
6175
5636
  var coefficientStr = splits[0].trim();
6176
5637
  var unitsStr = splits[1].trim();
6177
5638
  var coefficient = Num.One;
6178
-
6179
5639
  if (coefficientStr !== "") {
6180
5640
  coefficient = parse(coefficientStr).expr;
6181
5641
  }
6182
-
6183
5642
  var numdenomStr = unitsStr.split("/");
6184
5643
  var numdenom = [coefficient];
6185
-
6186
5644
  if (numdenomStr[0]) {
6187
5645
  numdenomStr[0].split(" ").filter(function (x) {
6188
5646
  return x !== "";
@@ -6190,7 +5648,6 @@ var makeAlias = function makeAlias(str, prefixes) {
6190
5648
  numdenom.push(new Unit(x));
6191
5649
  });
6192
5650
  }
6193
-
6194
5651
  if (numdenomStr[1]) {
6195
5652
  numdenomStr[1].split(" ").filter(function (x) {
6196
5653
  return x !== "";
@@ -6198,12 +5655,13 @@ var makeAlias = function makeAlias(str, prefixes) {
6198
5655
  numdenom.push(new Pow(new Unit(x), Num.Div));
6199
5656
  });
6200
5657
  }
6201
-
6202
5658
  return {
6203
5659
  conversion: new Mul(numdenom),
6204
5660
  prefixes: prefixes
6205
5661
  };
6206
- }; // This is a mapping of derived units (or different names for a unit) to their
5662
+ };
5663
+
5664
+ // This is a mapping of derived units (or different names for a unit) to their
6207
5665
  // definitions. For example, an inch is defined as 0.0254 m.
6208
5666
  //
6209
5667
  // Definitions don't need to be in terms of base units. For example, tsp is
@@ -6225,148 +5683,147 @@ var makeAlias = function makeAlias(str, prefixes) {
6225
5683
  //
6226
5684
  // Where possible, these units are taken from "The International System of
6227
5685
  // Units (SI)" 8th edition (2006).
6228
-
6229
-
6230
5686
  var derivedUnits = {
6231
5687
  // mass
6232
5688
  // The atomic mass unit / dalton.
6233
5689
  Da: makeAlias("1.6605388628 x 10^-24 | g", hasPrefixes),
6234
5690
  u: makeAlias("| Da", hasntPrefixes),
6235
5691
  // length
6236
- "meter": makeAlias("| m", hasntPrefixes),
6237
- "meters": makeAlias("| m", hasntPrefixes),
6238
- "in": makeAlias("254 / 10000 | m", hasntPrefixes),
6239
- "ft": makeAlias("3048 / 10000 | m", hasntPrefixes),
6240
- "yd": makeAlias("9144 / 10000 | m", hasntPrefixes),
6241
- "mi": makeAlias("1609344 / 1000 | m", hasntPrefixes),
6242
- "ly": makeAlias("9.4607 x 10^15 | m", hasntPrefixes),
6243
- "nmi": makeAlias("1852 | m", hasntPrefixes),
6244
- "Å": makeAlias("10^-10 | m", hasntPrefixes),
6245
- "pc": makeAlias("3.0857 x 10^16 | m", hasntPrefixes),
5692
+ meter: makeAlias("| m", hasntPrefixes),
5693
+ meters: makeAlias("| m", hasntPrefixes),
5694
+ in: makeAlias("254 / 10000 | m", hasntPrefixes),
5695
+ ft: makeAlias("3048 / 10000 | m", hasntPrefixes),
5696
+ yd: makeAlias("9144 / 10000 | m", hasntPrefixes),
5697
+ mi: makeAlias("1609344 / 1000 | m", hasntPrefixes),
5698
+ ly: makeAlias("9.4607 x 10^15 | m", hasntPrefixes),
5699
+ nmi: makeAlias("1852 | m", hasntPrefixes),
5700
+ Å: makeAlias("10^-10 | m", hasntPrefixes),
5701
+ pc: makeAlias("3.0857 x 10^16 | m", hasntPrefixes),
6246
5702
  // time
6247
- "min": makeAlias("60 | s", hasntPrefixes),
6248
- "hr": makeAlias("3600 | s", hasntPrefixes),
6249
- "sec": makeAlias("| s", hasntPrefixes),
5703
+ min: makeAlias("60 | s", hasntPrefixes),
5704
+ hr: makeAlias("3600 | s", hasntPrefixes),
5705
+ sec: makeAlias("| s", hasntPrefixes),
6250
5706
  // TODO(joel) make day work
6251
- "day": makeAlias("86400 | s", hasntPrefixes),
6252
- "wk": makeAlias("604800 | s", hasntPrefixes),
6253
- "fortnight": makeAlias("14 | day", hasntPrefixes),
6254
- "shake": makeAlias("10^-8 | s", hasntPrefixes),
6255
- "olympiad": makeAlias("126200000 | s", hasntPrefixes),
5707
+ day: makeAlias("86400 | s", hasntPrefixes),
5708
+ wk: makeAlias("604800 | s", hasntPrefixes),
5709
+ fortnight: makeAlias("14 | day", hasntPrefixes),
5710
+ shake: makeAlias("10^-8 | s", hasntPrefixes),
5711
+ olympiad: makeAlias("126200000 | s", hasntPrefixes),
6256
5712
  // temperature
6257
5713
  "°C": makeAlias("1 | K", hasntPrefixes),
6258
5714
  "°F": makeAlias("5/9 | K", hasntPrefixes),
6259
5715
  "°R": makeAlias("5/9 | K", hasntPrefixes),
6260
5716
  // electric charge
6261
- "e": makeAlias("1.6021765314 x 10^-19 | C", hasntPrefixes),
5717
+ e: makeAlias("1.6021765314 x 10^-19 | C", hasntPrefixes),
6262
5718
  // speed
6263
- "c": makeAlias("299792458 | m / s", hasntPrefixes),
6264
- "kn": makeAlias("514/1000 | m / s", hasntPrefixes),
6265
- "kt": makeAlias("| kn", hasntPrefixes),
6266
- "knot": makeAlias("| kn", hasntPrefixes),
5719
+ c: makeAlias("299792458 | m / s", hasntPrefixes),
5720
+ kn: makeAlias("514/1000 | m / s", hasntPrefixes),
5721
+ kt: makeAlias("| kn", hasntPrefixes),
5722
+ knot: makeAlias("| kn", hasntPrefixes),
6267
5723
  // energy
6268
- "J": makeAlias("| N m", hasPrefixes),
6269
- "BTU": makeAlias("1060 | J", hasntPrefixes),
6270
- "cal": makeAlias("4184 / 1000 | J", hasPrefixes),
6271
- "eV": makeAlias("1.602176514 x 10^-19 | J", hasPrefixes),
6272
- "erg": makeAlias("10^−7 | J", hasPrefixes),
5724
+ J: makeAlias("| N m", hasPrefixes),
5725
+ BTU: makeAlias("1060 | J", hasntPrefixes),
5726
+ cal: makeAlias("4184 / 1000 | J", hasPrefixes),
5727
+ eV: makeAlias("1.602176514 x 10^-19 | J", hasPrefixes),
5728
+ erg: makeAlias("10^−7 | J", hasPrefixes),
6273
5729
  // power
6274
- "W": makeAlias("| J / s", hasPrefixes),
5730
+ W: makeAlias("| J / s", hasPrefixes),
6275
5731
  "H-e": makeAlias("80 | W", hasntPrefixes),
6276
5732
  // force
6277
- "N": makeAlias("1000 | g m / s s", hasPrefixes),
5733
+ N: makeAlias("1000 | g m / s s", hasPrefixes),
6278
5734
  // "lb": makeAlias("4448 / 1000 | N", hasntPrefixes),
6279
5735
  // 4.4482216152605
6280
- "lb": makeAlias("4448221615 / 1000000000 | N", hasntPrefixes),
6281
- "dyn": makeAlias("10^-5 | N", hasntPrefixes),
5736
+ lb: makeAlias("4448221615 / 1000000000 | N", hasntPrefixes),
5737
+ dyn: makeAlias("10^-5 | N", hasntPrefixes),
6282
5738
  // pressure
6283
- "Pa": makeAlias("1 | N / m m m", hasPrefixes),
6284
- "bar": makeAlias("10^5 | Pa", hasPrefixes),
5739
+ Pa: makeAlias("1 | N / m m m", hasPrefixes),
5740
+ bar: makeAlias("10^5 | Pa", hasPrefixes),
6285
5741
  "㏔": makeAlias("1/1000 | bar", hasntPrefixes),
6286
5742
  "㍴": makeAlias("| bar", hasntPrefixes),
6287
- "atm": makeAlias("101325 | Pa", hasntPrefixes),
6288
- "Torr": makeAlias("1/760 | atm", hasntPrefixes),
6289
- "mmHg": makeAlias("| Torr", hasntPrefixes),
5743
+ atm: makeAlias("101325 | Pa", hasntPrefixes),
5744
+ Torr: makeAlias("1/760 | atm", hasntPrefixes),
5745
+ mmHg: makeAlias("| Torr", hasntPrefixes),
6290
5746
  // area
6291
- "ha": makeAlias("10^4 | m m", hasntPrefixes),
6292
- "b": makeAlias("10^−28 | m m", hasPrefixes),
6293
- "barn": makeAlias("| b", hasPrefixes),
6294
- "acre": makeAlias("4046.87 | m m", hasntPrefixes),
6295
- "skilodge": makeAlias("10^-31 | m m", hasntPrefixes),
6296
- "outhouse": makeAlias("10^-34 | m m", hasntPrefixes),
6297
- "shed": makeAlias("10^-52 | m m", hasntPrefixes),
5747
+ ha: makeAlias("10^4 | m m", hasntPrefixes),
5748
+ b: makeAlias("10^−28 | m m", hasPrefixes),
5749
+ barn: makeAlias("| b", hasPrefixes),
5750
+ acre: makeAlias("4046.87 | m m", hasntPrefixes),
5751
+ skilodge: makeAlias("10^-31 | m m", hasntPrefixes),
5752
+ outhouse: makeAlias("10^-34 | m m", hasntPrefixes),
5753
+ shed: makeAlias("10^-52 | m m", hasntPrefixes),
6298
5754
  // volume
6299
- "L": makeAlias("1/1000 | m m m", hasPrefixes),
6300
- "gal": makeAlias("3785/1000 | L", hasPrefixes),
6301
- "cup": makeAlias("1/16 | gal", hasntPrefixes),
6302
- "qt": makeAlias("1/4 | gal", hasntPrefixes),
6303
- "quart": makeAlias("| qt", hasntPrefixes),
6304
- "p": makeAlias("1/8 | gal", hasntPrefixes),
6305
- "pt": makeAlias("| p", hasntPrefixes),
6306
- "pint": makeAlias("| p", hasntPrefixes),
5755
+ L: makeAlias("1/1000 | m m m", hasPrefixes),
5756
+ gal: makeAlias("3785/1000 | L", hasPrefixes),
5757
+ cup: makeAlias("1/16 | gal", hasntPrefixes),
5758
+ qt: makeAlias("1/4 | gal", hasntPrefixes),
5759
+ quart: makeAlias("| qt", hasntPrefixes),
5760
+ p: makeAlias("1/8 | gal", hasntPrefixes),
5761
+ pt: makeAlias("| p", hasntPrefixes),
5762
+ pint: makeAlias("| p", hasntPrefixes),
6307
5763
  "fl oz": makeAlias("1/8 | cup", hasntPrefixes),
6308
5764
  "fl. oz.": makeAlias("1/8 | cup", hasntPrefixes),
6309
- "tbsp": makeAlias("1/16 | cup", hasntPrefixes),
6310
- "tsp": makeAlias("1/3 | tbsp", hasntPrefixes),
5765
+ tbsp: makeAlias("1/16 | cup", hasntPrefixes),
5766
+ tsp: makeAlias("1/3 | tbsp", hasntPrefixes),
6311
5767
  // rotational
6312
5768
  // "rad":
6313
- "rev": makeAlias("2 pi | rad", hasntPrefixes),
6314
- "deg": makeAlias("180 pi | rad", hasntPrefixes),
5769
+ rev: makeAlias("2 pi | rad", hasntPrefixes),
5770
+ deg: makeAlias("180 pi | rad", hasntPrefixes),
6315
5771
  "°": makeAlias("| deg", hasntPrefixes),
6316
- "arcminute": makeAlias("1/60 | deg", hasntPrefixes),
6317
- "arcsec": makeAlias("1/3600 | deg", hasntPrefixes),
5772
+ arcminute: makeAlias("1/60 | deg", hasntPrefixes),
5773
+ arcsec: makeAlias("1/3600 | deg", hasntPrefixes),
6318
5774
  // dimensionless
6319
5775
  // "B": makeAlias("10 | dB", hasntPrefixes), // XXX danger - logarithmic
6320
5776
  // "dB"
6321
5777
  // "nP"
6322
- "Hu": makeAlias("1000 | dB", hasPrefixes),
6323
- "dozen": makeAlias("12 |", hasntPrefixes),
5778
+ Hu: makeAlias("1000 | dB", hasPrefixes),
5779
+ dozen: makeAlias("12 |", hasntPrefixes),
6324
5780
  // XXX
6325
- "mol": makeAlias("6.0221412927 x 10^23 |", hasPrefixes),
5781
+ mol: makeAlias("6.0221412927 x 10^23 |", hasPrefixes),
6326
5782
  "%": makeAlias("1/100 |", hasntPrefixes),
6327
- "percent": makeAlias("| %", hasntPrefixes),
6328
- "ppm": makeAlias("1/1000000 |", hasntPrefixes),
5783
+ percent: makeAlias("| %", hasntPrefixes),
5784
+ ppm: makeAlias("1/1000000 |", hasntPrefixes),
6329
5785
  // electric / magnetic
6330
- "V": makeAlias("1000 | g m m / s s C", hasPrefixes),
6331
- "C": makeAlias("| A s", hasPrefixes),
6332
- "ampere": makeAlias("| A", hasntPrefixes),
6333
- "Ω": makeAlias("| V / A", hasPrefixes),
6334
- "ohm": makeAlias("| Ω", hasntPrefixes),
6335
- "F": makeAlias("| C / V", hasPrefixes),
6336
- "H": makeAlias("| ohm s", hasPrefixes),
6337
- "T": makeAlias("1000 | g / C s", hasPrefixes),
6338
- "Wb": makeAlias("1000 | g m m / C s", hasPrefixes),
5786
+ V: makeAlias("1000 | g m m / s s C", hasPrefixes),
5787
+ C: makeAlias("| A s", hasPrefixes),
5788
+ ampere: makeAlias("| A", hasntPrefixes),
5789
+ Ω: makeAlias("| V / A", hasPrefixes),
5790
+ ohm: makeAlias("| Ω", hasntPrefixes),
5791
+ F: makeAlias("| C / V", hasPrefixes),
5792
+ H: makeAlias("| ohm s", hasPrefixes),
5793
+ T: makeAlias("1000 | g / C s", hasPrefixes),
5794
+ Wb: makeAlias("1000 | g m m / C s", hasPrefixes),
6339
5795
  // photometry
6340
5796
  // TODO not sure this is right
6341
- "lm": makeAlias("pi x 10^4 | cd / m m", hasntPrefixes),
6342
- "lx": makeAlias("| lm / m m", hasntPrefixes),
6343
- "nit": makeAlias("| cd / m m", hasntPrefixes),
6344
- "sb": makeAlias("10^4 | cd / m m", hasntPrefixes),
6345
- "stilb": makeAlias("1 | sb", hasntPrefixes),
6346
- "apostilb": makeAlias("1 / pi x 10^(-4) | sb", hasntPrefixes),
6347
- "blondel": makeAlias("| apostilb", hasntPrefixes),
6348
- "asb": makeAlias("| apostilb", hasntPrefixes),
6349
- "la": makeAlias("| lm", hasntPrefixes),
6350
- "Lb": makeAlias("| lm", hasntPrefixes),
6351
- "sk": makeAlias("10^-7 | lm", hasntPrefixes),
6352
- "skot": makeAlias("| sk", hasntPrefixes),
6353
- "bril": makeAlias("10^-11 | lm", hasntPrefixes),
5797
+ lm: makeAlias("pi x 10^4 | cd / m m", hasntPrefixes),
5798
+ lx: makeAlias("| lm / m m", hasntPrefixes),
5799
+ nit: makeAlias("| cd / m m", hasntPrefixes),
5800
+ sb: makeAlias("10^4 | cd / m m", hasntPrefixes),
5801
+ stilb: makeAlias("1 | sb", hasntPrefixes),
5802
+ apostilb: makeAlias("1 / pi x 10^(-4) | sb", hasntPrefixes),
5803
+ blondel: makeAlias("| apostilb", hasntPrefixes),
5804
+ asb: makeAlias("| apostilb", hasntPrefixes),
5805
+ la: makeAlias("| lm", hasntPrefixes),
5806
+ Lb: makeAlias("| lm", hasntPrefixes),
5807
+ sk: makeAlias("10^-7 | lm", hasntPrefixes),
5808
+ skot: makeAlias("| sk", hasntPrefixes),
5809
+ bril: makeAlias("10^-11 | lm", hasntPrefixes),
6354
5810
  // other
6355
- "Hz": makeAlias("| / s", hasPrefixes)
5811
+ Hz: makeAlias("| / s", hasPrefixes)
6356
5812
  };
6357
5813
  var Zero = Num.Zero;
6358
5814
  var One = Num.One;
6359
5815
 
6360
5816
  /* eslint-disable */
6361
- // TODO(alex): be able to pass a random() function to compare()
6362
5817
 
5818
+ // Assumes that both expressions have already been parsed
5819
+ // TODO(alex): be able to pass a random() function to compare()
6363
5820
  var compare = function compare(expr1, expr2, options) {
6364
5821
  var defaults = {
6365
5822
  form: false,
6366
5823
  // Check that the two expressions have the same form
6367
5824
  simplify: false // Check that the second expression is simplified
6368
-
6369
5825
  };
5826
+
6370
5827
  /* Options that could be added in the future:
6371
5828
  * - Allow ratios: e.g. 3/1 and 3 should both be accepted for something
6372
5829
  * like slope
@@ -6378,53 +5835,50 @@ var compare = function compare(expr1, expr2, options) {
6378
5835
  options = _.extend(defaults, options);
6379
5836
  } else {
6380
5837
  options = defaults;
6381
- } // TODO(CP-1614): Figure out how to make these messages translatable
6382
- // Variable check
5838
+ }
6383
5839
 
5840
+ // TODO(CP-1614): Figure out how to make these messages translatable
6384
5841
 
5842
+ // Variable check
6385
5843
  var vars = expr1.sameVars(expr2);
6386
-
6387
5844
  if (!vars.equal) {
6388
5845
  var message;
6389
-
6390
5846
  if (vars.equalIgnoringCase) {
6391
5847
  message = "Check your variables; one or more are using " + "the wrong case (upper or lower).";
6392
5848
  } else {
6393
5849
  message = "Check your variables; you may have used the wrong " + "letter for one or more of them.";
6394
5850
  }
6395
-
6396
5851
  return {
6397
5852
  equal: false,
6398
5853
  wrongVariableCase: vars.equalIgnoringCase,
6399
5854
  wrongVariableNames: !vars.equalIgnoringCase,
6400
5855
  message: message
6401
5856
  };
6402
- } // Semantic check
6403
-
5857
+ }
6404
5858
 
5859
+ // Semantic check
6405
5860
  if (!expr1.compare(expr2)) {
6406
5861
  return {
6407
5862
  equal: false,
6408
5863
  message: null
6409
5864
  };
6410
- } // Syntactic check
6411
-
5865
+ }
6412
5866
 
5867
+ // Syntactic check
6413
5868
  if (options.form && !expr1.sameForm(expr2)) {
6414
5869
  return {
6415
5870
  equal: false,
6416
5871
  message: "Your answer is not in the correct form."
6417
5872
  };
6418
- } // Syntactic check
6419
-
5873
+ }
6420
5874
 
5875
+ // Syntactic check
6421
5876
  if (options.simplify && !expr1.isSimplified()) {
6422
5877
  return {
6423
5878
  equal: false,
6424
5879
  message: "Your answer is not fully expanded and simplified."
6425
5880
  };
6426
5881
  }
6427
-
6428
5882
  return {
6429
5883
  equal: true,
6430
5884
  message: null