UNPKG

nerdamer-ts

Version:

javascript light-weight symbolic math expression evaluator

156 lines 7.06 kB
"use strict"; 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