|
From: <mw...@gm...> - 2011-01-11 20:37:52
|
> Ethan Merritt <merritt@u.washington.edu> wrote:
> On Tuesday, January 11, 2011 09:00:19 am mw...@gm... wrote:
>> Hi,
>>
>> I want to add finite summation to gnuplot, that is a function sum(a, b,
>> x, f), where a, b (int) are the summation boundary, x (double) is a
>> varialbe, f (string) is the name of the function to eveluate a term.
>> Example usage:
>>
>> f(n, x) = sin(n*x)
>> plot sum(1, 10, x, "f")
>
> That pair of commands does not seem to be compatible with your
> description. How is the code to know there is a second parameter to
> f()? And where would it get this second parameter from?
sum requires its 4-th parameter to be the name of a 2 parametric function. Before the call to f in sum, two values are pushed. I think I missed the point of what you were trying to tell me.
>> I am stuck at how to call f from sum (see call(f) below) and would
>> appreciate your help very much. (I assume f is the string representing
>> the name of the function to call.)
>>
>> - for (i=a; i<=b; ++i) {
>> - // calculate f_i(x);
>> - push(Gcomplex(&tmp, x.real, x.imag)); // todo check the order
>> - push(Ginteger(&tmp, i));
>> -
>> - //call(f); // assume f is the name (string) of the function to call
>
> There is no existing routine that does either call-by-name or
> retrieve-user-function-by-name; you would have to write one. Something
> like (untested):
>
> struct udft_entry *
> get_udf_by_name(char *key)
> {
> struct udft_entry **udf_ptr = &first_udf;
>
> while (*udf_ptr) {
> if (!strcmp(key, (*udf_ptr)->udf_name))
> return (*udf_ptr);
> udf_ptr = &((*udf_ptr)->next_udf);
> }
>
> return NULL;
> }
>
> It would belong in eval.c next to add_udv_by_name().
>
> Then you would do something like:
>
> udft_entry *udf = get_udf_by_name( f );
> if (udf)
> execute_at(udf->at);
> else
> int_error(NOCARET, "No user-defined function %s",f);
>
>
>> -
>> - pop(&tmp);
>> - ret.real += real(&tmp);
>> - ret.imag += imag(&tmp);
>> - }
>>
>> Thank you very much for your time and effort.
>>
With your generous help I was able to get stuck a little bit later. I assume its related to your initial comment about the parameters of f. I thought, that I have to push two values (int n, cmplx x) onto the stack and then execute_at(..). I could verify (by calling pop()/more_on_stack() repediatly) that execute_at(..) doesn't pop values from the stack. In fact I believe that initially the stack containes two values (n, x) and then execute_at(..) adds another. Did I do it wrong? How can I pass n, x to the function if not by pushing them?
+ for (i=a; i<=b; ++i) {
+
+ // calculate f_i(x);
+ push(Gcomplex(&tmp, x.real, x.imag)); // todo check the order
+ push(Ginteger(&tmp, i));
+
+ if (udf = get_udf_by_name(f))
+ execute_at(udf->at);
+ else
+ int_error(NO_CARET, "No user-defined function %s", f);
+
+ /*
+ int_warn(NO_CARET, "stack_size == 3 (%d)", more_on_stack()); pop(&tmp);
+ int_warn(NO_CARET, "stack_size == 2 (%d)", more_on_stack()); pop(&tmp);
+ int_warn(NO_CARET, "stack_size == 1 (%d)", more_on_stack()); pop(&tmp);
+ int_warn(NO_CARET, "stack_size == 0 (%d)", more_on_stack());
+ */
+
+ pop(&tmp);
+ ret.real += real(&tmp);
+ ret.imag += imag(&tmp);
+ }
Thank you Sir.
--- specfun.c.orig 2011-01-11 17:37:27.000000000 +0100
+++ specfun.c 2011-01-11 21:06:01.000000000 +0100
@@ -1933,3 +1933,57 @@
push(Gcomplex(&a, x, 0.0));
}
+void
+f_sum(union argument *arg)
+{
+ struct value tmp;
+ int a, b;
+ struct cmplx x, ret, result;
+ int i;
+ udft_entry *udf;
+ char *f = "f";
+
+ (void) arg; /* avoid -Wunused warning */
+
+ // pop x
+ pop(&tmp);
+ x.real = real(&tmp);
+ x.imag = imag(&tmp);
+
+ // pop b
+ if (pop(&tmp)->type != INTGR)
+ int_warn(NO_CARET, "expecting an integer as second argument to sum");
+ b = tmp.v.int_val;
+
+ // pop a
+ if (pop(&tmp)->type != INTGR)
+ int_warn(NO_CARET, "expecting an integer as first argument to sum");
+ a = tmp.v.int_val;
+
+ ret.real = 0;
+ ret.imag = 0;
+ for (i=a; i<=b; ++i) {
+
+ // calculate f_i(x);
+ push(Gcomplex(&tmp, x.real, x.imag)); // todo check the order
+ push(Ginteger(&tmp, i));
+
+ if (udf = get_udf_by_name(f))
+ execute_at(udf->at);
+ else
+ int_error(NO_CARET, "No user-defined function %s", f);
+
+ /*
+ int_warn(NO_CARET, "stack_size == 3 (%d)", more_on_stack()); pop(&tmp);
+ int_warn(NO_CARET, "stack_size == 2 (%d)", more_on_stack()); pop(&tmp);
+ int_warn(NO_CARET, "stack_size == 1 (%d)", more_on_stack()); pop(&tmp);
+ int_warn(NO_CARET, "stack_size == 0 (%d)", more_on_stack());
+ */
+
+ pop(&tmp);
+ ret.real += real(&tmp);
+ ret.imag += imag(&tmp);
+ }
+
+ push(Gcomplex(&tmp, ret.real, ret.imag));
+}
--- eval.c.orig 2011-01-11 17:38:00.000000000 +0100
+++ eval.c 2011-01-11 20:41:11.000000000 +0100
@@ -176,6 +176,8 @@
{"atanh", f_atanh},
{"lambertw", f_lambertw}, /* HBB, from G.Kuhnle 20001107 */
+ {"sum", f_sum}, /* summation */
+
{"column", f_column}, /* for using */
{"valid", f_valid}, /* for using */
{"timecolumn", f_timecolumn}, /* for using */
@@ -689,6 +691,20 @@
return (*udv_ptr);
}
+struct udft_entry *
+get_udf_by_name(char *key)
+{
+ struct udft_entry *udf_ptr = first_udf;
+
+ while (udf_ptr) {
+ if (!strcmp(key, udf_ptr->udf_name))
+ return udf_ptr;
+
+ udf_ptr = udf_ptr->next_udf;
+ }
+
+ return NULL;
+}
static void update_plot_bounds __PROTO((void));
static void fill_gpval_axis __PROTO((AXIS_INDEX axis));
zsh: exit 1 diff -u eval.c.orig eval.c
--- specfun.h.orig 2011-01-11 17:37:21.000000000 +0100
+++ specfun.h 2011-01-11 16:22:05.000000000 +0100
@@ -61,4 +61,6 @@
void f_inverse_erf __PROTO((union argument *x));
void f_lambertw __PROTO((union argument *x));
+void f_sum __PROTO((union argument *x));
+
#endif /* GNUPLOT_SPECFUN_H */
--
NEU: FreePhone - kostenlos mobil telefonieren und surfen!
Jetzt informieren: http://www.gmx.net/de/go/freephone
|