Incorrect f2003 syntax?

Incorrect f2003 syntax?

I have the following assignment in my code:

factors = factors(:,f)

Is this not allowed with automatic de- and reallocation (f2003) on the 2013 compiler?
I get the following error: The shapes of the array expressions do not conform.   [FACTORS]

And btw, since in my case f<SIZE(factors,2) will the compiler do this in-place, ie. not by copying the section of factors to a temporary array?
What is the best way if I want to increase the bounds? Is that possible without making an explicit copy to a temporary array in my code?

8 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

You have a rank 1 expression on the right hand side. Try using

factors = factors(:,f:f)

Jim Dempsey


jimdempseyatthecove wrote:

You have a rank 1 expression on the right hand side. Try using

factors = factors(:,f:f)

Jim Dempsey

This is true, but doesn't of the Fortran 2003 standard suggest that the original code is acceptable (with /standard-semantics)?
22 If variable is an allocated allocatable variable, it is deallocated if expr is an array of different shape
23 or any of the corresponding length type parameter values of variable and expr differ. If variable is or
24 becomes an unallocated allocatable variable, then it is allocated with each deferred type parameter equal
25 to the corresponding type parameters of expr , with the shape of expr , and with each lower bound equal
26 to the corresponding element of LBOUND(expr ).

You can't change the rank this way.

For example, Intrinsic Assignment (F2008) says (bolding mine)

(3) the variable and the expr shall be conformable unless the variable is an allocatable array that has the same rank as expr and is neither a coarray nor a coindexed object

You can change the extents of each bound, but not the number of bounds.

Retired 12/31/2016

"shape" in the above standard refers to the extent of the bound limits of each of the ranks (dimensions).

>>If B is declared as B(2:4, -3:1), then SHAPE (B) has the value (3, 5).

Two arrays that differ in rank also differ in shape.

Two arrays of same rank but different entent of bound limits differ in shape.

real :: A(10,20), B(30,40), C(200), D(-5:4,-10:9)

SHAPE(A) (10,20)
SHAPE(B) (30,40)
SHAPE(C) (200)
SHAPE(D) (10,20)

Shape of A and D the same

Jim Dempsey

Thanks Steve and Jim. That makes sense because the object would then not match its original declaration in terms of rank if the assignment in the OPs post was allowed.

Thank you all, it was a STUPID mistake by me not to remember the colon before the f...
On the other hand, if I actually wanted the extent of the 2nd dimension to be 1, ie. SIZE(factors,2) == 1, how would I accomplish that using array slicing?

And my questions regarding usage of internal temporaries still remains:
And btw, since in my case f

If I understand correctly, Jim's reply gives you SIZE(factors,2) == 1.

"best" implies some sort of judgement about what's best (speed/code clarity, etc). Out of performance sensitive regions I very much tend to go for clarity, and personally I find the array operation syntax clearer than the possible multiline options that may help the compiler avoid a temporary.

(To be honest - I've not bothered to check whether the compiler does generate a temporary with some of these array syntax idioms, but I did have some stack overflow issues a while back that strongly indicate to me that's exactly what was happening with some of my code. Regardless, F2003 is still quite new compiler wise, so things should only get better, and if clear and concise syntax is obvious to me as a source reader as to the intent of a line of code then its probably not too far a step for it to be clear to an optimiser.)

So for chopping - code as presented by Jim. For growing a 1D array, where I know what the new bit is going to be, I simply do "array = [ array, new_bit ]" (being mindful that if array is a derived type with interesting components, then the compiler has been known to generate interesting code). For rank > 1, or when new_bit is yet to be figured out, I use a temporary allocatable and allocate bigger, copy, then swap:

  allocate(tmp(size(array,1), size(array,2)+extra))

  tmp(:,:size(array,2)) = array

  call move_alloc(tmp, array)

(If the lower bound of array isn't 1 then modifications to the above required.)

But I have been accused of profligacy in the past with respect to things like temporaries, etc. If you do some actual measurements I'd be interested in hearing about them.

Leave a Comment

Please sign in to add a comment. Not a member? Join today