To: J3 J3/19-173 From: Van Snyder Subject: Rank-agnostic array declaration Date: 2019-July-05 References: 19-110r1 19-150 18-247 Background ========== 19-110r1 proposed rank-agnostic array declarations of the form real :: X(A) ! bounds of X == bounds of A real, rank=rank(B), allocatable :: Y ! Deferred shape real, rank=rank(C), pointer :: P ! Deferred shape real, rank=rank(D), intent(...) :: Z ! Assumed shape tbat would declare objects having the ranks of A, B, C, and D respectively. In the fourth case, intent(...) is, of course, not required; that Z is a dummy argument would be obvious without it. Assuming a dummy argument were declared using real, intent(in) :: A(:,:,:) The obvious utility of real :: X(A) ! bounds of X == bounds of A to declare an automatic "work" array, as opposed to real :: x(lbound(a,1)-1:ubound(a,1)+1, & & lbound(a,2)-1:ubound(a,2)+1, & & lbound(a,3)-1:ubound(a,3)+1) ) or an allocatable "work" array real, allocatable :: X(:,:,:) ... allocate ( x(lbound(a,1)-1:ubound(a,1)+1, & & lbound(a,2)-1:ubound(a,2)+1, & & lbound(a,3)-1:ubound(a,3)+1) ) was described in 19-110r1. In a generic-programming context, one might declare module M(Q) real, rank=rank(Q), intent(in) :: A ! Assumed shape real :: X(A) ! SHAPE(X) == SHAPE(A) ! or real, rank=rank(Q), intent(in) :: A ! Assumed shape real, rank=rank(A), allocatable :: X ! Deferred shape ... allocate ( x(A) ) ... end module M The utility here is obvious. The British might say "bleeding obvious." The response from JOR to the proposals in 19-110r1 was "Huh?" even though there was an admonition in 19-110r1 If you don't understand the implications of this, PLEASE ASK FOR MORE EXPLANATION! There is nothing in DIMENSION(..) and SELECT RANK that provides any support in this direction. Nobody asked for illumination. The predecessor of 19-110r1, 18-247, was dismissed by JOR as being the same as vector subscripts, even though specifying the bounds of an array has nothing to do with subscripting, and the final example in 18-247 said This provides a more general scatter/gather facility than the present vector subscript facility. This is not the same as using the elements of the rank-one sections in S as vector subscripts... and S is NOT a vector subscript. appeared in the paper. Proposals ========= 1. Explicit shape ----------------- Allow a rank-one array with extent given by a constant expression to specify the rank and bounds of another array, e.g. real :: X(A) declares an array X such that RANK(X) == RANK(A), and X has the same bounds (not just shape) as A. The bounds of A shall be specified by constant expressions (any of its lower bounds might be the default "1" value). One bound of X could be a scalar, which is "broadcast" to the same shape as the other bound (which determines the rank), e.g., allow real :: X ( 0 : shape(A)+1 ) ) instead of requiring real :: X ( [ ( 0, i = 1, rank(A) ) ] : shape(A)+1 ) ) 2. Deferred shape ----------------- 2.1 Deferred-shape object declaration ..................................... Allow to specify the rank of an allocatable or pointer object using a RANK attribute, e.g. real, rank=rank(B), allocatable :: Y ! Deferred shape real, rank=rank(C), pointer :: P ! Deferred shape For example, if SIZE(B) = 3, this is equivalent to real, allocatable :: Y(:,:,:) which is not useful in a generic-programming context. Whether B or C being a scalar is prohibited (e.g., in a generic-programming context), results in declaring a scalar, or results in declaring a new entity called a rank-zero array, can be decided in due course. 2.2 Deferred shape object allocation .................................... Allow to allocate a deferred-shape object using a rank-one object of explicit shape and constant extent to specify bounds, e.g. allocate ( Y ( A ) ) ! lbound(Y) == [1,1,...], ubound(Y) == A, ! SIZE(A,1) is a constant expression or, more generally allocate ( Y ( B : A ) ) ! lbound(Y) == B, ubound(Y) == A, SIZE(A,1) ! == SIZE(B,1) are constant expressions e.g., allocate ( Y ( lbound(A)-1 : ubound(A) + 1 ) insead of requiring allocate ( Y(lbound(a,1)-1:ubound(a,1)+1, & & lbound(a,2)-1:ubound(a,2)+1, & & lbound(a,3)-1:ubound(a,3)+1) ) The latter is not useful in a generic-programming context, wherein RANK(Y) depends upon a generic parameter. One bound could be a scalar, which is "broadcast" to the same shape as the other bound, e.g. allocate ( Y ( 0 : shape(A)+1 ) ) instead of requiring allocate ( Y ( [ ( 0, i = 1, rank(A) ) ] : shape(A)+1 ) ) If the object (Y in the examples) is (allowed to be) a scalar, the object used to declare the bounds (A in the examples) shall be an array, and its extent shall be zero. 2.3 Pointer rank remapping .......................... In a rank-remapping pointer assignment, the upper bounds of a pointer object can be specified by a single rank-one array whose extent is a constant expression P(A) => M(...) in which case the lower bounds are all 1, or both bounds can be specified by rank-one arrays whose extents are constant expressions that have the same value P( lbound(A)-1 : ubound(A)+1 ) => M(...) instead of requiring P( lbound(A,1)-1 : ubound(A,1)+1, & & lbound(A,2)-1 : ubound(A,2)+1, & & lbound(A,3)-1 : ubound(A,3)+1 ) => M(...) The latter is not useful in a generic-programming context, wherein RANK(A) depends upon a generic parameter. In all cases, the rank of P is the extent of the bounds. One set of bounds could be specified by a scalar, which is "broadcast" to the same extent as the other bound, which specifies the rank, e.g. P ( 0 : shape(A)+1 ) => M(...) instead of requiring P ( [ ( 0, i = 1, rank(A) ) ] : shape(A)+1 ) => M(...) 3. Assumed shape ----------------- Allow to specify the rank of an assumed-shape object using a RANK attribute, e.g. real, rank=rank(B) :: Y ! Assumed shape if Y is a dummy argument ! even if the INTENT attribute is not ! specified For example, if SIZE(B) = 3, this is equivalent to real :: Y(:,:,:) which is not useful in a generic-programming context. Whether B being a scalar is prohibited (e.g., in a generic-programming context), results in declaring a scalar, or results in declaring a new entity called a rank-zero array, can be decided in