Reputation: 1284
I have recently attempted to concisely draw several graphs in a plot using gnuplot and the plot for ...
syntax. In this case, I needed nested loops because I wanted to pass something like the following index combinations (simplified here) to the plot
expression:
i = 0
, j = 0
i = 1
, j = 0
i = 1
, j = 1
i = 2
, j = 0
i = 2
, j = 1
i = 2
, j = 2
So i
loops from 0
to some upper limit N
and for each iteration of i
, j
loops from 0
to i
(so i <= j
). I tried doing this with the following:
# f(i, j, x) = ...
N = 5
plot for [i=0:N] for [j=0:i] f(i, j, x) title sprintf('j = %d', j)
but this only gives five iterations with j = 0
every time (as shown by the title
). So it seems that gnuplot only evaluates the for
expressions once, fixing i = 0
at the beginning and not re-evaluating to keep up with changing i
values. Something like this has already been hinted at in this answer (“in the plot for ...
structure the second index cannot depend on the first one.”).
Is there a simple way to do what I want in gnuplot (i.e. use the combinations of indices given above with some kind of loop)? There is the do for { ... }
structure since gnuplot 4.6, but that requires individual statements in its body, so it can’t be used to assemble a single plot
statement. I suppose one could use multiplot
to get around this, but I’d like to avoid multiplot
if possible because it makes things more complicated than seems necessary.
Upvotes: 3
Views: 659
Reputation: 7627
I took your problem personally. For your specific problem you can use a mathematical trick. Remap your indices (i,j) to a single index k, such that
(0,0) -> (0)
(1,0) -> (1)
(1,1) -> (2)
(2,0) -> (3)
...
It can be shown that the relation between i and j and k is
k = i*(i+1)/2 + j
which can be inverted with a bit of algebra
i(k)=floor((sqrt(1+8.*k)-1.)/2.)
j(k)=k-i(k)*(i(k)+1)/2
Now, you can use a single index k in your loop
N = 5
kmax = N*(N+1)/2 + N
plot for [k=0:kmax] f(i(k), j(k), x) title sprintf('j = %d', j(k))
Upvotes: 1