251 lines
8.3 KiB
JavaScript
251 lines
8.3 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.createSimplifyCore = void 0;
|
||
|
|
||
|
var _is = require("../../utils/is.js");
|
||
|
|
||
|
var _util = require("./simplify/util.js");
|
||
|
|
||
|
var _factory = require("../../utils/factory.js");
|
||
|
|
||
|
var name = 'simplifyCore';
|
||
|
var dependencies = ['equal', 'isZero', 'add', 'subtract', 'multiply', 'divide', 'pow', 'AccessorNode', 'ArrayNode', 'ConstantNode', 'FunctionNode', 'IndexNode', 'ObjectNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
|
||
|
var createSimplifyCore = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
|
||
|
var equal = _ref.equal,
|
||
|
isZero = _ref.isZero,
|
||
|
add = _ref.add,
|
||
|
subtract = _ref.subtract,
|
||
|
multiply = _ref.multiply,
|
||
|
divide = _ref.divide,
|
||
|
pow = _ref.pow,
|
||
|
AccessorNode = _ref.AccessorNode,
|
||
|
ArrayNode = _ref.ArrayNode,
|
||
|
ConstantNode = _ref.ConstantNode,
|
||
|
FunctionNode = _ref.FunctionNode,
|
||
|
IndexNode = _ref.IndexNode,
|
||
|
ObjectNode = _ref.ObjectNode,
|
||
|
OperatorNode = _ref.OperatorNode,
|
||
|
ParenthesisNode = _ref.ParenthesisNode,
|
||
|
SymbolNode = _ref.SymbolNode;
|
||
|
var node0 = new ConstantNode(0);
|
||
|
var node1 = new ConstantNode(1);
|
||
|
|
||
|
var _createUtil = (0, _util.createUtil)({
|
||
|
FunctionNode: FunctionNode,
|
||
|
OperatorNode: OperatorNode,
|
||
|
SymbolNode: SymbolNode
|
||
|
}),
|
||
|
hasProperty = _createUtil.hasProperty,
|
||
|
isCommutative = _createUtil.isCommutative;
|
||
|
/**
|
||
|
* simplifyCore() performs single pass simplification suitable for
|
||
|
* applications requiring ultimate performance. In contrast, simplify()
|
||
|
* extends simplifyCore() with additional passes to provide deeper
|
||
|
* simplification.
|
||
|
*
|
||
|
* Syntax:
|
||
|
*
|
||
|
* simplifyCore(expr)
|
||
|
*
|
||
|
* Examples:
|
||
|
*
|
||
|
* const f = math.parse('2 * 1 * x ^ (2 - 1)')
|
||
|
* math.simpifyCore(f) // Node {2 * x}
|
||
|
* math.simplify('2 * 1 * x ^ (2 - 1)', [math.simplifyCore]) // Node {2 * x}
|
||
|
*
|
||
|
* See also:
|
||
|
*
|
||
|
* simplify, resolve, derivative
|
||
|
*
|
||
|
* @param {Node} node
|
||
|
* The expression to be simplified
|
||
|
* @param {Object} options
|
||
|
* Simplification options, as per simplify()
|
||
|
* @return {Node} Returns expression with basic simplifications applied
|
||
|
*/
|
||
|
|
||
|
|
||
|
function simplifyCore(node, options) {
|
||
|
var context = options ? options.context : undefined;
|
||
|
|
||
|
if (hasProperty(node, 'trivial', context)) {
|
||
|
// This node does nothing if it has only one argument, so if so,
|
||
|
// return that argument simplified
|
||
|
if ((0, _is.isFunctionNode)(node) && node.args.length === 1) {
|
||
|
return simplifyCore(node.args[0], options);
|
||
|
} // For other node types, we try the generic methods
|
||
|
|
||
|
|
||
|
var simpChild = false;
|
||
|
var childCount = 0;
|
||
|
node.forEach(function (c) {
|
||
|
++childCount;
|
||
|
|
||
|
if (childCount === 1) {
|
||
|
simpChild = simplifyCore(c, options);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (childCount === 1) {
|
||
|
return simpChild;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((0, _is.isOperatorNode)(node) && node.isUnary()) {
|
||
|
var a0 = simplifyCore(node.args[0], options);
|
||
|
|
||
|
if (node.op === '-') {
|
||
|
// unary minus
|
||
|
if ((0, _is.isOperatorNode)(a0)) {
|
||
|
if (a0.isUnary() && a0.op === '-') {
|
||
|
return a0.args[0];
|
||
|
} else if (a0.isBinary() && a0.fn === 'subtract') {
|
||
|
return new OperatorNode('-', 'subtract', [a0.args[1], a0.args[0]]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return new OperatorNode(node.op, node.fn, [a0]);
|
||
|
}
|
||
|
} else if ((0, _is.isOperatorNode)(node) && node.isBinary()) {
|
||
|
var _a = simplifyCore(node.args[0], options);
|
||
|
|
||
|
var a1 = simplifyCore(node.args[1], options);
|
||
|
|
||
|
if (node.op === '+') {
|
||
|
if ((0, _is.isConstantNode)(_a)) {
|
||
|
if (isZero(_a.value)) {
|
||
|
return a1;
|
||
|
} else if ((0, _is.isConstantNode)(a1)) {
|
||
|
return new ConstantNode(add(_a.value, a1.value));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((0, _is.isConstantNode)(a1) && isZero(a1.value)) {
|
||
|
return _a;
|
||
|
}
|
||
|
|
||
|
if ((0, _is.isOperatorNode)(a1) && a1.isUnary() && a1.op === '-') {
|
||
|
return new OperatorNode('-', 'subtract', [_a, a1.args[0]]);
|
||
|
}
|
||
|
|
||
|
return new OperatorNode(node.op, node.fn, a1 ? [_a, a1] : [_a]);
|
||
|
} else if (node.op === '-') {
|
||
|
if ((0, _is.isConstantNode)(_a) && a1) {
|
||
|
if ((0, _is.isConstantNode)(a1)) {
|
||
|
return new ConstantNode(subtract(_a.value, a1.value));
|
||
|
} else if (isZero(_a.value)) {
|
||
|
return new OperatorNode('-', 'unaryMinus', [a1]);
|
||
|
}
|
||
|
} // if (node.fn === "subtract" && node.args.length === 2) {
|
||
|
|
||
|
|
||
|
if (node.fn === 'subtract') {
|
||
|
if ((0, _is.isConstantNode)(a1) && isZero(a1.value)) {
|
||
|
return _a;
|
||
|
}
|
||
|
|
||
|
if ((0, _is.isOperatorNode)(a1) && a1.isUnary() && a1.op === '-') {
|
||
|
return simplifyCore(new OperatorNode('+', 'add', [_a, a1.args[0]]), options);
|
||
|
}
|
||
|
|
||
|
return new OperatorNode(node.op, node.fn, [_a, a1]);
|
||
|
}
|
||
|
} else if (node.op === '*') {
|
||
|
if ((0, _is.isConstantNode)(_a)) {
|
||
|
if (isZero(_a.value)) {
|
||
|
return node0;
|
||
|
} else if (equal(_a.value, 1)) {
|
||
|
return a1;
|
||
|
} else if ((0, _is.isConstantNode)(a1)) {
|
||
|
return new ConstantNode(multiply(_a.value, a1.value));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((0, _is.isConstantNode)(a1)) {
|
||
|
if (isZero(a1.value)) {
|
||
|
return node0;
|
||
|
} else if (equal(a1.value, 1)) {
|
||
|
return _a;
|
||
|
} else if ((0, _is.isOperatorNode)(_a) && _a.isBinary() && _a.op === node.op && isCommutative(node, context)) {
|
||
|
var a00 = _a.args[0];
|
||
|
|
||
|
if ((0, _is.isConstantNode)(a00)) {
|
||
|
var a00a1 = new ConstantNode(multiply(a00.value, a1.value));
|
||
|
return new OperatorNode(node.op, node.fn, [a00a1, _a.args[1]], node.implicit); // constants on left
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isCommutative(node, context)) {
|
||
|
return new OperatorNode(node.op, node.fn, [a1, _a], node.implicit); // constants on left
|
||
|
} else {
|
||
|
return new OperatorNode(node.op, node.fn, [_a, a1], node.implicit);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return new OperatorNode(node.op, node.fn, [_a, a1], node.implicit);
|
||
|
} else if (node.op === '/') {
|
||
|
if ((0, _is.isConstantNode)(_a)) {
|
||
|
if (isZero(_a.value)) {
|
||
|
return node0;
|
||
|
} else if ((0, _is.isConstantNode)(a1) && (equal(a1.value, 1) || equal(a1.value, 2) || equal(a1.value, 4))) {
|
||
|
return new ConstantNode(divide(_a.value, a1.value));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return new OperatorNode(node.op, node.fn, [_a, a1]);
|
||
|
} else if (node.op === '^') {
|
||
|
if ((0, _is.isConstantNode)(a1)) {
|
||
|
if (isZero(a1.value)) {
|
||
|
return node1;
|
||
|
} else if (equal(a1.value, 1)) {
|
||
|
return _a;
|
||
|
} else {
|
||
|
if ((0, _is.isConstantNode)(_a)) {
|
||
|
// fold constant
|
||
|
return new ConstantNode(pow(_a.value, a1.value));
|
||
|
} else if ((0, _is.isOperatorNode)(_a) && _a.isBinary() && _a.op === '^') {
|
||
|
var a01 = _a.args[1];
|
||
|
|
||
|
if ((0, _is.isConstantNode)(a01)) {
|
||
|
return new OperatorNode(node.op, node.fn, [_a.args[0], new ConstantNode(multiply(a01.value, a1.value))]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return new OperatorNode(node.op, node.fn, [_a, a1]);
|
||
|
} else if ((0, _is.isFunctionNode)(node)) {
|
||
|
return new FunctionNode(simplifyCore(node.fn), node.args.map(function (n) {
|
||
|
return simplifyCore(n, options);
|
||
|
}));
|
||
|
} else if ((0, _is.isArrayNode)(node)) {
|
||
|
return new ArrayNode(node.items.map(function (n) {
|
||
|
return simplifyCore(n, options);
|
||
|
}));
|
||
|
} else if ((0, _is.isAccessorNode)(node)) {
|
||
|
return new AccessorNode(simplifyCore(node.object, options), simplifyCore(node.index, options));
|
||
|
} else if ((0, _is.isIndexNode)(node)) {
|
||
|
return new IndexNode(node.dimensions.map(function (n) {
|
||
|
return simplifyCore(n, options);
|
||
|
}));
|
||
|
} else if ((0, _is.isObjectNode)(node)) {
|
||
|
var newProps = {};
|
||
|
|
||
|
for (var prop in node.properties) {
|
||
|
newProps[prop] = simplifyCore(node.properties[prop], options);
|
||
|
}
|
||
|
|
||
|
return new ObjectNode(newProps);
|
||
|
} else {// cannot simplify
|
||
|
}
|
||
|
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
return simplifyCore;
|
||
|
});
|
||
|
exports.createSimplifyCore = createSimplifyCore;
|