Reputation: 361
I am facing the following problem:
I want to loop over a specific sequence of numbers e.g.
1 3 4 6 7 9 10 .... 528
I have thought a way to do it but I am not so familiar with fortran. The idea is to create a list with the numbers which are not in the sequence:
B=(/2 5 8 11 .... 527/)
and deduce this list from another one with all the numbers
A=(/1 2 3 4 5 6 7 8 9 10 11 ..... 528/)
C=A-B
What I was thinking is something like:
program test
implicit none
integer, dimension(6) :: A
integer, dimension(10) :: B
integer :: i, j
A = (/ 1 2 3 4 5 6 7 8 9 10 11 ..... 528/)
B = (/ 2 5 8 11 .... 527/)
C=A-B
end program test
Is this the correct way to do it? If yes how can I deduce two lists?
Upvotes: 1
Views: 1609
Reputation: 78354
Given A
and B
as in your question you could first declare an array of logical
s and set all its elements .true.
, ie:
logical, dimension(size(A)) :: themask = .true.
Then the expression
themask(B) = .false.
will set to .false.
all the elements of themask
in the index vector B
and
C = pack(A,themask)
will return, in C
, only those elements of A
for which the corresponding element in themask
is .true.
. For this to work you will have to have declared C
like this:
integer, dimension(:), allocatable :: C
and be using a Fortran 2003-compliant compiler which allows automatic allocation. Most of the current widely used compilers do implement this feature.
If you have no use for A
other than for holding a list of N
integers, you can just work with a temporary along the lines of
C = pack([(ix, ix = 1,N)],themask)
where ix
is a previously-declared integer. This expression -- [(ix, ix = 1,N)]
-- uses an implied-do loop to populate the temporary vector.
You can now loop over the values of C
if that is what you want to do, but maybe you want to use C
as a vector index into another rank-1 array, such as D(C)
.
No fiddling around with loops here but I make no claims that this approach will perform better (or worse or different) than the loop-based suggestion from @francescalus.
Upvotes: 3
Reputation: 32406
Your -
isn't a set complement operator, so C=A-B
doesn't return an array (which you haven't declared) consisting of the values in A not in B.
However, you don't need to do this for your desire:
do i=1, 528
if (....) ! i not in B
....
end do
Of course, the tricky part is in the if
condition. However, if B is sorted:
j = 1
do i=1, 528
if (i.eq.B(j)) then
j = j+1
cycle
end if
...
end do
Upvotes: 2