UNPKG

nerdamer-ts

Version:

javascript light-weight symbolic math expression evaluator

201 lines 6.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.separate = exports.scientificToDecimal = exports.nroots = exports.isNumericSymbol = exports.isNegative = exports.isFraction = exports.getCoeffs = exports.decompose_fn = void 0; const Groups_1 = require("../Types/Groups"); const expand_1 = require("../Functions/Core/math/expand"); const Core_1 = require("../Functions/Core"); const Symbol_1 = require("../Types/Symbol"); const Utils_1 = require("./Utils"); const Settings_1 = require("../Settings"); const Vector_1 = require("../Types/Vector"); const Math2_1 = require("../Functions/Math2"); const Parser_1 = require("../Parser/Parser"); /** * TODO: Pick a more descriptive name and better description * Breaks a function down into it's parts wrt to a variable, mainly coefficients * Example a*x^2+b wrt x * @param {Symbol} fn * @param {String} wrt * @param {boolean} as_obj */ function decompose_fn(fn, wrt, as_obj) { wrt = String(wrt); //convert to string let ax, a, x, b; if (fn.group === Groups_1.Groups.CP) { let t = (0, expand_1.expand)(fn.clone()).stripVar(wrt); ax = (0, Core_1.subtract)(fn.clone(), t.clone()); b = t; } else { ax = fn.clone(); } a = ax.stripVar(wrt); x = (0, Core_1.divide)(ax.clone(), a.clone()); b = b || new Symbol_1.Symbol(0); if (as_obj) return { a: a, x: x, ax: ax, b: b }; return [a, x, ax, b]; } exports.decompose_fn = decompose_fn; /** * Returns the coefficients of a symbol given a variable. Given ax^2+b^x+c, it divides * each nth term by x^n. * @param {Symbol} symbol * @param {Symbol} wrt */ function getCoeffs(symbol, wrt, info) { let coeffs = []; //we loop through the symbols and stick them in their respective //containers e.g. y*x^2 goes to index 2 symbol.each(function (term) { let coeff, p; if (term.contains(wrt)) { //we want only the coefficient which in this case will be everything but the variable //e.g. a*b*x -> a*b if the variable to solve for is x coeff = term.stripVar(wrt); let x = (0, Core_1.divide)(term.clone(), coeff.clone()); p = x.power.toDecimal(); } else { coeff = term; p = 0; } let e = coeffs[p]; //if it exists just add it to it coeffs[p] = e ? (0, Core_1.add)(e, coeff) : coeff; }, true); for (let i = 0; i < coeffs.length; i++) if (!coeffs[i]) coeffs[i] = new Symbol_1.Symbol(0); //fill the holes return coeffs; } exports.getCoeffs = getCoeffs; /** * Checks to see if a number or Symbol is a fraction * @param {Number|Symbol} num * @returns {boolean} */ function isFraction(num) { if ((0, Utils_1.isSymbol)(num)) return isFraction(num.multiplier.toDecimal()); return (num % 1 !== 0); } exports.isFraction = isFraction; /** * @param {Number|Symbol} obj * @returns {boolean} */ function isNegative(obj) { if ((0, Utils_1.isSymbol)(obj)) { obj = obj.multiplier; } return obj.lessThan(0); } exports.isNegative = isNegative; /** * Checks to see if a symbol is in group N * @param {Symbol} symbol */ function isNumericSymbol(symbol) { return symbol.group === Groups_1.Groups.N || symbol.group === Groups_1.Groups.P; } exports.isNumericSymbol = isNumericSymbol; /** * Gets nth roots of a number * @param {Symbol} symbol * @returns {Vector} */ function nroots(symbol) { var a, b; if (symbol.group === Groups_1.Groups.FN && symbol.fname === '') { a = Symbol_1.Symbol.unwrapPARENS((0, Parser_1.parse)(symbol).toLinear()); b = (0, Parser_1.parse)(symbol.power); } else if (symbol.group === Groups_1.Groups.P) { a = (0, Parser_1.parse)(symbol.value); b = (0, Parser_1.parse)(symbol.power); } if (a && b && (a.group === Groups_1.Groups.N) && b.group === Groups_1.Groups.N && a.multiplier.isNegative()) { let _roots = []; var parts = Symbol_1.Symbol.toPolarFormArray((0, Utils_1.evaluate)(symbol)); var r = parts[0]; //var r = parse(a).abs().toString(); //https://en.wikipedia.org/wiki/De_Moivre%27s_formula var x = (0, Core_1.arg)(a); var n = b.multiplier.den.toString(); var p = b.multiplier.num.toString(); var formula = '(({0})^({1})*(cos({3})+({2})*sin({3})))^({4})'; for (var i = 0; i < n; i++) { var t = (0, Utils_1.evaluate)((0, Parser_1.parse)((0, Utils_1.format)("(({0})+2*pi*({1}))/({2})", x, i, n))).multiplier.toDecimal(); _roots.push((0, Utils_1.evaluate)((0, Parser_1.parse)((0, Utils_1.format)(formula, r, n, Settings_1.Settings.IMAGINARY, t, p)))); } return Vector_1.Vector.fromArray(_roots); } else if (symbol.isConstant(true, true)) { var sign = symbol.sign(); var x = (0, Utils_1.evaluate)(symbol.abs()); var root = (0, Core_1.sqrt)(x); var _roots = [root.clone(), root.negate()]; if (sign < 0) _roots = _roots.map(function (x) { return (0, Core_1.multiply)(x, Symbol_1.Symbol.imaginary()); }); } else { _roots = [(0, Parser_1.parse)(symbol)]; } return Vector_1.Vector.fromArray(_roots); } exports.nroots = nroots; /** * Convert number from scientific format to decimal format * @param value */ function scientificToDecimal(value) { return Math2_1.Math2.scientificToDecimal(value); } exports.scientificToDecimal = scientificToDecimal; /** * Separates out the variables into terms of variabls. * e.g. x+y+x*y+sqrt(2)+pi returns * {x: x, y: y, x y: x*y, constants: sqrt(2)+pi * @param {type} symbol * @param {type} o * @returns {undefined} * @throws {Error} for expontentials */ function separate(symbol, o) { symbol = (0, expand_1.expand)(symbol); o = o || {}; let insert = function (key, sym) { if (!o[key]) o[key] = new Symbol_1.Symbol(0); o[key] = (0, Core_1.add)(o[key], sym.clone()); }; symbol.each(function (x) { if (x.isConstant('all')) { insert('constants', x); } else if (x.group === Groups_1.Groups.S) { insert(x.value, x); } else if (x.group === Groups_1.Groups.FN && (x.fname === Settings_1.Settings.ABS || x.fname === '')) { separate(x.args[0]); } else if (x.group === Groups_1.Groups.EX || x.group === Groups_1.Groups.FN) { throw new Error('Unable to separate. Term cannot be a function!'); } else { insert((0, Utils_1.isSymbol)(x) ? x.variables().join(' ') : '', x); } }); return o; } exports.separate = separate; //# sourceMappingURL=Utils-js.js.map