Reworking the derivative function, removed assignement in parser.

The new derivative now supports executable elements.
This commit is contained in:
Ad5001 2023-10-10 00:53:35 +02:00
parent ed4d30573c
commit d991deee7b
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
4 changed files with 28 additions and 41 deletions

View file

@ -42,7 +42,6 @@ Column {
*/
function openEditorDialog(obj) {
// Open editor
console.log(obj, obj.prototype)
objectEditor.obj = obj
objectEditor.objType = obj.type
objectEditor.objIndex = Objects.currentObjects[obj.type].indexOf(obj)

View file

@ -1117,7 +1117,7 @@ ParserState.prototype.parseExpression = function (instr) {
if (this.parseUntilEndStatement(instr, exprInstr)) {
return;
}
this.parseVariableAssignmentExpression(exprInstr);
this.parseConditionalExpression(exprInstr);
if (this.parseUntilEndStatement(instr, exprInstr)) {
return;
}
@ -1157,37 +1157,6 @@ ParserState.prototype.parseArrayList = function (instr) {
return argCount;
};
ParserState.prototype.parseVariableAssignmentExpression = function (instr) {
this.parseConditionalExpression(instr);
while (this.accept(TOP, '=')) {
var varName = instr.pop();
var varValue = [];
var lastInstrIndex = instr.length - 1;
if (varName.type === IFUNCALL) {
if (!this.tokens.isOperatorEnabled('()=')) {
throw new Error(qsTranslate('error', 'Function definition is not permitted.'));
}
for (var i = 0, len = varName.value + 1; i < len; i++) {
var index = lastInstrIndex - i;
if (instr[index].type === IVAR) {
instr[index] = new Instruction(IVARNAME, instr[index].value);
}
}
this.parseVariableAssignmentExpression(varValue);
instr.push(new Instruction(IEXPR, varValue));
instr.push(new Instruction(IFUNDEF, varName.value));
continue;
}
if (varName.type !== IVAR && varName.type !== IMEMBER) {
throw new Error(qsTranslate('error', 'Expected variable for assignment.'));
}
this.parseVariableAssignmentExpression(varValue);
instr.push(new Instruction(IVARNAME, varName.value));
instr.push(new Instruction(IEXPR, varValue));
instr.push(binaryInstruction('='));
}
};
ParserState.prototype.parseConditionalExpression = function (instr) {
this.parseOrExpression(instr);
while (this.accept(TOP, '?')) {

View file

@ -22,8 +22,6 @@
.import "../utils.js" as Utils
.import "latex.js" as Latex
const DERIVATION_PRECISION = 0.1
var evalVariables = { // Variables not provided by expr-eval.js, needs to be provided manually
"pi": Math.PI,
"PI": Math.PI,
@ -54,10 +52,27 @@ parser.functions.integral = function(a, b, f, variable) {
return (b-a)/6*(f(a)+4*f((a+b)/2)+f(b))
}
parser.functions.derivative = function(f, variable, x) {
if(f == null || variable == null || x == null)
throw EvalError("Usage: derivative(<function: string>, <variable: string>, <x: number>)")
f = parser.parse(f).toJSFunction(variable, currentVars)
return (f(x+DERIVATION_PRECISION/2)-f(x-DERIVATION_PRECISION/2))/DERIVATION_PRECISION
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 derivative_precision = x/10
return (f(x+derivative_precision/2)-f(x-derivative_precision/2))/derivative_precision
}

View file

@ -71,9 +71,13 @@ function parif(elem, contents) {
* @returns {string}
*/
function functionToLatex(f, args) {
console.log("Generating latex", f, args)
switch(f) {
case "derivative":
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}';
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}';
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);