UNPKG

nerdamer-ts

Version:

javascript light-weight symbolic math expression evaluator

192 lines 7.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.expandall = exports.expand = void 0; const Utils_1 = require("../../../Core/Utils"); const Symbol_1 = require("../../../Types/Symbol"); const Groups_1 = require("../../../Types/Groups"); const index_1 = require("../index"); const Parser_1 = require("../../../Parser/Parser"); /** * Expands a symbol * @param symbol */ // Old expand function expand(symbol, opt = undefined) { if (Array.isArray(symbol)) { return symbol.map(function (x) { return expand(x, opt); }); } opt = opt || {}; //deal with parenthesis if (symbol.group === Groups_1.Groups.FN && symbol.fname === '') { var f = expand(symbol.args[0], opt); var x = expand((0, index_1.pow)(f, (0, Parser_1.parse)(symbol.power)), opt); return (0, index_1.multiply)((0, Parser_1.parse)(symbol.multiplier), x).distributeMultiplier(); } // We can expand these groups so no need to waste time. Just return and be done. if ([Groups_1.Groups.N, Groups_1.Groups.P, Groups_1.Groups.S].indexOf(symbol.group) !== -1) { return symbol; //nothing to do } var original = symbol.clone(); // Set up a try-catch block. If anything goes wrong then we simply return the original symbol try { // Store the power and multiplier var m = symbol.multiplier.toString(); var p = Number(symbol.power); var retval = symbol; // Handle (a+b)^2 | (x+x^2)^2 if (symbol.isComposite() && (0, Utils_1.isInt)(symbol.power) && symbol.power > 0) { var n = p - 1; // Strip the expression of it's multiplier and power. We'll call it f. The power will be p and the multiplier m. var f = new Symbol_1.Symbol(0); symbol.each(function (x) { f = (0, index_1.add)(f, expand((0, Parser_1.parse)(x), opt)); }); var expanded = (0, Parser_1.parse)(f); for (var i = 0; i < n; i++) { expanded = mix(expanded, f, opt); } retval = (0, index_1.multiply)((0, Parser_1.parse)(m), expanded).distributeMultiplier(); } else if (symbol.group === Groups_1.Groups.FN && opt.expand_functions === true) { var args = []; // Expand function the arguments symbol.args.forEach(function (x) { args.push(expand(x, opt)); }); // Put back the power and multiplier retval = (0, index_1.pow)((0, Symbol_1.symfunction)(symbol.fname, args), (0, Parser_1.parse)(symbol.power)); retval = (0, index_1.multiply)(retval, (0, Parser_1.parse)(symbol.multiplier)); } else if (symbol.isComposite() && (0, Utils_1.isInt)(symbol.power) && symbol.power < 0 && opt.expand_denominator === true) { // Invert it. Expand it and then re-invert it. symbol = symbol.invert(); retval = expand(symbol, opt); retval.invert(); } else if (symbol.group === Groups_1.Groups.CB) { var rank = function (s) { switch (s.group) { case Groups_1.Groups.CP: return 0; case Groups_1.Groups.PL: return 1; case Groups_1.Groups.CB: return 2; case Groups_1.Groups.FN: return 3; default: return 4; } }; // Consider (a+b)(c+d). The result will be (a*c+a*d)+(b*c+b*d). // We start by moving collecting the symbols. We want others>FN>CB>PL>CP var symbols = symbol.collectSymbols().sort(function (a, b) { return rank(b) - rank(a); }) // Distribute the power to each symbol and expand .map(function (s) { var x = (0, index_1.pow)(s, (0, Parser_1.parse)(p)); var e = expand(x, opt); return e; }); var f = symbols.pop(); // If the first symbols isn't a composite then we're done if (f.isComposite() && f.isLinear()) { symbols.forEach(function (s) { f = mix(f, s, opt); }); // If f is of group PL or CP then we can expand some more if (f.isComposite()) { if (f.power > 1) { f = expand((0, index_1.pow)(f, (0, Parser_1.parse)(f.power)), opt); } // Put back the multiplier retval = (0, index_1.multiply)((0, Parser_1.parse)(m), f).distributeMultiplier(); } else { // Everything is expanded at this point so if it's still a CB // then just return the symbol retval = f; } } else { // Just multiply back in the expanded form of each retval = f; symbols.forEach(function (s) { retval = (0, index_1.multiply)(retval, s); }); // Put back the multiplier retval = (0, index_1.multiply)(retval, (0, Parser_1.parse)(m)).distributeMultiplier(); } // TODO: This exists solely as a quick fix for sqrt(11)*sqrt(33) not simplifying. if (retval.group === Groups_1.Groups.CB) { retval = (0, Parser_1.parse)(retval); } } else { // Otherwise just return the expression retval = symbol; } // Final cleanup and return return retval; } catch (e) { return original; } } exports.expand = expand; /** * A wrapper for the expand function * @param {Symbol} symbol * @returns {Symbol} */ function expandall(symbol, opt) { opt = opt || { expand_denominator: true, expand_functions: true }; return expand(symbol, opt); } exports.expandall = expandall; /** * Used to multiply two expression in expanded form * @param {Symbol} a * @param {Symbol} b */ function mix(a, b, opt) { // Flip them if b is a CP or PL and a is not if (b.isComposite() && !a.isComposite() || b.isLinear() && !a.isLinear()) { [a, b] = [b, a]; } // A temporary variable to hold the expanded terms var t = new Symbol_1.Symbol(0); if (a.isLinear()) { a.each(function (x) { // If b is not a PL or a CP then simply multiply it if (!b.isComposite()) { var term = (0, index_1.multiply)((0, Parser_1.parse)(x), (0, Parser_1.parse)(b)); t = (0, index_1.add)(t, expand(term, opt)); } // Otherwise multiply out each term. else if (b.isLinear()) { b.each(function (y) { var term = (0, index_1.multiply)((0, Parser_1.parse)(x), (0, Parser_1.parse)(y)); var expanded = expand((0, Parser_1.parse)(term), opt); t = (0, index_1.add)(t, expanded); }, true); } else { t = (0, index_1.add)(t, (0, index_1.multiply)(x, (0, Parser_1.parse)(b))); } }, true); } else { // Just multiply them together t = (0, index_1.multiply)(a, b); } // The expanded function is now t return t; } //# sourceMappingURL=expand.js.map