mathjs 10.1.0 → 10.3.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 +38 -0
- package/docs/expressions/algebra.md +27 -0
- package/docs/expressions/syntax.md +31 -2
- 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 +6 -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 +28 -5
- 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 +16 -2
- package/docs/reference/functions/subtract.md +6 -0
- package/docs/reference/functions/sum.md +6 -0
- package/docs/reference/functions/symbolicEqual.md +62 -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 +5 -1
- package/lib/browser/math.js +6 -6
- 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/dependenciesLeafCount.generated.js +23 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesRationalize.generated.js +3 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesResolve.generated.js +32 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSimplify.generated.js +6 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSimplifyCore.generated.js +65 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSymbolicEqual.generated.js +29 -0
- package/lib/cjs/entry/dependenciesAny.generated.js +32 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesRationalize.generated.js +3 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesResolve.generated.js +32 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesSimplify.generated.js +6 -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 +80 -34
- package/lib/cjs/entry/impureFunctionsNumber.generated.js +96 -64
- package/lib/cjs/entry/pureFunctionsAny.generated.js +62 -64
- 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 +247 -235
- 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/algebra/symbolicEqual.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/subset.js +2 -2
- package/lib/cjs/expression/node/FunctionNode.js +80 -61
- 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 +24 -41
- package/lib/cjs/function/algebra/resolve.js +106 -0
- package/lib/cjs/function/algebra/simplify/simplifyConstant.js +5 -5
- package/lib/cjs/function/algebra/simplify/util.js +171 -33
- package/lib/cjs/function/algebra/simplify.js +588 -211
- package/lib/cjs/function/algebra/{simplify/simplifyCore.js → simplifyCore.js} +67 -43
- package/lib/cjs/function/algebra/solver/lsolveAll.js +2 -2
- package/lib/cjs/function/algebra/solver/usolveAll.js +2 -2
- package/lib/cjs/function/algebra/symbolicEqual.js +88 -0
- 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 +1 -1
- 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 +13 -11
- package/lib/cjs/function/matrix/map.js +53 -15
- package/lib/cjs/function/matrix/matrixFromColumns.js +1 -1
- package/lib/cjs/function/matrix/matrixFromRows.js +1 -1
- package/lib/cjs/function/matrix/subset.js +15 -5
- package/lib/cjs/function/probability/util/seededRNG.js +2 -2
- package/lib/cjs/function/relational/compareNatural.js +6 -6
- package/lib/cjs/header.js +2 -2
- 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/dependenciesLeafCount.generated.js +12 -0
- package/lib/esm/entry/dependenciesAny/dependenciesRationalize.generated.js +2 -0
- package/lib/esm/entry/dependenciesAny/dependenciesResolve.generated.js +18 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSimplify.generated.js +4 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSimplifyCore.generated.js +40 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSymbolicEqual.generated.js +16 -0
- package/lib/esm/entry/dependenciesAny.generated.js +4 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesRationalize.generated.js +2 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesResolve.generated.js +18 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesSimplify.generated.js +4 -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 +69 -27
- package/lib/esm/entry/impureFunctionsNumber.generated.js +83 -53
- package/lib/esm/entry/pureFunctionsAny.generated.js +49 -49
- 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 +220 -212
- 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/algebra/symbolicEqual.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/subset.js +2 -2
- package/lib/esm/expression/node/FunctionNode.js +70 -53
- 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 +24 -40
- package/lib/esm/function/algebra/resolve.js +95 -0
- package/lib/esm/function/algebra/simplify/simplifyConstant.js +3 -3
- package/lib/esm/function/algebra/simplify/util.js +170 -34
- package/lib/esm/function/algebra/simplify.js +583 -206
- package/lib/esm/function/algebra/{simplify/simplifyCore.js → simplifyCore.js} +60 -44
- package/lib/esm/function/algebra/symbolicEqual.js +80 -0
- package/lib/esm/function/matrix/eigs/complexEigs.js +8 -6
- package/lib/esm/function/matrix/map.js +53 -15
- package/lib/esm/function/matrix/subset.js +15 -5
- package/lib/esm/plain/number/combinations.js +18 -6
- package/lib/esm/version.js +1 -1
- package/package.json +20 -15
- package/types/index.d.ts +52 -10
- 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', 'matrix', 'AccessorNode', 'ArrayNode', 'ConstantNode', 'FunctionNode', 'IndexNode', 'ObjectNode', '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,6 +18,8 @@ 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,
|
|
@@ -50,36 +50,18 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
50
50
|
OperatorNode,
|
|
51
51
|
SymbolNode
|
|
52
52
|
});
|
|
53
|
-
var simplifyCore = createSimplifyCore({
|
|
54
|
-
equal,
|
|
55
|
-
isZero,
|
|
56
|
-
add,
|
|
57
|
-
subtract,
|
|
58
|
-
multiply,
|
|
59
|
-
divide,
|
|
60
|
-
pow,
|
|
61
|
-
AccessorNode,
|
|
62
|
-
ArrayNode,
|
|
63
|
-
ConstantNode,
|
|
64
|
-
FunctionNode,
|
|
65
|
-
IndexNode,
|
|
66
|
-
ObjectNode,
|
|
67
|
-
OperatorNode,
|
|
68
|
-
ParenthesisNode
|
|
69
|
-
});
|
|
70
|
-
var resolve = createResolve({
|
|
71
|
-
parse,
|
|
72
|
-
FunctionNode,
|
|
73
|
-
OperatorNode,
|
|
74
|
-
ParenthesisNode
|
|
75
|
-
});
|
|
76
53
|
var {
|
|
54
|
+
hasProperty,
|
|
77
55
|
isCommutative,
|
|
78
56
|
isAssociative,
|
|
57
|
+
mergeContext,
|
|
79
58
|
flatten,
|
|
80
59
|
unflattenr,
|
|
81
60
|
unflattenl,
|
|
82
|
-
createMakeNodeFunction
|
|
61
|
+
createMakeNodeFunction,
|
|
62
|
+
defaultContext,
|
|
63
|
+
realContext,
|
|
64
|
+
positiveContext
|
|
83
65
|
} = createUtil({
|
|
84
66
|
FunctionNode,
|
|
85
67
|
OperatorNode,
|
|
@@ -115,17 +97,49 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
115
97
|
* The default list of rules is exposed on the function as `simplify.rules`
|
|
116
98
|
* and can be used as a basis to built a set of custom rules.
|
|
117
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
|
+
*
|
|
118
113
|
* For more details on the theory, see:
|
|
119
114
|
*
|
|
120
115
|
* - [Strategies for simplifying math expressions (Stackoverflow)](https://stackoverflow.com/questions/7540227/strategies-for-simplifying-math-expressions)
|
|
121
116
|
* - [Symbolic computation - Simplification (Wikipedia)](https://en.wikipedia.org/wiki/Symbolic_computation#Simplification)
|
|
122
117
|
*
|
|
123
118
|
* An optional `options` argument can be passed as last argument of `simplify`.
|
|
124
|
-
*
|
|
125
|
-
* - `
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
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`.
|
|
129
143
|
*
|
|
130
144
|
* Syntax:
|
|
131
145
|
*
|
|
@@ -148,7 +162,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
148
162
|
*
|
|
149
163
|
* See also:
|
|
150
164
|
*
|
|
151
|
-
* derivative, parse,
|
|
165
|
+
* simplifyCore, derivative, evaluate, parse, rationalize, resolve
|
|
152
166
|
*
|
|
153
167
|
* @param {Node | string} expr
|
|
154
168
|
* The expression to be simplified
|
|
@@ -195,7 +209,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
195
209
|
return this(expr, rules, createMap(scope), options);
|
|
196
210
|
},
|
|
197
211
|
'Node, Array, Map, Object': function NodeArrayMapObject(expr, rules, scope, options) {
|
|
198
|
-
|
|
212
|
+
var debug = options.consoleDebug;
|
|
213
|
+
rules = _buildRules(rules, options.context);
|
|
199
214
|
var res = resolve(expr, scope);
|
|
200
215
|
res = removeParens(res);
|
|
201
216
|
var visited = {};
|
|
@@ -207,15 +222,40 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
207
222
|
visited[str] = true;
|
|
208
223
|
_lastsym = 0; // counter for placeholder symbols
|
|
209
224
|
|
|
225
|
+
var laststr = str;
|
|
226
|
+
if (debug) console.log('Working on: ', str);
|
|
227
|
+
|
|
210
228
|
for (var i = 0; i < rules.length; i++) {
|
|
229
|
+
var rulestr = '';
|
|
230
|
+
|
|
211
231
|
if (typeof rules[i] === 'function') {
|
|
212
232
|
res = rules[i](res, options);
|
|
233
|
+
if (debug) rulestr = rules[i].name;
|
|
213
234
|
} else {
|
|
214
|
-
flatten(res);
|
|
215
|
-
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
|
+
}
|
|
216
252
|
}
|
|
253
|
+
/* Use left-heavy binary tree internally,
|
|
254
|
+
* since custom rule functions may expect it
|
|
255
|
+
*/
|
|
256
|
+
|
|
217
257
|
|
|
218
|
-
unflattenl(res);
|
|
258
|
+
unflattenl(res, options.context);
|
|
219
259
|
}
|
|
220
260
|
|
|
221
261
|
str = res.toString({
|
|
@@ -226,8 +266,9 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
226
266
|
return res;
|
|
227
267
|
}
|
|
228
268
|
});
|
|
229
|
-
simplify.
|
|
230
|
-
simplify.
|
|
269
|
+
simplify.defaultContext = defaultContext;
|
|
270
|
+
simplify.realContext = realContext;
|
|
271
|
+
simplify.positiveContext = positiveContext;
|
|
231
272
|
|
|
232
273
|
function removeParens(node) {
|
|
233
274
|
return node.transform(function (node, path, parent) {
|
|
@@ -279,52 +320,155 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
279
320
|
// Note initially we tend constants to the right because like-term
|
|
280
321
|
// collection prefers the left, and we would rather collect nonconstants
|
|
281
322
|
{
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
{
|
|
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: 'n-n -> 0',
|
|
332
|
+
// partial alternative when we can't always subtract
|
|
333
|
+
assuming: {
|
|
334
|
+
subtract: {
|
|
335
|
+
total: false
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}, {
|
|
339
|
+
s: '-(c*v) -> v * (-c)',
|
|
340
|
+
// make non-constant terms positive
|
|
341
|
+
assuming: {
|
|
342
|
+
multiply: {
|
|
343
|
+
commutative: true
|
|
344
|
+
},
|
|
345
|
+
subtract: {
|
|
346
|
+
total: true
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}, {
|
|
350
|
+
s: '-(c*v) -> (-c) * v',
|
|
351
|
+
// non-commutative version, part 1
|
|
352
|
+
assuming: {
|
|
353
|
+
multiply: {
|
|
354
|
+
commutative: false
|
|
355
|
+
},
|
|
356
|
+
subtract: {
|
|
357
|
+
total: true
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}, {
|
|
361
|
+
s: '-(v*c) -> v * (-c)',
|
|
362
|
+
// non-commutative version, part 2
|
|
363
|
+
assuming: {
|
|
364
|
+
multiply: {
|
|
365
|
+
commutative: false
|
|
366
|
+
},
|
|
367
|
+
subtract: {
|
|
368
|
+
total: true
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}, {
|
|
372
|
+
l: '-(n1/n2)',
|
|
373
|
+
r: '-n1/n2'
|
|
374
|
+
}, {
|
|
290
375
|
l: '-v',
|
|
291
376
|
r: 'v * (-1)'
|
|
292
|
-
},
|
|
377
|
+
}, // finish making non-constant terms positive
|
|
378
|
+
{
|
|
379
|
+
l: '(n1 + n2)*(-1)',
|
|
380
|
+
r: 'n1*(-1) + n2*(-1)',
|
|
381
|
+
repeat: true
|
|
382
|
+
}, // expand negations to achieve as much sign cancellation as possible
|
|
383
|
+
{
|
|
293
384
|
l: 'n/n1^n2',
|
|
294
385
|
r: 'n*n1^-n2'
|
|
295
386
|
}, // temporarily replace 'divide' so we can further flatten the 'multiply' operator
|
|
296
387
|
{
|
|
297
388
|
l: 'n/n1',
|
|
298
389
|
r: 'n*n1^-1'
|
|
299
|
-
}, // remove parenthesis in the case of negating a quantity
|
|
300
|
-
{
|
|
301
|
-
l: 'n1 + (n2 + n3)*(-1)',
|
|
302
|
-
r: 'n1 + n2*(-1) + n3*(-1)'
|
|
303
|
-
}, // subsume resulting -1 into constants where possible
|
|
304
|
-
{
|
|
305
|
-
l: '(-1) * c',
|
|
306
|
-
r: '-c'
|
|
307
390
|
}, {
|
|
308
|
-
|
|
309
|
-
|
|
391
|
+
s: '(n1*n2)^n3 -> n1^n3 * n2^n3',
|
|
392
|
+
assuming: {
|
|
393
|
+
multiply: {
|
|
394
|
+
commutative: true
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}, {
|
|
398
|
+
s: '(n1*n2)^(-1) -> n2^(-1) * n1^(-1)',
|
|
399
|
+
assuming: {
|
|
400
|
+
multiply: {
|
|
401
|
+
commutative: false
|
|
402
|
+
}
|
|
403
|
+
}
|
|
310
404
|
}, // expand nested exponentiation
|
|
311
405
|
{
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
406
|
+
s: '(n ^ n1) ^ n2 -> n ^ (n1 * n2)',
|
|
407
|
+
assuming: {
|
|
408
|
+
divide: {
|
|
409
|
+
total: true
|
|
410
|
+
}
|
|
411
|
+
} // 1/(1/n) = n needs 1/n to exist
|
|
412
|
+
|
|
413
|
+
}, // collect like factors; into a sum, only do this for nonconstants
|
|
315
414
|
{
|
|
415
|
+
l: ' v * ( v * n1 + n2)',
|
|
416
|
+
r: 'v^2 * n1 + v * n2'
|
|
417
|
+
}, {
|
|
418
|
+
s: ' v * (v^n4 * n1 + n2) -> v^(1+n4) * n1 + v * n2',
|
|
419
|
+
assuming: {
|
|
420
|
+
divide: {
|
|
421
|
+
total: true
|
|
422
|
+
}
|
|
423
|
+
} // v*1/v = v^(1+-1) needs 1/v
|
|
424
|
+
|
|
425
|
+
}, {
|
|
426
|
+
s: 'v^n3 * ( v * n1 + n2) -> v^(n3+1) * n1 + v^n3 * n2',
|
|
427
|
+
assuming: {
|
|
428
|
+
divide: {
|
|
429
|
+
total: true
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}, {
|
|
433
|
+
s: 'v^n3 * (v^n4 * n1 + n2) -> v^(n3+n4) * n1 + v^n3 * n2',
|
|
434
|
+
assuming: {
|
|
435
|
+
divide: {
|
|
436
|
+
total: true
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}, {
|
|
316
440
|
l: 'n*n',
|
|
317
441
|
r: 'n^2'
|
|
318
442
|
}, {
|
|
319
|
-
|
|
320
|
-
|
|
443
|
+
s: 'n * n^n1 -> n^(n1+1)',
|
|
444
|
+
assuming: {
|
|
445
|
+
divide: {
|
|
446
|
+
total: true
|
|
447
|
+
}
|
|
448
|
+
} // n*1/n = n^(-1+1) needs 1/n
|
|
449
|
+
|
|
321
450
|
}, {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
451
|
+
s: 'n^n1 * n^n2 -> n^(n1+n2)',
|
|
452
|
+
assuming: {
|
|
453
|
+
divide: {
|
|
454
|
+
total: true
|
|
455
|
+
}
|
|
456
|
+
} // ditto for n^2*1/n^2
|
|
457
|
+
|
|
458
|
+
}, // Unfortunately, to deal with more complicated cancellations, it
|
|
459
|
+
// becomes necessary to simplify constants twice per pass. It's not
|
|
460
|
+
// terribly expensive compared to matching rules, so this should not
|
|
461
|
+
// pose a performance problem.
|
|
462
|
+
simplifyConstant, // First: before collecting like terms
|
|
463
|
+
// collect like terms
|
|
325
464
|
{
|
|
326
|
-
|
|
327
|
-
|
|
465
|
+
s: 'n+n -> 2*n',
|
|
466
|
+
assuming: {
|
|
467
|
+
add: {
|
|
468
|
+
total: true
|
|
469
|
+
}
|
|
470
|
+
} // 2 = 1 + 1 needs to exist
|
|
471
|
+
|
|
328
472
|
}, {
|
|
329
473
|
l: 'n+-n',
|
|
330
474
|
r: '0'
|
|
@@ -337,25 +481,91 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
337
481
|
r: 'n3*(n1+n2)'
|
|
338
482
|
}, // All sub-monomials tried there.
|
|
339
483
|
{
|
|
484
|
+
l: 'n3^(-n4)*n1 + n3 * n2',
|
|
485
|
+
r: 'n3^(-n4)*(n1 + n3^(n4+1) *n2)'
|
|
486
|
+
}, {
|
|
487
|
+
l: 'n3^(-n4)*n1 + n3^n5 * n2',
|
|
488
|
+
r: 'n3^(-n4)*(n1 + n3^(n4+n5)*n2)'
|
|
489
|
+
}, {
|
|
490
|
+
s: 'n*v + v -> (n+1)*v',
|
|
491
|
+
// noncommutative additional cases
|
|
492
|
+
assuming: {
|
|
493
|
+
multiply: {
|
|
494
|
+
commutative: false
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}, {
|
|
498
|
+
s: 'n1*n3 + n2*n3 -> (n1+n2)*n3',
|
|
499
|
+
assuming: {
|
|
500
|
+
multiply: {
|
|
501
|
+
commutative: false
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}, {
|
|
505
|
+
s: 'n1*n3^(-n4) + n2 * n3 -> (n1 + n2*n3^(n4 + 1))*n3^(-n4)',
|
|
506
|
+
assuming: {
|
|
507
|
+
multiply: {
|
|
508
|
+
commutative: false
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}, {
|
|
512
|
+
s: 'n1*n3^(-n4) + n2 * n3^n5 -> (n1 + n2*n3^(n4 + n5))*n3^(-n4)',
|
|
513
|
+
assuming: {
|
|
514
|
+
multiply: {
|
|
515
|
+
commutative: false
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}, {
|
|
340
519
|
l: 'n*c + c',
|
|
341
520
|
r: '(n+1)*c'
|
|
342
|
-
},
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
521
|
+
}, {
|
|
522
|
+
s: 'c*n + c -> c*(n+1)',
|
|
523
|
+
assuming: {
|
|
524
|
+
multiply: {
|
|
525
|
+
commutative: false
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}, simplifyConstant, // Second: before returning expressions to "standard form"
|
|
529
|
+
// make factors positive (and undo 'make non-constant terms positive')
|
|
530
|
+
{
|
|
531
|
+
s: '(-n)*n1 -> -(n*n1)',
|
|
532
|
+
assuming: {
|
|
533
|
+
subtract: {
|
|
534
|
+
total: true
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}, {
|
|
538
|
+
s: 'n1*(-n) -> -(n1*n)',
|
|
539
|
+
// in case * non-commutative
|
|
540
|
+
assuming: {
|
|
541
|
+
subtract: {
|
|
542
|
+
total: true
|
|
543
|
+
},
|
|
544
|
+
multiply: {
|
|
545
|
+
commutative: false
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}, // final ordering of constants
|
|
347
549
|
{
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
550
|
+
s: 'c+v -> v+c',
|
|
551
|
+
assuming: {
|
|
552
|
+
add: {
|
|
553
|
+
commutative: true
|
|
554
|
+
}
|
|
555
|
+
},
|
|
556
|
+
imposeContext: {
|
|
351
557
|
add: {
|
|
352
558
|
commutative: false
|
|
353
559
|
}
|
|
354
560
|
}
|
|
355
561
|
}, {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
562
|
+
s: 'v*c -> c*v',
|
|
563
|
+
assuming: {
|
|
564
|
+
multiply: {
|
|
565
|
+
commutative: true
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
imposeContext: {
|
|
359
569
|
multiply: {
|
|
360
570
|
commutative: false
|
|
361
571
|
}
|
|
@@ -367,36 +577,125 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
367
577
|
r: 'n-n1'
|
|
368
578
|
}, // undo replace 'subtract'
|
|
369
579
|
{
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
580
|
+
s: 'n*(n1^-1) -> n/n1',
|
|
581
|
+
// undo replace 'divide'; for * commutative
|
|
582
|
+
assuming: {
|
|
583
|
+
multiply: {
|
|
584
|
+
commutative: true
|
|
585
|
+
}
|
|
586
|
+
} // o.w. / not conventional
|
|
587
|
+
|
|
376
588
|
}, {
|
|
377
|
-
|
|
378
|
-
|
|
589
|
+
s: 'n*n1^-n2 -> n/n1^n2',
|
|
590
|
+
assuming: {
|
|
591
|
+
multiply: {
|
|
592
|
+
commutative: true
|
|
593
|
+
}
|
|
594
|
+
} // o.w. / not conventional
|
|
595
|
+
|
|
379
596
|
}, {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
597
|
+
s: 'n^-1 -> 1/n',
|
|
598
|
+
assuming: {
|
|
599
|
+
multiply: {
|
|
600
|
+
commutative: true
|
|
601
|
+
}
|
|
602
|
+
} // o.w. / not conventional
|
|
603
|
+
|
|
604
|
+
}, {
|
|
605
|
+
l: 'n^1',
|
|
606
|
+
r: 'n'
|
|
607
|
+
}, // can be produced by power cancellation
|
|
383
608
|
{
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
609
|
+
s: 'n*(n1/n2) -> (n*n1)/n2',
|
|
610
|
+
// '*' before '/'
|
|
611
|
+
assuming: {
|
|
612
|
+
multiply: {
|
|
613
|
+
associative: true
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}, {
|
|
617
|
+
s: 'n-(n1+n2) -> n-n1-n2',
|
|
618
|
+
// '-' before '+'
|
|
619
|
+
assuming: {
|
|
620
|
+
addition: {
|
|
621
|
+
associative: true,
|
|
622
|
+
commutative: true
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}, // { l: '(n1/n2)/n3', r: 'n1/(n2*n3)' },
|
|
388
626
|
// { l: '(n*n1)/(n*n2)', r: 'n1/n2' },
|
|
627
|
+
// simplifyConstant can leave an extra factor of 1, which can always
|
|
628
|
+
// be eliminated, since the identity always commutes
|
|
389
629
|
{
|
|
390
630
|
l: '1*n',
|
|
391
|
-
r: 'n'
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
631
|
+
r: 'n',
|
|
632
|
+
imposeContext: {
|
|
633
|
+
multiply: {
|
|
634
|
+
commutative: true
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}, {
|
|
638
|
+
s: 'n1/(n2/n3) -> (n1*n3)/n2',
|
|
639
|
+
assuming: {
|
|
640
|
+
multiply: {
|
|
641
|
+
associative: true
|
|
642
|
+
}
|
|
643
|
+
}
|
|
396
644
|
}, {
|
|
397
645
|
l: 'n1/(-n2)',
|
|
398
646
|
r: '-n1/n2'
|
|
399
647
|
}];
|
|
648
|
+
/**
|
|
649
|
+
* Takes any rule object as allowed by the specification in simplify
|
|
650
|
+
* and puts it in a standard form used by applyRule
|
|
651
|
+
*/
|
|
652
|
+
|
|
653
|
+
function _canonicalizeRule(ruleObject, context) {
|
|
654
|
+
var newRule = {};
|
|
655
|
+
|
|
656
|
+
if (ruleObject.s) {
|
|
657
|
+
var lr = ruleObject.s.split('->');
|
|
658
|
+
|
|
659
|
+
if (lr.length === 2) {
|
|
660
|
+
newRule.l = lr[0];
|
|
661
|
+
newRule.r = lr[1];
|
|
662
|
+
} else {
|
|
663
|
+
throw SyntaxError('Could not parse rule: ' + ruleObject.s);
|
|
664
|
+
}
|
|
665
|
+
} else {
|
|
666
|
+
newRule.l = ruleObject.l;
|
|
667
|
+
newRule.r = ruleObject.r;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
newRule.l = removeParens(parse(newRule.l));
|
|
671
|
+
newRule.r = removeParens(parse(newRule.r));
|
|
672
|
+
|
|
673
|
+
for (var prop of ['imposeContext', 'repeat', 'assuming']) {
|
|
674
|
+
if (prop in ruleObject) {
|
|
675
|
+
newRule[prop] = ruleObject[prop];
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (ruleObject.evaluate) {
|
|
680
|
+
newRule.evaluate = parse(ruleObject.evaluate);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (isAssociative(newRule.l, context)) {
|
|
684
|
+
var makeNode = createMakeNodeFunction(newRule.l);
|
|
685
|
+
|
|
686
|
+
var expandsym = _getExpandPlaceholderSymbol();
|
|
687
|
+
|
|
688
|
+
newRule.expanded = {};
|
|
689
|
+
newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]); // Push the expandsym into the deepest possible branch.
|
|
690
|
+
// This helps to match the newRule against nodes returned from getSplits() later on.
|
|
691
|
+
|
|
692
|
+
flatten(newRule.expanded.l, context);
|
|
693
|
+
unflattenr(newRule.expanded.l, context);
|
|
694
|
+
newRule.expanded.r = makeNode([newRule.r, expandsym]);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
return newRule;
|
|
698
|
+
}
|
|
400
699
|
/**
|
|
401
700
|
* Parse the string array of rules into nodes
|
|
402
701
|
*
|
|
@@ -414,7 +713,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
414
713
|
* 'n1 * c1 -> c1 * n1'
|
|
415
714
|
*/
|
|
416
715
|
|
|
417
|
-
|
|
716
|
+
|
|
717
|
+
function _buildRules(rules, context) {
|
|
418
718
|
// Array of rules to be used to simplify expressions
|
|
419
719
|
var ruleSet = [];
|
|
420
720
|
|
|
@@ -425,49 +725,14 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
425
725
|
|
|
426
726
|
switch (ruleType) {
|
|
427
727
|
case 'string':
|
|
428
|
-
{
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if (lr.length === 2) {
|
|
432
|
-
rule = {
|
|
433
|
-
l: lr[0],
|
|
434
|
-
r: lr[1]
|
|
435
|
-
};
|
|
436
|
-
} else {
|
|
437
|
-
throw SyntaxError('Could not parse rule: ' + rule);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
728
|
+
rule = {
|
|
729
|
+
s: rule
|
|
730
|
+
};
|
|
440
731
|
|
|
441
732
|
/* falls through */
|
|
442
733
|
|
|
443
734
|
case 'object':
|
|
444
|
-
newRule =
|
|
445
|
-
l: removeParens(parse(rule.l)),
|
|
446
|
-
r: removeParens(parse(rule.r))
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
if (rule.context) {
|
|
450
|
-
newRule.context = rule.context;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
if (rule.evaluate) {
|
|
454
|
-
newRule.evaluate = parse(rule.evaluate);
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
if (isAssociative(newRule.l)) {
|
|
458
|
-
var makeNode = createMakeNodeFunction(newRule.l);
|
|
459
|
-
|
|
460
|
-
var expandsym = _getExpandPlaceholderSymbol();
|
|
461
|
-
|
|
462
|
-
newRule.expanded = {};
|
|
463
|
-
newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]); // Push the expandsym into the deepest possible branch.
|
|
464
|
-
// This helps to match the newRule against nodes returned from getSplits() later on.
|
|
465
|
-
|
|
466
|
-
flatten(newRule.expanded.l);
|
|
467
|
-
unflattenr(newRule.expanded.l);
|
|
468
|
-
newRule.expanded.r = makeNode([newRule.r, expandsym]);
|
|
469
|
-
}
|
|
470
|
-
|
|
735
|
+
newRule = _canonicalizeRule(rule, context);
|
|
471
736
|
break;
|
|
472
737
|
|
|
473
738
|
case 'function':
|
|
@@ -492,90 +757,155 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
492
757
|
return new SymbolNode('_p' + _lastsym++);
|
|
493
758
|
}
|
|
494
759
|
|
|
495
|
-
function mapRule(nodes, rule) {
|
|
760
|
+
function mapRule(nodes, rule, context) {
|
|
761
|
+
var resNodes = nodes;
|
|
762
|
+
|
|
496
763
|
if (nodes) {
|
|
497
764
|
for (var i = 0; i < nodes.length; ++i) {
|
|
498
|
-
|
|
765
|
+
var newNode = applyRule(nodes[i], rule, context);
|
|
766
|
+
|
|
767
|
+
if (newNode !== nodes[i]) {
|
|
768
|
+
if (resNodes === nodes) {
|
|
769
|
+
resNodes = nodes.slice();
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
resNodes[i] = newNode;
|
|
773
|
+
}
|
|
499
774
|
}
|
|
500
775
|
}
|
|
776
|
+
|
|
777
|
+
return resNodes;
|
|
501
778
|
}
|
|
502
779
|
/**
|
|
503
780
|
* Returns a simplfied form of node, or the original node if no simplification was possible.
|
|
504
781
|
*
|
|
505
782
|
* @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} node
|
|
783
|
+
* @param {Object | Function} rule
|
|
784
|
+
* @param {Object} context -- information about assumed properties of operators
|
|
506
785
|
* @return {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} The simplified form of `expr`, or the original node if no simplification was possible.
|
|
507
786
|
*/
|
|
508
787
|
|
|
509
788
|
|
|
510
|
-
|
|
511
|
-
'
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
} else if (res instanceof ParenthesisNode) {
|
|
521
|
-
if (res.content) {
|
|
522
|
-
res.content = applyRule(res.content, rule);
|
|
523
|
-
}
|
|
524
|
-
} else if (res instanceof ArrayNode) {
|
|
525
|
-
mapRule(res.items, rule);
|
|
526
|
-
} else if (res instanceof AccessorNode) {
|
|
527
|
-
if (res.object) {
|
|
528
|
-
res.object = applyRule(res.object, rule);
|
|
789
|
+
function applyRule(node, rule, context) {
|
|
790
|
+
// console.log('Entering applyRule("', rule.l.toString({parenthesis:'all'}), '->', rule.r.toString({parenthesis:'all'}), '",', node.toString({parenthesis:'all'}),')')
|
|
791
|
+
// check that the assumptions for this rule are satisfied by the current
|
|
792
|
+
// context:
|
|
793
|
+
if (rule.assuming) {
|
|
794
|
+
for (var symbol in rule.assuming) {
|
|
795
|
+
for (var property in rule.assuming[symbol]) {
|
|
796
|
+
if (hasProperty(symbol, property, context) !== rule.assuming[symbol][property]) {
|
|
797
|
+
return node;
|
|
798
|
+
}
|
|
529
799
|
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
530
802
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
803
|
+
var mergedContext = mergeContext(rule.imposeContext, context); // Do not clone node unless we find a match
|
|
804
|
+
|
|
805
|
+
var res = node; // First replace our child nodes with their simplified versions
|
|
806
|
+
// If a child could not be simplified, applying the rule to it
|
|
807
|
+
// will have no effect since the node is returned unchanged
|
|
808
|
+
|
|
809
|
+
if (res instanceof OperatorNode || res instanceof FunctionNode) {
|
|
810
|
+
var newArgs = mapRule(res.args, rule, context);
|
|
811
|
+
|
|
812
|
+
if (newArgs !== res.args) {
|
|
813
|
+
res = res.clone();
|
|
814
|
+
res.args = newArgs;
|
|
815
|
+
}
|
|
816
|
+
} else if (res instanceof ParenthesisNode) {
|
|
817
|
+
if (res.content) {
|
|
818
|
+
var newContent = applyRule(res.content, rule, context);
|
|
819
|
+
|
|
820
|
+
if (newContent !== res.content) {
|
|
821
|
+
res = new ParenthesisNode(newContent);
|
|
539
822
|
}
|
|
540
|
-
}
|
|
823
|
+
}
|
|
824
|
+
} else if (res instanceof ArrayNode) {
|
|
825
|
+
var newItems = mapRule(res.items, rule, context);
|
|
541
826
|
|
|
827
|
+
if (newItems !== res.items) {
|
|
828
|
+
res = new ArrayNode(newItems);
|
|
829
|
+
}
|
|
830
|
+
} else if (res instanceof AccessorNode) {
|
|
831
|
+
var newObj = res.object;
|
|
542
832
|
|
|
543
|
-
|
|
833
|
+
if (res.object) {
|
|
834
|
+
newObj = applyRule(res.object, rule, context);
|
|
835
|
+
}
|
|
544
836
|
|
|
545
|
-
var
|
|
546
|
-
// 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.
|
|
837
|
+
var newIndex = res.index;
|
|
547
838
|
|
|
839
|
+
if (res.index) {
|
|
840
|
+
newIndex = applyRule(res.index, rule, context);
|
|
841
|
+
}
|
|
548
842
|
|
|
549
|
-
if (
|
|
550
|
-
|
|
551
|
-
matches = _ruleMatch(rule.expanded.l, res)[0];
|
|
843
|
+
if (newObj !== res.object || newIndex !== res.index) {
|
|
844
|
+
res = new AccessorNode(newObj, newIndex);
|
|
552
845
|
}
|
|
846
|
+
} else if (res instanceof IndexNode) {
|
|
847
|
+
var newDims = mapRule(res.dimensions, rule, context);
|
|
553
848
|
|
|
554
|
-
if (
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
849
|
+
if (newDims !== res.dimensions) {
|
|
850
|
+
res = new IndexNode(newDims);
|
|
851
|
+
}
|
|
852
|
+
} else if (res instanceof ObjectNode) {
|
|
853
|
+
var changed = false;
|
|
854
|
+
var newProps = {};
|
|
560
855
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
} // Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
|
|
856
|
+
for (var prop in res.properties) {
|
|
857
|
+
newProps[prop] = applyRule(res.properties[prop], rule, context);
|
|
564
858
|
|
|
859
|
+
if (newProps[prop] !== res.properties[prop]) {
|
|
860
|
+
changed = true;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
565
863
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
return matches.placeholders[node.name].clone();
|
|
569
|
-
} else {
|
|
570
|
-
return node;
|
|
571
|
-
}
|
|
572
|
-
}); // const after = res.toString({parenthesis: 'all'})
|
|
573
|
-
// console.log('Simplified ' + before + ' to ' + after)
|
|
864
|
+
if (changed) {
|
|
865
|
+
res = new ObjectNode(newProps);
|
|
574
866
|
}
|
|
867
|
+
} // Try to match a rule against this node
|
|
575
868
|
|
|
576
|
-
|
|
869
|
+
|
|
870
|
+
var repl = rule.r;
|
|
871
|
+
|
|
872
|
+
var matches = _ruleMatch(rule.l, res, mergedContext)[0]; // If the rule is associative operator, we can try matching it while allowing additional terms.
|
|
873
|
+
// 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.
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
if (!matches && rule.expanded) {
|
|
877
|
+
repl = rule.expanded.r;
|
|
878
|
+
matches = _ruleMatch(rule.expanded.l, res, mergedContext)[0];
|
|
577
879
|
}
|
|
578
|
-
|
|
880
|
+
|
|
881
|
+
if (matches) {
|
|
882
|
+
// const before = res.toString({parenthesis: 'all'})
|
|
883
|
+
// Create a new node by cloning the rhs of the matched rule
|
|
884
|
+
// we keep any implicit multiplication state if relevant
|
|
885
|
+
var implicit = res.implicit;
|
|
886
|
+
res = repl.clone();
|
|
887
|
+
|
|
888
|
+
if (implicit && 'implicit' in repl) {
|
|
889
|
+
res.implicit = true;
|
|
890
|
+
} // Replace placeholders with their respective nodes without traversing deeper into the replaced nodes
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
res = res.transform(function (node) {
|
|
894
|
+
if (node.isSymbolNode && hasOwnProperty(matches.placeholders, node.name)) {
|
|
895
|
+
return matches.placeholders[node.name].clone();
|
|
896
|
+
} else {
|
|
897
|
+
return node;
|
|
898
|
+
}
|
|
899
|
+
}); // const after = res.toString({parenthesis: 'all'})
|
|
900
|
+
// console.log('Simplified ' + before + ' to ' + after)
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
if (rule.repeat && res !== node) {
|
|
904
|
+
res = applyRule(res, rule, context);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
return res;
|
|
908
|
+
}
|
|
579
909
|
/**
|
|
580
910
|
* Get (binary) combinations of a flattened binary node
|
|
581
911
|
* e.g. +(node1, node2, node3) -> [
|
|
@@ -585,6 +915,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
585
915
|
*
|
|
586
916
|
*/
|
|
587
917
|
|
|
918
|
+
|
|
588
919
|
function getSplits(node, context) {
|
|
589
920
|
var res = [];
|
|
590
921
|
var right, rightArgs;
|
|
@@ -598,9 +929,18 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
598
929
|
res.push(makeNode([node.args[i], right]));
|
|
599
930
|
}
|
|
600
931
|
} else {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
932
|
+
// Keep order, but try all parenthesizations
|
|
933
|
+
for (var _i = 1; _i < node.args.length; _i++) {
|
|
934
|
+
var left = node.args[0];
|
|
935
|
+
|
|
936
|
+
if (_i > 1) {
|
|
937
|
+
left = makeNode(node.args.slice(0, _i));
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
rightArgs = node.args.slice(_i);
|
|
941
|
+
right = rightArgs.length === 1 ? rightArgs[0] : makeNode(rightArgs);
|
|
942
|
+
res.push(makeNode([left, right]));
|
|
943
|
+
}
|
|
604
944
|
}
|
|
605
945
|
|
|
606
946
|
return res;
|
|
@@ -703,15 +1043,19 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
703
1043
|
*
|
|
704
1044
|
* @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} rule
|
|
705
1045
|
* @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} node
|
|
1046
|
+
* @param {Object} context -- provides assumed properties of operators
|
|
1047
|
+
* @param {Boolean} isSplit -- whether we are in process of splitting an
|
|
1048
|
+
* n-ary operator node into possible binary combinations.
|
|
1049
|
+
* Defaults to false.
|
|
706
1050
|
* @return {Object} Information about the match, if it exists.
|
|
707
1051
|
*/
|
|
708
1052
|
|
|
709
1053
|
|
|
710
|
-
function _ruleMatch(rule, node, isSplit) {
|
|
1054
|
+
function _ruleMatch(rule, node, context, isSplit) {
|
|
711
1055
|
// console.log('Entering _ruleMatch(' + JSON.stringify(rule) + ', ' + JSON.stringify(node) + ')')
|
|
712
1056
|
// console.log('rule = ' + rule)
|
|
713
1057
|
// console.log('node = ' + node)
|
|
714
|
-
// console.log('Entering _ruleMatch('
|
|
1058
|
+
// console.log('Entering _ruleMatch(', rule.toString({parenthesis:'all'}), ', ', node.toString({parenthesis:'all'}), ', ', context, ')')
|
|
715
1059
|
var res = [{
|
|
716
1060
|
placeholders: {}
|
|
717
1061
|
}];
|
|
@@ -729,32 +1073,65 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
|
729
1073
|
} // rule and node match. Search the children of rule and node.
|
|
730
1074
|
|
|
731
1075
|
|
|
732
|
-
if (node.args.length === 1 && rule.args.length === 1 || !isAssociative(node) && node.args.length === rule.args.length || isSplit) {
|
|
733
|
-
// Expect non-associative operators to match exactly
|
|
1076
|
+
if (node.args.length === 1 && rule.args.length === 1 || !isAssociative(node, context) && node.args.length === rule.args.length || isSplit) {
|
|
1077
|
+
// Expect non-associative operators to match exactly,
|
|
1078
|
+
// except in any order if operator is commutative
|
|
734
1079
|
var childMatches = [];
|
|
735
1080
|
|
|
736
1081
|
for (var i = 0; i < rule.args.length; i++) {
|
|
737
|
-
var childMatch = _ruleMatch(rule.args[i], node.args[i]);
|
|
1082
|
+
var childMatch = _ruleMatch(rule.args[i], node.args[i], context);
|
|
738
1083
|
|
|
739
1084
|
if (childMatch.length === 0) {
|
|
740
1085
|
// Child did not match, so stop searching immediately
|
|
741
|
-
|
|
1086
|
+
break;
|
|
742
1087
|
} // The child matched, so add the information returned from the child to our result
|
|
743
1088
|
|
|
744
1089
|
|
|
745
1090
|
childMatches.push(childMatch);
|
|
746
1091
|
}
|
|
747
1092
|
|
|
1093
|
+
if (childMatches.length !== rule.args.length) {
|
|
1094
|
+
if (!isCommutative(node, context) || // exact match in order needed
|
|
1095
|
+
rule.args.length === 1) {
|
|
1096
|
+
// nothing to commute
|
|
1097
|
+
return [];
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
if (rule.args.length > 2) {
|
|
1101
|
+
/* Need to generate all permutations and try them.
|
|
1102
|
+
* It's a bit complicated, and unlikely to come up since there
|
|
1103
|
+
* are very few ternary or higher operators. So punt for now.
|
|
1104
|
+
*/
|
|
1105
|
+
throw new Error('permuting >2 commutative non-associative rule arguments not yet implemented');
|
|
1106
|
+
}
|
|
1107
|
+
/* Exactly two arguments, try them reversed */
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
var leftMatch = _ruleMatch(rule.args[0], node.args[1], context);
|
|
1111
|
+
|
|
1112
|
+
if (leftMatch.length === 0) {
|
|
1113
|
+
return [];
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
var rightMatch = _ruleMatch(rule.args[1], node.args[0], context);
|
|
1117
|
+
|
|
1118
|
+
if (rightMatch.length === 0) {
|
|
1119
|
+
return [];
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
childMatches = [leftMatch, rightMatch];
|
|
1123
|
+
}
|
|
1124
|
+
|
|
748
1125
|
res = mergeChildMatches(childMatches);
|
|
749
1126
|
} else if (node.args.length >= 2 && rule.args.length === 2) {
|
|
750
1127
|
// node is flattened, rule is not
|
|
751
1128
|
// Associative operators/functions can be split in different ways so we check if the rule matches each
|
|
752
1129
|
// them and return their union.
|
|
753
|
-
var splits = getSplits(node,
|
|
1130
|
+
var splits = getSplits(node, context);
|
|
754
1131
|
var splitMatches = [];
|
|
755
1132
|
|
|
756
|
-
for (var
|
|
757
|
-
var matchSet = _ruleMatch(rule, splits[
|
|
1133
|
+
for (var _i2 = 0; _i2 < splits.length; _i2++) {
|
|
1134
|
+
var matchSet = _ruleMatch(rule, splits[_i2], context, true); // recursing at the same tree depth here
|
|
758
1135
|
|
|
759
1136
|
|
|
760
1137
|
splitMatches = splitMatches.concat(matchSet);
|