Samanosuke Akechi
Samanosuke Akechi

Reputation: 361

Input a sequence of numbers in a Fortran list

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

Answers (2)

High Performance Mark
High Performance Mark

Reputation: 78354

Given A and B as in your question you could first declare an array of logicals 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

francescalus
francescalus

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

Related Questions