Suppose I have a 1D array, for example, A(1:10) and I want to do an operation on all the elements of this array except the 3rd element (let's say). How can I skip this element while doing an operation? A(1:10)=2*A(1:10) will multiply all the elements of this array with 2 but suppose I don't want to multiply the 3rd element by 2. How do I do that in Fortran?
-
In this particular case, I would just do: `A=2*A; A(3)=A(3)/2` – kvantour May 08 '20 at 10:09
3 Answers
There is no basic operation in Fortran which says to select a particular set of elements of an array based on an exclusion criterion. However, there are several approaches available with more complicated effort.
If one can construct an array of desired indexes to include then vector subscripting can be used
integer a(10)
integer, allocatable :: idx(:)
idx = [...] ! An array constructor of the desired elements to select
a(idx) = 2*a(idx)
such an array constructor for the case of the question may well be idx=[1,(i,i=3,10)]
. We can build up this array in many statements, or not even even use a variable for the vector subscript.
We can select elements of an array to act on with a WHERE construct
integer a(10), i
a = 1
where ([(i,i=1,10)]/=2) ! Or other selecting expression
a = 2*a
end where
(For Fortran 90 as tagged, use array constructors (/(...)/)
instead.)
There are also approaches around array sections (as in the answer by Tine198), or just simply using exclusion in a loop:
do i=1, 10
if (i==2) cycle ! Or other element exclusion criterion
a(i) = 2*a(i)
end do

- 30,576
- 16
- 61
- 96
-
Thank you so much for your suggestions. I'm well aware of the above methods suggested by you. Actually the example I chose is quite a simple one, the actual procedure involves huge calculations to be performed on several different elements of an array, which is basically a 6D array. I was just wondering whether there is such functionality in Fortran which allows us to slice our arrays as we want. – MOHAMMAD UMAIR May 08 '20 at 04:51
As others replies have pointed out, there are several ways to accomplish that, but the option I like the most hasn't been listed, i.e., using a FORALL
statement:
forall (i=1:10,i/=3) A(i)=2*A(i)
For some reason, this is becoming obsolescent in Fortran 2018, but I believe it's the most clear, concise and vectorizable way to get what you need.
Another concise way to do that would be if you have a pure array index function stored somewhere else, like:
pure function arrayI(n) result(indices)
integer, intent(in) :: n
integer :: indices(n),i
forall(i=1:n) indices(i)=i
end function arrayI
and then solve your problem with a single line of code like
where (arrayI(10)/=3) a=2*a

- 1,414
- 8
- 13
-
For some of the reasons for dropping `for all` see https://stackoverflow.com/questions/8602596/fortran-forall-restrictions and some of the references it points you at. These days many prefer `do concurrent` which does not have the issues that `for all` has. – High Performance Mark Jun 17 '20 at 16:33
-
Thanks @HighPerformanceMark for the link - Yeah it looks like the decision was based on compiler performance, but to me, making code as short as possible is really important, especially when handling large projects. Fortran 90/95 was really good at that with all its "Matlab-style" syntax, you could get a lot in a single line, and I still see no better language in that yet. Modern Fortran is much worse from a readability standpoint, with all its `%`s and `very%long%variable%names` .... – Federico Perini Jun 17 '20 at 16:47
If it is just one element you could save it first to another variable and then rewrite its value after the operation:
backup=A(i)
A=2*A
A(i)=backup
another option would be to explicitely exclude it
A(:i-1)=2*A(:i-1)
A(i+1:)=2*A(i+1:)

- 136
- 3