mathjs 11.3.3 → 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HISTORY.md +14 -0
- package/lib/browser/math.js +1 -1
- package/lib/browser/math.js.LICENSE.txt +2 -2
- package/lib/browser/math.js.map +1 -1
- package/lib/cjs/entry/dependenciesAny/dependenciesLyap.generated.js +26 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesPolynomialRoot.generated.js +42 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSchur.generated.js +30 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSylvester.generated.js +46 -0
- package/lib/cjs/entry/dependenciesAny.generated.js +28 -0
- package/lib/cjs/entry/impureFunctionsAny.generated.js +21 -17
- package/lib/cjs/entry/pureFunctionsAny.generated.js +100 -48
- package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +8 -0
- package/lib/cjs/expression/embeddedDocs/function/algebra/polynomialRoot.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/lyap.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/schur.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/sylvester.js +15 -0
- package/lib/cjs/factoriesAny.js +28 -0
- package/lib/cjs/function/algebra/decomposition/schur.js +75 -0
- package/lib/cjs/function/algebra/lyap.js +57 -0
- package/lib/cjs/function/algebra/polynomialRoot.js +139 -0
- package/lib/cjs/function/algebra/simplify/wildcards.js +38 -0
- package/lib/cjs/function/algebra/simplify.js +104 -44
- package/lib/cjs/function/algebra/simplifyConstant.js +29 -12
- package/lib/cjs/function/algebra/sylvester.js +127 -0
- package/lib/cjs/function/matrix/forEach.js +1 -1
- package/lib/cjs/header.js +2 -2
- package/lib/cjs/version.js +1 -1
- package/lib/esm/entry/dependenciesAny/dependenciesLyap.generated.js +18 -0
- package/lib/esm/entry/dependenciesAny/dependenciesPolynomialRoot.generated.js +34 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSchur.generated.js +22 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSylvester.generated.js +38 -0
- package/lib/esm/entry/dependenciesAny.generated.js +4 -0
- package/lib/esm/entry/impureFunctionsAny.generated.js +22 -18
- package/lib/esm/entry/pureFunctionsAny.generated.js +87 -39
- package/lib/esm/expression/embeddedDocs/embeddedDocs.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/algebra/polynomialRoot.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/lyap.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/schur.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/sylvester.js +8 -0
- package/lib/esm/factoriesAny.js +4 -0
- package/lib/esm/function/algebra/decomposition/schur.js +70 -0
- package/lib/esm/function/algebra/lyap.js +52 -0
- package/lib/esm/function/algebra/polynomialRoot.js +122 -0
- package/lib/esm/function/algebra/simplify/wildcards.js +20 -0
- package/lib/esm/function/algebra/simplify.js +105 -45
- package/lib/esm/function/algebra/simplifyConstant.js +29 -12
- package/lib/esm/function/algebra/sylvester.js +118 -0
- package/lib/esm/function/matrix/forEach.js +1 -1
- package/lib/esm/version.js +1 -1
- package/package.json +8 -8
- package/types/index.d.ts +83 -5
@@ -0,0 +1,8 @@
|
|
1
|
+
export var lyapDocs = {
|
2
|
+
name: 'lyap',
|
3
|
+
category: 'Matrix',
|
4
|
+
syntax: ['lyap(A,Q)'],
|
5
|
+
description: 'Solves the Continuous-time Lyapunov equation AP+PA\'+Q=0 for P',
|
6
|
+
examples: ['lyap([[-2, 0], [1, -4]], [[3, 1], [1, 3]])', 'lyap(A,Q)'],
|
7
|
+
seealso: ['schur', 'sylvester']
|
8
|
+
};
|
@@ -0,0 +1,8 @@
|
|
1
|
+
export var sylvesterDocs = {
|
2
|
+
name: 'sylvester',
|
3
|
+
category: 'Matrix',
|
4
|
+
syntax: ['sylvester(A,B,C)'],
|
5
|
+
description: 'Solves the real-valued Sylvester equation AX+XB=C for X',
|
6
|
+
examples: ['sylvester([[-1, -2], [1, 1]], [[-2, 1], [-1, 2]], [[-3, 2], [3, 0]])', 'sylvester(A,B,C)'],
|
7
|
+
seealso: ['schur', 'lyap']
|
8
|
+
};
|
package/lib/esm/factoriesAny.js
CHANGED
@@ -210,6 +210,7 @@ export { createLup } from './function/algebra/decomposition/lup.js';
|
|
210
210
|
export { createQr } from './function/algebra/decomposition/qr.js';
|
211
211
|
export { createSlu } from './function/algebra/decomposition/slu.js';
|
212
212
|
export { createLusolve } from './function/algebra/solver/lusolve.js';
|
213
|
+
export { createPolynomialRoot } from './function/algebra/polynomialRoot.js';
|
213
214
|
export { createHelpClass } from './expression/Help.js';
|
214
215
|
export { createChainClass } from './type/chain/Chain.js';
|
215
216
|
export { createHelp } from './expression/function/help.js';
|
@@ -220,6 +221,9 @@ export { createPinv } from './function/matrix/pinv.js';
|
|
220
221
|
export { createEigs } from './function/matrix/eigs.js';
|
221
222
|
export { createExpm } from './function/matrix/expm.js';
|
222
223
|
export { createSqrtm } from './function/matrix/sqrtm.js';
|
224
|
+
export { createSylvester } from './function/algebra/sylvester.js';
|
225
|
+
export { createSchur } from './function/algebra/decomposition/schur.js';
|
226
|
+
export { createLyap } from './function/algebra/lyap.js';
|
223
227
|
export { createDivide } from './function/arithmetic/divide.js';
|
224
228
|
export { createDistance } from './function/geometry/distance.js';
|
225
229
|
export { createIntersect } from './function/geometry/intersect.js';
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import { factory } from '../../../utils/factory.js';
|
2
|
+
var name = 'schur';
|
3
|
+
var dependencies = ['typed', 'matrix', 'identity', 'multiply', 'qr', 'norm', 'subtract'];
|
4
|
+
export var createSchur = /* #__PURE__ */factory(name, dependencies, _ref => {
|
5
|
+
var {
|
6
|
+
typed,
|
7
|
+
matrix,
|
8
|
+
identity,
|
9
|
+
multiply,
|
10
|
+
qr,
|
11
|
+
norm,
|
12
|
+
subtract
|
13
|
+
} = _ref;
|
14
|
+
/**
|
15
|
+
*
|
16
|
+
* Performs a real Schur decomposition of the real matrix A = UTU' where U is orthogonal
|
17
|
+
* and T is upper quasi-triangular.
|
18
|
+
* https://en.wikipedia.org/wiki/Schur_decomposition
|
19
|
+
*
|
20
|
+
* Syntax:
|
21
|
+
*
|
22
|
+
* math.schur(A)
|
23
|
+
*
|
24
|
+
* Examples:
|
25
|
+
*
|
26
|
+
* const A = [[1, 0], [-4, 3]]
|
27
|
+
* math.schur(A) // returns {T: [[3, 4], [0, 1]], R: [[0, 1], [-1, 0]]}
|
28
|
+
*
|
29
|
+
* See also:
|
30
|
+
*
|
31
|
+
* sylvester, lyap, qr
|
32
|
+
*
|
33
|
+
* @param {Array | Matrix} A Matrix A
|
34
|
+
* @return {{U: Array | Matrix, T: Array | Matrix}} Object containing both matrix U and T of the Schur Decomposition A=UTU'
|
35
|
+
*/
|
36
|
+
return typed(name, {
|
37
|
+
Array: function Array(X) {
|
38
|
+
var r = _schur(matrix(X));
|
39
|
+
return {
|
40
|
+
U: r.U.valueOf(),
|
41
|
+
T: r.T.valueOf()
|
42
|
+
};
|
43
|
+
},
|
44
|
+
Matrix: function Matrix(X) {
|
45
|
+
return _schur(X);
|
46
|
+
}
|
47
|
+
});
|
48
|
+
function _schur(X) {
|
49
|
+
var n = X.size()[0];
|
50
|
+
var A = X;
|
51
|
+
var U = identity(n);
|
52
|
+
var k = 0;
|
53
|
+
var A0;
|
54
|
+
do {
|
55
|
+
A0 = A;
|
56
|
+
var QR = qr(A);
|
57
|
+
var Q = QR.Q;
|
58
|
+
var R = QR.R;
|
59
|
+
A = multiply(R, Q);
|
60
|
+
U = multiply(U, Q);
|
61
|
+
if (k++ > 100) {
|
62
|
+
break;
|
63
|
+
}
|
64
|
+
} while (norm(subtract(A, A0)) > 1e-4);
|
65
|
+
return {
|
66
|
+
U,
|
67
|
+
T: A
|
68
|
+
};
|
69
|
+
}
|
70
|
+
});
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import { factory } from '../../utils/factory.js';
|
2
|
+
var name = 'lyap';
|
3
|
+
var dependencies = ['typed', 'matrix', 'sylvester', 'multiply', 'transpose'];
|
4
|
+
export var createLyap = /* #__PURE__ */factory(name, dependencies, _ref => {
|
5
|
+
var {
|
6
|
+
typed,
|
7
|
+
matrix,
|
8
|
+
sylvester,
|
9
|
+
multiply,
|
10
|
+
transpose
|
11
|
+
} = _ref;
|
12
|
+
/**
|
13
|
+
*
|
14
|
+
* Solves the Continuous-time Lyapunov equation AP+PA'+Q=0 for P, where
|
15
|
+
* Q is an input matrix. When Q is symmetric, P is also symmetric. Notice
|
16
|
+
* that different equivalent definitions exist for the Continuous-time
|
17
|
+
* Lyapunov equation.
|
18
|
+
* https://en.wikipedia.org/wiki/Lyapunov_equation
|
19
|
+
*
|
20
|
+
* Syntax:
|
21
|
+
*
|
22
|
+
* math.lyap(A, Q)
|
23
|
+
*
|
24
|
+
* Examples:
|
25
|
+
*
|
26
|
+
* const A = [[-2, 0], [1, -4]]
|
27
|
+
* const Q = [[3, 1], [1, 3]]
|
28
|
+
* const P = math.lyap(A, Q)
|
29
|
+
*
|
30
|
+
* See also:
|
31
|
+
*
|
32
|
+
* sylvester, schur
|
33
|
+
*
|
34
|
+
* @param {Matrix | Array} A Matrix A
|
35
|
+
* @param {Matrix | Array} Q Matrix Q
|
36
|
+
* @return {Matrix | Array} Matrix P solution to the Continuous-time Lyapunov equation AP+PA'=Q
|
37
|
+
*/
|
38
|
+
return typed(name, {
|
39
|
+
'Matrix, Matrix': function MatrixMatrix(A, Q) {
|
40
|
+
return sylvester(A, transpose(A), multiply(-1, Q));
|
41
|
+
},
|
42
|
+
'Array, Matrix': function ArrayMatrix(A, Q) {
|
43
|
+
return sylvester(matrix(A), transpose(matrix(A)), multiply(-1, Q));
|
44
|
+
},
|
45
|
+
'Matrix, Array': function MatrixArray(A, Q) {
|
46
|
+
return sylvester(A, transpose(matrix(A)), matrix(multiply(-1, Q)));
|
47
|
+
},
|
48
|
+
'Array, Array': function ArrayArray(A, Q) {
|
49
|
+
return sylvester(matrix(A), transpose(matrix(A)), matrix(multiply(-1, Q))).toArray();
|
50
|
+
}
|
51
|
+
});
|
52
|
+
});
|
@@ -0,0 +1,122 @@
|
|
1
|
+
import { factory } from '../../utils/factory.js';
|
2
|
+
var name = 'polynomialRoot';
|
3
|
+
var dependencies = ['typed', 'isZero', 'equalScalar', 'add', 'subtract', 'multiply', 'divide', 'sqrt', 'unaryMinus', 'cbrt', 'typeOf', 'im', 're'];
|
4
|
+
export var createPolynomialRoot = /* #__PURE__ */factory(name, dependencies, _ref => {
|
5
|
+
var {
|
6
|
+
typed,
|
7
|
+
isZero,
|
8
|
+
equalScalar,
|
9
|
+
add,
|
10
|
+
subtract,
|
11
|
+
multiply,
|
12
|
+
divide,
|
13
|
+
sqrt,
|
14
|
+
unaryMinus,
|
15
|
+
cbrt,
|
16
|
+
typeOf,
|
17
|
+
im,
|
18
|
+
re
|
19
|
+
} = _ref;
|
20
|
+
/**
|
21
|
+
* Finds the numerical values of the distinct roots of a polynomial with real or complex coefficients.
|
22
|
+
* Currently operates only on linear, quadratic, and cubic polynomials using the standard
|
23
|
+
* formulas for the roots.
|
24
|
+
*
|
25
|
+
* Syntax:
|
26
|
+
*
|
27
|
+
* polynomialRoot(constant, linearCoeff, quadraticCoeff, cubicCoeff)
|
28
|
+
*
|
29
|
+
* Examples:
|
30
|
+
* // linear
|
31
|
+
* math.polynomialRoot(6, 3) // [-2]
|
32
|
+
* math.polynomialRoot(math.complex(6,3), 3) // [-2 - i]
|
33
|
+
* math.polynomialRoot(math.complex(6,3), math.complex(2,1)) // [-3 + 0i]
|
34
|
+
* // quadratic
|
35
|
+
* math.polynomialRoot(2, -3, 1) // [2, 1]
|
36
|
+
* math.polynomialRoot(8, 8, 2) // [-2]
|
37
|
+
* math.polynomialRoot(-2, 0, 1) // [1.4142135623730951, -1.4142135623730951]
|
38
|
+
* math.polynomialRoot(2, -2, 1) // [1 + i, 1 - i]
|
39
|
+
* math.polynomialRoot(math.complex(1,3), math.complex(-3, -2), 1) // [2 + i, 1 + i]
|
40
|
+
* // cubic
|
41
|
+
* math.polynomialRoot(-6, 11, -6, 1) // [1, 3, 2]
|
42
|
+
* math.polynomialRoot(-8, 0, 0, 1) // [-1 - 1.7320508075688774i, 2, -1 + 1.7320508075688774i]
|
43
|
+
* math.polynomialRoot(0, 8, 8, 2) // [0, -2]
|
44
|
+
* math.polynomialRoot(1, 1, 1, 1) // [-1 + 0i, 0 - i, 0 + i]
|
45
|
+
*
|
46
|
+
* See also:
|
47
|
+
* cbrt, sqrt
|
48
|
+
*
|
49
|
+
* @param {... number | Complex} coeffs
|
50
|
+
* The coefficients of the polynomial, starting with with the constant coefficent, followed
|
51
|
+
* by the linear coefficient and subsequent coefficients of increasing powers.
|
52
|
+
* @return {Array} The distinct roots of the polynomial
|
53
|
+
*/
|
54
|
+
|
55
|
+
return typed(name, {
|
56
|
+
'number|Complex, ...number|Complex': (constant, restCoeffs) => {
|
57
|
+
var coeffs = [constant, ...restCoeffs];
|
58
|
+
while (coeffs.length > 0 && isZero(coeffs[coeffs.length - 1])) {
|
59
|
+
coeffs.pop();
|
60
|
+
}
|
61
|
+
if (coeffs.length < 2) {
|
62
|
+
throw new RangeError("Polynomial [".concat(constant, ", ").concat(restCoeffs, "] must have a non-zero non-constant coefficient"));
|
63
|
+
}
|
64
|
+
switch (coeffs.length) {
|
65
|
+
case 2:
|
66
|
+
// linear
|
67
|
+
return [unaryMinus(divide(coeffs[0], coeffs[1]))];
|
68
|
+
case 3:
|
69
|
+
{
|
70
|
+
// quadratic
|
71
|
+
var [c, b, a] = coeffs;
|
72
|
+
var denom = multiply(2, a);
|
73
|
+
var d1 = multiply(b, b);
|
74
|
+
var d2 = multiply(4, a, c);
|
75
|
+
if (equalScalar(d1, d2)) return [divide(unaryMinus(b), denom)];
|
76
|
+
var discriminant = sqrt(subtract(d1, d2));
|
77
|
+
return [divide(subtract(discriminant, b), denom), divide(subtract(unaryMinus(discriminant), b), denom)];
|
78
|
+
}
|
79
|
+
case 4:
|
80
|
+
{
|
81
|
+
// cubic, cf. https://en.wikipedia.org/wiki/Cubic_equation
|
82
|
+
var [d, _c, _b, _a] = coeffs;
|
83
|
+
var _denom = unaryMinus(multiply(3, _a));
|
84
|
+
var D0_1 = multiply(_b, _b);
|
85
|
+
var D0_2 = multiply(3, _a, _c);
|
86
|
+
var D1_1 = add(multiply(2, _b, _b, _b), multiply(27, _a, _a, d));
|
87
|
+
var D1_2 = multiply(9, _a, _b, _c);
|
88
|
+
if (equalScalar(D0_1, D0_2) && equalScalar(D1_1, D1_2)) {
|
89
|
+
return [divide(_b, _denom)];
|
90
|
+
}
|
91
|
+
var Delta0 = subtract(D0_1, D0_2);
|
92
|
+
var Delta1 = subtract(D1_1, D1_2);
|
93
|
+
var discriminant1 = add(multiply(18, _a, _b, _c, d), multiply(_b, _b, _c, _c));
|
94
|
+
var discriminant2 = add(multiply(4, _b, _b, _b, d), multiply(4, _a, _c, _c, _c), multiply(27, _a, _a, d, d));
|
95
|
+
if (equalScalar(discriminant1, discriminant2)) {
|
96
|
+
return [divide(subtract(multiply(4, _a, _b, _c), add(multiply(9, _a, _a, d), multiply(_b, _b, _b))), multiply(_a, Delta0)),
|
97
|
+
// simple root
|
98
|
+
divide(subtract(multiply(9, _a, d), multiply(_b, _c)), multiply(2, Delta0)) // double root
|
99
|
+
];
|
100
|
+
}
|
101
|
+
// OK, we have three distinct roots
|
102
|
+
var Ccubed;
|
103
|
+
if (equalScalar(D0_1, D0_2)) {
|
104
|
+
Ccubed = Delta1;
|
105
|
+
} else {
|
106
|
+
Ccubed = divide(add(Delta1, sqrt(subtract(multiply(Delta1, Delta1), multiply(4, Delta0, Delta0, Delta0)))), 2);
|
107
|
+
}
|
108
|
+
var allRoots = true;
|
109
|
+
var rawRoots = cbrt(Ccubed, allRoots).toArray().map(C => divide(add(_b, C, divide(Delta0, C)), _denom));
|
110
|
+
return rawRoots.map(r => {
|
111
|
+
if (typeOf(r) === 'Complex' && equalScalar(re(r), re(r) + im(r))) {
|
112
|
+
return re(r);
|
113
|
+
}
|
114
|
+
return r;
|
115
|
+
});
|
116
|
+
}
|
117
|
+
default:
|
118
|
+
throw new RangeError("only implemented for cubic or lower-order polynomials, not ".concat(coeffs));
|
119
|
+
}
|
120
|
+
}
|
121
|
+
});
|
122
|
+
});
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { isConstantNode, isFunctionNode, isOperatorNode, isParenthesisNode } from '../../../utils/is.js';
|
2
|
+
export { isConstantNode, isSymbolNode as isVariableNode } from '../../../utils/is.js';
|
3
|
+
export function isNumericNode(x) {
|
4
|
+
return isConstantNode(x) || isOperatorNode(x) && x.isUnary() && isConstantNode(x.args[0]);
|
5
|
+
}
|
6
|
+
export function isConstantExpression(x) {
|
7
|
+
if (isConstantNode(x)) {
|
8
|
+
// Basic Constant types
|
9
|
+
return true;
|
10
|
+
}
|
11
|
+
if ((isFunctionNode(x) || isOperatorNode(x)) && x.args.every(isConstantExpression)) {
|
12
|
+
// Can be constant depending on arguments
|
13
|
+
return true;
|
14
|
+
}
|
15
|
+
if (isParenthesisNode(x) && isConstantExpression(x.content)) {
|
16
|
+
// Parenthesis are transparent
|
17
|
+
return true;
|
18
|
+
}
|
19
|
+
return false; // Probably missing some edge cases
|
20
|
+
}
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import {
|
1
|
+
import { isParenthesisNode } from '../../utils/is.js';
|
2
|
+
import { isConstantNode, isVariableNode, isNumericNode, isConstantExpression } from './simplify/wildcards.js';
|
2
3
|
import { factory } from '../../utils/factory.js';
|
3
4
|
import { createUtil } from './simplify/util.js';
|
4
5
|
import { hasOwnProperty } from '../../utils/object.js';
|
@@ -75,9 +76,15 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
75
76
|
* expression is that variables starting with the following characters are
|
76
77
|
* interpreted as wildcards:
|
77
78
|
*
|
78
|
-
* - 'n' -
|
79
|
-
* - 'c' -
|
80
|
-
* - '
|
79
|
+
* - 'n' - Matches any node [Node]
|
80
|
+
* - 'c' - Matches a constant literal (5 or 3.2) [ConstantNode]
|
81
|
+
* - 'cl' - Matches a constant literal; same as c [ConstantNode]
|
82
|
+
* - 'cd' - Matches a decimal literal (5 or -3.2) [ConstantNode or unaryMinus wrapping a ConstantNode]
|
83
|
+
* - 'ce' - Matches a constant expression (-5 or √3) [Expressions consisting of only ConstantNodes, functions, and operators]
|
84
|
+
* - 'v' - Matches a variable; anything not matched by c (-5 or x) [Node that is not a ConstantNode]
|
85
|
+
* - 'vl' - Matches a variable literal (x or y) [SymbolNode]
|
86
|
+
* - 'vd' - Matches a non-decimal expression; anything not matched by cd (x or √3) [Node that is not a ConstantNode or unaryMinus that is wrapping a ConstantNode]
|
87
|
+
* - 've' - Matches a variable expression; anything not matched by ce (x or 2x) [Expressions that contain a SymbolNode or other non-constant term]
|
81
88
|
*
|
82
89
|
* The default list of rules is exposed on the function as `simplify.rules`
|
83
90
|
* and can be used as a basis to built a set of custom rules. Note that since
|
@@ -250,7 +257,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
250
257
|
}
|
251
258
|
}
|
252
259
|
}, {
|
253
|
-
s: '-(
|
260
|
+
s: '-(cl*v) -> v * (-cl)',
|
254
261
|
// make non-constant terms positive
|
255
262
|
assuming: {
|
256
263
|
multiply: {
|
@@ -261,7 +268,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
261
268
|
}
|
262
269
|
}
|
263
270
|
}, {
|
264
|
-
s: '-(
|
271
|
+
s: '-(cl*v) -> (-cl) * v',
|
265
272
|
// non-commutative version, part 1
|
266
273
|
assuming: {
|
267
274
|
multiply: {
|
@@ -272,7 +279,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
272
279
|
}
|
273
280
|
}
|
274
281
|
}, {
|
275
|
-
s: '-(v*
|
282
|
+
s: '-(v*cl) -> v * (-cl)',
|
276
283
|
// non-commutative version, part 2
|
277
284
|
assuming: {
|
278
285
|
multiply: {
|
@@ -330,24 +337,24 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
330
337
|
},
|
331
338
|
// collect like factors; into a sum, only do this for nonconstants
|
332
339
|
{
|
333
|
-
l: '
|
334
|
-
r: '
|
340
|
+
l: ' vd * ( vd * n1 + n2)',
|
341
|
+
r: 'vd^2 * n1 + vd * n2'
|
335
342
|
}, {
|
336
|
-
s: '
|
343
|
+
s: ' vd * (vd^n4 * n1 + n2) -> vd^(1+n4) * n1 + vd * n2',
|
337
344
|
assuming: {
|
338
345
|
divide: {
|
339
346
|
total: true
|
340
347
|
}
|
341
348
|
} // v*1/v = v^(1+-1) needs 1/v
|
342
349
|
}, {
|
343
|
-
s: '
|
350
|
+
s: 'vd^n3 * ( vd * n1 + n2) -> vd^(n3+1) * n1 + vd^n3 * n2',
|
344
351
|
assuming: {
|
345
352
|
divide: {
|
346
353
|
total: true
|
347
354
|
}
|
348
355
|
}
|
349
356
|
}, {
|
350
|
-
s: '
|
357
|
+
s: 'vd^n3 * (vd^n4 * n1 + n2) -> vd^(n3+n4) * n1 + vd^n3 * n2',
|
351
358
|
assuming: {
|
352
359
|
divide: {
|
353
360
|
total: true
|
@@ -390,8 +397,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
390
397
|
l: 'n+-n',
|
391
398
|
r: '0'
|
392
399
|
}, {
|
393
|
-
l: '
|
394
|
-
r: '
|
400
|
+
l: 'vd*n + vd',
|
401
|
+
r: 'vd*(n+1)'
|
395
402
|
},
|
396
403
|
// NOTE: leftmost position is special:
|
397
404
|
{
|
@@ -406,7 +413,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
406
413
|
l: 'n3^(-n4)*n1 + n3^n5 * n2',
|
407
414
|
r: 'n3^(-n4)*(n1 + n3^(n4+n5)*n2)'
|
408
415
|
}, {
|
409
|
-
s: 'n*
|
416
|
+
s: 'n*vd + vd -> (n+1)*vd',
|
410
417
|
// noncommutative additional cases
|
411
418
|
assuming: {
|
412
419
|
multiply: {
|
@@ -435,10 +442,10 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
435
442
|
}
|
436
443
|
}
|
437
444
|
}, {
|
438
|
-
l: 'n*
|
439
|
-
r: '(n+1)*
|
445
|
+
l: 'n*cd + cd',
|
446
|
+
r: '(n+1)*cd'
|
440
447
|
}, {
|
441
|
-
s: '
|
448
|
+
s: 'cd*n + cd -> cd*(n+1)',
|
442
449
|
assuming: {
|
443
450
|
multiply: {
|
444
451
|
commutative: false
|
@@ -469,7 +476,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
469
476
|
},
|
470
477
|
// final ordering of constants
|
471
478
|
{
|
472
|
-
s: '
|
479
|
+
s: 'ce+ve -> ve+ce',
|
473
480
|
assuming: {
|
474
481
|
add: {
|
475
482
|
commutative: true
|
@@ -481,7 +488,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
481
488
|
}
|
482
489
|
}
|
483
490
|
}, {
|
484
|
-
s: '
|
491
|
+
s: 'vd*cd -> cd*vd',
|
485
492
|
assuming: {
|
486
493
|
multiply: {
|
487
494
|
commutative: true
|
@@ -1047,9 +1054,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
1047
1054
|
}
|
1048
1055
|
} else if (rule instanceof SymbolNode) {
|
1049
1056
|
// If the rule is a SymbolNode, then it carries a special meaning
|
1050
|
-
// according to the first
|
1051
|
-
//
|
1052
|
-
// n.* matches any node
|
1057
|
+
// according to the first one or two characters of the symbol node name.
|
1058
|
+
// These meanings are expalined in the documentation for simplify()
|
1053
1059
|
if (rule.name.length === 0) {
|
1054
1060
|
throw new Error('Symbol in rule has 0 length...!?');
|
1055
1061
|
}
|
@@ -1058,29 +1064,83 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
1058
1064
|
if (rule.name !== node.name) {
|
1059
1065
|
return [];
|
1060
1066
|
}
|
1061
|
-
} else if (rule.name[0] === 'n' || rule.name.substring(0, 2) === '_p') {
|
1062
|
-
// rule matches _anything_, so assign this node to the rule.name placeholder
|
1063
|
-
// Assign node to the rule.name placeholder.
|
1064
|
-
// Our parent will check for matches among placeholders.
|
1065
|
-
res[0].placeholders[rule.name] = node;
|
1066
|
-
} else if (rule.name[0] === 'v') {
|
1067
|
-
// rule matches any variable thing (not a ConstantNode)
|
1068
|
-
if (!isConstantNode(node)) {
|
1069
|
-
res[0].placeholders[rule.name] = node;
|
1070
|
-
} else {
|
1071
|
-
// Mis-match: rule was expecting something other than a ConstantNode
|
1072
|
-
return [];
|
1073
|
-
}
|
1074
|
-
} else if (rule.name[0] === 'c') {
|
1075
|
-
// rule matches any ConstantNode
|
1076
|
-
if (node instanceof ConstantNode) {
|
1077
|
-
res[0].placeholders[rule.name] = node;
|
1078
|
-
} else {
|
1079
|
-
// Mis-match: rule was expecting a ConstantNode
|
1080
|
-
return [];
|
1081
|
-
}
|
1082
1067
|
} else {
|
1083
|
-
|
1068
|
+
// wildcards are composed of up to two alphabetic or underscore characters
|
1069
|
+
switch (rule.name[1] >= 'a' && rule.name[1] <= 'z' ? rule.name.substring(0, 2) : rule.name[0]) {
|
1070
|
+
case 'n':
|
1071
|
+
case '_p':
|
1072
|
+
// rule matches _anything_, so assign this node to the rule.name placeholder
|
1073
|
+
// Assign node to the rule.name placeholder.
|
1074
|
+
// Our parent will check for matches among placeholders.
|
1075
|
+
res[0].placeholders[rule.name] = node;
|
1076
|
+
break;
|
1077
|
+
case 'c':
|
1078
|
+
case 'cl':
|
1079
|
+
// rule matches a ConstantNode
|
1080
|
+
if (isConstantNode(node)) {
|
1081
|
+
res[0].placeholders[rule.name] = node;
|
1082
|
+
} else {
|
1083
|
+
// mis-match: rule does not encompass current node
|
1084
|
+
return [];
|
1085
|
+
}
|
1086
|
+
break;
|
1087
|
+
case 'v':
|
1088
|
+
// rule matches anything other than a ConstantNode
|
1089
|
+
if (!isConstantNode(node)) {
|
1090
|
+
res[0].placeholders[rule.name] = node;
|
1091
|
+
} else {
|
1092
|
+
// mis-match: rule does not encompass current node
|
1093
|
+
return [];
|
1094
|
+
}
|
1095
|
+
break;
|
1096
|
+
case 'vl':
|
1097
|
+
// rule matches VariableNode
|
1098
|
+
if (isVariableNode(node)) {
|
1099
|
+
res[0].placeholders[rule.name] = node;
|
1100
|
+
} else {
|
1101
|
+
// mis-match: rule does not encompass current node
|
1102
|
+
return [];
|
1103
|
+
}
|
1104
|
+
break;
|
1105
|
+
case 'cd':
|
1106
|
+
// rule matches a ConstantNode or unaryMinus-wrapped ConstantNode
|
1107
|
+
if (isNumericNode(node)) {
|
1108
|
+
res[0].placeholders[rule.name] = node;
|
1109
|
+
} else {
|
1110
|
+
// mis-match: rule does not encompass current node
|
1111
|
+
return [];
|
1112
|
+
}
|
1113
|
+
break;
|
1114
|
+
case 'vd':
|
1115
|
+
// rule matches anything other than a ConstantNode or unaryMinus-wrapped ConstantNode
|
1116
|
+
if (!isNumericNode(node)) {
|
1117
|
+
res[0].placeholders[rule.name] = node;
|
1118
|
+
} else {
|
1119
|
+
// mis-match: rule does not encompass current node
|
1120
|
+
return [];
|
1121
|
+
}
|
1122
|
+
break;
|
1123
|
+
case 'ce':
|
1124
|
+
// rule matches expressions that have a constant value
|
1125
|
+
if (isConstantExpression(node)) {
|
1126
|
+
res[0].placeholders[rule.name] = node;
|
1127
|
+
} else {
|
1128
|
+
// mis-match: rule does not encompass current node
|
1129
|
+
return [];
|
1130
|
+
}
|
1131
|
+
break;
|
1132
|
+
case 've':
|
1133
|
+
// rule matches expressions that do not have a constant value
|
1134
|
+
if (!isConstantExpression(node)) {
|
1135
|
+
res[0].placeholders[rule.name] = node;
|
1136
|
+
} else {
|
1137
|
+
// mis-match: rule does not encompass current node
|
1138
|
+
return [];
|
1139
|
+
}
|
1140
|
+
break;
|
1141
|
+
default:
|
1142
|
+
throw new Error('Invalid symbol in rule: ' + rule.name);
|
1143
|
+
}
|
1084
1144
|
}
|
1085
1145
|
} else if (rule instanceof ConstantNode) {
|
1086
1146
|
// Literal constant must match exactly
|
@@ -286,20 +286,37 @@ export var createSimplifyConstant = /* #__PURE__ */factory(name, dependencies, _
|
|
286
286
|
* @return - Either a Node representing a binary expression or Fraction
|
287
287
|
*/
|
288
288
|
function foldOp(fn, args, makeNode, options) {
|
289
|
-
|
290
|
-
|
289
|
+
var first = args.shift();
|
290
|
+
|
291
|
+
// In the following reduction, sofar always has one of the three following
|
292
|
+
// forms: [NODE], [CONSTANT], or [NODE, CONSTANT]
|
293
|
+
var reduction = args.reduce((sofar, next) => {
|
294
|
+
if (!isNode(next)) {
|
295
|
+
var last = sofar.pop();
|
296
|
+
if (isNode(last)) {
|
297
|
+
return [last, next];
|
298
|
+
}
|
299
|
+
// Two constants in a row, try to fold them into one
|
291
300
|
try {
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
} else if (!isNode(b)) {
|
299
|
-
b = _toNode(b);
|
301
|
+
sofar.push(_eval(fn, [last, next], options));
|
302
|
+
return sofar;
|
303
|
+
} catch (ignoreandcontinue) {
|
304
|
+
sofar.push(last);
|
305
|
+
// fall through to Node case
|
306
|
+
}
|
300
307
|
}
|
301
|
-
|
302
|
-
|
308
|
+
|
309
|
+
// Encountered a Node, or failed folding --
|
310
|
+
// collapse everything so far into a single tree:
|
311
|
+
sofar.push(_ensureNode(sofar.pop()));
|
312
|
+
var newtree = sofar.length === 1 ? sofar[0] : makeNode(sofar);
|
313
|
+
return [makeNode([newtree, _ensureNode(next)])];
|
314
|
+
}, [first]);
|
315
|
+
if (reduction.length === 1) {
|
316
|
+
return reduction[0];
|
317
|
+
}
|
318
|
+
// Might end up with a tree and a constant at the end:
|
319
|
+
return makeNode([reduction[0], _toNode(reduction[1])]);
|
303
320
|
}
|
304
321
|
|
305
322
|
// destroys the original node and returns a folded one
|