mathjs 10.0.2 → 10.2.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 +37 -0
- package/NOTICE +1 -1
- package/README.md +10 -2
- package/bin/cli.js +1 -1
- package/docs/expressions/algebra.md +27 -0
- package/docs/expressions/syntax.md +1 -1
- package/docs/reference/functions/abs.md +6 -0
- package/docs/reference/functions/acos.md +6 -0
- package/docs/reference/functions/acosh.md +6 -0
- package/docs/reference/functions/acot.md +6 -0
- package/docs/reference/functions/acoth.md +6 -0
- package/docs/reference/functions/acsc.md +6 -0
- package/docs/reference/functions/acsch.md +6 -0
- package/docs/reference/functions/add.md +6 -0
- package/docs/reference/functions/and.md +6 -0
- package/docs/reference/functions/apply.md +6 -0
- package/docs/reference/functions/arg.md +6 -0
- package/docs/reference/functions/asec.md +6 -0
- package/docs/reference/functions/asech.md +6 -0
- package/docs/reference/functions/asin.md +6 -0
- package/docs/reference/functions/asinh.md +6 -0
- package/docs/reference/functions/atan.md +6 -0
- package/docs/reference/functions/atan2.md +6 -0
- package/docs/reference/functions/atanh.md +6 -0
- package/docs/reference/functions/bellNumbers.md +6 -0
- package/docs/reference/functions/bin.md +6 -0
- package/docs/reference/functions/bitAnd.md +6 -0
- package/docs/reference/functions/bitNot.md +6 -0
- package/docs/reference/functions/bitOr.md +6 -0
- package/docs/reference/functions/bitXor.md +6 -0
- package/docs/reference/functions/catalan.md +6 -0
- package/docs/reference/functions/cbrt.md +6 -0
- package/docs/reference/functions/ceil.md +6 -0
- package/docs/reference/functions/clone.md +6 -0
- package/docs/reference/functions/column.md +6 -0
- package/docs/reference/functions/combinations.md +6 -0
- package/docs/reference/functions/combinationsWithRep.md +6 -0
- package/docs/reference/functions/compare.md +6 -0
- package/docs/reference/functions/compareNatural.md +6 -0
- package/docs/reference/functions/compareText.md +6 -0
- package/docs/reference/functions/compile.md +6 -0
- package/docs/reference/functions/composition.md +6 -0
- package/docs/reference/functions/concat.md +6 -0
- package/docs/reference/functions/conj.md +6 -0
- package/docs/reference/functions/cos.md +6 -0
- package/docs/reference/functions/cosh.md +6 -0
- package/docs/reference/functions/cot.md +6 -0
- package/docs/reference/functions/coth.md +6 -0
- package/docs/reference/functions/count.md +6 -0
- package/docs/reference/functions/cross.md +6 -0
- package/docs/reference/functions/csc.md +6 -0
- package/docs/reference/functions/csch.md +6 -0
- package/docs/reference/functions/ctranspose.md +6 -0
- package/docs/reference/functions/cube.md +6 -0
- package/docs/reference/functions/deepEqual.md +6 -0
- package/docs/reference/functions/derivative.md +6 -0
- package/docs/reference/functions/det.md +6 -0
- package/docs/reference/functions/diag.md +6 -0
- package/docs/reference/functions/diff.md +6 -0
- package/docs/reference/functions/distance.md +6 -0
- package/docs/reference/functions/divide.md +6 -0
- package/docs/reference/functions/dot.md +6 -0
- package/docs/reference/functions/dotDivide.md +6 -0
- package/docs/reference/functions/dotMultiply.md +6 -0
- package/docs/reference/functions/dotPow.md +6 -0
- package/docs/reference/functions/eigs.md +6 -0
- package/docs/reference/functions/equal.md +6 -0
- package/docs/reference/functions/equalText.md +6 -0
- package/docs/reference/functions/erf.md +6 -0
- package/docs/reference/functions/evaluate.md +6 -0
- package/docs/reference/functions/exp.md +6 -0
- package/docs/reference/functions/expm.md +6 -0
- package/docs/reference/functions/expm1.md +6 -0
- package/docs/reference/functions/factorial.md +6 -0
- package/docs/reference/functions/filter.md +6 -0
- package/docs/reference/functions/fix.md +6 -0
- package/docs/reference/functions/flatten.md +6 -0
- package/docs/reference/functions/floor.md +6 -0
- package/docs/reference/functions/forEach.md +6 -0
- package/docs/reference/functions/format.md +6 -0
- package/docs/reference/functions/gamma.md +6 -0
- package/docs/reference/functions/gcd.md +6 -0
- package/docs/reference/functions/getMatrixDataType.md +6 -0
- package/docs/reference/functions/hasNumericValue.md +6 -0
- package/docs/reference/functions/help.md +6 -0
- package/docs/reference/functions/hex.md +6 -0
- package/docs/reference/functions/hypot.md +6 -0
- package/docs/reference/functions/identity.md +6 -0
- package/docs/reference/functions/im.md +6 -0
- package/docs/reference/functions/intersect.md +6 -0
- package/docs/reference/functions/inv.md +6 -0
- package/docs/reference/functions/invmod.md +47 -0
- package/docs/reference/functions/isInteger.md +6 -0
- package/docs/reference/functions/isNaN.md +6 -0
- package/docs/reference/functions/isNegative.md +6 -0
- package/docs/reference/functions/isNumeric.md +6 -0
- package/docs/reference/functions/isPositive.md +6 -0
- package/docs/reference/functions/isPrime.md +6 -0
- package/docs/reference/functions/isZero.md +6 -0
- package/docs/reference/functions/kldivergence.md +6 -0
- package/docs/reference/functions/kron.md +6 -0
- package/docs/reference/functions/larger.md +6 -0
- package/docs/reference/functions/largerEq.md +6 -0
- package/docs/reference/functions/lcm.md +6 -0
- package/docs/reference/functions/leafCount.md +52 -0
- package/docs/reference/functions/leftShift.md +6 -0
- package/docs/reference/functions/log.md +6 -0
- package/docs/reference/functions/log10.md +6 -0
- package/docs/reference/functions/log1p.md +6 -0
- package/docs/reference/functions/log2.md +6 -0
- package/docs/reference/functions/lsolve.md +6 -0
- package/docs/reference/functions/lsolveAll.md +6 -0
- package/docs/reference/functions/lup.md +6 -0
- package/docs/reference/functions/lusolve.md +6 -0
- package/docs/reference/functions/mad.md +6 -0
- package/docs/reference/functions/map.md +6 -0
- package/docs/reference/functions/matrixFromColumns.md +6 -0
- package/docs/reference/functions/matrixFromFunction.md +6 -0
- package/docs/reference/functions/matrixFromRows.md +6 -0
- package/docs/reference/functions/max.md +6 -0
- package/docs/reference/functions/mean.md +6 -0
- package/docs/reference/functions/median.md +6 -0
- package/docs/reference/functions/min.md +6 -0
- package/docs/reference/functions/mod.md +6 -0
- package/docs/reference/functions/mode.md +6 -0
- package/docs/reference/functions/multinomial.md +6 -0
- package/docs/reference/functions/multiply.md +6 -0
- package/docs/reference/functions/norm.md +6 -0
- package/docs/reference/functions/not.md +6 -0
- package/docs/reference/functions/nthRoot.md +6 -0
- package/docs/reference/functions/nthRoots.md +6 -0
- package/docs/reference/functions/numeric.md +6 -0
- package/docs/reference/functions/oct.md +6 -0
- package/docs/reference/functions/ones.md +6 -0
- package/docs/reference/functions/or.md +6 -0
- package/docs/reference/functions/parser.md +6 -0
- package/docs/reference/functions/partitionSelect.md +6 -0
- package/docs/reference/functions/permutations.md +6 -0
- package/docs/reference/functions/pickRandom.md +6 -0
- package/docs/reference/functions/pow.md +6 -0
- package/docs/reference/functions/print.md +6 -0
- package/docs/reference/functions/prod.md +6 -0
- package/docs/reference/functions/qr.md +6 -0
- package/docs/reference/functions/quantileSeq.md +6 -0
- package/docs/reference/functions/random.md +6 -0
- package/docs/reference/functions/randomInt.md +6 -0
- package/docs/reference/functions/range.md +6 -0
- package/docs/reference/functions/rationalize.md +7 -1
- package/docs/reference/functions/re.md +6 -0
- package/docs/reference/functions/reshape.md +7 -0
- package/docs/reference/functions/resize.md +6 -0
- package/docs/reference/functions/resolve.md +46 -0
- package/docs/reference/functions/rightArithShift.md +6 -0
- package/docs/reference/functions/rightLogShift.md +6 -0
- package/docs/reference/functions/rotate.md +6 -0
- package/docs/reference/functions/rotationMatrix.md +6 -0
- package/docs/reference/functions/round.md +6 -0
- package/docs/reference/functions/row.md +6 -0
- package/docs/reference/functions/sec.md +6 -0
- package/docs/reference/functions/sech.md +6 -0
- package/docs/reference/functions/setCartesian.md +6 -0
- package/docs/reference/functions/setDifference.md +6 -0
- package/docs/reference/functions/setDistinct.md +6 -0
- package/docs/reference/functions/setIntersect.md +6 -0
- package/docs/reference/functions/setIsSubset.md +6 -0
- package/docs/reference/functions/setMultiplicity.md +6 -0
- package/docs/reference/functions/setPowerset.md +6 -0
- package/docs/reference/functions/setSize.md +6 -0
- package/docs/reference/functions/setSymDifference.md +6 -0
- package/docs/reference/functions/setUnion.md +6 -0
- package/docs/reference/functions/sign.md +6 -0
- package/docs/reference/functions/simplify.md +47 -7
- package/docs/reference/functions/simplifyCore.md +50 -0
- package/docs/reference/functions/sin.md +6 -0
- package/docs/reference/functions/sinh.md +6 -0
- package/docs/reference/functions/size.md +6 -0
- package/docs/reference/functions/slu.md +6 -0
- package/docs/reference/functions/smaller.md +6 -0
- package/docs/reference/functions/smallerEq.md +6 -0
- package/docs/reference/functions/sort.md +6 -0
- package/docs/reference/functions/sqrt.md +6 -0
- package/docs/reference/functions/sqrtm.md +6 -0
- package/docs/reference/functions/square.md +6 -0
- package/docs/reference/functions/squeeze.md +6 -0
- package/docs/reference/functions/std.md +6 -0
- package/docs/reference/functions/stirlingS2.md +6 -0
- package/docs/reference/functions/subset.md +6 -0
- package/docs/reference/functions/subtract.md +6 -0
- package/docs/reference/functions/sum.md +6 -0
- package/docs/reference/functions/tan.md +6 -0
- package/docs/reference/functions/tanh.md +6 -0
- package/docs/reference/functions/to.md +6 -0
- package/docs/reference/functions/trace.md +6 -0
- package/docs/reference/functions/transpose.md +6 -0
- package/docs/reference/functions/typeOf.md +6 -0
- package/docs/reference/functions/unaryMinus.md +6 -0
- package/docs/reference/functions/unaryPlus.md +6 -0
- package/docs/reference/functions/unequal.md +6 -0
- package/docs/reference/functions/usolve.md +6 -0
- package/docs/reference/functions/usolveAll.md +6 -0
- package/docs/reference/functions/variance.md +6 -0
- package/docs/reference/functions/xgcd.md +6 -0
- package/docs/reference/functions/xor.md +6 -0
- package/docs/reference/functions/zeros.md +6 -0
- package/docs/reference/functions.md +4 -0
- package/lib/browser/math.js +7 -7
- package/lib/browser/math.js.map +1 -1
- package/lib/cjs/core/create.js +4 -4
- package/lib/cjs/core/function/import.js +3 -3
- package/lib/cjs/core/function/typed.js +2 -2
- package/lib/cjs/defaultInstance.js +3 -3
- package/lib/cjs/entry/allFactoriesAny.js +1 -1
- package/lib/cjs/entry/allFactoriesNumber.js +1 -1
- package/lib/cjs/entry/configReadonly.js +1 -1
- package/lib/cjs/entry/dependenciesAny/dependenciesInvmod.generated.js +41 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesLeafCount.generated.js +23 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesRationalize.generated.js +18 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesResolve.generated.js +32 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSimplify.generated.js +21 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSimplifyCore.generated.js +65 -0
- package/lib/cjs/entry/dependenciesAny.generated.js +32 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesRationalize.generated.js +18 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesResolve.generated.js +32 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesSimplify.generated.js +21 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesSimplifyCore.generated.js +65 -0
- package/lib/cjs/entry/dependenciesNumber.generated.js +16 -0
- package/lib/cjs/entry/impureFunctionsAny.generated.js +78 -29
- package/lib/cjs/entry/impureFunctionsNumber.generated.js +102 -60
- package/lib/cjs/entry/pureFunctionsAny.generated.js +65 -55
- package/lib/cjs/entry/pureFunctionsNumber.generated.js +46 -48
- package/lib/cjs/expression/Help.js +4 -0
- package/lib/cjs/expression/Parser.js +1 -1
- package/lib/cjs/expression/embeddedDocs/core/typed.js +1 -1
- package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +20 -6
- package/lib/cjs/expression/embeddedDocs/function/algebra/leafCount.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/algebra/resolve.js +16 -0
- package/lib/cjs/expression/embeddedDocs/function/algebra/simplify.js +1 -1
- package/lib/cjs/expression/embeddedDocs/function/algebra/simplifyCore.js +15 -0
- 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/expression/node/FunctionNode.js +7 -7
- package/lib/cjs/expression/node/IndexNode.js +1 -1
- package/lib/cjs/expression/node/Node.js +3 -3
- package/lib/cjs/expression/node/ObjectNode.js +1 -1
- package/lib/cjs/expression/node/utils/access.js +1 -1
- package/lib/cjs/expression/node/utils/assign.js +1 -1
- package/lib/cjs/expression/parse.js +13 -13
- package/lib/cjs/factoriesAny.js +32 -0
- package/lib/cjs/factoriesNumber.js +16 -0
- package/lib/cjs/function/algebra/decomposition/qr.js +1 -1
- package/lib/cjs/function/algebra/leafCount.js +66 -0
- package/lib/cjs/function/algebra/rationalize.js +36 -39
- package/lib/cjs/function/algebra/resolve.js +106 -0
- package/lib/cjs/function/algebra/simplify/simplifyConstant.js +226 -32
- package/lib/cjs/function/algebra/simplify/util.js +171 -33
- package/lib/cjs/function/algebra/simplify.js +608 -191
- package/lib/cjs/function/algebra/{simplify/simplifyCore.js → simplifyCore.js} +83 -31
- package/lib/cjs/function/algebra/solver/lsolveAll.js +2 -2
- package/lib/cjs/function/algebra/solver/usolveAll.js +2 -2
- package/lib/cjs/function/arithmetic/ceil.js +3 -3
- package/lib/cjs/function/arithmetic/floor.js +3 -3
- package/lib/cjs/function/arithmetic/invmod.js +73 -0
- package/lib/cjs/function/arithmetic/norm.js +1 -1
- package/lib/cjs/function/arithmetic/round.js +1 -1
- package/lib/cjs/function/matrix/eigs/complexEigs.js +5 -5
- package/lib/cjs/function/matrix/matrixFromColumns.js +1 -1
- package/lib/cjs/function/matrix/matrixFromRows.js +1 -1
- package/lib/cjs/function/probability/util/seededRNG.js +2 -2
- package/lib/cjs/function/relational/compareNatural.js +6 -6
- package/lib/cjs/header.js +3 -3
- package/lib/cjs/plain/bignumber/index.js +1 -1
- package/lib/cjs/plain/number/combinations.js +18 -6
- package/lib/cjs/type/bignumber/BigNumber.js +2 -2
- package/lib/cjs/type/bignumber/function/bignumber.js +1 -1
- package/lib/cjs/type/boolean.js +2 -2
- package/lib/cjs/type/complex/Complex.js +14 -14
- package/lib/cjs/type/complex/function/complex.js +1 -1
- package/lib/cjs/type/fraction/Fraction.js +6 -6
- package/lib/cjs/type/fraction/function/fraction.js +1 -1
- package/lib/cjs/type/matrix/DenseMatrix.js +5 -5
- package/lib/cjs/type/matrix/SparseMatrix.js +2 -2
- package/lib/cjs/type/number.js +1 -1
- package/lib/cjs/type/string.js +2 -2
- package/lib/cjs/type/unit/Unit.js +8 -8
- package/lib/cjs/utils/customs.js +2 -2
- package/lib/cjs/utils/emitter.js +1 -1
- package/lib/cjs/utils/function.js +2 -2
- package/lib/cjs/utils/is.js +6 -6
- package/lib/cjs/utils/latex.js +3 -3
- package/lib/cjs/utils/lruQueue.js +1 -1
- package/lib/cjs/utils/map.js +3 -3
- package/lib/cjs/utils/object.js +2 -2
- package/lib/cjs/utils/snapshot.js +7 -7
- package/lib/cjs/utils/string.js +2 -2
- package/lib/cjs/version.js +1 -1
- package/lib/esm/entry/dependenciesAny/dependenciesInvmod.generated.js +24 -0
- package/lib/esm/entry/dependenciesAny/dependenciesLeafCount.generated.js +12 -0
- package/lib/esm/entry/dependenciesAny/dependenciesRationalize.generated.js +12 -0
- package/lib/esm/entry/dependenciesAny/dependenciesResolve.generated.js +18 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSimplify.generated.js +14 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSimplifyCore.generated.js +40 -0
- package/lib/esm/entry/dependenciesAny.generated.js +4 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesRationalize.generated.js +12 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesResolve.generated.js +18 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesSimplify.generated.js +14 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesSimplifyCore.generated.js +40 -0
- package/lib/esm/entry/dependenciesNumber.generated.js +2 -0
- package/lib/esm/entry/impureFunctionsAny.generated.js +68 -22
- package/lib/esm/entry/impureFunctionsNumber.generated.js +92 -52
- package/lib/esm/entry/pureFunctionsAny.generated.js +53 -42
- package/lib/esm/entry/pureFunctionsNumber.generated.js +32 -32
- package/lib/esm/expression/Help.js +4 -0
- package/lib/esm/expression/embeddedDocs/core/typed.js +1 -1
- package/lib/esm/expression/embeddedDocs/embeddedDocs.js +10 -1
- package/lib/esm/expression/embeddedDocs/function/algebra/leafCount.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/algebra/resolve.js +9 -0
- package/lib/esm/expression/embeddedDocs/function/algebra/simplify.js +1 -1
- package/lib/esm/expression/embeddedDocs/function/algebra/simplifyCore.js +8 -0
- 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 +4 -0
- package/lib/esm/factoriesNumber.js +2 -0
- package/lib/esm/function/algebra/leafCount.js +59 -0
- package/lib/esm/function/algebra/rationalize.js +36 -38
- package/lib/esm/function/algebra/resolve.js +95 -0
- package/lib/esm/function/algebra/simplify/simplifyConstant.js +200 -32
- package/lib/esm/function/algebra/simplify/util.js +170 -34
- package/lib/esm/function/algebra/simplify.js +603 -186
- package/lib/esm/function/algebra/{simplify/simplifyCore.js → simplifyCore.js} +75 -31
- package/lib/esm/function/arithmetic/invmod.js +57 -0
- package/lib/esm/header.js +1 -1
- package/lib/esm/plain/number/combinations.js +18 -6
- package/lib/esm/version.js +1 -1
- package/package.json +21 -15
- package/types/index.d.ts +48 -6
- package/lib/cjs/function/algebra/simplify/resolve.js +0 -76
- package/lib/esm/function/algebra/simplify/resolve.js +0 -67
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { isConstantNode, isParenthesisNode } from '../../utils/is.js';
|
|
2
2
|
import { factory } from '../../utils/factory.js';
|
|
3
3
|
import { createUtil } from './simplify/util.js';
|
|
4
|
-
import { createSimplifyCore } from './simplify/simplifyCore.js';
|
|
5
4
|
import { createSimplifyConstant } from './simplify/simplifyConstant.js';
|
|
6
|
-
import { createResolve } from './simplify/resolve.js';
|
|
7
5
|
import { hasOwnProperty } from '../../utils/object.js';
|
|
8
6
|
import { createEmptyMap, createMap } from '../../utils/map.js';
|
|
9
7
|
var name = 'simplify';
|
|
10
|
-
var dependencies = ['config', 'typed', 'parse', 'add', 'subtract', 'multiply', 'divide', 'pow', 'isZero', 'equal', '?fraction', '?bignumber', 'mathWithTransform', 'ConstantNode', 'FunctionNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
|
|
8
|
+
var dependencies = ['config', 'typed', 'parse', 'add', 'subtract', 'multiply', 'divide', 'pow', 'isZero', 'equal', 'resolve', 'simplifyCore', '?fraction', '?bignumber', 'mathWithTransform', 'matrix', 'AccessorNode', 'ArrayNode', 'ConstantNode', 'FunctionNode', 'IndexNode', 'ObjectNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
|
|
11
9
|
export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
12
10
|
var {
|
|
13
11
|
config,
|
|
@@ -20,11 +18,18 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
20
18
|
pow,
|
|
21
19
|
isZero,
|
|
22
20
|
equal,
|
|
21
|
+
resolve,
|
|
22
|
+
simplifyCore,
|
|
23
23
|
fraction,
|
|
24
24
|
bignumber,
|
|
25
25
|
mathWithTransform,
|
|
26
|
+
matrix,
|
|
27
|
+
AccessorNode,
|
|
28
|
+
ArrayNode,
|
|
26
29
|
ConstantNode,
|
|
27
30
|
FunctionNode,
|
|
31
|
+
IndexNode,
|
|
32
|
+
ObjectNode,
|
|
28
33
|
OperatorNode,
|
|
29
34
|
ParenthesisNode,
|
|
30
35
|
SymbolNode
|
|
@@ -33,39 +38,30 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
33
38
|
typed,
|
|
34
39
|
config,
|
|
35
40
|
mathWithTransform,
|
|
41
|
+
matrix,
|
|
36
42
|
fraction,
|
|
37
43
|
bignumber,
|
|
44
|
+
AccessorNode,
|
|
45
|
+
ArrayNode,
|
|
38
46
|
ConstantNode,
|
|
39
|
-
OperatorNode,
|
|
40
|
-
FunctionNode,
|
|
41
|
-
SymbolNode
|
|
42
|
-
});
|
|
43
|
-
var simplifyCore = createSimplifyCore({
|
|
44
|
-
equal,
|
|
45
|
-
isZero,
|
|
46
|
-
add,
|
|
47
|
-
subtract,
|
|
48
|
-
multiply,
|
|
49
|
-
divide,
|
|
50
|
-
pow,
|
|
51
|
-
ConstantNode,
|
|
52
|
-
OperatorNode,
|
|
53
|
-
FunctionNode,
|
|
54
|
-
ParenthesisNode
|
|
55
|
-
});
|
|
56
|
-
var resolve = createResolve({
|
|
57
|
-
parse,
|
|
58
47
|
FunctionNode,
|
|
48
|
+
IndexNode,
|
|
49
|
+
ObjectNode,
|
|
59
50
|
OperatorNode,
|
|
60
|
-
|
|
51
|
+
SymbolNode
|
|
61
52
|
});
|
|
62
53
|
var {
|
|
54
|
+
hasProperty,
|
|
63
55
|
isCommutative,
|
|
64
56
|
isAssociative,
|
|
57
|
+
mergeContext,
|
|
65
58
|
flatten,
|
|
66
59
|
unflattenr,
|
|
67
60
|
unflattenl,
|
|
68
|
-
createMakeNodeFunction
|
|
61
|
+
createMakeNodeFunction,
|
|
62
|
+
defaultContext,
|
|
63
|
+
realContext,
|
|
64
|
+
positiveContext
|
|
69
65
|
} = createUtil({
|
|
70
66
|
FunctionNode,
|
|
71
67
|
OperatorNode,
|
|
@@ -101,17 +97,49 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
101
97
|
* The default list of rules is exposed on the function as `simplify.rules`
|
|
102
98
|
* and can be used as a basis to built a set of custom rules.
|
|
103
99
|
*
|
|
100
|
+
* To specify a rule as a string, separate the left and right pattern by '->'
|
|
101
|
+
* When specifying a rule as an object, the following keys are meaningful:
|
|
102
|
+
* - l - the left pattern
|
|
103
|
+
* - r - the right pattern
|
|
104
|
+
* - s - in lieu of l and r, the string form that is broken at -> to give them
|
|
105
|
+
* - repeat - whether to repeat this rule until the expression stabilizes
|
|
106
|
+
* - assuming - gives a context object, as in the 'context' option to
|
|
107
|
+
* simplify. Every property in the context object must match the current
|
|
108
|
+
* context in order, or else the rule will not be applied.
|
|
109
|
+
* - imposeContext - gives a context object, as in the 'context' option to
|
|
110
|
+
* simplify. Any settings specified will override the incoming context
|
|
111
|
+
* for all matches of this rule.
|
|
112
|
+
*
|
|
104
113
|
* For more details on the theory, see:
|
|
105
114
|
*
|
|
106
115
|
* - [Strategies for simplifying math expressions (Stackoverflow)](https://stackoverflow.com/questions/7540227/strategies-for-simplifying-math-expressions)
|
|
107
116
|
* - [Symbolic computation - Simplification (Wikipedia)](https://en.wikipedia.org/wiki/Symbolic_computation#Simplification)
|
|
108
117
|
*
|
|
109
118
|
* An optional `options` argument can be passed as last argument of `simplify`.
|
|
110
|
-
*
|
|
111
|
-
* - `
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
119
|
+
* Currently available options (defaults in parentheses):
|
|
120
|
+
* - `consoleDebug` (false): whether to write the expression being simplified
|
|
121
|
+
* and any changes to it, along with the rule responsible, to console
|
|
122
|
+
* - `context` (simplify.defaultContext): an object giving properties of
|
|
123
|
+
* each operator, which determine what simplifications are allowed. The
|
|
124
|
+
* currently meaningful properties are commutative, associative,
|
|
125
|
+
* total (whether the operation is defined for all arguments), and
|
|
126
|
+
* trivial (whether the operation applied to a single argument leaves
|
|
127
|
+
* that argument unchanged). The default context is very permissive and
|
|
128
|
+
* allows almost all simplifications. Only properties differing from
|
|
129
|
+
* the default need to be specified; the default context is used as a
|
|
130
|
+
* fallback. Additional contexts `simplify.realContext` and
|
|
131
|
+
* `simplify.positiveContext` are supplied to cause simplify to perform
|
|
132
|
+
* just simplifications guaranteed to preserve all values of the expression
|
|
133
|
+
* assuming all variables and subexpressions are real numbers or
|
|
134
|
+
* positive real numbers, respectively. (Note that these are in some cases
|
|
135
|
+
* more restrictive than the default context; for example, the default
|
|
136
|
+
* context will allow `x/x` to simplify to 1, whereas
|
|
137
|
+
* `simplify.realContext` will not, as `0/0` is not equal to 1.)
|
|
138
|
+
* - `exactFractions` (true): whether to try to convert all constants to
|
|
139
|
+
* exact rational numbers.
|
|
140
|
+
* - `fractionsLimit` (10000): when `exactFractions` is true, constants will
|
|
141
|
+
* be expressed as fractions only when both numerator and denominator
|
|
142
|
+
* are smaller than `fractionsLimit`.
|
|
115
143
|
*
|
|
116
144
|
* Syntax:
|
|
117
145
|
*
|
|
@@ -134,7 +162,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
134
162
|
*
|
|
135
163
|
* See also:
|
|
136
164
|
*
|
|
137
|
-
* derivative, parse,
|
|
165
|
+
* simplifyCore, derivative, evaluate, parse, rationalize, resolve
|
|
138
166
|
*
|
|
139
167
|
* @param {Node | string} expr
|
|
140
168
|
* The expression to be simplified
|
|
@@ -181,7 +209,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
181
209
|
return this(expr, rules, createMap(scope), options);
|
|
182
210
|
},
|
|
183
211
|
'Node, Array, Map, Object': function NodeArrayMapObject(expr, rules, scope, options) {
|
|
184
|
-
|
|
212
|
+
var debug = options.consoleDebug;
|
|
213
|
+
rules = _buildRules(rules, options.context);
|
|
185
214
|
var res = resolve(expr, scope);
|
|
186
215
|
res = removeParens(res);
|
|
187
216
|
var visited = {};
|
|
@@ -193,15 +222,40 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
193
222
|
visited[str] = true;
|
|
194
223
|
_lastsym = 0; // counter for placeholder symbols
|
|
195
224
|
|
|
225
|
+
var laststr = str;
|
|
226
|
+
if (debug) console.log('Working on: ', str);
|
|
227
|
+
|
|
196
228
|
for (var i = 0; i < rules.length; i++) {
|
|
229
|
+
var rulestr = '';
|
|
230
|
+
|
|
197
231
|
if (typeof rules[i] === 'function') {
|
|
198
232
|
res = rules[i](res, options);
|
|
233
|
+
if (debug) rulestr = rules[i].name;
|
|
199
234
|
} else {
|
|
200
|
-
flatten(res);
|
|
201
|
-
res = applyRule(res, rules[i]);
|
|
235
|
+
flatten(res, options.context);
|
|
236
|
+
res = applyRule(res, rules[i], options.context);
|
|
237
|
+
|
|
238
|
+
if (debug) {
|
|
239
|
+
rulestr = "".concat(rules[i].l.toString(), " -> ").concat(rules[i].r.toString());
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (debug) {
|
|
244
|
+
var newstr = res.toString({
|
|
245
|
+
parenthesis: 'all'
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
if (newstr !== laststr) {
|
|
249
|
+
console.log('Applying', rulestr, 'produced', newstr);
|
|
250
|
+
laststr = newstr;
|
|
251
|
+
}
|
|
202
252
|
}
|
|
253
|
+
/* Use left-heavy binary tree internally,
|
|
254
|
+
* since custom rule functions may expect it
|
|
255
|
+
*/
|
|
203
256
|
|
|
204
|
-
|
|
257
|
+
|
|
258
|
+
unflattenl(res, options.context);
|
|
205
259
|
}
|
|
206
260
|
|
|
207
261
|
str = res.toString({
|
|
@@ -212,8 +266,9 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
212
266
|
return res;
|
|
213
267
|
}
|
|
214
268
|
});
|
|
215
|
-
simplify.
|
|
216
|
-
simplify.
|
|
269
|
+
simplify.defaultContext = defaultContext;
|
|
270
|
+
simplify.realContext = realContext;
|
|
271
|
+
simplify.positiveContext = positiveContext;
|
|
217
272
|
|
|
218
273
|
function removeParens(node) {
|
|
219
274
|
return node.transform(function (node, path, parent) {
|
|
@@ -262,72 +317,247 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
262
317
|
l: 'log(e)',
|
|
263
318
|
r: '1'
|
|
264
319
|
}, // temporary rules
|
|
320
|
+
// Note initially we tend constants to the right because like-term
|
|
321
|
+
// collection prefers the left, and we would rather collect nonconstants
|
|
265
322
|
{
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
323
|
+
s: 'n-n1 -> n+-n1',
|
|
324
|
+
// temporarily replace 'subtract' so we can further flatten the 'add' operator
|
|
325
|
+
assuming: {
|
|
326
|
+
subtract: {
|
|
327
|
+
total: true
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}, {
|
|
331
|
+
s: '-(c*v) -> v * (-c)',
|
|
332
|
+
// make non-constant terms positive
|
|
333
|
+
assuming: {
|
|
334
|
+
multiply: {
|
|
335
|
+
commutative: true
|
|
336
|
+
},
|
|
337
|
+
subtract: {
|
|
338
|
+
total: true
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}, {
|
|
342
|
+
s: '-(c*v) -> (-c) * v',
|
|
343
|
+
// non-commutative version, part 1
|
|
344
|
+
assuming: {
|
|
345
|
+
multiply: {
|
|
346
|
+
commutative: false
|
|
347
|
+
},
|
|
348
|
+
subtract: {
|
|
349
|
+
total: true
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}, {
|
|
353
|
+
s: '-(v*c) -> v * (-c)',
|
|
354
|
+
// non-commutative version, part 2
|
|
355
|
+
assuming: {
|
|
356
|
+
multiply: {
|
|
357
|
+
commutative: false
|
|
358
|
+
},
|
|
359
|
+
subtract: {
|
|
360
|
+
total: true
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}, {
|
|
364
|
+
l: '-(n1/n2)',
|
|
365
|
+
r: '-n1/n2'
|
|
366
|
+
}, {
|
|
367
|
+
l: '-v',
|
|
368
|
+
r: 'v * (-1)'
|
|
369
|
+
}, // finish making non-constant terms positive
|
|
269
370
|
{
|
|
270
|
-
l: '
|
|
271
|
-
r: '(-
|
|
272
|
-
|
|
371
|
+
l: '(n1 + n2)*(-1)',
|
|
372
|
+
r: 'n1*(-1) + n2*(-1)',
|
|
373
|
+
repeat: true
|
|
374
|
+
}, // expand negations to achieve as much sign cancellation as possible
|
|
273
375
|
{
|
|
274
|
-
l: '-v',
|
|
275
|
-
r: '(-1) * v'
|
|
276
|
-
}, {
|
|
277
376
|
l: 'n/n1^n2',
|
|
278
377
|
r: 'n*n1^-n2'
|
|
279
378
|
}, // temporarily replace 'divide' so we can further flatten the 'multiply' operator
|
|
280
379
|
{
|
|
281
380
|
l: 'n/n1',
|
|
282
381
|
r: 'n*n1^-1'
|
|
382
|
+
}, {
|
|
383
|
+
s: '(n1*n2)^n3 -> n1^n3 * n2^n3',
|
|
384
|
+
assuming: {
|
|
385
|
+
multiply: {
|
|
386
|
+
commutative: true
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}, {
|
|
390
|
+
s: '(n1*n2)^(-1) -> n2^(-1) * n1^(-1)',
|
|
391
|
+
assuming: {
|
|
392
|
+
multiply: {
|
|
393
|
+
commutative: false
|
|
394
|
+
}
|
|
395
|
+
}
|
|
283
396
|
}, // expand nested exponentiation
|
|
284
397
|
{
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
398
|
+
s: '(n ^ n1) ^ n2 -> n ^ (n1 * n2)',
|
|
399
|
+
assuming: {
|
|
400
|
+
divide: {
|
|
401
|
+
total: true
|
|
402
|
+
}
|
|
403
|
+
} // 1/(1/n) = n needs 1/n to exist
|
|
404
|
+
|
|
405
|
+
}, // collect like factors; into a sum, only do this for nonconstants
|
|
288
406
|
{
|
|
407
|
+
l: ' v * ( v * n1 + n2)',
|
|
408
|
+
r: 'v^2 * n1 + v * n2'
|
|
409
|
+
}, {
|
|
410
|
+
s: ' v * (v^n4 * n1 + n2) -> v^(1+n4) * n1 + v * n2',
|
|
411
|
+
assuming: {
|
|
412
|
+
divide: {
|
|
413
|
+
total: true
|
|
414
|
+
}
|
|
415
|
+
} // v*1/v = v^(1+-1) needs 1/v
|
|
416
|
+
|
|
417
|
+
}, {
|
|
418
|
+
s: 'v^n3 * ( v * n1 + n2) -> v^(n3+1) * n1 + v^n3 * n2',
|
|
419
|
+
assuming: {
|
|
420
|
+
divide: {
|
|
421
|
+
total: true
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}, {
|
|
425
|
+
s: 'v^n3 * (v^n4 * n1 + n2) -> v^(n3+n4) * n1 + v^n3 * n2',
|
|
426
|
+
assuming: {
|
|
427
|
+
divide: {
|
|
428
|
+
total: true
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}, {
|
|
289
432
|
l: 'n*n',
|
|
290
433
|
r: 'n^2'
|
|
291
434
|
}, {
|
|
292
|
-
|
|
293
|
-
|
|
435
|
+
s: 'n * n^n1 -> n^(n1+1)',
|
|
436
|
+
assuming: {
|
|
437
|
+
divide: {
|
|
438
|
+
total: true
|
|
439
|
+
}
|
|
440
|
+
} // n*1/n = n^(-1+1) needs 1/n
|
|
441
|
+
|
|
294
442
|
}, {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
443
|
+
s: 'n^n1 * n^n2 -> n^(n1+n2)',
|
|
444
|
+
assuming: {
|
|
445
|
+
divide: {
|
|
446
|
+
total: true
|
|
447
|
+
}
|
|
448
|
+
} // ditto for n^2*1/n^2
|
|
449
|
+
|
|
450
|
+
}, // Unfortunately, to deal with more complicated cancellations, it
|
|
451
|
+
// becomes necessary to simplify constants twice per pass. It's not
|
|
452
|
+
// terribly expensive compared to matching rules, so this should not
|
|
453
|
+
// pose a performance problem.
|
|
454
|
+
simplifyConstant, // First: before collecting like terms
|
|
455
|
+
// collect like terms
|
|
298
456
|
{
|
|
299
|
-
|
|
300
|
-
|
|
457
|
+
s: 'n+n -> 2*n',
|
|
458
|
+
assuming: {
|
|
459
|
+
add: {
|
|
460
|
+
total: true
|
|
461
|
+
}
|
|
462
|
+
} // 2 = 1 + 1 needs to exist
|
|
463
|
+
|
|
301
464
|
}, {
|
|
302
465
|
l: 'n+-n',
|
|
303
466
|
r: '0'
|
|
304
467
|
}, {
|
|
305
|
-
l: '
|
|
306
|
-
r: '(
|
|
468
|
+
l: 'v*n + v',
|
|
469
|
+
r: 'v*(n+1)'
|
|
470
|
+
}, // NOTE: leftmost position is special:
|
|
471
|
+
{
|
|
472
|
+
l: 'n3*n1 + n3*n2',
|
|
473
|
+
r: 'n3*(n1+n2)'
|
|
474
|
+
}, // All sub-monomials tried there.
|
|
475
|
+
{
|
|
476
|
+
l: 'n3^(-n4)*n1 + n3 * n2',
|
|
477
|
+
r: 'n3^(-n4)*(n1 + n3^(n4+1) *n2)'
|
|
478
|
+
}, {
|
|
479
|
+
l: 'n3^(-n4)*n1 + n3^n5 * n2',
|
|
480
|
+
r: 'n3^(-n4)*(n1 + n3^(n4+n5)*n2)'
|
|
307
481
|
}, {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
482
|
+
s: 'n*v + v -> (n+1)*v',
|
|
483
|
+
// noncommutative additional cases
|
|
484
|
+
assuming: {
|
|
485
|
+
multiply: {
|
|
486
|
+
commutative: false
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}, {
|
|
490
|
+
s: 'n1*n3 + n2*n3 -> (n1+n2)*n3',
|
|
491
|
+
assuming: {
|
|
492
|
+
multiply: {
|
|
493
|
+
commutative: false
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}, {
|
|
497
|
+
s: 'n1*n3^(-n4) + n2 * n3 -> (n1 + n2*n3^(n4 + 1))*n3^(-n4)',
|
|
498
|
+
assuming: {
|
|
499
|
+
multiply: {
|
|
500
|
+
commutative: false
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}, {
|
|
504
|
+
s: 'n1*n3^(-n4) + n2 * n3^n5 -> (n1 + n2*n3^(n4 + n5))*n3^(-n4)',
|
|
505
|
+
assuming: {
|
|
506
|
+
multiply: {
|
|
507
|
+
commutative: false
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}, {
|
|
511
|
+
l: 'n*c + c',
|
|
512
|
+
r: '(n+1)*c'
|
|
513
|
+
}, {
|
|
514
|
+
s: 'c*n + c -> c*(n+1)',
|
|
515
|
+
assuming: {
|
|
516
|
+
multiply: {
|
|
517
|
+
commutative: false
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}, simplifyConstant, // Second: before returning expressions to "standard form"
|
|
521
|
+
// make factors positive (and undo 'make non-constant terms positive')
|
|
311
522
|
{
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
523
|
+
s: '(-n)*n1 -> -(n*n1)',
|
|
524
|
+
assuming: {
|
|
525
|
+
subtract: {
|
|
526
|
+
total: true
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}, {
|
|
530
|
+
s: 'n1*(-n) -> -(n1*n)',
|
|
531
|
+
// in case * non-commutative
|
|
532
|
+
assuming: {
|
|
533
|
+
subtract: {
|
|
534
|
+
total: true
|
|
535
|
+
},
|
|
536
|
+
multiply: {
|
|
537
|
+
commutative: false
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}, // final ordering of constants
|
|
319
541
|
{
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
542
|
+
s: 'c+v -> v+c',
|
|
543
|
+
assuming: {
|
|
544
|
+
add: {
|
|
545
|
+
commutative: true
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
imposeContext: {
|
|
323
549
|
add: {
|
|
324
550
|
commutative: false
|
|
325
551
|
}
|
|
326
552
|
}
|
|
327
553
|
}, {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
554
|
+
s: 'v*c -> c*v',
|
|
555
|
+
assuming: {
|
|
556
|
+
multiply: {
|
|
557
|
+
commutative: true
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
imposeContext: {
|
|
331
561
|
multiply: {
|
|
332
562
|
commutative: false
|
|
333
563
|
}
|
|
@@ -339,36 +569,125 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
339
569
|
r: 'n-n1'
|
|
340
570
|
}, // undo replace 'subtract'
|
|
341
571
|
{
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
572
|
+
s: 'n*(n1^-1) -> n/n1',
|
|
573
|
+
// undo replace 'divide'; for * commutative
|
|
574
|
+
assuming: {
|
|
575
|
+
multiply: {
|
|
576
|
+
commutative: true
|
|
577
|
+
}
|
|
578
|
+
} // o.w. / not conventional
|
|
579
|
+
|
|
348
580
|
}, {
|
|
349
|
-
|
|
350
|
-
|
|
581
|
+
s: 'n*n1^-n2 -> n/n1^n2',
|
|
582
|
+
assuming: {
|
|
583
|
+
multiply: {
|
|
584
|
+
commutative: true
|
|
585
|
+
}
|
|
586
|
+
} // o.w. / not conventional
|
|
587
|
+
|
|
588
|
+
}, {
|
|
589
|
+
s: 'n^-1 -> 1/n',
|
|
590
|
+
assuming: {
|
|
591
|
+
multiply: {
|
|
592
|
+
commutative: true
|
|
593
|
+
}
|
|
594
|
+
} // o.w. / not conventional
|
|
595
|
+
|
|
351
596
|
}, {
|
|
352
|
-
l: 'n
|
|
353
|
-
r: '
|
|
354
|
-
}, //
|
|
597
|
+
l: 'n^1',
|
|
598
|
+
r: 'n'
|
|
599
|
+
}, // can be produced by power cancellation
|
|
355
600
|
{
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
601
|
+
s: 'n*(n1/n2) -> (n*n1)/n2',
|
|
602
|
+
// '*' before '/'
|
|
603
|
+
assuming: {
|
|
604
|
+
multiply: {
|
|
605
|
+
associative: true
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}, {
|
|
609
|
+
s: 'n-(n1+n2) -> n-n1-n2',
|
|
610
|
+
// '-' before '+'
|
|
611
|
+
assuming: {
|
|
612
|
+
addition: {
|
|
613
|
+
associative: true,
|
|
614
|
+
commutative: true
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}, // { l: '(n1/n2)/n3', r: 'n1/(n2*n3)' },
|
|
360
618
|
// { l: '(n*n1)/(n*n2)', r: 'n1/n2' },
|
|
619
|
+
// simplifyConstant can leave an extra factor of 1, which can always
|
|
620
|
+
// be eliminated, since the identity always commutes
|
|
361
621
|
{
|
|
362
622
|
l: '1*n',
|
|
363
|
-
r: 'n'
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
623
|
+
r: 'n',
|
|
624
|
+
imposeContext: {
|
|
625
|
+
multiply: {
|
|
626
|
+
commutative: true
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}, {
|
|
630
|
+
s: 'n1/(n2/n3) -> (n1*n3)/n2',
|
|
631
|
+
assuming: {
|
|
632
|
+
multiply: {
|
|
633
|
+
associative: true
|
|
634
|
+
}
|
|
635
|
+
}
|
|
368
636
|
}, {
|
|
369
637
|
l: 'n1/(-n2)',
|
|
370
638
|
r: '-n1/n2'
|
|
371
639
|
}];
|
|
640
|
+
/**
|
|
641
|
+
* Takes any rule object as allowed by the specification in simplify
|
|
642
|
+
* and puts it in a standard form used by applyRule
|
|
643
|
+
*/
|
|
644
|
+
|
|
645
|
+
function _canonicalizeRule(ruleObject, context) {
|
|
646
|
+
var newRule = {};
|
|
647
|
+
|
|
648
|
+
if (ruleObject.s) {
|
|
649
|
+
var lr = ruleObject.s.split('->');
|
|
650
|
+
|
|
651
|
+
if (lr.length === 2) {
|
|
652
|
+
newRule.l = lr[0];
|
|
653
|
+
newRule.r = lr[1];
|
|
654
|
+
} else {
|
|
655
|
+
throw SyntaxError('Could not parse rule: ' + ruleObject.s);
|
|
656
|
+
}
|
|
657
|
+
} else {
|
|
658
|
+
newRule.l = ruleObject.l;
|
|
659
|
+
newRule.r = ruleObject.r;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
newRule.l = removeParens(parse(newRule.l));
|
|
663
|
+
newRule.r = removeParens(parse(newRule.r));
|
|
664
|
+
|
|
665
|
+
for (var prop of ['imposeContext', 'repeat', 'assuming']) {
|
|
666
|
+
if (prop in ruleObject) {
|
|
667
|
+
newRule[prop] = ruleObject[prop];
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (ruleObject.evaluate) {
|
|
672
|
+
newRule.evaluate = parse(ruleObject.evaluate);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if (isAssociative(newRule.l, context)) {
|
|
676
|
+
var makeNode = createMakeNodeFunction(newRule.l);
|
|
677
|
+
|
|
678
|
+
var expandsym = _getExpandPlaceholderSymbol();
|
|
679
|
+
|
|
680
|
+
newRule.expanded = {};
|
|
681
|
+
newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]); // Push the expandsym into the deepest possible branch.
|
|
682
|
+
// This helps to match the newRule against nodes returned from getSplits() later on.
|
|
683
|
+
|
|
684
|
+
flatten(newRule.expanded.l, context);
|
|
685
|
+
unflattenr(newRule.expanded.l, context);
|
|
686
|
+
newRule.expanded.r = makeNode([newRule.r, expandsym]);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
return newRule;
|
|
690
|
+
}
|
|
372
691
|
/**
|
|
373
692
|
* Parse the string array of rules into nodes
|
|
374
693
|
*
|
|
@@ -386,7 +705,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
386
705
|
* 'n1 * c1 -> c1 * n1'
|
|
387
706
|
*/
|
|
388
707
|
|
|
389
|
-
|
|
708
|
+
|
|
709
|
+
function _buildRules(rules, context) {
|
|
390
710
|
// Array of rules to be used to simplify expressions
|
|
391
711
|
var ruleSet = [];
|
|
392
712
|
|
|
@@ -397,49 +717,14 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
397
717
|
|
|
398
718
|
switch (ruleType) {
|
|
399
719
|
case 'string':
|
|
400
|
-
{
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
if (lr.length === 2) {
|
|
404
|
-
rule = {
|
|
405
|
-
l: lr[0],
|
|
406
|
-
r: lr[1]
|
|
407
|
-
};
|
|
408
|
-
} else {
|
|
409
|
-
throw SyntaxError('Could not parse rule: ' + rule);
|
|
410
|
-
}
|
|
411
|
-
}
|
|
720
|
+
rule = {
|
|
721
|
+
s: rule
|
|
722
|
+
};
|
|
412
723
|
|
|
413
724
|
/* falls through */
|
|
414
725
|
|
|
415
726
|
case 'object':
|
|
416
|
-
newRule =
|
|
417
|
-
l: removeParens(parse(rule.l)),
|
|
418
|
-
r: removeParens(parse(rule.r))
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
if (rule.context) {
|
|
422
|
-
newRule.evaluate = rule.context;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
if (rule.evaluate) {
|
|
426
|
-
newRule.evaluate = parse(rule.evaluate);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (isAssociative(newRule.l)) {
|
|
430
|
-
var makeNode = createMakeNodeFunction(newRule.l);
|
|
431
|
-
|
|
432
|
-
var expandsym = _getExpandPlaceholderSymbol();
|
|
433
|
-
|
|
434
|
-
newRule.expanded = {};
|
|
435
|
-
newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]); // Push the expandsym into the deepest possible branch.
|
|
436
|
-
// This helps to match the newRule against nodes returned from getSplits() later on.
|
|
437
|
-
|
|
438
|
-
flatten(newRule.expanded.l);
|
|
439
|
-
unflattenr(newRule.expanded.l);
|
|
440
|
-
newRule.expanded.r = makeNode([newRule.r, expandsym]);
|
|
441
|
-
}
|
|
442
|
-
|
|
727
|
+
newRule = _canonicalizeRule(rule, context);
|
|
443
728
|
break;
|
|
444
729
|
|
|
445
730
|
case 'function':
|
|
@@ -463,71 +748,156 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
463
748
|
function _getExpandPlaceholderSymbol() {
|
|
464
749
|
return new SymbolNode('_p' + _lastsym++);
|
|
465
750
|
}
|
|
751
|
+
|
|
752
|
+
function mapRule(nodes, rule, context) {
|
|
753
|
+
var resNodes = nodes;
|
|
754
|
+
|
|
755
|
+
if (nodes) {
|
|
756
|
+
for (var i = 0; i < nodes.length; ++i) {
|
|
757
|
+
var newNode = applyRule(nodes[i], rule, context);
|
|
758
|
+
|
|
759
|
+
if (newNode !== nodes[i]) {
|
|
760
|
+
if (resNodes === nodes) {
|
|
761
|
+
resNodes = nodes.slice();
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
resNodes[i] = newNode;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
return resNodes;
|
|
770
|
+
}
|
|
466
771
|
/**
|
|
467
772
|
* Returns a simplfied form of node, or the original node if no simplification was possible.
|
|
468
773
|
*
|
|
469
774
|
* @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} node
|
|
775
|
+
* @param {Object | Function} rule
|
|
776
|
+
* @param {Object} context -- information about assumed properties of operators
|
|
470
777
|
* @return {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} The simplified form of `expr`, or the original node if no simplification was possible.
|
|
471
778
|
*/
|
|
472
779
|
|
|
473
780
|
|
|
474
|
-
|
|
475
|
-
'
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if (res.args) {
|
|
484
|
-
for (var i = 0; i < res.args.length; i++) {
|
|
485
|
-
res.args[i] = applyRule(res.args[i], rule);
|
|
781
|
+
function applyRule(node, rule, context) {
|
|
782
|
+
// console.log('Entering applyRule("', rule.l.toString({parenthesis:'all'}), '->', rule.r.toString({parenthesis:'all'}), '",', node.toString({parenthesis:'all'}),')')
|
|
783
|
+
// check that the assumptions for this rule are satisfied by the current
|
|
784
|
+
// context:
|
|
785
|
+
if (rule.assuming) {
|
|
786
|
+
for (var symbol in rule.assuming) {
|
|
787
|
+
for (var property in rule.assuming[symbol]) {
|
|
788
|
+
if (hasProperty(symbol, property, context) !== rule.assuming[symbol][property]) {
|
|
789
|
+
return node;
|
|
486
790
|
}
|
|
487
791
|
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
var mergedContext = mergeContext(rule.imposeContext, context); // Do not clone node unless we find a match
|
|
796
|
+
|
|
797
|
+
var res = node; // First replace our child nodes with their simplified versions
|
|
798
|
+
// If a child could not be simplified, applying the rule to it
|
|
799
|
+
// will have no effect since the node is returned unchanged
|
|
800
|
+
|
|
801
|
+
if (res instanceof OperatorNode || res instanceof FunctionNode) {
|
|
802
|
+
var newArgs = mapRule(res.args, rule, context);
|
|
803
|
+
|
|
804
|
+
if (newArgs !== res.args) {
|
|
805
|
+
res = res.clone();
|
|
806
|
+
res.args = newArgs;
|
|
807
|
+
}
|
|
808
|
+
} else if (res instanceof ParenthesisNode) {
|
|
809
|
+
if (res.content) {
|
|
810
|
+
var newContent = applyRule(res.content, rule, context);
|
|
811
|
+
|
|
812
|
+
if (newContent !== res.content) {
|
|
813
|
+
res = new ParenthesisNode(newContent);
|
|
491
814
|
}
|
|
492
|
-
}
|
|
815
|
+
}
|
|
816
|
+
} else if (res instanceof ArrayNode) {
|
|
817
|
+
var newItems = mapRule(res.items, rule, context);
|
|
493
818
|
|
|
819
|
+
if (newItems !== res.items) {
|
|
820
|
+
res = new ArrayNode(newItems);
|
|
821
|
+
}
|
|
822
|
+
} else if (res instanceof AccessorNode) {
|
|
823
|
+
var newObj = res.object;
|
|
494
824
|
|
|
495
|
-
|
|
825
|
+
if (res.object) {
|
|
826
|
+
newObj = applyRule(res.object, rule, context);
|
|
827
|
+
}
|
|
496
828
|
|
|
497
|
-
var
|
|
498
|
-
// This allows us to match rules like 'n+n' to the expression '(1+x)+x' or even 'x+1+x' if the operator is commutative.
|
|
829
|
+
var newIndex = res.index;
|
|
499
830
|
|
|
831
|
+
if (res.index) {
|
|
832
|
+
newIndex = applyRule(res.index, rule, context);
|
|
833
|
+
}
|
|
500
834
|
|
|
501
|
-
if (
|
|
502
|
-
|
|
503
|
-
matches = _ruleMatch(rule.expanded.l, res)[0];
|
|
835
|
+
if (newObj !== res.object || newIndex !== res.index) {
|
|
836
|
+
res = new AccessorNode(newObj, newIndex);
|
|
504
837
|
}
|
|
838
|
+
} else if (res instanceof IndexNode) {
|
|
839
|
+
var newDims = mapRule(res.dimensions, rule, context);
|
|
505
840
|
|
|
506
|
-
if (
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
841
|
+
if (newDims !== res.dimensions) {
|
|
842
|
+
res = new IndexNode(newDims);
|
|
843
|
+
}
|
|
844
|
+
} else if (res instanceof ObjectNode) {
|
|
845
|
+
var changed = false;
|
|
846
|
+
var newProps = {};
|
|
512
847
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
} // Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
|
|
848
|
+
for (var prop in res.properties) {
|
|
849
|
+
newProps[prop] = applyRule(res.properties[prop], rule, context);
|
|
516
850
|
|
|
851
|
+
if (newProps[prop] !== res.properties[prop]) {
|
|
852
|
+
changed = true;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
517
855
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
return matches.placeholders[node.name].clone();
|
|
521
|
-
} else {
|
|
522
|
-
return node;
|
|
523
|
-
}
|
|
524
|
-
}); // const after = res.toString({parenthesis: 'all'})
|
|
525
|
-
// console.log('Simplified ' + before + ' to ' + after)
|
|
856
|
+
if (changed) {
|
|
857
|
+
res = new ObjectNode(newProps);
|
|
526
858
|
}
|
|
859
|
+
} // Try to match a rule against this node
|
|
527
860
|
|
|
528
|
-
|
|
861
|
+
|
|
862
|
+
var repl = rule.r;
|
|
863
|
+
|
|
864
|
+
var matches = _ruleMatch(rule.l, res, mergedContext)[0]; // If the rule is associative operator, we can try matching it while allowing additional terms.
|
|
865
|
+
// This allows us to match rules like 'n+n' to the expression '(1+x)+x' or even 'x+1+x' if the operator is commutative.
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
if (!matches && rule.expanded) {
|
|
869
|
+
repl = rule.expanded.r;
|
|
870
|
+
matches = _ruleMatch(rule.expanded.l, res, mergedContext)[0];
|
|
529
871
|
}
|
|
530
|
-
|
|
872
|
+
|
|
873
|
+
if (matches) {
|
|
874
|
+
// const before = res.toString({parenthesis: 'all'})
|
|
875
|
+
// Create a new node by cloning the rhs of the matched rule
|
|
876
|
+
// we keep any implicit multiplication state if relevant
|
|
877
|
+
var implicit = res.implicit;
|
|
878
|
+
res = repl.clone();
|
|
879
|
+
|
|
880
|
+
if (implicit && 'implicit' in repl) {
|
|
881
|
+
res.implicit = true;
|
|
882
|
+
} // Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
res = res.transform(function (node) {
|
|
886
|
+
if (node.isSymbolNode && hasOwnProperty(matches.placeholders, node.name)) {
|
|
887
|
+
return matches.placeholders[node.name].clone();
|
|
888
|
+
} else {
|
|
889
|
+
return node;
|
|
890
|
+
}
|
|
891
|
+
}); // const after = res.toString({parenthesis: 'all'})
|
|
892
|
+
// console.log('Simplified ' + before + ' to ' + after)
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (rule.repeat && res !== node) {
|
|
896
|
+
res = applyRule(res, rule, context);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
return res;
|
|
900
|
+
}
|
|
531
901
|
/**
|
|
532
902
|
* Get (binary) combinations of a flattened binary node
|
|
533
903
|
* e.g. +(node1, node2, node3) -> [
|
|
@@ -537,6 +907,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
537
907
|
*
|
|
538
908
|
*/
|
|
539
909
|
|
|
910
|
+
|
|
540
911
|
function getSplits(node, context) {
|
|
541
912
|
var res = [];
|
|
542
913
|
var right, rightArgs;
|
|
@@ -550,9 +921,18 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
550
921
|
res.push(makeNode([node.args[i], right]));
|
|
551
922
|
}
|
|
552
923
|
} else {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
924
|
+
// Keep order, but try all parenthesizations
|
|
925
|
+
for (var _i = 1; _i < node.args.length; _i++) {
|
|
926
|
+
var left = node.args[0];
|
|
927
|
+
|
|
928
|
+
if (_i > 1) {
|
|
929
|
+
left = makeNode(node.args.slice(0, _i));
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
rightArgs = node.args.slice(_i);
|
|
933
|
+
right = rightArgs.length === 1 ? rightArgs[0] : makeNode(rightArgs);
|
|
934
|
+
res.push(makeNode([left, right]));
|
|
935
|
+
}
|
|
556
936
|
}
|
|
557
937
|
|
|
558
938
|
return res;
|
|
@@ -655,15 +1035,19 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
655
1035
|
*
|
|
656
1036
|
* @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} rule
|
|
657
1037
|
* @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} node
|
|
1038
|
+
* @param {Object} context -- provides assumed properties of operators
|
|
1039
|
+
* @param {Boolean} isSplit -- whether we are in process of splitting an
|
|
1040
|
+
* n-ary operator node into possible binary combinations.
|
|
1041
|
+
* Defaults to false.
|
|
658
1042
|
* @return {Object} Information about the match, if it exists.
|
|
659
1043
|
*/
|
|
660
1044
|
|
|
661
1045
|
|
|
662
|
-
function _ruleMatch(rule, node, isSplit) {
|
|
1046
|
+
function _ruleMatch(rule, node, context, isSplit) {
|
|
663
1047
|
// console.log('Entering _ruleMatch(' + JSON.stringify(rule) + ', ' + JSON.stringify(node) + ')')
|
|
664
1048
|
// console.log('rule = ' + rule)
|
|
665
1049
|
// console.log('node = ' + node)
|
|
666
|
-
// console.log('Entering _ruleMatch('
|
|
1050
|
+
// console.log('Entering _ruleMatch(', rule.toString({parenthesis:'all'}), ', ', node.toString({parenthesis:'all'}), ', ', context, ')')
|
|
667
1051
|
var res = [{
|
|
668
1052
|
placeholders: {}
|
|
669
1053
|
}];
|
|
@@ -681,32 +1065,65 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
681
1065
|
} // rule and node match. Search the children of rule and node.
|
|
682
1066
|
|
|
683
1067
|
|
|
684
|
-
if (node.args.length === 1 && rule.args.length === 1 || !isAssociative(node) && node.args.length === rule.args.length || isSplit) {
|
|
685
|
-
// Expect non-associative operators to match exactly
|
|
1068
|
+
if (node.args.length === 1 && rule.args.length === 1 || !isAssociative(node, context) && node.args.length === rule.args.length || isSplit) {
|
|
1069
|
+
// Expect non-associative operators to match exactly,
|
|
1070
|
+
// except in any order if operator is commutative
|
|
686
1071
|
var childMatches = [];
|
|
687
1072
|
|
|
688
1073
|
for (var i = 0; i < rule.args.length; i++) {
|
|
689
|
-
var childMatch = _ruleMatch(rule.args[i], node.args[i]);
|
|
1074
|
+
var childMatch = _ruleMatch(rule.args[i], node.args[i], context);
|
|
690
1075
|
|
|
691
1076
|
if (childMatch.length === 0) {
|
|
692
1077
|
// Child did not match, so stop searching immediately
|
|
693
|
-
|
|
1078
|
+
break;
|
|
694
1079
|
} // The child matched, so add the information returned from the child to our result
|
|
695
1080
|
|
|
696
1081
|
|
|
697
1082
|
childMatches.push(childMatch);
|
|
698
1083
|
}
|
|
699
1084
|
|
|
1085
|
+
if (childMatches.length !== rule.args.length) {
|
|
1086
|
+
if (!isCommutative(node, context) || // exact match in order needed
|
|
1087
|
+
rule.args.length === 1) {
|
|
1088
|
+
// nothing to commute
|
|
1089
|
+
return [];
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
if (rule.args.length > 2) {
|
|
1093
|
+
/* Need to generate all permutations and try them.
|
|
1094
|
+
* It's a bit complicated, and unlikely to come up since there
|
|
1095
|
+
* are very few ternary or higher operators. So punt for now.
|
|
1096
|
+
*/
|
|
1097
|
+
throw new Error('permuting >2 commutative non-associative rule arguments not yet implemented');
|
|
1098
|
+
}
|
|
1099
|
+
/* Exactly two arguments, try them reversed */
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
var leftMatch = _ruleMatch(rule.args[0], node.args[1], context);
|
|
1103
|
+
|
|
1104
|
+
if (leftMatch.length === 0) {
|
|
1105
|
+
return [];
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
var rightMatch = _ruleMatch(rule.args[1], node.args[0], context);
|
|
1109
|
+
|
|
1110
|
+
if (rightMatch.length === 0) {
|
|
1111
|
+
return [];
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
childMatches = [leftMatch, rightMatch];
|
|
1115
|
+
}
|
|
1116
|
+
|
|
700
1117
|
res = mergeChildMatches(childMatches);
|
|
701
1118
|
} else if (node.args.length >= 2 && rule.args.length === 2) {
|
|
702
1119
|
// node is flattened, rule is not
|
|
703
1120
|
// Associative operators/functions can be split in different ways so we check if the rule matches each
|
|
704
1121
|
// them and return their union.
|
|
705
|
-
var splits = getSplits(node,
|
|
1122
|
+
var splits = getSplits(node, context);
|
|
706
1123
|
var splitMatches = [];
|
|
707
1124
|
|
|
708
|
-
for (var
|
|
709
|
-
var matchSet = _ruleMatch(rule, splits[
|
|
1125
|
+
for (var _i2 = 0; _i2 < splits.length; _i2++) {
|
|
1126
|
+
var matchSet = _ruleMatch(rule, splits[_i2], context, true); // recursing at the same tree depth here
|
|
710
1127
|
|
|
711
1128
|
|
|
712
1129
|
splitMatches = splitMatches.concat(matchSet);
|