FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

New expression type for summation sum [<var> = <beg> : <end>] <somet… · gnuplot/gnuplot@fe8c9b8 · GitHub

Repository navigation

Commit fe8c9b8

Browse files
authored andcommitted
New expression type for summation sum [<var> = <beg> : <end>] <something>
1 parent 7203f42 commit fe8c9b8

10 files changed

Lines changed: 228 additions & 13 deletions

File tree

‎ChangeLog‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
2011-07-30 Stefan Reiser <stefanreiser@users.sourceforge.net>
1+
2011-08-01 Micha Wiedenmann <mw-u2@gmx.de>
2+
3+
* src/eval.h src/eval.c (get_udv_by_name free_at) src/show.c (disp_at)
4+
src/internal.h src/internal.c (f_sum) src/parse.c (parse_sum_expression)
5+
docs/gnuplot.doc demo/bivariat.dem:
6+
7+
New expression type for summation:
8+
sum [<var> = <beg> : <end>] <something>
9+
10+
2011-07-30 Stefan Reiser <stefanreiser@users.sourceforge.net>
211

312
* src/win/wgraph.c (WriteGraphIni): Fix spelling of "Antialiasing"
413
field. Bug #3382732

‎NEWS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ New features, changes and fixes since gnuplot version 4.4
66
if (<cond>) { ... } else { ... }
77
do for [...] { ... }
88
while (<cond>) { ... }
9+
* NEW summation expression: sum [<var> = <beg> : <end>] <something>
910
* NEW nested iteration e.g. "plot for [i=1:5] for [j=1:5]"
1011
* NEW explicit justification for tic labels, e.g. "set xtics right"
1112
* NEW time formats can handle fractional seconds (microsecond precision)

‎demo/bivariat.dem‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# $Id: bivariat.dem,v 1.6 2005/07/29 07:54:32 mikulik Exp $
2+
# $Id: bivariat.dem,v 1.8 2006/07/06 21:52:19 sfeam Exp $
33
#
44
# This demo is very slow and requires unusually large stack size.
55
# Do not attempt to run this demo under MSDOS.
@@ -115,5 +115,27 @@ set title "Greatest Common Divisor (for integers only)"
115115
plot gcd(x, 60) with impulses
116116
pause -1 "Hit return to continue"
117117

118+
#
119+
# This definition computes the sum of the first 10, 100, 1000 fourier
120+
# coefficients of a (particular) square wave.
121+
122+
set title "Finite summation of 10, 100, 1000 fourier coefficients"
123+
124+
set samples 500
125+
set xrange [-10:10]
126+
set yrange [-0.4:1.2]
127+
set key bottom right
128+
129+
fourier(k, x) = sin(3./2*k)/k * 2./3*cos(k*x)
130+
sum10(x) = 1./2 + sum [k=1:10] fourier(k, x)
131+
sum100(x) = 1./2 + sum [k=1:100] fourier(k, x)
132+
sum1000(x) = 1./2 + sum [k=1:1000] fourier(k, x)
133+
134+
plot \
135+
sum10(x) title "1./2 + sum [k=1:10] sin(3./2*k)/k * 2./3*cos(k*x)", \
136+
sum100(x) title "1./2 + sum [k=1:100] sin(3./2*k)/k * 2./3*cos(k*x)", \
137+
sum1000(x) title "1./2 + sum [k=1:1000] sin(3./2*k)/k * 2./3*cos(k*x)"
138+
pause -1 "Hit return to continue"
139+
118140
reset
119141

‎docs/gnuplot.doc‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
C RCS $Id: gnuplot.doc,v 1.680 2011/07/14 21:29:41 sfeam Exp $
1+
C RCS $Id: gnuplot.doc,v 1.681 2011/07/27 20:22:58 sfeam Exp $
22
C
33
C Copyright (C) 1986 - 1993, 1998, 1999, 2000, 2001, 2004 Thomas Williams, Colin Kelley et al.
44
C
@@ -1886,7 +1886,26 @@ C^ <img align=bottom src="http://www.gnuplot.info/doc/ternary.gif" alt="[ternary
18861886
plot 'file' using 1:( $4<0 ? 1/0 : ($2+$3)/2 )
18871887

18881888
For an explanation of the `using` syntax, please see `plot datafile using`.
1889-
1889+
3 Summation
1890+
?expressions operators summation
1891+
?operators summation
1892+
?summation
1893+
A summation expression has the form
1894+
sum [<var> = <start> : <end>] <expression>
1895+
<var> is treated as an integer variable that takes on successive integral
1896+
values from <start> to <end>. For each of these, the current value of
1897+
<expression> is evaluated and added to a running total whose final value
1898+
becomes the value of the summation expression.
1899+
Examples:
1900+
print sum [i=1:10] i
1901+
55.
1902+
# Equivalent to plot 'data' using 1:($2+$3+$4+$5+$6+...)
1903+
plot 'data' using 1 : (sum [col=2:MAXCOL] column(col))
1904+
It is not necessary that <expression> contain the variable <var>.
1905+
Although <start> and <end> can be specified as variables or expressions,
1906+
their value cannot be changed dynamically as a side-effect of carrying
1907+
out the summation. If <end> is less than <start> then the value of the
1908+
summation is zero.
18901909
3 Gnuplot-defined variables
18911910
?gnuplot-defined variables
18921911
Gnuplot maintains a number of read-only variables that reflect the current

‎src/eval.c‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#ifndef lint
2-
static char *RCSid() { return RCSid("$Id: eval.c,v 1.91 2011/04/19 20:22:25 sfeam Exp $"); }
2+
static char *RCSid() { return RCSid("$Id: eval.c,v 1.92 2011/07/14 21:29:41 sfeam Exp $"); }
33
#endif
44

55
/* GNUPLOT - eval.c */
@@ -89,6 +89,7 @@ const struct ft_entry GPFAR ft[] =
8989
{"pop", f_pop},
9090
{"call", f_call},
9191
{"calln", f_calln},
92+
{"sum", f_sum},
9293
{"lnot", f_lnot},
9394
{"bnot", f_bnot},
9495
{"uminus", f_uminus},
@@ -641,6 +642,11 @@ free_at(struct at_type *at_ptr)
641642
/* if union a->arg is used as a->arg.v_arg free potential string */
642643
if ( a->index == PUSHC || a->index == DOLLARS )
643644
gpfree_string(&(a->arg.v_arg));
645+
/* a summation contains its own action table wrapped in a private udf */
646+
if (a->index == SUM) {
647+
free_at(a->arg.udf_arg->at);
648+
free(a->arg.udf_arg);
649+
}
644650
}
645651
free(at_ptr);
646652
}
@@ -670,6 +676,20 @@ add_udv_by_name(char *key)
670676
return (*udv_ptr);
671677
}
672678

679+
struct udvt_entry *
680+
get_udv_by_name(char *key)
681+
{
682+
struct udvt_entry *udv = first_udv;
683+
684+
while (udv) {
685+
if (!strcmp(key, udv->udv_name))
686+
return udv;
687+
688+
udv = udv->next_udv;
689+
}
690+
691+
return NULL;
692+
}
673693

674694
static void update_plot_bounds __PROTO((void));
675695
static void fill_gpval_axis __PROTO((AXIS_INDEX axis));

‎src/eval.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* $Id: eval.h,v 1.35 2011/04/16 11:15:55 markisch Exp $
2+
* $Id: eval.h,v 1.36 2011/07/14 21:29:41 sfeam Exp $
33
*/
44

55
/* GNUPLOT - eval.h */
@@ -53,7 +53,7 @@
5353
enum operators {
5454
/* keep this in line with table in eval.c */
5555
PUSH, PUSHC, PUSHD1, PUSHD2, PUSHD, POP,
56-
CALL, CALLN, LNOT, BNOT, UMINUS,
56+
CALL, CALLN, SUM, LNOT, BNOT, UMINUS,
5757
LOR, LAND, BOR, XOR, BAND, EQ, NE, GT, LT, GE, LE, PLUS, MINUS, MULT,
5858
DIV, MOD, POWER, FACTORIAL, BOOLE,
5959
DOLLARS,
@@ -160,6 +160,7 @@ void execute_at __PROTO((struct at_type *at_ptr));
160160
void evaluate_at __PROTO((struct at_type *at_ptr, struct value *val_ptr));
161161
void free_at __PROTO((struct at_type *at_ptr));
162162
struct udvt_entry * add_udv_by_name __PROTO((char *key));
163+
struct udvt_entry * get_udv_by_name __PROTO((char *key));
163164

164165
/* update GPVAL_ variables available to user */
165166
void update_gpval_variables __PROTO((int from_plot_command));

‎src/internal.c‎

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#ifndef lint
2-
static char *RCSid() { return RCSid("$Id: internal.c,v 1.62 2011/02/17 19:59:01 sfeam Exp $"); }
2+
static char *RCSid() { return RCSid("$Id: internal.c,v 1.63 2011/05/14 19:53:36 sfeam Exp $"); }
33
#endif
44

55
/* GNUPLOT - internal.c */
@@ -205,6 +205,54 @@ f_calln(union argument *x)
205205
}
206206

207207

208+
void
209+
f_sum(union argument *arg)
210+
{
211+
struct value beg, end, varname; /* [<var> = <start>:<end>] */
212+
udft_entry *udf; /* function to evaluate */
213+
udvt_entry *udv; /* iteration variable */
214+
struct value ret; /* result */
215+
struct value z;
216+
int i;
217+
218+
(void) pop(&end);
219+
(void) pop(&beg);
220+
(void) pop(&varname);
221+
222+
if (beg.type != INTGR || end.type != INTGR)
223+
int_error(NO_CARET, "range specifiers of sum must have integer values");
224+
if (varname.type != STRING)
225+
int_error(NO_CARET, "internal error: f_sum expects argument (varname) of type string.");
226+
227+
udv = get_udv_by_name(varname.v.string_val);
228+
if (!udv)
229+
int_error(NO_CARET, "internal error: f_sum could not access iteration variable.");
230+
udv->udv_undef = false;
231+
232+
udf = arg->udf_arg;
233+
if (!udf)
234+
int_error(NO_CARET, "internal error: f_sum could not access summation coefficient function");
235+
236+
Gcomplex(&ret, 0, 0);
237+
for (i=beg.v.int_val; i<=end.v.int_val; ++i) {
238+
double x, y;
239+
240+
/* calculate f_i = f() with user defined variable i */
241+
Ginteger(&udv->udv_value, i);
242+
execute_at(udf->at);
243+
244+
pop(&z);
245+
x = real(&ret) + real(&z);
246+
y = imag(&ret) + imag(&z);
247+
Gcomplex(&ret, x, y);
248+
}
249+
250+
gpfree_string(&varname);
251+
252+
push(Gcomplex(&z, real(&ret), imag(&ret)));
253+
}
254+
255+
208256
void
209257
f_lnot(union argument *arg)
210258
{

‎src/internal.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* $Id: internal.h,v 1.21 2010/09/18 22:00:37 sfeam Exp $
2+
* $Id: internal.h,v 1.22 2011/01/01 15:33:32 juhaszp Exp $
33
*/
44

55
/* GNUPLOT - internal.h */
@@ -55,6 +55,7 @@ void f_pushd __PROTO((union argument *x));
5555
void f_pop __PROTO((union argument *x));
5656
void f_call __PROTO((union argument *x));
5757
void f_calln __PROTO((union argument *x));
58+
void f_sum __PROTO((union argument *x));
5859
void f_lnot __PROTO((union argument *x));
5960
void f_bnot __PROTO((union argument *x));
6061
void f_lor __PROTO((union argument *x));

‎src/parse.c‎

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#ifndef lint
2-
static char *RCSid() { return RCSid("$Id: parse.c,v 1.62 2011/07/14 21:29:41 sfeam Exp $"); }
2+
static char *RCSid() { return RCSid("$Id: parse.c,v 1.63 2011/07/22 14:37:57 juhaszp Exp $"); }
33
#endif
44

55
/* GNUPLOT - parse.c */
@@ -89,6 +89,7 @@ static void parse_relational_expression __PROTO((void));
8989
static void parse_additive_expression __PROTO((void));
9090
static void parse_multiplicative_expression __PROTO((void));
9191
static void parse_unary_expression __PROTO((void));
92+
static void parse_sum_expression __PROTO((void));
9293
static int parse_assignment_expression __PROTO((void));
9394
static int is_builtin_function __PROTO((int t_num));
9495

@@ -190,7 +191,8 @@ string_or_express(struct at_type **atptr)
190191
has_dummies = FALSE;
191192
for (i = 0; i < at->a_count; i++) {
192193
enum operators op_index = at->actions[i].index;
193-
if ( op_index == PUSHD1 || op_index == PUSHD2 || op_index == PUSHD ) {
194+
if ( op_index == PUSHD1 || op_index == PUSHD2 || op_index == PUSHD
195+
|| op_index == SUM ) {
194196
has_dummies = TRUE;
195197
break;
196198
}
@@ -527,7 +529,9 @@ parse_primary_expression()
527529
c_token++;
528530
add_action(call_type)->udf_arg = add_udf(tok);
529531
}
530-
/* dummy_func==NULL is a flag to say no dummy variables active */
532+
} else if (equals(c_token, "sum") && equals(c_token+1, "[")) {
533+
parse_sum_expression();
534+
/* dummy_func==NULL is a flag to say no dummy variables active */
531535
} else if (dummy_func) {
532536
if (equals(c_token, c_dummy_var[0])) {
533537
c_token++;
@@ -872,6 +876,95 @@ parse_unary_expression()
872876
parse_primary_expression();
873877
}
874878

879+
880+
/* create action code for 'sum' expressions */
881+
static void
882+
parse_sum_expression()
883+
{
884+
/* sum [<var>=<range>] <expr>
885+
* - Pass a udf to f_sum (with action code (for <expr>) that is not added
886+
* to the global action table).
887+
* - f_sum uses a newly created udv (<var>) to pass the current value of
888+
* <var> to <expr> (resp. its ac).
889+
* - The original idea was to treat <expr> as function f(<var>), but there
890+
* was the following problem: Consider 'g(x) = sum [k=1:4] f(k)'. There
891+
* are two dummy variables 'x' and 'k' from different functions 'g' and
892+
* 'f' which would require changing the parsing of dummy variables.
893+
*/
894+
895+
char *errormsg = "Expecting 'sum [<var> = <start>:<end>] <expression>'\n";
896+
char *varname = NULL;
897+
union argument *arg;
898+
struct udft_entry *udf;
899+
900+
struct at_type * save_at;
901+
int save_at_size;
902+
int i;
903+
904+
/* Caller already checked for string "sum [" so skip both tokens */
905+
c_token += 2;
906+
907+
/* <var> */
908+
if (!isletter(c_token))
909+
int_error(c_token, errormsg);
910+
/* create a user defined variable and pass it to f_sum via PUSHC, since the
911+
* argument of f_sum is already used by the udf */
912+
m_capture(&varname, c_token, c_token);
913+
add_udv(c_token);
914+
arg = add_action(PUSHC);
915+
Gstring(&(arg->v_arg), varname);
916+
c_token++;
917+
918+
if (!equals(c_token, "="))
919+
int_error(c_token, errormsg);
920+
c_token++;
921+
922+
/* <start> */
923+
parse_expression();
924+
925+
if (!equals(c_token, ":"))
926+
int_error(c_token, errormsg);
927+
c_token++;
928+
929+
/* <end> */
930+
parse_expression();
931+
932+
if (!equals(c_token, "]"))
933+
int_error(c_token, errormsg);
934+
c_token++;
935+
936+
/* parse <expr> and convert it to a new action table. */
937+
/* modeled on code from temp_at(). */
938+
/* 1. save environment to restart parsing */
939+
save_at = at;
940+
save_at_size = at_size;
941+
942+
at = (struct at_type *) gp_alloc(sizeof(struct at_type), "action table");
943+
at->a_count = 0;
944+
memset(at, 0, sizeof(*at));
945+
at_size = MAX_AT_LEN;
946+
947+
parse_expression();
948+
949+
/* 2. save action table in a user defined function */
950+
udf = (struct udft_entry *) gp_alloc(sizeof(struct udft_entry), "sum");
951+
udf->next_udf = (struct udft_entry *) NULL;
952+
udf->udf_name = NULL; /* TODO maybe add a name and definition */
953+
udf->at = at;
954+
udf->definition = NULL;
955+
udf->dummy_num = 0;
956+
for (i = 0; i < MAX_NUM_VAR; i++)
957+
(void) Ginteger(&(udf->dummy_values[i]), 0);
958+
959+
/* 3. restore environment */
960+
at = save_at;
961+
at_size = save_at_size;
962+
963+
/* pass the udf to f_sum using the argument */
964+
add_action(SUM)->udf_arg = udf;
965+
}
966+
967+
875968
/* find or add value and return pointer */
876969
struct udvt_entry *
877970
add_udv(int t_num)

‎src/show.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#ifndef lint
2-
static char *RCSid() { return RCSid("$Id: show.c,v 1.251 2011/06/01 03:44:36 sfeam Exp $"); }
2+
static char *RCSid() { return RCSid("$Id: show.c,v 1.252 2011/07/12 19:30:34 juhaszp Exp $"); }
33
#endif
44

55
/* GNUPLOT - show.c */
@@ -716,6 +716,7 @@ disp_at(struct at_type *curr_at, int level)
716716
(void) putc('\n', stderr);
717717
break;
718718
case CALLN:
719+
case SUM:
719720
fprintf(stderr, " %s", arg->udf_arg->udf_name);
720721
if (level < 6) {
721722
if (arg->udf_arg->at) {

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL