@khanacademy/kas 0.5.1 → 1.0.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/index.js CHANGED
@@ -1,98 +1,15 @@
1
- 'use strict';
1
+ import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
2
+ import _extends from '@babel/runtime/helpers/extends';
3
+ import _ from 'underscore';
2
4
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var perseusUtils = require('@khanacademy/perseus-utils');
6
- var _ = require('underscore');
7
-
8
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
-
10
- var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
11
-
12
- // This file is processed by a Rollup plugin (replace) to inject the production
13
5
  const libName = "@khanacademy/kas";
14
- const libVersion = "0.5.1";
15
- perseusUtils.addLibraryVersionToPerseusDebug(libName, libVersion);
16
-
17
- // this is a @generated file
18
-
19
- /* parser generated by jison 0.4.15 */
20
- /*
21
- Returns a Parser object of the following structure:
22
-
23
- Parser: {
24
- yy: {}
25
- }
26
-
27
- Parser.prototype: {
28
- yy: {},
29
- trace: function(),
30
- symbols_: {associative list: name ==> number},
31
- terminals_: {associative list: number ==> name},
32
- productions_: [...],
33
- performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
34
- table: [...],
35
- defaultActions: {...},
36
- parseError: function(str, hash),
37
- parse: function(input),
38
-
39
- lexer: {
40
- EOF: 1,
41
- parseError: function(str, hash),
42
- setInput: function(input),
43
- input: function(),
44
- unput: function(str),
45
- more: function(),
46
- less: function(n),
47
- pastInput: function(),
48
- upcomingInput: function(),
49
- showPosition: function(),
50
- test_match: function(regex_match_array, rule_index),
51
- next: function(),
52
- lex: function(),
53
- begin: function(condition),
54
- popState: function(),
55
- _currentRules: function(),
56
- topState: function(),
57
- pushState: function(condition),
58
-
59
- options: {
60
- ranges: boolean (optional: true ==> token location info will include a .range[] member)
61
- flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
62
- backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
63
- },
64
-
65
- performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
66
- rules: [...],
67
- conditions: {associative list: name ==> set},
68
- }
69
- }
70
-
71
-
72
- token location info (@$, _$, etc.): {
73
- first_line: n,
74
- last_line: n,
75
- first_column: n,
76
- last_column: n,
77
- range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
78
- }
79
-
6
+ const libVersion = "1.0.0";
7
+ addLibraryVersionToPerseusDebug(libName, libVersion);
80
8
 
81
- the parseError function receives a 'hash' object with these members for lexer and parser errors: {
82
- text: (matched text)
83
- token: (the produced terminal token, if any)
84
- line: (yylineno)
85
- }
86
- while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
87
- loc: (yylloc)
88
- expected: (string describing the set of expected tokens)
89
- recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
90
- }
91
- */
92
9
  var parser$1 = function () {
93
- var o = function (k, v, o, l) {
94
- for (o = o || {}, l = k.length; l--; o[k[l]] = v);
95
- return o;
10
+ var o = function o(k, v, _o, l) {
11
+ for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v);
12
+ return _o;
96
13
  },
97
14
  $V0 = [1, 11],
98
15
  $V1 = [1, 9],
@@ -138,9 +55,7 @@ var parser$1 = function () {
138
55
  20: "NEG"
139
56
  },
140
57
  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]],
141
- performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
142
- /* this == yyval */
143
-
58
+ performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
144
59
  var $0 = $$.length - 1;
145
60
  switch (yystate) {
146
61
  case 1:
@@ -325,7 +240,6 @@ var parser$1 = function () {
325
240
  } else {
326
241
  this.parseError = Object.getPrototypeOf(this).parseError;
327
242
  }
328
- //_token_stack:
329
243
  function lex() {
330
244
  var token;
331
245
  token = lexer.lex() || EOF;
@@ -425,7 +339,6 @@ var parser$1 = function () {
425
339
  return true;
426
340
  }
427
341
  };
428
- /* generated by jison-lex 0.3.4 */
429
342
  var lexer = function () {
430
343
  var lexer = {
431
344
  EOF: 1,
@@ -436,7 +349,6 @@ var parser$1 = function () {
436
349
  throw new Error(str);
437
350
  }
438
351
  },
439
- // resets the lexer, sets new input
440
352
  setInput: function (input, yy) {
441
353
  this.yy = yy || this.yy || {};
442
354
  this._input = input;
@@ -456,7 +368,6 @@ var parser$1 = function () {
456
368
  this.offset = 0;
457
369
  return this;
458
370
  },
459
- // consumes and returns one char from the input
460
371
  input: function () {
461
372
  var ch = this._input[0];
462
373
  this.yytext += ch;
@@ -477,13 +388,11 @@ var parser$1 = function () {
477
388
  this._input = this._input.slice(1);
478
389
  return ch;
479
390
  },
480
- // unshifts one char (or a string) into the input
481
391
  unput: function (ch) {
482
392
  var len = ch.length;
483
393
  var lines = ch.split(/(?:\r\n?|\n)/g);
484
394
  this._input = ch + this._input;
485
395
  this.yytext = this.yytext.substr(0, this.yytext.length - len);
486
- //this.yyleng -= len;
487
396
  this.offset -= len;
488
397
  var oldLines = this.match.split(/(?:\r\n?|\n)/g);
489
398
  this.match = this.match.substr(0, this.match.length - 1);
@@ -504,12 +413,10 @@ var parser$1 = function () {
504
413
  this.yyleng = this.yytext.length;
505
414
  return this;
506
415
  },
507
- // When called from action, caches matched text and appends it on next action
508
416
  more: function () {
509
417
  this._more = true;
510
418
  return this;
511
419
  },
512
- // When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
513
420
  reject: function () {
514
421
  if (this.options.backtrack_lexer) {
515
422
  this._backtrack = true;
@@ -522,16 +429,13 @@ var parser$1 = function () {
522
429
  }
523
430
  return this;
524
431
  },
525
- // retain first n characters of the match
526
432
  less: function (n) {
527
433
  this.unput(this.match.slice(n));
528
434
  },
529
- // displays already matched input, i.e. for error messages
530
435
  pastInput: function () {
531
436
  var past = this.matched.substr(0, this.matched.length - this.match.length);
532
437
  return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
533
438
  },
534
- // displays upcoming input, i.e. for error messages
535
439
  upcomingInput: function () {
536
440
  var next = this.match;
537
441
  if (next.length < 20) {
@@ -539,17 +443,14 @@ var parser$1 = function () {
539
443
  }
540
444
  return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
541
445
  },
542
- // displays the character position where the lexing error occurred, i.e. for error messages
543
446
  showPosition: function () {
544
447
  var pre = this.pastInput();
545
448
  var c = new Array(pre.length + 1).join("-");
546
449
  return pre + this.upcomingInput() + "\n" + c + "^";
547
450
  },
548
- // test the lexed token: return FALSE when not a match, otherwise return token
549
451
  test_match: function (match, indexed_rule) {
550
452
  var token, lines, backup;
551
453
  if (this.options.backtrack_lexer) {
552
- // save context
553
454
  backup = {
554
455
  yylineno: this.yylineno,
555
456
  yylloc: {
@@ -602,15 +503,13 @@ var parser$1 = function () {
602
503
  if (token) {
603
504
  return token;
604
505
  } else if (this._backtrack) {
605
- // recover context
606
506
  for (var k in backup) {
607
507
  this[k] = backup[k];
608
508
  }
609
- return false; // rule action called reject() implying the next rule should be tested instead.
509
+ return false;
610
510
  }
611
511
  return false;
612
512
  },
613
- // return next match in input
614
513
  next: function () {
615
514
  if (this.done) {
616
515
  return this.EOF;
@@ -635,9 +534,8 @@ var parser$1 = function () {
635
534
  return token;
636
535
  } else if (this._backtrack) {
637
536
  match = false;
638
- continue; // rule action called reject() implying a rule MISmatch.
537
+ continue;
639
538
  } else {
640
- // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
641
539
  return false;
642
540
  }
643
541
  } else if (!this.options.flex) {
@@ -650,7 +548,6 @@ var parser$1 = function () {
650
548
  if (token !== false) {
651
549
  return token;
652
550
  }
653
- // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
654
551
  return false;
655
552
  }
656
553
  if (this._input === "") {
@@ -663,7 +560,6 @@ var parser$1 = function () {
663
560
  });
664
561
  }
665
562
  },
666
- // return next match that has a token
667
563
  lex: function lex() {
668
564
  var r = this.next();
669
565
  if (r) {
@@ -672,11 +568,9 @@ var parser$1 = function () {
672
568
  return this.lex();
673
569
  }
674
570
  },
675
- // activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
676
571
  begin: function begin(condition) {
677
572
  this.conditionStack.push(condition);
678
573
  },
679
- // pop the previously active lexer condition state off the condition stack
680
574
  popState: function popState() {
681
575
  var n = this.conditionStack.length - 1;
682
576
  if (n > 0) {
@@ -685,7 +579,6 @@ var parser$1 = function () {
685
579
  return this.conditionStack[0];
686
580
  }
687
581
  },
688
- // produce the lexer rule set which is active for the currently active lexer condition state
689
582
  _currentRules: function _currentRules() {
690
583
  if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
691
584
  return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
@@ -693,7 +586,6 @@ var parser$1 = function () {
693
586
  return this.conditions["INITIAL"].rules;
694
587
  }
695
588
  },
696
- // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
697
589
  topState: function topState(n) {
698
590
  n = this.conditionStack.length - 1 - Math.abs(n || 0);
699
591
  if (n >= 0) {
@@ -702,11 +594,9 @@ var parser$1 = function () {
702
594
  return "INITIAL";
703
595
  }
704
596
  },
705
- // alias for begin(condition)
706
597
  pushState: function pushState(condition) {
707
598
  this.begin(condition);
708
599
  },
709
- // return the number of states currently on the stack
710
600
  stateStackSize: function stateStackSize() {
711
601
  return this.conditionStack.length;
712
602
  },
@@ -738,7 +628,6 @@ var parser$1 = function () {
738
628
  case 11:
739
629
  return 17;
740
630
  case 12:
741
- /* skip whitespace */
742
631
  break;
743
632
  case 13:
744
633
  return 6;
@@ -764,85 +653,10 @@ var parser$1 = function () {
764
653
  }();
765
654
  const unitParser = parser$1;
766
655
 
767
- // This is a @generated file
768
-
769
- /* parser generated by jison 0.4.15 */
770
- /*
771
- Returns a Parser object of the following structure:
772
-
773
- Parser: {
774
- yy: {}
775
- }
776
-
777
- Parser.prototype: {
778
- yy: {},
779
- trace: function(),
780
- symbols_: {associative list: name ==> number},
781
- terminals_: {associative list: number ==> name},
782
- productions_: [...],
783
- performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
784
- table: [...],
785
- defaultActions: {...},
786
- parseError: function(str, hash),
787
- parse: function(input),
788
-
789
- lexer: {
790
- EOF: 1,
791
- parseError: function(str, hash),
792
- setInput: function(input),
793
- input: function(),
794
- unput: function(str),
795
- more: function(),
796
- less: function(n),
797
- pastInput: function(),
798
- upcomingInput: function(),
799
- showPosition: function(),
800
- test_match: function(regex_match_array, rule_index),
801
- next: function(),
802
- lex: function(),
803
- begin: function(condition),
804
- popState: function(),
805
- _currentRules: function(),
806
- topState: function(),
807
- pushState: function(condition),
808
-
809
- options: {
810
- ranges: boolean (optional: true ==> token location info will include a .range[] member)
811
- flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
812
- backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
813
- },
814
-
815
- performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
816
- rules: [...],
817
- conditions: {associative list: name ==> set},
818
- }
819
- }
820
-
821
-
822
- token location info (@$, _$, etc.): {
823
- first_line: n,
824
- last_line: n,
825
- first_column: n,
826
- last_column: n,
827
- range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
828
- }
829
-
830
-
831
- the parseError function receives a 'hash' object with these members for lexer and parser errors: {
832
- text: (matched text)
833
- token: (the produced terminal token, if any)
834
- line: (yylineno)
835
- }
836
- while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
837
- loc: (yylloc)
838
- expected: (string describing the set of expected tokens)
839
- recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
840
- }
841
- */
842
656
  var parser = function () {
843
- var o = function (k, v, o, l) {
844
- for (o = o || {}, l = k.length; l--; o[k[l]] = v);
845
- return o;
657
+ var o = function o(k, v, _o, l) {
658
+ for (_o = _o || {}, l = k.length; l--; _o[k[l]] = v);
659
+ return _o;
846
660
  },
847
661
  $V0 = [1, 7],
848
662
  $V1 = [1, 17],
@@ -954,9 +768,7 @@ var parser = function () {
954
768
  46: "FRAC"
955
769
  },
956
770
  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]],
957
- performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
958
- /* this == yyval */
959
-
771
+ performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
960
772
  var $0 = $$.length - 1;
961
773
  switch (yystate) {
962
774
  case 1:
@@ -2002,7 +1814,6 @@ var parser = function () {
2002
1814
  } else {
2003
1815
  this.parseError = Object.getPrototypeOf(this).parseError;
2004
1816
  }
2005
- //_token_stack:
2006
1817
  function lex() {
2007
1818
  var token;
2008
1819
  token = lexer.lex() || EOF;
@@ -2102,7 +1913,6 @@ var parser = function () {
2102
1913
  return true;
2103
1914
  }
2104
1915
  };
2105
- /* generated by jison-lex 0.3.4 */
2106
1916
  var lexer = function () {
2107
1917
  var lexer = {
2108
1918
  EOF: 1,
@@ -2113,7 +1923,6 @@ var parser = function () {
2113
1923
  throw new Error(str);
2114
1924
  }
2115
1925
  },
2116
- // resets the lexer, sets new input
2117
1926
  setInput: function (input, yy) {
2118
1927
  this.yy = yy || this.yy || {};
2119
1928
  this._input = input;
@@ -2133,7 +1942,6 @@ var parser = function () {
2133
1942
  this.offset = 0;
2134
1943
  return this;
2135
1944
  },
2136
- // consumes and returns one char from the input
2137
1945
  input: function () {
2138
1946
  var ch = this._input[0];
2139
1947
  this.yytext += ch;
@@ -2154,13 +1962,11 @@ var parser = function () {
2154
1962
  this._input = this._input.slice(1);
2155
1963
  return ch;
2156
1964
  },
2157
- // unshifts one char (or a string) into the input
2158
1965
  unput: function (ch) {
2159
1966
  var len = ch.length;
2160
1967
  var lines = ch.split(/(?:\r\n?|\n)/g);
2161
1968
  this._input = ch + this._input;
2162
1969
  this.yytext = this.yytext.substr(0, this.yytext.length - len);
2163
- //this.yyleng -= len;
2164
1970
  this.offset -= len;
2165
1971
  var oldLines = this.match.split(/(?:\r\n?|\n)/g);
2166
1972
  this.match = this.match.substr(0, this.match.length - 1);
@@ -2181,12 +1987,10 @@ var parser = function () {
2181
1987
  this.yyleng = this.yytext.length;
2182
1988
  return this;
2183
1989
  },
2184
- // When called from action, caches matched text and appends it on next action
2185
1990
  more: function () {
2186
1991
  this._more = true;
2187
1992
  return this;
2188
1993
  },
2189
- // When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
2190
1994
  reject: function () {
2191
1995
  if (this.options.backtrack_lexer) {
2192
1996
  this._backtrack = true;
@@ -2199,16 +2003,13 @@ var parser = function () {
2199
2003
  }
2200
2004
  return this;
2201
2005
  },
2202
- // retain first n characters of the match
2203
2006
  less: function (n) {
2204
2007
  this.unput(this.match.slice(n));
2205
2008
  },
2206
- // displays already matched input, i.e. for error messages
2207
2009
  pastInput: function () {
2208
2010
  var past = this.matched.substr(0, this.matched.length - this.match.length);
2209
2011
  return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
2210
2012
  },
2211
- // displays upcoming input, i.e. for error messages
2212
2013
  upcomingInput: function () {
2213
2014
  var next = this.match;
2214
2015
  if (next.length < 20) {
@@ -2216,17 +2017,14 @@ var parser = function () {
2216
2017
  }
2217
2018
  return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
2218
2019
  },
2219
- // displays the character position where the lexing error occurred, i.e. for error messages
2220
2020
  showPosition: function () {
2221
2021
  var pre = this.pastInput();
2222
2022
  var c = new Array(pre.length + 1).join("-");
2223
2023
  return pre + this.upcomingInput() + "\n" + c + "^";
2224
2024
  },
2225
- // test the lexed token: return FALSE when not a match, otherwise return token
2226
2025
  test_match: function (match, indexed_rule) {
2227
2026
  var token, lines, backup;
2228
2027
  if (this.options.backtrack_lexer) {
2229
- // save context
2230
2028
  backup = {
2231
2029
  yylineno: this.yylineno,
2232
2030
  yylloc: {
@@ -2279,15 +2077,13 @@ var parser = function () {
2279
2077
  if (token) {
2280
2078
  return token;
2281
2079
  } else if (this._backtrack) {
2282
- // recover context
2283
2080
  for (var k in backup) {
2284
2081
  this[k] = backup[k];
2285
2082
  }
2286
- return false; // rule action called reject() implying the next rule should be tested instead.
2083
+ return false;
2287
2084
  }
2288
2085
  return false;
2289
2086
  },
2290
- // return next match in input
2291
2087
  next: function () {
2292
2088
  if (this.done) {
2293
2089
  return this.EOF;
@@ -2312,9 +2108,8 @@ var parser = function () {
2312
2108
  return token;
2313
2109
  } else if (this._backtrack) {
2314
2110
  match = false;
2315
- continue; // rule action called reject() implying a rule MISmatch.
2111
+ continue;
2316
2112
  } else {
2317
- // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
2318
2113
  return false;
2319
2114
  }
2320
2115
  } else if (!this.options.flex) {
@@ -2327,7 +2122,6 @@ var parser = function () {
2327
2122
  if (token !== false) {
2328
2123
  return token;
2329
2124
  }
2330
- // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
2331
2125
  return false;
2332
2126
  }
2333
2127
  if (this._input === "") {
@@ -2340,7 +2134,6 @@ var parser = function () {
2340
2134
  });
2341
2135
  }
2342
2136
  },
2343
- // return next match that has a token
2344
2137
  lex: function lex() {
2345
2138
  var r = this.next();
2346
2139
  if (r) {
@@ -2349,11 +2142,9 @@ var parser = function () {
2349
2142
  return this.lex();
2350
2143
  }
2351
2144
  },
2352
- // activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
2353
2145
  begin: function begin(condition) {
2354
2146
  this.conditionStack.push(condition);
2355
2147
  },
2356
- // pop the previously active lexer condition state off the condition stack
2357
2148
  popState: function popState() {
2358
2149
  var n = this.conditionStack.length - 1;
2359
2150
  if (n > 0) {
@@ -2362,7 +2153,6 @@ var parser = function () {
2362
2153
  return this.conditionStack[0];
2363
2154
  }
2364
2155
  },
2365
- // produce the lexer rule set which is active for the currently active lexer condition state
2366
2156
  _currentRules: function _currentRules() {
2367
2157
  if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
2368
2158
  return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
@@ -2370,7 +2160,6 @@ var parser = function () {
2370
2160
  return this.conditions["INITIAL"].rules;
2371
2161
  }
2372
2162
  },
2373
- // return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
2374
2163
  topState: function topState(n) {
2375
2164
  n = this.conditionStack.length - 1 - Math.abs(n || 0);
2376
2165
  if (n >= 0) {
@@ -2379,11 +2168,9 @@ var parser = function () {
2379
2168
  return "INITIAL";
2380
2169
  }
2381
2170
  },
2382
- // alias for begin(condition)
2383
2171
  pushState: function pushState(condition) {
2384
2172
  this.begin(condition);
2385
2173
  },
2386
- // return the number of states currently on the stack
2387
2174
  stateStackSize: function stateStackSize() {
2388
2175
  return this.conditionStack.length;
2389
2176
  },
@@ -2393,13 +2180,10 @@ var parser = function () {
2393
2180
  performAction: function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
2394
2181
  switch ($avoiding_name_collisions) {
2395
2182
  case 0:
2396
- /* skip whitespace */
2397
2183
  break;
2398
2184
  case 1:
2399
- /* skip \space */
2400
2185
  break;
2401
2186
  case 2:
2402
- /* skip '\ ' */
2403
2187
  break;
2404
2188
  case 3:
2405
2189
  return "INT";
@@ -2621,62 +2405,20 @@ var parser = function () {
2621
2405
  return new Parser();
2622
2406
  }();
2623
2407
 
2624
- /* eslint-disable prettier/prettier */
2625
-
2626
- /* The node hierarcy is as follows:
2627
-
2628
- (Expr)
2629
- (Seq) 2+ children
2630
- Add
2631
- Mul
2632
- Pow 2 children
2633
- Log 2 children
2634
- Eq 2 children
2635
- Trig 1 child
2636
- Abs 1 child
2637
- (Sym)
2638
- Func 1 child e.g. f(x)
2639
- Var leaf node e.g. x, x_n
2640
- Const leaf node e.g. pi, e, <i>
2641
- Unit leaf node e.g. kg
2642
- (Num) leaf node
2643
- Rational e.g. 2/3
2644
- Int
2645
- Float
2646
-
2647
- (abstract, not meant to be instantiated)
2648
-
2649
- == Key design concepts ==
2650
- Functional: All methods return new nodes - nodes are never mutated.
2651
- Ignore commutativity: Commutative inputs should be parsed equivalently.
2652
- Exploit commutativity: Output should take advantage of ordering.
2653
- */
2654
-
2655
- /* non user-facing functions */
2656
-
2657
- // reliably detect NaN
2658
- const isNaN = function (object) {
2408
+ var _class5, _class12;
2409
+ const isNaN = function isNaN(object) {
2659
2410
  return object !== object;
2660
2411
  };
2661
-
2662
- // return a random float between min (inclusive) and max (exclusive),
2663
- // not that inclusivity means much, probabilistically, on floats
2664
- const randomFloat = function (min, max) {
2412
+ const randomFloat = function randomFloat(min, max) {
2665
2413
  var extent = max - min;
2666
2414
  return Math.random() * extent + min;
2667
2415
  };
2668
-
2669
- /* constants */
2670
2416
  var ITERATIONS = 12;
2671
- var TOLERANCE = 9; // decimal places
2672
-
2673
- // NOTE(kevinb): _.partition exists in a more recent version of underscore.
2674
- // To avoid having to update underscore I've added a hacky version of this
2675
- // method here.
2417
+ var TOLERANCE = 9;
2676
2418
  function partition(list, iteratee) {
2677
2419
  const a = [];
2678
2420
  const b = [];
2679
- ___default["default"].forEach(list, (elem, key, ctx) => {
2421
+ _.forEach(list, (elem, key, ctx) => {
2680
2422
  if (iteratee(elem, key, ctx)) {
2681
2423
  a.push(elem);
2682
2424
  } else {
@@ -2688,7 +2430,7 @@ function partition(list, iteratee) {
2688
2430
  function isExpr(arg) {
2689
2431
  return arg instanceof Expr;
2690
2432
  }
2691
- const isAdd = function (term) {
2433
+ const isAdd = function isAdd(term) {
2692
2434
  return term instanceof Add;
2693
2435
  };
2694
2436
  function isRational(arg) {
@@ -2701,23 +2443,13 @@ function getFactors(expr) {
2701
2443
  return [expr];
2702
2444
  }
2703
2445
  }
2704
- /* abstract base expression node */
2705
2446
  class Expr {
2706
- hints;
2707
2447
  constructor() {
2448
+ this.hints = void 0;
2708
2449
  this.hints = {
2709
2450
  parens: false
2710
2451
  };
2711
2452
  }
2712
-
2713
- // this node's immediate constructor
2714
- // The `new (...args: any[]): any;` part of the type is a
2715
- // "construct" signature. It indicates that `func` is a class.
2716
- // See https://www.typescriptlang.org/docs/handbook/2/functions.html#construct-signatures.
2717
-
2718
- // an array of the arguments to this node's immediate constructor
2719
-
2720
- // make a new node with the given arguments
2721
2453
  construct(args) {
2722
2454
  const func = this.func;
2723
2455
  const instance = new func(...args);
@@ -2726,59 +2458,29 @@ class Expr {
2726
2458
  }
2727
2459
  return instance;
2728
2460
  }
2729
-
2730
- // an abstraction for chainable, bottom-up recursion
2731
- // NOTE(kevinb): This method is highly dynamic. It's possible that it
2732
- // could be made more type-safe using overload signatures.
2733
- recurse(method) {
2734
- for (var _len = arguments.length, passed = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
2735
- passed[_key - 1] = arguments[_key];
2736
- }
2461
+ recurse(method, ...passed) {
2737
2462
  var args = this.args().map(function (arg) {
2738
- return ___default["default"].isString(arg) || ___default["default"].isNumber(arg) ? arg : arg?.[method].apply(arg, passed);
2463
+ return _.isString(arg) || _.isNumber(arg) ? arg : arg == null ? void 0 : arg[method].apply(arg, passed);
2739
2464
  });
2740
2465
  return this.construct(args);
2741
2466
  }
2742
-
2743
- // evaluate numerically with given variable mapping
2744
- // NOTE(kevin): This could made into an abstract method but
2745
- // Eq doesn't implement it. This indicates that we probably
2746
- // need to introduce another class in our hierarchy.
2747
- eval() {
2748
- throw new Error("Abstract method - must override for expr: " +
2749
- // eslint-disable-next-line @babel/no-invalid-this
2750
- this.print());
2467
+ eval(vars = {}, options) {
2468
+ throw new Error("Abstract method - must override for expr: " + this.print());
2751
2469
  }
2752
-
2753
- // NOTE(kevin): This could made into an abstract method but
2754
- // Eq doesn't implement it. This indicates that we probably
2755
- // need to introduce another class in our hierarchy.
2756
2470
  codegen() {
2757
- throw new Error("Abstract method - must override for expr: " +
2758
- // eslint-disable-next-line @babel/no-invalid-this
2759
- this.print());
2471
+ throw new Error("Abstract method - must override for expr: " + this.print());
2760
2472
  }
2761
2473
  compile() {
2762
2474
  var code = this.codegen();
2763
2475
  try {
2764
- // @ts-expect-error: TypeScript doesn't want to unify
2765
- // `Function` with the `compile`'s return type.
2766
2476
  return new Function("vars", "return " + code + ";");
2767
- } catch {
2477
+ } catch (_unused) {
2768
2478
  throw new Error("Function did not compile: " + code);
2769
2479
  }
2770
2480
  }
2771
-
2772
- // returns a string unambiguously representing the expression
2773
- // should be valid as input
2774
- // e.g. this.equals(parse(this.print())) === true
2775
-
2776
- // returns a TeX string representing the expression
2777
-
2778
- // returns a TeX string, modified by the given options
2779
2481
  asTex(options) {
2780
2482
  options = options || {};
2781
- ___default["default"].defaults(options, {
2483
+ _.defaults(options, {
2782
2484
  display: true,
2783
2485
  dynamic: true,
2784
2486
  times: false
@@ -2796,76 +2498,46 @@ class Expr {
2796
2498
  }
2797
2499
  return tex;
2798
2500
  }
2799
-
2800
- // returns the name of this expression's constructor as a string
2801
- // only used for testing and debugging
2802
2501
  name() {
2803
2502
  return this.func.name;
2804
2503
  }
2805
-
2806
- // returns a string representing current node structure
2807
2504
  repr() {
2808
2505
  return this.name() + "(" + this.args().map(function (arg) {
2809
- return ___default["default"].isString(arg) || ___default["default"].isNumber(arg) ? arg : arg?.repr();
2506
+ return _.isString(arg) || _.isNumber(arg) ? arg : arg == null ? void 0 : arg.repr();
2810
2507
  }).join(",") + ")";
2811
2508
  }
2812
-
2813
- // removes all negative signs
2814
2509
  strip() {
2815
2510
  return this.recurse("strip");
2816
2511
  }
2817
-
2818
- // canonically reorders all commutative elements
2819
2512
  normalize() {
2820
2513
  return this.recurse("normalize");
2821
2514
  }
2822
-
2823
- // expands the expression
2824
2515
  expand() {
2825
2516
  return this.recurse("expand");
2826
2517
  }
2827
-
2828
- // naively factors out like terms
2829
2518
  factor(options) {
2830
2519
  return this.recurse("factor", options);
2831
2520
  }
2832
-
2833
- // collect all like terms
2834
2521
  collect(options) {
2835
2522
  return this.recurse("collect", options);
2836
2523
  }
2837
-
2838
- // strict syntactic equality check
2839
2524
  equals(other) {
2840
2525
  return this.normalize().print() === other.normalize().print();
2841
2526
  }
2842
-
2843
- // expand and collect until the expression no longer changes
2844
2527
  simplify(options) {
2845
- options = {
2846
- once: false,
2847
- ...options
2848
- };
2849
-
2850
- // Attempt to factor and collect
2528
+ options = _extends({
2529
+ once: false
2530
+ }, options);
2851
2531
  var step1 = this.factor(options);
2852
2532
  var step2 = step1.collect(options);
2853
-
2854
- // Rollback if collect didn't do anything
2855
2533
  if (step1.equals(step2)) {
2856
2534
  step2 = this.collect(options);
2857
2535
  }
2858
-
2859
- // Attempt to expand and collect
2860
2536
  var step3 = step2.expand();
2861
2537
  var step4 = step3.collect(options);
2862
-
2863
- // Rollback if collect didn't do anything
2864
2538
  if (step3.equals(step4)) {
2865
2539
  step4 = step2.collect(options);
2866
2540
  }
2867
-
2868
- // One round of simplification complete
2869
2541
  var simplified = step4;
2870
2542
  if (options.once || this.equals(simplified)) {
2871
2543
  return simplified;
@@ -2873,52 +2545,35 @@ class Expr {
2873
2545
  return simplified.simplify(options);
2874
2546
  }
2875
2547
  }
2876
-
2877
- // check whether this expression is simplified
2878
2548
  isSimplified() {
2879
2549
  return this.equals(this.simplify());
2880
2550
  }
2881
-
2882
- // return the child nodes of this node
2883
2551
  exprArgs() {
2884
- // @ts-expect-error: Type 'string | number | Expr | undefined' is not assignable to type 'string | Expr'.
2885
2552
  return this.args().filter(isExpr);
2886
2553
  }
2887
-
2888
- // return the variables (function and non) within the expression
2889
2554
  getVars(excludeFunc) {
2890
- return ___default["default"].uniq(___default["default"].flatten(___default["default"].invoke(this.exprArgs(), "getVars", excludeFunc))).sort();
2555
+ return _.uniq(_.flatten(_.invoke(this.exprArgs(), "getVars", excludeFunc))).sort();
2891
2556
  }
2892
2557
  getConsts() {
2893
- return ___default["default"].uniq(___default["default"].flatten(___default["default"].invoke(this.exprArgs(), "getConsts"))).sort();
2558
+ return _.uniq(_.flatten(_.invoke(this.exprArgs(), "getConsts"))).sort();
2894
2559
  }
2895
2560
  getUnits() {
2896
- return ___default["default"].flatten(___default["default"].invoke(this.exprArgs(), "getUnits"));
2561
+ return _.flatten(_.invoke(this.exprArgs(), "getUnits"));
2897
2562
  }
2898
-
2899
- // check whether this expression node is of a particular type
2900
2563
  is(func) {
2901
2564
  return this instanceof func;
2902
2565
  }
2903
-
2904
- // check whether this expression has a particular node type
2905
2566
  has(func) {
2906
2567
  if (this instanceof func) {
2907
2568
  return true;
2908
2569
  }
2909
- return ___default["default"].any(this.exprArgs(), function (arg) {
2570
+ return _.any(this.exprArgs(), function (arg) {
2910
2571
  return arg.has(func);
2911
2572
  });
2912
2573
  }
2913
-
2914
- // raise this expression to a given exponent
2915
- // most useful for eventually implementing i^3 = -i, etc.
2916
2574
  raiseToThe(exp, options) {
2917
2575
  return new Pow(this, exp);
2918
2576
  }
2919
-
2920
- // does this expression have a specific rendering hint?
2921
- // rendering hints are picked up while parsing, but are lost during transformations
2922
2577
  isSubtract() {
2923
2578
  return false;
2924
2579
  }
@@ -2928,24 +2583,17 @@ class Expr {
2928
2583
  isRoot() {
2929
2584
  return false;
2930
2585
  }
2931
-
2932
- // whether this node needs an explicit multiplication sign if following a Num
2933
2586
  needsExplicitMul() {
2934
2587
  return this.exprArgs()[0].needsExplicitMul();
2935
2588
  }
2936
-
2937
- // check that the variables in both expressions are the same
2938
2589
  sameVars(other) {
2939
2590
  var vars1 = this.getVars();
2940
2591
  var vars2 = other.getVars();
2941
-
2942
- // the other Expr can have more variables than this one
2943
- // this lets you multiply equations by other variables
2944
- var same = function (array1, array2) {
2945
- return !___default["default"].difference(array1, array2).length;
2592
+ var same = function same(array1, array2) {
2593
+ return !_.difference(array1, array2).length;
2946
2594
  };
2947
- var lower = function (array) {
2948
- return ___default["default"].uniq(___default["default"].invoke(array, "toLowerCase")).sort();
2595
+ var lower = function lower(array) {
2596
+ return _.uniq(_.invoke(array, "toLowerCase")).sort();
2949
2597
  };
2950
2598
  var equal = same(vars1, vars2);
2951
2599
  var equalIgnoringCase = same(lower(vars1), lower(vars2));
@@ -2954,85 +2602,39 @@ class Expr {
2954
2602
  equalIgnoringCase: equalIgnoringCase
2955
2603
  };
2956
2604
  }
2957
-
2958
- // semantic equality check, call after sameVars() to avoid potential false positives
2959
- // plug in random numbers for the variables in both expressions
2960
- // if they both consistently evaluate the same, then they're the same
2961
2605
  compare(other) {
2962
- // equation comparisons are handled by Eq.compare()
2963
2606
  if (other instanceof Eq) {
2964
2607
  return false;
2965
2608
  }
2966
- var varList = ___default["default"].union(this.getVars(/* excludeFunc */true), other.getVars(/* excludeFunc */true));
2967
-
2968
- // If the numbers are large we would like to do a relative comparison
2969
- // rather than an absolute one, but if they're small enough then an
2970
- // absolute comparison makes more sense
2971
- var getDelta = function (num1, num2) {
2609
+ var varList = _.union(this.getVars(true), other.getVars(true));
2610
+ var getDelta = function getDelta(num1, num2) {
2972
2611
  if (Math.abs(num1) < 1 || Math.abs(num2) < 1) {
2973
2612
  return Math.abs(num1 - num2);
2974
2613
  } else {
2975
2614
  return Math.abs(1 - num1 / num2);
2976
2615
  }
2977
2616
  };
2978
- var equalNumbers = function (num1, num2) {
2617
+ var equalNumbers = function equalNumbers(num1, num2) {
2979
2618
  var delta = getDelta(num1, num2);
2980
- return num1 === num2 /* needed if either is +/- Infinity */ || isNaN(num1) && isNaN(num2) || delta < Math.pow(10, -TOLERANCE);
2619
+ return num1 === num2 || isNaN(num1) && isNaN(num2) || delta < Math.pow(10, -9);
2981
2620
  };
2982
-
2983
- // If no variables, only need to evaluate once.
2984
- // note(matthew) Seems to be an optimization for simple cases like `2+2=4`
2985
- // where there are no variables / functions.
2986
- // Ran into issues with it in LEMS-2777 and found that tests pass
2987
- // with this removed, but keeping a modified version out of caution.
2988
- const varAndFuncList = ___default["default"].union(this.getVars(/* excludeFunc */false), other.getVars(/* excludeFunc */false));
2621
+ const varAndFuncList = _.union(this.getVars(false), other.getVars(false));
2989
2622
  if (!varAndFuncList.length && !this.has(Unit) && !other.has(Unit)) {
2990
2623
  return equalNumbers(this.eval(), other.eval());
2991
2624
  }
2992
-
2993
- // collect here to avoid sometimes dividing by zero, and sometimes not
2994
- // it is better to be deterministic, e.g. x/x -> 1
2995
- // TODO(alex): may want to keep track of assumptions as they're made
2996
2625
  var expr1 = this.collect();
2997
2626
  var expr2 = other.collect();
2998
2627
  var unitList1 = this.getUnits();
2999
2628
  var unitList2 = other.getUnits();
3000
- if (!___default["default"].isEqual(unitList1, unitList2)) {
2629
+ if (!_.isEqual(unitList1, unitList2)) {
3001
2630
  return false;
3002
2631
  }
3003
-
3004
- // Compare at a set number (currently 12) of points to determine
3005
- // equality.
3006
- //
3007
- // `range` (and `vars`) is the only variable that varies through the
3008
- // iterations. For each of range = 10, 100, and 1000, each random
3009
- // variable is picked from (-range, range).
3010
- //
3011
- // Note that because there are 12 iterations and three ranges, each
3012
- // range is checked four times.
3013
2632
  for (var i = 0; i < ITERATIONS; i++) {
3014
2633
  var vars = {};
3015
-
3016
- // One third total iterations each with range 10, 100, and 1000
3017
2634
  var range = Math.pow(10, 1 + Math.floor(3 * i / ITERATIONS));
3018
-
3019
- // Half of the iterations should only use integer values.
3020
- // This is because expressions like (-2)^x are common but result
3021
- // in NaN when evaluated in JS with non-integer values of x.
3022
- // Without this, (-2)^x and (-2)^(x+1) both end up always being NaN
3023
- // and thus equivalent. With this, the most common failure case is
3024
- // avoided. However, less common cases such as (-2)^(x+0.1) and
3025
- // (-2)^(x+1.1) will still both evaluate to NaN and result in a
3026
- // false positive.
3027
- //
3028
- // Note that the above is only true in vanilla JS Number-land,
3029
- // which has no concept of complex numbers. The solution is simple:
3030
- // Integrate a library for handling complex numbers.
3031
- //
3032
- // TODO(alex): Add support for complex numbers, then remove this.
3033
2635
  var useFloats = i % 2 === 0;
3034
- ___default["default"].each(varList, function (v) {
3035
- vars[v] = useFloats ? randomFloat(-range, range) : ___default["default"].random(-range, range);
2636
+ _.each(varList, function (v) {
2637
+ vars[v] = useFloats ? randomFloat(-range, range) : _.random(-range, range);
3036
2638
  });
3037
2639
  let equal;
3038
2640
  if (expr1.has(Func) || expr2.has(Func) || expr1.has(Unit) || expr2.has(Unit)) {
@@ -3050,8 +2652,6 @@ class Expr {
3050
2652
  }
3051
2653
  return true;
3052
2654
  }
3053
-
3054
- // evaluate as much of the expression as possible
3055
2655
  partialEval(vars) {
3056
2656
  if (this instanceof Unit) {
3057
2657
  return this;
@@ -3063,86 +2663,50 @@ class Expr {
3063
2663
  return this.recurse("partialEval", vars);
3064
2664
  }
3065
2665
  }
3066
-
3067
- // check that the structure of both expressions is the same
3068
- // all negative signs are stripped and the expressions are converted to
3069
- // a canonical commutative form
3070
- // should only be done after compare() returns true to avoid false positives
3071
2666
  sameForm(other) {
3072
2667
  return this.strip().equals(other.strip());
3073
2668
  }
3074
-
3075
- // returns the GCD of this expression and the given factor
3076
2669
  findGCD(factor) {
3077
2670
  return this.equals(factor) ? factor : NumOne;
3078
2671
  }
3079
-
3080
- // return this expression's denominator
3081
2672
  getDenominator() {
3082
2673
  return NumOne;
3083
2674
  }
3084
-
3085
- // return this expression as a Mul
3086
2675
  asMul() {
3087
2676
  return new Mul(NumOne, this);
3088
2677
  }
3089
-
3090
- // TODO(alex): rename to isDefinitePositive or similar?
3091
- // return whether this expression is 100% positive
3092
2678
  isPositive() {
3093
- throw new Error("Abstract method - must override for expr: " +
3094
- // eslint-disable-next-line @babel/no-invalid-this
3095
- this.print());
2679
+ throw new Error("Abstract method - must override for expr: " + this.print());
3096
2680
  }
3097
-
3098
- // TODO(alex): rename to hasNegativeSign or similar?
3099
- // return whether this expression has a negative sign
3100
2681
  isNegative() {
3101
2682
  return false;
3102
2683
  }
3103
-
3104
- // return a factor of this expression that is 100% positive
3105
2684
  asPositiveFactor() {
3106
2685
  return this.isPositive() ? this : NumOne;
3107
2686
  }
3108
-
3109
- // return a copy of the expression with a new hint set (preserves hints)
3110
2687
  addHint(hint) {
3111
2688
  if (!hint) {
3112
2689
  return this;
3113
2690
  }
3114
2691
  var expr = this.construct(this.args());
3115
- expr.hints = ___default["default"].clone(this.hints);
2692
+ expr.hints = _.clone(this.hints);
3116
2693
  expr.hints[hint] = true;
3117
2694
  return expr;
3118
2695
  }
3119
-
3120
- // complete parse by performing a few necessary transformations
3121
2696
  completeParse() {
3122
2697
  return this.recurse("completeParse");
3123
2698
  }
3124
2699
  abs() {
3125
- throw new Error("Abstract method - must override for expr: " +
3126
- // eslint-disable-next-line @babel/no-invalid-this
3127
- this.print());
2700
+ throw new Error("Abstract method - must override for expr: " + this.print());
3128
2701
  }
3129
2702
  negate() {
3130
2703
  return new Mul(NumNeg, this);
3131
2704
  }
3132
2705
  }
3133
-
3134
- /* abstract sequence node */
3135
2706
  class Seq extends Expr {
3136
- // This should always have at least two terms.
3137
- // TODO(kevinb): Try enforcing this at the type-level using [T, T, T[]]
3138
- terms;
3139
-
3140
- // TODO(kevinb): Update this use `...args: Expr[]`
3141
- constructor() {
2707
+ constructor(...args) {
3142
2708
  super();
3143
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
3144
- args[_key2] = arguments[_key2];
3145
- }
2709
+ this.terms = void 0;
3146
2710
  if (args.length === 1) {
3147
2711
  this.terms = args[0];
3148
2712
  } else {
@@ -3153,7 +2717,7 @@ class Seq extends Expr {
3153
2717
  return this.terms;
3154
2718
  }
3155
2719
  normalize() {
3156
- var terms = ___default["default"].sortBy(___default["default"].invoke(this.terms, "normalize"), term => {
2720
+ var terms = _.sortBy(_.invoke(this.terms, "normalize"), term => {
3157
2721
  return term.print();
3158
2722
  });
3159
2723
  return new this.func(terms);
@@ -3161,54 +2725,35 @@ class Seq extends Expr {
3161
2725
  expand() {
3162
2726
  return this.recurse("expand").flatten();
3163
2727
  }
3164
-
3165
- // partition the sequence into its numeric and non-numeric parts
3166
- // makes no guarantees about the validity of either part!
3167
2728
  partition() {
3168
2729
  var [numbers, others] = partition(this.terms, term => {
3169
2730
  return term instanceof Num;
3170
2731
  });
3171
2732
  return [new this.func(numbers), new this.func(others)];
3172
2733
  }
3173
-
3174
- // ensure that sequences have 2+ terms and no nested sequences of the same type
3175
- // this is a shallow flattening and will return a non-Seq if terms.length <= 1
3176
2734
  flatten() {
3177
2735
  var type = this;
3178
- var terms = ___default["default"].reject(this.terms, term => {
3179
- // @ts-expect-error: `identity` is defined on Add and Mul but doesn't
3180
- // exist on Seq itself.
2736
+ var terms = _.reject(this.terms, term => {
3181
2737
  return term.equals(type.identity);
3182
2738
  });
3183
2739
  if (terms.length === 0) {
3184
- // @ts-expect-error: `identity` is defined on Add and Mul but doesn't
3185
- // exist on Seq itself.
3186
2740
  return type.identity;
3187
2741
  }
3188
2742
  if (terms.length === 1) {
3189
2743
  return terms[0];
3190
2744
  }
3191
-
3192
- // same contains the children which are Seqs of the same type as this Seq
3193
2745
  const [same, others] = partition(terms, term => {
3194
2746
  return term instanceof type.func;
3195
2747
  });
3196
- var flattened = others.concat(___default["default"].flatten(___default["default"].pluck(same, "terms"), /* shallow: */true));
2748
+ var flattened = others.concat(_.flatten(_.pluck(same, "terms"), true));
3197
2749
  return new type.func(flattened);
3198
2750
  }
3199
-
3200
- // reduce a numeric sequence to a Num
3201
-
3202
2751
  isPositive() {
3203
- var terms = ___default["default"].invoke(this.terms, "collect");
3204
- return ___default["default"].all(___default["default"].invoke(terms, "isPositive"));
2752
+ var terms = _.invoke(this.terms, "collect");
2753
+ return _.all(_.invoke(terms, "isPositive"));
3205
2754
  }
3206
-
3207
- // return a new Seq with a given term replaced by a different term
3208
- // (or array of terms). given term can be passed directly, or by index
3209
- // if no new term is provided, the old one is simply removed
3210
2755
  replace(oldTerm, newTerm) {
3211
- const index = oldTerm instanceof Expr ? ___default["default"].indexOf(this.terms, oldTerm) : oldTerm;
2756
+ const index = oldTerm instanceof Expr ? _.indexOf(this.terms, oldTerm) : oldTerm;
3212
2757
  var newTerms = [];
3213
2758
  if (Array.isArray(newTerm)) {
3214
2759
  newTerms = newTerm;
@@ -3218,39 +2763,35 @@ class Seq extends Expr {
3218
2763
  var terms = this.terms.slice(0, index).concat(newTerms).concat(this.terms.slice(index + 1));
3219
2764
  return new this.func(terms);
3220
2765
  }
3221
-
3222
- // syntactic sugar for replace()
3223
2766
  remove(term) {
3224
2767
  return this.replace(term);
3225
2768
  }
3226
2769
  getDenominator() {
3227
- // TODO(alex): find and return LCM
3228
- return new Mul(___default["default"].invoke(this.terms, "getDenominator")).flatten();
2770
+ return new Mul(_.invoke(this.terms, "getDenominator")).flatten();
3229
2771
  }
3230
2772
  }
3231
-
3232
- /* sequence of additive terms */
3233
2773
  class Add extends Seq {
3234
- identity = NumZero;
3235
- func = Add;
3236
- eval() {
3237
- let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3238
- let options = arguments.length > 1 ? arguments[1] : undefined;
3239
- return ___default["default"].reduce(this.terms, (memo, term) => {
2774
+ constructor(...args) {
2775
+ super(...args);
2776
+ this.identity = NumZero;
2777
+ this.func = Add;
2778
+ }
2779
+ eval(vars = {}, options) {
2780
+ return _.reduce(this.terms, (memo, term) => {
3240
2781
  return memo + term.eval(vars, options);
3241
2782
  }, 0);
3242
2783
  }
3243
2784
  codegen() {
3244
- return ___default["default"].map(this.terms, term => {
2785
+ return _.map(this.terms, term => {
3245
2786
  return "(" + term.codegen() + ")";
3246
2787
  }).join(" + ") || "0";
3247
2788
  }
3248
2789
  print() {
3249
- return ___default["default"].invoke(this.terms, "print").join("+");
2790
+ return _.invoke(this.terms, "print").join("+");
3250
2791
  }
3251
2792
  tex() {
3252
2793
  let tex = "";
3253
- ___default["default"].each(this.terms, term => {
2794
+ _.each(this.terms, term => {
3254
2795
  if (!tex || term.isSubtract()) {
3255
2796
  tex += term.tex();
3256
2797
  } else {
@@ -3260,9 +2801,9 @@ class Add extends Seq {
3260
2801
  return tex;
3261
2802
  }
3262
2803
  collect(options) {
3263
- var terms = ___default["default"].invoke(this.terms, "collect", options);
2804
+ var terms = _.invoke(this.terms, "collect", options);
3264
2805
  var pairs = [];
3265
- ___default["default"].each(terms, term => {
2806
+ _.each(terms, term => {
3266
2807
  if (term instanceof Mul) {
3267
2808
  var muls = term.partition();
3268
2809
  pairs.push([muls[1].flatten(), muls[0].reduce(options)]);
@@ -3272,30 +2813,20 @@ class Add extends Seq {
3272
2813
  pairs.push([term, NumOne]);
3273
2814
  }
3274
2815
  });
3275
-
3276
- // { (Expr expr).print(): [[Expr expr, Num coefficient]] }
3277
- var grouped = ___default["default"].groupBy(pairs, pair => {
2816
+ var grouped = _.groupBy(pairs, pair => {
3278
2817
  return pair[0].normalize().print();
3279
2818
  });
3280
- var collected = ___default["default"].compact(___default["default"].map(grouped, pairs => {
2819
+ var collected = _.compact(_.map(grouped, pairs => {
3281
2820
  var expr = pairs[0][0];
3282
- var sum = new Add(___default["default"].zip.apply(___default["default"], pairs)[1]);
2821
+ var sum = new Add(_.zip.apply(_, pairs)[1]);
3283
2822
  var coefficient = sum.reduce(options);
3284
2823
  return new Mul(coefficient, expr).collect(options);
3285
2824
  }));
3286
-
3287
- // TODO(alex): use the Pythagorean identity here
3288
- // e.g. x*sin^2(y) + x*cos^2(y) -> x
3289
-
3290
2825
  return new Add(collected).flatten();
3291
2826
  }
3292
-
3293
- // naively factor out anything that is common to all terms
3294
- // if options.keepNegative is specified, won't factor out a common -1
3295
- factor() {
3296
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
3297
- keepNegative: false
3298
- };
2827
+ factor(options = {
2828
+ keepNegative: false
2829
+ }) {
3299
2830
  const terms = this.terms.map(term => term.collect());
3300
2831
  let factors;
3301
2832
  if (terms[0] instanceof Mul) {
@@ -3303,8 +2834,8 @@ class Add extends Seq {
3303
2834
  } else {
3304
2835
  factors = [terms[0]];
3305
2836
  }
3306
- ___default["default"].each(___default["default"].rest(this.terms), term => {
3307
- factors = ___default["default"].map(factors, factor => {
2837
+ _.each(_.rest(this.terms), term => {
2838
+ factors = _.map(factors, factor => {
3308
2839
  return term.findGCD(factor);
3309
2840
  });
3310
2841
  });
@@ -3317,9 +2848,7 @@ class Add extends Seq {
3317
2848
  return Mul.createOrAppend(left, right).flatten();
3318
2849
  }
3319
2850
  reduce(options) {
3320
- return ___default["default"].reduce(this.terms,
3321
- // @ts-expect-error: Type 'Expr' is not assignable to type 'Num'.
3322
- (memo, term) => {
2851
+ return _.reduce(this.terms, (memo, term) => {
3323
2852
  return memo.add(term, options);
3324
2853
  }, this.identity);
3325
2854
  }
@@ -3327,14 +2856,12 @@ class Add extends Seq {
3327
2856
  return false;
3328
2857
  }
3329
2858
  isNegative() {
3330
- var terms = ___default["default"].invoke(this.terms, "collect");
3331
- return ___default["default"].all(___default["default"].invoke(terms, "isNegative"));
2859
+ var terms = _.invoke(this.terms, "collect");
2860
+ return _.all(_.invoke(terms, "isNegative"));
3332
2861
  }
3333
2862
  negate() {
3334
- return new Add(___default["default"].invoke(this.terms, "negate"));
2863
+ return new Add(_.invoke(this.terms, "negate"));
3335
2864
  }
3336
-
3337
- // create a new sequence unless left is already one (returns a copy)
3338
2865
  static createOrAppend(left, right) {
3339
2866
  if (left instanceof Add) {
3340
2867
  return new Add(left.terms.concat(right));
@@ -3343,41 +2870,37 @@ class Add extends Seq {
3343
2870
  }
3344
2871
  }
3345
2872
  }
3346
-
3347
- /* sequence of multiplicative terms */
3348
2873
  class Mul extends Seq {
3349
- identity = NumOne;
3350
- func = Mul;
3351
- eval() {
3352
- let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3353
- let options = arguments.length > 1 ? arguments[1] : undefined;
3354
- return ___default["default"].reduce(this.terms, (memo, term) => {
2874
+ constructor(...args) {
2875
+ super(...args);
2876
+ this.identity = NumOne;
2877
+ this.func = Mul;
2878
+ }
2879
+ eval(vars = {}, options) {
2880
+ return _.reduce(this.terms, (memo, term) => {
3355
2881
  return memo * term.eval(vars, options);
3356
2882
  }, 1);
3357
2883
  }
3358
2884
  codegen() {
3359
- return ___default["default"].map(this.terms, term => {
2885
+ return _.map(this.terms, term => {
3360
2886
  return "(" + term.codegen() + ")";
3361
2887
  }).join(" * ") || "0";
3362
2888
  }
3363
2889
  print() {
3364
- return ___default["default"].map(this.terms, term => {
2890
+ return _.map(this.terms, term => {
3365
2891
  return term instanceof Add ? "(" + term.print() + ")" : term.print();
3366
2892
  }).join("*");
3367
2893
  }
3368
2894
  getUnits() {
3369
- var tmUnits = ___default["default"](this.terms).chain().map(term => {
2895
+ var tmUnits = _(this.terms).chain().map(term => {
3370
2896
  return term.getUnits();
3371
2897
  }).flatten().value();
3372
2898
  tmUnits.sort((a, b) => a.unit.localeCompare(b.unit));
3373
2899
  return tmUnits;
3374
2900
  }
3375
-
3376
- // since we don't care about commutativity, we can render a Mul any way we choose
3377
- // so we follow convention: first any negatives, then any numbers, then everything else
3378
2901
  tex() {
3379
2902
  var cdot = " \\cdot ";
3380
- var terms = ___default["default"].groupBy(this.terms, term => {
2903
+ var terms = _.groupBy(this.terms, term => {
3381
2904
  if (term.isDivide()) {
3382
2905
  return "inverse";
3383
2906
  } else if (term instanceof Num) {
@@ -3391,10 +2914,6 @@ class Mul extends Seq {
3391
2914
  var others = terms.other || [];
3392
2915
  var negatives = "";
3393
2916
  var numerator;
3394
-
3395
- // check all the numbers to see if there is a rational we can extract,
3396
- // since we would like 1/2x/y to come out as \frac{1}{2}\frac{x}{y},
3397
- // and not \frac{1x}{2y}.
3398
2917
  for (var i = 0; i < numbers.length; i++) {
3399
2918
  var isRational = numbers[i] instanceof Rational && !(numbers[i] instanceof Int);
3400
2919
  if (isRational && others.length > 0 && inverses.length > 0) {
@@ -3404,45 +2923,37 @@ class Mul extends Seq {
3404
2923
  return numbers[i].tex() + new Mul(newTerms).tex();
3405
2924
  }
3406
2925
  }
3407
- numbers = ___default["default"].compact(___default["default"].map(numbers, term => {
2926
+ numbers = _.compact(_.map(numbers, term => {
3408
2927
  var shouldPushDown = !term.hints.fraction || inverses.length > 0;
3409
2928
  if (term instanceof Rational && !(term instanceof Int) && shouldPushDown) {
3410
- // e.g. 3x/4 -> 3/4*x (internally) -> 3x/4 (rendered)
3411
2929
  inverses.push(new Pow(new Int(term.d), NumDiv));
3412
2930
  var number = new Int(term.n);
3413
2931
  number.hints = term.hints;
3414
- return ___default["default"].any(term.hints) ? number : null;
2932
+ return _.any(term.hints) ? number : null;
3415
2933
  } else {
3416
2934
  return term;
3417
2935
  }
3418
2936
  }));
3419
2937
  if (numbers.length === 0 && others.length === 1) {
3420
- // e.g. (x+y)/z -> \frac{x+y}{z}
3421
2938
  numerator = others[0].tex();
3422
2939
  } else {
3423
2940
  var tex = "";
3424
- ___default["default"].each(numbers, term => {
2941
+ _.each(numbers, term => {
3425
2942
  if (term.hints.subtract && term.hints.entered) {
3426
2943
  negatives += "-";
3427
2944
  tex += (tex ? cdot : "") + term.abs().tex();
3428
2945
  } else if (term instanceof Int && term.n === -1 && (term.hints.negate || term.hints.subtract)) {
3429
- // e.g. -1*-1 -> --1
3430
- // e.g. -1*x -> -x
3431
2946
  negatives += "-";
3432
2947
  } else {
3433
- // e.g. 2*3 -> 2(dot)3
3434
2948
  tex += (tex ? cdot : "") + term.tex();
3435
2949
  }
3436
2950
  });
3437
- ___default["default"].each(others, term => {
2951
+ _.each(others, term => {
3438
2952
  if (term.needsExplicitMul()) {
3439
- // e.g. 2*2^3 -> 2(dot)2^3
3440
2953
  tex += (tex ? cdot : "") + term.tex();
3441
2954
  } else if (term instanceof Add) {
3442
- // e.g. (a+b)*c -> (a+b)c
3443
2955
  tex += "(" + term.tex() + ")";
3444
2956
  } else {
3445
- // e.g. a*b*c -> abc
3446
2957
  tex += term.tex();
3447
2958
  }
3448
2959
  });
@@ -3451,53 +2962,45 @@ class Mul extends Seq {
3451
2962
  if (!inverses.length) {
3452
2963
  return negatives + numerator;
3453
2964
  } else {
3454
- var denominator = new Mul(___default["default"].invoke(inverses, "asDivide")).flatten().tex();
2965
+ var denominator = new Mul(_.invoke(inverses, "asDivide")).flatten().tex();
3455
2966
  return negatives + "\\frac{" + numerator + "}{" + denominator + "}";
3456
2967
  }
3457
2968
  }
3458
2969
  strip() {
3459
- var terms = ___default["default"].map(this.terms, term => {
2970
+ var terms = _.map(this.terms, term => {
3460
2971
  return term instanceof Num ? term.abs() : term.strip();
3461
2972
  });
3462
2973
  return new Mul(terms).flatten();
3463
2974
  }
3464
-
3465
- // expand numerator and denominator separately
3466
2975
  expand() {
3467
- const isInverse = function (term) {
2976
+ const isInverse = function isInverse(term) {
3468
2977
  return term instanceof Pow && term.exp.isNegative();
3469
2978
  };
3470
- const isInverseAdd = function (term) {
2979
+ const isInverseAdd = function isInverseAdd(term) {
3471
2980
  return isInverse(term) && isAdd(term.base);
3472
2981
  };
3473
2982
  const mul = this.recurse("expand").flatten();
3474
2983
  const factors = getFactors(mul);
3475
- const hasAdd = ___default["default"].any(factors, isAdd);
3476
- const hasInverseAdd = ___default["default"].any(factors, isInverseAdd);
2984
+ const hasAdd = _.any(factors, isAdd);
2985
+ const hasInverseAdd = _.any(factors, isInverseAdd);
3477
2986
  if (!(hasAdd || hasInverseAdd)) {
3478
2987
  return mul;
3479
2988
  }
3480
2989
  let [inverses, normals] = partition(factors, isInverse);
3481
2990
  if (hasAdd) {
3482
2991
  const [adds, others] = partition(normals, isAdd);
3483
-
3484
- // loop over each additive sequence
3485
- const expanded = ___default["default"].reduce(adds, function (expanded, add) {
3486
- // loop over each expanded array of terms
3487
- return ___default["default"].reduce(expanded, function (temp, array) {
3488
- // loop over each additive sequence's terms
3489
- return temp.concat(___default["default"].map(add.terms, term => array.concat(term)));
2992
+ const expanded = _.reduce(adds, function (expanded, add) {
2993
+ return _.reduce(expanded, function (temp, array) {
2994
+ return temp.concat(_.map(add.terms, term => array.concat(term)));
3490
2995
  }, []);
3491
2996
  }, [[]]);
3492
-
3493
- // join each fully expanded array of factors with remaining multiplicative factors
3494
- const muls = ___default["default"].map(expanded, function (array) {
2997
+ const muls = _.map(expanded, function (array) {
3495
2998
  return new Mul(others.concat(array)).flatten();
3496
2999
  });
3497
3000
  normals = [new Add(muls)];
3498
3001
  }
3499
3002
  if (hasInverseAdd) {
3500
- const denominator = new Mul(___default["default"].invoke(inverses, "getDenominator")).flatten();
3003
+ const denominator = new Mul(_.invoke(inverses, "getDenominator")).flatten();
3501
3004
  inverses = [new Pow(denominator.expand(), NumDiv)];
3502
3005
  }
3503
3006
  return new Mul(normals.concat(inverses)).flatten();
@@ -3507,16 +3010,10 @@ class Mul extends Seq {
3507
3010
  if (!(factored instanceof Mul)) {
3508
3011
  return factored;
3509
3012
  }
3510
-
3511
- // Combine any factored out Rationals into one, but don't collect
3512
3013
  var [rationals, others] = partition(factored.terms, term => {
3513
3014
  return term instanceof Rational;
3514
3015
  });
3515
-
3516
- // Could also accomplish this by passing a new option
3517
- // e.g. return memo.mul(term, {autocollect: false});
3518
- // TODO(alex): Decide whether this is a good use of options or not
3519
- const ratObj = ___default["default"].reduce(rationals, (memo, term) => {
3016
+ const ratObj = _.reduce(rationals, (memo, term) => {
3520
3017
  return {
3521
3018
  n: memo.n * term.n,
3522
3019
  d: memo.d * term.d
@@ -3531,35 +3028,28 @@ class Mul extends Seq {
3531
3028
  collect(options) {
3532
3029
  var partitioned = this.recurse("collect", options).partition();
3533
3030
  var number = partitioned[0].reduce(options);
3534
-
3535
- // e.g. 0*x -> 0
3536
3031
  if (number.eval() === 0) {
3537
3032
  return NumZero;
3538
3033
  }
3539
3034
  const other = partitioned[1].flatten();
3540
-
3541
- // e.g. 2*2 -> 4
3542
- // e.g. 2*2*x -> 4*x
3543
3035
  if (!(other instanceof Mul)) {
3544
3036
  return new Mul(number, other).flatten();
3545
3037
  }
3546
3038
  const others = other.terms;
3547
3039
  var pairs = [];
3548
- ___default["default"].each(others, term => {
3040
+ _.each(others, term => {
3549
3041
  if (term instanceof Pow) {
3550
3042
  pairs.push([term.base, term.exp]);
3551
3043
  } else {
3552
3044
  pairs.push([term, NumOne]);
3553
3045
  }
3554
3046
  });
3555
-
3556
- // {(Expr base).print(): [[Expr base, Expr exp]]}
3557
- var grouped = ___default["default"].groupBy(pairs, pair => {
3047
+ var grouped = _.groupBy(pairs, pair => {
3558
3048
  return pair[0].normalize().print();
3559
3049
  });
3560
- var summed = ___default["default"].compact(___default["default"].map(grouped, pairs => {
3050
+ var summed = _.compact(_.map(grouped, pairs => {
3561
3051
  var base = pairs[0][0];
3562
- var sum = new Add(___default["default"].zip.apply(___default["default"], pairs)[1]);
3052
+ var sum = new Add(_.zip.apply(_, pairs)[1]);
3563
3053
  var exp = sum.collect(options);
3564
3054
  if (exp instanceof Num && exp.eval() === 0) {
3565
3055
  return null;
@@ -3567,9 +3057,7 @@ class Mul extends Seq {
3567
3057
  return [base, exp];
3568
3058
  }
3569
3059
  }));
3570
-
3571
- // XXX `pairs` is shadowed four or five times in this function
3572
- const groupedPairs = ___default["default"].groupBy(summed, pair => {
3060
+ const groupedPairs = _.groupBy(summed, pair => {
3573
3061
  if (pair[0] instanceof Trig && pair[0].isBasic()) {
3574
3062
  return "trig";
3575
3063
  } else if (pair[0] instanceof Log) {
@@ -3582,26 +3070,20 @@ class Mul extends Seq {
3582
3070
  let logs = groupedPairs.log || [];
3583
3071
  const exprs = groupedPairs.expr || [];
3584
3072
  if (trigs.length > 1) {
3585
- // combine sines and cosines into other trig functions
3586
-
3587
- // {Trig.arg.print(): [[Trig base, Expr exp]]}
3588
- var byArg = ___default["default"].groupBy(trigs, pair => {
3073
+ var byArg = _.groupBy(trigs, pair => {
3589
3074
  return pair[0].arg.normalize().print();
3590
3075
  });
3591
3076
  trigs = [];
3592
- ___default["default"].each(byArg, pairs => {
3077
+ _.each(byArg, pairs => {
3593
3078
  const arg = pairs[0][0].arg;
3594
-
3595
- // {Trig.type: Expr exp}
3596
3079
  let funcs = {
3597
3080
  sin: NumZero,
3598
3081
  cos: NumZero
3599
3082
  };
3600
- ___default["default"].each(pairs, pair => {
3083
+ _.each(pairs, pair => {
3601
3084
  funcs[pair[0].type] = pair[1];
3602
3085
  });
3603
3086
  if (Mul.handleNegative(funcs.sin).collect(options).equals(funcs.cos)) {
3604
- // e.g. sin^x(y)/cos^x(y) -> tan^x(y)
3605
3087
  if (funcs.cos.isNegative()) {
3606
3088
  funcs = {
3607
3089
  tan: funcs.sin
@@ -3612,30 +3094,18 @@ class Mul extends Seq {
3612
3094
  };
3613
3095
  }
3614
3096
  }
3615
-
3616
- // TODO(alex): combine even if exponents not a perfect match
3617
- // TODO(alex): transform 1/sin and 1/cos into csc and sec
3618
-
3619
- ___default["default"].each(funcs, (exp, type) => {
3097
+ _.each(funcs, (exp, type) => {
3620
3098
  trigs.push([new Trig(type, arg), exp]);
3621
3099
  });
3622
3100
  });
3623
3101
  }
3624
3102
  if (logs.length > 1) {
3625
- // combine logs with the same base
3626
-
3627
- // {Log.base.print(): [[Log base, Expr exp]]}
3628
- var byBase = ___default["default"].groupBy(logs, pair => {
3103
+ var byBase = _.groupBy(logs, pair => {
3629
3104
  return pair[0].base.normalize().print();
3630
3105
  });
3631
3106
  logs = [];
3632
- ___default["default"].each(byBase, pairs => {
3633
- // only combine two logs of the same base, otherwise commutative
3634
- // differences result in different equally valid output
3635
- // e.g. ln(x)/ln(z)*ln(y) -> log_z(x)*ln(y)
3636
- // e.g. ln(x)*ln(y)/ln(z) -> ln(x)*log_z(y)
3107
+ _.each(byBase, pairs => {
3637
3108
  if (pairs.length === 2 && Mul.handleNegative(pairs[0][1]).collect(options).equals(pairs[1][1])) {
3638
- // e.g. ln(x)^y/ln(b)^y -> log_b(x)^y
3639
3109
  if (pairs[0][1].isNegative()) {
3640
3110
  logs.push([new Log(pairs[0][0].power, pairs[1][0].power), pairs[1][1]]);
3641
3111
  } else {
@@ -3645,45 +3115,32 @@ class Mul extends Seq {
3645
3115
  logs = logs.concat(pairs);
3646
3116
  }
3647
3117
  });
3648
-
3649
- // TODO(alex): combine if all inverses are the same e.g. ln(y)*ln(z)/ln(x)/ln(x)
3650
3118
  }
3651
- var collected = ___default["default"].map([...trigs, ...logs, ...exprs], pair => {
3119
+ var collected = _.map([...trigs, ...logs, ...exprs], pair => {
3652
3120
  return new Pow(pair[0], pair[1]).collect(options);
3653
3121
  });
3654
3122
  return new Mul([number].concat(collected)).flatten();
3655
3123
  }
3656
3124
  isSubtract() {
3657
- return ___default["default"].any(this.terms, term => {
3125
+ return _.any(this.terms, term => {
3658
3126
  return term instanceof Num && Boolean(term.hints.subtract);
3659
3127
  });
3660
3128
  }
3661
-
3662
- // factor a single -1 in to the Mul
3663
- // combine with a Num if all Nums are positive, else add as a term
3664
3129
  factorIn(hint) {
3665
3130
  var partitioned = this.partition();
3666
- // `partition` splits the terms into two Seqs - one containing
3667
- // only Nums and the all non-Num nodes.
3668
3131
  var numbers = partitioned[0].terms;
3669
- var fold = numbers.length && ___default["default"].all(numbers, num => num.n > 0);
3132
+ var fold = numbers.length && _.all(numbers, num => num.n > 0);
3670
3133
  if (fold) {
3671
- // e.g. - x*2*3 -> x*-2*3
3672
3134
  var num = numbers[0].negate();
3673
3135
  num.hints = numbers[0].hints;
3674
3136
  return this.replace(numbers[0], num.addHint(hint));
3675
3137
  } else {
3676
- // e.g. - x*y -> -1*x*y
3677
- // e.g. - x*-2 -> -1*x*-2
3678
3138
  return new Mul([Num.negativeOne(hint)].concat(this.terms));
3679
3139
  }
3680
3140
  }
3681
-
3682
- // factor out a single hinted -1 (assume it is the division hint)
3683
- // TODO(alex): make more general or rename to be more specific
3684
3141
  factorOut() {
3685
3142
  var factored = false;
3686
- var terms = ___default["default"].compact(___default["default"].map(this.terms, term => {
3143
+ var terms = _.compact(_.map(this.terms, term => {
3687
3144
  if (!factored && term instanceof Num && term.hints.divide) {
3688
3145
  factored = true;
3689
3146
  return term.n !== -1 ? term.negate() : null;
@@ -3698,14 +3155,12 @@ class Mul extends Seq {
3698
3155
  }
3699
3156
  }
3700
3157
  reduce(options) {
3701
- return ___default["default"].reduce(this.terms,
3702
- // @ts-expect-error: Type 'Expr' is not assignable to type 'Num'.
3703
- (memo, term) => {
3158
+ return _.reduce(this.terms, (memo, term) => {
3704
3159
  return memo.mul(term, options);
3705
3160
  }, this.identity);
3706
3161
  }
3707
3162
  findGCD(factor) {
3708
- return new Mul(___default["default"].invoke(this.terms, "findGCD", factor)).flatten();
3163
+ return new Mul(_.invoke(this.terms, "findGCD", factor)).flatten();
3709
3164
  }
3710
3165
  asMul() {
3711
3166
  return this;
@@ -3720,7 +3175,7 @@ class Mul extends Seq {
3720
3175
  }
3721
3176
  isNegative() {
3722
3177
  const terms = getFactors(this.collect()).map(factor => factor.isNegative());
3723
- return ___default["default"].any(terms);
3178
+ return _.any(terms);
3724
3179
  }
3725
3180
  fold() {
3726
3181
  return Mul.fold(this);
@@ -3729,42 +3184,28 @@ class Mul extends Seq {
3729
3184
  var isNum = expr => {
3730
3185
  return expr instanceof Num;
3731
3186
  };
3732
- const num = ___default["default"].find(this.terms, isNum);
3187
+ const num = _.find(this.terms, isNum);
3733
3188
  if (num) {
3734
3189
  return this.replace(num, num.negate());
3735
3190
  } else {
3736
3191
  return new Mul([NumNeg].concat(this.terms));
3737
3192
  }
3738
3193
  }
3739
-
3740
- // negative signs should be folded into numbers whenever possible
3741
- // never fold into a Num that's already negative or a Mul that has a negative Num
3742
- // an optional hint is kept track of to properly render user input
3743
- // an empty hint means negation
3744
3194
  static handleNegative(expr, hint) {
3745
3195
  if (expr instanceof Num && expr.n > 0) {
3746
- // e.g. - 2 -> -2
3747
3196
  var negated = expr.negate();
3748
- // TODO(alex): rework hint system so that this isn't necessary
3749
3197
  negated.hints = expr.hints;
3750
3198
  return negated.addHint(hint);
3751
3199
  } else if (expr instanceof Mul) {
3752
- // e.g. - x*2*3 -> x*-2*3
3753
- // e.g. - x*y -> -1*x*y
3754
- // e.g. - x*-2 -> -1*x*-2
3755
3200
  return expr.factorIn(hint);
3756
3201
  } else {
3757
- // e.g. - x -> -1*x
3758
3202
  return new Mul(Num.negativeOne(hint), expr);
3759
3203
  }
3760
3204
  }
3761
-
3762
- // division can create either a Rational or a Mul
3763
3205
  static handleDivide(left, right) {
3764
- // dividing by a Mul is the same as repeated division by its terms
3765
3206
  if (right instanceof Mul) {
3766
3207
  var first = Mul.handleDivide(left, right.terms[0]);
3767
- var rest = new Mul(___default["default"].rest(right.terms)).flatten();
3208
+ var rest = new Mul(_.rest(right.terms)).flatten();
3768
3209
  return Mul.handleDivide(first, rest);
3769
3210
  }
3770
3211
  var isInt = expr => {
@@ -3773,11 +3214,7 @@ class Mul extends Seq {
3773
3214
  var isRational = expr => {
3774
3215
  return expr instanceof Rational;
3775
3216
  };
3776
-
3777
- // for simplification purposes, fold Ints into Rationals if possible
3778
- // e.g. 3x / 4 -> 3/4 * x (will still render as 3x/4)
3779
- if (isInt(right) && left instanceof Mul && ___default["default"].any(left.terms, isInt)) {
3780
- // search from the right
3217
+ if (isInt(right) && left instanceof Mul && _.any(left.terms, isInt)) {
3781
3218
  var reversed = left.terms.slice().reverse();
3782
3219
  var num = reversed.find(isRational);
3783
3220
  if (!isInt(num)) {
@@ -3785,9 +3222,6 @@ class Mul extends Seq {
3785
3222
  }
3786
3223
  var rational = new Rational(num.n, right.n);
3787
3224
  rational.hints = num.hints;
3788
-
3789
- // in the case of something like 1/3 * 6/8, we want the
3790
- // 6/8 to be considered a fraction, not just a division
3791
3225
  if (num === reversed[0]) {
3792
3226
  rational = rational.addHint("fraction");
3793
3227
  }
@@ -3802,17 +3236,11 @@ class Mul extends Seq {
3802
3236
  if (b instanceof Int) {
3803
3237
  if (a instanceof Int) {
3804
3238
  if (a.n < 0 && b.n < 0) {
3805
- // e.g. -2 / -3 -> -1*-2/3
3806
3239
  return [NumNeg, new Rational(a.n, -b.n).addHint("fraction")];
3807
3240
  } else {
3808
- // e.g. 2 / 3 -> 2/3
3809
- // e.g. -2 / 3 -> -2/3
3810
- // e.g. 2 / -3 -> -2/3
3811
3241
  return [new Rational(a.n, b.n).addHint("fraction")];
3812
3242
  }
3813
3243
  } else {
3814
- // e.g. x / 3 -> x*1/3
3815
- // e.g. x / -3 -> x*-1/3
3816
3244
  var inverse = new Rational(1, b.eval());
3817
3245
  if (b.eval() < 0) {
3818
3246
  return [a, inverse.addHint("negate")];
@@ -3823,66 +3251,42 @@ class Mul extends Seq {
3823
3251
  } else {
3824
3252
  var pow;
3825
3253
  if (b instanceof Trig && b.exp) {
3826
- // e.g. sin^2(x) -> sin(x)^2
3827
3254
  var exp = b.exp;
3828
3255
  b.exp = undefined;
3829
3256
  b = new Pow(b, exp);
3830
3257
  }
3831
3258
  if (b instanceof Pow) {
3832
- // e.g. (x^2) ^ -1 -> x^-2
3833
- // e.g. (x^y) ^ -1 -> x^(-1*y)
3834
- // e.g. (x^(yz)) ^ -1 -> x^(-1*y*z)
3835
3259
  pow = new Pow(b.base, Mul.handleNegative(b.exp, "divide"));
3836
3260
  } else {
3837
- // e.g. x ^ -1 -> x^-1
3838
3261
  pow = new Pow(b, NumDiv);
3839
3262
  }
3840
3263
  if (a instanceof Int && a.n === 1) {
3841
- // e.g. 1 / x -> x^-1
3842
3264
  return [pow];
3843
3265
  } else {
3844
- // e.g. 2 / x -> 2*x^-1
3845
3266
  return [a, pow];
3846
3267
  }
3847
3268
  }
3848
3269
  };
3849
3270
  if (left instanceof Mul) {
3850
- // NOTE(kevinb): `terms` should always have at least two
3851
- // elements so getting the last element is safe to do.
3852
- var divided = divide(___default["default"].last(left.terms), right);
3853
- return new Mul(___default["default"].initial(left.terms).concat(divided));
3271
+ var divided = divide(_.last(left.terms), right);
3272
+ return new Mul(_.initial(left.terms).concat(divided));
3854
3273
  } else {
3855
3274
  var divided = divide(left, right);
3856
3275
  return new Mul(divided).flatten();
3857
3276
  }
3858
3277
  }
3859
-
3860
- // fold negative signs into numbers if possible
3861
- // negative signs are not the same as multiplying by negative one!
3862
- // e.g. -x -> -1*x simplified
3863
- // e.g. -2*x -> -2*x simplified
3864
- // e.g. -x*2 -> -1*x*2 not simplified -> x*-2 simplified
3865
- // e.g. -1*x*2 -> -1*x*2 not simplified
3866
-
3867
- // also fold multiplicative terms into open Trig and Log nodes
3868
- // e.g. (sin x)*x -> sin(x)*x
3869
- // e.g. sin(x)*x -> sin(x)*x
3870
- // e.g. sin(x)*(x) -> sin(x)*x
3871
- // e.g. sin(x)*sin(y) -> sin(x)*sin(y)
3872
3278
  static fold(expr) {
3873
3279
  if (expr instanceof Mul) {
3874
- // assuming that this will be second to last
3875
- var trigLog = ___default["default"].find(___default["default"].initial(expr.terms), term => {
3280
+ var trigLog = _.find(_.initial(expr.terms), term => {
3876
3281
  return (term instanceof Trig || term instanceof Log) && Boolean(term.hints.open);
3877
3282
  });
3878
3283
  if (trigLog) {
3879
- // expr.terms should always have at least two terms
3880
- const last = ___default["default"].last(expr.terms);
3284
+ const last = _.last(expr.terms);
3881
3285
  if (trigLog.hints.parens || last.hints.parens || last.has(Trig) || last.has(Log)) {
3882
3286
  trigLog.hints.open = false;
3883
3287
  } else {
3884
3288
  const newTrigLog = trigLog instanceof Trig ? Trig.create([trigLog.type, trigLog.exp], Mul.createOrAppend(trigLog.arg, last).fold()) : Log.create(trigLog.base, Mul.createOrAppend(trigLog.power, last).fold());
3885
- const index = ___default["default"].indexOf(expr.terms, trigLog);
3289
+ const index = _.indexOf(expr.terms, trigLog);
3886
3290
  if (index === 0) {
3887
3291
  return newTrigLog;
3888
3292
  } else {
@@ -3898,32 +3302,21 @@ class Mul extends Seq {
3898
3302
  var neg = num => {
3899
3303
  return num.n === -1 && Boolean(num.hints.negate);
3900
3304
  };
3901
- var posOrNeg = function (num) {
3305
+ var posOrNeg = function posOrNeg(num) {
3902
3306
  return pos(num) || neg(num);
3903
3307
  };
3904
-
3905
- // @ts-expect-error: Type 'Expr' is not assignable to type 'Num'.
3906
3308
  const posNum = numbers.find(pos);
3907
- // @ts-expect-error: Type 'Expr' is not assignable to type 'Num'.
3908
3309
  const negNum = numbers.find(neg);
3909
- if (numbers.length > 1 && negNum && posNum &&
3910
- // @ts-expect-error: Type 'Expr' is not assignable to type 'Num'.
3911
- ___default["default"].every(numbers, posOrNeg)) {
3912
- var firstNeg = ___default["default"].indexOf(expr.terms, negNum);
3913
- var firstNum = ___default["default"].indexOf(expr.terms, posNum);
3914
-
3915
- // e.g. -x*2 -> x*-2
3310
+ if (numbers.length > 1 && negNum && posNum && _.every(numbers, posOrNeg)) {
3311
+ var firstNeg = _.indexOf(expr.terms, negNum);
3312
+ var firstNum = _.indexOf(expr.terms, posNum);
3916
3313
  if (firstNeg < firstNum) {
3917
3314
  return expr.replace(firstNum, expr.terms[firstNum].negate()).remove(firstNeg);
3918
3315
  }
3919
3316
  }
3920
3317
  }
3921
-
3922
- // in all other cases, make no change
3923
3318
  return expr;
3924
3319
  }
3925
-
3926
- // create a new sequence unless left is already one (returns a copy)
3927
3320
  static createOrAppend(left, right) {
3928
3321
  if (left instanceof Mul) {
3929
3322
  return new Mul(left.terms.concat(right));
@@ -3932,39 +3325,23 @@ class Mul extends Seq {
3932
3325
  }
3933
3326
  }
3934
3327
  }
3935
-
3936
- /* exponentiation */
3937
3328
  class Pow extends Expr {
3938
- base;
3939
- exp;
3940
3329
  constructor(base, exp) {
3941
3330
  super();
3331
+ this.base = void 0;
3332
+ this.exp = void 0;
3333
+ this.func = Pow;
3942
3334
  this.base = base;
3943
3335
  this.exp = exp;
3944
3336
  }
3945
- func = Pow;
3946
3337
  args() {
3947
3338
  return [this.base, this.exp];
3948
3339
  }
3949
- eval() {
3950
- let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3951
- let options = arguments.length > 1 ? arguments[1] : undefined;
3340
+ eval(vars = {}, options) {
3952
3341
  var evaledBase = this.base.eval(vars, options);
3953
3342
  var evaledExp = this.exp.eval(vars, options);
3954
-
3955
- // Math.pow unequivocally returns NaN when provided with both a
3956
- // negative base and a fractional exponent. However, in some cases, we
3957
- // know that our exponent is actually valid for use with negative
3958
- // bases (e.g., (-5)^(1/3)).
3959
- //
3960
- // Here, we explicitly check for such cases. We really only handle a
3961
- // limited subset (by requiring that the exponent is rational with an
3962
- // odd denominator), but it's still useful.
3963
- // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/pow
3964
3343
  if (evaledBase < 0) {
3965
3344
  var simplifiedExp = this.exp.simplify();
3966
-
3967
- // If Float, convert to a Rational to enable the logic below
3968
3345
  if (simplifiedExp instanceof Float) {
3969
3346
  var num = simplifiedExp.n;
3970
3347
  var decimals = (num - +num.toFixed()).toString().length - 2;
@@ -3987,7 +3364,6 @@ class Pow extends Expr {
3987
3364
  return this.base.getUnits().map(unit => {
3988
3365
  return {
3989
3366
  unit: unit.unit,
3990
- // Exponents in units should always be integers
3991
3367
  pow: unit.pow * this.exp.n
3992
3368
  };
3993
3369
  });
@@ -4004,31 +3380,24 @@ class Pow extends Expr {
4004
3380
  }
4005
3381
  tex() {
4006
3382
  if (this.isDivide()) {
4007
- // e.g. x ^ -1 w/hint -> 1/x
4008
3383
  return "\\frac{1}{" + this.asDivide().tex() + "}";
4009
3384
  } else if (this.isRoot() && isRational(this.exp)) {
4010
3385
  if (this.exp.n !== 1) {
4011
3386
  throw new Error("Node marked with hint 'root' does not have exponent " + "of form 1/x.");
4012
3387
  }
4013
3388
  if (this.exp.d === 2) {
4014
- // e.g. x ^ 1/2 w/hint -> sqrt{x}
4015
3389
  return "\\sqrt{" + this.base.tex() + "}";
4016
3390
  } else {
4017
- // e.g. x ^ 1/y w/hint -> sqrt[y]{x}
4018
3391
  return "\\sqrt[" + this.exp.d + "]{" + this.base.tex() + "}";
4019
3392
  }
4020
3393
  } else if (this.base instanceof Trig && !this.base.isInverse() && this.exp instanceof Num && this.exp.isSimple() && this.exp.eval() >= 0) {
4021
- // e.g sin(x) ^ 2 -> sin^2(x)
4022
3394
  var split = this.base.texSplit();
4023
3395
  return split[0] + "^{" + this.exp.tex() + "}" + split[1];
4024
3396
  } else {
4025
- // e.g. x ^ y -> x^y
4026
3397
  var base = this.base.tex();
4027
3398
  if (this.base instanceof Seq || this.base instanceof Pow || this.base instanceof Num && !this.base.isSimple()) {
4028
- // e.g. a+b ^ c -> (a+b)^c
4029
3399
  base = "(" + base + ")";
4030
3400
  } else if (this.base instanceof Trig || this.base instanceof Log) {
4031
- // e.g. ln(x) ^ 2 -> [ln(x)]^2
4032
3401
  base = "[" + base + "]";
4033
3402
  }
4034
3403
  return base + "^{" + this.exp.tex() + "}";
@@ -4040,43 +3409,30 @@ class Pow extends Expr {
4040
3409
  expand() {
4041
3410
  var pow = this.recurse("expand");
4042
3411
  if (pow.base instanceof Mul) {
4043
- // e.g. (ab)^c -> a^c*b^c
4044
-
4045
- var terms = ___default["default"].map(pow.base.terms, term => {
3412
+ var terms = _.map(pow.base.terms, term => {
4046
3413
  return new Pow(term, pow.exp);
4047
3414
  });
4048
3415
  return new Mul(terms).expand();
4049
3416
  } else if (pow.base instanceof Add && pow.exp instanceof Int && pow.exp.abs().eval() > 1) {
4050
- // e.g. (a+b)^2 -> a*a+a*b+a*b+b*b
4051
- // e.g. (a+b)^-2 -> (a*a+a*b+a*b+b*b)^-1
4052
-
4053
3417
  var positive = pow.exp.eval() > 0;
4054
3418
  var n = pow.exp.abs().eval();
4055
- var signed = function (mul) {
3419
+ var signed = function signed(mul) {
4056
3420
  return positive ? mul : new Pow(mul, NumDiv);
4057
3421
  };
4058
-
4059
- // compute and cache powers of 2 up to n
4060
3422
  const cache = {
4061
3423
  1: pow.base
4062
3424
  };
4063
3425
  for (var i = 2; i <= n; i *= 2) {
4064
- const mul = new Mul(cache[i / 2], cache[i / 2]);
4065
- cache[i] = mul.expand().collect();
3426
+ const _mul = new Mul(cache[i / 2], cache[i / 2]);
3427
+ cache[i] = _mul.expand().collect();
4066
3428
  }
4067
-
4068
- // if n is a power of 2, you're done!
4069
3429
  if (n in cache) {
4070
3430
  return signed(cache[n]);
4071
3431
  }
4072
-
4073
- // otherwise decompose n into powers of 2 ...
4074
- let indices = ___default["default"].map(n.toString(2).split(""), function (str, i, list) {
3432
+ let indices = _.map(n.toString(2).split(""), function (str, i, list) {
4075
3433
  return Number(str) * Math.pow(2, list.length - i - 1);
4076
3434
  });
4077
- indices = ___default["default"].without(indices, 0);
4078
-
4079
- // ... then combine
3435
+ indices = _.without(indices, 0);
4080
3436
  const factors = [];
4081
3437
  for (const index of indices) {
4082
3438
  if (index in cache) {
@@ -4086,13 +3442,10 @@ class Pow extends Expr {
4086
3442
  const mul = new Mul(factors).expand().collect();
4087
3443
  return signed(mul);
4088
3444
  } else if (pow.exp instanceof Add) {
4089
- // DEFINITELY want behind super-simplify() flag
4090
- // e.g. x^(a+b) -> x^a*x^b
4091
-
4092
- const terms = ___default["default"].map(pow.exp.terms, term => {
3445
+ const _terms = _.map(pow.exp.terms, term => {
4093
3446
  return new Pow(pow.base, term).expand();
4094
3447
  });
4095
- return new Mul(terms).expand();
3448
+ return new Mul(_terms).expand();
4096
3449
  } else {
4097
3450
  return pow;
4098
3451
  }
@@ -4100,10 +3453,8 @@ class Pow extends Expr {
4100
3453
  factor() {
4101
3454
  var pow = this.recurse("factor");
4102
3455
  if (pow.base instanceof Mul) {
4103
- var terms = ___default["default"].map(pow.base.terms, term => {
3456
+ var terms = _.map(pow.base.terms, term => {
4104
3457
  if (term instanceof Int && pow.exp.equals(NumDiv)) {
4105
- // Anything that can be a Rational should be a Rational
4106
- // e.g. 2^(-1) -> 1/2
4107
3458
  return new Rational(1, term.n);
4108
3459
  } else {
4109
3460
  return new Pow(term, pow.exp);
@@ -4116,86 +3467,54 @@ class Pow extends Expr {
4116
3467
  }
4117
3468
  collect(options) {
4118
3469
  if (this.base instanceof Pow) {
4119
- // collect this first to avoid having to deal with float precision
4120
- // e.g. sqrt(2)^2 -> 2, not 2.0000000000000004
4121
- // e.g. (x^y)^z -> x^(yz)
4122
3470
  const base = this.base.base;
4123
3471
  const exp = Mul.createOrAppend(this.base.exp, this.exp);
4124
3472
  return new Pow(base, exp).collect(options);
4125
3473
  }
4126
3474
  const pow = this.recurse("collect", options);
4127
- const isSimilarLog = function (term) {
3475
+ const isSimilarLog = function isSimilarLog(term) {
4128
3476
  return term instanceof Log && term.base.equals(pow.base);
4129
3477
  };
4130
3478
  if (pow.exp instanceof Num && pow.exp.eval() === 0) {
4131
- // e.g. x^0 -> 1
4132
3479
  return NumOne;
4133
3480
  } else if (pow.exp instanceof Num && pow.exp.eval() === 1) {
4134
- // e.g. x^1 -> x
4135
3481
  return pow.base;
4136
3482
  } else if (isSimilarLog(pow.exp)) {
4137
- // e.g. b^(log_b(x)) -> x
4138
3483
  return pow.exp.power;
4139
- } else if (pow.exp instanceof Mul && ___default["default"].any(pow.exp.terms, isSimilarLog)) {
4140
- // e.g. b^(2*y*log_b(x)) -> x^(2*y)
4141
- // `log` will always be defined here because of the
4142
- // `_.any(pow.exp.terms, isSimilarLog)` check above.
3484
+ } else if (pow.exp instanceof Mul && _.any(pow.exp.terms, isSimilarLog)) {
4143
3485
  const log = pow.exp.terms.find(isSimilarLog);
4144
3486
  const base = log.power;
4145
3487
  const exp = pow.exp.remove(log).flatten();
4146
3488
  return new Pow(base, exp).collect(options);
4147
3489
  } else if (pow.base instanceof Num && pow.exp instanceof Num) {
4148
- // TODO(alex): Consider encapsualting this logic (and similar logic
4149
- // elsewhere) into a separate Decimal class for user-entered floats
4150
3490
  if (options && options.preciseFloats) {
4151
- // Avoid creating an imprecise float
4152
- // e.g. 23^1.5 -> 12167^0.5, not ~110.304
4153
-
4154
- // If you take the root as specified by the denominator and
4155
- // end up with more digits after the decimal point,
4156
- // the result is imprecise. This works for rationals as well
4157
- // as floats, but ideally rationals should be pre-processed
4158
- // e.g. (1/27)^(1/3) -> 1/3 to avoid most cases.
4159
- // TODO(alex): Catch such cases and avoid converting to floats.
4160
3491
  const exp = pow.exp.asRational();
4161
3492
  const decimalsInBase = pow.base.getDecimalPlaces();
4162
3493
  const root = new Pow(pow.base, new Rational(1, exp.d));
4163
- const decimalsInRoot = root.collect()
4164
- // @ts-expect-error: we assume that `root.collect()` returns
4165
- // a Num here but tbh I'm not sure how this code isn't causing
4166
- // an infinite loop.
4167
- .getDecimalPlaces();
3494
+ const decimalsInRoot = root.collect().getDecimalPlaces();
4168
3495
  if (decimalsInRoot > decimalsInBase) {
4169
- // Collecting over this denominator would result in an
4170
- // imprecise float, so avoid doing so.
4171
3496
  const newBase = new Pow(pow.base, new Int(exp.n)).collect();
4172
3497
  return new Pow(newBase, new Rational(1, exp.d));
4173
3498
  }
4174
3499
  }
4175
-
4176
- // e.g. 4^1.5 -> 8
4177
3500
  return pow.base.raiseToThe(pow.exp, options);
4178
3501
  } else {
4179
3502
  return pow;
4180
3503
  }
4181
3504
  }
4182
-
4183
- // checks whether this Pow represents user-entered division
4184
3505
  isDivide() {
4185
- var isDiv = function (arg) {
3506
+ var isDiv = function isDiv(arg) {
4186
3507
  return arg instanceof Num && Boolean(arg.hints.divide);
4187
3508
  };
4188
- return isDiv(this.exp) || this.exp instanceof Mul && ___default["default"].any(this.exp.terms, isDiv);
3509
+ return isDiv(this.exp) || this.exp instanceof Mul && _.any(this.exp.terms, isDiv);
4189
3510
  }
4190
-
4191
- // assuming this Pow represents user-entered division, returns the denominator
4192
3511
  asDivide() {
4193
3512
  if (this.exp instanceof Num) {
4194
3513
  if (this.exp.eval() === -1) {
4195
3514
  return this.base;
4196
3515
  } else {
4197
3516
  var negated = this.exp.negate();
4198
- negated.hints = ___default["default"].clone(this.exp.hints);
3517
+ negated.hints = _.clone(this.exp.hints);
4199
3518
  negated.hints.divide = false;
4200
3519
  return new Pow(this.base, negated);
4201
3520
  }
@@ -4211,9 +3530,6 @@ class Pow extends Expr {
4211
3530
  isSquaredTrig() {
4212
3531
  return this.base instanceof Trig && !this.base.isInverse() && this.exp instanceof Num && this.exp.eval() === 2;
4213
3532
  }
4214
-
4215
- // extract whatever denominator makes sense, ignoring hints
4216
- // if negative exponent, will recursively include the base's denominator as well
4217
3533
  getDenominator() {
4218
3534
  if (this.exp instanceof Num && this.exp.eval() === -1) {
4219
3535
  return Mul.createOrAppend(this.base, this.base.getDenominator()).flatten();
@@ -4228,27 +3544,17 @@ class Pow extends Expr {
4228
3544
  }
4229
3545
  findGCD(factor) {
4230
3546
  const [base, exp] = factor instanceof Pow ? [factor.base, factor.exp] : [factor, NumOne];
4231
-
4232
- // GCD is only relevant if same base
4233
3547
  if (this.base.equals(base)) {
4234
3548
  if (this.exp.equals(exp)) {
4235
- // exact match
4236
- // e.g. GCD(x^y^z, x^y^z) -> x^y^z
4237
3549
  return this;
4238
3550
  } else if (this.exp instanceof Num && exp instanceof Num) {
4239
- // two numerical exponents
4240
- // e.g. GCD(x^3, x^2) -> x^2
4241
3551
  return new Pow(this.base, Num.min(this.exp, exp)).collect();
4242
3552
  } else if (this.exp instanceof Num || exp instanceof Num) {
4243
- // one numerical exponent
4244
- // e.g. GCD(x^2, x^y) -> 1
4245
3553
  return NumOne;
4246
3554
  }
4247
3555
  var expA = this.exp.asMul().partition();
4248
3556
  var expB = exp.asMul().partition();
4249
3557
  if (expA[1].equals(expB[1])) {
4250
- // exponents match except for coefficient
4251
- // e.g. GCD(x^3y, x^y) -> x^y
4252
3558
  var coefficient = Num.min(expA[0].reduce(), expB[0].reduce());
4253
3559
  var mul = new Mul(coefficient, expA[1].flatten()).flatten();
4254
3560
  return new Pow(base, mul).collect();
@@ -4271,10 +3577,8 @@ class Pow extends Expr {
4271
3577
  if (exp instanceof Int) {
4272
3578
  var n = exp.eval();
4273
3579
  if (n > 2) {
4274
- // e.g. x^3 -> x^2
4275
3580
  return new Pow(this.base, new Int(n - 1));
4276
3581
  } else if (n < -2) {
4277
- // e.g. x^-3 -> x^-2
4278
3582
  return new Pow(this.base, new Int(n + 1));
4279
3583
  }
4280
3584
  }
@@ -4284,40 +3588,28 @@ class Pow extends Expr {
4284
3588
  static sqrt(arg) {
4285
3589
  return new Pow(arg, NumSqrt);
4286
3590
  }
4287
-
4288
- // NOTE(kevinb): nthroot is used as a constructor so we need to
4289
- // define it as a static property instead of a static method.
4290
- // TODO(kevinb): update parser-generator.ts to call nthrooth
4291
- // without using `new`.
4292
- static nthroot = function (radicand, degree) {
4293
- var exp = Mul.fold(Mul.handleDivide(new Int(1), degree));
4294
-
4295
- // FIXME(johnsullivan): If oneOverDegree ends up being a pow object,
4296
- // this "root" hint is lost between here and when tex() is called.
4297
- return new Pow(radicand, exp.addHint("root"));
4298
- };
4299
3591
  }
4300
-
4301
- /* logarithm */
3592
+ _class5 = Pow;
3593
+ Pow.nthroot = function (radicand, degree) {
3594
+ var exp = Mul.fold(Mul.handleDivide(new Int(1), degree));
3595
+ return new _class5(radicand, exp.addHint("root"));
3596
+ };
4302
3597
  class Log extends Expr {
4303
- base;
4304
- power;
4305
3598
  constructor(base, power) {
4306
3599
  super();
3600
+ this.base = void 0;
3601
+ this.power = void 0;
3602
+ this.func = Log;
4307
3603
  this.base = base;
4308
3604
  this.power = power;
4309
- this.hints = {
4310
- ...this.hints,
3605
+ this.hints = _extends({}, this.hints, {
4311
3606
  open: false
4312
- };
3607
+ });
4313
3608
  }
4314
- func = Log;
4315
3609
  args() {
4316
3610
  return [this.base, this.power];
4317
3611
  }
4318
- eval() {
4319
- let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4320
- let options = arguments.length > 1 ? arguments[1] : undefined;
3612
+ eval(vars = {}, options) {
4321
3613
  return Math.log(this.power.eval(vars, options)) / Math.log(this.base.eval(vars, options));
4322
3614
  }
4323
3615
  codegen() {
@@ -4342,13 +3634,10 @@ class Log extends Expr {
4342
3634
  collect(options) {
4343
3635
  var log = this.recurse("collect", options);
4344
3636
  if (log.power instanceof Num && log.power.eval() === 1) {
4345
- // e.g. ln(1) -> 0
4346
3637
  return NumZero;
4347
3638
  } else if (log.base.equals(log.power)) {
4348
- // e.g. log_b(b) -> 1
4349
3639
  return NumOne;
4350
3640
  } else if (log.power instanceof Pow && log.power.base.equals(log.base)) {
4351
- // e.g. log_b(b^x) -> x
4352
3641
  return log.power.exp;
4353
3642
  } else {
4354
3643
  return log;
@@ -4357,21 +3646,13 @@ class Log extends Expr {
4357
3646
  expand() {
4358
3647
  var log = this.recurse("expand");
4359
3648
  if (log.power instanceof Mul) {
4360
- // might want behind super-simplify() flag
4361
- // e.g. ln(xy) -> ln(x) + ln(y)
4362
-
4363
- var terms = ___default["default"].map(log.power.terms, term => {
4364
- // need to expand again in case new log powers are Pows
3649
+ var terms = _.map(log.power.terms, term => {
4365
3650
  return new Log(log.base, term).expand();
4366
3651
  });
4367
3652
  return new Add(terms);
4368
3653
  } else if (log.power instanceof Pow) {
4369
- // e.g. ln(x^y) -> y*ln(x)
4370
-
4371
3654
  return new Mul(log.power.exp, new Log(log.base, log.power.base).expand()).flatten();
4372
3655
  } else if (!log.isNatural()) {
4373
- // e.g. log_b(x) -> ln(x)/ln(b)
4374
-
4375
3656
  return Mul.handleDivide(new Log(Const.e, log.power), new Log(Const.e, log.base));
4376
3657
  } else {
4377
3658
  return log;
@@ -4405,178 +3686,172 @@ class Log extends Expr {
4405
3686
  return log;
4406
3687
  }
4407
3688
  }
4408
- /* trigonometric functions */
4409
3689
  class Trig extends Expr {
4410
- type; // TODO(kevinb): Use a union type for this
4411
- arg;
4412
- exp;
4413
- constructor(type, arg) {
3690
+ constructor(type, _arg) {
4414
3691
  super();
4415
- this.type = type;
4416
- this.arg = arg;
4417
- this.hints = {
4418
- ...this.hints,
4419
- open: false
4420
- };
4421
- }
4422
- func = Trig;
4423
- args() {
4424
- return [this.type, this.arg];
4425
- }
4426
-
4427
- // TODO(kevinb): Use union type for the function names.
4428
- functions = {
4429
- sin: {
4430
- eval: Math.sin,
4431
- codegen: "Math.sin((",
4432
- tex: "\\sin",
4433
- expand: () => this
4434
- },
4435
- cos: {
4436
- eval: Math.cos,
4437
- codegen: "Math.cos((",
4438
- tex: "\\cos",
4439
- expand: () => this
4440
- },
4441
- tan: {
4442
- eval: Math.tan,
4443
- codegen: "Math.tan((",
4444
- tex: "\\tan",
4445
- expand: () => Mul.handleDivide(Trig.sin(this.arg), Trig.cos(this.arg))
4446
- },
4447
- csc: {
4448
- eval: arg => {
4449
- return 1 / Math.sin(arg);
4450
- },
4451
- codegen: "(1/Math.sin(",
4452
- tex: "\\csc",
4453
- expand: () => Mul.handleDivide(NumOne, Trig.sin(this.arg))
4454
- },
4455
- sec: {
4456
- eval: arg => {
4457
- return 1 / Math.cos(arg);
3692
+ this.type = void 0;
3693
+ this.arg = void 0;
3694
+ this.exp = void 0;
3695
+ this.func = Trig;
3696
+ this.functions = {
3697
+ sin: {
3698
+ eval: Math.sin,
3699
+ codegen: "Math.sin((",
3700
+ tex: "\\sin",
3701
+ expand: () => this
4458
3702
  },
4459
- codegen: "(1/Math.cos(",
4460
- tex: "\\sec",
4461
- expand: () => Mul.handleDivide(NumOne, Trig.cos(this.arg))
4462
- },
4463
- cot: {
4464
- eval: arg => {
4465
- return 1 / Math.tan(arg);
3703
+ cos: {
3704
+ eval: Math.cos,
3705
+ codegen: "Math.cos((",
3706
+ tex: "\\cos",
3707
+ expand: () => this
4466
3708
  },
4467
- codegen: "(1/Math.tan(",
4468
- tex: "\\cot",
4469
- expand: () => Mul.handleDivide(Trig.cos(this.arg), Trig.sin(this.arg))
4470
- },
4471
- arcsin: {
4472
- eval: Math.asin,
4473
- codegen: "Math.asin((",
4474
- tex: "\\arcsin"
4475
- },
4476
- arccos: {
4477
- eval: Math.acos,
4478
- codegen: "Math.acos((",
4479
- tex: "\\arccos"
4480
- },
4481
- arctan: {
4482
- eval: Math.atan,
4483
- codegen: "Math.atan((",
4484
- tex: "\\arctan"
4485
- },
4486
- arccsc: {
4487
- eval: arg => {
4488
- return Math.asin(1 / arg);
3709
+ tan: {
3710
+ eval: Math.tan,
3711
+ codegen: "Math.tan((",
3712
+ tex: "\\tan",
3713
+ expand: () => Mul.handleDivide(Trig.sin(this.arg), Trig.cos(this.arg))
4489
3714
  },
4490
- codegen: "Math.asin(1/(",
4491
- tex: "\\operatorname{arccsc}"
4492
- },
4493
- arcsec: {
4494
- eval: arg => {
4495
- return Math.acos(1 / arg);
3715
+ csc: {
3716
+ eval: arg => {
3717
+ return 1 / Math.sin(arg);
3718
+ },
3719
+ codegen: "(1/Math.sin(",
3720
+ tex: "\\csc",
3721
+ expand: () => Mul.handleDivide(NumOne, Trig.sin(this.arg))
4496
3722
  },
4497
- codegen: "Math.acos(1/(",
4498
- tex: "\\operatorname{arcsec}"
4499
- },
4500
- arccot: {
4501
- eval: arg => {
4502
- return Math.atan(1 / arg);
3723
+ sec: {
3724
+ eval: arg => {
3725
+ return 1 / Math.cos(arg);
3726
+ },
3727
+ codegen: "(1/Math.cos(",
3728
+ tex: "\\sec",
3729
+ expand: () => Mul.handleDivide(NumOne, Trig.cos(this.arg))
4503
3730
  },
4504
- codegen: "Math.atan(1/(",
4505
- tex: "\\operatorname{arccot}"
4506
- },
4507
- sinh: {
4508
- eval: arg => {
4509
- return (Math.exp(arg) - Math.exp(-arg)) / 2;
3731
+ cot: {
3732
+ eval: arg => {
3733
+ return 1 / Math.tan(arg);
3734
+ },
3735
+ codegen: "(1/Math.tan(",
3736
+ tex: "\\cot",
3737
+ expand: () => Mul.handleDivide(Trig.cos(this.arg), Trig.sin(this.arg))
4510
3738
  },
4511
- codegen: argStr => {
4512
- return "((Math.exp(" + argStr + ") - Math.exp(-(" + argStr + "))) / 2)";
3739
+ arcsin: {
3740
+ eval: Math.asin,
3741
+ codegen: "Math.asin((",
3742
+ tex: "\\arcsin"
4513
3743
  },
4514
- tex: "\\sinh",
4515
- expand: () => this
4516
- },
4517
- cosh: {
4518
- eval: arg => {
4519
- return (Math.exp(arg) + Math.exp(-arg)) / 2;
3744
+ arccos: {
3745
+ eval: Math.acos,
3746
+ codegen: "Math.acos((",
3747
+ tex: "\\arccos"
4520
3748
  },
4521
- codegen: argStr => {
4522
- return "((Math.exp(" + argStr + ") + Math.exp(-(" + argStr + "))) / 2)";
3749
+ arctan: {
3750
+ eval: Math.atan,
3751
+ codegen: "Math.atan((",
3752
+ tex: "\\arctan"
4523
3753
  },
4524
- tex: "\\cosh",
4525
- expand: () => this
4526
- },
4527
- tanh: {
4528
- eval: arg => {
4529
- return (Math.exp(arg) - Math.exp(-arg)) / (Math.exp(arg) + Math.exp(-arg));
3754
+ arccsc: {
3755
+ eval: arg => {
3756
+ return Math.asin(1 / arg);
3757
+ },
3758
+ codegen: "Math.asin(1/(",
3759
+ tex: "\\operatorname{arccsc}"
4530
3760
  },
4531
- codegen: argStr => {
4532
- return "(" + "(Math.exp(" + argStr + ") - Math.exp(-(" + argStr + ")))" + " / " + "(Math.exp(" + argStr + ") + Math.exp(-(" + argStr + ")))" + ")";
3761
+ arcsec: {
3762
+ eval: arg => {
3763
+ return Math.acos(1 / arg);
3764
+ },
3765
+ codegen: "Math.acos(1/(",
3766
+ tex: "\\operatorname{arcsec}"
4533
3767
  },
4534
- tex: "\\tanh",
4535
- expand: () => Mul.handleDivide(Trig.sinh(this.arg), Trig.cosh(this.arg))
4536
- },
4537
- csch: {
4538
- eval: arg => {
4539
- return 2 / (Math.exp(arg) - Math.exp(-arg));
3768
+ arccot: {
3769
+ eval: arg => {
3770
+ return Math.atan(1 / arg);
3771
+ },
3772
+ codegen: "Math.atan(1/(",
3773
+ tex: "\\operatorname{arccot}"
4540
3774
  },
4541
- codegen: argStr => {
4542
- return "(2 / (Math.exp(" + argStr + ") - Math.exp(-(" + argStr + "))))";
3775
+ sinh: {
3776
+ eval: arg => {
3777
+ return (Math.exp(arg) - Math.exp(-arg)) / 2;
3778
+ },
3779
+ codegen: argStr => {
3780
+ return "((Math.exp(" + argStr + ") - Math.exp(-(" + argStr + "))) / 2)";
3781
+ },
3782
+ tex: "\\sinh",
3783
+ expand: () => this
4543
3784
  },
4544
- tex: "\\csch",
4545
- expand: () => Mul.handleDivide(NumOne, Trig.sinh(this.arg))
4546
- },
4547
- sech: {
4548
- eval: arg => {
4549
- return 2 / (Math.exp(arg) + Math.exp(-arg));
3785
+ cosh: {
3786
+ eval: arg => {
3787
+ return (Math.exp(arg) + Math.exp(-arg)) / 2;
3788
+ },
3789
+ codegen: argStr => {
3790
+ return "((Math.exp(" + argStr + ") + Math.exp(-(" + argStr + "))) / 2)";
3791
+ },
3792
+ tex: "\\cosh",
3793
+ expand: () => this
4550
3794
  },
4551
- codegen: argStr => {
4552
- return "(2 / (Math.exp(" + argStr + ") + Math.exp(-(" + argStr + "))))";
3795
+ tanh: {
3796
+ eval: arg => {
3797
+ return (Math.exp(arg) - Math.exp(-arg)) / (Math.exp(arg) + Math.exp(-arg));
3798
+ },
3799
+ codegen: argStr => {
3800
+ return "(" + "(Math.exp(" + argStr + ") - Math.exp(-(" + argStr + ")))" + " / " + "(Math.exp(" + argStr + ") + Math.exp(-(" + argStr + ")))" + ")";
3801
+ },
3802
+ tex: "\\tanh",
3803
+ expand: () => Mul.handleDivide(Trig.sinh(this.arg), Trig.cosh(this.arg))
4553
3804
  },
4554
- tex: "\\sech",
4555
- expand: () => Mul.handleDivide(NumOne, Trig.cosh(this.arg))
4556
- },
4557
- coth: {
4558
- eval: arg => {
4559
- return (Math.exp(arg) + Math.exp(-arg)) / (Math.exp(arg) - Math.exp(-arg));
3805
+ csch: {
3806
+ eval: arg => {
3807
+ return 2 / (Math.exp(arg) - Math.exp(-arg));
3808
+ },
3809
+ codegen: argStr => {
3810
+ return "(2 / (Math.exp(" + argStr + ") - Math.exp(-(" + argStr + "))))";
3811
+ },
3812
+ tex: "\\csch",
3813
+ expand: () => Mul.handleDivide(NumOne, Trig.sinh(this.arg))
4560
3814
  },
4561
- codegen: argStr => {
4562
- return "(" + "(Math.exp(" + argStr + ") + Math.exp(-(" + argStr + ")))" + " / " + "(Math.exp(" + argStr + ") - Math.exp(-(" + argStr + ")))" + ")";
3815
+ sech: {
3816
+ eval: arg => {
3817
+ return 2 / (Math.exp(arg) + Math.exp(-arg));
3818
+ },
3819
+ codegen: argStr => {
3820
+ return "(2 / (Math.exp(" + argStr + ") + Math.exp(-(" + argStr + "))))";
3821
+ },
3822
+ tex: "\\sech",
3823
+ expand: () => Mul.handleDivide(NumOne, Trig.cosh(this.arg))
4563
3824
  },
4564
- tex: "\\coth",
4565
- expand: () => Mul.handleDivide(Trig.cosh(this.arg), Trig.sinh(this.arg))
4566
- }
4567
- };
3825
+ coth: {
3826
+ eval: arg => {
3827
+ return (Math.exp(arg) + Math.exp(-arg)) / (Math.exp(arg) - Math.exp(-arg));
3828
+ },
3829
+ codegen: argStr => {
3830
+ return "(" + "(Math.exp(" + argStr + ") + Math.exp(-(" + argStr + ")))" + " / " + "(Math.exp(" + argStr + ") - Math.exp(-(" + argStr + ")))" + ")";
3831
+ },
3832
+ tex: "\\coth",
3833
+ expand: () => Mul.handleDivide(Trig.cosh(this.arg), Trig.sinh(this.arg))
3834
+ }
3835
+ };
3836
+ this.type = type;
3837
+ this.arg = _arg;
3838
+ this.hints = _extends({}, this.hints, {
3839
+ open: false
3840
+ });
3841
+ }
3842
+ args() {
3843
+ return [this.type, this.arg];
3844
+ }
4568
3845
  isEven() {
4569
- return ___default["default"].contains(["cos", "sec"], this.type);
3846
+ return _.contains(["cos", "sec"], this.type);
4570
3847
  }
4571
3848
  isInverse() {
4572
3849
  return this.type.indexOf("arc") === 0;
4573
3850
  }
4574
3851
  isBasic() {
4575
- return ___default["default"].contains(["sin", "cos"], this.type);
3852
+ return _.contains(["sin", "cos"], this.type);
4576
3853
  }
4577
- eval() {
4578
- let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4579
- let options = arguments.length > 1 ? arguments[1] : undefined;
3854
+ eval(vars = {}, options) {
4580
3855
  var func = this.functions[this.type].eval;
4581
3856
  var arg = this.arg.eval(vars, options);
4582
3857
  return func(arg);
@@ -4621,18 +3896,14 @@ class Trig extends Expr {
4621
3896
  return this;
4622
3897
  }
4623
3898
  }
4624
-
4625
- // TODO(alex): does every new node type need to redefine these?
4626
3899
  needsExplicitMul() {
4627
3900
  return false;
4628
3901
  }
4629
3902
  expand() {
4630
3903
  var trig = this.recurse("expand");
4631
3904
  if (!trig.isInverse()) {
4632
- // e.g. tan(x) -> sin(x)/cos(x)
4633
- // NOTE(kevinb): All non-inverse trig functions have an expand property.
4634
3905
  var expand = trig.functions[trig.type].expand;
4635
- return ___default["default"].bind(expand, trig)();
3906
+ return _.bind(expand, trig)();
4636
3907
  } else {
4637
3908
  return trig;
4638
3909
  }
@@ -4642,10 +3913,8 @@ class Trig extends Expr {
4642
3913
  if (!trig.isInverse() && trig.arg.isNegative()) {
4643
3914
  const arg = trig.arg instanceof Num ? trig.arg.abs() : Mul.handleDivide(trig.arg, NumNeg).collect(options);
4644
3915
  if (trig.isEven()) {
4645
- // e.g. cos(-x) -> cos(x)
4646
3916
  return new Trig(trig.type, arg);
4647
3917
  } else {
4648
- // e.g. sin(-x) -> -sin(x)
4649
3918
  return new Mul(NumNeg, new Trig(trig.type, arg));
4650
3919
  }
4651
3920
  } else {
@@ -4656,7 +3925,6 @@ class Trig extends Expr {
4656
3925
  var type = pair[0];
4657
3926
  var exp = pair[1];
4658
3927
  if (exp && exp.equals(NumNeg)) {
4659
- // e.g. sin^-1(x) -> arcsin(x)
4660
3928
  type = "arc" + type;
4661
3929
  exp = undefined;
4662
3930
  }
@@ -4683,18 +3951,16 @@ class Trig extends Expr {
4683
3951
  }
4684
3952
  }
4685
3953
  class Abs extends Expr {
4686
- arg;
4687
3954
  constructor(arg) {
4688
3955
  super();
3956
+ this.arg = void 0;
3957
+ this.func = Abs;
4689
3958
  this.arg = arg;
4690
3959
  }
4691
- func = Abs;
4692
3960
  args() {
4693
3961
  return [this.arg];
4694
3962
  }
4695
- eval() {
4696
- let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4697
- let options = arguments.length > 1 ? arguments[1] : undefined;
3963
+ eval(vars = {}, options) {
4698
3964
  return Math.abs(this.arg.eval(vars, options));
4699
3965
  }
4700
3966
  codegen() {
@@ -4709,14 +3975,11 @@ class Abs extends Expr {
4709
3975
  collect(options) {
4710
3976
  var abs = this.recurse("collect", options);
4711
3977
  if (abs.arg.isPositive()) {
4712
- // e.g. |2^x| -> 2^x
4713
3978
  return abs.arg;
4714
3979
  } else if (abs.arg instanceof Num) {
4715
- // e.g. |-2| -> 2
4716
3980
  return abs.arg.abs();
4717
3981
  } else if (abs.arg instanceof Mul) {
4718
- // e.g. |-2*pi*x| -> 2*pi*|x|
4719
- var terms = ___default["default"].groupBy(abs.arg.terms, term => {
3982
+ var terms = _.groupBy(abs.arg.terms, term => {
4720
3983
  if (term.isPositive()) {
4721
3984
  return "positive";
4722
3985
  } else if (term instanceof Num) {
@@ -4725,7 +3988,7 @@ class Abs extends Expr {
4725
3988
  return "other";
4726
3989
  }
4727
3990
  });
4728
- var positives = terms.positive.concat(___default["default"].invoke(terms.number, "abs"));
3991
+ var positives = terms.positive.concat(_.invoke(terms.number, "abs"));
4729
3992
  if (terms.other.length) {
4730
3993
  positives.push(new Abs(new Mul(terms.other).flatten()));
4731
3994
  }
@@ -4734,13 +3997,10 @@ class Abs extends Expr {
4734
3997
  return abs;
4735
3998
  }
4736
3999
  }
4737
-
4738
- // this should definitely be behind a super-simplify flag
4739
4000
  expand() {
4740
4001
  var abs = this.recurse("expand");
4741
4002
  if (abs.arg instanceof Mul) {
4742
- // e.g. |xyz| -> |x|*|y|*|z|
4743
- var terms = ___default["default"].map(abs.arg.terms, term => {
4003
+ var terms = _.map(abs.arg.terms, term => {
4744
4004
  return new Abs(term);
4745
4005
  });
4746
4006
  return new Mul(terms);
@@ -4752,19 +4012,25 @@ class Abs extends Expr {
4752
4012
  return true;
4753
4013
  }
4754
4014
  }
4755
-
4756
- /* equation */
4757
4015
  class Eq extends Expr {
4758
- left;
4759
- type; // TODO(kevinb): use an enum for this
4760
- right;
4761
4016
  constructor(left, type, right) {
4762
4017
  super();
4018
+ this.left = void 0;
4019
+ this.type = void 0;
4020
+ this.right = void 0;
4021
+ this.func = Eq;
4022
+ this.signs = {
4023
+ "=": " = ",
4024
+ "<": " < ",
4025
+ ">": " > ",
4026
+ "<>": " \\ne ",
4027
+ "<=": " \\le ",
4028
+ ">=": " \\ge "
4029
+ };
4763
4030
  this.left = left;
4764
4031
  this.type = type;
4765
4032
  this.right = right;
4766
4033
  }
4767
- func = Eq;
4768
4034
  args() {
4769
4035
  return [this.left, this.type, this.right];
4770
4036
  }
@@ -4774,41 +4040,24 @@ class Eq extends Expr {
4774
4040
  print() {
4775
4041
  return this.left.print() + this.type + this.right.print();
4776
4042
  }
4777
- signs = {
4778
- "=": " = ",
4779
- "<": " < ",
4780
- ">": " > ",
4781
- "<>": " \\ne ",
4782
- "<=": " \\le ",
4783
- ">=": " \\ge "
4784
- };
4785
4043
  tex() {
4786
4044
  return this.left.tex() + this.signs[this.type] + this.right.tex();
4787
4045
  }
4788
4046
  normalize() {
4789
4047
  var eq = this.recurse("normalize");
4790
- if (___default["default"].contains([">", ">="], eq.type)) {
4791
- // inequalities should have the smaller side on the left
4048
+ if (_.contains([">", ">="], eq.type)) {
4792
4049
  return new Eq(eq.right, eq.type.replace(">", "<"), eq.left);
4793
4050
  } else {
4794
4051
  return eq;
4795
4052
  }
4796
4053
  }
4797
-
4798
- // convert this equation to an expression set to zero
4799
- // the expression is normalized to a canonical form
4800
- // e.g. y/2=x/4 -> y/2-x/4(=0) -> 2y-x(=0)
4801
- // unless unfactored is specified, will then divide through
4802
- asExpr() {
4803
- let unfactored = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
4054
+ asExpr(unfactored = false) {
4804
4055
  var isZero = expr => {
4805
4056
  return expr instanceof Num && expr.isSimple() && expr.eval() === 0;
4806
4057
  };
4807
-
4808
- // first convert to a sequence of additive terms
4809
4058
  let terms = [];
4810
4059
  if (this.left instanceof Add) {
4811
- terms = ___default["default"].clone(this.left.terms);
4060
+ terms = _.clone(this.left.terms);
4812
4061
  } else if (!isZero(this.left)) {
4813
4062
  terms = [this.left];
4814
4063
  }
@@ -4818,26 +4067,16 @@ class Eq extends Expr {
4818
4067
  terms.push(this.right.negate());
4819
4068
  }
4820
4069
  var isInequality = !this.isEquality();
4821
-
4822
- // Collect over each term individually to transform simple expressions
4823
- // into numbers that might have denominators, taking into account
4824
- // float precision. We have to be very careful to not introduce any
4825
- // irrational floats before asExpr() returns, because by definition
4826
- // they do not have exact denominators...
4827
- terms = ___default["default"].invoke(terms, "collect", {
4070
+ terms = _.invoke(terms, "collect", {
4828
4071
  preciseFloats: true
4829
4072
  });
4830
-
4831
- // ...and we multiply through by every denominator.
4832
4073
  for (var i = 0; i < terms.length; i++) {
4833
4074
  var denominator = terms[i].getDenominator();
4834
-
4835
- // Can't multiply inequalities by non 100% positive factors
4836
4075
  if (isInequality && !denominator.isPositive()) {
4837
4076
  denominator = denominator.asPositiveFactor();
4838
4077
  }
4839
4078
  if (!denominator.equals(NumOne)) {
4840
- terms = ___default["default"].map(terms, term => {
4079
+ terms = _.map(terms, term => {
4841
4080
  return Mul.createOrAppend(term, denominator).simplify({
4842
4081
  once: true,
4843
4082
  preciseFloats: true
@@ -4848,11 +4087,6 @@ class Eq extends Expr {
4848
4087
  var add = new Add(terms).flatten();
4849
4088
  return unfactored ? add : this.divideThrough(add);
4850
4089
  }
4851
-
4852
- // divide through by every common factor in the expression
4853
- // e.g. 2y-4x(=0) -> y-2x(=0)
4854
- // TODO(alex): Make it an option to only divide by variables/expressions
4855
- // guaranteed to be nonzero
4856
4090
  divideThrough(expr) {
4857
4091
  const isInequality = !this.isEquality();
4858
4092
  const simplified = expr.simplify({
@@ -4869,31 +4103,20 @@ class Eq extends Expr {
4869
4103
  const isOne = term => term.equals(NumOne);
4870
4104
  const [adds, others] = partition(terms, isAdd);
4871
4105
  if (adds.length && this.isEquality()) {
4872
- // keep only Adds
4873
- // e.g. 2xy(z+1)(=0) -> z+1(=0)
4874
4106
  return new Mul(adds).flatten();
4875
4107
  }
4876
4108
  let denominator = others;
4877
4109
  if (!adds.length) {
4878
- // if no Adds, keep all variable terms to preserve meaning
4879
- // e.g. 42xyz(=0) -> xyz(=0)
4880
- denominator = ___default["default"].reject(denominator, hasVar);
4110
+ denominator = _.reject(denominator, hasVar);
4881
4111
  }
4882
4112
  if (isInequality) {
4883
- // can't divide inequalities by non 100% positive factors
4884
- // e.g. 42x^2y(z+1)(=0) -> y(z+1)(=0)
4885
- denominator = ___default["default"].invoke(denominator, "asPositiveFactor");
4113
+ denominator = _.invoke(denominator, "asPositiveFactor");
4886
4114
  }
4887
-
4888
- // don't need to divide by one
4889
- denominator = ___default["default"].reject(denominator, isOne);
4890
- denominator = ___default["default"].map(denominator, term => {
4115
+ denominator = _.reject(denominator, isOne);
4116
+ denominator = _.map(denominator, term => {
4891
4117
  return new Pow(term, NumDiv);
4892
4118
  });
4893
4119
  const dividedResult = new Mul(terms.concat(denominator)).collect();
4894
-
4895
- // If the end result is the same as the original factoring,
4896
- // rollback the factoring and discard all intermediate steps.
4897
4120
  if (dividedResult.equals(factored)) {
4898
4121
  return simplified;
4899
4122
  } else {
@@ -4901,10 +4124,9 @@ class Eq extends Expr {
4901
4124
  }
4902
4125
  }
4903
4126
  isEquality() {
4904
- return ___default["default"].contains(["=", "<>"], this.type);
4127
+ return _.contains(["=", "<>"], this.type);
4905
4128
  }
4906
4129
  compare(other) {
4907
- // expression comparisons are handled by Expr.compare()
4908
4130
  if (!(other instanceof Eq)) {
4909
4131
  return false;
4910
4132
  }
@@ -4913,48 +4135,36 @@ class Eq extends Expr {
4913
4135
  if (eq1.type !== eq2.type) {
4914
4136
  return false;
4915
4137
  }
4916
-
4917
- // need to collect to properly factor out common factors
4918
- // e.g x+2x=6 -> 3x=6 -> 3x-6(=0) -> x-2(=0)
4919
- var expr1 = eq1.divideThrough(eq1.asExpr(/* unfactored */true).collect());
4920
- var expr2 = eq2.divideThrough(eq2.asExpr(/* unfactored */true).collect());
4138
+ var expr1 = eq1.divideThrough(eq1.asExpr(true).collect());
4139
+ var expr2 = eq2.divideThrough(eq2.asExpr(true).collect());
4921
4140
  if (eq1.isEquality()) {
4922
- // equals and not-equals can be subtracted either way
4923
4141
  return expr1.compare(expr2) || expr1.compare(Mul.handleNegative(expr2));
4924
4142
  } else {
4925
4143
  return expr1.compare(expr2);
4926
4144
  }
4927
4145
  }
4928
-
4929
- // should only be done after compare() returns true to avoid false positives
4930
4146
  sameForm(other) {
4931
4147
  var eq1 = this.normalize();
4932
4148
  var eq2 = other.normalize();
4933
4149
  var same = eq1.left.sameForm(eq2.left) && eq1.right.sameForm(eq2.right);
4934
4150
  if (eq1.isEquality()) {
4935
- // equals and not-equals can be commutative with respect to the sign
4936
4151
  return same || eq1.left.sameForm(eq2.right) && eq1.right.sameForm(eq2.left);
4937
4152
  } else {
4938
4153
  return same;
4939
4154
  }
4940
4155
  }
4941
-
4942
- // we don't want to override collect because it would turn y=x into y-x(=0)
4943
- // instead, we ask if the equation was in that form, would it be simplified?
4944
4156
  isSimplified() {
4945
- var expr = this.asExpr(/* unfactored */true);
4157
+ var expr = this.asExpr(true);
4946
4158
  var simplified = this.divideThrough(expr).simplify();
4947
4159
  return expr.equals(simplified) && this.left.isSimplified() && this.right.isSimplified();
4948
4160
  }
4949
-
4950
- // Assumptions: Expression is of the form a+bx, and we solve for x
4951
4161
  solveLinearEquationForVariable(variable) {
4952
4162
  var expr = this.asExpr();
4953
4163
  if (!(expr instanceof Add) || expr.terms.length !== 2) {
4954
4164
  throw new Error("Can only handle linear equations of the form " + "a + bx (= 0)");
4955
4165
  }
4956
4166
  var hasVar = term => {
4957
- return term.has(Var) && ___default["default"].contains(term.getVars(), variable.symbol);
4167
+ return term.has(Var) && _.contains(term.getVars(), variable.symbol);
4958
4168
  };
4959
4169
  const termHasVar = hasVar(expr.terms[0]);
4960
4170
  const a = termHasVar ? Mul.handleNegative(expr.terms[1]) : Mul.handleNegative(expr.terms[0]);
@@ -4962,8 +4172,6 @@ class Eq extends Expr {
4962
4172
  return Mul.handleDivide(a, b).simplify();
4963
4173
  }
4964
4174
  }
4965
-
4966
- /* abstract symbol node */
4967
4175
  class Sym extends Expr {
4968
4176
  needsExplicitMul() {
4969
4177
  return false;
@@ -4976,17 +4184,15 @@ class Sym extends Expr {
4976
4184
  }
4977
4185
  }
4978
4186
  }
4979
-
4980
- /* function variable */
4981
4187
  class Func extends Sym {
4982
- symbol;
4983
- arg;
4984
4188
  constructor(symbol, arg) {
4985
4189
  super();
4190
+ this.symbol = void 0;
4191
+ this.arg = void 0;
4192
+ this.func = Func;
4986
4193
  this.symbol = symbol;
4987
4194
  this.arg = arg;
4988
4195
  }
4989
- func = Func;
4990
4196
  args() {
4991
4197
  return [this.symbol, this.arg];
4992
4198
  }
@@ -4996,19 +4202,16 @@ class Func extends Sym {
4996
4202
  tex() {
4997
4203
  return this.symbol + "(" + this.arg.tex() + ")";
4998
4204
  }
4999
- eval() {
5000
- let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5001
- let options = arguments.length > 1 ? arguments[1] : undefined;
4205
+ eval(vars = {}, options) {
5002
4206
  var arg = this.arg;
5003
4207
  var func = vars[this.symbol];
5004
- var newVars = ___default["default"].extend(___default["default"].clone(vars), {
4208
+ var newVars = _.extend(_.clone(vars), {
5005
4209
  x: arg.eval(vars, options)
5006
4210
  });
5007
4211
  var parsedFunc = parse(func, options);
5008
4212
  if (parsedFunc.parsed) {
5009
4213
  return parsedFunc.expr.eval(newVars, options);
5010
4214
  }
5011
- // If parsedFunc isn't actually parsed, return its error
5012
4215
  return parsedFunc;
5013
4216
  }
5014
4217
  codegen() {
@@ -5021,24 +4224,22 @@ class Func extends Sym {
5021
4224
  if (excludeFunc) {
5022
4225
  return this.arg.getVars();
5023
4226
  } else {
5024
- return ___default["default"].union(this.arg.getVars(), [this.symbol]).sort();
4227
+ return _.union(this.arg.getVars(), [this.symbol]).sort();
5025
4228
  }
5026
4229
  }
5027
4230
  getConsts() {
5028
4231
  return this.arg.getConsts();
5029
4232
  }
5030
4233
  }
5031
-
5032
- /* variable */
5033
4234
  class Var extends Sym {
5034
- symbol;
5035
- subscript;
5036
4235
  constructor(symbol, subscript) {
5037
4236
  super();
4237
+ this.symbol = void 0;
4238
+ this.subscript = void 0;
4239
+ this.func = Var;
5038
4240
  this.symbol = symbol;
5039
4241
  this.subscript = subscript;
5040
4242
  }
5041
- func = Var;
5042
4243
  args() {
5043
4244
  return [this.symbol, this.subscript];
5044
4245
  }
@@ -5055,9 +4256,6 @@ class Var extends Sym {
5055
4256
  }
5056
4257
  return this.symbol + sub;
5057
4258
  }
5058
-
5059
- // Provide a way to easily evalate expressions with the common case,
5060
- // subscripts that consist of a single number or symbol e.g. x_a or x_42
5061
4259
  prettyPrint() {
5062
4260
  var sub = this.subscript;
5063
4261
  if (sub && (sub instanceof Num || sub instanceof Sym)) {
@@ -5077,12 +4275,7 @@ class Var extends Sym {
5077
4275
  repr() {
5078
4276
  return "Var(" + this.print() + ")";
5079
4277
  }
5080
- eval() {
5081
- let vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5082
- // @ts-expect-error: values is Vars are strings, but here
5083
- // we expect them to be numbers. We should probably store
5084
- // Var and Func entries separately in the Vars type so that
5085
- // they can be typed correctly.
4278
+ eval(vars = {}, options) {
5086
4279
  return vars[this.prettyPrint()];
5087
4280
  }
5088
4281
  codegen() {
@@ -5095,28 +4288,25 @@ class Var extends Sym {
5095
4288
  return false;
5096
4289
  }
5097
4290
  }
5098
-
5099
- /* constant */
5100
4291
  class Const extends Sym {
5101
- symbol;
5102
4292
  constructor(symbol) {
5103
4293
  super();
4294
+ this.symbol = void 0;
4295
+ this.func = Const;
5104
4296
  this.symbol = symbol;
5105
4297
  }
5106
- func = Const;
5107
4298
  args() {
5108
4299
  return [this.symbol];
5109
4300
  }
5110
4301
  recurse() {
5111
4302
  return this;
5112
4303
  }
5113
- eval() {
4304
+ eval(vars = {}, options) {
5114
4305
  if (this.symbol === "pi") {
5115
4306
  return Math.PI;
5116
4307
  } else if (this.symbol === "e") {
5117
4308
  return Math.E;
5118
4309
  } else {
5119
- // @ts-expect-error: should we throw an error here?
5120
4310
  return undefined;
5121
4311
  }
5122
4312
  }
@@ -5126,7 +4316,6 @@ class Const extends Sym {
5126
4316
  } else if (this.symbol === "e") {
5127
4317
  return "Math.E";
5128
4318
  } else {
5129
- // @ts-expect-error: should we throw an error here?
5130
4319
  return undefined;
5131
4320
  }
5132
4321
  }
@@ -5139,7 +4328,6 @@ class Const extends Sym {
5139
4328
  } else if (this.symbol === "e") {
5140
4329
  return "e";
5141
4330
  } else {
5142
- // @ts-expect-error: should we return this.symbol here?
5143
4331
  return undefined;
5144
4332
  }
5145
4333
  }
@@ -5156,25 +4344,22 @@ class Const extends Sym {
5156
4344
  getConsts() {
5157
4345
  return [this.print()];
5158
4346
  }
5159
- static e = new Const("e");
5160
- static pi = new Const("pi");
5161
4347
  }
5162
-
5163
- /* abstract number node */
4348
+ _class12 = Const;
4349
+ Const.e = new _class12("e");
4350
+ Const.pi = new _class12("pi");
5164
4351
  class Num extends Expr {
5165
- n = 0;
5166
4352
  constructor() {
5167
4353
  super();
5168
- // hints for interpreting and rendering user input
5169
- this.hints = {
5170
- ...this.hints,
4354
+ this.n = 0;
4355
+ this.hints = _extends({}, this.hints, {
5171
4356
  negate: false,
5172
4357
  subtract: false,
5173
4358
  divide: false,
5174
4359
  root: false,
5175
4360
  fraction: false,
5176
4361
  entered: false
5177
- };
4362
+ });
5178
4363
  }
5179
4364
  repr() {
5180
4365
  return this.print();
@@ -5188,17 +4373,9 @@ class Num extends Expr {
5188
4373
  codegen() {
5189
4374
  return this.print();
5190
4375
  }
5191
-
5192
- // takes another Num and returns a new Num
5193
-
5194
- // returns this Num's additive inverse
5195
-
5196
4376
  isSubtract() {
5197
4377
  return Boolean(this.hints.subtract);
5198
4378
  }
5199
-
5200
- // return the absolute value of the number
5201
-
5202
4379
  needsExplicitMul() {
5203
4380
  return true;
5204
4381
  }
@@ -5211,19 +4388,10 @@ class Num extends Expr {
5211
4388
  asPositiveFactor() {
5212
4389
  return this.isPositive() ? this : this.abs();
5213
4390
  }
5214
-
5215
- // whether a number is considered simple (one term)
5216
- // e.g. for reals, ints and floats are simple
5217
-
5218
- // Based on http://stackoverflow.com/a/10454560/2571482
5219
4391
  getDecimalPlaces() {
5220
4392
  var match = ("" + this.n).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
5221
4393
  if (match) {
5222
- return Math.max(0,
5223
- // Number of digits right of decimal point
5224
- (match[1] ? match[1].length : 0) - (
5225
- // Adjust for scientific notation
5226
- match[2] ? +match[2] : 0));
4394
+ return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
5227
4395
  } else {
5228
4396
  return 0;
5229
4397
  }
@@ -5237,16 +4405,10 @@ class Num extends Expr {
5237
4405
  return NumNeg;
5238
4406
  }
5239
4407
  }
5240
-
5241
- // find the greatest common denominator
5242
4408
  static findGCD(a, b) {
5243
4409
  var mod;
5244
4410
  a = Math.abs(a);
5245
4411
  b = Math.abs(b);
5246
-
5247
- // Euclid's method doesn't handle non-integers very well. For now
5248
- // we just say we can't pull out a common factor. It might be
5249
- // reasonable to do better than this in the future.
5250
4412
  if (a !== Math.floor(a) || b !== Math.floor(b)) {
5251
4413
  return 1;
5252
4414
  }
@@ -5257,26 +4419,19 @@ class Num extends Expr {
5257
4419
  }
5258
4420
  return a;
5259
4421
  }
5260
- static min() {
5261
- for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
5262
- args[_key3] = arguments[_key3];
5263
- }
5264
- return ___default["default"].min(args, num => num.eval());
4422
+ static min(...args) {
4423
+ return _.min(args, num => num.eval());
5265
4424
  }
5266
- static max() {
5267
- for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
5268
- args[_key4] = arguments[_key4];
5269
- }
5270
- return ___default["default"].max(args, num => num.eval());
4425
+ static max(...args) {
4426
+ return _.max(args, num => num.eval());
5271
4427
  }
5272
4428
  }
5273
-
5274
- /* rational number (n: numerator, d: denominator) */
5275
4429
  class Rational extends Num {
5276
- n;
5277
- d;
5278
4430
  constructor(numerator, denominator) {
5279
4431
  super();
4432
+ this.n = void 0;
4433
+ this.d = void 0;
4434
+ this.func = Rational;
5280
4435
  var n = numerator;
5281
4436
  var d = denominator;
5282
4437
  if (d < 0) {
@@ -5286,7 +4441,6 @@ class Rational extends Num {
5286
4441
  this.n = n;
5287
4442
  this.d = d;
5288
4443
  }
5289
- func = Rational;
5290
4444
  args() {
5291
4445
  return [this.n, this.d];
5292
4446
  }
@@ -5331,14 +4485,9 @@ class Rational extends Num {
5331
4485
  return new Rational(Math.abs(this.n), this.d);
5332
4486
  }
5333
4487
  findGCD(factor) {
5334
- // Attempt to factor out common numerators and denominators to return
5335
- // a Rational instead of a Float
5336
4488
  if (factor instanceof Rational) {
5337
- // For more background, see
5338
- // http://math.stackexchange.com/questions/151081/gcd-of-rationals
5339
4489
  var numerator = Num.findGCD(this.n * factor.d, factor.n * this.d);
5340
4490
  var denominator = this.d * factor.d;
5341
- // Create the rational, then call .collect() to simplify it
5342
4491
  return new Rational(numerator, denominator).collect();
5343
4492
  } else if (factor instanceof Int) {
5344
4493
  return new Rational(Num.findGCD(this.n, factor.n), this.d);
@@ -5346,8 +4495,6 @@ class Rational extends Num {
5346
4495
  return factor.findGCD(this);
5347
4496
  }
5348
4497
  }
5349
-
5350
- // for now, assuming that exp is a Num
5351
4498
  raiseToThe(exp) {
5352
4499
  if (exp instanceof Int) {
5353
4500
  var positive = exp.eval() > 0;
@@ -5373,13 +4520,11 @@ class Rational extends Num {
5373
4520
  return this;
5374
4521
  }
5375
4522
  }
5376
-
5377
- /* integer (n: numerator/number) */
5378
4523
  class Int extends Rational {
5379
4524
  constructor(number) {
5380
4525
  super(number, 1);
4526
+ this.func = Int;
5381
4527
  }
5382
- func = Int;
5383
4528
  args() {
5384
4529
  return [this.n];
5385
4530
  }
@@ -5409,24 +4554,19 @@ class Int extends Rational {
5409
4554
  return new Int(n).addHint("entered");
5410
4555
  }
5411
4556
  }
5412
-
5413
- /* float (n: number) */
5414
4557
  class Float extends Num {
5415
- n;
5416
4558
  constructor(number) {
5417
4559
  super();
4560
+ this.n = void 0;
4561
+ this.func = Float;
5418
4562
  this.n = number;
5419
4563
  }
5420
- func = Float;
5421
4564
  args() {
5422
4565
  return [this.n];
5423
4566
  }
5424
4567
  eval() {
5425
4568
  return this.n;
5426
4569
  }
5427
-
5428
- // TODO(alex): when we internationalize number parsing/display
5429
- // we should make sure to use the appropriate decimal mark here
5430
4570
  print() {
5431
4571
  return this.n.toString();
5432
4572
  }
@@ -5448,8 +4588,6 @@ class Float extends Num {
5448
4588
  }
5449
4589
  }
5450
4590
  collect(options) {
5451
- // We used to simplify Floats to Ints here whenever possible, but no
5452
- // longer do so in order to preserve significant figures.
5453
4591
  return this;
5454
4592
  }
5455
4593
  negate() {
@@ -5465,8 +4603,6 @@ class Float extends Num {
5465
4603
  return factor.findGCD(this);
5466
4604
  }
5467
4605
  }
5468
-
5469
- // for now, assuming that exp is a Num
5470
4606
  raiseToThe(exp, options) {
5471
4607
  if (options && options.preciseFloats && exp instanceof Int && exp.n > 1) {
5472
4608
  return Float.toDecimalPlaces(new Pow(this, exp).eval(), this.getDecimalPlaces() * exp.n);
@@ -5474,8 +4610,6 @@ class Float extends Num {
5474
4610
  return new Float(new Pow(this, exp).eval()).collect();
5475
4611
  }
5476
4612
  }
5477
-
5478
- // only to be used on non-repeating decimals (e.g. user-provided)
5479
4613
  asRational() {
5480
4614
  var parts = this.n.toString().split(".");
5481
4615
  if (parts.length === 1) {
@@ -5495,9 +4629,6 @@ class Float extends Num {
5495
4629
  static create(n) {
5496
4630
  return new Float(n).addHint("entered");
5497
4631
  }
5498
-
5499
- // Account for floating point imprecision by explicitly controlling the
5500
- // number of decimal places in common operations (e.g. +, *, ^)
5501
4632
  static toDecimalPlaces(n, places) {
5502
4633
  return new Float(+n.toFixed(Math.min(places, 20))).collect();
5503
4634
  }
@@ -5509,13 +4640,9 @@ const NumSqrt = new Rational(1, 2).addHint("root");
5509
4640
  const NumZero = new Int(0);
5510
4641
  const NumOne = new Int(1);
5511
4642
  const NumTen = new Int(10);
5512
- var parseError = function (str, hash) {
5513
- // return int location of parsing error
4643
+ var parseError = function parseError(str, hash) {
5514
4644
  throw new Error(hash.loc.first_column);
5515
4645
  };
5516
-
5517
- // expose concrete nodes to parser scope
5518
- // see http://zaach.github.io/jison/docs/#sharing-scope
5519
4646
  parser.yy = {
5520
4647
  Add: Add,
5521
4648
  Mul: Mul,
@@ -5532,28 +4659,22 @@ parser.yy = {
5532
4659
  parseError: parseError,
5533
4660
  constants: ["e"],
5534
4661
  symbolLexer: function (symbol) {
5535
- if (___default["default"].contains(parser.yy.constants, symbol)) {
4662
+ if (_.contains(parser.yy.constants, symbol)) {
5536
4663
  return "CONST";
5537
- } else if (___default["default"].contains(parser.yy.functions, symbol)) {
4664
+ } else if (_.contains(parser.yy.functions, symbol)) {
5538
4665
  return "FUNC";
5539
4666
  } else {
5540
4667
  return "VAR";
5541
4668
  }
5542
4669
  }
5543
4670
  };
5544
- const parse = function (input, options) {
4671
+ const parse = function parse(input, options) {
5545
4672
  try {
5546
4673
  if (options && options.functions) {
5547
- // reserve the symbol "i" for complex numbers
5548
- parser.yy.functions = ___default["default"].without(options.functions, "i");
4674
+ parser.yy.functions = _.without(options.functions, "i");
5549
4675
  } else {
5550
4676
  parser.yy.functions = [];
5551
4677
  }
5552
-
5553
- // If ',' is the decimal dividor in your country, replace any ','s
5554
- // with '.'s.
5555
- // This isn't perfect, since the output will all still have '.'s.
5556
- // TODO(jack): Fix the output to have ','s in this case
5557
4678
  if (options && options.decimal_separator) {
5558
4679
  input = input.split(options.decimal_separator).join(".");
5559
4680
  }
@@ -5569,29 +4690,20 @@ const parse = function (input, options) {
5569
4690
  };
5570
4691
  }
5571
4692
  };
5572
-
5573
- /* unit */
5574
4693
  class Unit extends Sym {
5575
- symbol;
5576
4694
  constructor(symbol) {
5577
4695
  super();
4696
+ this.symbol = void 0;
4697
+ this.func = Unit;
5578
4698
  this.symbol = symbol;
5579
4699
  }
5580
- func = Unit;
5581
4700
  args() {
5582
4701
  return [this.symbol];
5583
4702
  }
5584
4703
  recurse() {
5585
4704
  return this;
5586
4705
  }
5587
- eval() {
5588
- // This is called when comparing units. A unit doesn't affect the
5589
- // numerical value of its coefficient, so this needs to be 1.
5590
- //
5591
- // On the other hand, things must not evaluate to the same thing if
5592
- // they don't have the same type. I believe that's also true - form is
5593
- // checked before numerical equivalence. I do not know where, though.
5594
- // However, there are a couple tests checking this.
4706
+ eval(vars = {}, options) {
5595
4707
  return 1;
5596
4708
  }
5597
4709
  getUnits() {
@@ -5609,42 +4721,26 @@ class Unit extends Sym {
5609
4721
  tex() {
5610
4722
  return this.symbol;
5611
4723
  }
5612
-
5613
- // Simplify units by replacing prefixes with multiplication
5614
4724
  collect(options) {
5615
- if (___default["default"](baseUnits).has(this.symbol)) {
4725
+ if (_(baseUnits).has(this.symbol)) {
5616
4726
  return this;
5617
- } else if (___default["default"](derivedUnits).has(this.symbol)) {
4727
+ } else if (_(derivedUnits).has(this.symbol)) {
5618
4728
  return derivedUnits[this.symbol].conversion;
5619
4729
  } else {
5620
4730
  throw new Error("could not understand unit: " + this.symbol);
5621
4731
  }
5622
4732
  }
5623
4733
  }
5624
-
5625
- // If possible, replace unit prefixes with a multiplication.
5626
- //
5627
- // "g" -> Unit("g")
5628
- // "kg" -> 1000 * Unit("g")
5629
- var unprefixify = function (symbol) {
5630
- if (___default["default"](baseUnits).has(symbol) || ___default["default"](derivedUnits).has(symbol)) {
4734
+ var unprefixify = function unprefixify(symbol) {
4735
+ if (_(baseUnits).has(symbol) || _(derivedUnits).has(symbol)) {
5631
4736
  return new Unit(symbol);
5632
4737
  }
5633
-
5634
- // check for prefix
5635
- var prefix = ___default["default"](___default["default"](siPrefixes).keys()).find(testPrefix => {
4738
+ var prefix = _(_(siPrefixes).keys()).find(testPrefix => {
5636
4739
  return new RegExp("^" + testPrefix).test(symbol);
5637
4740
  });
5638
4741
  if (prefix) {
5639
4742
  var base = symbol.replace(new RegExp("^" + prefix), "");
5640
-
5641
- // It's okay to be here if either:
5642
- // * `base` is a base unit (the seven units listed in baseUnits)
5643
- // * `base` is a derived unit which allows prefixes
5644
- //
5645
- // Otherwise, we're trying to parse a unit label which is not
5646
- // allowed (mwk, mBTU, etc).
5647
- if (___default["default"](baseUnits).has(base) || derivedUnits[base] && derivedUnits[base].prefixes === hasPrefixes) {
4743
+ if (_(baseUnits).has(base) || derivedUnits[base] && derivedUnits[base].prefixes === hasPrefixes) {
5648
4744
  return new Mul(siPrefixes[prefix], new Unit(base));
5649
4745
  } else {
5650
4746
  throw new Error(base + " does not allow prefixes");
@@ -5653,36 +4749,18 @@ var unprefixify = function (symbol) {
5653
4749
  return new Unit(symbol);
5654
4750
  }
5655
4751
  };
5656
- const unitParse = function (input) {
4752
+ const unitParse = function unitParse(input) {
5657
4753
  try {
5658
4754
  var parseResult = unitParser.parse(input);
5659
-
5660
- // parseResult looks like:
5661
- // {
5662
- // magnitude: "5",
5663
- // unit: {
5664
- // num: [
5665
- // { name: "s", pow: 2 }
5666
- // ],
5667
- // denom: [
5668
- // { name: "kg", pow: 1 }
5669
- // ]
5670
- // }
5671
- // }
5672
- //
5673
- // denom is optionally null
5674
-
5675
4755
  const unitArray = [];
5676
- ___default["default"](parseResult.unit.num).each(unitSpec => {
4756
+ _(parseResult.unit.num).each(unitSpec => {
5677
4757
  unitArray.push(new Pow(unprefixify(unitSpec.name), new Int(unitSpec.pow)));
5678
4758
  });
5679
- ___default["default"](parseResult.unit.denom).each(unitSpec => {
4759
+ _(parseResult.unit.denom).each(unitSpec => {
5680
4760
  unitArray.push(new Pow(unprefixify(unitSpec.name), new Int(-1 * unitSpec.pow)));
5681
4761
  });
5682
4762
  var unit = new Mul(unitArray).flatten();
5683
4763
  if (parseResult.type === "unitMagnitude") {
5684
- // in the first case we have a magnitude coefficient as well as the
5685
- // unit itself.
5686
4764
  var coefArray = [new Float(+parseResult.magnitude), ...unitArray];
5687
4765
  var expr = new Mul(coefArray);
5688
4766
  return {
@@ -5693,7 +4771,6 @@ const unitParse = function (input) {
5693
4771
  type: parseResult.type
5694
4772
  };
5695
4773
  } else {
5696
- // in the second case it's just the unit with no magnitude.
5697
4774
  return {
5698
4775
  parsed: true,
5699
4776
  unit: unit,
@@ -5709,7 +4786,6 @@ const unitParse = function (input) {
5709
4786
  };
5710
4787
  var baseUnits = {
5711
4788
  m: new Unit("m"),
5712
- // Note: kg is the SI base unit but we use g for consistency
5713
4789
  g: new Unit("g"),
5714
4790
  s: new Unit("s"),
5715
4791
  A: new Unit("A"),
@@ -5734,14 +4810,11 @@ var siPrefixes = {
5734
4810
  T: new Pow(new Int(10), new Int(12)),
5735
4811
  P: new Pow(new Int(10), new Int(15)),
5736
4812
  E: new Pow(new Int(10), new Int(18)),
5737
- // http://en.wikipedia.org/wiki/Metric_prefix#.22Hella.22_prefix_proposal
5738
4813
  hella: new Pow(new Int(10), new Int(27))
5739
4814
  };
5740
-
5741
- // Use these two values to mark a unit as either SI-prefixable or not.
5742
4815
  const hasPrefixes = "hasPrefixes";
5743
4816
  const hasntPrefixes = "hasntPrefixes";
5744
- const makeAlias = function (str, prefixes) {
4817
+ const makeAlias = function makeAlias(str, prefixes) {
5745
4818
  var splits = str.split("|");
5746
4819
  var coefficientStr = splits[0].trim();
5747
4820
  var unitsStr = splits[1].trim();
@@ -5762,35 +4835,9 @@ const makeAlias = function (str, prefixes) {
5762
4835
  prefixes: prefixes
5763
4836
  };
5764
4837
  };
5765
-
5766
- // This is a mapping of derived units (or different names for a unit) to their
5767
- // definitions. For example, an inch is defined as 0.0254 m.
5768
- //
5769
- // Definitions don't need to be in terms of base units. For example, tsp is
5770
- // defined in terms of tbsp (which is defined in terms of cup -> gal -> L ->
5771
- // m^3). However, units must get simpler. I.e. there's no loop checking.
5772
- //
5773
- // makeAlias takes two parameters:
5774
- // * a string specifying the simplification to perform
5775
- // - a required pipe separates the constant factor from the base units
5776
- // - the constant factor is parsed by KAS
5777
- // - the base units are in a simple format which disallows exponents and
5778
- // requires multiplicands to be space-separated ("m m" rather than "m^2)
5779
- // with an optional "/" separating numerator and denominator
5780
- // - prefixes are not allowed to be used in the converted to units
5781
- // (note that this restriction, the format of the string, and the choice to
5782
- // use a string in the first place are made out of laziness to minimize
5783
- // both typing and parsing)
5784
- // * a boolean specifying whether or not it's acceptable to use SI units
5785
- //
5786
- // Where possible, these units are taken from "The International System of
5787
- // Units (SI)" 8th edition (2006).
5788
4838
  var derivedUnits = {
5789
- // mass
5790
- // The atomic mass unit / dalton.
5791
4839
  Da: makeAlias("1.6605388628 x 10^-24 | g", hasPrefixes),
5792
4840
  u: makeAlias("| Da", hasntPrefixes),
5793
- // length
5794
4841
  meter: makeAlias("| m", hasntPrefixes),
5795
4842
  meters: makeAlias("| m", hasntPrefixes),
5796
4843
  in: makeAlias("254 / 10000 | m", hasntPrefixes),
@@ -5801,43 +4848,32 @@ var derivedUnits = {
5801
4848
  nmi: makeAlias("1852 | m", hasntPrefixes),
5802
4849
  Å: makeAlias("10^-10 | m", hasntPrefixes),
5803
4850
  pc: makeAlias("3.0857 x 10^16 | m", hasntPrefixes),
5804
- // time
5805
4851
  min: makeAlias("60 | s", hasntPrefixes),
5806
4852
  hr: makeAlias("3600 | s", hasntPrefixes),
5807
4853
  sec: makeAlias("| s", hasntPrefixes),
5808
- // TODO(joel) make day work
5809
4854
  day: makeAlias("86400 | s", hasntPrefixes),
5810
4855
  wk: makeAlias("604800 | s", hasntPrefixes),
5811
4856
  fortnight: makeAlias("14 | day", hasntPrefixes),
5812
4857
  shake: makeAlias("10^-8 | s", hasntPrefixes),
5813
4858
  olympiad: makeAlias("126200000 | s", hasntPrefixes),
5814
- // temperature
5815
4859
  "°C": makeAlias("1 | K", hasntPrefixes),
5816
4860
  "°F": makeAlias("5/9 | K", hasntPrefixes),
5817
4861
  "°R": makeAlias("5/9 | K", hasntPrefixes),
5818
- // electric charge
5819
4862
  e: makeAlias("1.6021765314 x 10^-19 | C", hasntPrefixes),
5820
- // speed
5821
4863
  c: makeAlias("299792458 | m / s", hasntPrefixes),
5822
4864
  kn: makeAlias("514/1000 | m / s", hasntPrefixes),
5823
4865
  kt: makeAlias("| kn", hasntPrefixes),
5824
4866
  knot: makeAlias("| kn", hasntPrefixes),
5825
- // energy
5826
4867
  J: makeAlias("| N m", hasPrefixes),
5827
4868
  BTU: makeAlias("1060 | J", hasntPrefixes),
5828
4869
  cal: makeAlias("4184 / 1000 | J", hasPrefixes),
5829
4870
  eV: makeAlias("1.602176514 x 10^-19 | J", hasPrefixes),
5830
4871
  erg: makeAlias("10^−7 | J", hasPrefixes),
5831
- // power
5832
4872
  W: makeAlias("| J / s", hasPrefixes),
5833
4873
  "H-e": makeAlias("80 | W", hasntPrefixes),
5834
- // force
5835
4874
  N: makeAlias("1000 | g m / s s", hasPrefixes),
5836
- // "lb": makeAlias("4448 / 1000 | N", hasntPrefixes),
5837
- // 4.4482216152605
5838
4875
  lb: makeAlias("4448221615 / 1000000000 | N", hasntPrefixes),
5839
4876
  dyn: makeAlias("10^-5 | N", hasntPrefixes),
5840
- // pressure
5841
4877
  Pa: makeAlias("1 | N / m m m", hasPrefixes),
5842
4878
  bar: makeAlias("10^5 | Pa", hasPrefixes),
5843
4879
  "㏔": makeAlias("1/1000 | bar", hasntPrefixes),
@@ -5845,7 +4881,6 @@ var derivedUnits = {
5845
4881
  atm: makeAlias("101325 | Pa", hasntPrefixes),
5846
4882
  Torr: makeAlias("1/760 | atm", hasntPrefixes),
5847
4883
  mmHg: makeAlias("| Torr", hasntPrefixes),
5848
- // area
5849
4884
  ha: makeAlias("10^4 | m m", hasntPrefixes),
5850
4885
  b: makeAlias("10^−28 | m m", hasPrefixes),
5851
4886
  barn: makeAlias("| b", hasPrefixes),
@@ -5853,7 +4888,6 @@ var derivedUnits = {
5853
4888
  skilodge: makeAlias("10^-31 | m m", hasntPrefixes),
5854
4889
  outhouse: makeAlias("10^-34 | m m", hasntPrefixes),
5855
4890
  shed: makeAlias("10^-52 | m m", hasntPrefixes),
5856
- // volume
5857
4891
  L: makeAlias("1/1000 | m m m", hasPrefixes),
5858
4892
  gal: makeAlias("3785/1000 | L", hasPrefixes),
5859
4893
  cup: makeAlias("1/16 | gal", hasntPrefixes),
@@ -5866,25 +4900,17 @@ var derivedUnits = {
5866
4900
  "fl. oz.": makeAlias("1/8 | cup", hasntPrefixes),
5867
4901
  tbsp: makeAlias("1/16 | cup", hasntPrefixes),
5868
4902
  tsp: makeAlias("1/3 | tbsp", hasntPrefixes),
5869
- // rotational
5870
- // "rad":
5871
4903
  rev: makeAlias("2 pi | rad", hasntPrefixes),
5872
4904
  deg: makeAlias("180 pi | rad", hasntPrefixes),
5873
4905
  "°": makeAlias("| deg", hasntPrefixes),
5874
4906
  arcminute: makeAlias("1/60 | deg", hasntPrefixes),
5875
4907
  arcsec: makeAlias("1/3600 | deg", hasntPrefixes),
5876
- // dimensionless
5877
- // "B": makeAlias("10 | dB", hasntPrefixes), // XXX danger - logarithmic
5878
- // "dB"
5879
- // "nP"
5880
4908
  Hu: makeAlias("1000 | dB", hasPrefixes),
5881
4909
  dozen: makeAlias("12 |", hasntPrefixes),
5882
- // XXX
5883
4910
  mol: makeAlias("6.0221412927 x 10^23 |", hasPrefixes),
5884
4911
  "%": makeAlias("1/100 |", hasntPrefixes),
5885
4912
  percent: makeAlias("| %", hasntPrefixes),
5886
4913
  ppm: makeAlias("1/1000000 |", hasntPrefixes),
5887
- // electric / magnetic
5888
4914
  V: makeAlias("1000 | g m m / s s C", hasPrefixes),
5889
4915
  C: makeAlias("| A s", hasPrefixes),
5890
4916
  ampere: makeAlias("| A", hasntPrefixes),
@@ -5894,8 +4920,6 @@ var derivedUnits = {
5894
4920
  H: makeAlias("| ohm s", hasPrefixes),
5895
4921
  T: makeAlias("1000 | g / C s", hasPrefixes),
5896
4922
  Wb: makeAlias("1000 | g m m / C s", hasPrefixes),
5897
- // photometry
5898
- // TODO not sure this is right
5899
4923
  lm: makeAlias("pi x 10^4 | cd / m m", hasntPrefixes),
5900
4924
  lx: makeAlias("| lm / m m", hasntPrefixes),
5901
4925
  nit: makeAlias("| cd / m m", hasntPrefixes),
@@ -5909,38 +4933,17 @@ var derivedUnits = {
5909
4933
  sk: makeAlias("10^-7 | lm", hasntPrefixes),
5910
4934
  skot: makeAlias("| sk", hasntPrefixes),
5911
4935
  bril: makeAlias("10^-11 | lm", hasntPrefixes),
5912
- // other
5913
4936
  Hz: makeAlias("| / s", hasPrefixes)
5914
4937
  };
5915
4938
  const Zero = NumZero;
5916
4939
  const One = NumOne;
5917
4940
 
5918
- /**
5919
- * Compares two expressions for equality.
5920
- *
5921
- * Assumes that both expressions have already been parsed.
5922
- */
5923
- // TODO(alex): be able to pass a random() function to compare()
5924
- const compare = function (expr1, expr2) {
5925
- let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
4941
+ const compare = function compare(expr1, expr2, options = {}) {
5926
4942
  const defaults = {
5927
4943
  form: false,
5928
4944
  simplify: false
5929
4945
  };
5930
-
5931
- /* Options that could be added in the future:
5932
- * - Allow ratios: e.g. 3/1 and 3 should both be accepted for something
5933
- * like slope
5934
- * - Allow student to choose their own variable names
5935
- */
5936
- const optionsWithDefaults = {
5937
- ...defaults,
5938
- ...options
5939
- };
5940
-
5941
- // TODO(CP-1614): Figure out how to make these messages translatable
5942
-
5943
- // Variable check
4946
+ const optionsWithDefaults = _extends({}, defaults, options);
5944
4947
  const vars = expr1.sameVars(expr2);
5945
4948
  if (!vars.equal) {
5946
4949
  let message;
@@ -5956,24 +4959,18 @@ const compare = function (expr1, expr2) {
5956
4959
  message: message
5957
4960
  };
5958
4961
  }
5959
-
5960
- // Semantic check
5961
4962
  if (!expr1.compare(expr2)) {
5962
4963
  return {
5963
4964
  equal: false,
5964
4965
  message: null
5965
4966
  };
5966
4967
  }
5967
-
5968
- // Syntactic check
5969
4968
  if (optionsWithDefaults.form && !expr1.sameForm(expr2)) {
5970
4969
  return {
5971
4970
  equal: false,
5972
4971
  message: "Your answer is not in the correct form."
5973
4972
  };
5974
4973
  }
5975
-
5976
- // Syntactic check
5977
4974
  if (optionsWithDefaults.simplify && !expr1.isSimplified()) {
5978
4975
  return {
5979
4976
  equal: false,
@@ -5986,24 +4983,5 @@ const compare = function (expr1, expr2) {
5986
4983
  };
5987
4984
  };
5988
4985
 
5989
- exports.Abs = Abs;
5990
- exports.Add = Add;
5991
- exports.Const = Const;
5992
- exports.Eq = Eq;
5993
- exports.Float = Float;
5994
- exports.Func = Func;
5995
- exports.Int = Int;
5996
- exports.Log = Log;
5997
- exports.Mul = Mul;
5998
- exports.One = One;
5999
- exports.Pow = Pow;
6000
- exports.Rational = Rational;
6001
- exports.Trig = Trig;
6002
- exports.Unit = Unit;
6003
- exports.Var = Var;
6004
- exports.Zero = Zero;
6005
- exports.compare = compare;
6006
- exports.libVersion = libVersion;
6007
- exports.parse = parse;
6008
- exports.unitParse = unitParse;
4986
+ export { Abs, Add, Const, Eq, Float, Func, Int, Log, Mul, One, Pow, Rational, Trig, Unit, Var, Zero, compare, libVersion, parse, unitParse };
6009
4987
  //# sourceMappingURL=index.js.map