mathjs 10.0.0 → 10.1.1

Sign up to get free protection for your applications and to get access to all the features.
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