nerdamer-ts
Version:
javascript light-weight symbolic math expression evaluator
232 lines • 9.59 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.add = void 0;
const Symbol_1 = require("../../../Types/Symbol");
const Errors_1 = require("../../../Core/Errors");
const Settings_1 = require("../../../Settings");
const Groups_1 = require("../../../Types/Groups");
const Text_1 = require("../../../Core/Text");
const Utils_1 = require("../../../Core/Utils");
const Matrix_1 = require("../../../Types/Matrix");
const index_1 = require("../index");
/**
* Adds two symbols
* @param {Symbol} a
* @param {Symbol} b
* @returns {Symbol}
*/
function add(a, b) {
var aIsSymbol = (0, Utils_1.isSymbol)(a), bIsSymbol = (0, Utils_1.isSymbol)(b);
//we're dealing with two symbols
if (aIsSymbol && bIsSymbol) {
//forward the adding of symbols with units to the Unit module
if (a.unit || b.unit) {
return deps.Unit.add(a, b);
}
//handle Infinity
//https://www.encyclopediaofmath.org/index.php/Infinity
if (a.isInfinity || b.isInfinity) {
var aneg = a.multiplier.lessThan(0), bneg = b.multiplier.lessThan(0);
if (a.isInfinity && b.isInfinity && aneg !== bneg) {
throw new Errors_1.UndefinedError('(' + a + ')+(' + b + ') is not defined!');
}
var inf = Symbol_1.Symbol.infinity();
if (bneg)
inf.negate();
return inf;
}
if (a.isComposite() && a.isLinear() && b.isComposite() && b.isLinear()) {
a.distributeMultiplier();
b.distributeMultiplier();
// Fix for issue #606
if (b.length > a.length && a.group === b.group) {
[a, b] = [b, a];
}
}
//no need to waste time on zeroes
if (a.multiplier.equals(0))
return b;
if (b.multiplier.equals(0))
return a;
if (a.isConstant() && b.isConstant() && Settings_1.Settings.PARSE2NUMBER) {
var result = new Symbol_1.Symbol(a.multiplier.add(b.multiplier).toDecimal(Settings_1.Settings.PRECISION));
return result;
}
var g1 = a.group, g2 = b.group, ap = a.power.toString(), bp = b.power.toString();
//always keep the greater group on the left.
if (g1 < g2 || (g1 === g2 && ap > bp && bp > 0)) {
return add(b, a);
}
/*note to self: Please don't forget about this dilemma ever again. In this model Groups.PL and Groups.CB goes crazy
* because it doesn't know which one to prioritize. */
//correction to Groups.PL dilemma
if (g1 === Groups_1.Groups.CB && g2 === Groups_1.Groups.PL && a.value === b.value) {
//swap
var t = a;
a = b;
b = t;
g1 = a.group;
g2 = b.group;
ap = a.power.toString();
bp = b.power.toString();
}
var powEQ = ap === bp, v1 = a.value, v2 = b.value, aIsComposite = a.isComposite(), bIsComposite = b.isComposite(), h1, h2, result;
if (aIsComposite)
h1 = (0, Text_1.text)(a, 'hash');
if (bIsComposite)
h2 = (0, Text_1.text)(b, 'hash');
if (g1 === Groups_1.Groups.CP && g2 === Groups_1.Groups.CP && b.isLinear() && !a.isLinear() && h1 !== h2) {
return add(b, a);
}
//Groups.PL & Groups.PL should compare hashes and not values e.g. compare x+x^2 with x+x^3 and not x with x
if (g1 === Groups_1.Groups.PL && g2 === Groups_1.Groups.PL) {
v1 = h1;
v2 = h2;
}
var PN = g1 === Groups_1.Groups.P && g2 === Groups_1.Groups.N, PNEQ = a.value === b.multiplier.toString(), valEQ = (v1 === v2 || h1 === h2 && h1 !== undefined || (PN && PNEQ));
//equal values, equal powers
if (valEQ && powEQ && g1 === g2) {
//make sure to convert Groups.N to something Groups.P can work with
if (PN)
b = b.convert(Groups_1.Groups.P); //CL
//handle Groups.PL
if (g1 === Groups_1.Groups.PL && (g2 === Groups_1.Groups.S || g2 === Groups_1.Groups.P)) {
a.distributeMultiplier();
result = a.attach(b);
}
else {
result = a; //CL
if (a.multiplier.isOne() && b.multiplier.isOne() && g1 === Groups_1.Groups.CP && a.isLinear() && b.isLinear()) {
for (var s in b.symbols) {
var x = b.symbols[s];
result.attach(x);
}
}
else
result.multiplier = result.multiplier.add(b.multiplier);
}
}
//equal values uneven powers
else if (valEQ && g1 !== Groups_1.Groups.PL) {
//break the tie for e.g. (x+1)+((x+1)^2+(x+1)^3)
if (g1 === Groups_1.Groups.CP && g2 === Groups_1.Groups.PL) {
b.insert(a, 'add');
result = b;
}
else {
result = Symbol_1.Symbol.shell(Groups_1.Groups.PL).attach([a, b]);
//update the hash
result.value = g1 === Groups_1.Groups.PL ? h1 : v1;
}
}
else if (aIsComposite && a.isLinear()) {
var canIterate = g1 === g2, bothPL = g1 === Groups_1.Groups.PL && g2 === Groups_1.Groups.PL;
//we can only iterate group Groups.PL if they values match
if (bothPL)
canIterate = a.value === b.value;
//distribute the multiplier over the entire symbol
a.distributeMultiplier();
if (b.isComposite() && b.isLinear() && canIterate) {
b.distributeMultiplier();
//CL
for (var s in b.symbols) {
var x = b.symbols[s];
a.attach(x);
}
result = a;
}
//handle cases like 2*(x+x^2)^2+2*(x+x^2)^3+4*(x+x^2)^2
else if (bothPL && a.value !== h2 || g1 === Groups_1.Groups.PL && !valEQ) {
result = Symbol_1.Symbol.shell(Groups_1.Groups.CP).attach([a, b]);
result.updateHash();
}
else {
result = a.attach(b);
}
}
else {
if (g1 === Groups_1.Groups.FN && a.fname === Settings_1.Settings.SQRT && g2 !== Groups_1.Groups.EX && b.power.equals(0.5)) {
var m = b.multiplier.clone();
b = (0, index_1.sqrt)(b.toUnitMultiplier().toLinear());
b.multiplier = m;
}
//fix for issue #3 and #159
if (a.length === 2 && b.length === 2 && (0, Utils_1.even)(a.power) && (0, Utils_1.even)(b.power)) {
result = add((0, index_1.expand)(a), (0, index_1.expand)(b));
}
else {
result = Symbol_1.Symbol.shell(Groups_1.Groups.CP).attach([a, b]);
result.updateHash();
}
}
if (result.multiplier.equals(0))
result = new Symbol_1.Symbol(0);
//make sure to remove unnecessary wraps
if (result.length === 1) {
var m = result.multiplier;
result = (0, Utils_1.firstObject)(result.symbols);
result.multiplier = result.multiplier.multiply(m);
}
return result;
}
else {
//keep symbols to the right
if (bIsSymbol && !aIsSymbol) {
var t = a;
a = b;
b = t; //swap
t = bIsSymbol;
bIsSymbol = aIsSymbol;
aIsSymbol = t;
}
var bIsMatrix = (0, Utils_1.isMatrix)(b);
if (aIsSymbol && bIsMatrix) {
var M = new Matrix_1.Matrix();
b.eachElement(function (e, i, j) {
M.set(i, j, add(a.clone(), e));
});
b = M;
}
else {
if ((0, Utils_1.isMatrix)(a) && bIsMatrix) {
b = a.add(b);
}
else if (aIsSymbol && (0, Utils_1.isVector)(b)) {
b.each(function (x, i) {
i--;
b.elements[i] = add(a.clone(), b.elements[i]);
});
}
else {
if ((0, Utils_1.isVector)(a) && (0, Utils_1.isVector)(b)) {
b.each(function (x, i) {
i--;
b.elements[i] = add(a.elements[i], b.elements[i]);
});
}
else if ((0, Utils_1.isVector)(a) && (0, Utils_1.isMatrix)(b)) {
//try to convert a to a matrix
return add(b, a);
}
else if ((0, Utils_1.isMatrix)(a) && (0, Utils_1.isVector)(b)) {
if (b.elements.length === a.rows()) {
var M = new Matrix_1.Matrix(), l = a.cols();
b.each(function (e, i) {
var row = [];
for (var j = 0; j < l; j++) {
row.push(add(a.elements[i - 1][j].clone(), e.clone()));
}
M.elements.push(row);
});
return M;
}
else
(0, Errors_1.err)('Dimensions must match!');
}
}
}
return b;
}
}
exports.add = add;
//# sourceMappingURL=add.js.map