3

Fortran allows the use of array operations much easily. For example,

double precision :: a(3,3), b(3,3), c(3,3)

Given a and b are initialized, I am aware that a simple c=a+b would result in a matrix addition. The same can be achieved using c(:,:) = a(:,:)+b(:,:). I am aware that the second method allows slicing of arrays with the use of appropriate indexing. Apart from this, are there any differences between these two methods? Should a particular method be preferred over other?

4
  • If you cannot look under the hood to see what a particular compiler is doing, I would ecommend that if you can use whole array syntax (i.e, c = a + b) then you'll likely benefit (1, from code clarity, and 2, for performance). Commented Aug 24, 2019 at 22:04
  • Note if c is allocatable the former may lead it to be reallocated to the appropriate size if at the start of the operation it is not that already, while the latter will not. Commented Aug 25, 2019 at 7:37
  • 2
    See software.intel.com/en-us/blogs/2008/03/31/… Commented Aug 25, 2019 at 15:29
  • 1
    This question may also be relevant: stackoverflow.com/questions/25741884/… Commented Aug 25, 2019 at 17:48

1 Answer 1

4

In the expression

c = a + b

the references a, b and c are to whole arrays. In

c(:,:) = a(:,:) + b(:,:)

the references a(:,:), b(:,:) and c(:,:) are to array sections. These are different things.

In general an array section does not have the properties of the whole array: if c is a pointer or allocatable array even then c(:,:) is not. Such an aspect is most notable when reallocation may occur on assignment.

In c=a+b c may be unallocated and will be allocated in response, but in c(:)=... c must be allocated before the assignment. If c is allocated by the time of the assignment c=... then it will be deallocated if:

  • the right-hand side is a different shape from that of c; or
  • any length type parameters of the right-hand side differ from that of c; or
  • c is polymorphic and has either a different dynamic type or corresponding kind type parameters of the right-hand side expression differ from those of c.

If there is such deallocation then c is re-allocated to match the right-hand side expression.

With the array section no such freedom exists: c(:) must suitably match the right-hand side expression or there must be appropriate conversion available (including instead defined assignment).

There are other aspects following from the distinction of whole array and array section.

In the specific context of the question where the arrays are explicit shape then there is less to worry about.

In terms of style, one may view using the array section as adding clarity to human readers of code as "this is an array assignment" or using whole arrays as an aid to compilers in optimizing array operations. The balance between these is situation specific and King notes a related question which considers performance aspects.

Further, because of the deallocation/reallocation mentioned above, compilers are obliged to perform (potentially expensive) shape/type/type parameter checks on intrinsic assignment to allocatable whole arrays (to determine whether deallocation must happen). Using an array section means that these tests are not necessary. For example, with

c(:,:) = array_expr

the programmer guarantees that the array expression array_expr is of the same shape as c (if this is not the case then the fragment cannot be valid Fortran) and the compiler need not run the deallocation checks. Again, using this is a choice for the individual situation. (Also note that the compiler may offer runtime checks which look at whether such expressions match: if using this "trick" one should disable these checks.)

Sign up to request clarification or add additional context in comments.

4 Comments

Your answer has a few inaccuracies. The last paragraph is wrong. An array section won't disable checks for type parameters. Type conversion will happen as described in the Standard. While the use of an array section can disable reallocation, a shape mismatch is likely nonconforming anyway. A compiler may (not) notify a user of the mismatch. Underneath, a compiler can be aggressive. E.g., c = 0 can use a single memset to zero memory. A compiler may determine that c(:,:) is equivalent to the whole array, but it isn't require so a compiler may loop onver memory.
Yes, in the case of mismatching shape/parameter the array section code is non-conforming. My answer isn't intended to say to the contrary. The intention is that if you as a programmer know that there is matching use of the array section means the compiler doesn't need to check this. I will redraft to find a way to make that clear.
@francescalus This is significant if it is true. Which compilers already follow this convention to avoid reallocation checks?
@King That is not a convention, that is required by the standard semantics. See the link to Intel I provided above (Steven Lionel is alse a StsckOverflow regular). Any compiler is bound to follow this semantics when automatic reallocation is enabled.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.