nerdamer-ts
Version:
javascript light-weight symbolic math expression evaluator
255 lines • 8.26 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Expression = void 0;
const Settings_1 = require("../Settings");
const Build_1 = require("./Build");
const Text_1 = require("../Core/Text");
const LaTeX_1 = require("../LaTeX/LaTeX");
const Utils_1 = require("../Core/Utils");
const Core_1 = require("../Functions/Core");
const expand_1 = require("../Functions/Core/math/expand");
const Parser_1 = require("./Parser");
/**
* This is what nerdamer returns. It's sort of a wrapper around the symbol class and
* provides the user with some useful functions. If you want to provide the user with extra
* library functions then add them to this class's prototype.
* @param {Symbol} symbol
*/
class Expression {
constructor(symbol) {
//we don't want arrays wrapped
this.symbol = symbol;
}
/**
* Returns stored expression at index. For first index use 1 not 0.
* @param {number | string} expression_number
* @param {boolean} asType
*/
static getExpression(expression_number, asType = false) {
if (expression_number === 'last' || !expression_number)
expression_number = Expression.$EXPRESSIONS.length;
if (expression_number === 'first')
expression_number = 1;
let index = expression_number - 1, expression = Expression.$EXPRESSIONS[index];
return expression ? new Expression(expression) : expression;
}
/**
* Returns the text representation of the expression
* @param {String} opt - option of formatting numbers
* @param {Number} n The number of significant figures
* @returns {String}
*/
text(opt = 'decimals', n = 0) {
n = n || 19;
opt = opt || 'decimals';
if (this.symbol.text_)
return this.symbol.text_(opt);
return (0, Text_1.text)(this.symbol, opt, undefined, n);
}
/**
* Returns the latex representation of the expression
* @param {String} option - option for formatting numbers
* @returns {String}
*/
latex(option) {
if (this.symbol.latex)
return this.symbol.latex(option);
return LaTeX_1.LaTeX.latex(this.symbol, option);
}
valueOf() {
return this.symbol.valueOf();
}
/**
* Evaluates the expression and tries to reduce it to a number if possible.
* If an argument is given in the form of %{integer} it will evaluate that expression.
* Other than that it will just use it's own text and reparse
* @returns {Expression}
*/
evaluate() {
// Don't evaluate an empty vector
if ((0, Utils_1.isVector)(this.symbol) && this.symbol.dimensions() === 0) {
return this;
}
let first_arg = arguments[0], expression, idx = 1;
//Enable getting of expressions using the % so for example %1 should get the first expression
if (typeof first_arg === 'string') {
expression = (first_arg.charAt(0) === '%') ? Expression.getExpression(first_arg.substr(1)).text() : first_arg;
}
else if (first_arg instanceof Expression || (0, Utils_1.isSymbol)(first_arg)) {
expression = first_arg.text();
}
else {
expression = this.symbol.text();
idx--;
}
let subs = arguments[idx] || {};
return new Expression((0, Utils_1.block)('PARSE2NUMBER', function () {
return (0, Parser_1.parse)(expression, subs);
}, true, this));
}
/**
* Converts a symbol to a JS function. Pass in an array of variables to use that order instead of
* the default alphabetical order
* @param vars {Array}
*/
buildFunction(vars) {
return Build_1.Build.build(this.symbol, vars);
}
/**
* Checks to see if the expression is just a plain old number
* @returns {boolean}
*/
isNumber() {
return (0, Utils_1.isNumericSymbol)(this.symbol);
}
/**
* Checks to see if the expression is infinity
* @returns {boolean}
*/
isInfinity() {
return Math.abs(this.symbol.multiplier) === Infinity;
}
/**
* Checks to see if the expression contains imaginary numbers
* @returns {boolean}
*/
isImaginary() {
return (0, Parser_1.evaluate)((0, Parser_1.parse)(this.symbol)).isImaginary();
}
/**
* Returns all the variables in the expression
* @returns {Array}
*/
variables() {
if (!(0, Utils_1.isSymbol)(this.symbol)) {
return [];
}
return this.symbol.variables();
}
/**
*
* @return {string}
*/
toString() {
try {
if (Array.isArray(this.symbol))
return '[' + this.symbol.toString() + ']';
return this.symbol.toString();
}
catch (e) {
return '';
}
}
//forces the symbol to be returned as a decimal
toDecimal(prec) {
Settings_1.Settings.precision = prec;
let dec = (0, Text_1.text)(this.symbol, 'decimals');
Settings_1.Settings.precision = undefined;
return dec;
}
//checks to see if the expression is a fraction
isFraction() {
return (0, Utils_1.isFraction)(this.symbol);
}
//checks to see if the symbol is a multivariate polynomial
isPolynomial() {
return this.symbol.isPoly();
}
//performs a substitution
sub(symbol, for_symbol) {
return new Expression(this.symbol.sub((0, Parser_1.parse)(symbol), (0, Parser_1.parse)(for_symbol)));
}
operation(otype, symbol) {
if (isExpression(symbol)) {
symbol = symbol.symbol;
}
else if (!(0, Utils_1.isSymbol)(symbol)) {
symbol = (0, Parser_1.parse)(symbol);
}
return new Expression(Parser_1.ParseDeps.parser.getAction(otype)(this.symbol.clone(), symbol.clone()));
}
add(symbol) {
return this.operation('add', symbol);
}
subtract(symbol) {
return this.operation('subtract', symbol);
}
multiply(symbol) {
return this.operation('multiply', symbol);
}
divide(symbol) {
return this.operation('divide', symbol);
}
pow(symbol) {
return this.operation('pow', symbol);
}
expand() {
return new Expression((0, expand_1.expand)(this.symbol));
}
each(callback, i) {
if (this.symbol.each)
this.symbol.each(callback, i);
else if (Array.isArray(this.symbol)) {
for (let i = 0; i < this.symbol.length; i++)
callback.call(this.symbol, this.symbol[i], i);
}
else
callback.call(this.symbol);
}
eq(value) {
if (!(0, Utils_1.isSymbol)(value))
value = (0, Parser_1.parse)(value);
try {
let d = (0, Core_1.subtract)(this.symbol.clone(), value);
return d.equals(0);
}
catch (e) {
return false;
}
}
lt(value) {
if (!(0, Utils_1.isSymbol)(value))
value = (0, Parser_1.parse)(value);
try {
let d = (0, Parser_1.evaluate)((0, Core_1.subtract)(this.symbol.clone(), value));
return d.lessThan(0);
}
catch (e) {
return false;
}
}
gt(value) {
if (!(0, Utils_1.isSymbol)(value))
value = (0, Parser_1.parse)(value);
try {
let d = (0, Parser_1.evaluate)((0, Core_1.subtract)(this.symbol.clone(), value));
return d.greaterThan(0);
}
catch (e) {
return false;
}
}
gte(value) {
return this.gt(value) || this.eq(value);
}
lte(value) {
return this.lt(value) || this.eq(value);
}
numerator() {
return new Expression(this.symbol.getNum());
}
denominator() {
return new Expression(this.symbol.getDenom());
}
hasFunction(f) {
return this.symbol.containsFunction(f);
}
contains(variable) {
return this.symbol.contains(variable);
}
toTeX(option) {
return this.latex(option);
}
}
exports.Expression = Expression;
//# sourceMappingURL=Expression.js.map