comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Re: Removing if then else loop for efficiency
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Re: Removing if then else loop for efficiency [message #69275] Tue, 12 January 2010 08:04
penteado is currently offline  penteado
Messages: 866
Registered: February 2018
Senior Member
Administrator
On Jan 12, 11:09 am, Tom Ashbee <tlash...@googlemail.com> wrote:
> On Jan 10, 6:25 pm, pp <pp.pente...@gmail.com> wrote:
>
>
>
>> I think this does the same as your code, but it does not use any
>> loops, and it should be much faster and easier to read:
>
>> function velocities,t,xyvec
>> compile_opt idl2
>> ;Constants
>> N=50
>> R=5d0
>> ;Unpack the input
>> xvec=xyvec[0:N-1]
>> yvec=xyvec[N:(N*2)-1]
>> ;Temporary arrays for x[j], x[i], y[j], y[i]
>> xj=rebin(xvec,N,N)
>> xi=transpose(xj)
>> yj=rebin(yvec,N,N)
>> yi=transpose(yj)
>> ;Repeated terms in the expressions
>> tmp1=(xi-xj)^2+(yi-yj)^2
>> tmp2=R^2/(xj^2+yj^2)
>> tmp3=(xi-xj*tmp2)^2+(yi-yj*tmp2)^2
>> ;Terms of dxdt,dydt present everywhere
>> dxdt=-(yi-yj*tmp2)/tmp3
>> dydt=(xi-xj*tmp2)/tmp3
>> ;Terms present only out of the diagonal
>> tmp4=1d0-identity(N) ;this is 0 in the diagonal, 1 out of it
>> dxdt+=((yj-yi)/tmp1)*tmp4
>> dydt-=((xi-xj)/tmp1)*tmp4
>> ;Put the gamma factor
>> gamm=rebin(gamma(N,2.0d,10.0d)/(2d0*!dpi),N,N) ;this does not seem to
>> be IDL's gamma function
>> dxdt*=gamm
>> dydt*=gamm
>> ;Sum over the rows
>> dxvecdt=total(dxdt,1)
>> dyvecdt=total(dydt,1)
>> ;Pack the results
>> z=[dxvecdt,dyvecdt]
>> return,z
>> end
>
>> You should check that I did not misidentify anything, which would not
>> have been difficult in such convoluted expressions.
>
>> Other points to note:
>
>> 1) Do not use () for array indexes. Use [] instead. That makes it
>> unambiguous that it is an array index, and not a function call.
>
>> 2) When using doubles, as you did, use !dpi instead of !pi.
>
>> 3) Your function has an argument t that is not used anywhere in it. I
>> left it there, so that the argument order does not change.
>
> Hi,
>
> thanks a lot for this; it was very insightful and helpful.
> Unfortunately it's just giving NaNs for z at the moment but I'm
> working on debugging it.

Now that you mention it, I see a reason for the NaNs. The lines

tmp4=1d0-identity(N) ;this is 0 in the diagonal, 1 out of it
dxdt+=((yj-yi)/tmp1)*tmp4
dydt-=((xi-xj)/tmp1)*tmp4

were intended to add to dxdt only in the off-diagonal elements, by
multiplying the diagonal elements of ((yj-yi)/tmp1) by 0 (same for
dydt). But these diagonal elements are some non finite value (some
form of NaN or Infinity), so their product with 0 is not 0, it is some
NaN.

One way to get around this is to replace those 7 lines with:

;Terms of dxdt,dydt present only out of the diagonal
dxdt=((yj-yi)/tmp1)
dydt=-((xi-xj)/tmp1)
;Reset to 0 the diagonal elements
dxdt[0:N*N-1:N+1]=0d0
dydt[0:N*N-1:N+1]=0d0
;Terms of dxdt,dydt present everywhere
dxdt-=(yi-yj*tmp2)/tmp3
dydt+=(xi-xj*tmp2)/tmp3
Re: Removing if then else loop for efficiency [message #69280 is a reply to message #69275] Tue, 12 January 2010 05:09 Go to previous message
Tom Ashbee is currently offline  Tom Ashbee
Messages: 3
Registered: January 2010
Junior Member
On Jan 10, 6:25 pm, pp <pp.pente...@gmail.com> wrote:
> I think this does the same as your code, but it does not use any
> loops, and it should be much faster and easier to read:
>
> function velocities,t,xyvec
> compile_opt idl2
> ;Constants
> N=50
> R=5d0
> ;Unpack the input
> xvec=xyvec[0:N-1]
> yvec=xyvec[N:(N*2)-1]
> ;Temporary arrays for x[j], x[i], y[j], y[i]
> xj=rebin(xvec,N,N)
> xi=transpose(xj)
> yj=rebin(yvec,N,N)
> yi=transpose(yj)
> ;Repeated terms in the expressions
> tmp1=(xi-xj)^2+(yi-yj)^2
> tmp2=R^2/(xj^2+yj^2)
> tmp3=(xi-xj*tmp2)^2+(yi-yj*tmp2)^2
> ;Terms of dxdt,dydt present everywhere
> dxdt=-(yi-yj*tmp2)/tmp3
> dydt=(xi-xj*tmp2)/tmp3
> ;Terms present only out of the diagonal
> tmp4=1d0-identity(N) ;this is 0 in the diagonal, 1 out of it
> dxdt+=((yj-yi)/tmp1)*tmp4
> dydt-=((xi-xj)/tmp1)*tmp4
> ;Put the gamma factor
> gamm=rebin(gamma(N,2.0d,10.0d)/(2d0*!dpi),N,N) ;this does not seem to
> be IDL's gamma function
> dxdt*=gamm
> dydt*=gamm
> ;Sum over the rows
> dxvecdt=total(dxdt,1)
> dyvecdt=total(dydt,1)
> ;Pack the results
> z=[dxvecdt,dyvecdt]
> return,z
> end
>
> You should check that I did not misidentify anything, which would not
> have been difficult in such convoluted expressions.
>
> Other points to note:
>
> 1) Do not use () for array indexes. Use [] instead. That makes it
> unambiguous that it is an array index, and not a function call.
>
> 2) When using doubles, as you did, use !dpi instead of !pi.
>
> 3) Your function has an argument t that is not used anywhere in it. I
> left it there, so that the argument order does not change.

Hi,

thanks a lot for this; it was very insightful and helpful.
Unfortunately it's just giving NaNs for z at the moment but I'm
working on debugging it.

Thanks again
Re: Removing if then else loop for efficiency [message #69298 is a reply to message #69280] Sun, 10 January 2010 10:25 Go to previous message
penteado is currently offline  penteado
Messages: 866
Registered: February 2018
Senior Member
Administrator
I think this does the same as your code, but it does not use any
loops, and it should be much faster and easier to read:

function velocities,t,xyvec
compile_opt idl2
;Constants
N=50
R=5d0
;Unpack the input
xvec=xyvec[0:N-1]
yvec=xyvec[N:(N*2)-1]
;Temporary arrays for x[j], x[i], y[j], y[i]
xj=rebin(xvec,N,N)
xi=transpose(xj)
yj=rebin(yvec,N,N)
yi=transpose(yj)
;Repeated terms in the expressions
tmp1=(xi-xj)^2+(yi-yj)^2
tmp2=R^2/(xj^2+yj^2)
tmp3=(xi-xj*tmp2)^2+(yi-yj*tmp2)^2
;Terms of dxdt,dydt present everywhere
dxdt=-(yi-yj*tmp2)/tmp3
dydt=(xi-xj*tmp2)/tmp3
;Terms present only out of the diagonal
tmp4=1d0-identity(N) ;this is 0 in the diagonal, 1 out of it
dxdt+=((yj-yi)/tmp1)*tmp4
dydt-=((xi-xj)/tmp1)*tmp4
;Put the gamma factor
gamm=rebin(gamma(N,2.0d,10.0d)/(2d0*!dpi),N,N) ;this does not seem to
be IDL's gamma function
dxdt*=gamm
dydt*=gamm
;Sum over the rows
dxvecdt=total(dxdt,1)
dyvecdt=total(dydt,1)
;Pack the results
z=[dxvecdt,dyvecdt]
return,z
end

You should check that I did not misidentify anything, which would not
have been difficult in such convoluted expressions.

Other points to note:

1) Do not use () for array indexes. Use [] instead. That makes it
unambiguous that it is an array index, and not a function call.

2) When using doubles, as you did, use !dpi instead of !pi.

3) Your function has an argument t that is not used anywhere in it. I
left it there, so that the argument order does not change.
Re: Removing if then else loop for efficiency [message #69304 is a reply to message #69298] Sun, 10 January 2010 06:46 Go to previous message
Tom Ashbee is currently offline  Tom Ashbee
Messages: 3
Registered: January 2010
Junior Member
On Jan 10, 12:06 pm, Tom Ashbee <tlash...@googlemail.com> wrote:
> Hello,
>
> apologies for my newb-ness, but I was hoping I could get some help
> with increasing the efficiency of the following program:
>
> At the moment it is like this
>
> for i=0, N-1 do begin
>    for j=0, N-1 do begin
>       if i ne j then begin
>           ;stuff
>       endif else begin
>           ;more stuff
>       endif
>    endfor
> endfor
>
> It's way too slow at the moment, but I gather I can remove one of the
> for loops and the if then else loop but I have no idea how!
>
> Any help would be much appreciated and I can post the full program too
> if it helps. FTR it's the RHS of a Hamiltonian.
>
> Thanks again

OK here's the whole program:

function velocities, t, xyvec

N = 50
R = 5.0

xvec = xyvec(0: N-1)
yvec = xyvec(N: (N*2)-1)

dxvecdt = dblarr(N)
dyvecdt = dblarr(N)

for i = 0, N-1 do begin

dxvecdt(i) = 0.0d
dyvecdt(i) = 0.0d

for j = 0, N-1 do begin

gam = gamma(N, 2.0d, 10.0d)

if i ne j then begin

dxvecdt(i) = dxvecdt(i) + ( gam(j) /(2.0d*!pi))*(yvec(j)-yvec
(i))/((xvec(i)-xvec(j))^2+(yvec(i)-yvec(j))^2) - ( gam(j) /(2.0d*!
pi))*((yvec(j)*R^2)/((xvec(j))^2+(yvec(j))^2)-yvec(i))/((xve c(i)-(xvec
(j)*R^2)/((xvec(j))^2+(yvec(j))^2))^2+(yvec(i)-(yvec(j)*R^2) /((xvec(j))
^2+(yvec(j))^2))^2)

dyvecdt(i) = dyvecdt(i) + ( gam(j) /(2.0d*!pi))*(xvec(i)-xvec
(j))/((xvec(i)-xvec(j))^2+(yvec(i)-yvec(j))^2) - ( gam(j) /(2.0d*!
pi))*(xvec(i)-(xvec(j)*R^2)/((xvec(j))^2+(yvec(j))^2))/((xve c(i)-(xvec
(j)*R^2)/((xvec(j))^2+(yvec(j))^2))^2+(yvec(i)-(yvec(j)*R^2) /((xvec(j))
^2+(yvec(j))^2))^2)

endif else begin

dxvecdt(i) = dxvecdt(i) - ( gam(j) /(2.0d*!pi))*((yvec(j)*R^2)/
((xvec(j))^2+(yvec(j))^2)-yvec(i))/((xvec(i)-(xvec(j)*R^2)/( (xvec(j))
^2+(yvec(j))^2))^2+(yvec(i)-(yvec(j)*R^2)/((xvec(j))^2+(yvec (j))^2))
^2)

dyvecdt(i) = dyvecdt(i) - ( gam(j) /(2.0d*!pi))*(xvec(i)-(xvec
(j)*R^2)/((xvec(j))^2+(yvec(j))^2))/((xvec(i)-(xvec(j)*R^2)/ ((xvec(j))
^2+(yvec(j))^2))^2+(yvec(i)-(yvec(j)*R^2)/((xvec(j))^2+(yvec (j))^2))
^2)

endelse

endfor

endfor

z = [dxvecdt, dyvecdt]

return, z

end
Re: Removing if then else loop for efficiency [message #69305 is a reply to message #69304] Sun, 10 January 2010 06:42 Go to previous message
penteado is currently offline  penteado
Messages: 866
Registered: February 2018
Senior Member
Administrator
On Jan 10, 10:06 am, Tom Ashbee <tlash...@googlemail.com> wrote:
>
> It's way too slow at the moment, but I gather I can remove one of the
> for loops and the if then else loop but I have no idea how!

It is impossible to tell without knowing what happens in the lines you
omitted.

if..then..else is not a loop, it is a conditional construct. Loops are
control structures that (potentially) make some piece of code get
executed multiple times, such as for, while and repeat.
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: pointer & structure
Next Topic: Re: Greek Symbols in Plot Annotations

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 15:17:49 PDT 2025

Total time taken to generate the page: 0.00672 seconds