mathjs 10.0.0 → 10.1.1

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.
Files changed (70) hide show
  1. package/HISTORY.md +37 -0
  2. package/NOTICE +1 -1
  3. package/README.md +10 -2
  4. package/bin/cli.js +1 -1
  5. package/docs/expressions/syntax.md +1 -1
  6. package/docs/reference/constants.md +1 -1
  7. package/docs/reference/functions/invmod.md +41 -0
  8. package/docs/reference/functions/simplify.md +8 -5
  9. package/docs/reference/functions.md +1 -0
  10. package/examples/expressions.js +1 -1
  11. package/lib/browser/math.js +7 -7
  12. package/lib/browser/math.js.map +1 -1
  13. package/lib/cjs/entry/dependenciesAny/dependenciesIntersect.generated.js +6 -0
  14. package/lib/cjs/entry/dependenciesAny/dependenciesInvmod.generated.js +41 -0
  15. package/lib/cjs/entry/dependenciesAny/dependenciesRationalize.generated.js +15 -0
  16. package/lib/cjs/entry/dependenciesAny/dependenciesSimplify.generated.js +15 -0
  17. package/lib/cjs/entry/dependenciesAny.generated.js +8 -0
  18. package/lib/cjs/entry/dependenciesNumber/dependenciesRationalize.generated.js +15 -0
  19. package/lib/cjs/entry/dependenciesNumber/dependenciesSimplify.generated.js +15 -0
  20. package/lib/cjs/entry/impureFunctionsAny.generated.js +11 -0
  21. package/lib/cjs/entry/impureFunctionsNumber.generated.js +10 -0
  22. package/lib/cjs/entry/pureFunctionsAny.generated.js +16 -2
  23. package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +6 -1
  24. package/lib/cjs/expression/embeddedDocs/function/arithmetic/invmod.js +15 -0
  25. package/lib/cjs/expression/embeddedDocs/function/matrix/forEach.js +1 -1
  26. package/lib/cjs/factoriesAny.js +8 -0
  27. package/lib/cjs/function/algebra/rationalize.js +18 -4
  28. package/lib/cjs/function/algebra/simplify/simplifyConstant.js +223 -29
  29. package/lib/cjs/function/algebra/simplify/simplifyCore.js +34 -6
  30. package/lib/cjs/function/algebra/simplify.js +103 -30
  31. package/lib/cjs/function/arithmetic/invmod.js +73 -0
  32. package/lib/cjs/function/arithmetic/round.js +2 -2
  33. package/lib/cjs/function/geometry/intersect.js +12 -13
  34. package/lib/cjs/function/probability/gamma.js +28 -30
  35. package/lib/cjs/header.js +3 -3
  36. package/lib/cjs/type/matrix/SparseMatrix.js +19 -15
  37. package/lib/cjs/type/unit/Unit.js +2 -2
  38. package/lib/cjs/utils/number.js +1 -1
  39. package/lib/cjs/utils/snapshot.js +2 -2
  40. package/lib/cjs/version.js +1 -1
  41. package/lib/esm/entry/dependenciesAny/dependenciesIntersect.generated.js +4 -0
  42. package/lib/esm/entry/dependenciesAny/dependenciesInvmod.generated.js +24 -0
  43. package/lib/esm/entry/dependenciesAny/dependenciesRationalize.generated.js +10 -0
  44. package/lib/esm/entry/dependenciesAny/dependenciesSimplify.generated.js +10 -0
  45. package/lib/esm/entry/dependenciesAny.generated.js +1 -0
  46. package/lib/esm/entry/dependenciesNumber/dependenciesRationalize.generated.js +10 -0
  47. package/lib/esm/entry/dependenciesNumber/dependenciesSimplify.generated.js +10 -0
  48. package/lib/esm/entry/impureFunctionsAny.generated.js +12 -1
  49. package/lib/esm/entry/impureFunctionsNumber.generated.js +10 -0
  50. package/lib/esm/entry/pureFunctionsAny.generated.js +14 -1
  51. package/lib/esm/expression/embeddedDocs/embeddedDocs.js +4 -1
  52. package/lib/esm/expression/embeddedDocs/function/arithmetic/invmod.js +8 -0
  53. package/lib/esm/expression/embeddedDocs/function/matrix/forEach.js +1 -1
  54. package/lib/esm/factoriesAny.js +1 -0
  55. package/lib/esm/function/algebra/rationalize.js +18 -4
  56. package/lib/esm/function/algebra/simplify/simplifyConstant.js +197 -29
  57. package/lib/esm/function/algebra/simplify/simplifyCore.js +35 -7
  58. package/lib/esm/function/algebra/simplify.js +103 -30
  59. package/lib/esm/function/arithmetic/invmod.js +57 -0
  60. package/lib/esm/function/arithmetic/round.js +2 -2
  61. package/lib/esm/function/geometry/intersect.js +12 -12
  62. package/lib/esm/function/probability/gamma.js +28 -30
  63. package/lib/esm/header.js +1 -1
  64. package/lib/esm/type/matrix/SparseMatrix.js +19 -15
  65. package/lib/esm/type/unit/Unit.js +2 -2
  66. package/lib/esm/utils/number.js +1 -1
  67. package/lib/esm/utils/snapshot.js +2 -2
  68. package/lib/esm/version.js +1 -1
  69. package/package.json +15 -14
  70. package/types/index.d.ts +4 -4
@@ -1,10 +1,14 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
3
5
  Object.defineProperty(exports, "__esModule", {
4
6
  value: true
5
7
  });
6
8
  exports.createSimplifyConstant = void 0;
7
9
 
10
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
11
+
8
12
  var _is = require("../../../utils/is.js");
9
13
 
10
14
  var _factory = require("../../../utils/factory.js");
@@ -13,18 +17,28 @@ var _util = require("./util.js");
13
17
 
14
18
  var _noop = require("../../../utils/noop.js");
15
19
 
16
- // TODO this could be improved by simplifying seperated constants under associative and commutative operators
20
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
21
+
22
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
23
+
24
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
25
+
17
26
  var name = 'simplifyConstant';
18
- var dependencies = ['typed', 'config', 'mathWithTransform', '?fraction', '?bignumber', 'ConstantNode', 'OperatorNode', 'FunctionNode', 'SymbolNode'];
27
+ var dependencies = ['typed', 'config', 'mathWithTransform', 'matrix', '?fraction', '?bignumber', 'AccessorNode', 'ArrayNode', 'ConstantNode', 'FunctionNode', 'IndexNode', 'ObjectNode', 'OperatorNode', 'SymbolNode'];
19
28
  var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
20
29
  var typed = _ref.typed,
21
30
  config = _ref.config,
22
31
  mathWithTransform = _ref.mathWithTransform,
32
+ matrix = _ref.matrix,
23
33
  fraction = _ref.fraction,
24
34
  bignumber = _ref.bignumber,
35
+ AccessorNode = _ref.AccessorNode,
36
+ ArrayNode = _ref.ArrayNode,
25
37
  ConstantNode = _ref.ConstantNode,
26
- OperatorNode = _ref.OperatorNode,
27
38
  FunctionNode = _ref.FunctionNode,
39
+ IndexNode = _ref.IndexNode,
40
+ ObjectNode = _ref.ObjectNode,
41
+ OperatorNode = _ref.OperatorNode,
28
42
  SymbolNode = _ref.SymbolNode;
29
43
 
30
44
  var _createUtil = (0, _util.createUtil)({
@@ -38,22 +52,31 @@ var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependen
38
52
  createMakeNodeFunction = _createUtil.createMakeNodeFunction;
39
53
 
40
54
  function simplifyConstant(expr, options) {
41
- var res = foldFraction(expr, options);
42
- return (0, _is.isNode)(res) ? res : _toNode(res);
55
+ return _ensureNode(foldFraction(expr, options));
56
+ }
57
+
58
+ function _removeFractions(thing) {
59
+ if ((0, _is.isFraction)(thing)) {
60
+ return thing.valueOf();
61
+ }
62
+
63
+ if (thing instanceof Array) {
64
+ return thing.map(_removeFractions);
65
+ }
66
+
67
+ if ((0, _is.isMatrix)(thing)) {
68
+ return matrix(_removeFractions(thing.valueOf()));
69
+ }
70
+
71
+ return thing;
43
72
  }
44
73
 
45
74
  function _eval(fnname, args, options) {
46
75
  try {
47
- return _toNumber(mathWithTransform[fnname].apply(null, args), options);
76
+ return mathWithTransform[fnname].apply(null, args);
48
77
  } catch (ignore) {
49
78
  // sometimes the implicit type conversion causes the evaluation to fail, so we'll try again after removing Fractions
50
- args = args.map(function (x) {
51
- if ((0, _is.isFraction)(x)) {
52
- return x.valueOf();
53
- }
54
-
55
- return x;
56
- });
79
+ args = args.map(_removeFractions);
57
80
  return _toNumber(mathWithTransform[fnname].apply(null, args), options);
58
81
  }
59
82
  }
@@ -76,8 +99,24 @@ var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependen
76
99
  },
77
100
  Complex: function Complex(s) {
78
101
  throw new Error('Cannot convert Complex number to Node');
102
+ },
103
+ string: function string(s) {
104
+ return new ConstantNode(s);
105
+ },
106
+ Matrix: function Matrix(m) {
107
+ return new ArrayNode(m.valueOf().map(function (e) {
108
+ return _toNode(e);
109
+ }));
110
+ }
111
+ });
112
+
113
+ function _ensureNode(thing) {
114
+ if ((0, _is.isNode)(thing)) {
115
+ return thing;
79
116
  }
80
- }); // convert a number to a fraction only if it can be expressed exactly,
117
+
118
+ return _toNode(thing);
119
+ } // convert a number to a fraction only if it can be expressed exactly,
81
120
  // and when both numerator and denominator are small enough
82
121
 
83
122
 
@@ -134,6 +173,12 @@ var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependen
134
173
  }
135
174
 
136
175
  return _exactFraction(s.re, options);
176
+ },
177
+ 'Matrix, Object': function MatrixObject(s, options) {
178
+ return matrix(_exactFraction(s.valueOf()));
179
+ },
180
+ 'Array, Object': function ArrayObject(s, options) {
181
+ return s.map(_exactFraction);
137
182
  }
138
183
  });
139
184
 
@@ -157,6 +202,114 @@ var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependen
157
202
 
158
203
  return new OperatorNode('/', 'divide', [n, new ConstantNode(f.d)]);
159
204
  }
205
+ /* Handles constant indexing of ArrayNodes, matrices, and ObjectNodes */
206
+
207
+
208
+ function _foldAccessor(obj, index, options) {
209
+ if (!(0, _is.isIndexNode)(index)) {
210
+ // don't know what to do with that...
211
+ return new AccessorNode(_ensureNode(obj), _ensureNode(index));
212
+ }
213
+
214
+ if ((0, _is.isArrayNode)(obj) || (0, _is.isMatrix)(obj)) {
215
+ var remainingDims = Array.from(index.dimensions);
216
+ /* We will resolve constant indices one at a time, looking
217
+ * just in the first or second dimensions because (a) arrays
218
+ * of more than two dimensions are likely rare, and (b) pulling
219
+ * out the third or higher dimension would be pretty intricate.
220
+ * The price is that we miss simplifying [..3d array][x,y,1]
221
+ */
222
+
223
+ while (remainingDims.length > 0) {
224
+ if ((0, _is.isConstantNode)(remainingDims[0]) && typeof remainingDims[0].value !== 'string') {
225
+ var first = _toNumber(remainingDims.shift().value, options);
226
+
227
+ if ((0, _is.isArrayNode)(obj)) {
228
+ obj = obj.items[first - 1];
229
+ } else {
230
+ // matrix
231
+ obj = obj.valueOf()[first - 1];
232
+
233
+ if (obj instanceof Array) {
234
+ obj = matrix(obj);
235
+ }
236
+ }
237
+ } else if (remainingDims.length > 1 && (0, _is.isConstantNode)(remainingDims[1]) && typeof remainingDims[1].value !== 'string') {
238
+ var second = _toNumber(remainingDims[1].value, options);
239
+
240
+ var tryItems = [];
241
+ var fromItems = (0, _is.isArrayNode)(obj) ? obj.items : obj.valueOf();
242
+
243
+ var _iterator = _createForOfIteratorHelper(fromItems),
244
+ _step;
245
+
246
+ try {
247
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
248
+ var item = _step.value;
249
+
250
+ if ((0, _is.isArrayNode)(item)) {
251
+ tryItems.push(item.items[second - 1]);
252
+ } else if ((0, _is.isMatrix)(obj)) {
253
+ tryItems.push(item[second - 1]);
254
+ } else {
255
+ break;
256
+ }
257
+ }
258
+ } catch (err) {
259
+ _iterator.e(err);
260
+ } finally {
261
+ _iterator.f();
262
+ }
263
+
264
+ if (tryItems.length === fromItems.length) {
265
+ if ((0, _is.isArrayNode)(obj)) {
266
+ obj = new ArrayNode(tryItems);
267
+ } else {
268
+ // matrix
269
+ obj = matrix(tryItems);
270
+ }
271
+
272
+ remainingDims.splice(1, 1);
273
+ } else {
274
+ // extracting slice along 2nd dimension failed, give up
275
+ break;
276
+ }
277
+ } else {
278
+ // neither 1st or 2nd dimension is constant, give up
279
+ break;
280
+ }
281
+ }
282
+
283
+ if (remainingDims.length === index.dimensions.length) {
284
+ /* No successful constant indexing */
285
+ return new AccessorNode(_ensureNode(obj), index);
286
+ }
287
+
288
+ if (remainingDims.length > 0) {
289
+ /* Indexed some but not all dimensions */
290
+ index = new IndexNode(remainingDims);
291
+ return new AccessorNode(_ensureNode(obj), index);
292
+ }
293
+ /* All dimensions were constant, access completely resolved */
294
+
295
+
296
+ return obj;
297
+ }
298
+
299
+ if ((0, _is.isObjectNode)(obj) && index.dimensions.length === 1 && (0, _is.isConstantNode)(index.dimensions[0])) {
300
+ var key = index.dimensions[0].value;
301
+
302
+ if (key in obj.properties) {
303
+ return obj.properties[key];
304
+ }
305
+
306
+ return new ConstantNode(); // undefined
307
+ }
308
+ /* Don't know how to index this sort of obj, at least not with this index */
309
+
310
+
311
+ return new AccessorNode(_ensureNode(obj), index);
312
+ }
160
313
  /*
161
314
  * Create a binary tree from a list of Fractions and Nodes.
162
315
  * Tries to fold Fractions by evaluating them until the first Node in the list is hit, so
@@ -195,8 +348,15 @@ var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependen
195
348
  return node;
196
349
 
197
350
  case 'ConstantNode':
198
- if (typeof node.value === 'number' || !isNaN(node.value)) {
199
- return _toNumber(node.value, options);
351
+ switch ((0, _typeof2["default"])(node.value)) {
352
+ case 'number':
353
+ return _toNumber(node.value, options);
354
+
355
+ case 'string':
356
+ return node.value;
357
+
358
+ default:
359
+ if (!isNaN(node.value)) return _toNumber(node.value, options);
200
360
  }
201
361
 
202
362
  return node;
@@ -218,14 +378,24 @@ var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependen
218
378
  if (!args.some(_is.isNode)) {
219
379
  try {
220
380
  return _eval(node.name, args, options);
221
- } catch (ignoreandcontine) {}
381
+ } catch (ignoreandcontinue) {}
382
+ } // Size of a matrix does not depend on entries
383
+
384
+
385
+ if (node.name === 'size' && args.length === 1 && (0, _is.isArrayNode)(args[0])) {
386
+ var sz = [];
387
+ var section = args[0];
388
+
389
+ while ((0, _is.isArrayNode)(section)) {
390
+ sz.push(section.items.length);
391
+ section = section.items[0];
392
+ }
393
+
394
+ return matrix(sz);
222
395
  } // Convert all args to nodes and construct a symbolic function call
223
396
 
224
397
 
225
- args = args.map(function (arg) {
226
- return (0, _is.isNode)(arg) ? arg : _toNode(arg);
227
- });
228
- return new FunctionNode(node.name, args);
398
+ return new FunctionNode(node.name, args.map(_ensureNode));
229
399
  } else {// treat as operator
230
400
  }
231
401
  }
@@ -296,10 +466,40 @@ var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependen
296
466
  return foldFraction(node.content, options);
297
467
 
298
468
  case 'AccessorNode':
299
- /* falls through */
469
+ return _foldAccessor(foldFraction(node.object, options), foldFraction(node.index, options), options);
300
470
 
301
471
  case 'ArrayNode':
302
- /* falls through */
472
+ {
473
+ var foldItems = node.items.map(function (item) {
474
+ return foldFraction(item, options);
475
+ });
476
+
477
+ if (foldItems.some(_is.isNode)) {
478
+ return new ArrayNode(foldItems.map(_ensureNode));
479
+ }
480
+ /* All literals -- return a Matrix so we can operate on it */
481
+
482
+
483
+ return matrix(foldItems);
484
+ }
485
+
486
+ case 'IndexNode':
487
+ {
488
+ return new IndexNode(node.dimensions.map(function (n) {
489
+ return simplifyConstant(n, options);
490
+ }));
491
+ }
492
+
493
+ case 'ObjectNode':
494
+ {
495
+ var foldProps = {};
496
+
497
+ for (var prop in node.properties) {
498
+ foldProps[prop] = simplifyConstant(node.properties[prop], options);
499
+ }
500
+
501
+ return new ObjectNode(foldProps);
502
+ }
303
503
 
304
504
  case 'AssignmentNode':
305
505
  /* falls through */
@@ -310,12 +510,6 @@ var createSimplifyConstant = /* #__PURE__ */(0, _factory.factory)(name, dependen
310
510
  case 'FunctionAssignmentNode':
311
511
  /* falls through */
312
512
 
313
- case 'IndexNode':
314
- /* falls through */
315
-
316
- case 'ObjectNode':
317
- /* falls through */
318
-
319
513
  case 'RangeNode':
320
514
  /* falls through */
321
515
 
@@ -10,7 +10,7 @@ var _is = require("../../../utils/is.js");
10
10
  var _factory = require("../../../utils/factory.js");
11
11
 
12
12
  var name = 'simplifyCore';
13
- var dependencies = ['equal', 'isZero', 'add', 'subtract', 'multiply', 'divide', 'pow', 'ConstantNode', 'OperatorNode', 'FunctionNode', 'ParenthesisNode'];
13
+ var dependencies = ['equal', 'isZero', 'add', 'subtract', 'multiply', 'divide', 'pow', 'AccessorNode', 'ArrayNode', 'ConstantNode', 'FunctionNode', 'IndexNode', 'ObjectNode', 'OperatorNode', 'ParenthesisNode'];
14
14
  var createSimplifyCore = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
15
15
  var equal = _ref.equal,
16
16
  isZero = _ref.isZero,
@@ -19,12 +19,22 @@ var createSimplifyCore = /* #__PURE__ */(0, _factory.factory)(name, dependencies
19
19
  multiply = _ref.multiply,
20
20
  divide = _ref.divide,
21
21
  pow = _ref.pow,
22
+ AccessorNode = _ref.AccessorNode,
23
+ ArrayNode = _ref.ArrayNode,
22
24
  ConstantNode = _ref.ConstantNode,
23
- OperatorNode = _ref.OperatorNode,
24
25
  FunctionNode = _ref.FunctionNode,
26
+ IndexNode = _ref.IndexNode,
27
+ ObjectNode = _ref.ObjectNode,
28
+ OperatorNode = _ref.OperatorNode,
25
29
  ParenthesisNode = _ref.ParenthesisNode;
26
30
  var node0 = new ConstantNode(0);
27
31
  var node1 = new ConstantNode(1);
32
+
33
+ function mapSimplifyCore(nodeArray) {
34
+ return nodeArray.map(simplifyCore).map(function (arg) {
35
+ return (0, _is.isParenthesisNode)(arg) ? arg.content : arg;
36
+ });
37
+ }
28
38
  /**
29
39
  * simplifyCore() performs single pass simplification suitable for
30
40
  * applications requiring ultimate performance. In contrast, simplify()
@@ -49,6 +59,7 @@ var createSimplifyCore = /* #__PURE__ */(0, _factory.factory)(name, dependencies
49
59
  * The expression to be simplified
50
60
  */
51
61
 
62
+
52
63
  function simplifyCore(node) {
53
64
  if ((0, _is.isOperatorNode)(node) && node.isUnary()) {
54
65
  var a0 = simplifyCore(node.args[0]);
@@ -184,10 +195,27 @@ var createSimplifyCore = /* #__PURE__ */(0, _factory.factory)(name, dependencies
184
195
 
185
196
  return new ParenthesisNode(c);
186
197
  } else if ((0, _is.isFunctionNode)(node)) {
187
- var args = node.args.map(simplifyCore).map(function (arg) {
188
- return (0, _is.isParenthesisNode)(arg) ? arg.content : arg;
189
- });
190
- return new FunctionNode(simplifyCore(node.fn), args);
198
+ return new FunctionNode(simplifyCore(node.fn), mapSimplifyCore(node.args));
199
+ } else if ((0, _is.isArrayNode)(node)) {
200
+ return new ArrayNode(mapSimplifyCore(node.items));
201
+ } else if ((0, _is.isAccessorNode)(node)) {
202
+ var obj = mapSimplifyCore(node.object);
203
+
204
+ if ((0, _is.isParenthesisNode)(obj)) {
205
+ obj = obj.content;
206
+ }
207
+
208
+ return new AccessorNode(obj, simplifyCore(node.index));
209
+ } else if ((0, _is.isIndexNode)(node)) {
210
+ return new IndexNode(mapSimplifyCore(node.dimensions));
211
+ } else if ((0, _is.isObjectNode)(node)) {
212
+ var newProps = {};
213
+
214
+ for (var prop in node.properties) {
215
+ newProps[prop] = simplifyCore(node.properties[prop]);
216
+ }
217
+
218
+ return new ObjectNode(newProps);
191
219
  } else {// cannot simplify
192
220
  }
193
221
 
@@ -26,7 +26,7 @@ var _object = require("../../utils/object.js");
26
26
  var _map = require("../../utils/map.js");
27
27
 
28
28
  var name = 'simplify';
29
- var dependencies = ['config', 'typed', 'parse', 'add', 'subtract', 'multiply', 'divide', 'pow', 'isZero', 'equal', '?fraction', '?bignumber', 'mathWithTransform', 'ConstantNode', 'FunctionNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
29
+ var dependencies = ['config', 'typed', 'parse', 'add', 'subtract', 'multiply', 'divide', 'pow', 'isZero', 'equal', '?fraction', '?bignumber', 'mathWithTransform', 'matrix', 'AccessorNode', 'ArrayNode', 'ConstantNode', 'FunctionNode', 'IndexNode', 'ObjectNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
30
30
  var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
31
31
  var config = _ref.config,
32
32
  typed = _ref.typed,
@@ -41,8 +41,13 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
41
41
  fraction = _ref.fraction,
42
42
  bignumber = _ref.bignumber,
43
43
  mathWithTransform = _ref.mathWithTransform,
44
+ matrix = _ref.matrix,
45
+ AccessorNode = _ref.AccessorNode,
46
+ ArrayNode = _ref.ArrayNode,
44
47
  ConstantNode = _ref.ConstantNode,
45
48
  FunctionNode = _ref.FunctionNode,
49
+ IndexNode = _ref.IndexNode,
50
+ ObjectNode = _ref.ObjectNode,
46
51
  OperatorNode = _ref.OperatorNode,
47
52
  ParenthesisNode = _ref.ParenthesisNode,
48
53
  SymbolNode = _ref.SymbolNode;
@@ -50,11 +55,16 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
50
55
  typed: typed,
51
56
  config: config,
52
57
  mathWithTransform: mathWithTransform,
58
+ matrix: matrix,
53
59
  fraction: fraction,
54
60
  bignumber: bignumber,
61
+ AccessorNode: AccessorNode,
62
+ ArrayNode: ArrayNode,
55
63
  ConstantNode: ConstantNode,
56
- OperatorNode: OperatorNode,
57
64
  FunctionNode: FunctionNode,
65
+ IndexNode: IndexNode,
66
+ ObjectNode: ObjectNode,
67
+ OperatorNode: OperatorNode,
58
68
  SymbolNode: SymbolNode
59
69
  });
60
70
  var simplifyCore = (0, _simplifyCore.createSimplifyCore)({
@@ -65,9 +75,13 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
65
75
  multiply: multiply,
66
76
  divide: divide,
67
77
  pow: pow,
78
+ AccessorNode: AccessorNode,
79
+ ArrayNode: ArrayNode,
68
80
  ConstantNode: ConstantNode,
69
- OperatorNode: OperatorNode,
70
81
  FunctionNode: FunctionNode,
82
+ IndexNode: IndexNode,
83
+ ObjectNode: ObjectNode,
84
+ OperatorNode: OperatorNode,
71
85
  ParenthesisNode: ParenthesisNode
72
86
  });
73
87
  var resolve = (0, _resolve.createResolve)({
@@ -124,11 +138,14 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
124
138
  * - [Symbolic computation - Simplification (Wikipedia)](https://en.wikipedia.org/wiki/Symbolic_computation#Simplification)
125
139
  *
126
140
  * An optional `options` argument can be passed as last argument of `simplify`.
127
- * There is currently one option available:
128
- * - `exactFractions`: a boolean which is `true` by default.
129
- * - `fractionsLimit`: when `exactFractions` is true, a fraction will be returned
130
- * only when both numerator and denominator are smaller than `fractionsLimit`.
131
- * Default value is 10000.
141
+ * Currently available options (defaults in parentheses):
142
+ * - `consoleDebug` (false): whether to write the expression being simplified
143
+ and any changes to it, along with the rule responsible, to console
144
+ * - `exactFractions` (true): whether to try to convert all constants to
145
+ exact rational numbers.
146
+ * - `fractionsLimit` (10000): when `exactFractions` is true, constants will
147
+ be expressed as fractions only when both numerator and denominator
148
+ are smaller than `fractionsLimit`.
132
149
  *
133
150
  * Syntax:
134
151
  *
@@ -199,6 +216,7 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
199
216
  return this(expr, rules, (0, _map.createMap)(scope), options);
200
217
  },
201
218
  'Node, Array, Map, Object': function NodeArrayMapObject(expr, rules, scope, options) {
219
+ var debug = options.consoleDebug;
202
220
  rules = _buildRules(rules);
203
221
  var res = resolve(expr, scope);
204
222
  res = removeParens(res);
@@ -211,12 +229,33 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
211
229
  visited[str] = true;
212
230
  _lastsym = 0; // counter for placeholder symbols
213
231
 
232
+ var laststr = str;
233
+ if (debug) console.log('Working on: ', str);
234
+
214
235
  for (var i = 0; i < rules.length; i++) {
236
+ var rulestr = '';
237
+
215
238
  if (typeof rules[i] === 'function') {
216
239
  res = rules[i](res, options);
240
+ if (debug) rulestr = rules[i].name;
217
241
  } else {
218
242
  flatten(res);
219
243
  res = applyRule(res, rules[i]);
244
+
245
+ if (debug) {
246
+ rulestr = "".concat(rules[i].l.toString(), " -> ").concat(rules[i].r.toString());
247
+ }
248
+ }
249
+
250
+ if (debug) {
251
+ var newstr = res.toString({
252
+ parenthesis: 'all'
253
+ });
254
+
255
+ if (newstr !== laststr) {
256
+ console.log('Applying', rulestr, 'produced', newstr);
257
+ laststr = newstr;
258
+ }
220
259
  }
221
260
 
222
261
  unflattenl(res); // using left-heavy binary tree here since custom rule functions may expect it
@@ -280,17 +319,19 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
280
319
  l: 'log(e)',
281
320
  r: '1'
282
321
  }, // temporary rules
322
+ // Note initially we tend constants to the right because like-term
323
+ // collection prefers the left, and we would rather collect nonconstants
283
324
  {
284
325
  l: 'n-n1',
285
326
  r: 'n+-n1'
286
327
  }, // temporarily replace 'subtract' so we can further flatten the 'add' operator
287
328
  {
288
329
  l: '-(c*v)',
289
- r: '(-c) * v'
330
+ r: 'v * (-c)'
290
331
  }, // make non-constant terms positive
291
332
  {
292
333
  l: '-v',
293
- r: '(-1) * v'
334
+ r: 'v * (-1)'
294
335
  }, {
295
336
  l: 'n/n1^n2',
296
337
  r: 'n*n1^-n2'
@@ -298,7 +339,7 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
298
339
  {
299
340
  l: 'n/n1',
300
341
  r: 'n*n1^-1'
301
- }, // expand nested exponentiation
342
+ }, simplifyConstant, // expand nested exponentiation
302
343
  {
303
344
  l: '(n ^ n1) ^ n2',
304
345
  r: 'n ^ (n1 * n2)'
@@ -320,20 +361,29 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
320
361
  l: 'n+-n',
321
362
  r: '0'
322
363
  }, {
323
- l: 'n1*n2 + n2',
324
- r: '(n1+1)*n2'
325
- }, {
326
- l: 'n1*n3 + n2*n3',
327
- r: '(n1+n2)*n3'
328
- }, // remove parenthesis in the case of negating a quantitiy
364
+ l: 'v*n + v',
365
+ r: 'v*(n+1)'
366
+ }, // NOTE: leftmost position is special:
367
+ {
368
+ l: 'n3*n1 + n3*n2',
369
+ r: 'n3*(n1+n2)'
370
+ }, // All sub-monomials tried there.
371
+ {
372
+ l: 'n*c + c',
373
+ r: '(n+1)*c'
374
+ }, // remove parenthesis in the case of negating a quantity
375
+ // (It might seem this rule should precede collecting like terms,
376
+ // but putting it after gives another chance of noticing like terms,
377
+ // and any new like terms produced by this will be collected
378
+ // on the next pass through all the rules.)
379
+ {
380
+ l: 'n1 + (n2 + n3)*(-1)',
381
+ r: 'n1 + n2*(-1) + n3*(-1)'
382
+ }, // make factors positive (and undo 'make non-constant terms positive')
329
383
  {
330
- l: 'n1 + -1 * (n2 + n3)',
331
- r: 'n1 + -1 * n2 + -1 * n3'
332
- }, simplifyConstant, {
333
384
  l: '(-n)*n1',
334
385
  r: '-(n*n1)'
335
- }, // make factors positive (and undo 'make non-constant terms positive')
336
- // ordering of constants
386
+ }, // final ordering of constants
337
387
  {
338
388
  l: 'c+v',
339
389
  r: 'v+c',
@@ -383,6 +433,9 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
383
433
  {
384
434
  l: 'n1/(n2/n3)',
385
435
  r: '(n1*n3)/n2'
436
+ }, {
437
+ l: 'n1/(-n2)',
438
+ r: '-n1/n2'
386
439
  }];
387
440
  /**
388
441
  * Parse the string array of rules into nodes
@@ -434,7 +487,7 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
434
487
  };
435
488
 
436
489
  if (rule.context) {
437
- newRule.evaluate = rule.context;
490
+ newRule.context = rule.context;
438
491
  }
439
492
 
440
493
  if (rule.evaluate) {
@@ -478,6 +531,14 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
478
531
  function _getExpandPlaceholderSymbol() {
479
532
  return new SymbolNode('_p' + _lastsym++);
480
533
  }
534
+
535
+ function mapRule(nodes, rule) {
536
+ if (nodes) {
537
+ for (var i = 0; i < nodes.length; ++i) {
538
+ nodes[i] = applyRule(nodes[i], rule);
539
+ }
540
+ }
541
+ }
481
542
  /**
482
543
  * Returns a simplfied form of node, or the original node if no simplification was possible.
483
544
  *
@@ -491,19 +552,31 @@ var createSimplify = /* #__PURE__ */(0, _factory.factory)(name, dependencies, fu
491
552
  // console.log('Entering applyRule(' + node.toString() + ')')
492
553
  // Do not clone node unless we find a match
493
554
  var res = node; // First replace our child nodes with their simplified versions
494
- // If a child could not be simplified, the assignments will have
495
- // no effect since the node is returned unchanged
555
+ // If a child could not be simplified, applying the rule to it
556
+ // will have no effect since the node is returned unchanged
496
557
 
497
558
  if (res instanceof OperatorNode || res instanceof FunctionNode) {
498
- if (res.args) {
499
- for (var i = 0; i < res.args.length; i++) {
500
- res.args[i] = applyRule(res.args[i], rule);
501
- }
502
- }
559
+ mapRule(res.args, rule);
503
560
  } else if (res instanceof ParenthesisNode) {
504
561
  if (res.content) {
505
562
  res.content = applyRule(res.content, rule);
506
563
  }
564
+ } else if (res instanceof ArrayNode) {
565
+ mapRule(res.items, rule);
566
+ } else if (res instanceof AccessorNode) {
567
+ if (res.object) {
568
+ res.object = applyRule(res.object, rule);
569
+ }
570
+
571
+ if (res.index) {
572
+ res.index = applyRule(res.index, rule);
573
+ }
574
+ } else if (res instanceof IndexNode) {
575
+ mapRule(res.dimensions, rule);
576
+ } else if (res instanceof ObjectNode) {
577
+ for (var prop in res.properties) {
578
+ res.properties[prop] = applyRule(res.properties[prop], rule);
579
+ }
507
580
  } // Try to match a rule against this node
508
581
 
509
582