DO loop excluding several values in Fortran - loops

How to achieve this in Fortran ?
do i = 1, n Except n/2
Is there a convenient way instead of using 'if' in the loop ?

There are many solutions. Here is one using cycle. It still has an if statement in the loop but doesn't have an if ... end if block.
MyLoop: do i=1, N
if ( i == N/2 ) cycle MyLoop
! use the loop....
write (*, *) i
end do MyLoop

If you have an aversion to conditionals inside loops
do i = 1,(n/2)-1
...
end do
do i = (n/2)+1,n
...
end do
If n is, or may be, odd, you'll need to adjust the stop/start indices for the loops.

Place an if statement inside a loop
do i=1,n
if (i /= n/2) ...
end do
or the forall statement with a mask or the where statement are possible to use in certain situations.

Related

Open MP in do nested loop

If I have this code,
subroutine min_distance(r,n,k,centroid,distance,indices,distancereg)
integer, intent(out):: n,k
real,dimension(:,:),intent(in),allocatable::centroid
real,dimension(:,:),intent(in),allocatable::r
integer,dimension(:),intent(out),allocatable::indices,distancereg
real ::d_min
integer::y,i_min,j,i
integer,parameter :: data_dim=2
allocate (indices(n))
allocate (distancereg(k))
!cost=0.d0
do j=1,n
i_min = -1
d_min=1.d6
do i=1,k
distance=0.d0
distancereg(i)=0.d0
do y=1,data_dim
distance = distance+abs(r(y,j)-centroid(y,i))
distancereg(i)=distancereg(i)+abs(r(y,j)-centroid(y,i))
end do
if (distance<d_min) then
d_min=distance
i_min=i
end if
end do
if( i_min < 0 ) print*," found error by assigning k-index to particle ",j
indices(j)=i_min
end do
What I want to do is, when I calculate distance for each k, I want to paralelize it. ie. Assign each thread to do it. For example if k=3, then for k=1 the distance calculated by thread 1, and so on. I have tried with omp_nested, omp_ordered, but still showing some error. will appreciate if there is any advice / guidance .
Thanks
If you want to parallelize a loop (or loop nest) you have to wonder first which iterations are independent. In your case, each outer j iteration computes an i_min value that is 1. initialized in each i iteration, and 2. written into location (j). So each i_min calculation is independent and you can make the j loop parallel. (You also have d_min but that is never used.)
If the j loop is long enough that should be enough to get high performance. You might be tempted to look at the next loop over i. It computes a separate distance value for each iteration, so that's again parallel. Except that you update i_min,d_min, so you need to declare that loop a reduction.
However, the two loops are not "perfectly nested", so you can not spread the total i,j iteration space over the threads.
TLDR: your outer j loop can be parallelized.
What simply about:
do j=1,n
distancereg(:)=0.d0
!$OMP PARALLEL DO PRIVATE(y)
do i=1,k
do y=1,data_dim
distancereg(i)=distancereg(i)+abs(r(y,j)-centroid(y,i))
end do
end do
!$OMP PARALLEL END DO
indices(j)=minloc(distancereg,dim=1)
end do
Since you are storing the distances for each i, the search for the minimum value can be postponed after the loop on i
Or parallelizing the outer loop (here you don't need to store the distances):
!$OMP PARALLEL DO PRIVATE(i,y,i_min,d_min,distance)
do j=1,n
i_min = -1
d_min=1.d6
do i=1,k
distance=0.d0
do y=1,data_dim
distance = distance+abs(r(y,j)-centroid(y,i))
end do
if (distance<d_min) then
d_min=distance
i_min=i
end if
end do
if( i_min < 0 ) print*," found error by assigning k-index to particle ",j
indices(j)=i_min
end do
!$OMP END PARALLEL DO

Can a recursive function containing a for loop that contains a call of the mentioned function be implemented using only for loops?

Similar questions have been asked and the general consensus is that anything can be converted from recursion to for loops and vice versa. However, I can't find a way to convert a function of the following pseudocode type to a for loop:
def recursive(n):
if n == 0:
return
for i in range(some_number):
do_sth...
recursive(n-1)
In this case, there is n nested loops and n varies depending on the given argument. When using only for loops, the number of nested loops seems to be always predetermined in the code, it doesn't vary depending on "input". Is there a way to make something like this using only for loops?
Is there a way to make something like this using only for loops?
Well, if you admit a while loop as a case of a pseudocode for loop, at least your example can be made:
def nonrecursive(n):
a = []
z = 0
while n:
while n:
i = z
if i == some_number: break
print((n, i))
a += [[n, i]]
n -= 1
z = 0
if not a: break
n, i = a.pop()
i += 1
z = i
We need to be careful here.
The general true statement is that loops can replace recursion and vice versa. This can be shown lots of ways; see the structured programming theorem for ideas.
Whether for loops can replace recursion depends upon your definitions. Can your for loops run forever, or for an indefinite amount of time not known in advance? If so, they are functionally equivalent to while loops, and they can replace recursion. If your for loops cannot be made to run forever or for an unknown (initially) number of iterations, recursion cannot always be replaced.
Really, it's while loops (plus a stack data structure) that can replace recursion without much trouble.

Infinite for loop in Lua

Why doesn't this work in lua?
for i = 1, 100, -1 do
print('Infinite')
end
The above loop prints nothing. From what I know from conventional languages like C/C++, the above should be an infinite loop.
C++ equivalent
for (int i = 1; i <= 100; i--)
cout << "Infinite";
I want to know how exactly a for loop in lua works. Isn't it the same as the C++ one given above?
Edit: I don't want to know How to make an infinite loop in lua. I am more concerned here with how a for loop in lua works?
As stated before, the for loop has three functions just like C/C++.
for i = <start>, <finish>, <increment> do
But lua will detect that the increment will not allow the function to end and will completely ignore this loop.
To create an infinite loop, you simple use:
while true do
In lua, putting a variable as an argument with no operator will check if the value exists/is true. If it is false/nil then it will not run. In this case, true is always true because it is constant so the loop goes forever.
while true do
print('Infinite Loop')
end
for is explicitly defined in Lua to check if current value is lower than limit if step is negative. Since step -1 is negative and current value 1 is lower than limit 100 right from the start, this for performs no loops.
A for loop in lua has the syntax below:
for init,max/min value, increment
do
statement(s)
end
so the code below will print from 1 to 10:
for i=10,1,-1
do
print(i)
end
To generate infinite loops in lua you might have to use while loops:
while( true )
do
print("This loop will run forever.")
end
for more visit http://www.tutorialspoint.com/lua/lua_loops.htm

End of array in variable in julia

I would like to slice an array a in Julia in a loop in such a way that it's divided in chunks of n samples. The length of the array nsamples is not a multiple of n, so the last stride would be shorter.
My attempt would be using a ternary operator to check if the size of the stride is greater than the length of the array:
for i in 0:n:nsamples-1
end_ = i+n < nsamples ? i+n : end
window = a[i+1:end_]
end
In this way, a[i+1:end_] would resolve to a[i+1:end] if I'm exceeding the size of the array.
However, the use of the keyword "end" in line 2 is not acceptable (it's also the keyword for "end of control statement" in julia.
In python, I can assign None to end_ and this would resolve to a[i+1:None], which will be the end of the array.
How can I get around this?
The end keyword is only given this kind of special treatment inside of indexing expressions, where it evaluates to the last index of the dimension being indexed. You could put it inside with e.g.
for i in 0:n:nsamples-1
window = a[i+1:min(i+n, end)]
end
Or you could just use length(a) (or nsamples, I guess they are the same?) instead of end to make it clear which end you are referring to.
Ugly way:
a=rand(7);
nsamples=7;
n=3;
for i in 0:n:nsamples-1
end_ = i+n < nsamples ? i+n : :end
window = #eval a[$i+1:$end_]
println(window)
end
Better solution:
for i in 0:n:nsamples-1
window = i+n < nsamples ? a[i+1:i+n] : a[i+1:end]
println(window)
end
In order to simplify the loop (and perhaps improve performance) the last partial window can be processed after the loop. This is recommended since it usually requires some special processing anyway. In code:
i = 0 # define loop variable outside for to retain it after
for i=n:n:length(a)
println(a[(i-n+1):i])
end
i < length(a) && println(a[(i+1):end])
The last bit can be done with an if but && is pretty clear.

Start one loop where another one stopped

I have a loop that internally unrolls a sparse matrix vector multiplication. We calculate this using a diagonal approach for the upper right matrix with leads to a different length for each diagonal.
The unrolling then happens linewise, i.e. I calculate several diagonals at once, until the shortest diagonal reaches the end of the matrix. Then I want to calculate the remaining diagonals with another loop with decreased unrolling length.
This leads to the problem that the second loop needs to start where the first loop has ended. I'm now stumbling upon a construct like the following (very simplified):
do diag=1, nDiagonals-3, 4
! here be dragons
end do
do diag=diag, nDiagonals-2, 3
! here be smaller dragons
end do
In Fortran the do index has to be set in the control clause, in contrast to C where for(;n<m;==n) is a possible loop control clause. But is the construct above with do index=index, upperbound valid? Or are there better approaches for this kind of loop index handling?
I can't see anything syntactically wrong with your code, nor do I think you are doing anything dangerous if legal.
After the end of the first loop diag will have the value it would have if the loop continued for one more iteration. This behaviour is defined by the standard. Given the snippet
do diag = start, stop, stride
! do stuff
end do
at the end of the loop diag has value equal to (start + n*stride) where n is the smallest integer such that (start + n*stride)>stop
So, for a loop such as
do diag = 1,10,3
! do stuff
end do
! now diag == 13
and you can carry on using it to start the next loop as you outline.
What you can't do, in Fortran, is adjust the value of the do-variable inside the loop, the compiler behaves as if it establishes the loop limits at the first encounter with the do statement.

Resources