New system for integrals the same as for derivatives.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Ad5001 2023-10-10 01:33:57 +02:00
parent d991deee7b
commit 803416d08d
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
2 changed files with 47 additions and 24 deletions

View file

@ -44,34 +44,55 @@ const parser = new ExprEval.Parser()
parser.consts = Object.assign({}, parser.consts, evalVariables)
/**
* Parses arguments for a function, returns the corresponding JS function if it exists.
* Throws either usage error otherwise.
* @param {array} args - Arguments of the function, either [ ExecutableObject ] or [ string, variable ].
* @param {string} usage1 - Usage for executable object.
* @param {string} usage2 - Usage for string function.
* @return {callable} JS function to call..
*/
function parseArgumentsForFunction(args, usage1, usage2) {
let f, target, variable
if(args.length == 1) {
// Parse object
f = args[0]
if(typeof f != 'object' || !f.execute)
throw EvalError(qsTranslate('usage', 'Usage: %1').arg(usage1))
let target = f
f = (x) => target.execute(x)
} else if(args.length == 2) {
// Parse variable
[f,variable] = args
if(typeof f != 'string' || typeof variable != 'number')
throw EvalError(qsTranslate('usage', 'Usage: %1').arg(usage2))
f = parser.parse(f).toJSFunction(variable, currentVars)
} else
throw EvalError(qsTranslate('usage', 'Usage: %1 or\n%2').arg(usage1).arg(usage2)))
return f
}
// Function definition
parser.functions.integral = function(a, b, f, variable) {
parser.functions.integral = function(a, b, ...args) {
let usage1 = qsTranslate('usage', 'integral(<from: number>, <to: number>, <f: ExecutableObject>)')
let usage2 = qsTranslate('usage', 'integral(<from: number>, <to: number>, <f: string>, <variable: string>)')
let f = parseArgumentsForFunction(args, usage1, usage2)
if(a == null || b == null)
throw EvalError(qsTranslate('usage', 'Usage: %1 or\n%2').arg(usage1).arg(usage2)))
// https://en.wikipedia.org/wiki/Simpson%27s_rule
// Simpler, faster than tokenizing the expression
f = parser.parse(f).toJSFunction(variable, currentVars)
return (b-a)/6*(f(a)+4*f((a+b)/2)+f(b))
}
parser.functions.derivative = function(...args) {
let f, target, variable, x
if(args.length == 2) {
[f, x] = args
if(typeof f != 'object' || !f.execute)
throw EvalError(qsTranslate('usage', 'Usage: %1')
.arg(qsTranslate('usage', 'derivative(<function: ExecutableObject>, <x: variable>)')))
target = f
f = (x) => target.execute(x)
} else if(args.length == 3) {
[f, variable, x] = args
if(typeof f != 'string')
throw EvalError(qsTranslate('usage', 'Usage: %1')
.arg(qsTranslate('usage', 'derivative(<function: string>, <variable: string>, <x: variable>)')))
f = parser.parse(f).toJSFunction(variable, currentVars)
} else
throw EvalError(qsTranslate('usage', 'Usage: %1 or\n%2')
.arg(qsTranslate('usage', 'derivative(<function: string>, <variable: string>, <x: variable>)')
.arg(qsTranslate('usage', 'derivative(<function: string>, <variable: string>, <x: variable>)'))))
let usage1 = qsTranslate('usage', 'derivative(<f: ExecutableObject>, <x: variable>)')
let usage2 = qsTranslate('usage', 'derivative(<f: string>, <variable: string>, <x: variable>)')
let x = args.pop()
let f = parseArgumentsForFunction(args, usage1, usage2)
if(x == null)
throw EvalError(qsTranslate('usage', 'Usage: %1 or\n%2').arg(usage1).arg(usage2)))
let derivative_precision = x/10
return (f(x+derivative_precision/2)-f(x-derivative_precision/2))/derivative_precision
}

View file

@ -71,16 +71,18 @@ function parif(elem, contents) {
* @returns {string}
*/
function functionToLatex(f, args) {
console.log("Generating latex", f, args)
switch(f) {
case "derivative":
if(args.length == 3)
return '\\frac{d' + args[0].substr(1, args[0].length-2).replace(new RegExp(args[1].substr(1, args[1].length-2), 'g'), 'x') + '}{dx}';
else
return '\\frac{d' + args[0] + '}{dx}';
return '\\frac{d' + args[0] + '}{dx}(x)';
break;
case "integral":
return '\\int\\limits_{' + args[0] + '}^{' + args[1] + '}' + args[2].substr(1, args[2].length-2) + ' d' + args[3].substr(1, args[3].length-2);
if(args.length == 4)
return '\\int\\limits_{' + args[0] + '}^{' + args[1] + '}' + args[2].substr(1, args[2].length-2) + ' d' + args[3].substr(1, args[3].length-2);
else
return '\\int\\limits_{' + args[0] + '}^{' + args[1] + '}' + args[2] + '(t) dt';
break;
case "sqrt":
return '\\sqrt\\left(' + args.join(', ') + '\\right)';