simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

simplifyCore.js (8533B)


      1 "use strict";
      2 
      3 Object.defineProperty(exports, "__esModule", {
      4   value: true
      5 });
      6 exports.createSimplifyCore = void 0;
      7 
      8 var _is = require("../../utils/is.js");
      9 
     10 var _util = require("./simplify/util.js");
     11 
     12 var _factory = require("../../utils/factory.js");
     13 
     14 var name = 'simplifyCore';
     15 var dependencies = ['equal', 'isZero', 'add', 'subtract', 'multiply', 'divide', 'pow', 'AccessorNode', 'ArrayNode', 'ConstantNode', 'FunctionNode', 'IndexNode', 'ObjectNode', 'OperatorNode', 'ParenthesisNode', 'SymbolNode'];
     16 var createSimplifyCore = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
     17   var equal = _ref.equal,
     18       isZero = _ref.isZero,
     19       add = _ref.add,
     20       subtract = _ref.subtract,
     21       multiply = _ref.multiply,
     22       divide = _ref.divide,
     23       pow = _ref.pow,
     24       AccessorNode = _ref.AccessorNode,
     25       ArrayNode = _ref.ArrayNode,
     26       ConstantNode = _ref.ConstantNode,
     27       FunctionNode = _ref.FunctionNode,
     28       IndexNode = _ref.IndexNode,
     29       ObjectNode = _ref.ObjectNode,
     30       OperatorNode = _ref.OperatorNode,
     31       ParenthesisNode = _ref.ParenthesisNode,
     32       SymbolNode = _ref.SymbolNode;
     33   var node0 = new ConstantNode(0);
     34   var node1 = new ConstantNode(1);
     35 
     36   var _createUtil = (0, _util.createUtil)({
     37     FunctionNode: FunctionNode,
     38     OperatorNode: OperatorNode,
     39     SymbolNode: SymbolNode
     40   }),
     41       hasProperty = _createUtil.hasProperty,
     42       isCommutative = _createUtil.isCommutative;
     43   /**
     44    * simplifyCore() performs single pass simplification suitable for
     45    * applications requiring ultimate performance. In contrast, simplify()
     46    * extends simplifyCore() with additional passes to provide deeper
     47    * simplification.
     48    *
     49    * Syntax:
     50    *
     51    *     simplifyCore(expr)
     52    *
     53    * Examples:
     54    *
     55    *     const f = math.parse('2 * 1 * x ^ (2 - 1)')
     56    *     math.simpifyCore(f)                          // Node {2 * x}
     57    *     math.simplify('2 * 1 * x ^ (2 - 1)', [math.simplifyCore]) // Node {2 * x}
     58    *
     59    * See also:
     60    *
     61    *     simplify, resolve, derivative
     62    *
     63    * @param {Node} node
     64    *     The expression to be simplified
     65    * @param {Object} options
     66    *     Simplification options, as per simplify()
     67    * @return {Node} Returns expression with basic simplifications applied
     68    */
     69 
     70 
     71   function simplifyCore(node, options) {
     72     var context = options ? options.context : undefined;
     73 
     74     if (hasProperty(node, 'trivial', context)) {
     75       // This node does nothing if it has only one argument, so if so,
     76       // return that argument simplified
     77       if ((0, _is.isFunctionNode)(node) && node.args.length === 1) {
     78         return simplifyCore(node.args[0], options);
     79       } // For other node types, we try the generic methods
     80 
     81 
     82       var simpChild = false;
     83       var childCount = 0;
     84       node.forEach(function (c) {
     85         ++childCount;
     86 
     87         if (childCount === 1) {
     88           simpChild = simplifyCore(c, options);
     89         }
     90       });
     91 
     92       if (childCount === 1) {
     93         return simpChild;
     94       }
     95     }
     96 
     97     if ((0, _is.isOperatorNode)(node) && node.isUnary()) {
     98       var a0 = simplifyCore(node.args[0], options);
     99 
    100       if (node.op === '-') {
    101         // unary minus
    102         if ((0, _is.isOperatorNode)(a0)) {
    103           if (a0.isUnary() && a0.op === '-') {
    104             return a0.args[0];
    105           } else if (a0.isBinary() && a0.fn === 'subtract') {
    106             return new OperatorNode('-', 'subtract', [a0.args[1], a0.args[0]]);
    107           }
    108         }
    109 
    110         return new OperatorNode(node.op, node.fn, [a0]);
    111       }
    112     } else if ((0, _is.isOperatorNode)(node) && node.isBinary()) {
    113       var _a = simplifyCore(node.args[0], options);
    114 
    115       var a1 = simplifyCore(node.args[1], options);
    116 
    117       if (node.op === '+') {
    118         if ((0, _is.isConstantNode)(_a)) {
    119           if (isZero(_a.value)) {
    120             return a1;
    121           } else if ((0, _is.isConstantNode)(a1)) {
    122             return new ConstantNode(add(_a.value, a1.value));
    123           }
    124         }
    125 
    126         if ((0, _is.isConstantNode)(a1) && isZero(a1.value)) {
    127           return _a;
    128         }
    129 
    130         if ((0, _is.isOperatorNode)(a1) && a1.isUnary() && a1.op === '-') {
    131           return new OperatorNode('-', 'subtract', [_a, a1.args[0]]);
    132         }
    133 
    134         return new OperatorNode(node.op, node.fn, a1 ? [_a, a1] : [_a]);
    135       } else if (node.op === '-') {
    136         if ((0, _is.isConstantNode)(_a) && a1) {
    137           if ((0, _is.isConstantNode)(a1)) {
    138             return new ConstantNode(subtract(_a.value, a1.value));
    139           } else if (isZero(_a.value)) {
    140             return new OperatorNode('-', 'unaryMinus', [a1]);
    141           }
    142         } // if (node.fn === "subtract" && node.args.length === 2) {
    143 
    144 
    145         if (node.fn === 'subtract') {
    146           if ((0, _is.isConstantNode)(a1) && isZero(a1.value)) {
    147             return _a;
    148           }
    149 
    150           if ((0, _is.isOperatorNode)(a1) && a1.isUnary() && a1.op === '-') {
    151             return simplifyCore(new OperatorNode('+', 'add', [_a, a1.args[0]]), options);
    152           }
    153 
    154           return new OperatorNode(node.op, node.fn, [_a, a1]);
    155         }
    156       } else if (node.op === '*') {
    157         if ((0, _is.isConstantNode)(_a)) {
    158           if (isZero(_a.value)) {
    159             return node0;
    160           } else if (equal(_a.value, 1)) {
    161             return a1;
    162           } else if ((0, _is.isConstantNode)(a1)) {
    163             return new ConstantNode(multiply(_a.value, a1.value));
    164           }
    165         }
    166 
    167         if ((0, _is.isConstantNode)(a1)) {
    168           if (isZero(a1.value)) {
    169             return node0;
    170           } else if (equal(a1.value, 1)) {
    171             return _a;
    172           } else if ((0, _is.isOperatorNode)(_a) && _a.isBinary() && _a.op === node.op && isCommutative(node, context)) {
    173             var a00 = _a.args[0];
    174 
    175             if ((0, _is.isConstantNode)(a00)) {
    176               var a00a1 = new ConstantNode(multiply(a00.value, a1.value));
    177               return new OperatorNode(node.op, node.fn, [a00a1, _a.args[1]], node.implicit); // constants on left
    178             }
    179           }
    180 
    181           if (isCommutative(node, context)) {
    182             return new OperatorNode(node.op, node.fn, [a1, _a], node.implicit); // constants on left
    183           } else {
    184             return new OperatorNode(node.op, node.fn, [_a, a1], node.implicit);
    185           }
    186         }
    187 
    188         return new OperatorNode(node.op, node.fn, [_a, a1], node.implicit);
    189       } else if (node.op === '/') {
    190         if ((0, _is.isConstantNode)(_a)) {
    191           if (isZero(_a.value)) {
    192             return node0;
    193           } else if ((0, _is.isConstantNode)(a1) && (equal(a1.value, 1) || equal(a1.value, 2) || equal(a1.value, 4))) {
    194             return new ConstantNode(divide(_a.value, a1.value));
    195           }
    196         }
    197 
    198         return new OperatorNode(node.op, node.fn, [_a, a1]);
    199       } else if (node.op === '^') {
    200         if ((0, _is.isConstantNode)(a1)) {
    201           if (isZero(a1.value)) {
    202             return node1;
    203           } else if (equal(a1.value, 1)) {
    204             return _a;
    205           } else {
    206             if ((0, _is.isConstantNode)(_a)) {
    207               // fold constant
    208               return new ConstantNode(pow(_a.value, a1.value));
    209             } else if ((0, _is.isOperatorNode)(_a) && _a.isBinary() && _a.op === '^') {
    210               var a01 = _a.args[1];
    211 
    212               if ((0, _is.isConstantNode)(a01)) {
    213                 return new OperatorNode(node.op, node.fn, [_a.args[0], new ConstantNode(multiply(a01.value, a1.value))]);
    214               }
    215             }
    216           }
    217         }
    218       }
    219 
    220       return new OperatorNode(node.op, node.fn, [_a, a1]);
    221     } else if ((0, _is.isFunctionNode)(node)) {
    222       return new FunctionNode(simplifyCore(node.fn), node.args.map(function (n) {
    223         return simplifyCore(n, options);
    224       }));
    225     } else if ((0, _is.isArrayNode)(node)) {
    226       return new ArrayNode(node.items.map(function (n) {
    227         return simplifyCore(n, options);
    228       }));
    229     } else if ((0, _is.isAccessorNode)(node)) {
    230       return new AccessorNode(simplifyCore(node.object, options), simplifyCore(node.index, options));
    231     } else if ((0, _is.isIndexNode)(node)) {
    232       return new IndexNode(node.dimensions.map(function (n) {
    233         return simplifyCore(n, options);
    234       }));
    235     } else if ((0, _is.isObjectNode)(node)) {
    236       var newProps = {};
    237 
    238       for (var prop in node.properties) {
    239         newProps[prop] = simplifyCore(node.properties[prop], options);
    240       }
    241 
    242       return new ObjectNode(newProps);
    243     } else {// cannot simplify
    244     }
    245 
    246     return node;
    247   }
    248 
    249   return simplifyCore;
    250 });
    251 exports.createSimplifyCore = createSimplifyCore;