nerdamer-ts
Version:
javascript light-weight symbolic math expression evaluator
222 lines • 9.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Build = void 0;
const Math2_1 = require("../Functions/Math2");
const Frac_1 = require("../Types/Frac");
const Utils_1 = require("../Core/Utils");
const Symbol_1 = require("../Types/Symbol");
const Groups_1 = require("../Types/Groups");
const Parser_1 = require("./Parser");
exports.Build = {
dependencies: {
_rename: {
'Math2.factorial': 'factorial'
},
factorial: {
'Math2.gamma': Math2_1.Math2.gamma
},
gamma_incomplete: {
'Math2.factorial': Math2_1.Math2.factorial
},
Li: {
'Math2.Ei': Math2_1.Math2.Ei,
'Math2.bigLog': Math2_1.Math2.bigLog,
'Frac': Frac_1.Frac
},
Ci: {
'Math2.factorial': Math2_1.Math2.factorial
},
Ei: {
'Math2.factorial': Math2_1.Math2.factorial
},
Si: {
'Math2.factorial': Math2_1.Math2.factorial
},
Shi: {
'Math2.factorial': Math2_1.Math2.factorial
},
Chi: {
'isInt': Utils_1.isInt,
'nround': Utils_1.nround,
'Math2.num_integrate': Math2_1.Math2.num_integrate
},
factor: {
'Math2.ifactor': Math2_1.Math2.ifactor,
'Symbol': Symbol_1.Symbol
},
num_integrate: {
'Math2.simpson': Math2_1.Math2.simpson,
'nround': Utils_1.nround
},
fib: {
'even': Utils_1.even
}
},
/* Some functions need to be made numeric safe. Build checks if there's a
* reformat option and calls that instead when compiling the function string.
*/
reformat: {
// this simply extends the build function
diff: function (symbol, deps) {
var v = symbol.args[1].toString();
var f = 'var f = ' + exports.Build.build(symbol.args[0].toString(), [v]) + ';';
deps[1] += 'var diff = ' + Math2_1.Math2.diff.toString() + ';';
deps[1] += f;
return ['diff(f)(' + v + ')', deps];
}
},
getProperName: function (f) {
var map = {
continued_fraction: 'continuedFraction'
};
return map[f] || f;
},
// assumes that dependences are at max 2 levels
compileDependencies: function (f, deps) {
// grab the predefined dependiences
var dependencies = exports.Build.dependencies[f];
// the dependency string
var dep_string = deps && deps[1] ? deps[1] : '';
// the functions to be replaced
var replacements = deps && deps[0] ? deps[0] : {};
// loop through them and add them to the list
for (var x in dependencies) {
if (typeof dependencies[x] === 'object')
continue; // skip object
var components = x.split('.'); //Math.f becomes f
// if the function isn't part of an object then reference the function itself
dep_string += 'var ' + (components.length > 1 ? components[1] : components[0]) + '=' + dependencies[x] + ';';
replacements[x] = components.pop();
}
return [replacements, dep_string];
},
getArgsDeps: function (symbol, dependencies) {
var args = symbol.args;
for (var i = 0; i < args.length; i++) {
symbol.args[i].each(function (x) {
if (x.group === Groups_1.Groups.FN)
dependencies = exports.Build.compileDependencies(x.fname, dependencies);
});
}
return dependencies;
},
build: function (symbol, arg_array) {
symbol = (0, Utils_1.block)('PARSE2NUMBER', function () {
return (0, Parser_1.parse)(symbol);
}, true);
var args = symbol.variables();
var supplements = [];
var dependencies = [];
var ftext = function (symbol, xports) {
//Fix for #545 - Parentheses confuse build.
if (symbol.fname === '') {
symbol = Symbol_1.Symbol.unwrapPARENS(symbol);
}
xports = xports || [];
var c = [], group = symbol.group, prefix = '';
var ftext_complex = function (group) {
var d = group === Groups_1.Groups.CB ? '*' : '+', cc = [];
for (var x in symbol.symbols) {
var sym = symbol.symbols[x], ft = ftext(sym, xports)[0];
// wrap it in brackets if it's group PL or CP
if (sym.isComposite())
ft = (0, Utils_1.inBrackets)(ft);
cc.push(ft);
}
var retval = cc.join(d);
retval = retval && !symbol.multiplier.equals(1) ? (0, Utils_1.inBrackets)(retval) : retval;
return retval;
}, ftext_function = function (bn) {
var retval;
if (bn in Math)
retval = 'Math.' + bn;
else {
bn = exports.Build.getProperName(bn);
if (supplements.indexOf(bn) === -1) { // make sure you're not adding the function twice
//Math2 functions aren't part of the standard javascript
//Math library and must be exported.
xports.push('var ' + bn + ' = ' + Math2_1.Math2[bn].toString() + '; ');
supplements.push(bn);
}
retval = bn;
}
retval = retval + (0, Utils_1.inBrackets)(symbol.args.map(function (x) {
return ftext(x, xports)[0];
}).join(','));
return retval;
};
// the multiplier
if (group === Groups_1.Groups.N)
c.push(symbol.multiplier.toDecimal());
else if (symbol.multiplier.equals(-1))
prefix = '-';
else if (!symbol.multiplier.equals(1))
c.push(symbol.multiplier.toDecimal());
// the value
var value;
if (group === Groups_1.Groups.S || group === Groups_1.Groups.P)
value = symbol.value;
else if (group === Groups_1.Groups.FN) {
dependencies = exports.Build.compileDependencies(symbol.fname, dependencies);
dependencies = exports.Build.getArgsDeps(symbol, dependencies);
if (exports.Build.reformat[symbol.fname]) {
var components = exports.Build.reformat[symbol.fname](symbol, dependencies);
dependencies = components[1];
value = components[0];
}
else {
value = ftext_function(symbol.fname);
}
}
else if (group === Groups_1.Groups.EX) {
var pg = symbol.previousGroup;
if (pg === Groups_1.Groups.N || pg === Groups_1.Groups.S)
value = symbol.value;
else if (pg === Groups_1.Groups.FN) {
value = ftext_function(symbol.fname);
dependencies = exports.Build.compileDependencies(symbol.fname, dependencies);
dependencies = exports.Build.getArgsDeps(symbol, dependencies);
}
else
value = ftext_complex(symbol.previousGroup);
}
else {
value = ftext_complex(symbol.group);
}
if (symbol.group !== Groups_1.Groups.N && !symbol.power.equals(1)) {
var pow = ftext((0, Parser_1.parse)(symbol.power));
xports.push(pow[1]);
value = 'Math.pow' + (0, Utils_1.inBrackets)(value + ',' + pow[0]);
}
if (value)
c.push(prefix + value);
return [c.join('*'), xports.join('').replace(/\n+\s+/g, ' ')];
};
if (arg_array) {
// Fix for issue #546
// Disable argument checking since it's a bit presumptuous.
// Consider f(x) = 5; If I explicitely pass in an argument array contain x
// this check will fail and complain since the function doesn't contain x.
/*
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg_array.indexOf(arg) === -1)
err(arg + ' not found in argument array');
}
*/
args = arg_array;
}
var f_array = ftext(symbol);
// make all the substitutions;
for (var x in dependencies[0]) {
f_array[1] = f_array[1].replace('exports.', '');
dependencies[1] = dependencies[1].replace('exports.', '');
var alias = dependencies[0][x];
f_array[1] = f_array[1].replace(x, alias);
dependencies[1] = dependencies[1].replace(x, alias);
}
var f = new Function(args, (dependencies[1] || '') + f_array[1] + ' return ' + f_array[0] + ';');
return f;
}
};
//# sourceMappingURL=Build.js.map