|
From: <mw...@gm...> - 2011-01-16 18:23:15
|
Hi,
I have recently with your help been able to implement finite summation by adding the functions sum() and sumx(). I have also thought about your comments and tried to implement an expression 'for' that should work like:
a = for [k=1:4] k
f(x) = for [k=1:4] sin(k*x)
print for [k=1:4] k
plot for [k=1:4] sin(k*x)
I can parse "for [k=1:4]" decently. The following token should be similar to a function of k. I have thus tried to create a udf (on the fly) with the corresponding action code, but I have not succeeded and need your help to continue. The relevant code is in parse_for_expression() at:
/* parse the following expression and convert it to an action table. */
/* XXX I am very unsure about the following part */
save_at = at;
save_at_size = at_size;
at = (struct at_type *) gp_alloc(sizeof(struct at_type), "action table");
memset(at, 0, sizeof(*at)); /* XXX understand why: reset action table !!! */
at_size = MAX_AT_LEN;
/* XXX maybe I have to save the recursion level */
parse_expression();
/* create a udf (user defined function) with the parsed action talbe (at) */
udf = (struct udft_entry *) gp_alloc(sizeof(struct udft_entry), "for");
udf->next_udf = (struct udft_entry *) NULL;
udf->definition = NULL;
udf->at = at;
udf->udf_name = NULL; /* TODO maybe add */
udf->dummy_num = 1;
for (i = 0; i < MAX_NUM_VAR; i++)
(void) Ginteger(&(udf->dummy_values[i]), 0);
/* restore at */
at = save_at;
at_size = save_at_size;
add_action(FOR)->udf_arg = udf;
I appreciate your help very much.
Thanks for your consideration,
Micha Wiedenmann
diff --git a/src/eval.c b/src/eval.c
index 056159b..8681857 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -93,6 +93,7 @@ const struct ft_entry GPFAR ft[] =
{"pop", f_pop},
{"call", f_call},
{"calln", f_calln},
+ {"for", f_for},
{"lnot", f_lnot},
{"bnot", f_bnot},
{"uminus", f_uminus},
diff --git a/src/eval.h b/src/eval.h
index 2af029e..b7da3b9 100644
--- a/src/eval.h
+++ b/src/eval.h
@@ -53,7 +53,7 @@
enum operators {
/* keep this in line with table in eval.c */
PUSH, PUSHC, PUSHD1, PUSHD2, PUSHD, POP,
- CALL, CALLN, LNOT, BNOT, UMINUS,
+ CALL, CALLN, FOR, LNOT, BNOT, UMINUS,
LOR, LAND, BOR, XOR, BAND, EQ, NE, GT, LT, GE, LE, PLUS, MINUS, MULT,
DIV, MOD, POWER, FACTORIAL, BOOLE,
DOLLARS, /* for using extension - div */
diff --git a/src/internal.c b/src/internal.c
index a397af2..2f9ac25 100644
--- a/src/internal.c
+++ b/src/internal.c
@@ -188,6 +188,57 @@ f_calln(union argument *x)
void
+f_for(union argument *arg)
+{
+#if 0
+ /* XXX compare with f_range */
+ struct value beg, end; /* bounds [beg, end] */
+#endif
+
+ int a, b; /* bounds [a, b] */
+ udft_entry *udf; /* function to evaluate */
+ struct cmplx ret; /* result */
+
+ struct value tmp;
+ union argument calln_arg;
+ int i;
+
+ udf = arg->udf_arg;
+
+ /* pop upper bound (b) */
+ if (pop(&tmp)->type != INTGR)
+ int_warn(NO_CARET, "expecting an integer as 2nd argument to sum");
+ b = tmp.v.int_val;
+
+ /* pop lower bound (a) */
+ if (pop(&tmp)->type != INTGR)
+ int_warn(NO_CARET, "expecting an integer as 1st argument to sum");
+ a = tmp.v.int_val;
+
+ ret.real = 0;
+ ret.imag = 0;
+ for (i=a; i<=b; ++i) {
+
+ /* calculate f_k = f(k); */
+
+ push(Ginteger(&tmp, i));
+ /* XXX maybe change to 'call'? */
+ push(Ginteger(&tmp, 1)); /* push argument count */
+
+ calln_arg.udf_arg = udf;
+ f_calln(&calln_arg);
+
+ pop(&tmp);
+ ret.real += real(&tmp);
+ ret.imag += imag(&tmp);
+ }
+
+ push(Gcomplex(&tmp, ret.real, ret.imag));
+
+}
+
+
+void
f_lnot(union argument *arg)
{
struct value a;
diff --git a/src/internal.h b/src/internal.h
index 0d254de..f4bfb8a 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -54,6 +54,7 @@ void f_pushd __PROTO((union argument *x));
void f_pop __PROTO((union argument *x));
void f_call __PROTO((union argument *x));
void f_calln __PROTO((union argument *x));
+void f_for __PROTO((union argument *x));
void f_lnot __PROTO((union argument *x));
void f_bnot __PROTO((union argument *x));
void f_lor __PROTO((union argument *x));
diff --git a/src/parse.c b/src/parse.c
index 0569ebb..c984dd1 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -88,6 +88,7 @@ static void parse_relational_expression __PROTO((void));
static void parse_additive_expression __PROTO((void));
static void parse_multiplicative_expression __PROTO((void));
static void parse_unary_expression __PROTO((void));
+static void parse_for_expression __PROTO((void));
static int parse_assignment_expression __PROTO((void));
static int is_builtin_function __PROTO((int t_num));
@@ -487,6 +488,9 @@ parse_primary_expression()
c_token++;
add_action(call_type)->udf_arg = add_udf(tok);
}
+ } else if (equals(c_token, "for")) {
+ FPRINTF((stderr, "found 'for' keyword\n"));
+ parse_for_expression();
/* dummy_func==NULL is a flag to say no dummy variables active */
} else if (dummy_func) {
if (equals(c_token, c_dummy_var[0])) {
@@ -828,6 +832,110 @@ parse_unary_expression()
parse_primary_expression();
}
+
+/* create action code for 'for' expressions */
+static void
+parse_for_expression()
+{
+ /* parse [<var> = <start> : <end>] */
+ /* push <start>
+ * push <end>
+ * create a udf for##
+ * save dummy_func and set it to new udf
+ * 1 variable
+ * parse remainder as function of <var>
+ * pass udf as arg to add_action(FOR)
+ */
+
+ /* FIXME what if dummy_func is not NULL in the beginning? ( I think this is
+ * the case for foo(x) = for [k=1:10] sin(k*x), since parsing foo(x) set it
+ * and then for overrides it further down the parsing.
+ */
+ char *errormsg = "Expecting iterator for [<var> = <start> : <end>]\n";
+ int beg, end;
+ union argument *arg;
+
+ struct udvt_entry *udv;
+ struct udft_entry *udf;
+
+ struct at_type * save_at;
+ int save_at_size;
+ int i;
+
+ if (!equals(c_token, "for"))
+ return;
+ c_token++;
+
+ /* XXX what if c_token is too large (out of bounds) in isletter? */
+ /* XXX is this use of '++' undefined behaviour defined? */
+ /* XXX why do I have to create an udv? */
+ if (!equals(c_token++, "[") || !isletter(c_token))
+ int_error(c_token-1, errormsg);
+ udv = add_udv(c_token);
+ c_token++;
+
+ if (!equals(c_token, "="))
+ int_error(c_token-1, errormsg); /* why -1? */
+ c_token++;
+
+ beg = int_expression();
+
+ if (!equals(c_token, ":"))
+ int_error(c_token, errormsg);
+ c_token++;
+
+ end = int_expression();
+
+ /* TODO add increment */
+ if (!equals(c_token, "]"))
+ int_error(c_token, errormsg);
+ c_token++;
+
+ /* FIXME to implement, debug use 1 for <beg> */
+ arg = add_action(PUSHC);
+ arg->v_arg.type = INTGR;
+ arg->v_arg.v.int_val = beg;
+
+ /* FIXME to implement, debug use 10 for <end> */
+ arg = add_action(PUSHC);
+ arg->v_arg.type = INTGR;
+ arg->v_arg.v.int_val = end;
+
+ /* parse the following expression and convert it to an action table. */
+ /* XXX I am very unsure about the following part */
+ save_at = at;
+ save_at_size = at_size;
+
+ at = (struct at_type *) gp_alloc(sizeof(struct at_type), "action table");
+ memset(at, 0, sizeof(*at)); /* XXX understand why: reset action table !!! */
+ at_size = MAX_AT_LEN;
+
+ /* XXX maybe I have to save the recursion level */
+ parse_expression();
+
+ /* create a udf (user defined function) with the parsed action talbe (at) */
+ udf = (struct udft_entry *) gp_alloc(sizeof(struct udft_entry), "for");
+ udf->next_udf = (struct udft_entry *) NULL;
+ udf->definition = NULL;
+ udf->at = at;
+ udf->udf_name = NULL; /* TODO maybe add */
+ udf->dummy_num = 1;
+ for (i = 0; i < MAX_NUM_VAR; i++)
+ (void) Ginteger(&(udf->dummy_values[i]), 0);
+
+ /* restore at */
+ at = save_at;
+ at_size = save_at_size;
+
+ add_action(FOR)->udf_arg = udf;
+}
+
+
/* find or add value and return pointer */
struct udvt_entry *
add_udv(int t_num)
--
Neu: GMX De-Mail - Einfach wie E-Mail, sicher wie ein Brief!
Jetzt De-Mail-Adresse reservieren: http://portal.gmx.net/de/go/demail
|