nerdamer-ts
Version:
javascript light-weight symbolic math expression evaluator
156 lines • 7.06 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sqrt = void 0;
const Symbol_1 = require("../../../Types/Symbol");
const Groups_1 = require("../../../Types/Groups");
const Settings_1 = require("../../../Settings");
const decimal_js_1 = __importDefault(require("decimal.js"));
const Complex_1 = require("../../Complex");
const multiply_1 = require("../operations/multiply");
const Frac_1 = require("../../../Types/Frac");
const Utils_1 = require("../../../Core/Utils");
const Math2_1 = require("../../Math2");
const pfactor_1 = require("./pfactor");
const pow_1 = require("../operations/pow");
const divide_1 = require("../operations/divide");
const Parser_1 = require("../../../Parser/Parser");
/**
* The square root function
* @param {Symbol} symbol
* @returns {Symbol}
*/
function sqrt(symbol) {
if (!(0, Utils_1.isSymbol)(symbol)) {
symbol = (0, Parser_1.parse)(symbol);
}
// Exit early for Groups.EX
if (symbol.group === Groups_1.Groups.EX) {
return (0, Symbol_1.symfunction)(Settings_1.Settings.SQRT, [symbol]);
}
if (symbol.fname === '' && symbol.power.equals(1))
symbol = symbol.args[0];
var is_negative = symbol.multiplier.sign() < 0;
if (Settings_1.Settings.PARSE2NUMBER) {
if (symbol.isConstant() && !is_negative) {
return new Symbol_1.Symbol(decimal_js_1.default.sqrt(symbol.multiplier.toDecimal()));
}
else if (symbol.isImaginary()) {
return Complex_1.Complex.sqrt(symbol);
}
else if (symbol.group === Groups_1.Groups.S) {
return (0, Symbol_1.symfunction)('sqrt', [symbol]);
}
}
var img, retval, isConstant = symbol.isConstant();
if (symbol.group === Groups_1.Groups.CB && symbol.isLinear()) {
var m = sqrt(new Symbol_1.Symbol(symbol.multiplier));
for (var s in symbol.symbols) {
var x = symbol.symbols[s];
m = (0, multiply_1.multiply)(m, sqrt(x));
}
retval = m;
}
//if the symbol is already sqrt then it's that symbol^(1/4) and we can unwrap it
else if (symbol.fname === Settings_1.Settings.SQRT) {
var s = symbol.args[0];
var ms = symbol.multiplier;
s.setPower(symbol.power.multiply(new Frac_1.Frac(0.25)));
retval = s;
//grab the multiplier
if (!ms.equals(1))
retval = (0, multiply_1.multiply)(sqrt((0, Parser_1.parse)(ms)), retval);
}
//if the symbol is a fraction then we don't keep can unwrap it. For instance
//no need to keep sqrt(x^(1/3))
else if (!symbol.power.isInteger()) {
symbol.setPower(symbol.power.multiply(new Frac_1.Frac(0.5)));
retval = symbol;
}
else if (symbol.multiplier < 0 && symbol.group === Groups_1.Groups.S) {
var a = (0, Parser_1.parse)(symbol.multiplier).negate();
var b = (0, Parser_1.parse)(symbol).toUnitMultiplier().negate();
retval = (0, multiply_1.multiply)((0, Symbol_1.symfunction)(Settings_1.Settings.SQRT, [b]), sqrt(a));
}
else {
//Related to issue #401. Since sqrt(a)*sqrt(b^-1) relates in issues, we'll change the form
//to sqrt(a)*sqrt(b)^1 for better simplification
//the sign of the power
var sign = symbol.power.sign();
//remove the sign
symbol.power = symbol.power.abs();
//if the symbols is imagary then we place in the imaginary part. We'll return it
//as a product
if (isConstant && symbol.multiplier.lessThan(0)) {
img = Symbol_1.Symbol.imaginary();
symbol.multiplier = symbol.multiplier.abs();
}
var q = symbol.multiplier.toDecimal(), qa = Math.abs(q), t = Math.sqrt(qa);
var m;
//it's a perfect square so take the square
if ((0, Utils_1.isInt)(t)) {
m = new Symbol_1.Symbol(t);
}
else if ((0, Utils_1.isInt)(q)) {
var factors = Math2_1.Math2.ifactor(q);
var tw = 1;
for (var x in factors) {
var n = factors[x], nn = (n - (n % 2)); //get out the whole numbers
if (nn) { //if there is a whole number ...
var w = Math.pow(x, nn);
tw *= Math.pow(x, nn / 2); //add to total wholes
q /= w; //reduce the number by the wholes
}
}
m = (0, multiply_1.multiply)((0, Symbol_1.symfunction)(Settings_1.Settings.SQRT, [new Symbol_1.Symbol(q)]), new Symbol_1.Symbol(tw));
}
else {
//reduce the numerator and denominator using prime factorization
var c = [new Symbol_1.Symbol(symbol.multiplier.num), new Symbol_1.Symbol(symbol.multiplier.den)];
var r = [new Symbol_1.Symbol(1), new Symbol_1.Symbol(1)];
var sq = [new Symbol_1.Symbol(1), new Symbol_1.Symbol(1)];
for (var i = 0; i < 2; i++) {
var n = c[i];
//get the prime factors and loop through each.
(0, pfactor_1.pfactor)(n).each(function (x) {
x = Symbol_1.Symbol.unwrapPARENS(x);
var b = x.clone().toLinear();
var p = Number(x.power);
//We'll consider it safe to use the native Number since 2^1000 is already a pretty huge number
var rem = p % 2; //get the remainder. This will be 1 if 3 since sqrt(n^2) = n where n is positive
var w = (p - rem) / 2; //get the whole numbers of n/2
r[i] = (0, multiply_1.multiply)(r[i], (0, pow_1.pow)(b, new Symbol_1.Symbol(w)));
sq[i] = (0, multiply_1.multiply)(sq[i], sqrt((0, pow_1.pow)(b, new Symbol_1.Symbol(rem))));
});
}
m = (0, divide_1.divide)((0, multiply_1.multiply)(r[0], sq[0]), (0, multiply_1.multiply)(r[1], sq[1]));
}
//strip the multiplier since we already took the sqrt
symbol = symbol.toUnitMultiplier(true);
//if the symbol is one just return one and not the sqrt function
if (symbol.isOne()) {
retval = symbol;
}
else if ((0, Utils_1.even)(symbol.power.toString())) {
//just raise it to the 1/2
retval = (0, pow_1.pow)(symbol.clone(), new Symbol_1.Symbol(0.5));
}
else {
retval = (0, Symbol_1.symfunction)(Settings_1.Settings.SQRT, [symbol]);
}
//put back the sign that was removed earlier
if (sign < 0)
retval.power.negate();
if (m)
retval = (0, multiply_1.multiply)(m, retval);
if (img)
retval = (0, multiply_1.multiply)(img, retval);
}
if (is_negative && Settings_1.Settings.PARSE2NUMBER)
return (0, Parser_1.parse)(retval);
return retval;
}
exports.sqrt = sqrt;
//# sourceMappingURL=sqrt.js.map