Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nerdamer

Package Overview
Dependencies
Maintainers
2
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nerdamer - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

0

BREAKING_CHANGES.md

@@ -0,0 +0,0 @@ *version 0.8.0*

2

package.json

@@ -9,3 +9,3 @@ {

"license": "MIT",
"version": "1.0.0",
"version": "1.0.1",
"homepage": "http://nerdamer.com/",

@@ -12,0 +12,0 @@ "directory": {

@@ -22,2 +22,3 @@ /*

explode = _C.integration.decompose_arg,
evaluate = core.Utils.evaluate,
remove = core.Utils.remove,

@@ -36,11 +37,3 @@ format = core.Utils.format,

//version solve
core.Solve = {
version: '1.2.7',
solve: function (eq, variable) {
var solution = solve(eq, String(variable));
return new core.Vector(solution);
//return new core.Vector(solve(eq.toString(), variable ? variable.toString() : variable));
}
};
// The search radius for the roots

@@ -54,2 +47,12 @@ core.Settings.SOLVE_RADIUS = 1000;

core.Settings.STEP_SIZE = 0.1;
//the maximum iterations for Newton's method
core.Settings.MAX_NEWTON_ITERATIONS = 200;
//the maximum number of time non-linear solve tries another jump point
core.Settings.MAX_NON_LINEAR_TRIES = 12;
//the amount of iterations the function will start to jump at
core.Settings.NON_LINEAR_JUMP_AT = 50;
//the size of the jump
core.Settings.NON_LINEAR_JUMP_SIZE = 100;
//the original starting point for nonlinear solving
core.Settings.NON_LINEAR_START = 0.01;

@@ -70,3 +73,3 @@ core.Symbol.prototype.hasTrig = function () {

};
/* nerdamer version 0.7.x and up allows us to make better use of operator overloading

@@ -81,60 +84,6 @@ * As such we can have this data type be supported completely outside of the core.

this.RHS = rhs; //right and side
}
;
};
//UTILS ##!!
/**
* This function is confusing and should be refactored. Why is removeDenom bringing the equation to LHS????
* @param {Symbol} a
* @param {Symbol} b
* @returns {Symbol}
*/
var removeDenom = function (a, b) {
//remove the denominator on both sides
var den = _.multiply(a.getDenom(), b.getDenom());
a = _.expand(_.multiply(a, den.clone()));
b = _.expand(_.multiply(b, den));
//swap the groups
if (b.group === CP && b.group !== CP) {
var t = a;
a = b;
b = t; //swap
}
//scan to eliminate denominators
if (a.group === CB) {
var t = new Symbol(a.multiplier),
newRHS = b.clone();
a.each(function (y) {
if (y.power.lessThan(0))
newRHS = _.divide(newRHS, y);
else
t = _.multiply(t, y);
});
a = t;
b = newRHS;
}
else if (a.group === CP) {
//the logic: loop through each and if it has a denominator then multiply it out on both ends
//and then start over
for (var x in a.symbols) {
var sym = a.symbols[x];
if (sym.group === CB) {
for (var y in sym.symbols) {
var sym2 = sym.symbols[y];
if (sym2.power.lessThan(0)) {
return removeDenom(
_.expand(_.multiply(sym2.clone().toLinear(), a)),
_.expand(_.multiply(sym2.clone().toLinear(), b))
);
}
}
}
}
}
return _.expand(_.subtract(a, b));
};
Equation.prototype = {

@@ -148,4 +97,54 @@ toString: function () {

toLHS: function () {
return removeDenom(this.LHS.clone(), this.RHS.clone());
var eqn = this.removeDenom();
return _.expand(_.subtract(eqn.LHS, eqn.RHS));;
},
removeDenom: function () {
var a = this.LHS.clone();
var b = this.RHS.clone();
//remove the denominator on both sides
var den = _.multiply(a.getDenom(), b.getDenom());
a = _.expand(_.multiply(a, den.clone()));
b = _.expand(_.multiply(b, den));
//swap the groups
if (b.group === CP && b.group !== CP) {
var t = a;
a = b;
b = t; //swap
}
//scan to eliminate denominators
if (a.group === CB) {
var t = new Symbol(a.multiplier),
newRHS = b.clone();
a.each(function (y) {
if (y.power.lessThan(0))
newRHS = _.divide(newRHS, y);
else
t = _.multiply(t, y);
});
a = t;
b = newRHS;
}
else if (a.group === CP) {
//the logic: loop through each and if it has a denominator then multiply it out on both ends
//and then start over
for (var x in a.symbols) {
var sym = a.symbols[x];
if (sym.group === CB) {
for (var y in sym.symbols) {
var sym2 = sym.symbols[y];
if (sym2.power.lessThan(0)) {
return new Equation(
_.expand(_.multiply(sym2.clone().toLinear(), a)),
_.expand(_.multiply(sym2.clone().toLinear(), b))
);
}
}
}
}
}
return new Equation(a, b);
},
clone: function () {

@@ -171,13 +170,68 @@ return new Equation(this.LHS.clone(), this.RHS.clone());

};
// A utility function to parse an expression to left hand side when working with strings
var toLHS = function (eqn) {
//If it's an equation then call its toLHS function instead
if (eqn instanceof Equation)
return eqn.toLHS();
var es = eqn.split('=');
if (es[1] === undefined)
es[1] = '0';
var e1 = _.parse(es[0]), e2 = _.parse(es[1]);
return removeDenom(e1, e2);
core.Expression.prototype.solveFor = function (x) {
return solve(core.Utils.isSymbol(this.symbol) ? this.symbol : this.symbol.toLHS(), x).map(function (x) {
return new core.Expression(x);
});
};
core.Expression.prototype.expand = function () {
if (this.symbol instanceof Equation) {
var clone = this.symbol.clone();
clone.RHS = _.expand(clone.RHS);
clone.LHS = _.expand(clone.LHS);
return new core.Expression(clone);
}
return new core.Expression(_.expand(this.symbol));
};
core.Expression.prototype.variables = function () {
if (this.symbol instanceof Equation)
return core.Utils.arrayUnique(variables(this.symbol.LHS).concat(variables(this.symbol.RHS)));
return variables(this.symbol);
};
core.Matrix.jacobian = function(eqns, vars) {
var jacobian = new core.Matrix();
//get the variables if not supplied
if(!vars) {
vars = __.getSystemVariables(eqns);
}
vars.forEach(function(v, i) {
eqns.forEach(function(eq, j) {
var e = core.Calculus.diff(eq.clone(), v);
jacobian.set(j, i, e);
});
});
return jacobian;
};
core.Matrix.prototype.max = function() {
var max = new Symbol(0);
this.each(function(x) {
var e = x.abs();
if(e.gt(max))
max = e;
});
return max;
};
core.Matrix.cMatrix = function(value, vars) {
var m = new core.Matrix();
//make an initial guess
vars.forEach(function(v, i) {
m.set(i, 0, _.parse(value));
});
return m;
};
var setEq = function (a, b) {
return _.equals(a, b);
};
//link the Equation class back to the core
core.Equation = Equation;
//Loops through an array and attempts to fails a test. Stops if manages to fail.

@@ -190,13 +244,196 @@ var checkAll = core.Utils.checkAll = function (args, test) {

};
//version solve
var __ = core.Solve = {
version: '2.0.0',
solutions: [],
solve: function (eq, variable) {
var solution = solve(eq, String(variable));
return new core.Vector(solution);
//return new core.Vector(solve(eq.toString(), variable ? variable.toString() : variable));
},
/**
* Brings the equation to LHS. A string can be supplied which will be converted to an Equation
* @param {Equation|String} eqn
* @returns {Symbol}
*/
toLHS: function (eqn) {
//If it's an equation then call its toLHS function instead
if (!(eqn instanceof Equation)) {
var es = eqn.split('=');
//convert falsey values to zero
es[1] = es[1] || '0';
eqn = new Equation(_.parse(es[0]), _.parse(es[1]));
}
return eqn.toLHS();
},
getSystemVariables: function(eqns) {
vars = variables(eqns[0], null, null, true);
// Solves a system of equations
var sys_solve = function (eqns, var_array) {
//check if a var_array was specified
//nerdamer.clearVars();// this deleted ALL variables: not what we want
//parse all the equations to LHS. Remember that they come in as strings
for (var i = 0; i < eqns.length; i++)
eqns[i] = toLHS(eqns[i]);
//get all variables
for (var i = 1, l=eqns.length; i < l; i++)
vars = vars.concat(variables(eqns[i]));
//remove duplicates
vars = core.Utils.arrayUnique(vars).sort();
//done
return vars;
},
solveNonLinearSystem: function(eqns, tries, start) {
if(tries < 0)
return [];//can't find a solution
start = typeof start === 'undefined' ? core.Settings.NON_LINEAR_START : start;
var l = eqns.length,
//the maximum number of times to jump
var max_tries = core.Settings.MAX_NON_LINEAR_TRIES;
//halfway through the tries
var halfway = Math.floor(max_tries/2);
//initialize the number of tries to 10 if not specified
tries = typeof tries === 'undefined' ? max_tries : tries;
//a point at which we check to see if we're converging. By inspection it seems that we can
//use around 20 iterations to see if we're converging. If not then we retry a jump of x
var jump_at = core.Settings.NON_LINEAR_JUMP_AT;
//we jump by this many points at each pivot point
var jump = core.Settings.NON_LINEAR_JUMP_SIZE;
//used to check if we actually found a solution or if we gave up. Assume we will find a solution.
var found = true;
var create_subs = function(vars, matrix) {
return vars.map(function(x, i) {
return Number(matrix.get(i, 0));
});
};
var vars = __.getSystemVariables(eqns);
var jacobian = core.Matrix.jacobian(eqns, vars, function(x) {
return build(x, vars);
}, true);
var max_iter = core.Settings.MAX_NEWTON_ITERATIONS;
var o, y, iters, xn1, norm, lnorm, xn, d;
var f_eqns = eqns.map(function(eq) {
return build(eq, vars);
});
var J = jacobian.map(function(e) {
return build(e, vars);
}, true);
//initial values
xn1 = core.Matrix.cMatrix(0, vars);;
//initialize the c matrix with something close to 0.
var c = core.Matrix.cMatrix(start, vars);
iters = 0;
//start of algorithm
do {
//if we've reached the max iterations then exit
if(iters > max_iter) {
break;
found = false;
}
//set the substitution object
o = create_subs(vars, c);
//set xn
xn = c.clone();
//make all the substitutions for each of the equations
f_eqns.forEach(function(f, i) {
c.set(i, 0, f.apply(null, o));
});
var m = new core.Matrix();
J.each(function(fn, i, j) {
var ans = fn.apply(null, o);
m.set(i, j, ans);
});
m = m.invert();
//preform the elimination
y = _.multiply(m, c).negate();
//the callback is to avoid overflow in the coeffient denonimator
//it converts it to a decimal and then back to a fraction. Some precision
//is lost be it's better than overflow.
d = y.subtract(xn1, function(x) { return _.parse(Number(x)); });
xn1 = xn.add(y, function(x) { return _.parse(Number(x)); });
//move c is now xn1
c = xn1;
//get the norm
//the expectation is that we're converging to some answer as this point regardless of where we start
//this may have to be adjusted at some point because of erroneous assumptions
if(iters >= jump_at) {
//check the norm. If the norm is greater than one then it's time to try another point
if(norm > 1) {
//reset the start point at halway
if(tries === halfway)
start = 0;
var sign = tries > halfway ? 1 : -1; //which side are we incrementing
//we increment +n at one side and -n at the other.
n = (tries % Math.floor(halfway))+1;
//adjust the start point
start += (sign*n*jump);
//call restart
return __.solveNonLinearSystem(eqns, --tries, start);
}
}
lnorm = norm;
iters++;
norm = d.max();
//exit early. Revisit if we get bugs
if(Number(norm) === Number(lnorm))
break;
}
while(Number(norm) >= Number.EPSILON)
//return a blank set if nothing was found;
if(!found)
return [];
//return c since that's the answer
return __.systemSolutions(c, vars, true, function(x) {
return core.Utils.round(Number(x), 14);
});
},
systemSolutions: function(result, vars, expand_result, callback) {
var solutions = core.Settings.SOLUTIONS_AS_OBJECT ? {} : [];
result.each(function (e, idx) {
var solution = (expand_result ? _.expand(e) : e).valueOf();
if(callback)
solution = callback.call(e, solution);
var variable = vars[idx];
if (core.Settings.SOLUTIONS_AS_OBJECT) {
solutions[variable] = solution;
}
else
solutions.push([variable, solution]); /*NO*/
});
//done
return solutions;
},
//https://www.lakeheadu.ca/sites/default/files/uploads/77/docs/RemaniFinal.pdf
solveSystem: function (eqns, var_array) {
//check if a var_array was specified
//nerdamer.clearVars();// this deleted ALL variables: not what we want
//parse all the equations to LHS. Remember that they come in as strings
for (var i = 0; i < eqns.length; i++)
eqns[i] = __.toLHS(eqns[i]);
var l = eqns.length,
m = new core.Matrix(),

@@ -207,321 +444,412 @@ c = new core.Matrix(),

if (typeof var_array === 'undefined') {
//check to make sure that all the equations are linear
if (!_A.allLinear(eqns))
core.err('System must contain all linear equations!');
vars = variables(eqns[0], null, null, true);
if (typeof var_array === 'undefined') {
//check to make sure that all the equations are linear
if (!_A.allLinear(eqns))
return __.solveNonLinearSystem(eqns);
//core.err('System must contain all linear equations!');
vars = __.getSystemVariables(eqns);
// deletes only the variables of the linear equations in the nerdamer namespace
for (var i = 0; i < vars.length; i++) {
nerdamer.setVar(vars[i], "delete");
}
// populate the matrix
for (var i = 0; i < l; i++) {
var e = eqns[i]; //store the expression
for (var j = 0; j < l; j++) {
var v = vars[j];
var coeffs = [];
e.each(function(x) {
if(x.contains(v)) {
coeffs = coeffs.concat(x.coeffs());
}
});
//get all variables
for (var i = 1; i < l; i++)
vars = vars.concat(variables(eqns[i]));
//remove duplicates
vars = core.Utils.arrayUnique(vars).sort();
var cf = core.Utils.arraySum(coeffs);
m.set(i, j, cf);
}
// deletes only the variables of the linear equations in the nerdamer namespace
for (var i = 0; i < vars.length; i++) {
nerdamer.setVar(vars[i], "delete");
}
// populate the matrix
for (var i = 0; i < l; i++) {
var e = eqns[i]; //store the expression
// for (var j = 0; j < l; j++) {
// var variable = e.symbols[vars[j]];
// m.set(i, j, variable ? variable.multiplier : 0);
// }
for (var j = 0; j < l; j++) {
var v = vars[j];
var coeffs = [];
e.each(function(x) {
if(x.contains(v)) {
coeffs = coeffs.concat(x.coeffs());
}
//strip the variables from the symbol so we're left with only the zeroth coefficient
//start with the symbol and remove each variable and its coefficient
var num = e.clone();
vars.map(function(e) {
num = num.stripVar(e);
});
var cf = core.Utils.arraySum(coeffs);
m.set(i, j, cf);
c.set(i, 0, num.negate());
}
//strip the variables from the symbol so we're left with only the zeroth coefficient
//start with the symbol and remove each variable and its coefficient
var num = e.clone();
vars.map(function(e) {
num = num.stripVar(e);
});
c.set(i, 0, num.negate());
}
}
else {
/**
* The idea is that we loop through each equation and then expand it. Afterwards we loop
* through each term and see if and check to see if it matches one of the variables.
* When a match is found we mark it. No other match should be found for that term. If it
* is we stop since it's not linear.
*/
vars = var_array;
expand_result = true;
for (i = 0; i < l; i++) {
//prefill
c.set(i, 0, new Symbol(0));
var e = _.expand(eqns[i]).collectSymbols(); //expand and store
//go trough each of the variables
for (var j = 0; j < var_array.length; j++) {
m.set(i, j, new Symbol(0));
var v = var_array[j];
//go through the terms and sort the variables
for (var k = 0; k < e.length; k++) {
var term = e[k],
check = false;
for (var z = 0; z < var_array.length; z++) {
//check to see if terms contain multiple variables
if (term.contains(var_array[z])) {
if (check)
core.err('Multiple variables found for term ' + term);
check = true;
else {
/**
* The idea is that we loop through each equation and then expand it. Afterwards we loop
* through each term and see if and check to see if it matches one of the variables.
* When a match is found we mark it. No other match should be found for that term. If it
* is we stop since it's not linear.
*/
vars = var_array;
expand_result = true;
for (i = 0; i < l; i++) {
//prefill
c.set(i, 0, new Symbol(0));
var e = _.expand(eqns[i]).collectSymbols(); //expand and store
//go trough each of the variables
for (var j = 0; j < var_array.length; j++) {
m.set(i, j, new Symbol(0));
var v = var_array[j];
//go through the terms and sort the variables
for (var k = 0; k < e.length; k++) {
var term = e[k],
check = false;
for (var z = 0; z < var_array.length; z++) {
//check to see if terms contain multiple variables
if (term.contains(var_array[z])) {
if (check)
core.err('Multiple variables found for term ' + term);
check = true;
}
}
//we made sure that every term contains one variable so it's safe to assume that if the
//variable is found then the remainder is the coefficient.
if (term.contains(v)) {
var tparts = explode(remove(e, k), v);
m.set(i, j, _.add(m.get(i, j), tparts[0]));
}
}
//we made sure that every term contains one variable so it's safe to assume that if the
//variable is found then the remainder is the coefficient.
if (term.contains(v)) {
var tparts = explode(remove(e, k), v);
m.set(i, j, _.add(m.get(i, j), tparts[0]));
}
}
//all the remaining terms go to the c matrix
for (k = 0; k < e.length; k++) {
c.set(i, 0, _.add(c.get(i, 0), e[k]));
}
}
//all the remaining terms go to the c matrix
for (k = 0; k < e.length; k++) {
c.set(i, 0, _.add(c.get(i, 0), e[k]));
}
//consider case (a+b)*I+u
}
//consider case (a+b)*I+u
}
//check if the system has a distinct solution
if(m.determinant().equals(0))
throw new core.exceptions.SolveError('System does not have a distinct solution');
// Use M^-1*c to solve system
m = m.invert();
var result = m.multiply(c);
//correct the sign as per issue #410
if (core.Utils.isArray(var_array))
result.each(function (x) {
return x.negate();
//check if the system has a distinct solution
if(m.determinant().equals(0))
throw new core.exceptions.SolveError('System does not have a distinct solution');
// Use M^-1*c to solve system
m = m.invert();
var result = m.multiply(c);
//correct the sign as per issue #410
if (core.Utils.isArray(var_array))
result.each(function (x) {
return x.negate();
});
return __.systemSolutions(result, vars, expand_result);
},
/**
* The quadratic function but only one side.
* @param {Symbol} c
* @param {Symbol} b
* @param {Symbol} a
* @returns {Symbol}
*/
quad: function (c, b, a) {
var bsqmin4ac = _.subtract(_.pow(b.clone(), Symbol(2)), _.multiply(_.multiply(a.clone(), c.clone()), Symbol(4)))/*b^2 - 4ac*/;
var det = _.pow(bsqmin4ac, Symbol(0.5));
var retval = [
_.parse(_.divide(_.add(b.clone().negate(), det.clone()), _.multiply(new Symbol(2), a.clone()))),
_.parse(_.divide(_.subtract(b.clone().negate(), det.clone()), _.multiply(new Symbol(2), a.clone())))
];
return retval;
},
/**
* The cubic equation
* http://math.stackexchange.com/questions/61725/is-there-a-systematic-way-of-solving-cubic-equations
* @param {Symbol} d_o
* @param {Symbol} c_o
* @param {Symbol} b_o
* @param {Symbol} a_o
* @returns {Array}
*/
cubic:function (d_o, c_o, b_o, a_o) {
//convert everything to text
var a = a_o.text(), b = b_o.text(), c = c_o.text(), d = d_o.text();
var d0s = '({1})^2-3*({0})*({2})',
d0 = _.parse(format(d0s, a, b, c)),
Q = _.parse(format('((2*({1})^3-9*({0})*({1})*({2})+27*({0})^2*({3}))^2-4*(({1})^2-3*({0})*({2}))^3)^(1/2)', a, b, c, d)),
C = _.parse(format('((1/2)*(({4})+2*({1})^3-9*({0})*({1})*({2})+27*({0})^2*({3})))^(1/3)', a, b, c, d, Q));
//check if C equals 0
var scope = {};
//populate the scope object
variables(C).map(function (x) {
scope[x] = 1;
});
var solutions = core.Settings.SOLUTIONS_AS_OBJECT ? {} : [];
result.each(function (e, idx) {
var solution = (expand_result ? _.expand(e) : e).valueOf();
var variable = vars[idx];
if (core.Settings.SOLUTIONS_AS_OBJECT) {
solutions[variable] = solution;
}
else
solutions.push([variable, solution]);
});
//done
return solutions;
};
// solve quad oder polynomials symbolically
var quad = function (c, b, a, plus_or_min) {
var plus_or_minus = plus_or_min === '-' ? 'subtract' : 'add';
var bsqmin4ac = _.subtract(_.pow(b.clone(), Symbol(2)), _.multiply(_.multiply(a.clone(), c.clone()), Symbol(4)))/*b^2 - 4ac*/;
var det = _.pow(bsqmin4ac, Symbol(0.5));
var retval = _.divide(_[plus_or_minus](b.clone().negate(), det), _.multiply(new Symbol(2), a.clone()));
return retval;
};
//http://math.stackexchange.com/questions/61725/is-there-a-systematic-way-of-solving-cubic-equations
var cubic = function (d_o, c_o, b_o, a_o) {
//convert everything to text
var a = a_o.text(), b = b_o.text(), c = c_o.text(), d = d_o.text();
var d0s = '({1})^2-3*({0})*({2})',
d0 = _.parse(format(d0s, a, b, c)),
Q = _.parse(format('((2*({1})^3-9*({0})*({1})*({2})+27*({0})^2*({3}))^2-4*(({1})^2-3*({0})*({2}))^3)^(1/2)', a, b, c, d)),
C = _.parse(format('((1/2)*(({4})+2*({1})^3-9*({0})*({1})*({2})+27*({0})^2*({3})))^(1/3)', a, b, c, d, Q));
//check if C equals 0
var scope = {};
//populate the scope object
variables(C).map(function (x) {
scope[x] = 1;
});
var Ct = core.Utils.block('PARSE2NUMBER', function () {
return _.parse(C, scope);
});
var Ct = core.Utils.block('PARSE2NUMBER', function () {
return _.parse(C, scope);
});
if (Number(d0) === 0 && Number(Ct) === 0) //negate Q such that C != 0
C = _.parse(format('((1/2)*(-({4})+2*({1})^3-9*({0})*({1})*({2})+27*({0})^2*({3})))^(1/3)', a, b, c, d, Q));
if (Number(d0) === 0 && Number(Ct) === 0) //negate Q such that C != 0
C = _.parse(format('((1/2)*(-({4})+2*({1})^3-9*({0})*({1})*({2})+27*({0})^2*({3})))^(1/3)', a, b, c, d, Q));
var xs = [
'-(b/(3*a))-C/(3*a)-(((b^2-3*a*c))/(3*a*C))',
'-(b/(3*a))+(C*(1+i*sqrt(3)))/(6*a)+((1-i*sqrt(3))*(b^2-3*a*c))/(6*a*C)'.replace(/i/g, core.Settings.IMAGINARY),
'-(b/(3*a))+(C*(1-i*sqrt(3)))/(6*a)+((1+i*sqrt(3))*(b^2-3*a*c))/(6*a*C)'.replace(/i/g, core.Settings.IMAGINARY)
];
var xs = [
'-(b/(3*a))-C/(3*a)-(((b^2-3*a*c))/(3*a*C))',
'-(b/(3*a))+(C*(1+i*sqrt(3)))/(6*a)+((1-i*sqrt(3))*(b^2-3*a*c))/(6*a*C)'.replace(/i/g, core.Settings.IMAGINARY),
'-(b/(3*a))+(C*(1-i*sqrt(3)))/(6*a)+((1+i*sqrt(3))*(b^2-3*a*c))/(6*a*C)'.replace(/i/g, core.Settings.IMAGINARY)
];
return xs.map(function (e, i) {
var o = {a: a_o.clone(), b: b_o.clone(), c: c_o.clone(), d: d_o.clone(), C: C.clone()};
return _.parse(e, o);
});
},
/**
* The quartic equation
* @param {Symbol} e
* @param {Symbol} d
* @param {Symbol} c
* @param {Symbol} b
* @param {Symbol} a
* @returns {Array}
*/
quartic: function (e, d, c, b, a) {
var scope = {};
core.Utils.arrayUnique(variables(a).concat(variables(b))
.concat(variables(c)).concat(variables(d)).concat(variables(e)))
.map(function (x) {
scope[x] = 1;
});
a = a.toString();
b = b.toString();
c = c.toString();
d = d.toString();
e = e.toString();
var p, q, D, D0, D1, Q, x1, x2, x3, x4;
/*var D = core.Utils.block('PARSE2NUMBER', function() {
return _.parse(format("256*({0})^3*({4})^3-192*({0})^2*({1})*({3})*({4})^2-128*({0})^2*({2})^2*({4})^2+144*({0})^2*({2})*({3})^2*({4})"+
"-27*({0})^2*({3})^4+144*({0})*({1})^2*({2})*({4})^2-6*({0})*({1})^2*({3})^2*({4})-80*({0})*({1})*({2})^2*({3})*({4})+18*({0})*({1})*({2})*({3})^3"+
"+16*({0})*({2})^4*({4})-4*({0})*({2})^3*({3})^2-27*({1})^4*({4})^2+18*({1})^3*({2})*({3})*({4})-4*({1})^3*({3})^3-4*({1})^2*({2})^3*({4})+({1})^2*({2})^2*({3})^2",
a, b, c, d, e), scope);
});*/
return xs.map(function (e, i) {
var o = {a: a_o.clone(), b: b_o.clone(), c: c_o.clone(), d: d_o.clone(), C: C.clone()};
return _.parse(e, o);
});
};
/* in progress */
//solve(x^4+x+0.1, x)
var quartic = function (e, d, c, b, a) {
var scope = {};
core.Utils.arrayUnique(variables(a).concat(variables(b))
.concat(variables(c)).concat(variables(d)).concat(variables(e)))
.map(function (x) {
scope[x] = 1;
p = _.parse(format("(8*({0})*({2})-3*({1})^2)/(8*({0})^2)", a, b, c)).toString(); //a, b, c
q = _.parse(format("(({1})^3-4*({0})*({1})*({2})+8*({0})^2*({3}))/(8*({0})^3)", a, b, c, d)).toString();//a, b, c, d, e
D0 = _.parse(format("12*({0})*({4})-3*({1})*({3})+({2})^2", a, b, c, d, e)).toString(); //a, b, c, d, e
D1 = _.parse(format("2*({2})^3-9*({1})*({2})*({3})+27*({1})^2*({4})+27*({0})*({3})^2-72*({0})*({2})*({4})", a, b, c, d, e)).toString(); //a, b, c, d, e
Q = _.parse(format("((({1})+(({1})^2-4*({0})^3)^(1/2))/2)^(1/3)", D0, D1)).toString(); //D0, D1
S = _.parse(format("(1/2)*(-(2/3)*({1})+(1/(3*({0}))*(({2})+(({3})/({2})))))^(1/2)", a, p, Q, D0)).toString(); //a, p, Q, D0
x1 = _.parse(format("-(({1})/(4*({0})))-({4})+(1/2)*sqrt(-4*({4})^2-2*({2})+(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
x2 = _.parse(format("-(({1})/(4*({0})))-({4})-(1/2)*sqrt(-4*({4})^2-2*({2})+(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
x3 = _.parse(format("-(({1})/(4*({0})))+({4})+(1/2)*sqrt(-4*({4})^2-2*({2})-(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
x4 = _.parse(format("-(({1})/(4*({0})))+({4})-(1/2)*sqrt(-4*({4})^2-2*({2})-(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
return [x1, x2, x3, x4];
},
/**
* Breaks the equation up in its factors and tries to solve the smaller parts
* @param {Symbol} symbol
* @param {String} solve_for
* @returns {Array}
*/
divideAndConquer: function (symbol, solve_for) {
var sols = [];
//see if we can solve the factors
var factors = core.Algebra.Factor.factor(symbol);
if (factors.group === CB) {
factors.each(function (x) {
x = Symbol.unwrapPARENS(x);
sols = sols.concat(solve(x, solve_for));
});
a = a.toString();
b = b.toString();
c = c.toString();
d = d.toString();
e = e.toString();
var p, q, D, D0, D1, Q, x1, x2, x3, x4;
/*var D = core.Utils.block('PARSE2NUMBER', function() {
return _.parse(format("256*({0})^3*({4})^3-192*({0})^2*({1})*({3})*({4})^2-128*({0})^2*({2})^2*({4})^2+144*({0})^2*({2})*({3})^2*({4})"+
"-27*({0})^2*({3})^4+144*({0})*({1})^2*({2})*({4})^2-6*({0})*({1})^2*({3})^2*({4})-80*({0})*({1})*({2})^2*({3})*({4})+18*({0})*({1})*({2})*({3})^3"+
"+16*({0})*({2})^4*({4})-4*({0})*({2})^3*({3})^2-27*({1})^4*({4})^2+18*({1})^3*({2})*({3})*({4})-4*({1})^3*({3})^3-4*({1})^2*({2})^3*({4})+({1})^2*({2})^2*({3})^2",
a, b, c, d, e), scope);
});*/
p = _.parse(format("(8*({0})*({2})-3*({1})^2)/(8*({0})^2)", a, b, c)).toString(); //a, b, c
q = _.parse(format("(({1})^3-4*({0})*({1})*({2})+8*({0})^2*({3}))/(8*({0})^3)", a, b, c, d)).toString();//a, b, c, d, e
D0 = _.parse(format("12*({0})*({4})-3*({1})*({3})+({2})^2", a, b, c, d, e)).toString(); //a, b, c, d, e
D1 = _.parse(format("2*({2})^3-9*({1})*({2})*({3})+27*({1})^2*({4})+27*({0})*({3})^2-72*({0})*({2})*({4})", a, b, c, d, e)).toString(); //a, b, c, d, e
Q = _.parse(format("((({1})+(({1})^2-4*({0})^3)^(1/2))/2)^(1/3)", D0, D1)).toString(); //D0, D1
S = _.parse(format("(1/2)*(-(2/3)*({1})+(1/(3*({0}))*(({2})+(({3})/({2})))))^(1/2)", a, p, Q, D0)).toString(); //a, p, Q, D0
x1 = _.parse(format("-(({1})/(4*({0})))-({4})+(1/2)*sqrt(-4*({4})^2-2*({2})+(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
x2 = _.parse(format("-(({1})/(4*({0})))-({4})-(1/2)*sqrt(-4*({4})^2-2*({2})+(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
x3 = _.parse(format("-(({1})/(4*({0})))+({4})+(1/2)*sqrt(-4*({4})^2-2*({2})-(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
x4 = _.parse(format("-(({1})/(4*({0})))+({4})-(1/2)*sqrt(-4*({4})^2-2*({2})-(({3})/({4})))", a, b, p, q, S)); //a, b, p, q, S
return [x1, x2, x3, x4];
};
//solve by divide and conquer
var divnconsolve = function (symbol, solve_for) {
var sols = [];
//see if we can solve the factors
var factors = core.Algebra.Factor.factor(symbol);
if (factors.group === CB) {
factors.each(function (x) {
x = Symbol.unwrapPARENS(x);
sols = sols.concat(solve(x, solve_for));
}
return sols;
},
/**
* Attempts to solve the equation assuming it's a polynomial with numeric coefficients
* @param {Symbol} eq
* @param {String} solve_for
* @returns {Array}
*/
csolve: function (eq, solve_for) {
return core.Utils.block('IGNORE_E', function () {
var f, p, pn, n, pf, r, theta, sr, sp, roots;
roots = [];
f = core.Utils.decompose_fn(eq, solve_for, true);
if (f.x.group === S) {
p = _.parse(f.x.power);
pn = Number(p);
n = _.pow(_.divide(f.b.negate(), f.a), p.invert());
pf = Symbol.toPolarFormArray(n);
r = pf[0];
theta = pf[1];
sr = r.toString();
sp = p.toString();
var k, root, str;
for (var i = 0; i < pn; i++) {
k = i;
str = format('({0})*e^(2*{1}*pi*{2}*{3})', sr, k, p, core.Settings.IMAGINARY);
root = _.parse(str);
roots.push(root);
}
}
return roots;
}, true);
},
/**
* Generates starting points for the Newton solver given an expression at zero.
* It beings by check if zero is a good point and starts expanding by a provided step size.
* Builds on the fact that if the sign changes over an interval then a zero
* must exist on that interval
* @param {Symbol} symbol
* @param {Number} step
* @returns {Array}
*/
getPoints: function (symbol, step) {
step = step || 0.01;
var f = build(symbol);
var start = Math.round(f(0)),
last = f(start),
last_sign = last / Math.abs(last),
points = [],
rside = core.Settings.ROOTS_PER_SIDE, // the max number of roots on right side
lside = rside * 2 + 1; // the max number of roots on left side
// check around the starting point
points.push(Math.floor(start / 2)); //half way from zero might be a good start
points.push(Math.abs(start)); //|f(0)| could be a good start
points.push(start);//|f(0)| could be a good start
//adjust for log. A good starting point to include for log is 0.1
symbol.each(function (x) {
if (x.containsFunction('log'))
points.push(0.1);
});
}
return sols;
};
// Possible issue #1. If the step size exceeds the zeros then they'll be missed. Consider the case
// where the function dips to negative and then back the positive with a step size of 0.1. The function
// will miss the zeros because it will jump right over it. Think of a case where this can happen.
for (var i = start; (i) < core.Settings.SOLVE_RADIUS; i++) {
var val = f(i * step),
sign = val / Math.abs(val);
if (isNaN(val) || !isFinite(val) || points.length > rside) {
break;
}
//compare the signs. The have to be different if they cross a zero
if (sign !== last_sign) {
points.push((i - 1) / 2); //take note of the possible zero location
}
last_sign = sign;
}
var csolve = function (symbol, solve_for) {
return core.Utils.block('IGNORE_E', function () {
var f, p, pn, n, pf, r, theta, sr, sp, roots;
roots = [];
f = core.Utils.decompose_fn(symbol, solve_for, true);
if (f.x.group === S) {
p = _.parse(f.x.power);
pn = Number(p);
n = _.pow(_.divide(f.b.negate(), f.a), p.invert());
pf = Symbol.toPolarFormArray(n);
r = pf[0];
theta = pf[1];
sr = r.toString();
sp = p.toString();
var k, root, str;
for (var i = 0; i < pn; i++) {
k = i;
str = format('({0})*e^(2*{1}*pi*{2}*{3})', sr, k, p, core.Settings.IMAGINARY);
root = _.parse(str);
roots.push(root);
//check the other side
for (var i = start - 1; i > -core.Settings.SOLVE_RADIUS; i--) {
var val = f(i),
sign = val / Math.abs(val);
if (isNaN(val) || !isFinite(val) || points.length > lside)
break;
//compare the signs. The have to be different if they cross a zero
if (sign !== last_sign)
points.push((i - 1) / 2); //take note of the possible zero location
last_sign = sign;
}
return points;
},
Newton: function (point, f, fp) {
var maxiter = core.Settings.MAX_NEWTON_ITERATIONS,
iter = 0;
//first try the point itself. If it's zero viola. We're done
var x0 = point, x;
do {
var fx0 = f(x0); //store the result of the function
//if the value is zero then we're done because 0 - (0/d f(x0)) = 0
if (x0 === 0 && fx0 === 0) {
x = 0;
break;
}
iter++;
if (iter > maxiter)
return; //naximum iterations reached
x = x0 - fx0 / fp(x0);
var e = Math.abs(x - x0);
x0 = x;
}
return roots;
}, true);
};
while (e > Number.EPSILON)
var polysolve = function (EQ, solve_for) {
solve_for = solve_for.toString();
var eq = core.Utils.isSymbol(EQ) ? EQ : toLHS(EQ);
var factors = _A.Factor.factor(eq);
var solutions = [];
factors.each(function (x) {
var sols = solve(x.arg ? x.args[0] : x, solve_for).map(function (a) {
solutions.push(a);
});
});
return new core.Vector(solutions);
};
return x;
},
rewrite: function (rhs, lhs, for_variable) {
lhs = lhs || new Symbol(0);
if(rhs.isComposite() && rhs.isLinear()) {
//try to isolate the square root
//container for the square roots
var sqrts = [];
//all else
var rem = [];
rhs.each(function(x) {
x = x.clone();
if(x.fname === 'sqrt' && x.contains(for_variable)) {
sqrts.push(x);
}
else {
rem.push(x);
}
}, true);
var get_points = function (symbol, step) {
step = step || 0.01;
var f = build(symbol);
var start = Math.round(f(0)),
last = f(start),
last_sign = last / Math.abs(last),
points = [],
rside = core.Settings.ROOTS_PER_SIDE, // the max number of roots on right side
lside = rside * 2 + 1; // the max number of roots on left side
// check around the starting point
points.push(Math.floor(start / 2)); //half way from zero might be a good start
points.push(Math.abs(start)); //|f(0)| could be a good start
points.push(start);//|f(0)| could be a good start
//adjust for log. A good starting point to include for log is 0.1
symbol.each(function (x) {
if (x.containsFunction('log'))
points.push(0.1);
});
// Possible issue #1. If the step size exceeds the zeros then they'll be missed. Consider the case
// where the function dips to negative and then back the positive with a step size of 0.1. The function
// will miss the zeros because it will jump right over it. Think of a case where this can happen.
for (var i = start; (i) < core.Settings.SOLVE_RADIUS; i++) {
var val = f(i * step),
sign = val / Math.abs(val);
if (isNaN(val) || !isFinite(val) || points.length > rside) {
break;
if(sqrts.length === 1) {
//move the remainder to the RHS
lhs = _.expand(_.pow(_.subtract(lhs, core.Utils.arraySum(rem)), new Symbol(2)));
//square both sides
rhs = _.expand(_.pow(Symbol.unwrapSQRT(sqrts[0]), new Symbol(2)));
}
}
//compare the signs. The have to be different if they cross a zero
if (sign !== last_sign) {
points.push((i - 1) / 2); //take note of the possible zero location
else {
rhs = Symbol.unwrapSQRT(_.expand(rhs)); //expand the term expression go get rid of quotients when possible
}
last_sign = sign;
}
var c = 0, //a counter to see if we have all terms with the variable
l = rhs.length;
//try to rewrite the whole thing
if (rhs.group === CP && rhs.contains(for_variable) && rhs.isLinear()) {
rhs.distributeMultiplier();
var t = new Symbol(0);
//first bring all the terms containing the variable to the lhs
rhs.each(function (x) {
if (x.contains(for_variable)) {
c++;
t = _.add(t, x.clone());
}
else
lhs = _.subtract(lhs, x.clone());
});
rhs = t;
//check the other side
for (var i = start - 1; i > -core.Settings.SOLVE_RADIUS; i--) {
var val = f(i),
sign = val / Math.abs(val);
if (isNaN(val) || !isFinite(val) || points.length > lside)
break;
//compare the signs. The have to be different if they cross a zero
if (sign !== last_sign)
points.push((i - 1) / 2); //take note of the possible zero location
last_sign = sign;
}
return points;
};
//Newton's iteration
var Newton = function (point, f, fp) {
var maxiter = 200,
iter = 0;
//first try the point itself. If it's zero viola. We're done
var x0 = point, x;
do {
var fx0 = f(x0); //store the result of the function
//if the value is zero then we're done because 0 - (0/d f(x0)) = 0
if (x0 === 0 && fx0 === 0) {
x = 0;
break;
//if not all the terms contain the variable so it's in the form
//a*x^2+x
if (c !== l) {
return __.rewrite(rhs, lhs, for_variable);
}
else {
return [rhs, lhs];
}
}
iter++;
if (iter > maxiter)
return; //naximum iterations reached
else if (rhs.group === CB && rhs.contains(for_variable) && rhs.isLinear()) {
if (rhs.multiplier.lessThan(0)) {
rhs.multiplier = rhs.multiplier.multiply(new core.Frac(-1));
lhs.multiplier = lhs.multiplier.multiply(new core.Frac(-1));
}
if (lhs.equals(0))
return new Symbol(0);
else {
var t = new Symbol(1);
rhs.each(function (x) {
if (x.contains(for_variable))
t = _.multiply(t, x.clone());
else
lhs = _.divide(lhs, x.clone());
});
rhs = t;
return __.rewrite(rhs, lhs, for_variable);
x = x0 - fx0 / fp(x0);
var e = Math.abs(x - x0);
x0 = x;
}
}
else if (!rhs.isLinear() && rhs.contains(for_variable)) {
var p = _.parse(rhs.power.clone().invert());
rhs = _.pow(rhs, p.clone());
lhs = _.pow(_.expand(lhs), p.clone());
return __.rewrite(rhs, lhs, for_variable);
}
else if (rhs.group === FN || rhs.group === S || rhs.group === PL) {
return [rhs, lhs];
}
}
while (e > Number.EPSILON)
};
return x;
};
/*

@@ -534,3 +862,4 @@ *

var solve = function (eqns, solve_for, solutions) {
//make preparations if it's an Equation
if (eqns instanceof Equation) {

@@ -556,3 +885,3 @@ //if it's zero then we're done

if (isArray(eqns)) {
return sys_solve.apply(undefined, arguments);
return __.solveSystem.apply(undefined, arguments);
}

@@ -563,5 +892,40 @@ //parse out functions. Fix for issue #300

solutions = solutions || [];
//mark existing solutions as not to have duplicates
var existing = {};
//Is usued to add solutions to set.
//TODO: Set is now implemented and should be utilized
var add_to_result = function (r, has_trig) {
var r_is_symbol = isSymbol(r);
if (r === undefined || typeof r === 'number' && isNaN(r))
return;
if (isArray(r)) {
r.map(function(sol) {
add_to_result(sol);
});
}
else {
if (r.valueOf() !== 'null') {
if (!r_is_symbol)
r = _.parse(r);
//try to convert the number to multiples of pi
if (core.Settings.make_pi_conversions && has_trig) {
var temp = _.divide(r.clone(), new Symbol(Math.PI)),
m = temp.multiplier,
a = Math.abs(m.num),
b = Math.abs(m.den);
if (a < 10 && b < 10)
r = _.multiply(temp, new Symbol('pi'));
}
//convert to a string so we can mark it as a known solution
var r_str = r.toString();
if (!existing[r_str])
solutions.push(r); /*NO*/
//mark the answer as seen
existing[r_str] = true;
}
}
};
//maybe we get lucky
if (eqns.group === S && eqns.contains(solve_for)) {
solutions.push(new Symbol(0));
add_to_result(new Symbol(0));
return solutions;

@@ -582,56 +946,4 @@ }

}
var existing = {}, //mark existing solutions as not to have duplicates
add_to_result = function (r, has_trig) {
var r_is_symbol = isSymbol(r);
if (r === undefined || typeof r === 'number' && isNaN(r))
return;
if (isArray(r))
solutions = solutions.concat(r);
else {
if (r.valueOf() !== 'null') {
if (!r_is_symbol)
r = _.parse(r);
//try to convert the number to multiples of pi
if (core.Settings.make_pi_conversions && has_trig) {
var temp = _.divide(r.clone(), new Symbol(Math.PI)),
m = temp.multiplier,
a = Math.abs(m.num),
b = Math.abs(m.den);
if (a < 10 && b < 10)
r = _.multiply(temp, new Symbol('pi'));
}
//convert to a string so we can mark it as a known solution
var r_str = r.toString();
if (!existing[r_str])
solutions.push(r);
//mark the answer as seen
existing[r_str] = true;
}
}
};
//gets points around which to solve. It does that because it builds on the principle that if
//the sign changes over an interval then there must be a zero on that interval
var attempt_Newton = function (symbol) {
var has_trig = symbol.hasTrig();
// we get all the points where a possible zero might exist
var points1 = get_points(symbol, 0.1);
var points2 = get_points(symbol, 0.05);
var points3 = get_points(symbol, 0.01);
var points = core.Utils.arrayUnique(points1.concat(points2).concat(points3)),
l = points.length;
//compile the function and the derivative of the function
var f = build(symbol.clone());
var d = _C.diff(symbol.clone());
var fp = build(d);
for (var i = 0; i < l; i++) {
var point = points[i];
add_to_result(Newton(point, f, fp), has_trig);
}
solutions.sort();
};
var eq = core.Utils.isSymbol(eqns) ? eqns : toLHS(eqns),
var eq = core.Utils.isSymbol(eqns) ? eqns : __.toLHS(eqns),
vars = core.Utils.variables(eq), //get a list of all the variables

@@ -697,62 +1009,3 @@ numvars = vars.length;//how many variables are we dealing with

};
//rewrites equations/expression in simpler form
var rewrite = function (rhs, lhs) {
lhs = lhs || new Symbol(0);
rhs = Symbol.unwrapSQRT(_.expand(rhs)); //expand the term expression go get rid of quotients when possible
var c = 0, //a counter to see if we have all terms with the variable
l = rhs.length;
//try to rewrite the whole thing
if (rhs.group === CP && rhs.contains(solve_for) && rhs.isLinear()) {
rhs.distributeMultiplier();
var t = new Symbol(0);
//first bring all the terms containing the variable to the lhs
rhs.each(function (x) {
if (x.contains(solve_for)) {
c++;
t = _.add(t, x.clone());
}
else
lhs = _.subtract(lhs, x.clone());
});
rhs = t;
//if not all the terms contain the variable so it's in the form
//a*x^2+x
if (c !== l)
return rewrite(rhs, lhs);
else {
return [rhs, lhs];
}
}
else if (rhs.group === CB && rhs.contains(solve_for) && rhs.isLinear()) {
if (rhs.multiplier.lessThan(0)) {
rhs.multiplier = rhs.multiplier.multiply(new core.Frac(-1));
lhs.multiplier = lhs.multiplier.multiply(new core.Frac(-1));
}
if (lhs.equals(0))
return new Symbol(0);
else {
var t = new Symbol(1);
rhs.each(function (x) {
if (x.contains(solve_for))
t = _.multiply(t, x.clone());
else
lhs = _.divide(lhs, x.clone());
});
rhs = t;
return rewrite(rhs, lhs);
}
}
else if (!rhs.isLinear() && rhs.contains(solve_for)) {
var p = _.parse(rhs.power.clone().invert());
rhs = _.pow(rhs, p.clone());
lhs = _.pow(_.expand(lhs), p.clone());
return rewrite(rhs, lhs);
}
else if (rhs.group === FN || rhs.group === S || rhs.group === PL) {
return [rhs, lhs];
}
};
//separate the equation

@@ -837,8 +1090,12 @@ var separate = function (eq) {

else if (deg === 2) {
add_to_result(_.expand(quad.apply(undefined, coeffs)));
coeffs.push('-');
add_to_result(_.expand(quad.apply(undefined, coeffs)));
add_to_result(_.expand(__.quad.apply(undefined, coeffs)));
}
else if (deg === 3)
add_to_result(cubic.apply(undefined, coeffs));
else if (deg === 3) {
//first try to factor and solve
var solutions = solve(core.Algebra.Factor.factor(eqns));
if(solutions.length > 0)
add_to_result(solutions);
else
add_to_result(__.cubic.apply(undefined, coeffs));
}
else {

@@ -860,5 +1117,26 @@ /*

else {
//since it's not a polynomial then we'll try to look for a solution using Newton's method
//this is not a very broad search but takes the positions that something is better than nothing
attempt_Newton(eq);
try {
//Attempt Newton
//since it's not a polynomial then we'll try to look for a solution using Newton's method
//this is not a very broad search but takes the positions that something is better than nothing
var has_trig = eq.hasTrig();
// we get all the points where a possible zero might exist.
var points1 = __.getPoints(eq, 0.1);
var points2 = __.getPoints(eq, 0.05);
var points3 = __.getPoints(eq, 0.01);
var points = core.Utils.arrayUnique(points1.concat(points2).concat(points3)),
l = points.length;
//compile the function and the derivative of the function
var f = build(eq.clone());
var d = _C.diff(eq.clone());
var fp = build(d);
for (var i = 0; i < l; i++) {
var point = points[i];
add_to_result(__.Newton(point, f, fp), has_trig);
}
solutions.sort();
}
catch(e) {
;
}
}

@@ -891,16 +1169,14 @@ }

case 2:
add_to_result(quad.apply(undefined, coeffs));
coeffs.push('-');
add_to_result(quad.apply(undefined, coeffs));
add_to_result(__.quad.apply(undefined, coeffs));
break;
case 3:
add_to_result(cubic.apply(undefined, coeffs));
add_to_result(__.cubic.apply(undefined, coeffs));
break;
case 4:
add_to_result(quartic.apply(undefined, coeffs));
add_to_result(__.quartic.apply(undefined, coeffs));
break;
default:
add_to_result(csolve(eq, solve_for));
add_to_result(__.csolve(eq, solve_for));
if (solutions.length === 0)
add_to_result(divnconsolve(eq, solve_for));
add_to_result(__.divideAndConquer(eq, solve_for));
}

@@ -914,3 +1190,3 @@ }

try {
var rw = rewrite(eq);
var rw = __.rewrite(eq, null, solve_for);
var lhs = rw[0];

@@ -920,24 +1196,38 @@ var rhs = rw[1];

if (lhs.fname === 'abs') {
solutions.push(rhs.clone());
solutions.push(rhs.negate());
add_to_result([rhs.clone(), rhs.negate()]);
}
else if(lhs.fname === 'sin') {
//asin
solutions.push(inverse_function('asin', lhs, rhs));
add_to_result(inverse_function('asin', lhs, rhs));
}
else if(lhs.fname === 'cos') {
//asin
solutions.push(inverse_function('acos', lhs, rhs));
add_to_result(inverse_function('acos', lhs, rhs));
}
else if(lhs.fname === 'tan') {
//asin
solutions.push(inverse_function('atan', lhs, rhs));
add_to_result(inverse_function('atan', lhs, rhs));
}
else if(lhs.fname === 'log') {
//asin
solutions.push(_.pow(new Symbol('e'), _.divide(rhs, _.parse(lhs.multiplier))));
//ax+b comes back as [a, x, ax, b];
var parts = explode(lhs.args[0], solve_for);
//check if x is by itself
var x = parts[1];
if(x.group === S) {
rhs = _.divide(_.subtract(_.pow(new Symbol('e'), _.divide(rhs, _.parse(lhs.multiplier))), parts[3]), parts[0]);
var eq = new Equation(x, rhs).toLHS();
add_to_result(solve(eq, solve_for));
}
}
else
solutions.push(_.subtract(lhs, rhs));
add_to_result(_.subtract(lhs, rhs));
}
else {
var neq = new Equation(lhs, rhs).toLHS(); //create a new equation
if(neq.equals(eq))
throw new Error('Stopping. No stop condition exists');
add_to_result(solve(neq, solve_for));
}
}

@@ -950,3 +1240,3 @@ catch (error) {

if (eq.group === CB)
solutions.push(0);
add_to_result(0);
else if (eq.group === CP) {

@@ -961,3 +1251,3 @@ var separated = separate(eq);

var p = lhs.power.clone().invert();
solutions.push(_.pow(rhs, p));
add_to_result(_.pow(rhs, p));
}

@@ -981,32 +1271,4 @@ }

};
core.Expression.prototype.solveFor = function (x) {
return solve(core.Utils.isSymbol(this.symbol) ? this.symbol : this.symbol.toLHS(), x).map(function (x) {
return new core.Expression(x);
});
};
core.Expression.prototype.expand = function () {
if (this.symbol instanceof Equation) {
var clone = this.symbol.clone();
clone.RHS = _.expand(clone.RHS);
clone.LHS = _.expand(clone.LHS);
return new core.Expression(clone);
}
return new core.Expression(_.expand(this.symbol));
};
core.Expression.prototype.variables = function () {
if (this.symbol instanceof Equation)
return core.Utils.arrayUnique(variables(this.symbol.LHS).concat(variables(this.symbol.RHS)));
return variables(this.symbol);
};
var setEq = function (a, b) {
return _.equals(a, b);
};
//link the Equation class back to the core
core.Equation = Equation;
//Register the functions for external use
nerdamer.register([

@@ -1013,0 +1275,0 @@ {

@@ -0,0 +0,0 @@ /* global expect */

@@ -0,0 +0,0 @@ /* global expect */

@@ -257,2 +257,6 @@ /* global expect */

},
{
given: 'limit(cos(sin(x)+2), x, Infinity)',
expected: '[cos(1),cos(3)]'
},
/*

@@ -259,0 +263,0 @@ {

@@ -63,3 +63,3 @@ /* global expect */

given: 'solve(-5 sqrt(14)x-14x^2 sqrt(83)-10=0,x)',
expected: '[(-1/28)*sqrt(-560*sqrt(83)+350)*sqrt(83)^(-1)+(-5/28)*sqrt(14)*sqrt(83)^(-1),(-5/28)*sqrt(14)*sqrt(83)^(-1)+(1/28)*sqrt(-560*sqrt(83)+350)*sqrt(83)^(-1)]'
expected: '[(-1/28)*(5*sqrt(14)+sqrt(-560*sqrt(83)+350))*sqrt(83)^(-1),(-1/28)*(-sqrt(-560*sqrt(83)+350)+5*sqrt(14))*sqrt(83)^(-1)]'
},

@@ -110,7 +110,4 @@ {

given: 'solve(sqrt(97)x^2-sqrt(13)x+sqrt(14)x+sqrt(43)x^2+sqrt(3)*sqrt(101)=0,x)',
expected: '[(-1/2)*(sqrt(43)+sqrt(97))^(-1)*sqrt(14)+(1/2)*(sqrt(43)+sqrt(97))^(-1)'+
'*sqrt((-sqrt(13)+sqrt(14))^2-4*(sqrt(43)+sqrt(97))*sqrt(101)*sqrt(3))+(1/2)*'+
'(sqrt(43)+sqrt(97))^(-1)*sqrt(13),(-1/2)*(sqrt(43)+sqrt(97))^(-1)*sqrt((-sqrt(13)'+
'+sqrt(14))^2-4*(sqrt(43)+sqrt(97))*sqrt(101)*sqrt(3))+(-1/2)*(sqrt(43)+sqrt(97))^(-1)'+
'*sqrt(14)+(1/2)*(sqrt(43)+sqrt(97))^(-1)*sqrt(13)]'
expected: '[(1/2)*(-sqrt(14)+sqrt((-sqrt(13)+sqrt(14))^2-4*(sqrt(43)+sqrt(97))*sqrt(101)*sqrt(3))+sqrt(13))*(sqrt(43)+sqrt(97))^(-1),'+
'(1/2)*(-sqrt((-sqrt(13)+sqrt(14))^2-4*(sqrt(43)+sqrt(97))*sqrt(101)*sqrt(3))-sqrt(14)+sqrt(13))*(sqrt(43)+sqrt(97))^(-1)]'
},

@@ -154,2 +151,10 @@ {

expected: '[1]'
},
{
given: 'solve((1/2)*sqrt(-4*x+4*y)-2+y, y)',
expected: '[(-1/2)*(-5+sqrt(-4*x+9)),(-1/2)*(-5-sqrt(-4*x+9))]'
},
{
given: 'solve(log(a*x-c)-b=21, x)',
expected: '[-(-c-e^(21+b))*a^(-1)]'
}

@@ -186,2 +191,15 @@ ];

expected: '(1/2)*(1+sqrt(-15-4*y)),(1/2)*(-sqrt(-15-4*y)+1)'
},
//non-linear systems
{
given: ['x+y=3','y^3-x=7'],
expected: 'x,1,y,2'
},
{
given: ['x^2+y=3','x+y+z=6', 'z^2-y=7'],
expected: 'x,1,y,2,z,3'
},
{
given: ['x*y-cos(z)=-3', '3*z^3-y^2+1=12', '3*sin(x)*cos(y)-x^3=-4'],
expected: 'x,1.10523895006979,y,-2.98980336936266,z,1.88015428627437'
}

@@ -188,0 +206,0 @@

@@ -0,0 +0,0 @@ /* global expect */

@@ -0,0 +0,0 @@ 'use strict';

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc