nerdamer-ts
Version:
javascript light-weight symbolic math expression evaluator
201 lines • 6.88 kB
JavaScript
;
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