eigenmath/userfunc.cpp

152 lines
2.3 KiB
C++
Raw Permalink Normal View History

2008-06-14 02:34:35 +02:00
// Evaluate a user defined function
2008-05-19 03:23:04 +02:00
2004-03-03 21:24:06 +01:00
#include "stdafx.h"
#include "defs.h"
2008-06-13 15:22:16 +02:00
#define F p3 // F is the function body
#define A p4 // A is the formal argument list
#define B p5 // B is the calling argument list
#define S p6 // S is the argument substitution list
2004-03-03 21:24:06 +01:00
void
eval_user_function(void)
{
2008-06-13 15:22:16 +02:00
int h;
2004-03-03 21:24:06 +01:00
2008-06-13 15:22:16 +02:00
// Use "derivative" instead of "d" if there is no user function "d"
2007-05-09 01:43:47 +02:00
2008-05-18 20:03:22 +02:00
if (car(p1) == symbol(SYMBOL_D) && get_arglist(symbol(SYMBOL_D)) == symbol(NIL)) {
2007-05-09 01:43:47 +02:00
eval_derivative();
return;
}
2008-06-09 01:14:21 +02:00
F = get_binding(car(p1));
A = get_arglist(car(p1));
B = cdr(p1);
2007-03-21 01:49:40 +01:00
2008-06-13 15:22:16 +02:00
// Undefined function?
2007-03-21 01:49:40 +01:00
2008-06-09 01:14:21 +02:00
if (F == car(p1)) {
2008-06-13 15:22:16 +02:00
h = tos;
2008-06-09 01:14:21 +02:00
push(F);
2008-06-13 06:26:19 +02:00
p1 = B;
while (iscons(p1)) {
push(car(p1));
eval();
p1 = cdr(p1);
}
list(tos - h);
2008-05-18 20:03:22 +02:00
return;
2004-03-03 21:24:06 +01:00
}
2008-06-13 15:22:16 +02:00
// Create the argument substitution list S
2008-06-09 01:14:21 +02:00
p1 = A;
2008-06-13 06:26:19 +02:00
p2 = B;
2008-06-13 15:22:16 +02:00
h = tos;
2008-06-13 06:26:19 +02:00
while (iscons(p1) && iscons(p2)) {
push(car(p1));
push(car(p2));
eval();
2008-06-09 01:14:21 +02:00
p1 = cdr(p1);
2008-06-13 06:26:19 +02:00
p2 = cdr(p2);
2008-06-09 01:14:21 +02:00
}
2008-06-13 06:26:19 +02:00
list(tos - h);
2008-06-13 15:22:16 +02:00
S = pop();
// Evaluate the function body
2008-06-09 01:14:21 +02:00
push(F);
2008-08-23 22:30:37 +02:00
if (iscons(S)) {
push(S);
rewrite_args();
}
2004-03-03 21:24:06 +01:00
eval();
2008-06-09 01:14:21 +02:00
}
2008-08-23 22:41:32 +02:00
// Rewrite by expanding symbols that contain args
2008-06-14 15:11:01 +02:00
2008-08-23 21:24:20 +02:00
int
2008-08-23 22:30:37 +02:00
rewrite_args(void)
2008-06-09 01:14:21 +02:00
{
2008-08-23 22:41:32 +02:00
int h, n = 0;
2008-06-13 06:26:19 +02:00
save();
2008-06-14 15:11:01 +02:00
2008-08-23 22:41:32 +02:00
p2 = pop(); // subst. list
p1 = pop(); // expr
2008-06-13 06:26:19 +02:00
if (istensor(p1)) {
2008-08-23 22:30:37 +02:00
n = rewrite_args_tensor();
2008-06-13 06:26:19 +02:00
restore();
2008-08-23 21:24:20 +02:00
return n;
2008-06-13 06:26:19 +02:00
}
if (iscons(p1)) {
h = tos;
2008-06-14 02:29:16 +02:00
push(car(p1)); // Do not rewrite function name
2008-06-13 06:26:19 +02:00
p1 = cdr(p1);
while (iscons(p1)) {
push(car(p1));
2008-06-14 15:11:01 +02:00
push(p2);
2008-08-23 22:30:37 +02:00
n += rewrite_args();
2008-06-13 06:26:19 +02:00
p1 = cdr(p1);
}
list(tos - h);
restore();
2008-08-23 21:24:20 +02:00
return n;
2008-06-13 06:26:19 +02:00
}
2008-06-14 02:29:16 +02:00
// If not a symbol then done
2008-06-13 15:22:16 +02:00
if (!issymbol(p1)) {
push(p1);
2008-06-13 06:26:19 +02:00
restore();
2008-08-23 21:24:20 +02:00
return 0;
2008-06-09 01:14:21 +02:00
}
2008-06-13 06:26:19 +02:00
2008-06-13 15:22:16 +02:00
// Try for an argument substitution first
2008-06-14 15:11:01 +02:00
p3 = p2;
while (iscons(p3)) {
if (p1 == car(p3)) {
push(cadr(p3));
2008-06-13 15:22:16 +02:00
restore();
2008-08-23 21:24:20 +02:00
return 1;
2008-06-13 15:22:16 +02:00
}
2008-06-14 15:11:01 +02:00
p3 = cddr(p3);
2008-06-13 15:22:16 +02:00
}
2008-06-13 15:22:16 +02:00
// Get the symbol's binding, try again
2008-06-14 15:11:01 +02:00
p3 = get_binding(p1);
push(p3);
if (p1 != p3) {
2008-08-23 21:24:20 +02:00
push(p2); // subst. list
2008-08-23 22:30:37 +02:00
n = rewrite_args();
if (n == 0) {
2008-08-23 21:24:20 +02:00
pop();
push(p1); // restore if not rewritten with arg
}
2008-06-14 15:11:01 +02:00
}
2008-06-13 15:22:16 +02:00
2008-06-13 06:26:19 +02:00
restore();
2008-08-23 21:24:20 +02:00
return n;
2004-03-03 21:24:06 +01:00
}
2008-08-23 21:24:20 +02:00
int
2008-08-23 22:30:37 +02:00
rewrite_args_tensor(void)
2008-06-14 02:29:16 +02:00
{
2008-08-23 21:24:20 +02:00
int i, n = 0;
2008-06-14 02:29:16 +02:00
push(p1);
copy_tensor();
p1 = pop();
for (i = 0; i < p1->u.tensor->nelem; i++) {
push(p1->u.tensor->elem[i]);
2008-06-14 15:11:01 +02:00
push(p2);
2008-08-23 22:30:37 +02:00
n += rewrite_args();
2008-06-14 02:29:16 +02:00
p1->u.tensor->elem[i] = pop();
}
push(p1);
2008-08-23 21:24:20 +02:00
return n;
2008-06-14 02:29:16 +02:00
}