mathjs 10.0.0 → 10.1.1
Sign up to get free protection for your applications and to get access to all the features.
- package/HISTORY.md +37 -0
- package/NOTICE +1 -1
- package/README.md +10 -2
- package/bin/cli.js +1 -1
- package/docs/expressions/syntax.md +1 -1
- package/docs/reference/constants.md +1 -1
- package/docs/reference/functions/invmod.md +41 -0
- package/docs/reference/functions/simplify.md +8 -5
- package/docs/reference/functions.md +1 -0
- package/examples/expressions.js +1 -1
- package/lib/browser/math.js +7 -7
- package/lib/browser/math.js.map +1 -1
- package/lib/cjs/entry/dependenciesAny/dependenciesIntersect.generated.js +6 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesInvmod.generated.js +41 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesRationalize.generated.js +15 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSimplify.generated.js +15 -0
- package/lib/cjs/entry/dependenciesAny.generated.js +8 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesRationalize.generated.js +15 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesSimplify.generated.js +15 -0
- package/lib/cjs/entry/impureFunctionsAny.generated.js +11 -0
- package/lib/cjs/entry/impureFunctionsNumber.generated.js +10 -0
- package/lib/cjs/entry/pureFunctionsAny.generated.js +16 -2
- package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +6 -1
- package/lib/cjs/expression/embeddedDocs/function/arithmetic/invmod.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/forEach.js +1 -1
- package/lib/cjs/factoriesAny.js +8 -0
- package/lib/cjs/function/algebra/rationalize.js +18 -4
- package/lib/cjs/function/algebra/simplify/simplifyConstant.js +223 -29
- package/lib/cjs/function/algebra/simplify/simplifyCore.js +34 -6
- package/lib/cjs/function/algebra/simplify.js +103 -30
- package/lib/cjs/function/arithmetic/invmod.js +73 -0
- package/lib/cjs/function/arithmetic/round.js +2 -2
- package/lib/cjs/function/geometry/intersect.js +12 -13
- package/lib/cjs/function/probability/gamma.js +28 -30
- package/lib/cjs/header.js +3 -3
- package/lib/cjs/type/matrix/SparseMatrix.js +19 -15
- package/lib/cjs/type/unit/Unit.js +2 -2
- package/lib/cjs/utils/number.js +1 -1
- package/lib/cjs/utils/snapshot.js +2 -2
- package/lib/cjs/version.js +1 -1
- package/lib/esm/entry/dependenciesAny/dependenciesIntersect.generated.js +4 -0
- package/lib/esm/entry/dependenciesAny/dependenciesInvmod.generated.js +24 -0
- package/lib/esm/entry/dependenciesAny/dependenciesRationalize.generated.js +10 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSimplify.generated.js +10 -0
- package/lib/esm/entry/dependenciesAny.generated.js +1 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesRationalize.generated.js +10 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesSimplify.generated.js +10 -0
- package/lib/esm/entry/impureFunctionsAny.generated.js +12 -1
- package/lib/esm/entry/impureFunctionsNumber.generated.js +10 -0
- package/lib/esm/entry/pureFunctionsAny.generated.js +14 -1
- package/lib/esm/expression/embeddedDocs/embeddedDocs.js +4 -1
- package/lib/esm/expression/embeddedDocs/function/arithmetic/invmod.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/forEach.js +1 -1
- package/lib/esm/factoriesAny.js +1 -0
- package/lib/esm/function/algebra/rationalize.js +18 -4
- package/lib/esm/function/algebra/simplify/simplifyConstant.js +197 -29
- package/lib/esm/function/algebra/simplify/simplifyCore.js +35 -7
- package/lib/esm/function/algebra/simplify.js +103 -30
- package/lib/esm/function/arithmetic/invmod.js +57 -0
- package/lib/esm/function/arithmetic/round.js +2 -2
- package/lib/esm/function/geometry/intersect.js +12 -12
- package/lib/esm/function/probability/gamma.js +28 -30
- package/lib/esm/header.js +1 -1
- package/lib/esm/type/matrix/SparseMatrix.js +19 -15
- package/lib/esm/type/unit/Unit.js +2 -2
- package/lib/esm/utils/number.js +1 -1
- package/lib/esm/utils/snapshot.js +2 -2
- package/lib/esm/version.js +1 -1
- package/package.json +15 -14
- 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
|
-
|
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', '
|
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
|
-
|
42
|
-
|
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
|
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(
|
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
|
-
|
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
|
-
|
199
|
-
|
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 (
|
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
|
-
|
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
|
-
|
469
|
+
return _foldAccessor(foldFraction(node.object, options), foldFraction(node.index, options), options);
|
300
470
|
|
301
471
|
case 'ArrayNode':
|
302
|
-
|
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', '
|
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
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
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
|
-
*
|
128
|
-
* - `
|
129
|
-
|
130
|
-
*
|
131
|
-
|
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)
|
330
|
+
r: 'v * (-c)'
|
290
331
|
}, // make non-constant terms positive
|
291
332
|
{
|
292
333
|
l: '-v',
|
293
|
-
r: '(-1)
|
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: '
|
324
|
-
r: '(
|
325
|
-
},
|
326
|
-
|
327
|
-
|
328
|
-
|
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
|
-
}, //
|
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.
|
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
|
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
|
-
|
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
|
|