@khanacademy/kas 0.2.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/nodes.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /* eslint-disable prettier/prettier */
2
2
  /* eslint-disable import/order */
3
3
  /* TODO(charlie): fix these lint errors (http://eslint.org/docs/rules): */
4
- /* eslint-disable indent, no-undef, no-var, one-var, no-dupe-keys, no-new-func, no-redeclare, no-unused-vars, comma-dangle, max-len, prefer-spread, space-infix-ops, space-unary-ops */
4
+ /* eslint-disable indent, no-undef, no-var, one-var, no-dupe-keys, no-new-func, no-redeclare, @typescript-eslint/no-unused-vars, comma-dangle, max-len, prefer-spread, space-infix-ops, space-unary-ops */
5
5
  import _ from "underscore";
6
6
 
7
- import {unitParser} from "./__genfiles__/unitparser.js";
8
- import {parser} from "./__genfiles__/parser.js";
7
+ import {unitParser} from "./__genfiles__/unitparser";
8
+ import {parser} from "./__genfiles__/parser";
9
9
 
10
10
  /* The node hierarcy is as follows:
11
11
 
@@ -39,22 +39,28 @@ import {parser} from "./__genfiles__/parser.js";
39
39
  /* non user-facing functions */
40
40
 
41
41
  // assert that all abstract methods have been overridden
42
- var abstract = function() {
42
+ var abstract = function () {
43
43
  // Try to give people a bit of information when this happens
44
- throw new Error("Abstract method - must override for expr: " +
44
+ throw new Error(
45
+ "Abstract method - must override for expr: " +
45
46
  // eslint-disable-next-line @babel/no-invalid-this
46
- this.print());
47
+ this.print(),
48
+ );
47
49
  };
48
50
 
49
51
  // throw an error that is meant to be caught by the test suite (not user facing)
50
- var error = function(message) { throw new Error(message); };
52
+ var error = function (message) {
53
+ throw new Error(message);
54
+ };
51
55
 
52
56
  // reliably detect NaN
53
- var isNaN = function(object) { return object !== object; };
57
+ var isNaN = function (object) {
58
+ return object !== object;
59
+ };
54
60
 
55
61
  // return a random float between min (inclusive) and max (exclusive),
56
62
  // not that inclusivity means much, probabilistically, on floats
57
- var randomFloat = function(min, max) {
63
+ var randomFloat = function (min, max) {
58
64
  var extent = max - min;
59
65
  return Math.random() * extent + min;
60
66
  };
@@ -63,12 +69,10 @@ var randomFloat = function(min, max) {
63
69
  var ITERATIONS = 12;
64
70
  var TOLERANCE = 9; // decimal places
65
71
 
66
-
67
72
  /* abstract base expression node */
68
73
  function Expr() {}
69
74
 
70
75
  _.extend(Expr.prototype, {
71
-
72
76
  // this node's immediate constructor
73
77
  func: abstract,
74
78
 
@@ -76,16 +80,16 @@ _.extend(Expr.prototype, {
76
80
  args: abstract,
77
81
 
78
82
  // make a new node with the given arguments
79
- construct: function(args) {
83
+ construct: function (args) {
80
84
  var instance = new this.func();
81
85
  this.func.apply(instance, args);
82
86
  return instance;
83
87
  },
84
88
 
85
89
  // an abstraction for chainable, bottom-up recursion
86
- recurse: function(method) {
90
+ recurse: function (method) {
87
91
  var passed = Array.prototype.slice.call(arguments, 1);
88
- var args = _.map(this.args(), function(arg) {
92
+ var args = _.map(this.args(), function (arg) {
89
93
  return _.isString(arg) ? arg : arg[method].apply(arg, passed);
90
94
  });
91
95
  return this.construct(args);
@@ -96,7 +100,7 @@ _.extend(Expr.prototype, {
96
100
 
97
101
  codegen: abstract,
98
102
 
99
- compile: function() {
103
+ compile: function () {
100
104
  var code = this.codegen();
101
105
  try {
102
106
  return new Function("vars", "return " + code + ";");
@@ -114,13 +118,12 @@ _.extend(Expr.prototype, {
114
118
  tex: abstract,
115
119
 
116
120
  // returns a TeX string, modified by the given options
117
- asTex: function(options) {
118
-
121
+ asTex: function (options) {
119
122
  options = options || {};
120
123
  _.defaults(options, {
121
124
  display: true,
122
125
  dynamic: true,
123
- times: false
126
+ times: false,
124
127
  });
125
128
 
126
129
  var tex = this.tex();
@@ -141,7 +144,7 @@ _.extend(Expr.prototype, {
141
144
 
142
145
  // returns the name of this expression's constructor as a string
143
146
  // only used for testing and debugging (the ugly regex is for IE8)
144
- name: function() {
147
+ name: function () {
145
148
  if (this.func.name) {
146
149
  return this.func.name;
147
150
  } else {
@@ -150,37 +153,55 @@ _.extend(Expr.prototype, {
150
153
  },
151
154
 
152
155
  // returns a string representing current node structure
153
- repr: function() {
154
- return this.name() + "(" + _.map(this.args(), function(arg) {
155
- return _.isString(arg) ? arg : arg.repr();
156
- }).join(",") + ")";
156
+ repr: function () {
157
+ return (
158
+ this.name() +
159
+ "(" +
160
+ _.map(this.args(), function (arg) {
161
+ return _.isString(arg) ? arg : arg.repr();
162
+ }).join(",") +
163
+ ")"
164
+ );
157
165
  },
158
166
 
159
167
  // removes all negative signs
160
- strip: function() { return this.recurse("strip"); },
168
+ strip: function () {
169
+ return this.recurse("strip");
170
+ },
161
171
 
162
172
  // canonically reorders all commutative elements
163
- normalize: function() { return this.recurse("normalize"); },
173
+ normalize: function () {
174
+ return this.recurse("normalize");
175
+ },
164
176
 
165
177
  // expands the expression
166
- expand: function() { return this.recurse("expand"); },
178
+ expand: function () {
179
+ return this.recurse("expand");
180
+ },
167
181
 
168
182
  // naively factors out like terms
169
- factor: function(options) { return this.recurse("factor", options); },
183
+ factor: function (options) {
184
+ return this.recurse("factor", options);
185
+ },
170
186
 
171
187
  // collect all like terms
172
- collect: function(options) { return this.recurse("collect", options); },
188
+ collect: function (options) {
189
+ return this.recurse("collect", options);
190
+ },
173
191
 
174
192
  // strict syntactic equality check
175
- equals: function(other) {
193
+ equals: function (other) {
176
194
  return this.normalize().print() === other.normalize().print();
177
195
  },
178
196
 
179
197
  // expand and collect until the expression no longer changes
180
- simplify: function(options) {
181
- options = _.extend({
182
- once: false
183
- }, options);
198
+ simplify: function (options) {
199
+ options = _.extend(
200
+ {
201
+ once: false,
202
+ },
203
+ options,
204
+ );
184
205
 
185
206
  // Attempt to factor and collect
186
207
  var step1 = this.factor(options);
@@ -211,72 +232,82 @@ _.extend(Expr.prototype, {
211
232
  },
212
233
 
213
234
  // check whether this expression is simplified
214
- isSimplified: function() {
235
+ isSimplified: function () {
215
236
  return this.equals(this.simplify());
216
237
  },
217
238
 
218
239
  // return the child nodes of this node
219
- exprArgs: function() {
220
- return _.filter(this.args(), function(arg) {
240
+ exprArgs: function () {
241
+ return _.filter(this.args(), function (arg) {
221
242
  return arg instanceof Expr;
222
243
  });
223
244
  },
224
245
 
225
246
  // return the variables (function and non) within the expression
226
- getVars: function(excludeFunc) {
227
- return _.uniq(_.flatten(_.invoke(this.exprArgs(), "getVars", excludeFunc))).sort();
247
+ getVars: function (excludeFunc) {
248
+ return _.uniq(
249
+ _.flatten(_.invoke(this.exprArgs(), "getVars", excludeFunc)),
250
+ ).sort();
228
251
  },
229
252
 
230
- getConsts: function() {
253
+ getConsts: function () {
231
254
  return _.uniq(_.flatten(_.invoke(this.exprArgs(), "getConsts"))).sort();
232
255
  },
233
256
 
234
- getUnits: function() {
257
+ getUnits: function () {
235
258
  return _.flatten(_.invoke(this.exprArgs(), "getUnits"));
236
259
  },
237
260
 
238
261
  // check whether this expression node is of a particular type
239
- is: function(func) {
262
+ is: function (func) {
240
263
  return this instanceof func;
241
264
  },
242
265
 
243
266
  // check whether this expression has a particular node type
244
- has: function(func) {
267
+ has: function (func) {
245
268
  if (this instanceof func) {
246
269
  return true;
247
270
  }
248
- return _.any(this.exprArgs(), function(arg) { return arg.has(func); });
271
+ return _.any(this.exprArgs(), function (arg) {
272
+ return arg.has(func);
273
+ });
249
274
  },
250
275
 
251
276
  // raise this expression to a given exponent
252
277
  // most useful for eventually implementing i^3 = -i, etc.
253
- raiseToThe: function(exp) {
278
+ raiseToThe: function (exp) {
254
279
  return new Pow(this, exp);
255
280
  },
256
281
 
257
282
  // does this expression have a specific rendering hint?
258
283
  // rendering hints are picked up while parsing, but are lost during transformations
259
- isSubtract: function() { return false; },
260
- isDivide: function() { return false; },
261
- isRoot: function() { return false; },
284
+ isSubtract: function () {
285
+ return false;
286
+ },
287
+ isDivide: function () {
288
+ return false;
289
+ },
290
+ isRoot: function () {
291
+ return false;
292
+ },
262
293
 
263
294
  // whether this node needs an explicit multiplication sign if following a Num
264
- needsExplicitMul: function() {
295
+ needsExplicitMul: function () {
265
296
  return this.args()[0].needsExplicitMul();
266
297
  },
267
298
 
268
299
  // check that the variables in both expressions are the same
269
- sameVars: function(other) {
300
+ sameVars: function (other) {
270
301
  var vars1 = this.getVars();
271
302
  var vars2 = other.getVars();
272
303
 
273
304
  // the other Expr can have more variables than this one
274
305
  // this lets you multiply equations by other variables
275
- var same = function(array1, array2) {
306
+ var same = function (array1, array2) {
276
307
  return !_.difference(array1, array2).length;
277
308
  };
278
309
 
279
- var lower = function(array) {
310
+ var lower = function (array) {
280
311
  return _.uniq(_.invoke(array, "toLowerCase")).sort();
281
312
  };
282
313
 
@@ -289,7 +320,7 @@ _.extend(Expr.prototype, {
289
320
  // semantic equality check, call after sameVars() to avoid potential false positives
290
321
  // plug in random numbers for the variables in both expressions
291
322
  // if they both consistently evaluate the same, then they're the same
292
- compare: function(other) {
323
+ compare: function (other) {
293
324
  // equation comparisons are handled by Eq.compare()
294
325
  if (other instanceof Eq) {
295
326
  return false;
@@ -297,12 +328,13 @@ _.extend(Expr.prototype, {
297
328
 
298
329
  var varList = _.union(
299
330
  this.getVars(/* excludeFunc */ true),
300
- other.getVars(/* excludeFunc */ true));
331
+ other.getVars(/* excludeFunc */ true),
332
+ );
301
333
 
302
334
  // If the numbers are large we would like to do a relative comparison
303
335
  // rather than an absolute one, but if they're small enough then an
304
336
  // absolute comparison makes more sense
305
- var getDelta = function(num1, num2) {
337
+ var getDelta = function (num1, num2) {
306
338
  if (Math.abs(num1) < 1 || Math.abs(num2) < 1) {
307
339
  return Math.abs(num1 - num2);
308
340
  } else {
@@ -310,11 +342,13 @@ _.extend(Expr.prototype, {
310
342
  }
311
343
  };
312
344
 
313
- var equalNumbers = function(num1, num2) {
345
+ var equalNumbers = function (num1, num2) {
314
346
  var delta = getDelta(num1, num2);
315
- return ((num1 === num2) || /* needed if either is +/- Infinity */
316
- (isNaN(num1) && isNaN(num2)) ||
317
- (delta < Math.pow(10, -TOLERANCE)));
347
+ return (
348
+ num1 === num2 /* needed if either is +/- Infinity */ ||
349
+ (isNaN(num1) && isNaN(num2)) ||
350
+ delta < Math.pow(10, -TOLERANCE)
351
+ );
318
352
  };
319
353
 
320
354
  // if no variables, only need to evaluate once
@@ -345,11 +379,10 @@ _.extend(Expr.prototype, {
345
379
  // Note that because there are 12 iterations and three ranges, each
346
380
  // range is checked four times.
347
381
  for (var i = 0; i < ITERATIONS; i++) {
348
-
349
382
  var vars = {};
350
383
 
351
384
  // One third total iterations each with range 10, 100, and 1000
352
- var range = Math.pow(10, 1 + Math.floor(3 * i / ITERATIONS));
385
+ var range = Math.pow(10, 1 + Math.floor((3 * i) / ITERATIONS));
353
386
 
354
387
  // Half of the iterations should only use integer values.
355
388
  // This is because expressions like (-2)^x are common but result
@@ -367,15 +400,19 @@ _.extend(Expr.prototype, {
367
400
  // TODO(alex): Add support for complex numbers, then remove this.
368
401
  var useFloats = i % 2 === 0;
369
402
 
370
- _.each(varList, function(v) {
371
- vars[v] = useFloats ? randomFloat(-range, range)
372
- : _.random(-range, range);
403
+ _.each(varList, function (v) {
404
+ vars[v] = useFloats
405
+ ? randomFloat(-range, range)
406
+ : _.random(-range, range);
373
407
  });
374
408
 
375
409
  var equal;
376
- if (expr1.has(Func) || expr2.has(Func) ||
377
- expr1.has(Unit) || expr2.has(Unit)) {
378
-
410
+ if (
411
+ expr1.has(Func) ||
412
+ expr2.has(Func) ||
413
+ expr1.has(Unit) ||
414
+ expr2.has(Unit)
415
+ ) {
379
416
  var result1 = expr1.partialEval(vars);
380
417
  var result2 = expr2.partialEval(vars);
381
418
 
@@ -396,7 +433,7 @@ _.extend(Expr.prototype, {
396
433
  },
397
434
 
398
435
  // evaluate as much of the expression as possible
399
- partialEval: function(vars) {
436
+ partialEval: function (vars) {
400
437
  if (this instanceof Unit) {
401
438
  return this;
402
439
  } else if (!this.has(Func)) {
@@ -412,22 +449,22 @@ _.extend(Expr.prototype, {
412
449
  // all negative signs are stripped and the expressions are converted to
413
450
  // a canonical commutative form
414
451
  // should only be done after compare() returns true to avoid false positives
415
- sameForm: function(other) {
452
+ sameForm: function (other) {
416
453
  return this.strip().equals(other.strip());
417
454
  },
418
455
 
419
456
  // returns the GCD of this expression and the given factor
420
- findGCD: function(factor) {
457
+ findGCD: function (factor) {
421
458
  return this.equals(factor) ? factor : Num.One;
422
459
  },
423
460
 
424
461
  // return this expression's denominator
425
- getDenominator: function() {
462
+ getDenominator: function () {
426
463
  return Num.One;
427
464
  },
428
465
 
429
466
  // return this expression as a Mul
430
- asMul: function() {
467
+ asMul: function () {
431
468
  return new Mul(Num.One, this);
432
469
  },
433
470
 
@@ -437,15 +474,17 @@ _.extend(Expr.prototype, {
437
474
 
438
475
  // TODO(alex): rename to hasNegativeSign or similar?
439
476
  // return whether this expression has a negative sign
440
- isNegative: function() { return false; },
477
+ isNegative: function () {
478
+ return false;
479
+ },
441
480
 
442
481
  // return a factor of this expression that is 100% positive
443
- asPositiveFactor: function() {
482
+ asPositiveFactor: function () {
444
483
  return this.isPositive() ? this : Num.One;
445
484
  },
446
485
 
447
486
  // return a copy of the expression with a new hint set (preserves hints)
448
- addHint: function(hint) {
487
+ addHint: function (hint) {
449
488
  if (!hint) {
450
489
  return this;
451
490
  }
@@ -457,46 +496,54 @@ _.extend(Expr.prototype, {
457
496
  },
458
497
 
459
498
  hints: {
460
- parens: false
499
+ parens: false,
461
500
  },
462
501
 
463
502
  // currently unused!
464
- asExpr: function() { return this; },
503
+ asExpr: function () {
504
+ return this;
505
+ },
465
506
 
466
507
  // complete parse by performing a few necessary transformations
467
- completeParse: function() { return this.recurse("completeParse"); },
508
+ completeParse: function () {
509
+ return this.recurse("completeParse");
510
+ },
468
511
 
469
512
  abs: abstract,
470
513
 
471
- negate: function() {
514
+ negate: function () {
472
515
  return new Mul(Num.Neg, this);
473
- }
516
+ },
474
517
  });
475
518
 
476
-
477
519
  /* abstract sequence node */
478
520
  function Seq() {}
479
521
  Seq.prototype = new Expr();
480
522
 
481
523
  _.extend(Seq.prototype, {
482
- args: function() { return this.terms; },
524
+ args: function () {
525
+ return this.terms;
526
+ },
483
527
 
484
- normalize: function() {
485
- var terms = _.sortBy(_.invoke(this.terms, "normalize"), function(term) {
486
- return term.print();
487
- });
528
+ normalize: function () {
529
+ var terms = _.sortBy(
530
+ _.invoke(this.terms, "normalize"),
531
+ function (term) {
532
+ return term.print();
533
+ },
534
+ );
488
535
 
489
536
  return new this.func(terms);
490
537
  },
491
538
 
492
- expand: function() {
539
+ expand: function () {
493
540
  return this.recurse("expand").flatten();
494
541
  },
495
542
 
496
543
  // partition the sequence into its numeric and non-numeric parts
497
544
  // makes no guarantees about the validity of either part!
498
- partition: function() {
499
- var terms = _.groupBy(this.terms, function(term) {
545
+ partition: function () {
546
+ var terms = _.groupBy(this.terms, function (term) {
500
547
  return term instanceof Num;
501
548
  });
502
549
 
@@ -511,9 +558,9 @@ _.extend(Seq.prototype, {
511
558
 
512
559
  // ensure that sequences have 2+ terms and no nested sequences of the same type
513
560
  // this is a shallow flattening and will return a non-Seq if terms.length <= 1
514
- flatten: function() {
561
+ flatten: function () {
515
562
  var type = this;
516
- var terms = _.reject(this.terms, function(term) {
563
+ var terms = _.reject(this.terms, function (term) {
517
564
  return term.equals(type.identity);
518
565
  });
519
566
 
@@ -524,7 +571,7 @@ _.extend(Seq.prototype, {
524
571
  return terms[0];
525
572
  }
526
573
 
527
- var grouped = _.groupBy(terms, function(term) {
574
+ var grouped = _.groupBy(terms, function (term) {
528
575
  return term instanceof type.func;
529
576
  });
530
577
 
@@ -532,7 +579,9 @@ _.extend(Seq.prototype, {
532
579
  var same = grouped[true] || [];
533
580
  var others = grouped[false] || [];
534
581
 
535
- var flattened = others.concat(_.flatten(_.pluck(same, "terms"), /* shallow: */ true));
582
+ var flattened = others.concat(
583
+ _.flatten(_.pluck(same, "terms"), /* shallow: */ true),
584
+ );
536
585
  return new type.func(flattened);
537
586
  },
538
587
 
@@ -542,7 +591,7 @@ _.extend(Seq.prototype, {
542
591
  // reduce a numeric sequence to a Num
543
592
  reduce: abstract,
544
593
 
545
- isPositive: function() {
594
+ isPositive: function () {
546
595
  var terms = _.invoke(this.terms, "collect");
547
596
  return _.all(_.invoke(terms, "isPositive"));
548
597
  },
@@ -550,7 +599,7 @@ _.extend(Seq.prototype, {
550
599
  // return a new Seq with a given term replaced by a different term
551
600
  // (or array of terms). given term can be passed directly, or by index
552
601
  // if no new term is provided, the old one is simply removed
553
- replace: function(oldTerm, newTerm) {
602
+ replace: function (oldTerm, newTerm) {
554
603
  var index;
555
604
 
556
605
  if (oldTerm instanceof Expr) {
@@ -566,25 +615,25 @@ _.extend(Seq.prototype, {
566
615
  newTerms = [newTerm];
567
616
  }
568
617
 
569
- var terms = this.terms.slice(0, index)
570
- .concat(newTerms)
571
- .concat(this.terms.slice(index + 1));
618
+ var terms = this.terms
619
+ .slice(0, index)
620
+ .concat(newTerms)
621
+ .concat(this.terms.slice(index + 1));
572
622
 
573
623
  return new this.func(terms);
574
624
  },
575
625
 
576
626
  // syntactic sugar for replace()
577
- remove: function(term) {
627
+ remove: function (term) {
578
628
  return this.replace(term);
579
629
  },
580
630
 
581
- getDenominator: function() {
631
+ getDenominator: function () {
582
632
  // TODO(alex): find and return LCM
583
633
  return new Mul(_.invoke(this.terms, "getDenominator")).flatten();
584
- }
634
+ },
585
635
  });
586
636
 
587
-
588
637
  /* sequence of additive terms */
589
638
  export function Add() {
590
639
  if (arguments.length === 1) {
@@ -598,24 +647,32 @@ Add.prototype = new Seq();
598
647
  _.extend(Add.prototype, {
599
648
  func: Add,
600
649
 
601
- eval: function(vars, options) {
602
- return _.reduce(this.terms, function(memo, term) { return memo + term.eval(vars, options); }, 0);
650
+ eval: function (vars, options) {
651
+ return _.reduce(
652
+ this.terms,
653
+ function (memo, term) {
654
+ return memo + term.eval(vars, options);
655
+ },
656
+ 0,
657
+ );
603
658
  },
604
659
 
605
- codegen: function() {
606
- return _.map(this.terms, function(term) {
607
- return "(" + term.codegen() + ")";
608
- }).join(" + ") || "0";
660
+ codegen: function () {
661
+ return (
662
+ _.map(this.terms, function (term) {
663
+ return "(" + term.codegen() + ")";
664
+ }).join(" + ") || "0"
665
+ );
609
666
  },
610
667
 
611
- print: function() {
668
+ print: function () {
612
669
  return _.invoke(this.terms, "print").join("+");
613
670
  },
614
671
 
615
- tex: function() {
672
+ tex: function () {
616
673
  var tex = "";
617
674
 
618
- _.each(this.terms, function(term) {
675
+ _.each(this.terms, function (term) {
619
676
  if (!tex || term.isSubtract()) {
620
677
  tex += term.tex();
621
678
  } else {
@@ -626,13 +683,13 @@ _.extend(Add.prototype, {
626
683
  return tex;
627
684
  },
628
685
 
629
- collect: function(options) {
686
+ collect: function (options) {
630
687
  var terms = _.invoke(this.terms, "collect", options);
631
688
 
632
689
  // [Expr expr, Num coefficient]
633
690
  var pairs = [];
634
691
 
635
- _.each(terms, function(term) {
692
+ _.each(terms, function (term) {
636
693
  if (term instanceof Mul) {
637
694
  var muls = term.partition();
638
695
  pairs.push([muls[1].flatten(), muls[0].reduce(options)]);
@@ -644,16 +701,18 @@ _.extend(Add.prototype, {
644
701
  });
645
702
 
646
703
  // { (Expr expr).print(): [[Expr expr, Num coefficient]] }
647
- var grouped = _.groupBy(pairs, function(pair) {
704
+ var grouped = _.groupBy(pairs, function (pair) {
648
705
  return pair[0].normalize().print();
649
706
  });
650
707
 
651
- var collected = _.compact(_.map(grouped, function(pairs) {
652
- var expr = pairs[0][0];
653
- var sum = new Add(_.zip.apply(_, pairs)[1]);
654
- var coefficient = sum.reduce(options);
655
- return new Mul(coefficient, expr).collect(options);
656
- }));
708
+ var collected = _.compact(
709
+ _.map(grouped, function (pairs) {
710
+ var expr = pairs[0][0];
711
+ var sum = new Add(_.zip.apply(_, pairs)[1]);
712
+ var coefficient = sum.reduce(options);
713
+ return new Mul(coefficient, expr).collect(options);
714
+ }),
715
+ );
657
716
 
658
717
  // TODO(alex): use the Pythagorean identity here
659
718
  // e.g. x*sin^2(y) + x*cos^2(y) -> x
@@ -663,10 +722,13 @@ _.extend(Add.prototype, {
663
722
 
664
723
  // naively factor out anything that is common to all terms
665
724
  // if options.keepNegative is specified, won't factor out a common -1
666
- factor: function(options) {
667
- options = _.extend({
668
- keepNegative: false
669
- }, options);
725
+ factor: function (options) {
726
+ options = _.extend(
727
+ {
728
+ keepNegative: false,
729
+ },
730
+ options,
731
+ );
670
732
 
671
733
  var terms = _.invoke(this.terms, "collect");
672
734
  var factors;
@@ -677,8 +739,8 @@ _.extend(Add.prototype, {
677
739
  factors = [terms[0]];
678
740
  }
679
741
 
680
- _.each(_.rest(this.terms), function(term) {
681
- factors = _.map(factors, function(factor) {
742
+ _.each(_.rest(this.terms), function (term) {
743
+ factors = _.map(factors, function (factor) {
682
744
  return term.findGCD(factor);
683
745
  });
684
746
  });
@@ -689,7 +751,7 @@ _.extend(Add.prototype, {
689
751
 
690
752
  factors = new Mul(factors).flatten().collect();
691
753
 
692
- var remainder = _.map(terms, function(term) {
754
+ var remainder = _.map(terms, function (term) {
693
755
  return Mul.handleDivide(term, factors).simplify();
694
756
  });
695
757
  remainder = new Add(remainder).flatten();
@@ -697,25 +759,30 @@ _.extend(Add.prototype, {
697
759
  return Mul.createOrAppend(factors, remainder).flatten();
698
760
  },
699
761
 
700
- reduce: function(options) {
701
- return _.reduce(this.terms, function(memo, term) {
702
- return memo.add(term, options);
703
- }, this.identity);
762
+ reduce: function (options) {
763
+ return _.reduce(
764
+ this.terms,
765
+ function (memo, term) {
766
+ return memo.add(term, options);
767
+ },
768
+ this.identity,
769
+ );
704
770
  },
705
771
 
706
- needsExplicitMul: function() { return false; },
772
+ needsExplicitMul: function () {
773
+ return false;
774
+ },
707
775
 
708
- isNegative: function() {
776
+ isNegative: function () {
709
777
  var terms = _.invoke(this.terms, "collect");
710
778
  return _.all(_.invoke(terms, "isNegative"));
711
779
  },
712
780
 
713
- negate: function() {
781
+ negate: function () {
714
782
  return new Add(_.invoke(this.terms, "negate"));
715
- }
783
+ },
716
784
  });
717
785
 
718
-
719
786
  /* sequence of multiplicative terms */
720
787
  export function Mul() {
721
788
  if (arguments.length === 1) {
@@ -729,26 +796,36 @@ Mul.prototype = new Seq();
729
796
  _.extend(Mul.prototype, {
730
797
  func: Mul,
731
798
 
732
- eval: function(vars, options) {
733
- return _.reduce(this.terms, function(memo, term) { return memo * term.eval(vars, options); }, 1);
799
+ eval: function (vars, options) {
800
+ return _.reduce(
801
+ this.terms,
802
+ function (memo, term) {
803
+ return memo * term.eval(vars, options);
804
+ },
805
+ 1,
806
+ );
734
807
  },
735
808
 
736
- codegen: function() {
737
- return _.map(this.terms, function(term) {
738
- return "(" + term.codegen() + ")";
739
- }).join(" * ") || "0";
809
+ codegen: function () {
810
+ return (
811
+ _.map(this.terms, function (term) {
812
+ return "(" + term.codegen() + ")";
813
+ }).join(" * ") || "0"
814
+ );
740
815
  },
741
816
 
742
- print: function() {
743
- return _.map(this.terms, function(term) {
744
- return (term instanceof Add) ? "(" + term.print() + ")" : term.print();
817
+ print: function () {
818
+ return _.map(this.terms, function (term) {
819
+ return term instanceof Add
820
+ ? "(" + term.print() + ")"
821
+ : term.print();
745
822
  }).join("*");
746
823
  },
747
824
 
748
- getUnits: function() {
825
+ getUnits: function () {
749
826
  var tmUnits = _(this.terms)
750
827
  .chain()
751
- .map(function(term) {
828
+ .map(function (term) {
752
829
  return term.getUnits();
753
830
  })
754
831
  .flatten()
@@ -761,10 +838,10 @@ _.extend(Mul.prototype, {
761
838
 
762
839
  // since we don't care about commutativity, we can render a Mul any way we choose
763
840
  // so we follow convention: first any negatives, then any numbers, then everything else
764
- tex: function() {
841
+ tex: function () {
765
842
  var cdot = " \\cdot ";
766
843
 
767
- var terms = _.groupBy(this.terms, function(term) {
844
+ var terms = _.groupBy(this.terms, function (term) {
768
845
  if (term.isDivide()) {
769
846
  return "inverse";
770
847
  } else if (term instanceof Num) {
@@ -785,8 +862,8 @@ _.extend(Mul.prototype, {
785
862
  // since we would like 1/2x/y to come out as \frac{1}{2}\frac{x}{y},
786
863
  // and not \frac{1x}{2y}.
787
864
  for (var i = 0; i < numbers.length; i++) {
788
- var isRational = numbers[i] instanceof Rational &&
789
- !(numbers[i] instanceof Int);
865
+ var isRational =
866
+ numbers[i] instanceof Rational && !(numbers[i] instanceof Int);
790
867
  if (isRational && others.length > 0 && inverses.length > 0) {
791
868
  var withThisRemoved = numbers.slice();
792
869
  withThisRemoved.splice(i, 1);
@@ -795,19 +872,23 @@ _.extend(Mul.prototype, {
795
872
  }
796
873
  }
797
874
 
798
- numbers = _.compact(_.map(numbers, function(term) {
799
- var hasDenom = (term instanceof Rational) && !(term instanceof Int);
800
- var shouldPushDown = !term.hints.fraction || inverses.length > 0;
801
- if (hasDenom && shouldPushDown) {
802
- // e.g. 3x/4 -> 3/4*x (internally) -> 3x/4 (rendered)
803
- inverses.push(new Pow(new Int(term.d), Num.Div));
804
- var number = new Int(term.n);
805
- number.hints = term.hints;
806
- return _.any(term.hints) ? number : null;
807
- } else {
808
- return term;
809
- }
810
- }));
875
+ numbers = _.compact(
876
+ _.map(numbers, function (term) {
877
+ var hasDenom =
878
+ term instanceof Rational && !(term instanceof Int);
879
+ var shouldPushDown =
880
+ !term.hints.fraction || inverses.length > 0;
881
+ if (hasDenom && shouldPushDown) {
882
+ // e.g. 3x/4 -> 3/4*x (internally) -> 3x/4 (rendered)
883
+ inverses.push(new Pow(new Int(term.d), Num.Div));
884
+ var number = new Int(term.n);
885
+ number.hints = term.hints;
886
+ return _.any(term.hints) ? number : null;
887
+ } else {
888
+ return term;
889
+ }
890
+ }),
891
+ );
811
892
 
812
893
  if (numbers.length === 0 && others.length === 1) {
813
894
  // e.g. (x+y)/z -> \frac{x+y}{z}
@@ -815,12 +896,15 @@ _.extend(Mul.prototype, {
815
896
  } else {
816
897
  var tex = "";
817
898
 
818
- _.each(numbers, function(term) {
899
+ _.each(numbers, function (term) {
819
900
  if (term.hints.subtract && term.hints.entered) {
820
901
  negatives += "-";
821
902
  tex += (tex ? cdot : "") + term.abs().tex();
822
- } else if ((term instanceof Int) && (term.n === -1) &&
823
- (term.hints.negate || term.hints.subtract)) {
903
+ } else if (
904
+ term instanceof Int &&
905
+ term.n === -1 &&
906
+ (term.hints.negate || term.hints.subtract)
907
+ ) {
824
908
  // e.g. -1*-1 -> --1
825
909
  // e.g. -1*x -> -x
826
910
  negatives += "-";
@@ -830,7 +914,7 @@ _.extend(Mul.prototype, {
830
914
  }
831
915
  });
832
916
 
833
- _.each(others, function(term) {
917
+ _.each(others, function (term) {
834
918
  if (term.needsExplicitMul()) {
835
919
  // e.g. 2*2^3 -> 2(dot)2^3
836
920
  tex += (tex ? cdot : "") + term.tex();
@@ -849,30 +933,31 @@ _.extend(Mul.prototype, {
849
933
  if (!inverses.length) {
850
934
  return negatives + numerator;
851
935
  } else {
852
- var denominator = new Mul(_.invoke(inverses, "asDivide")).flatten().tex();
936
+ var denominator = new Mul(_.invoke(inverses, "asDivide"))
937
+ .flatten()
938
+ .tex();
853
939
  return negatives + "\\frac{" + numerator + "}{" + denominator + "}";
854
940
  }
855
941
  },
856
942
 
857
- strip: function() {
858
- var terms = _.map(this.terms, function(term) {
943
+ strip: function () {
944
+ var terms = _.map(this.terms, function (term) {
859
945
  return term instanceof Num ? term.abs() : term.strip();
860
946
  });
861
947
  return new Mul(terms).flatten();
862
948
  },
863
949
 
864
950
  // expand numerator and denominator separately
865
- expand: function() {
866
-
867
- var isAdd = function(term) {
951
+ expand: function () {
952
+ var isAdd = function (term) {
868
953
  return term instanceof Add;
869
954
  };
870
955
 
871
- var isInverse = function(term) {
956
+ var isInverse = function (term) {
872
957
  return term instanceof Pow && term.exp.isNegative();
873
958
  };
874
959
 
875
- var isInverseAdd = function(term) {
960
+ var isInverseAdd = function (term) {
876
961
  return isInverse(term) && isAdd(term.base);
877
962
  };
878
963
 
@@ -895,18 +980,28 @@ _.extend(Mul.prototype, {
895
980
  var others = grouped[false] || [];
896
981
 
897
982
  // loop over each additive sequence
898
- var expanded = _.reduce(adds, function(expanded, add) {
899
- // loop over each expanded array of terms
900
- return _.reduce(expanded, function(temp, array) {
901
- // loop over each additive sequence's terms
902
- return temp.concat(_.map(add.terms, function(term) {
903
- return array.concat(term);
904
- }));
905
- }, []);
906
- }, [[]]);
983
+ var expanded = _.reduce(
984
+ adds,
985
+ function (expanded, add) {
986
+ // loop over each expanded array of terms
987
+ return _.reduce(
988
+ expanded,
989
+ function (temp, array) {
990
+ // loop over each additive sequence's terms
991
+ return temp.concat(
992
+ _.map(add.terms, function (term) {
993
+ return array.concat(term);
994
+ }),
995
+ );
996
+ },
997
+ [],
998
+ );
999
+ },
1000
+ [[]],
1001
+ );
907
1002
 
908
1003
  // join each fully expanded array of factors with remaining multiplicative factors
909
- var muls = _.map(expanded, function(array) {
1004
+ var muls = _.map(expanded, function (array) {
910
1005
  return new Mul(others.concat(array)).flatten();
911
1006
  });
912
1007
 
@@ -914,30 +1009,36 @@ _.extend(Mul.prototype, {
914
1009
  }
915
1010
 
916
1011
  if (hasInverseAdd) {
917
- var denominator = new Mul(_.invoke(inverses, "getDenominator")).flatten();
1012
+ var denominator = new Mul(
1013
+ _.invoke(inverses, "getDenominator"),
1014
+ ).flatten();
918
1015
  inverses = [new Pow(denominator.expand(), Num.Div)];
919
1016
  }
920
1017
 
921
1018
  return new Mul(normals.concat(inverses)).flatten();
922
1019
  },
923
1020
 
924
- factor: function(options) {
1021
+ factor: function (options) {
925
1022
  var factored = this.recurse("factor", options).flatten();
926
- if (! (factored instanceof Mul)) {
1023
+ if (!(factored instanceof Mul)) {
927
1024
  return factored;
928
1025
  }
929
1026
 
930
1027
  // Combine any factored out Rationals into one, but don't collect
931
- var grouped = _.groupBy(factored.terms, function(term) {
1028
+ var grouped = _.groupBy(factored.terms, function (term) {
932
1029
  return term instanceof Rational;
933
1030
  });
934
1031
 
935
1032
  // Could also accomplish this by passing a new option
936
1033
  // e.g. return memo.mul(term, {autocollect: false});
937
1034
  // TODO(alex): Decide whether this is a good use of options or not
938
- var rational = _.reduce(grouped[true], function(memo, term) {
939
- return {n: memo.n * term.n, d: memo.d * term.d};
940
- }, {n: 1, d: 1});
1035
+ var rational = _.reduce(
1036
+ grouped[true],
1037
+ function (memo, term) {
1038
+ return {n: memo.n * term.n, d: memo.d * term.d};
1039
+ },
1040
+ {n: 1, d: 1},
1041
+ );
941
1042
 
942
1043
  if (rational.d === 1) {
943
1044
  rational = new Int(rational.n);
@@ -948,7 +1049,7 @@ _.extend(Mul.prototype, {
948
1049
  return new Mul((grouped[false] || []).concat(rational)).flatten();
949
1050
  },
950
1051
 
951
- collect: function(options) {
1052
+ collect: function (options) {
952
1053
  var partitioned = this.recurse("collect", options).partition();
953
1054
  var number = partitioned[0].reduce(options);
954
1055
 
@@ -970,7 +1071,7 @@ _.extend(Mul.prototype, {
970
1071
  // [Expr base, Expr exp]
971
1072
  var pairs = [];
972
1073
 
973
- _.each(others, function(term) {
1074
+ _.each(others, function (term) {
974
1075
  if (term instanceof Pow) {
975
1076
  pairs.push([term.base, term.exp]);
976
1077
  } else {
@@ -979,25 +1080,27 @@ _.extend(Mul.prototype, {
979
1080
  });
980
1081
 
981
1082
  // {(Expr base).print(): [[Expr base, Expr exp]]}
982
- var grouped = _.groupBy(pairs, function(pair) {
1083
+ var grouped = _.groupBy(pairs, function (pair) {
983
1084
  return pair[0].normalize().print();
984
1085
  });
985
1086
 
986
1087
  // [[Expr base, Expr exp]]
987
- var summed = _.compact(_.map(grouped, function(pairs) {
988
- var base = pairs[0][0];
989
- var sum = new Add(_.zip.apply(_, pairs)[1]);
990
- var exp = sum.collect(options);
991
-
992
- if (exp instanceof Num && exp.eval() === 0) {
993
- return null;
994
- } else {
995
- return [base, exp];
996
- }
997
- }));
1088
+ var summed = _.compact(
1089
+ _.map(grouped, function (pairs) {
1090
+ var base = pairs[0][0];
1091
+ var sum = new Add(_.zip.apply(_, pairs)[1]);
1092
+ var exp = sum.collect(options);
1093
+
1094
+ if (exp instanceof Num && exp.eval() === 0) {
1095
+ return null;
1096
+ } else {
1097
+ return [base, exp];
1098
+ }
1099
+ }),
1100
+ );
998
1101
 
999
1102
  // XXX `pairs` is shadowed four or five times in this function
1000
- var pairs = _.groupBy(summed, function(pair) {
1103
+ var pairs = _.groupBy(summed, function (pair) {
1001
1104
  if (pair[0] instanceof Trig && pair[0].isBasic()) {
1002
1105
  return "trig";
1003
1106
  } else if (pair[0] instanceof Log) {
@@ -1014,21 +1117,25 @@ _.extend(Mul.prototype, {
1014
1117
  // combine sines and cosines into other trig functions
1015
1118
 
1016
1119
  // {Trig.arg.print(): [[Trig base, Expr exp]]}
1017
- var byArg = _.groupBy(trigs, function(pair) {
1120
+ var byArg = _.groupBy(trigs, function (pair) {
1018
1121
  return pair[0].arg.normalize().print();
1019
1122
  });
1020
1123
 
1021
1124
  trigs = [];
1022
- _.each(byArg, function(pairs) {
1125
+ _.each(byArg, function (pairs) {
1023
1126
  var arg = pairs[0][0].arg;
1024
1127
 
1025
1128
  // {Trig.type: Expr exp}
1026
1129
  var funcs = {sin: Num.Zero, cos: Num.Zero};
1027
- _.each(pairs, function(pair) {
1130
+ _.each(pairs, function (pair) {
1028
1131
  funcs[pair[0].type] = pair[1];
1029
1132
  });
1030
1133
 
1031
- if (Mul.handleNegative(funcs.sin).collect(options).equals(funcs.cos)) {
1134
+ if (
1135
+ Mul.handleNegative(funcs.sin)
1136
+ .collect(options)
1137
+ .equals(funcs.cos)
1138
+ ) {
1032
1139
  // e.g. sin^x(y)/cos^x(y) -> tan^x(y)
1033
1140
  if (funcs.cos.isNegative()) {
1034
1141
  funcs = {tan: funcs.sin};
@@ -1040,7 +1147,7 @@ _.extend(Mul.prototype, {
1040
1147
  // TODO(alex): combine even if exponents not a perfect match
1041
1148
  // TODO(alex): transform 1/sin and 1/cos into csc and sec
1042
1149
 
1043
- _.each(funcs, function(exp, type) {
1150
+ _.each(funcs, function (exp, type) {
1044
1151
  trigs.push([new Trig(type, arg), exp]);
1045
1152
  });
1046
1153
  });
@@ -1050,24 +1157,34 @@ _.extend(Mul.prototype, {
1050
1157
  // combine logs with the same base
1051
1158
 
1052
1159
  // {Log.base.print(): [[Log base, Expr exp]]}
1053
- var byBase = _.groupBy(logs, function(pair) {
1160
+ var byBase = _.groupBy(logs, function (pair) {
1054
1161
  return pair[0].base.normalize().print();
1055
1162
  });
1056
1163
 
1057
1164
  logs = [];
1058
1165
 
1059
- _.each(byBase, function(pairs) {
1166
+ _.each(byBase, function (pairs) {
1060
1167
  // only combine two logs of the same base, otherwise commutative
1061
1168
  // differences result in different equally valid output
1062
1169
  // e.g. ln(x)/ln(z)*ln(y) -> log_z(x)*ln(y)
1063
1170
  // e.g. ln(x)*ln(y)/ln(z) -> ln(x)*log_z(y)
1064
- if (pairs.length === 2 &&
1065
- Mul.handleNegative(pairs[0][1]).collect(options).equals(pairs[1][1])) {
1171
+ if (
1172
+ pairs.length === 2 &&
1173
+ Mul.handleNegative(pairs[0][1])
1174
+ .collect(options)
1175
+ .equals(pairs[1][1])
1176
+ ) {
1066
1177
  // e.g. ln(x)^y/ln(b)^y -> log_b(x)^y
1067
1178
  if (pairs[0][1].isNegative()) {
1068
- logs.push([new Log(pairs[0][0].power, pairs[1][0].power), pairs[1][1]]);
1179
+ logs.push([
1180
+ new Log(pairs[0][0].power, pairs[1][0].power),
1181
+ pairs[1][1],
1182
+ ]);
1069
1183
  } else {
1070
- logs.push([new Log(pairs[1][0].power, pairs[0][0].power), pairs[0][1]]);
1184
+ logs.push([
1185
+ new Log(pairs[1][0].power, pairs[0][0].power),
1186
+ pairs[0][1],
1187
+ ]);
1071
1188
  }
1072
1189
  } else {
1073
1190
  logs = logs.concat(pairs);
@@ -1079,27 +1196,29 @@ _.extend(Mul.prototype, {
1079
1196
 
1080
1197
  pairs = trigs.concat(logs).concat(exprs);
1081
1198
 
1082
- var collected = _.map(pairs, function(pair) {
1199
+ var collected = _.map(pairs, function (pair) {
1083
1200
  return new Pow(pair[0], pair[1]).collect(options);
1084
1201
  });
1085
1202
 
1086
1203
  return new Mul([number].concat(collected)).flatten();
1087
1204
  },
1088
1205
 
1089
- isSubtract: function() {
1090
- return _.any(this.terms, function(term) {
1206
+ isSubtract: function () {
1207
+ return _.any(this.terms, function (term) {
1091
1208
  return term instanceof Num && term.hints.subtract;
1092
1209
  });
1093
1210
  },
1094
1211
 
1095
1212
  // factor a single -1 in to the Mul
1096
1213
  // combine with a Num if all Nums are positive, else add as a term
1097
- factorIn: function(hint) {
1214
+ factorIn: function (hint) {
1098
1215
  var partitioned = this.partition();
1099
1216
  var numbers = partitioned[0].terms;
1100
- var fold = numbers.length && _.all(numbers, function(num) {
1101
- return num.n > 0;
1102
- });
1217
+ var fold =
1218
+ numbers.length &&
1219
+ _.all(numbers, function (num) {
1220
+ return num.n > 0;
1221
+ });
1103
1222
 
1104
1223
  if (fold) {
1105
1224
  // e.g. - x*2*3 -> x*-2*3
@@ -1115,16 +1234,18 @@ _.extend(Mul.prototype, {
1115
1234
 
1116
1235
  // factor out a single hinted -1 (assume it is the division hint)
1117
1236
  // TODO(alex): make more general or rename to be more specific
1118
- factorOut: function() {
1237
+ factorOut: function () {
1119
1238
  var factored = false;
1120
- var terms = _.compact(_.map(this.terms, function(term, i, list) {
1121
- if (!factored && term instanceof Num && term.hints.divide) {
1122
- factored = true;
1123
- return term.n !== -1 ? term.negate() : null;
1124
- } else {
1125
- return term;
1126
- }
1127
- }));
1239
+ var terms = _.compact(
1240
+ _.map(this.terms, function (term, i, list) {
1241
+ if (!factored && term instanceof Num && term.hints.divide) {
1242
+ factored = true;
1243
+ return term.n !== -1 ? term.negate() : null;
1244
+ } else {
1245
+ return term;
1246
+ }
1247
+ }),
1248
+ );
1128
1249
 
1129
1250
  if (terms.length === 1) {
1130
1251
  return terms[0];
@@ -1133,21 +1254,25 @@ _.extend(Mul.prototype, {
1133
1254
  }
1134
1255
  },
1135
1256
 
1136
- reduce: function(options) {
1137
- return _.reduce(this.terms, function(memo, term) {
1138
- return memo.mul(term, options);
1139
- }, this.identity);
1257
+ reduce: function (options) {
1258
+ return _.reduce(
1259
+ this.terms,
1260
+ function (memo, term) {
1261
+ return memo.mul(term, options);
1262
+ },
1263
+ this.identity,
1264
+ );
1140
1265
  },
1141
1266
 
1142
- findGCD: function(factor) {
1267
+ findGCD: function (factor) {
1143
1268
  return new Mul(_.invoke(this.terms, "findGCD", factor)).flatten();
1144
1269
  },
1145
1270
 
1146
- asMul: function() {
1271
+ asMul: function () {
1147
1272
  return this;
1148
1273
  },
1149
1274
 
1150
- asPositiveFactor: function() {
1275
+ asPositiveFactor: function () {
1151
1276
  if (this.isPositive()) {
1152
1277
  return this;
1153
1278
  } else {
@@ -1156,36 +1281,38 @@ _.extend(Mul.prototype, {
1156
1281
  }
1157
1282
  },
1158
1283
 
1159
- isNegative: function() {
1284
+ isNegative: function () {
1160
1285
  return _.any(_.invoke(this.collect().terms, "isNegative"));
1161
1286
  },
1162
1287
 
1163
- fold: function() {
1288
+ fold: function () {
1164
1289
  return Mul.fold(this);
1165
1290
  },
1166
1291
 
1167
- negate: function() {
1168
- var isNum = function(expr) { return expr instanceof Num; };
1292
+ negate: function () {
1293
+ var isNum = function (expr) {
1294
+ return expr instanceof Num;
1295
+ };
1169
1296
  if (_.any(this.terms, isNum)) {
1170
1297
  var num = _.find(this.terms, isNum);
1171
1298
  return this.replace(num, num.negate());
1172
1299
  } else {
1173
1300
  return new Mul([Num.Neg].concat(this.terms));
1174
1301
  }
1175
- }
1302
+ },
1176
1303
  });
1177
1304
 
1178
1305
  // static methods for the sequence types
1179
- _.each([Add, Mul], function(type) {
1306
+ _.each([Add, Mul], function (type) {
1180
1307
  _.extend(type, {
1181
1308
  // create a new sequence unless left is already one (returns a copy)
1182
- createOrAppend: function(left, right) {
1309
+ createOrAppend: function (left, right) {
1183
1310
  if (left instanceof type) {
1184
1311
  return new type(left.terms.concat(right));
1185
1312
  } else {
1186
1313
  return new type(left, right);
1187
1314
  }
1188
- }
1315
+ },
1189
1316
  });
1190
1317
  });
1191
1318
 
@@ -1194,7 +1321,7 @@ _.extend(Mul, {
1194
1321
  // never fold into a Num that's already negative or a Mul that has a negative Num
1195
1322
  // an optional hint is kept track of to properly render user input
1196
1323
  // an empty hint means negation
1197
- handleNegative: function(expr, hint) {
1324
+ handleNegative: function (expr, hint) {
1198
1325
  if (expr instanceof Num && expr.n > 0) {
1199
1326
  // e.g. - 2 -> -2
1200
1327
  var negated = expr.negate();
@@ -1213,8 +1340,7 @@ _.extend(Mul, {
1213
1340
  },
1214
1341
 
1215
1342
  // division can create either a Rational or a Mul
1216
- handleDivide: function(left, right) {
1217
-
1343
+ handleDivide: function (left, right) {
1218
1344
  // dividing by a Mul is the same as repeated division by its terms
1219
1345
  if (right instanceof Mul) {
1220
1346
  var first = Mul.handleDivide(left, right.terms[0]);
@@ -1222,19 +1348,26 @@ _.extend(Mul, {
1222
1348
  return Mul.handleDivide(first, rest);
1223
1349
  }
1224
1350
 
1225
- var isInt = function(expr) { return expr instanceof Int; };
1226
- var isRational = function(expr) { return expr instanceof Rational; };
1351
+ var isInt = function (expr) {
1352
+ return expr instanceof Int;
1353
+ };
1354
+ var isRational = function (expr) {
1355
+ return expr instanceof Rational;
1356
+ };
1227
1357
 
1228
1358
  // for simplification purposes, fold Ints into Rationals if possible
1229
1359
  // e.g. 3x / 4 -> 3/4 * x (will still render as 3x/4)
1230
1360
  if (isInt(right) && left instanceof Mul && _.any(left.terms, isInt)) {
1231
-
1232
1361
  // search from the right
1233
1362
  var reversed = left.terms.slice().reverse();
1234
1363
  var num = _.find(reversed, isRational);
1235
1364
 
1236
1365
  if (!isInt(num)) {
1237
- return new Mul(left.terms.concat([new Rational(1, right.n).addHint("fraction")]));
1366
+ return new Mul(
1367
+ left.terms.concat([
1368
+ new Rational(1, right.n).addHint("fraction"),
1369
+ ]),
1370
+ );
1238
1371
  }
1239
1372
 
1240
1373
  var rational = new Rational(num.n, right.n);
@@ -1255,12 +1388,15 @@ _.extend(Mul, {
1255
1388
  }
1256
1389
  }
1257
1390
 
1258
- var divide = function(a, b) {
1391
+ var divide = function (a, b) {
1259
1392
  if (b instanceof Int) {
1260
1393
  if (a instanceof Int) {
1261
1394
  if (a.n < 0 && b.n < 0) {
1262
1395
  // e.g. -2 / -3 -> -1*-2/3
1263
- return [Num.Neg, new Rational(a.n, -b.n).addHint("fraction")];
1396
+ return [
1397
+ Num.Neg,
1398
+ new Rational(a.n, -b.n).addHint("fraction"),
1399
+ ];
1264
1400
  } else {
1265
1401
  // e.g. 2 / 3 -> 2/3
1266
1402
  // e.g. -2 / 3 -> -2/3
@@ -1328,31 +1464,46 @@ _.extend(Mul, {
1328
1464
  // e.g. sin(x)*x -> sin(x)*x
1329
1465
  // e.g. sin(x)*(x) -> sin(x)*x
1330
1466
  // e.g. sin(x)*sin(y) -> sin(x)*sin(y)
1331
- fold: function(expr) {
1467
+ fold: function (expr) {
1332
1468
  if (expr instanceof Mul) {
1333
1469
  // assuming that this will be second to last
1334
- var trigLog = _.find(_.initial(expr.terms), function(term) {
1335
- return (term instanceof Trig || term instanceof Log) && term.hints.open;
1470
+ var trigLog = _.find(_.initial(expr.terms), function (term) {
1471
+ return (
1472
+ (term instanceof Trig || term instanceof Log) &&
1473
+ term.hints.open
1474
+ );
1336
1475
  });
1337
1476
  var index = _.indexOf(expr.terms, trigLog);
1338
1477
 
1339
1478
  if (trigLog) {
1340
1479
  var last = _.last(expr.terms);
1341
- if (trigLog.hints.parens || last.hints.parens ||
1342
- last.has(Trig) || last.has(Log)) {
1480
+ if (
1481
+ trigLog.hints.parens ||
1482
+ last.hints.parens ||
1483
+ last.has(Trig) ||
1484
+ last.has(Log)
1485
+ ) {
1343
1486
  trigLog.hints.open = false;
1344
1487
  } else {
1345
1488
  var newTrigLog;
1346
1489
  if (trigLog instanceof Trig) {
1347
- newTrigLog = Trig.create([trigLog.type, trigLog.exp], Mul.createOrAppend(trigLog.arg, last).fold());
1490
+ newTrigLog = Trig.create(
1491
+ [trigLog.type, trigLog.exp],
1492
+ Mul.createOrAppend(trigLog.arg, last).fold(),
1493
+ );
1348
1494
  } else {
1349
- newTrigLog = Log.create(trigLog.base, Mul.createOrAppend(trigLog.power, last).fold());
1495
+ newTrigLog = Log.create(
1496
+ trigLog.base,
1497
+ Mul.createOrAppend(trigLog.power, last).fold(),
1498
+ );
1350
1499
  }
1351
1500
 
1352
1501
  if (index === 0) {
1353
1502
  return newTrigLog;
1354
1503
  } else {
1355
- return new Mul(expr.terms.slice(0, index).concat(newTrigLog)).fold();
1504
+ return new Mul(
1505
+ expr.terms.slice(0, index).concat(newTrigLog),
1506
+ ).fold();
1356
1507
  }
1357
1508
  }
1358
1509
  }
@@ -1360,42 +1511,53 @@ _.extend(Mul, {
1360
1511
  var partitioned = expr.partition();
1361
1512
  var numbers = partitioned[0].terms;
1362
1513
 
1363
- var pos = function(num) { return num.n > 0; };
1364
- var neg = function(num) { return num.n === -1 && num.hints.negate; };
1365
- var posOrNeg = function(num) { return pos(num) || neg(num); };
1514
+ var pos = function (num) {
1515
+ return num.n > 0;
1516
+ };
1517
+ var neg = function (num) {
1518
+ return num.n === -1 && num.hints.negate;
1519
+ };
1520
+ var posOrNeg = function (num) {
1521
+ return pos(num) || neg(num);
1522
+ };
1366
1523
 
1367
- if (numbers.length > 1 &&
1524
+ if (
1525
+ numbers.length > 1 &&
1368
1526
  _.some(numbers, neg) &&
1369
1527
  _.some(numbers, pos) &&
1370
- _.every(numbers, posOrNeg)) {
1371
-
1528
+ _.every(numbers, posOrNeg)
1529
+ ) {
1372
1530
  var firstNeg = _.indexOf(expr.terms, _.find(expr.terms, neg));
1373
1531
  var firstNum = _.indexOf(expr.terms, _.find(expr.terms, pos));
1374
1532
 
1375
1533
  // e.g. -x*2 -> x*-2
1376
1534
  if (firstNeg < firstNum) {
1377
- return expr.replace(firstNum,
1378
- expr.terms[firstNum].negate())
1379
- .remove(firstNeg);
1535
+ return expr
1536
+ .replace(firstNum, expr.terms[firstNum].negate())
1537
+ .remove(firstNeg);
1380
1538
  }
1381
1539
  }
1382
1540
  }
1383
1541
 
1384
1542
  // in all other cases, make no change
1385
1543
  return expr;
1386
- }
1544
+ },
1387
1545
  });
1388
1546
 
1389
-
1390
1547
  /* exponentiation */
1391
- export function Pow(base, exp) { this.base = base; this.exp = exp; }
1548
+ export function Pow(base, exp) {
1549
+ this.base = base;
1550
+ this.exp = exp;
1551
+ }
1392
1552
  Pow.prototype = new Expr();
1393
1553
 
1394
1554
  _.extend(Pow.prototype, {
1395
1555
  func: Pow,
1396
- args: function() { return [this.base, this.exp]; },
1556
+ args: function () {
1557
+ return [this.base, this.exp];
1558
+ },
1397
1559
 
1398
- eval: function(vars, options) {
1560
+ eval: function (vars, options) {
1399
1561
  var evaledBase = this.base.eval(vars, options);
1400
1562
  var evaledExp = this.exp.eval(vars, options);
1401
1563
 
@@ -1423,7 +1585,7 @@ _.extend(Pow.prototype, {
1423
1585
  var oddDenominator = Math.abs(simplifiedExp.d) % 2 === 1;
1424
1586
  if (oddDenominator) {
1425
1587
  var oddNumerator = Math.abs(simplifiedExp.n) % 2 === 1;
1426
- var sign = (oddNumerator) ? -1 : 1;
1588
+ var sign = oddNumerator ? -1 : 1;
1427
1589
  return sign * Math.pow(-1 * evaledBase, evaledExp);
1428
1590
  }
1429
1591
  }
@@ -1431,21 +1593,24 @@ _.extend(Pow.prototype, {
1431
1593
  return Math.pow(evaledBase, evaledExp);
1432
1594
  },
1433
1595
 
1434
- getUnits: function() {
1435
- return this.base.getUnits().map(function(unit) {
1436
- return {
1437
- unit: unit.unit,
1438
- pow: unit.pow * this.exp.n
1439
- };
1440
- }.bind(this));
1596
+ getUnits: function () {
1597
+ return this.base.getUnits().map(
1598
+ function (unit) {
1599
+ return {
1600
+ unit: unit.unit,
1601
+ pow: unit.pow * this.exp.n,
1602
+ };
1603
+ }.bind(this),
1604
+ );
1441
1605
  },
1442
1606
 
1443
- codegen: function() {
1444
- return "Math.pow(" + this.base.codegen() +
1445
- ", " + this.exp.codegen() + ")";
1607
+ codegen: function () {
1608
+ return (
1609
+ "Math.pow(" + this.base.codegen() + ", " + this.exp.codegen() + ")"
1610
+ );
1446
1611
  },
1447
1612
 
1448
- print: function() {
1613
+ print: function () {
1449
1614
  var base = this.base.print();
1450
1615
  if (this.base instanceof Seq || this.base instanceof Pow) {
1451
1616
  base = "(" + base + ")";
@@ -1453,17 +1618,16 @@ _.extend(Pow.prototype, {
1453
1618
  return base + "^(" + this.exp.print() + ")";
1454
1619
  },
1455
1620
 
1456
- tex: function() {
1621
+ tex: function () {
1457
1622
  if (this.isDivide()) {
1458
-
1459
1623
  // e.g. x ^ -1 w/hint -> 1/x
1460
1624
  return "\\frac{1}{" + this.asDivide().tex() + "}";
1461
-
1462
1625
  } else if (this.isRoot()) {
1463
-
1464
1626
  if (this.exp.n !== 1) {
1465
- error("Node marked with hint 'root' does not have exponent " +
1466
- "of form 1/x.");
1627
+ error(
1628
+ "Node marked with hint 'root' does not have exponent " +
1629
+ "of form 1/x.",
1630
+ );
1467
1631
  }
1468
1632
 
1469
1633
  if (this.exp.d === 2) {
@@ -1473,21 +1637,24 @@ _.extend(Pow.prototype, {
1473
1637
  // e.g. x ^ 1/y w/hint -> sqrt[y]{x}
1474
1638
  return "\\sqrt[" + this.exp.d + "]{" + this.base.tex() + "}";
1475
1639
  }
1476
-
1477
- } else if (this.base instanceof Trig && !this.base.isInverse() &&
1478
- this.exp instanceof Num && this.exp.isSimple() &&
1479
- this.exp.eval() >= 0) {
1480
-
1640
+ } else if (
1641
+ this.base instanceof Trig &&
1642
+ !this.base.isInverse() &&
1643
+ this.exp instanceof Num &&
1644
+ this.exp.isSimple() &&
1645
+ this.exp.eval() >= 0
1646
+ ) {
1481
1647
  // e.g sin(x) ^ 2 -> sin^2(x)
1482
1648
  var split = this.base.tex({split: true});
1483
1649
  return split[0] + "^{" + this.exp.tex() + "}" + split[1];
1484
-
1485
1650
  } else {
1486
-
1487
1651
  // e.g. x ^ y -> x^y
1488
1652
  var base = this.base.tex();
1489
- if (this.base instanceof Seq || this.base instanceof Pow ||
1490
- (this.base instanceof Num && !this.base.isSimple())) {
1653
+ if (
1654
+ this.base instanceof Seq ||
1655
+ this.base instanceof Pow ||
1656
+ (this.base instanceof Num && !this.base.isSimple())
1657
+ ) {
1491
1658
  // e.g. a+b ^ c -> (a+b)^c
1492
1659
  base = "(" + base + ")";
1493
1660
  } else if (this.base instanceof Trig || this.base instanceof Log) {
@@ -1498,30 +1665,33 @@ _.extend(Pow.prototype, {
1498
1665
  }
1499
1666
  },
1500
1667
 
1501
- needsExplicitMul: function() {
1668
+ needsExplicitMul: function () {
1502
1669
  return this.isRoot() ? false : this.base.needsExplicitMul();
1503
1670
  },
1504
1671
 
1505
- expand: function() {
1672
+ expand: function () {
1506
1673
  var pow = this.recurse("expand");
1507
1674
 
1508
1675
  if (pow.base instanceof Mul) {
1509
1676
  // e.g. (ab)^c -> a^c*b^c
1510
1677
 
1511
- var terms = _.map(pow.base.terms, function(term) {
1678
+ var terms = _.map(pow.base.terms, function (term) {
1512
1679
  return new Pow(term, pow.exp);
1513
1680
  });
1514
1681
 
1515
1682
  return new Mul(terms).expand();
1516
-
1517
- } else if (pow.base instanceof Add && pow.exp instanceof Int && pow.exp.abs().eval() > 1) {
1683
+ } else if (
1684
+ pow.base instanceof Add &&
1685
+ pow.exp instanceof Int &&
1686
+ pow.exp.abs().eval() > 1
1687
+ ) {
1518
1688
  // e.g. (a+b)^2 -> a*a+a*b+a*b+b*b
1519
1689
  // e.g. (a+b)^-2 -> (a*a+a*b+a*b+b*b)^-1
1520
1690
 
1521
1691
  var positive = pow.exp.eval() > 0;
1522
1692
  var n = pow.exp.abs().eval();
1523
1693
 
1524
- var signed = function(mul) {
1694
+ var signed = function (mul) {
1525
1695
  return positive ? mul : new Pow(mul, Num.Div);
1526
1696
  };
1527
1697
 
@@ -1538,19 +1708,22 @@ _.extend(Pow.prototype, {
1538
1708
  }
1539
1709
 
1540
1710
  // otherwise decompose n into powers of 2 ...
1541
- var indices = _.map(n.toString(2).split(""), function(str, i, list) {
1542
- return Number(str) * Math.pow(2, list.length - i - 1);
1543
- });
1711
+ var indices = _.map(
1712
+ n.toString(2).split(""),
1713
+ function (str, i, list) {
1714
+ return Number(str) * Math.pow(2, list.length - i - 1);
1715
+ },
1716
+ );
1544
1717
  indices = _.without(indices, 0);
1545
1718
 
1546
1719
  // ... then combine
1547
1720
  var mul = new Mul(_.pick(cache, indices)).expand().collect();
1548
1721
  return signed(mul);
1549
-
1550
- } else if (pow.exp instanceof Add) { // DEFINITELY want behind super-simplify() flag
1722
+ } else if (pow.exp instanceof Add) {
1723
+ // DEFINITELY want behind super-simplify() flag
1551
1724
  // e.g. x^(a+b) -> x^a*x^b
1552
1725
 
1553
- var terms = _.map(pow.exp.terms, function(term) {
1726
+ var terms = _.map(pow.exp.terms, function (term) {
1554
1727
  return new Pow(pow.base, term).expand();
1555
1728
  });
1556
1729
 
@@ -1560,10 +1733,10 @@ _.extend(Pow.prototype, {
1560
1733
  }
1561
1734
  },
1562
1735
 
1563
- factor: function() {
1736
+ factor: function () {
1564
1737
  var pow = this.recurse("factor");
1565
1738
  if (pow.base instanceof Mul) {
1566
- var terms = _.map(pow.base.terms, function(term) {
1739
+ var terms = _.map(pow.base.terms, function (term) {
1567
1740
  if (term instanceof Int && pow.exp.equals(Num.Div)) {
1568
1741
  // Anything that can be a Rational should be a Rational
1569
1742
  // e.g. 2^(-1) -> 1/2
@@ -1578,8 +1751,7 @@ _.extend(Pow.prototype, {
1578
1751
  }
1579
1752
  },
1580
1753
 
1581
- collect: function(options) {
1582
-
1754
+ collect: function (options) {
1583
1755
  if (this.base instanceof Pow) {
1584
1756
  // collect this first to avoid having to deal with float precision
1585
1757
  // e.g. sqrt(2)^2 -> 2, not 2.0000000000000004
@@ -1591,39 +1763,29 @@ _.extend(Pow.prototype, {
1591
1763
 
1592
1764
  var pow = this.recurse("collect", options);
1593
1765
 
1594
- var isSimilarLog = function(term) {
1766
+ var isSimilarLog = function (term) {
1595
1767
  return term instanceof Log && term.base.equals(pow.base);
1596
1768
  };
1597
1769
 
1598
- if (pow.exp instanceof Num &&
1599
- pow.exp.eval() === 0) {
1600
-
1770
+ if (pow.exp instanceof Num && pow.exp.eval() === 0) {
1601
1771
  // e.g. x^0 -> 1
1602
1772
  return Num.One;
1603
-
1604
- } else if (pow.exp instanceof Num &&
1605
- pow.exp.eval() === 1) {
1606
-
1773
+ } else if (pow.exp instanceof Num && pow.exp.eval() === 1) {
1607
1774
  // e.g. x^1 -> x
1608
1775
  return pow.base;
1609
-
1610
1776
  } else if (isSimilarLog(pow.exp)) {
1611
-
1612
1777
  // e.g. b^(log_b(x)) -> x
1613
1778
  return pow.exp.power;
1614
-
1615
- } else if (pow.exp instanceof Mul &&
1616
- _.any(pow.exp.terms, isSimilarLog)) {
1617
-
1779
+ } else if (
1780
+ pow.exp instanceof Mul &&
1781
+ _.any(pow.exp.terms, isSimilarLog)
1782
+ ) {
1618
1783
  // e.g. b^(2*y*log_b(x)) -> x^(2*y)
1619
1784
  var log = _.find(pow.exp.terms, isSimilarLog);
1620
1785
  var base = log.power;
1621
1786
  var exp = pow.exp.remove(log).flatten();
1622
1787
  return new Pow(base, exp).collect(options);
1623
-
1624
- } else if (pow.base instanceof Num &&
1625
- pow.exp instanceof Num) {
1626
-
1788
+ } else if (pow.base instanceof Num && pow.exp instanceof Num) {
1627
1789
  // TODO(alex): Consider encapsualting this logic (and similar logic
1628
1790
  // elsewhere) into a separate Decimal class for user-entered floats
1629
1791
  if (options && options.preciseFloats) {
@@ -1657,13 +1819,18 @@ _.extend(Pow.prototype, {
1657
1819
  },
1658
1820
 
1659
1821
  // checks whether this Pow represents user-entered division
1660
- isDivide: function() {
1661
- var isDiv = function(arg) { return arg instanceof Num && arg.hints.divide; };
1662
- return isDiv(this.exp) || (this.exp instanceof Mul && _.any(this.exp.terms, isDiv));
1822
+ isDivide: function () {
1823
+ var isDiv = function (arg) {
1824
+ return arg instanceof Num && arg.hints.divide;
1825
+ };
1826
+ return (
1827
+ isDiv(this.exp) ||
1828
+ (this.exp instanceof Mul && _.any(this.exp.terms, isDiv))
1829
+ );
1663
1830
  },
1664
1831
 
1665
1832
  // assuming this Pow represents user-entered division, returns the denominator
1666
- asDivide: function() {
1833
+ asDivide: function () {
1667
1834
  if (this.exp instanceof Num) {
1668
1835
  if (this.exp.eval() === -1) {
1669
1836
  return this.base;
@@ -1680,23 +1847,36 @@ _.extend(Pow.prototype, {
1680
1847
  }
1681
1848
  },
1682
1849
 
1683
- isRoot: function() {
1850
+ isRoot: function () {
1684
1851
  return this.exp instanceof Rational && this.exp.hints.root;
1685
1852
  },
1686
1853
 
1687
- isSquaredTrig: function() {
1688
- return this.base instanceof Trig && !this.base.isInverse() &&
1689
- this.exp instanceof Num && this.exp.eval() === 2;
1854
+ isSquaredTrig: function () {
1855
+ return (
1856
+ this.base instanceof Trig &&
1857
+ !this.base.isInverse() &&
1858
+ this.exp instanceof Num &&
1859
+ this.exp.eval() === 2
1860
+ );
1690
1861
  },
1691
1862
 
1692
1863
  // extract whatever denominator makes sense, ignoring hints
1693
1864
  // if negative exponent, will recursively include the base's denominator as well
1694
- getDenominator: function() {
1865
+ getDenominator: function () {
1695
1866
  if (this.exp instanceof Num && this.exp.eval() === -1) {
1696
- return Mul.createOrAppend(this.base, this.base.getDenominator()).flatten();
1867
+ return Mul.createOrAppend(
1868
+ this.base,
1869
+ this.base.getDenominator(),
1870
+ ).flatten();
1697
1871
  } else if (this.exp.isNegative()) {
1698
- var pow = new Pow(this.base, Mul.handleNegative(this.exp).collect());
1699
- return Mul.createOrAppend(pow, pow.collect().getDenominator()).flatten();
1872
+ var pow = new Pow(
1873
+ this.base,
1874
+ Mul.handleNegative(this.exp).collect(),
1875
+ );
1876
+ return Mul.createOrAppend(
1877
+ pow,
1878
+ pow.collect().getDenominator(),
1879
+ ).flatten();
1700
1880
  } else if (this.base instanceof Num) {
1701
1881
  return new Pow(this.base.getDenominator(), this.exp).collect();
1702
1882
  } else {
@@ -1704,7 +1884,7 @@ _.extend(Pow.prototype, {
1704
1884
  }
1705
1885
  },
1706
1886
 
1707
- findGCD: function(factor) {
1887
+ findGCD: function (factor) {
1708
1888
  var base, exp;
1709
1889
  if (factor instanceof Pow) {
1710
1890
  base = factor.base;
@@ -1745,7 +1925,7 @@ _.extend(Pow.prototype, {
1745
1925
  return Num.One;
1746
1926
  },
1747
1927
 
1748
- isPositive: function() {
1928
+ isPositive: function () {
1749
1929
  if (this.base.isPositive()) {
1750
1930
  return true;
1751
1931
  }
@@ -1754,7 +1934,7 @@ _.extend(Pow.prototype, {
1754
1934
  return exp instanceof Int && exp.eval() % 2 === 0;
1755
1935
  },
1756
1936
 
1757
- asPositiveFactor: function() {
1937
+ asPositiveFactor: function () {
1758
1938
  if (this.isPositive()) {
1759
1939
  return this;
1760
1940
  } else {
@@ -1763,23 +1943,23 @@ _.extend(Pow.prototype, {
1763
1943
  var n = exp.eval();
1764
1944
  if (n > 2) {
1765
1945
  // e.g. x^3 -> x^2
1766
- return new Pow(this.base, new Int(n-1));
1946
+ return new Pow(this.base, new Int(n - 1));
1767
1947
  } else if (n < -2) {
1768
1948
  // e.g. x^-3 -> x^-2
1769
- return new Pow(this.base, new Int(n+1));
1949
+ return new Pow(this.base, new Int(n + 1));
1770
1950
  }
1771
1951
  }
1772
1952
  return Num.One;
1773
1953
  }
1774
- }
1954
+ },
1775
1955
  });
1776
1956
 
1777
1957
  _.extend(Pow, {
1778
- sqrt: function(arg) {
1958
+ sqrt: function (arg) {
1779
1959
  return new Pow(arg, Num.Sqrt);
1780
1960
  },
1781
1961
 
1782
- nthroot: function(radicand, degree) {
1962
+ nthroot: function (radicand, degree) {
1783
1963
  var exp = Mul.fold(Mul.handleDivide(new Int(1), degree));
1784
1964
 
1785
1965
  // FIXME(johnsullivan): If oneOverDegree ends up being a pow object,
@@ -1788,25 +1968,37 @@ _.extend(Pow, {
1788
1968
  },
1789
1969
  });
1790
1970
 
1791
-
1792
1971
  /* logarithm */
1793
- export function Log(base, power) { this.base = base; this.power = power; }
1972
+ export function Log(base, power) {
1973
+ this.base = base;
1974
+ this.power = power;
1975
+ }
1794
1976
  Log.prototype = new Expr();
1795
1977
 
1796
1978
  _.extend(Log.prototype, {
1797
1979
  func: Log,
1798
- args: function() { return [this.base, this.power]; },
1980
+ args: function () {
1981
+ return [this.base, this.power];
1982
+ },
1799
1983
 
1800
- eval: function(vars, options) {
1801
- return Math.log(this.power.eval(vars, options)) / Math.log(this.base.eval(vars, options));
1984
+ eval: function (vars, options) {
1985
+ return (
1986
+ Math.log(this.power.eval(vars, options)) /
1987
+ Math.log(this.base.eval(vars, options))
1988
+ );
1802
1989
  },
1803
1990
 
1804
- codegen: function() {
1805
- return "(Math.log(" + this.power.codegen() +
1806
- ") / Math.log(" + this.base.codegen() + "))";
1991
+ codegen: function () {
1992
+ return (
1993
+ "(Math.log(" +
1994
+ this.power.codegen() +
1995
+ ") / Math.log(" +
1996
+ this.base.codegen() +
1997
+ "))"
1998
+ );
1807
1999
  },
1808
2000
 
1809
- print: function() {
2001
+ print: function () {
1810
2002
  var power = "(" + this.power.print() + ")";
1811
2003
  if (this.isNatural()) {
1812
2004
  return "ln" + power;
@@ -1815,7 +2007,7 @@ _.extend(Log.prototype, {
1815
2007
  }
1816
2008
  },
1817
2009
 
1818
- tex: function() {
2010
+ tex: function () {
1819
2011
  var power = "(" + this.power.tex() + ")";
1820
2012
  if (this.isNatural()) {
1821
2013
  return "\\ln" + power;
@@ -1824,22 +2016,19 @@ _.extend(Log.prototype, {
1824
2016
  }
1825
2017
  },
1826
2018
 
1827
- collect: function(options) {
2019
+ collect: function (options) {
1828
2020
  var log = this.recurse("collect", options);
1829
2021
 
1830
2022
  if (log.power instanceof Num && log.power.eval() === 1) {
1831
-
1832
2023
  // e.g. ln(1) -> 0
1833
2024
  return Num.Zero;
1834
-
1835
2025
  } else if (log.base.equals(log.power)) {
1836
-
1837
2026
  // e.g. log_b(b) -> 1
1838
2027
  return Num.One;
1839
-
1840
- } else if (log.power instanceof Pow &&
1841
- log.power.base.equals(log.base)) {
1842
-
2028
+ } else if (
2029
+ log.power instanceof Pow &&
2030
+ log.power.base.equals(log.base)
2031
+ ) {
1843
2032
  // e.g. log_b(b^x) -> x
1844
2033
  return log.power.exp;
1845
2034
  } else {
@@ -1847,242 +2036,339 @@ _.extend(Log.prototype, {
1847
2036
  }
1848
2037
  },
1849
2038
 
1850
- expand: function() {
2039
+ expand: function () {
1851
2040
  var log = this.recurse("expand");
1852
2041
 
1853
- if (log.power instanceof Mul) { // might want behind super-simplify() flag
2042
+ if (log.power instanceof Mul) {
2043
+ // might want behind super-simplify() flag
1854
2044
  // e.g. ln(xy) -> ln(x) + ln(y)
1855
2045
 
1856
- var terms = _.map(log.power.terms, function(term) {
2046
+ var terms = _.map(log.power.terms, function (term) {
1857
2047
  // need to expand again in case new log powers are Pows
1858
2048
  return new Log(log.base, term).expand();
1859
2049
  });
1860
2050
 
1861
2051
  return new Add(terms);
1862
-
1863
2052
  } else if (log.power instanceof Pow) {
1864
2053
  // e.g. ln(x^y) -> y*ln(x)
1865
2054
 
1866
- return new Mul(log.power.exp, new Log(log.base, log.power.base).expand()).flatten();
2055
+ return new Mul(
2056
+ log.power.exp,
2057
+ new Log(log.base, log.power.base).expand(),
2058
+ ).flatten();
1867
2059
  } else if (!log.isNatural()) {
1868
2060
  // e.g. log_b(x) -> ln(x)/ln(b)
1869
2061
 
1870
- return Mul.handleDivide(new Log(Const.e, log.power), new Log(Const.e, log.base));
2062
+ return Mul.handleDivide(
2063
+ new Log(Const.e, log.power),
2064
+ new Log(Const.e, log.base),
2065
+ );
1871
2066
  } else {
1872
2067
  return log;
1873
2068
  }
1874
2069
  },
1875
2070
 
1876
2071
  hints: _.extend(Log.prototype.hints, {
1877
- open: false
2072
+ open: false,
1878
2073
  }),
1879
2074
 
1880
- isPositive: function() {
2075
+ isPositive: function () {
1881
2076
  var log = this.collect();
1882
2077
 
1883
- if (log.base instanceof Num &&
1884
- log.power instanceof Num) {
2078
+ if (log.base instanceof Num && log.power instanceof Num) {
1885
2079
  return this.eval() > 0;
1886
2080
  } else {
1887
2081
  return false;
1888
2082
  }
1889
2083
  },
1890
2084
 
1891
- needsExplicitMul: function() { return false; },
2085
+ needsExplicitMul: function () {
2086
+ return false;
2087
+ },
1892
2088
 
1893
- isNatural: function() { return this.base.equals(Const.e); }
2089
+ isNatural: function () {
2090
+ return this.base.equals(Const.e);
2091
+ },
1894
2092
  });
1895
2093
 
1896
2094
  _.extend(Log, {
1897
- natural: function() { return Const.e; },
1898
- common: function() { return Num.Ten; },
2095
+ natural: function () {
2096
+ return Const.e;
2097
+ },
2098
+ common: function () {
2099
+ return Num.Ten;
2100
+ },
1899
2101
 
1900
- create: function(base, power) {
2102
+ create: function (base, power) {
1901
2103
  var log = new Log(base, power);
1902
2104
  if (!power.hints.parens) {
1903
2105
  log = log.addHint("open");
1904
2106
  }
1905
2107
  return log;
1906
- }
2108
+ },
1907
2109
  });
1908
2110
 
1909
-
1910
2111
  /* trigonometric functions */
1911
- export function Trig(type, arg) { this.type = type; this.arg = arg; }
2112
+ export function Trig(type, arg) {
2113
+ this.type = type;
2114
+ this.arg = arg;
2115
+ }
1912
2116
  Trig.prototype = new Expr();
1913
2117
 
1914
2118
  _.extend(Trig.prototype, {
1915
2119
  func: Trig,
1916
- args: function() { return [this.type, this.arg]; },
2120
+ args: function () {
2121
+ return [this.type, this.arg];
2122
+ },
1917
2123
 
1918
2124
  functions: {
1919
2125
  sin: {
1920
2126
  eval: Math.sin,
1921
2127
  codegen: "Math.sin((",
1922
2128
  tex: "\\sin",
1923
- expand: function() { return this; }
2129
+ expand: function () {
2130
+ return this;
2131
+ },
1924
2132
  },
1925
2133
  cos: {
1926
2134
  eval: Math.cos,
1927
2135
  codegen: "Math.cos((",
1928
2136
  tex: "\\cos",
1929
- expand: function() { return this; }
2137
+ expand: function () {
2138
+ return this;
2139
+ },
1930
2140
  },
1931
2141
  tan: {
1932
2142
  eval: Math.tan,
1933
2143
  codegen: "Math.tan((",
1934
2144
  tex: "\\tan",
1935
- expand: function() {
2145
+ expand: function () {
1936
2146
  return Mul.handleDivide(Trig.sin(this.arg), Trig.cos(this.arg));
1937
- }
2147
+ },
1938
2148
  },
1939
2149
  csc: {
1940
- eval: function(arg) { return 1 / Math.sin(arg); },
2150
+ eval: function (arg) {
2151
+ return 1 / Math.sin(arg);
2152
+ },
1941
2153
  codegen: "(1/Math.sin(",
1942
2154
  tex: "\\csc",
1943
- expand: function() {
2155
+ expand: function () {
1944
2156
  return Mul.handleDivide(Num.One, Trig.sin(this.arg));
1945
- }
2157
+ },
1946
2158
  },
1947
2159
  sec: {
1948
- eval: function(arg) { return 1 / Math.cos(arg); },
2160
+ eval: function (arg) {
2161
+ return 1 / Math.cos(arg);
2162
+ },
1949
2163
  codegen: "(1/Math.cos(",
1950
2164
  tex: "\\sec",
1951
- expand: function() {
2165
+ expand: function () {
1952
2166
  return Mul.handleDivide(Num.One, Trig.cos(this.arg));
1953
- }
2167
+ },
1954
2168
  },
1955
2169
  cot: {
1956
- eval: function(arg) { return 1 / Math.tan(arg); },
2170
+ eval: function (arg) {
2171
+ return 1 / Math.tan(arg);
2172
+ },
1957
2173
  codegen: "(1/Math.tan(",
1958
2174
  tex: "\\cot",
1959
- expand: function() {
2175
+ expand: function () {
1960
2176
  return Mul.handleDivide(Trig.cos(this.arg), Trig.sin(this.arg));
1961
- }
2177
+ },
1962
2178
  },
1963
2179
  arcsin: {
1964
2180
  eval: Math.asin,
1965
2181
  codegen: "Math.asin((",
1966
- tex: "\\arcsin"
2182
+ tex: "\\arcsin",
1967
2183
  },
1968
2184
  arccos: {
1969
2185
  eval: Math.acos,
1970
2186
  codegen: "Math.acos((",
1971
- tex: "\\arccos"
2187
+ tex: "\\arccos",
1972
2188
  },
1973
2189
  arctan: {
1974
2190
  eval: Math.atan,
1975
2191
  codegen: "Math.atan((",
1976
- tex: "\\arctan"
2192
+ tex: "\\arctan",
1977
2193
  },
1978
2194
  arccsc: {
1979
- eval: function(arg) { return Math.asin(1 / arg); },
2195
+ eval: function (arg) {
2196
+ return Math.asin(1 / arg);
2197
+ },
1980
2198
  codegen: "Math.asin(1/(",
1981
- tex: "\\operatorname{arccsc}"
2199
+ tex: "\\operatorname{arccsc}",
1982
2200
  },
1983
2201
  arcsec: {
1984
- eval: function(arg) { return Math.acos(1 / arg); },
2202
+ eval: function (arg) {
2203
+ return Math.acos(1 / arg);
2204
+ },
1985
2205
  codegen: "Math.acos(1/(",
1986
- tex: "\\operatorname{arcsec}"
2206
+ tex: "\\operatorname{arcsec}",
1987
2207
  },
1988
2208
  arccot: {
1989
- eval: function(arg) { return Math.atan(1 / arg); },
2209
+ eval: function (arg) {
2210
+ return Math.atan(1 / arg);
2211
+ },
1990
2212
  codegen: "Math.atan(1/(",
1991
- tex: "\\operatorname{arccot}"
2213
+ tex: "\\operatorname{arccot}",
1992
2214
  },
1993
2215
  sinh: {
1994
- eval: function(arg) {
2216
+ eval: function (arg) {
1995
2217
  return (Math.exp(arg) - Math.exp(-arg)) / 2;
1996
2218
  },
1997
- codegen: function(argStr) {
1998
- return "((Math.exp(" + argStr + ") - Math.exp(-(" + argStr + "))) / 2)";
2219
+ codegen: function (argStr) {
2220
+ return (
2221
+ "((Math.exp(" +
2222
+ argStr +
2223
+ ") - Math.exp(-(" +
2224
+ argStr +
2225
+ "))) / 2)"
2226
+ );
1999
2227
  },
2000
2228
  tex: "\\sinh",
2001
- expand: function() { return this; }
2229
+ expand: function () {
2230
+ return this;
2231
+ },
2002
2232
  },
2003
2233
  cosh: {
2004
- eval: function(arg) {
2234
+ eval: function (arg) {
2005
2235
  return (Math.exp(arg) + Math.exp(-arg)) / 2;
2006
2236
  },
2007
- codegen: function(argStr) {
2008
- return "((Math.exp(" + argStr + ") + Math.exp(-(" + argStr + "))) / 2)";
2237
+ codegen: function (argStr) {
2238
+ return (
2239
+ "((Math.exp(" +
2240
+ argStr +
2241
+ ") + Math.exp(-(" +
2242
+ argStr +
2243
+ "))) / 2)"
2244
+ );
2009
2245
  },
2010
2246
  tex: "\\cosh",
2011
- expand: function() { return this; }
2247
+ expand: function () {
2248
+ return this;
2249
+ },
2012
2250
  },
2013
2251
  tanh: {
2014
- eval: function(arg) {
2015
- return (Math.exp(arg) - Math.exp(-arg)) / (Math.exp(arg) + Math.exp(-arg));
2252
+ eval: function (arg) {
2253
+ return (
2254
+ (Math.exp(arg) - Math.exp(-arg)) /
2255
+ (Math.exp(arg) + Math.exp(-arg))
2256
+ );
2016
2257
  },
2017
- codegen: function(argStr) {
2018
- return "(" +
2019
- "(Math.exp(" + argStr + ") - Math.exp(-(" + argStr + ")))" +
2258
+ codegen: function (argStr) {
2259
+ return (
2260
+ "(" +
2261
+ "(Math.exp(" +
2262
+ argStr +
2263
+ ") - Math.exp(-(" +
2264
+ argStr +
2265
+ ")))" +
2020
2266
  " / " +
2021
- "(Math.exp(" + argStr + ") + Math.exp(-(" + argStr + ")))" +
2022
- ")";
2267
+ "(Math.exp(" +
2268
+ argStr +
2269
+ ") + Math.exp(-(" +
2270
+ argStr +
2271
+ ")))" +
2272
+ ")"
2273
+ );
2023
2274
  },
2024
2275
  tex: "\\tanh",
2025
- expand: function() {
2026
- return Mul.handleDivide(Trig.sinh(this.arg), Trig.cosh(this.arg));
2027
- }
2276
+ expand: function () {
2277
+ return Mul.handleDivide(
2278
+ Trig.sinh(this.arg),
2279
+ Trig.cosh(this.arg),
2280
+ );
2281
+ },
2028
2282
  },
2029
2283
  csch: {
2030
- eval: function(arg) { return 2 / (Math.exp(arg) - Math.exp(-arg)); },
2031
- codegen: function(argStr) {
2032
- return "(2 / (Math.exp(" + argStr + ") - Math.exp(-(" + argStr + "))))";
2284
+ eval: function (arg) {
2285
+ return 2 / (Math.exp(arg) - Math.exp(-arg));
2286
+ },
2287
+ codegen: function (argStr) {
2288
+ return (
2289
+ "(2 / (Math.exp(" +
2290
+ argStr +
2291
+ ") - Math.exp(-(" +
2292
+ argStr +
2293
+ "))))"
2294
+ );
2033
2295
  },
2034
2296
  tex: "\\csch",
2035
- expand: function() {
2297
+ expand: function () {
2036
2298
  return Mul.handleDivide(Num.One, Trig.sinh(this.arg));
2037
- }
2299
+ },
2038
2300
  },
2039
2301
  sech: {
2040
- eval: function(arg) { return 2 / (Math.exp(arg) + Math.exp(-arg)); },
2041
- codegen: function(argStr) {
2042
- return "(2 / (Math.exp(" + argStr + ") + Math.exp(-(" + argStr + "))))";
2302
+ eval: function (arg) {
2303
+ return 2 / (Math.exp(arg) + Math.exp(-arg));
2304
+ },
2305
+ codegen: function (argStr) {
2306
+ return (
2307
+ "(2 / (Math.exp(" +
2308
+ argStr +
2309
+ ") + Math.exp(-(" +
2310
+ argStr +
2311
+ "))))"
2312
+ );
2043
2313
  },
2044
2314
  tex: "\\sech",
2045
- expand: function() {
2315
+ expand: function () {
2046
2316
  return Mul.handleDivide(Num.One, Trig.cosh(this.arg));
2047
- }
2317
+ },
2048
2318
  },
2049
2319
  coth: {
2050
- eval: function(arg) {
2051
- return (Math.exp(arg) + Math.exp(-arg)) / (Math.exp(arg) - Math.exp(-arg));
2320
+ eval: function (arg) {
2321
+ return (
2322
+ (Math.exp(arg) + Math.exp(-arg)) /
2323
+ (Math.exp(arg) - Math.exp(-arg))
2324
+ );
2052
2325
  },
2053
- codegen: function(argStr) {
2054
- return "(" +
2055
- "(Math.exp(" + argStr + ") + Math.exp(-(" + argStr + ")))" +
2326
+ codegen: function (argStr) {
2327
+ return (
2328
+ "(" +
2329
+ "(Math.exp(" +
2330
+ argStr +
2331
+ ") + Math.exp(-(" +
2332
+ argStr +
2333
+ ")))" +
2056
2334
  " / " +
2057
- "(Math.exp(" + argStr + ") - Math.exp(-(" + argStr + ")))" +
2058
- ")";
2335
+ "(Math.exp(" +
2336
+ argStr +
2337
+ ") - Math.exp(-(" +
2338
+ argStr +
2339
+ ")))" +
2340
+ ")"
2341
+ );
2059
2342
  },
2060
2343
  tex: "\\coth",
2061
- expand: function() {
2062
- return Mul.handleDivide(Trig.cosh(this.arg), Trig.sinh(this.arg));
2063
- }
2344
+ expand: function () {
2345
+ return Mul.handleDivide(
2346
+ Trig.cosh(this.arg),
2347
+ Trig.sinh(this.arg),
2348
+ );
2349
+ },
2064
2350
  },
2065
2351
  },
2066
2352
 
2067
- isEven: function() {
2353
+ isEven: function () {
2068
2354
  return _.contains(["cos", "sec"], this.type);
2069
2355
  },
2070
2356
 
2071
- isInverse: function() {
2357
+ isInverse: function () {
2072
2358
  return this.type.indexOf("arc") === 0;
2073
2359
  },
2074
2360
 
2075
- isBasic: function() {
2361
+ isBasic: function () {
2076
2362
  return _.contains(["sin", "cos"], this.type);
2077
2363
  },
2078
2364
 
2079
- eval: function(vars, options) {
2365
+ eval: function (vars, options) {
2080
2366
  var func = this.functions[this.type].eval;
2081
2367
  var arg = this.arg.eval(vars, options);
2082
2368
  return func(arg);
2083
2369
  },
2084
2370
 
2085
- codegen: function() {
2371
+ codegen: function () {
2086
2372
  var func = this.functions[this.type].codegen;
2087
2373
  if (typeof func === "function") {
2088
2374
  return func(this.arg.codegen());
@@ -2093,21 +2379,21 @@ _.extend(Trig.prototype, {
2093
2379
  }
2094
2380
  },
2095
2381
 
2096
- print: function() {
2382
+ print: function () {
2097
2383
  return this.type + "(" + this.arg.print() + ")";
2098
2384
  },
2099
2385
 
2100
- tex: function(options) {
2386
+ tex: function (options) {
2101
2387
  var func = this.functions[this.type].tex;
2102
2388
  var arg = "(" + this.arg.tex() + ")";
2103
- return (options && options.split) ? [func, arg] : func + arg;
2389
+ return options && options.split ? [func, arg] : func + arg;
2104
2390
  },
2105
2391
 
2106
2392
  hints: _.extend(Trig.prototype.hints, {
2107
- open: false
2393
+ open: false,
2108
2394
  }),
2109
2395
 
2110
- isPositive: function() {
2396
+ isPositive: function () {
2111
2397
  var trig = this.collect();
2112
2398
 
2113
2399
  if (trig.arg instanceof Num) {
@@ -2117,7 +2403,7 @@ _.extend(Trig.prototype, {
2117
2403
  }
2118
2404
  },
2119
2405
 
2120
- completeParse: function() {
2406
+ completeParse: function () {
2121
2407
  if (this.exp) {
2122
2408
  var pow = new Pow(this, this.exp);
2123
2409
  this.exp = undefined;
@@ -2128,9 +2414,11 @@ _.extend(Trig.prototype, {
2128
2414
  },
2129
2415
 
2130
2416
  // TODO(alex): does every new node type need to redefine these?
2131
- needsExplicitMul: function() { return false; },
2417
+ needsExplicitMul: function () {
2418
+ return false;
2419
+ },
2132
2420
 
2133
- expand: function() {
2421
+ expand: function () {
2134
2422
  var trig = this.recurse("expand");
2135
2423
  if (!trig.isInverse()) {
2136
2424
  // e.g. tan(x) -> sin(x)/cos(x)
@@ -2141,7 +2429,7 @@ _.extend(Trig.prototype, {
2141
2429
  }
2142
2430
  },
2143
2431
 
2144
- collect: function(options) {
2432
+ collect: function (options) {
2145
2433
  var trig = this.recurse("collect", options);
2146
2434
  if (!trig.isInverse() && trig.arg.isNegative()) {
2147
2435
  var arg;
@@ -2154,7 +2442,6 @@ _.extend(Trig.prototype, {
2154
2442
  if (trig.isEven()) {
2155
2443
  // e.g. cos(-x) -> cos(x)
2156
2444
  return new Trig(trig.type, arg);
2157
-
2158
2445
  } else {
2159
2446
  // e.g. sin(-x) -> -sin(x)
2160
2447
  return new Mul(Num.Neg, new Trig(trig.type, arg));
@@ -2162,11 +2449,11 @@ _.extend(Trig.prototype, {
2162
2449
  } else {
2163
2450
  return trig;
2164
2451
  }
2165
- }
2452
+ },
2166
2453
  });
2167
2454
 
2168
2455
  _.extend(Trig, {
2169
- create: function(pair, arg) {
2456
+ create: function (pair, arg) {
2170
2457
  var type = pair[0];
2171
2458
  var exp = pair[1];
2172
2459
 
@@ -2188,39 +2475,48 @@ _.extend(Trig, {
2188
2475
  return trig;
2189
2476
  },
2190
2477
 
2191
- sin: function(arg) {
2478
+ sin: function (arg) {
2192
2479
  return new Trig("sin", arg);
2193
2480
  },
2194
2481
 
2195
- cos: function(arg) {
2482
+ cos: function (arg) {
2196
2483
  return new Trig("cos", arg);
2197
2484
  },
2198
2485
 
2199
- sinh: function(arg) {
2486
+ sinh: function (arg) {
2200
2487
  return new Trig("sinh", arg);
2201
2488
  },
2202
2489
 
2203
- cosh: function(arg) {
2490
+ cosh: function (arg) {
2204
2491
  return new Trig("cosh", arg);
2205
- }
2492
+ },
2206
2493
  });
2207
2494
 
2208
-
2209
- export function Abs(arg) { this.arg = arg; }
2495
+ export function Abs(arg) {
2496
+ this.arg = arg;
2497
+ }
2210
2498
  Abs.prototype = new Expr();
2211
2499
 
2212
2500
  _.extend(Abs.prototype, {
2213
2501
  func: Abs,
2214
- args: function() { return [this.arg]; },
2215
- eval: function(vars, options) { return Math.abs(this.arg.eval(vars, options)); },
2216
- codegen: function() { return "Math.abs(" + this.arg.codegen() + ")"; },
2217
- print: function() { return "abs(" + this.arg.print() + ")"; },
2502
+ args: function () {
2503
+ return [this.arg];
2504
+ },
2505
+ eval: function (vars, options) {
2506
+ return Math.abs(this.arg.eval(vars, options));
2507
+ },
2508
+ codegen: function () {
2509
+ return "Math.abs(" + this.arg.codegen() + ")";
2510
+ },
2511
+ print: function () {
2512
+ return "abs(" + this.arg.print() + ")";
2513
+ },
2218
2514
 
2219
- tex: function() {
2515
+ tex: function () {
2220
2516
  return "\\left|" + this.arg.tex() + "\\right|";
2221
2517
  },
2222
2518
 
2223
- collect: function(options) {
2519
+ collect: function (options) {
2224
2520
  var abs = this.recurse("collect", options);
2225
2521
 
2226
2522
  if (abs.arg.isPositive()) {
@@ -2231,7 +2527,7 @@ _.extend(Abs.prototype, {
2231
2527
  return abs.arg.abs();
2232
2528
  } else if (abs.arg instanceof Mul) {
2233
2529
  // e.g. |-2*pi*x| -> 2*pi*|x|
2234
- var terms = _.groupBy(abs.arg.terms, function(term) {
2530
+ var terms = _.groupBy(abs.arg.terms, function (term) {
2235
2531
  if (term.isPositive()) {
2236
2532
  return "positive";
2237
2533
  } else if (term instanceof Num) {
@@ -2241,7 +2537,9 @@ _.extend(Abs.prototype, {
2241
2537
  }
2242
2538
  });
2243
2539
 
2244
- var positives = terms.positive.concat(_.invoke(terms.number, "abs"));
2540
+ var positives = terms.positive.concat(
2541
+ _.invoke(terms.number, "abs"),
2542
+ );
2245
2543
 
2246
2544
  if (terms.other.length) {
2247
2545
  positives.push(new Abs(new Mul(terms.other).flatten()));
@@ -2254,12 +2552,12 @@ _.extend(Abs.prototype, {
2254
2552
  },
2255
2553
 
2256
2554
  // this should definitely be behind a super-simplify flag
2257
- expand: function() {
2555
+ expand: function () {
2258
2556
  var abs = this.recurse("expand");
2259
2557
 
2260
2558
  if (abs.arg instanceof Mul) {
2261
2559
  // e.g. |xyz| -> |x|*|y|*|z|
2262
- var terms = _.map(abs.arg.terms, function(term) {
2560
+ var terms = _.map(abs.arg.terms, function (term) {
2263
2561
  return new Abs(term);
2264
2562
  });
2265
2563
  return new Mul(terms);
@@ -2268,10 +2566,11 @@ _.extend(Abs.prototype, {
2268
2566
  }
2269
2567
  },
2270
2568
 
2271
- isPositive: function() { return true; }
2569
+ isPositive: function () {
2570
+ return true;
2571
+ },
2272
2572
  });
2273
2573
 
2274
-
2275
2574
  /* equation */
2276
2575
  export function Eq(left, type, right) {
2277
2576
  this.left = left;
@@ -2282,11 +2581,15 @@ Eq.prototype = new Expr();
2282
2581
 
2283
2582
  _.extend(Eq.prototype, {
2284
2583
  func: Eq,
2285
- args: function() { return [this.left, this.type, this.right]; },
2584
+ args: function () {
2585
+ return [this.left, this.type, this.right];
2586
+ },
2286
2587
 
2287
- needsExplicitMul: function() { return false; },
2588
+ needsExplicitMul: function () {
2589
+ return false;
2590
+ },
2288
2591
 
2289
- print: function() {
2592
+ print: function () {
2290
2593
  return this.left.print() + this.type + this.right.print();
2291
2594
  },
2292
2595
 
@@ -2296,14 +2599,14 @@ _.extend(Eq.prototype, {
2296
2599
  ">": " > ",
2297
2600
  "<>": " \\ne ",
2298
2601
  "<=": " \\le ",
2299
- ">=": " \\ge "
2602
+ ">=": " \\ge ",
2300
2603
  },
2301
2604
 
2302
- tex: function() {
2605
+ tex: function () {
2303
2606
  return this.left.tex() + this.signs[this.type] + this.right.tex();
2304
2607
  },
2305
2608
 
2306
- normalize: function() {
2609
+ normalize: function () {
2307
2610
  var eq = this.recurse("normalize");
2308
2611
 
2309
2612
  if (_.contains([">", ">="], eq.type)) {
@@ -2318,8 +2621,8 @@ _.extend(Eq.prototype, {
2318
2621
  // the expression is normalized to a canonical form
2319
2622
  // e.g. y/2=x/4 -> y/2-x/4(=0) -> 2y-x(=0)
2320
2623
  // unless unfactored is specified, will then divide through
2321
- asExpr: function(unfactored) {
2322
- var isZero = function(expr) {
2624
+ asExpr: function (unfactored) {
2625
+ var isZero = function (expr) {
2323
2626
  return expr instanceof Num && expr.isSimple() && expr.eval() === 0;
2324
2627
  };
2325
2628
 
@@ -2357,10 +2660,10 @@ _.extend(Eq.prototype, {
2357
2660
  }
2358
2661
 
2359
2662
  if (!denominator.equals(Num.One)) {
2360
- terms = _.map(terms, function(term) {
2663
+ terms = _.map(terms, function (term) {
2361
2664
  return Mul.createOrAppend(term, denominator).simplify({
2362
2665
  once: true,
2363
- preciseFloats: true
2666
+ preciseFloats: true,
2364
2667
  });
2365
2668
  });
2366
2669
  }
@@ -2374,7 +2677,7 @@ _.extend(Eq.prototype, {
2374
2677
  // e.g. 2y-4x(=0) -> y-2x(=0)
2375
2678
  // TODO(alex): Make it an option to only divide by variables/expressions
2376
2679
  // guaranteed to be nonzero
2377
- divideThrough: function(expr) {
2680
+ divideThrough: function (expr) {
2378
2681
  var isInequality = !this.isEquality();
2379
2682
 
2380
2683
  var simplified = expr.simplify({once: true});
@@ -2386,9 +2689,15 @@ _.extend(Eq.prototype, {
2386
2689
 
2387
2690
  var terms = factored.terms;
2388
2691
 
2389
- var isAdd = function(term) { return term instanceof Add; };
2390
- var hasVar = function(term) { return !!term.getVars().length; };
2391
- var isOne = function(term) { return term.equals(Num.One); };
2692
+ var isAdd = function (term) {
2693
+ return term instanceof Add;
2694
+ };
2695
+ var hasVar = function (term) {
2696
+ return !!term.getVars().length;
2697
+ };
2698
+ var isOne = function (term) {
2699
+ return term.equals(Num.One);
2700
+ };
2392
2701
 
2393
2702
  var grouped = _.groupBy(terms, isAdd);
2394
2703
  var adds = grouped[true] || [];
@@ -2417,7 +2726,7 @@ _.extend(Eq.prototype, {
2417
2726
  // don't need to divide by one
2418
2727
  denominator = _.reject(denominator, isOne);
2419
2728
 
2420
- denominator = _.map(denominator, function(term) {
2729
+ denominator = _.map(denominator, function (term) {
2421
2730
  return new Pow(term, Num.Div);
2422
2731
  });
2423
2732
 
@@ -2432,11 +2741,11 @@ _.extend(Eq.prototype, {
2432
2741
  }
2433
2742
  },
2434
2743
 
2435
- isEquality: function() {
2744
+ isEquality: function () {
2436
2745
  return _.contains(["=", "<>"], this.type);
2437
2746
  },
2438
2747
 
2439
- compare: function(other) {
2748
+ compare: function (other) {
2440
2749
  // expression comparisons are handled by Expr.compare()
2441
2750
  if (!(other instanceof Eq)) {
2442
2751
  return false;
@@ -2451,20 +2760,25 @@ _.extend(Eq.prototype, {
2451
2760
 
2452
2761
  // need to collect to properly factor out common factors
2453
2762
  // e.g x+2x=6 -> 3x=6 -> 3x-6(=0) -> x-2(=0)
2454
- var expr1 = eq1.divideThrough(eq1.asExpr(/* unfactored */ true).collect());
2455
- var expr2 = eq2.divideThrough(eq2.asExpr(/* unfactored */ true).collect());
2763
+ var expr1 = eq1.divideThrough(
2764
+ eq1.asExpr(/* unfactored */ true).collect(),
2765
+ );
2766
+ var expr2 = eq2.divideThrough(
2767
+ eq2.asExpr(/* unfactored */ true).collect(),
2768
+ );
2456
2769
 
2457
2770
  if (eq1.isEquality()) {
2458
2771
  // equals and not-equals can be subtracted either way
2459
- return expr1.compare(expr2) ||
2460
- expr1.compare(Mul.handleNegative(expr2));
2772
+ return (
2773
+ expr1.compare(expr2) || expr1.compare(Mul.handleNegative(expr2))
2774
+ );
2461
2775
  } else {
2462
2776
  return expr1.compare(expr2);
2463
2777
  }
2464
2778
  },
2465
2779
 
2466
2780
  // should only be done after compare() returns true to avoid false positives
2467
- sameForm: function(other) {
2781
+ sameForm: function (other) {
2468
2782
  var eq1 = this.normalize();
2469
2783
  var eq2 = other.normalize();
2470
2784
 
@@ -2472,7 +2786,10 @@ _.extend(Eq.prototype, {
2472
2786
 
2473
2787
  if (eq1.isEquality()) {
2474
2788
  // equals and not-equals can be commutative with respect to the sign
2475
- return same || (eq1.left.sameForm(eq2.right) && eq1.right.sameForm(eq2.left));
2789
+ return (
2790
+ same ||
2791
+ (eq1.left.sameForm(eq2.right) && eq1.right.sameForm(eq2.left))
2792
+ );
2476
2793
  } else {
2477
2794
  return same;
2478
2795
  }
@@ -2480,25 +2797,29 @@ _.extend(Eq.prototype, {
2480
2797
 
2481
2798
  // we don't want to override collect because it would turn y=x into y-x(=0)
2482
2799
  // instead, we ask if the equation was in that form, would it be simplified?
2483
- isSimplified: function() {
2800
+ isSimplified: function () {
2484
2801
  var expr = this.asExpr(/* unfactored */ true);
2485
2802
  var simplified = this.divideThrough(expr).simplify();
2486
- return expr.equals(simplified) &&
2487
- this.left.isSimplified() &&
2488
- this.right.isSimplified();
2489
- }
2803
+ return (
2804
+ expr.equals(simplified) &&
2805
+ this.left.isSimplified() &&
2806
+ this.right.isSimplified()
2807
+ );
2808
+ },
2490
2809
  });
2491
2810
 
2492
2811
  _.extend(Eq.prototype, {
2493
2812
  // Assumptions: Expression is of the form a+bx, and we solve for x
2494
- solveLinearEquationForVariable: function(variable) {
2813
+ solveLinearEquationForVariable: function (variable) {
2495
2814
  var expr = this.asExpr();
2496
2815
  if (!expr.is(Add) || expr.terms.length !== 2) {
2497
- throw new Error("Can only handle linear equations of the form " +
2498
- "a + bx (= 0)");
2816
+ throw new Error(
2817
+ "Can only handle linear equations of the form " +
2818
+ "a + bx (= 0)",
2819
+ );
2499
2820
  }
2500
2821
 
2501
- var hasVar = function(term) {
2822
+ var hasVar = function (term) {
2502
2823
  return term.has(Var) && _.contains(term.getVars(), variable.symbol);
2503
2824
  };
2504
2825
 
@@ -2513,51 +2834,53 @@ _.extend(Eq.prototype, {
2513
2834
  }
2514
2835
 
2515
2836
  return Mul.handleDivide(a, b).simplify();
2516
- }
2837
+ },
2517
2838
  });
2518
2839
 
2519
-
2520
2840
  /* abstract symbol node */
2521
2841
  function Symbol() {}
2522
2842
  Symbol.prototype = new Expr();
2523
2843
 
2524
2844
  _.extend(Symbol.prototype, {
2845
+ needsExplicitMul: function () {
2846
+ return false;
2847
+ },
2525
2848
 
2526
- needsExplicitMul: function() { return false; },
2527
-
2528
- findGCD: function(factor) {
2849
+ findGCD: function (factor) {
2529
2850
  if (factor instanceof Symbol || factor instanceof Num) {
2530
2851
  return this.equals(factor) ? this : Num.One;
2531
2852
  } else {
2532
2853
  return factor.findGCD(this);
2533
2854
  }
2534
- }
2855
+ },
2535
2856
  });
2536
2857
 
2537
-
2538
2858
  /* function variable */
2539
2859
  export function Func(symbol, arg) {
2540
- this.symbol = symbol; this.arg = arg;
2860
+ this.symbol = symbol;
2861
+ this.arg = arg;
2541
2862
  }
2542
2863
  Func.prototype = new Symbol();
2543
2864
 
2544
2865
  _.extend(Func.prototype, {
2545
2866
  func: Func,
2546
- args: function() { return [this.symbol, this.arg]; },
2867
+ args: function () {
2868
+ return [this.symbol, this.arg];
2869
+ },
2547
2870
 
2548
- print: function() {
2871
+ print: function () {
2549
2872
  return this.symbol + "(" + this.arg.print() + ")";
2550
2873
  },
2551
2874
 
2552
- tex: function() {
2875
+ tex: function () {
2553
2876
  return this.symbol + "(" + this.arg.tex() + ")";
2554
2877
  },
2555
2878
 
2556
- eval: function(vars, options) {
2879
+ eval: function (vars, options) {
2557
2880
  var arg = this.arg;
2558
2881
  var func = vars[this.symbol];
2559
2882
  var newVars = _.extend(_.clone(vars), {
2560
- x: arg.eval(vars, options)
2883
+ x: arg.eval(vars, options),
2561
2884
  });
2562
2885
  var parsedFunc = parse(func, options);
2563
2886
  if (parsedFunc.parsed) {
@@ -2567,16 +2890,15 @@ _.extend(Func.prototype, {
2567
2890
  return parsedFunc;
2568
2891
  },
2569
2892
 
2570
- codegen: function() {
2571
- return 'vars["' + this.symbol + '"](' +
2572
- this.arg.codegen() + ')';
2893
+ codegen: function () {
2894
+ return 'vars["' + this.symbol + '"](' + this.arg.codegen() + ")";
2573
2895
  },
2574
2896
 
2575
- getUnits: function() {
2897
+ getUnits: function () {
2576
2898
  return this.arg.getUnits();
2577
2899
  },
2578
2900
 
2579
- getVars: function(excludeFunc) {
2901
+ getVars: function (excludeFunc) {
2580
2902
  if (excludeFunc) {
2581
2903
  return this.arg.getVars();
2582
2904
  } else {
@@ -2584,12 +2906,11 @@ _.extend(Func.prototype, {
2584
2906
  }
2585
2907
  },
2586
2908
 
2587
- getConsts: function() {
2909
+ getConsts: function () {
2588
2910
  return this.arg.getConsts();
2589
2911
  },
2590
2912
  });
2591
2913
 
2592
-
2593
2914
  /* variable */
2594
2915
  export function Var(symbol, subscript) {
2595
2916
  this.symbol = symbol;
@@ -2599,12 +2920,18 @@ Var.prototype = new Symbol();
2599
2920
 
2600
2921
  _.extend(Var.prototype, {
2601
2922
  func: Var,
2602
- args: function() { return [this.symbol, this.subscript]; },
2923
+ args: function () {
2924
+ return [this.symbol, this.subscript];
2925
+ },
2603
2926
 
2604
- exprArgs: function() { return []; },
2605
- recurse: function() { return this; },
2927
+ exprArgs: function () {
2928
+ return [];
2929
+ },
2930
+ recurse: function () {
2931
+ return this;
2932
+ },
2606
2933
 
2607
- print: function() {
2934
+ print: function () {
2608
2935
  var sub = "";
2609
2936
  if (this.subscript) {
2610
2937
  sub = "_(" + this.subscript.print() + ")";
@@ -2614,7 +2941,7 @@ _.extend(Var.prototype, {
2614
2941
 
2615
2942
  // Provide a way to easily evalate expressions with the common case,
2616
2943
  // subscripts that consist of a single number or symbol e.g. x_a or x_42
2617
- prettyPrint: function() {
2944
+ prettyPrint: function () {
2618
2945
  var sub = this.subscript;
2619
2946
  if (sub && (sub instanceof Num || sub instanceof Symbol)) {
2620
2947
  return this.symbol + "_" + sub.print();
@@ -2623,7 +2950,7 @@ _.extend(Var.prototype, {
2623
2950
  }
2624
2951
  },
2625
2952
 
2626
- tex: function() {
2953
+ tex: function () {
2627
2954
  var sub = "";
2628
2955
  if (this.subscript) {
2629
2956
  sub = "_{" + this.subscript.tex() + "}";
@@ -2632,32 +2959,43 @@ _.extend(Var.prototype, {
2632
2959
  return prefix + this.symbol + sub;
2633
2960
  },
2634
2961
 
2635
- repr: function() { return "Var(" + this.print() + ")"; },
2962
+ repr: function () {
2963
+ return "Var(" + this.print() + ")";
2964
+ },
2636
2965
 
2637
- eval: function(vars, options) {
2966
+ eval: function (vars, options) {
2638
2967
  return vars[this.prettyPrint()];
2639
2968
  },
2640
2969
 
2641
- codegen: function() {
2970
+ codegen: function () {
2642
2971
  return 'vars["' + this.prettyPrint() + '"]';
2643
2972
  },
2644
2973
 
2645
- getVars: function() { return [this.prettyPrint()]; },
2974
+ getVars: function () {
2975
+ return [this.prettyPrint()];
2976
+ },
2646
2977
 
2647
- isPositive: function() { return false; }
2978
+ isPositive: function () {
2979
+ return false;
2980
+ },
2648
2981
  });
2649
2982
 
2650
-
2651
2983
  /* constant */
2652
- export function Const(symbol) { this.symbol = symbol; }
2984
+ export function Const(symbol) {
2985
+ this.symbol = symbol;
2986
+ }
2653
2987
  Const.prototype = new Symbol();
2654
2988
 
2655
2989
  _.extend(Const.prototype, {
2656
2990
  func: Const,
2657
- args: function() { return [this.symbol]; },
2658
- recurse: function() { return this; },
2991
+ args: function () {
2992
+ return [this.symbol];
2993
+ },
2994
+ recurse: function () {
2995
+ return this;
2996
+ },
2659
2997
 
2660
- eval: function(vars, options) {
2998
+ eval: function (vars, options) {
2661
2999
  if (this.symbol === "pi") {
2662
3000
  return Math.PI;
2663
3001
  } else if (this.symbol === "e") {
@@ -2665,7 +3003,7 @@ _.extend(Const.prototype, {
2665
3003
  }
2666
3004
  },
2667
3005
 
2668
- codegen: function() {
3006
+ codegen: function () {
2669
3007
  if (this.symbol === "pi") {
2670
3008
  return "Math.PI";
2671
3009
  } else if (this.symbol === "e") {
@@ -2673,9 +3011,11 @@ _.extend(Const.prototype, {
2673
3011
  }
2674
3012
  },
2675
3013
 
2676
- print: function() { return this.symbol; },
3014
+ print: function () {
3015
+ return this.symbol;
3016
+ },
2677
3017
 
2678
- tex: function() {
3018
+ tex: function () {
2679
3019
  if (this.symbol === "pi") {
2680
3020
  return "\\pi ";
2681
3021
  } else if (this.symbol === "e") {
@@ -2683,11 +3023,11 @@ _.extend(Const.prototype, {
2683
3023
  }
2684
3024
  },
2685
3025
 
2686
- isPositive: function() {
3026
+ isPositive: function () {
2687
3027
  return this.eval() > 0;
2688
3028
  },
2689
3029
 
2690
- abs: function() {
3030
+ abs: function () {
2691
3031
  if (this.eval() > 0) {
2692
3032
  return this;
2693
3033
  } else {
@@ -2695,7 +3035,7 @@ _.extend(Const.prototype, {
2695
3035
  }
2696
3036
  },
2697
3037
 
2698
- getConsts: function() {
3038
+ getConsts: function () {
2699
3039
  return [this.print()];
2700
3040
  },
2701
3041
  });
@@ -2703,16 +3043,23 @@ _.extend(Const.prototype, {
2703
3043
  Const.e = new Const("e");
2704
3044
  Const.pi = new Const("pi");
2705
3045
 
2706
-
2707
3046
  /* abstract number node */
2708
3047
  function Num() {}
2709
3048
  Num.prototype = new Expr();
2710
3049
 
2711
3050
  _.extend(Num.prototype, {
2712
- repr: function() { return this.print(); },
2713
- strip: function() { return this.abs(); },
2714
- recurse: function() { return this; },
2715
- codegen: function() { return this.print(); },
3051
+ repr: function () {
3052
+ return this.print();
3053
+ },
3054
+ strip: function () {
3055
+ return this.abs();
3056
+ },
3057
+ recurse: function () {
3058
+ return this;
3059
+ },
3060
+ codegen: function () {
3061
+ return this.print();
3062
+ },
2716
3063
 
2717
3064
  // takes another Num and returns a new Num
2718
3065
  add: abstract,
@@ -2721,24 +3068,28 @@ _.extend(Num.prototype, {
2721
3068
  // returns this Num's additive inverse
2722
3069
  negate: abstract,
2723
3070
 
2724
- isSubtract: function() { return this.hints.subtract; },
3071
+ isSubtract: function () {
3072
+ return this.hints.subtract;
3073
+ },
2725
3074
 
2726
3075
  // return the absolute value of the number
2727
3076
  abs: abstract,
2728
3077
 
2729
- needsExplicitMul: function() { return true; },
3078
+ needsExplicitMul: function () {
3079
+ return true;
3080
+ },
2730
3081
 
2731
3082
  findGCD: abstract,
2732
3083
 
2733
- isPositive: function() {
3084
+ isPositive: function () {
2734
3085
  return this.eval() > 0;
2735
3086
  },
2736
3087
 
2737
- isNegative: function() {
3088
+ isNegative: function () {
2738
3089
  return this.eval() < 0;
2739
3090
  },
2740
3091
 
2741
- asPositiveFactor: function() {
3092
+ asPositiveFactor: function () {
2742
3093
  return this.isPositive() ? this : this.abs();
2743
3094
  },
2744
3095
 
@@ -2749,7 +3100,7 @@ _.extend(Num.prototype, {
2749
3100
  divide: false,
2750
3101
  root: false,
2751
3102
  fraction: false,
2752
- entered: false
3103
+ entered: false,
2753
3104
  }),
2754
3105
 
2755
3106
  // whether a number is considered simple (one term)
@@ -2757,58 +3108,72 @@ _.extend(Num.prototype, {
2757
3108
  isSimple: abstract,
2758
3109
 
2759
3110
  // Based on http://stackoverflow.com/a/10454560/2571482
2760
- getDecimalPlaces: function() {
3111
+ getDecimalPlaces: function () {
2761
3112
  var match = ("" + this.n).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
2762
3113
  if (match) {
2763
3114
  return Math.max(
2764
3115
  0,
2765
3116
  // Number of digits right of decimal point
2766
3117
  (match[1] ? match[1].length : 0) -
2767
- // Adjust for scientific notation
2768
- (match[2] ? +match[2] : 0)
3118
+ // Adjust for scientific notation
3119
+ (match[2] ? +match[2] : 0),
2769
3120
  );
2770
3121
  } else {
2771
3122
  return 0;
2772
3123
  }
2773
3124
  },
2774
3125
 
2775
- asRational: abstract
3126
+ asRational: abstract,
2776
3127
  });
2777
3128
 
2778
-
2779
3129
  /* rational number (n: numerator, d: denominator) */
2780
3130
  export function Rational(numerator, denominator) {
2781
- var n = numerator; var d = denominator;
3131
+ var n = numerator;
3132
+ var d = denominator;
2782
3133
  if (d < 0) {
2783
- n = -n; d = -d;
3134
+ n = -n;
3135
+ d = -d;
2784
3136
  }
2785
- this.n = n; this.d = d;
3137
+ this.n = n;
3138
+ this.d = d;
2786
3139
  }
2787
3140
  Rational.prototype = new Num();
2788
3141
 
2789
3142
  _.extend(Rational.prototype, {
2790
3143
  func: Rational,
2791
- args: function() { return [this.n, this.d]; },
2792
- eval: function() { return this.n / this.d; },
3144
+ args: function () {
3145
+ return [this.n, this.d];
3146
+ },
3147
+ eval: function () {
3148
+ return this.n / this.d;
3149
+ },
2793
3150
 
2794
- print: function() {
3151
+ print: function () {
2795
3152
  return this.n.toString() + "/" + this.d.toString();
2796
3153
  },
2797
3154
 
2798
- tex: function() {
2799
- var tex = "\\frac{" + Math.abs(this.n).toString() + "}{" + this.d.toString() + "}";
3155
+ tex: function () {
3156
+ var tex =
3157
+ "\\frac{" +
3158
+ Math.abs(this.n).toString() +
3159
+ "}{" +
3160
+ this.d.toString() +
3161
+ "}";
2800
3162
  return this.n < 0 ? "-" + tex : tex;
2801
3163
  },
2802
3164
 
2803
- add: function(num, options) {
3165
+ add: function (num, options) {
2804
3166
  if (num instanceof Rational) {
2805
- return new Rational(this.n * num.d + this.d * num.n, this.d * num.d).collect();
3167
+ return new Rational(
3168
+ this.n * num.d + this.d * num.n,
3169
+ this.d * num.d,
3170
+ ).collect();
2806
3171
  } else {
2807
3172
  return num.add(this, options);
2808
3173
  }
2809
3174
  },
2810
3175
 
2811
- mul: function(num, options) {
3176
+ mul: function (num, options) {
2812
3177
  if (num instanceof Rational) {
2813
3178
  return new Rational(this.n * num.n, this.d * num.d).collect();
2814
3179
  } else {
@@ -2816,7 +3181,7 @@ _.extend(Rational.prototype, {
2816
3181
  }
2817
3182
  },
2818
3183
 
2819
- collect: function() {
3184
+ collect: function () {
2820
3185
  var gcd = Num.findGCD(this.n, this.d);
2821
3186
 
2822
3187
  var n = this.n / gcd;
@@ -2829,15 +3194,15 @@ _.extend(Rational.prototype, {
2829
3194
  }
2830
3195
  },
2831
3196
 
2832
- negate: function() {
3197
+ negate: function () {
2833
3198
  return new Rational(-this.n, this.d);
2834
3199
  },
2835
3200
 
2836
- abs: function() {
3201
+ abs: function () {
2837
3202
  return new Rational(Math.abs(this.n), this.d);
2838
3203
  },
2839
3204
 
2840
- findGCD: function(factor) {
3205
+ findGCD: function (factor) {
2841
3206
  // Attempt to factor out common numerators and denominators to return
2842
3207
  // a Rational instead of a Float
2843
3208
  if (factor instanceof Rational) {
@@ -2855,7 +3220,7 @@ _.extend(Rational.prototype, {
2855
3220
  },
2856
3221
 
2857
3222
  // for now, assuming that exp is a Num
2858
- raiseToThe: function(exp) {
3223
+ raiseToThe: function (exp) {
2859
3224
  if (exp instanceof Int) {
2860
3225
  var positive = exp.eval() > 0;
2861
3226
  var abs = exp.abs().eval();
@@ -2871,87 +3236,120 @@ _.extend(Rational.prototype, {
2871
3236
  }
2872
3237
  },
2873
3238
 
2874
- getDenominator: function() {
3239
+ getDenominator: function () {
2875
3240
  return new Int(this.d);
2876
3241
  },
2877
3242
 
2878
- isSimple: function() { return false; },
3243
+ isSimple: function () {
3244
+ return false;
3245
+ },
2879
3246
 
2880
- asRational: function() { return this; }
3247
+ asRational: function () {
3248
+ return this;
3249
+ },
2881
3250
  });
2882
3251
 
2883
-
2884
3252
  /* integer (n: numerator/number) */
2885
- export function Int(number) { this.n = number; }
3253
+ export function Int(number) {
3254
+ this.n = number;
3255
+ }
2886
3256
  Int.prototype = new Rational(0, 1);
2887
3257
 
2888
3258
  _.extend(Int.prototype, {
2889
3259
  func: Int,
2890
- args: function() { return [this.n]; },
2891
- print: function() { return this.n.toString(); },
2892
- tex: function() { return this.n.toString(); },
2893
- negate: function() { return new Int(-this.n); },
2894
- abs: function() { return new Int(Math.abs(this.n)); },
2895
- isSimple: function() { return true; },
2896
- findGCD: function(factor) {
3260
+ args: function () {
3261
+ return [this.n];
3262
+ },
3263
+ print: function () {
3264
+ return this.n.toString();
3265
+ },
3266
+ tex: function () {
3267
+ return this.n.toString();
3268
+ },
3269
+ negate: function () {
3270
+ return new Int(-this.n);
3271
+ },
3272
+ abs: function () {
3273
+ return new Int(Math.abs(this.n));
3274
+ },
3275
+ isSimple: function () {
3276
+ return true;
3277
+ },
3278
+ findGCD: function (factor) {
2897
3279
  if (factor instanceof Int) {
2898
3280
  return new Int(Num.findGCD(this.n, factor.n));
2899
3281
  } else {
2900
3282
  return factor.findGCD(this);
2901
3283
  }
2902
- }
3284
+ },
2903
3285
  });
2904
3286
 
2905
3287
  _.extend(Int, {
2906
- create: function(n) { return new Int(n).addHint("entered"); }
3288
+ create: function (n) {
3289
+ return new Int(n).addHint("entered");
3290
+ },
2907
3291
  });
2908
3292
 
2909
3293
  /* float (n: number) */
2910
- export function Float(number) { this.n = number; }
3294
+ export function Float(number) {
3295
+ this.n = number;
3296
+ }
2911
3297
  Float.prototype = new Num();
2912
3298
 
2913
3299
  _.extend(Float.prototype, {
2914
3300
  func: Float,
2915
- args: function() { return [this.n]; },
2916
- eval: function() { return this.n; },
3301
+ args: function () {
3302
+ return [this.n];
3303
+ },
3304
+ eval: function () {
3305
+ return this.n;
3306
+ },
2917
3307
 
2918
3308
  // TODO(alex): when we internationalize number parsing/display
2919
3309
  // we should make sure to use the appropriate decimal mark here
2920
- print: function() { return this.n.toString(); },
2921
- tex: function() { return this.n.toString(); },
3310
+ print: function () {
3311
+ return this.n.toString();
3312
+ },
3313
+ tex: function () {
3314
+ return this.n.toString();
3315
+ },
2922
3316
 
2923
- add: function(num, options) {
3317
+ add: function (num, options) {
2924
3318
  if (options && options.preciseFloats) {
2925
3319
  return Float.toDecimalPlaces(
2926
3320
  this.n + num.eval(),
2927
- Math.max(this.getDecimalPlaces(), num.getDecimalPlaces())
3321
+ Math.max(this.getDecimalPlaces(), num.getDecimalPlaces()),
2928
3322
  );
2929
3323
  } else {
2930
3324
  return new Float(this.n + num.eval()).collect();
2931
3325
  }
2932
3326
  },
2933
3327
 
2934
- mul: function(num, options) {
3328
+ mul: function (num, options) {
2935
3329
  if (options && options.preciseFloats) {
2936
3330
  return Float.toDecimalPlaces(
2937
3331
  this.n * num.eval(),
2938
- this.getDecimalPlaces() + num.getDecimalPlaces()
3332
+ this.getDecimalPlaces() + num.getDecimalPlaces(),
2939
3333
  );
2940
3334
  } else {
2941
3335
  return new Float(this.n * num.eval()).collect();
2942
3336
  }
2943
3337
  },
2944
3338
 
2945
- collect: function() {
3339
+ collect: function () {
2946
3340
  // We used to simplify Floats to Ints here whenever possible, but no
2947
3341
  // longer do so in order to preserve significant figures.
2948
3342
  return this;
2949
3343
  },
2950
3344
 
2951
- negate: function() { return new Float(-this.n); },
2952
- abs: function() { return new Float(Math.abs(this.n)); },
3345
+ negate: function () {
3346
+ return new Float(-this.n);
3347
+ },
3348
+ abs: function () {
3349
+ return new Float(Math.abs(this.n));
3350
+ },
2953
3351
 
2954
- findGCD: function(factor) {
3352
+ findGCD: function (factor) {
2955
3353
  if (factor instanceof Num) {
2956
3354
  return new Float(Num.findGCD(this.eval(), factor.eval())).collect();
2957
3355
  } else {
@@ -2960,12 +3358,16 @@ _.extend(Float.prototype, {
2960
3358
  },
2961
3359
 
2962
3360
  // for now, assuming that exp is a Num
2963
- raiseToThe: function(exp, options) {
2964
- if (options && options.preciseFloats &&
2965
- exp instanceof Int && exp.n > 1) {
3361
+ raiseToThe: function (exp, options) {
3362
+ if (
3363
+ options &&
3364
+ options.preciseFloats &&
3365
+ exp instanceof Int &&
3366
+ exp.n > 1
3367
+ ) {
2966
3368
  return Float.toDecimalPlaces(
2967
3369
  new Pow(this, exp).eval(),
2968
- this.getDecimalPlaces() * exp.n
3370
+ this.getDecimalPlaces() * exp.n,
2969
3371
  );
2970
3372
  } else {
2971
3373
  return new Float(new Pow(this, exp).eval()).collect();
@@ -2973,7 +3375,7 @@ _.extend(Float.prototype, {
2973
3375
  },
2974
3376
 
2975
3377
  // only to be used on non-repeating decimals (e.g. user-provided)
2976
- asRational: function() {
3378
+ asRational: function () {
2977
3379
  var parts = this.n.toString().split(".");
2978
3380
  if (parts.length === 1) {
2979
3381
  return new Rational(this.n, 1);
@@ -2984,26 +3386,30 @@ _.extend(Float.prototype, {
2984
3386
  }
2985
3387
  },
2986
3388
 
2987
- getDenominator: function() {
3389
+ getDenominator: function () {
2988
3390
  return this.asRational().getDenominator();
2989
3391
  },
2990
3392
 
2991
- isSimple: function() { return true; }
3393
+ isSimple: function () {
3394
+ return true;
3395
+ },
2992
3396
  });
2993
3397
 
2994
3398
  _.extend(Float, {
2995
- create: function(n) { return new Float(n).addHint("entered"); },
3399
+ create: function (n) {
3400
+ return new Float(n).addHint("entered");
3401
+ },
2996
3402
 
2997
3403
  // Account for floating point imprecision by explicitly controlling the
2998
3404
  // number of decimal places in common operations (e.g. +, *, ^)
2999
- toDecimalPlaces: function(n, places) {
3405
+ toDecimalPlaces: function (n, places) {
3000
3406
  return new Float(+n.toFixed(Math.min(places, 20))).collect();
3001
- }
3407
+ },
3002
3408
  });
3003
3409
 
3004
3410
  // static methods and fields that are best defined on Num
3005
3411
  _.extend(Num, {
3006
- negativeOne: function(hint) {
3412
+ negativeOne: function (hint) {
3007
3413
  if (hint === "subtract") {
3008
3414
  return Num.Sub;
3009
3415
  } else if (hint === "divide") {
@@ -3014,7 +3420,7 @@ _.extend(Num, {
3014
3420
  },
3015
3421
 
3016
3422
  // find the greatest common denominator
3017
- findGCD: function(a, b) {
3423
+ findGCD: function (a, b) {
3018
3424
  var mod;
3019
3425
 
3020
3426
  a = Math.abs(a);
@@ -3036,17 +3442,17 @@ _.extend(Num, {
3036
3442
  return a;
3037
3443
  },
3038
3444
 
3039
- min: function() {
3040
- return _.min(_.toArray(arguments), function(num) {
3445
+ min: function () {
3446
+ return _.min(_.toArray(arguments), function (num) {
3041
3447
  return num.eval();
3042
3448
  });
3043
3449
  },
3044
3450
 
3045
- max: function() {
3046
- return _.max(_.toArray(arguments), function(num) {
3451
+ max: function () {
3452
+ return _.max(_.toArray(arguments), function (num) {
3047
3453
  return num.eval();
3048
3454
  });
3049
- }
3455
+ },
3050
3456
  });
3051
3457
 
3052
3458
  Num.Neg = new Int(-1).addHint("negate");
@@ -3059,12 +3465,11 @@ Num.Zero = new Int(0);
3059
3465
  Num.One = new Int(1);
3060
3466
  Num.Ten = new Int(10);
3061
3467
 
3062
-
3063
3468
  // set identities here
3064
3469
  Add.prototype.identity = Num.Zero;
3065
3470
  Mul.prototype.identity = Num.One;
3066
3471
 
3067
- var parseError = function(str, hash) {
3472
+ var parseError = function (str, hash) {
3068
3473
  // return int location of parsing error
3069
3474
  throw new Error(hash.loc.first_column);
3070
3475
  };
@@ -3087,7 +3492,7 @@ parser.yy = {
3087
3492
  parseError: parseError,
3088
3493
 
3089
3494
  constants: ["e"],
3090
- symbolLexer: function(symbol) {
3495
+ symbolLexer: function (symbol) {
3091
3496
  if (_.contains(parser.yy.constants, symbol)) {
3092
3497
  return "CONST";
3093
3498
  } else if (_.contains(parser.yy.functions, symbol)) {
@@ -3095,10 +3500,10 @@ parser.yy = {
3095
3500
  } else {
3096
3501
  return "VAR";
3097
3502
  }
3098
- }
3503
+ },
3099
3504
  };
3100
3505
 
3101
- export const parse = function(input, options) {
3506
+ export const parse = function (input, options) {
3102
3507
  try {
3103
3508
  if (options && options.functions) {
3104
3509
  // reserve the symbol "i" for complex numbers
@@ -3132,13 +3537,13 @@ Unit.prototype = new Symbol();
3132
3537
  //
3133
3538
  // "g" -> Unit("g")
3134
3539
  // "kg" -> 1000 * Unit("g")
3135
- var unprefixify = function(symbol) {
3540
+ var unprefixify = function (symbol) {
3136
3541
  if (_(baseUnits).has(symbol) || _(derivedUnits).has(symbol)) {
3137
3542
  return new Unit(symbol);
3138
3543
  }
3139
3544
 
3140
3545
  // check for prefix
3141
- var prefix = _(_(siPrefixes).keys()).find(function(testPrefix) {
3546
+ var prefix = _(_(siPrefixes).keys()).find(function (testPrefix) {
3142
3547
  return new RegExp("^" + testPrefix).test(symbol);
3143
3548
  });
3144
3549
 
@@ -3151,10 +3556,10 @@ var unprefixify = function(symbol) {
3151
3556
  //
3152
3557
  // Otherwise, we're trying to parse a unit label which is not
3153
3558
  // allowed (mwk, mBTU, etc).
3154
- if (_(baseUnits).has(base) ||
3155
- (derivedUnits[base] &&
3156
- derivedUnits[base].prefixes === hasPrefixes)) {
3157
-
3559
+ if (
3560
+ _(baseUnits).has(base) ||
3561
+ (derivedUnits[base] && derivedUnits[base].prefixes === hasPrefixes)
3562
+ ) {
3158
3563
  return new Mul(siPrefixes[prefix], new Unit(base));
3159
3564
  } else {
3160
3565
  throw new Error(base + " does not allow prefixes");
@@ -3164,7 +3569,7 @@ var unprefixify = function(symbol) {
3164
3569
  }
3165
3570
  };
3166
3571
 
3167
- export const unitParse = function(input) {
3572
+ export const unitParse = function (input) {
3168
3573
  try {
3169
3574
  var parseResult = unitParser.parse(input);
3170
3575
 
@@ -3185,15 +3590,15 @@ export const unitParse = function(input) {
3185
3590
 
3186
3591
  var unitArray = [];
3187
3592
 
3188
- _(parseResult.unit.num).each(function(unitSpec) {
3593
+ _(parseResult.unit.num).each(function (unitSpec) {
3189
3594
  unitArray.push(
3190
- new Pow(unprefixify(unitSpec.name), new Int(unitSpec.pow))
3595
+ new Pow(unprefixify(unitSpec.name), new Int(unitSpec.pow)),
3191
3596
  );
3192
3597
  });
3193
3598
 
3194
- _(parseResult.unit.denom).each(function(unitSpec) {
3599
+ _(parseResult.unit.denom).each(function (unitSpec) {
3195
3600
  unitArray.push(
3196
- new Pow(unprefixify(unitSpec.name), new Int(-1 * unitSpec.pow))
3601
+ new Pow(unprefixify(unitSpec.name), new Int(-1 * unitSpec.pow)),
3197
3602
  );
3198
3603
  });
3199
3604
 
@@ -3202,18 +3607,18 @@ export const unitParse = function(input) {
3202
3607
  if (parseResult.type === "unitMagnitude") {
3203
3608
  // in the first case we have a magnitude coefficient as well as the
3204
3609
  // unit itself.
3205
- var coefArray =
3206
- [new Float(+parseResult.magnitude)].concat(unitArray);
3610
+ var coefArray = [new Float(+parseResult.magnitude)].concat(
3611
+ unitArray,
3612
+ );
3207
3613
  var expr = new Mul(coefArray);
3208
3614
  return {
3209
3615
  parsed: true,
3210
3616
  unit: unit,
3211
3617
  expr: expr,
3212
3618
  coefficient: parseResult.magnitude,
3213
- type: parseResult.type
3619
+ type: parseResult.type,
3214
3620
  };
3215
3621
  } else {
3216
-
3217
3622
  // in the second case it's just the unit with no magnitude.
3218
3623
  return {
3219
3624
  parsed: true,
@@ -3228,10 +3633,14 @@ export const unitParse = function(input) {
3228
3633
 
3229
3634
  _.extend(Unit.prototype, {
3230
3635
  func: Unit,
3231
- args: function() { return [this.symbol]; },
3232
- recurse: function() { return this; },
3636
+ args: function () {
3637
+ return [this.symbol];
3638
+ },
3639
+ recurse: function () {
3640
+ return this;
3641
+ },
3233
3642
 
3234
- eval: function(vars, options) {
3643
+ eval: function (vars, options) {
3235
3644
  // This is called when comparing units. A unit doesn't affect the
3236
3645
  // numerical value of its coefficient, so this needs to be 1.
3237
3646
  //
@@ -3242,16 +3651,24 @@ _.extend(Unit.prototype, {
3242
3651
  return 1;
3243
3652
  },
3244
3653
 
3245
- getUnits: function() { return [{unit: this.symbol, pow: 1}]; },
3654
+ getUnits: function () {
3655
+ return [{unit: this.symbol, pow: 1}];
3656
+ },
3246
3657
 
3247
- codegen: function() { return "1"; },
3658
+ codegen: function () {
3659
+ return "1";
3660
+ },
3248
3661
 
3249
- print: function() { return this.symbol; },
3662
+ print: function () {
3663
+ return this.symbol;
3664
+ },
3250
3665
 
3251
- tex: function() { return this.symbol; },
3666
+ tex: function () {
3667
+ return this.symbol;
3668
+ },
3252
3669
 
3253
3670
  // Simplify units by replacing prefixes with multiplication
3254
- collect: function(options) {
3671
+ collect: function (options) {
3255
3672
  if (_(baseUnits).has(this.symbol)) {
3256
3673
  return this;
3257
3674
  } else if (_(derivedUnits).has(this.symbol)) {
@@ -3298,7 +3715,7 @@ var siPrefixes = {
3298
3715
  var hasPrefixes = {};
3299
3716
  var hasntPrefixes = {};
3300
3717
 
3301
- var makeAlias = function(str, prefixes) {
3718
+ var makeAlias = function (str, prefixes) {
3302
3719
  var splits = str.split("|");
3303
3720
  var coefficientStr = splits[0].trim();
3304
3721
  var unitsStr = splits[1].trim();
@@ -3314,9 +3731,10 @@ var makeAlias = function(str, prefixes) {
3314
3731
  if (numdenomStr[0]) {
3315
3732
  numdenomStr[0]
3316
3733
  .split(" ")
3317
- .filter(function(x) {
3734
+ .filter(function (x) {
3318
3735
  return x !== "";
3319
- }).map(function(x) {
3736
+ })
3737
+ .map(function (x) {
3320
3738
  numdenom.push(new Unit(x));
3321
3739
  });
3322
3740
  }
@@ -3324,9 +3742,10 @@ var makeAlias = function(str, prefixes) {
3324
3742
  if (numdenomStr[1]) {
3325
3743
  numdenomStr[1]
3326
3744
  .split(" ")
3327
- .filter(function(x) {
3745
+ .filter(function (x) {
3328
3746
  return x !== "";
3329
- }).map(function(x) {
3747
+ })
3748
+ .map(function (x) {
3330
3749
  numdenom.push(new Pow(new Unit(x), Num.Div));
3331
3750
  });
3332
3751
  }
@@ -3366,27 +3785,27 @@ var derivedUnits = {
3366
3785
  u: makeAlias("| Da", hasntPrefixes),
3367
3786
 
3368
3787
  // length
3369
- "meter": makeAlias("| m", hasntPrefixes),
3370
- "meters": makeAlias("| m", hasntPrefixes),
3371
- "in": makeAlias("254 / 10000 | m", hasntPrefixes),
3372
- "ft": makeAlias("3048 / 10000 | m", hasntPrefixes),
3373
- "yd": makeAlias("9144 / 10000 | m", hasntPrefixes),
3374
- "mi": makeAlias("1609344 / 1000 | m", hasntPrefixes),
3375
- "ly": makeAlias("9.4607 x 10^15 | m", hasntPrefixes),
3376
- "nmi": makeAlias("1852 | m", hasntPrefixes),
3377
- "Å": makeAlias("10^-10 | m", hasntPrefixes),
3378
- "pc": makeAlias("3.0857 x 10^16 | m", hasntPrefixes),
3788
+ meter: makeAlias("| m", hasntPrefixes),
3789
+ meters: makeAlias("| m", hasntPrefixes),
3790
+ in: makeAlias("254 / 10000 | m", hasntPrefixes),
3791
+ ft: makeAlias("3048 / 10000 | m", hasntPrefixes),
3792
+ yd: makeAlias("9144 / 10000 | m", hasntPrefixes),
3793
+ mi: makeAlias("1609344 / 1000 | m", hasntPrefixes),
3794
+ ly: makeAlias("9.4607 x 10^15 | m", hasntPrefixes),
3795
+ nmi: makeAlias("1852 | m", hasntPrefixes),
3796
+ Å: makeAlias("10^-10 | m", hasntPrefixes),
3797
+ pc: makeAlias("3.0857 x 10^16 | m", hasntPrefixes),
3379
3798
 
3380
3799
  // time
3381
- "min": makeAlias("60 | s", hasntPrefixes),
3382
- "hr": makeAlias("3600 | s", hasntPrefixes),
3383
- "sec": makeAlias("| s", hasntPrefixes),
3800
+ min: makeAlias("60 | s", hasntPrefixes),
3801
+ hr: makeAlias("3600 | s", hasntPrefixes),
3802
+ sec: makeAlias("| s", hasntPrefixes),
3384
3803
  // TODO(joel) make day work
3385
- "day": makeAlias("86400 | s", hasntPrefixes),
3386
- "wk": makeAlias("604800 | s", hasntPrefixes),
3387
- "fortnight": makeAlias("14 | day", hasntPrefixes),
3388
- "shake": makeAlias("10^-8 | s", hasntPrefixes),
3389
- "olympiad": makeAlias("126200000 | s", hasntPrefixes),
3804
+ day: makeAlias("86400 | s", hasntPrefixes),
3805
+ wk: makeAlias("604800 | s", hasntPrefixes),
3806
+ fortnight: makeAlias("14 | day", hasntPrefixes),
3807
+ shake: makeAlias("10^-8 | s", hasntPrefixes),
3808
+ olympiad: makeAlias("126200000 | s", hasntPrefixes),
3390
3809
 
3391
3810
  // temperature
3392
3811
  "°C": makeAlias("1 | K", hasntPrefixes),
@@ -3394,113 +3813,113 @@ var derivedUnits = {
3394
3813
  "°R": makeAlias("5/9 | K", hasntPrefixes),
3395
3814
 
3396
3815
  // electric charge
3397
- "e": makeAlias("1.6021765314 x 10^-19 | C", hasntPrefixes),
3816
+ e: makeAlias("1.6021765314 x 10^-19 | C", hasntPrefixes),
3398
3817
 
3399
3818
  // speed
3400
- "c": makeAlias("299792458 | m / s", hasntPrefixes),
3401
- "kn": makeAlias("514/1000 | m / s", hasntPrefixes),
3402
- "kt": makeAlias("| kn", hasntPrefixes),
3403
- "knot": makeAlias("| kn", hasntPrefixes),
3819
+ c: makeAlias("299792458 | m / s", hasntPrefixes),
3820
+ kn: makeAlias("514/1000 | m / s", hasntPrefixes),
3821
+ kt: makeAlias("| kn", hasntPrefixes),
3822
+ knot: makeAlias("| kn", hasntPrefixes),
3404
3823
 
3405
3824
  // energy
3406
- "J": makeAlias("| N m", hasPrefixes),
3407
- "BTU": makeAlias("1060 | J", hasntPrefixes),
3408
- "cal": makeAlias("4184 / 1000 | J", hasPrefixes),
3409
- "eV": makeAlias("1.602176514 x 10^-19 | J", hasPrefixes),
3410
- "erg": makeAlias("10^−7 | J", hasPrefixes),
3825
+ J: makeAlias("| N m", hasPrefixes),
3826
+ BTU: makeAlias("1060 | J", hasntPrefixes),
3827
+ cal: makeAlias("4184 / 1000 | J", hasPrefixes),
3828
+ eV: makeAlias("1.602176514 x 10^-19 | J", hasPrefixes),
3829
+ erg: makeAlias("10^−7 | J", hasPrefixes),
3411
3830
 
3412
3831
  // power
3413
- "W": makeAlias("| J / s", hasPrefixes),
3832
+ W: makeAlias("| J / s", hasPrefixes),
3414
3833
  "H-e": makeAlias("80 | W", hasntPrefixes),
3415
3834
 
3416
3835
  // force
3417
- "N": makeAlias("1000 | g m / s s", hasPrefixes),
3836
+ N: makeAlias("1000 | g m / s s", hasPrefixes),
3418
3837
  // "lb": makeAlias("4448 / 1000 | N", hasntPrefixes),
3419
3838
  // 4.4482216152605
3420
- "lb": makeAlias("4448221615 / 1000000000 | N", hasntPrefixes),
3421
- "dyn": makeAlias("10^-5 | N", hasntPrefixes),
3839
+ lb: makeAlias("4448221615 / 1000000000 | N", hasntPrefixes),
3840
+ dyn: makeAlias("10^-5 | N", hasntPrefixes),
3422
3841
 
3423
3842
  // pressure
3424
- "Pa": makeAlias("1 | N / m m m", hasPrefixes),
3425
- "bar": makeAlias("10^5 | Pa", hasPrefixes),
3843
+ Pa: makeAlias("1 | N / m m m", hasPrefixes),
3844
+ bar: makeAlias("10^5 | Pa", hasPrefixes),
3426
3845
  "㏔": makeAlias("1/1000 | bar", hasntPrefixes),
3427
3846
  "㍴": makeAlias("| bar", hasntPrefixes),
3428
- "atm": makeAlias("101325 | Pa", hasntPrefixes),
3429
- "Torr": makeAlias("1/760 | atm", hasntPrefixes),
3430
- "mmHg": makeAlias("| Torr", hasntPrefixes),
3847
+ atm: makeAlias("101325 | Pa", hasntPrefixes),
3848
+ Torr: makeAlias("1/760 | atm", hasntPrefixes),
3849
+ mmHg: makeAlias("| Torr", hasntPrefixes),
3431
3850
 
3432
3851
  // area
3433
- "ha": makeAlias("10^4 | m m", hasntPrefixes),
3434
- "b": makeAlias("10^−28 | m m", hasPrefixes),
3435
- "barn": makeAlias("| b", hasPrefixes),
3436
- "acre": makeAlias("4046.87 | m m", hasntPrefixes),
3437
- "skilodge": makeAlias("10^-31 | m m", hasntPrefixes),
3438
- "outhouse": makeAlias("10^-34 | m m", hasntPrefixes),
3439
- "shed": makeAlias("10^-52 | m m", hasntPrefixes),
3852
+ ha: makeAlias("10^4 | m m", hasntPrefixes),
3853
+ b: makeAlias("10^−28 | m m", hasPrefixes),
3854
+ barn: makeAlias("| b", hasPrefixes),
3855
+ acre: makeAlias("4046.87 | m m", hasntPrefixes),
3856
+ skilodge: makeAlias("10^-31 | m m", hasntPrefixes),
3857
+ outhouse: makeAlias("10^-34 | m m", hasntPrefixes),
3858
+ shed: makeAlias("10^-52 | m m", hasntPrefixes),
3440
3859
 
3441
3860
  // volume
3442
- "L": makeAlias("1/1000 | m m m", hasPrefixes),
3443
- "gal": makeAlias("3785/1000 | L", hasPrefixes),
3444
- "cup": makeAlias("1/16 | gal", hasntPrefixes),
3445
- "qt": makeAlias("1/4 | gal", hasntPrefixes),
3446
- "quart": makeAlias("| qt", hasntPrefixes),
3447
- "p": makeAlias("1/8 | gal", hasntPrefixes),
3448
- "pt": makeAlias("| p", hasntPrefixes),
3449
- "pint": makeAlias("| p", hasntPrefixes),
3861
+ L: makeAlias("1/1000 | m m m", hasPrefixes),
3862
+ gal: makeAlias("3785/1000 | L", hasPrefixes),
3863
+ cup: makeAlias("1/16 | gal", hasntPrefixes),
3864
+ qt: makeAlias("1/4 | gal", hasntPrefixes),
3865
+ quart: makeAlias("| qt", hasntPrefixes),
3866
+ p: makeAlias("1/8 | gal", hasntPrefixes),
3867
+ pt: makeAlias("| p", hasntPrefixes),
3868
+ pint: makeAlias("| p", hasntPrefixes),
3450
3869
  "fl oz": makeAlias("1/8 | cup", hasntPrefixes),
3451
3870
  "fl. oz.": makeAlias("1/8 | cup", hasntPrefixes),
3452
- "tbsp": makeAlias("1/16 | cup", hasntPrefixes),
3453
- "tsp": makeAlias("1/3 | tbsp", hasntPrefixes),
3871
+ tbsp: makeAlias("1/16 | cup", hasntPrefixes),
3872
+ tsp: makeAlias("1/3 | tbsp", hasntPrefixes),
3454
3873
 
3455
3874
  // rotational
3456
3875
  // "rad":
3457
- "rev": makeAlias("2 pi | rad", hasntPrefixes),
3458
- "deg": makeAlias("180 pi | rad", hasntPrefixes),
3876
+ rev: makeAlias("2 pi | rad", hasntPrefixes),
3877
+ deg: makeAlias("180 pi | rad", hasntPrefixes),
3459
3878
  "°": makeAlias("| deg", hasntPrefixes),
3460
- "arcminute": makeAlias("1/60 | deg", hasntPrefixes),
3461
- "arcsec": makeAlias("1/3600 | deg", hasntPrefixes),
3879
+ arcminute: makeAlias("1/60 | deg", hasntPrefixes),
3880
+ arcsec: makeAlias("1/3600 | deg", hasntPrefixes),
3462
3881
 
3463
3882
  // dimensionless
3464
3883
  // "B": makeAlias("10 | dB", hasntPrefixes), // XXX danger - logarithmic
3465
3884
  // "dB"
3466
3885
  // "nP"
3467
- "Hu": makeAlias("1000 | dB", hasPrefixes),
3468
- "dozen": makeAlias("12 |", hasntPrefixes),
3886
+ Hu: makeAlias("1000 | dB", hasPrefixes),
3887
+ dozen: makeAlias("12 |", hasntPrefixes),
3469
3888
  // XXX
3470
- "mol": makeAlias("6.0221412927 x 10^23 |", hasPrefixes),
3889
+ mol: makeAlias("6.0221412927 x 10^23 |", hasPrefixes),
3471
3890
  "%": makeAlias("1/100 |", hasntPrefixes),
3472
- "percent": makeAlias("| %", hasntPrefixes),
3473
- "ppm": makeAlias("1/1000000 |", hasntPrefixes),
3891
+ percent: makeAlias("| %", hasntPrefixes),
3892
+ ppm: makeAlias("1/1000000 |", hasntPrefixes),
3474
3893
 
3475
3894
  // electric / magnetic
3476
- "V": makeAlias("1000 | g m m / s s C", hasPrefixes),
3477
- "C": makeAlias("| A s", hasPrefixes),
3478
- "ampere": makeAlias("| A", hasntPrefixes),
3479
- "Ω": makeAlias("| V / A", hasPrefixes),
3480
- "ohm": makeAlias("| Ω", hasntPrefixes),
3481
- "F": makeAlias("| C / V", hasPrefixes),
3482
- "H": makeAlias("| ohm s", hasPrefixes),
3483
- "T": makeAlias("1000 | g / C s", hasPrefixes),
3484
- "Wb": makeAlias("1000 | g m m / C s", hasPrefixes),
3895
+ V: makeAlias("1000 | g m m / s s C", hasPrefixes),
3896
+ C: makeAlias("| A s", hasPrefixes),
3897
+ ampere: makeAlias("| A", hasntPrefixes),
3898
+ Ω: makeAlias("| V / A", hasPrefixes),
3899
+ ohm: makeAlias("| Ω", hasntPrefixes),
3900
+ F: makeAlias("| C / V", hasPrefixes),
3901
+ H: makeAlias("| ohm s", hasPrefixes),
3902
+ T: makeAlias("1000 | g / C s", hasPrefixes),
3903
+ Wb: makeAlias("1000 | g m m / C s", hasPrefixes),
3485
3904
 
3486
3905
  // photometry
3487
3906
  // TODO not sure this is right
3488
- "lm": makeAlias("pi x 10^4 | cd / m m", hasntPrefixes),
3489
- "lx": makeAlias("| lm / m m", hasntPrefixes),
3490
- "nit": makeAlias("| cd / m m", hasntPrefixes),
3491
- "sb": makeAlias("10^4 | cd / m m", hasntPrefixes),
3492
- "stilb": makeAlias("1 | sb", hasntPrefixes),
3493
- "apostilb": makeAlias("1 / pi x 10^(-4) | sb", hasntPrefixes),
3494
- "blondel": makeAlias("| apostilb", hasntPrefixes),
3495
- "asb": makeAlias("| apostilb", hasntPrefixes),
3496
- "la": makeAlias("| lm", hasntPrefixes),
3497
- "Lb": makeAlias("| lm", hasntPrefixes),
3498
- "sk": makeAlias("10^-7 | lm", hasntPrefixes),
3499
- "skot": makeAlias("| sk", hasntPrefixes),
3500
- "bril": makeAlias("10^-11 | lm", hasntPrefixes),
3907
+ lm: makeAlias("pi x 10^4 | cd / m m", hasntPrefixes),
3908
+ lx: makeAlias("| lm / m m", hasntPrefixes),
3909
+ nit: makeAlias("| cd / m m", hasntPrefixes),
3910
+ sb: makeAlias("10^4 | cd / m m", hasntPrefixes),
3911
+ stilb: makeAlias("1 | sb", hasntPrefixes),
3912
+ apostilb: makeAlias("1 / pi x 10^(-4) | sb", hasntPrefixes),
3913
+ blondel: makeAlias("| apostilb", hasntPrefixes),
3914
+ asb: makeAlias("| apostilb", hasntPrefixes),
3915
+ la: makeAlias("| lm", hasntPrefixes),
3916
+ Lb: makeAlias("| lm", hasntPrefixes),
3917
+ sk: makeAlias("10^-7 | lm", hasntPrefixes),
3918
+ skot: makeAlias("| sk", hasntPrefixes),
3919
+ bril: makeAlias("10^-11 | lm", hasntPrefixes),
3501
3920
 
3502
3921
  // other
3503
- "Hz": makeAlias("| / s", hasPrefixes),
3922
+ Hz: makeAlias("| / s", hasPrefixes),
3504
3923
  };
3505
3924
 
3506
3925
  export const Zero = Num.Zero;