To: J3 J3/15-163 Subject: Alternative to SELECT RANK From: Van Snyder Reference: 15-007r1, 04-195, 13-216 Date: 2015 June 07 1. Introduction =============== A SELECT RANK construct has been proposed to allow access to assumed rank dummy arguments. It was inscrutably crippled, for no specified reason, by prohibiting its use with specific-rank objects. An alternative that has broader applicability and is simpler to use can be based upon what was proposed in 04-195 and 13-216. The proposal in 04-195 is extended here to cover essentially everything that a SELECT RANK construct would offer, with equal security. 2. Proposal =========== Allow a rank-1 extent R integer array to specify all the subscripts of a rank R array or assumed-rank entity. The result is a scalar. This allows the result of, e.g., FINDLOC to be directly usable as a subscript if DIM is not present. For example print *, A(findloc(A%key,hunt))%value works whether the array A is of specified or assumed rank. Allow a rank-1 extent R integer array and one or two conformant expressions to specify all subscripts and strides of a rank R array or assumed-rank entity. The result is a rank R array section if R > 0, else it is a scalar. For example print *, A( [ ( 1, i = 1, rank(A) ) ] ) prints the (1,1,...1) element of the array A, no matter whether A is of specified or assumed rank, and print *, A( [ ( 1, i = 1, rank(A) ) ]: [ ( w, i = 1, rank(A) ) ] ) prints the (1:2,1:2,...1:2) section of the array A, no matter whether A is of specified or assumed rank. Allow a rank M+1 integer array, with M > 0 and extent R in its first dimension, to be the subscript of a rank R array or assumed-rank entity. The result is a rank M array section, having the same shape as dimensions 2..M of the subscript, if R > 0, else it is a scalar. This is a vector subscript, and the rules concerning vector subscripts, appropriately generalized, apply. A subscript triplet having M > 0 should not be allowed, because the result would have rank M*R. C613a, C613b, and subclause 5.5.8.2.2 in the proposed edits below ensure that a subscript of this form for an assumed-rank array has the same (first) extent as the rank of the array. It is therefore equally as secure as a SELECT RANK construct, but easier to use, and has far more utility. Allow assumed-rank pointers and pointer targets. Allow a rank-1 extent R integer array to declare the lower or upper bounds of an explicit-shape array, or the lower bounds alone of an assumed-shape array, which array is declared to have rank R. This allows, e.g., UBOUND without a DIM argument, to be used directly as an array bound. For example real :: B ( lbound(A) : ubound(A) ) declares an array B that has the same rank and bounds as A, even if A is of assumed rank. This is much simpler than, for example real :: B ( lbound(A,1) : ubound(A,1) , & & lbound(A,2) : ubound(A,2) , & & lbound(A,3) : ubound(A,3) , & & lbound(A,4) : ubound(A,4) ) which cannot be used if A is of assumed rank. See 13-216. Allow a rank-1 extent R integer array to declare the lower bounds of an assumed-rank array of rank R. Allow a rank-1 extent R integer array to declare the lower bounds or both bounds of a data pointer object in a pointer assignment statement. 3. Edits ======== {Allow to declare an array using an array to specify either the lower or upper bounds, or arrays to specify both.} [98:8+ R515] Add an alternative to R515 : " <> " [98:9+ R515] Add an alternative to R515 : " <> " [98:15+ 5.5.8.2p1-] Insert a subclause header: "5.5.8.2.1 Shape specification" [98:18+ R518+] Define : " R518a <> [ : ] \smudge \smudge <> R518b <> <> R518c <> <> R518d <> [99:2+ C532+] Add constraints that guarantee an array that is not an assumed-rank array has constant rank: " C532a (R518d) A shall be a rank-1 specification expression. In an or it shall have constant extent (5.5.8.2.2). " {Requiring constant extent prevents assumed-rank automatic variables.} C532b (R518a) If and both appear, either they shall be s that have the same extent, or one shall be a . C532c (R518a) A or that is not a constant expression shall appear only in a subprogram, derived type definition, BLOCK construct, or interface body. " {No provision is made for type parameters to be arrays, so if appears in a component declaration, it will necessarily be either a named constant or an array constructor, not a type parameter value.} [99:3-4 5.5.8.2p1] After "" insert "or ". Replace "The" with "If the shape is specified by ". Append a sentence to the end of the paragraph: "If the shape is specified by the rank is equal to the extent of whichever of or is not a scalar." [99:12 5.5.8.2p3] Before "The value" insert the following as a new paragraph: "The values of the elements of , or the value of if it is a scalar, specify the lower bounds of all dimensions. The values of the elements of , or the value of if it is a scalar, specify the upper bounds of all dimensions. If does not appear, the lower bound in every dimension is 1." Then start a new paragraph with "The value...." {Define the terms "constant extent" or "extent determined by reference to the RANK intrinsic function:} [99:15+ 5.5.8.2p3+] Insert a subclause "5.5.8.2.2 Determinable extent "The extent of a dimension of an explicit-shape array is either constant, or equal to the value of a reference to the RANK intrinsic function with an assumed-rank argument, if the array is o a constant expression, o an explicit-shape variable and the lower and upper bounds of the dimension in question are constants if the condition is that the extent be constant, or one is a constant and the other is a reference to the RANK intrinsic function, o an array constructor, every is a scalar or an array that has constant extent in every dimension, and the iteration count meets the condition, o the result of an intrinsic elemental operation and the extent in the dimension in question of the operand that determines the shape of the result meets the condition, o the result of the intrinsic function ALL, ANY, COUNT, or PARITY, the DIM argument appears and is a constant expression not equal to the dimension in question, and the dimension of the MASK argument that determines the extent in the dimension in question of the result meets the condition, o the result of the intrinsic function CSHIFT, EOSHIFT, MAXVAL, or MINVAL, and the dimension in question of the ARRAY argument meets the condition, o the result of the intrinsic function FINDLOC, MAXLOC, MINLOC, PRODUCT, or SUM, and either the DIM argument does not appear, or DIM appears, is a constant expression not equal to the dimension in question, and the dimension of the ARRAY argument that determines the extent in the dimension in question of the result meets the condition, o the result of the intrinsic function IALL, IANY, or IPARITY, the DIM argument appears and is a constant not equal to the dimension in question, and the dimension of the ARRAY argument that determines the extent in the dimension in question of the result meets the condition, o the result of the intrinsic function LBOUND or UBOUND, the ARRAY argument is not assumed rank if the condition is that the extent is constant, and the DIM argument does not appear, o the result of the intrinsic function LCOBOUND or UCOBOUND, and the DIM argument does not appear, o the result of the intrinsic function PACK, and either the MASK argument is a constant array, the VECTOR argument appears and its extent meets the condition, or VECTOR does not appear, MASK is a scalar with the constant value true, and the extent in the dimension of ARRAY meets the condition, o the result of the intrinsic function RESHAPE, the SHAPE argument is an array constructor or a named constant, and the element of the SHAPE argument that determines the dimension in question of the result meets the condition, o the result of the intrinsic function SPREAD,the DIM argument is a constant expression and either the value of DIM is not the dimension in question and the extent in the dimension in question of SOURCE meets the condition in the dimension in question, or the value of DIM is a constant expression equal to the dimension in question and NCOPIES meets the condition, o the result of the intrinsic function TRANSFER, and the SIZE argument appears and meets the condition, o the result of the intrinsic function UNPACK and the extent in the dimension in question of the MASK argument meets the condition, o the result of an elemental function that has an array result and the dimension in question of the array argument that determines the shape of the result meets the condition, or o the result of a nonelemental nonintrinsic function that has an array result and the dimension in question of the result meets the condition. {Defined :} [99:19+ R519+] Insert a syntax rule: "R519a <> :" [99:20 5.5.8.3p2] Replace "The" with "If appears, the". Append a sentence: "If appears, the rank is the extent of ." {C532a above ensures the rank specified by the extent of is a constant.} [99:20+ 5.5.8.3p2+] Insert a paragraph: "If appears, each element specifies the lower bound of the corresponding dimension of the dummy argument array." [99:24+ 5.5.8.3p3+] Insert a note: "NOTE 5.12a The declarations real :: A ( -1:, 0:, 1: ), B ( lbound(a) : ) declare A and B to be assumed-shape dummy argument arrays. The array B has the same rank and lower bounds as the array A. " {Allow to specify lower bounds for assumed-rank objects:} [101:10 R525] Replace R525: "R525 <> [ : ] .." [101:20 C540+] Insert a paragraph: "If appears and has extent greater than zero, each element specifies the lower bound of the corresponding dimension of the assumed-rank entity." {It will be seen below in C540a that the extent of is necessarily the same as the rank of the array being declared.} {Allow assumed-rank pointers:} [101:12 C538] After "attribute" insert ", or shall have the POINTER attribute." {Allow a subscripted assumed-rank object. The subscript will be seen in edits for [123:8+] to be a rank-1 array of extent equal to the assumed rank.} [101:13 C539] Replace "in a designator or expression" with "without a subscript," {If no other part of this proposal is accepted, replace the proposal for SELECT RANK with the following edit, and edits below for pages 162 and 163:} [101:15 C539] After "except" insert "as the in a pointer assignment statement" [101:20+ C540+] Insert a constraint: " C540a (R525) If appears it shall be a rank-one integer array whose extent is equal to the rank of the dummy data object being declared (5.5.8.2.2). " {Specify the requirements on .} [123:1 R612] Replace "( )" with "". [123:1+ R612+] Insert syntax rule: " R612a <> ( ) <> ( ) R612b <> ( ) <> ( ) " [123:7 C613] After "appears" insert "and is not of assumed rank" [123:8+ C613+] Add constraints: " C613a (R612a) If is of assumed rank and is neither an actual argument nor a or in a pointer assignment statement, shall appear. If is of assumed rank, shall not appear. C613b (R612a) The extent of the first dimension of shall be equal to the rank of (5.5.8.2.2). The extent of the first dimension of each or of that is not a scalar shall be equal to the rank of (5.5.8.2.2). That extent shall be constant if is not of assumed rank. " {C613a and C613b ensure that the (first) extent of the is equal to the rank of the . This is equally as secure as a SELECT RANK construct, and simpler to use.} [123:10 C615] Replace "" with "". [123:18+ C618+] Insert paragraphs that define the rank of : "If is of assumed rank and does not appear, is of assumed rank. "If is not of assumed rank and does not appear, or appears, the rank of the is its declared rank. If appears, the rank of is the number of s that are . "If appears, the rank of is one less than the rank of . If appears the rank of is the rank of ." {Specify how subscripting using array subscripts works:} [125:26+ R620+] Insert syntax rules: " R620a <> R620b <> [ ]:\smudge \smudge [ ] \smudge \smudge [ : ] R620c < <> " [126:5+ C627+] Insert constraints and paragraphs: "C627a (R620a) shall not be a scalar. "C627b (R620b) shall be a scalar or a rank-1 array. "C627c (R620b) shall be a scalar or a rank-1 array. "C627d (R620b) At least one or shall appear and not be a scalar. "C628c (R620b) The shapes of s and shall conform. "Denote by S. If S has shape [ $n_1$ ], the effect is as if $n_1$ s appeared, with the $i^\text{th}$ subscript having the value S($i$), and $i$ taking all values within the bounds of S; the has rank zero. "If S has shape $[ n_1, n_2, ..., n_{m+1} ]$, the shape of is $[ n_2, ..., n_{m+1} ]$. The $( i_2, ... i_{m+1} )$ element of is the element selected by the array subscript S( :, i_2, ..., i_{m+1} )$, where each $i_k$ independently takes all values within the bounds of the $k^\text{th}$ dimension of S. "If appears in , the effect is as if a number of s equal to the extent of an array in had appeared, in which the $i^\text{th}$ consisted of the $i^\text{th}$ element of the first , or the value of the first if it is a scalar, or the lower bound of the $i^\text{th}$ dimension of the array if the first does not appear, followed by the $i^\text{th}$ element of the second , or the value of the second if it is a scalar, or the upper bound of the $i^\text{th}$ dimension of the array if the second does not appear, followed by the $i^\text{th}$ element of , or the value of if it is a scalar, or 1 if does not appear." [127:6+ 6.5.3.3p1+] Insert a paragraph and note: "In an having that is and has rank greater than one, the rank of the array section is one less than the rank of the . If the shape of the is $[n_1, n_2, ..., n_{m+1}]$, the shape of the array section $[n_2, ..., n_{m+1}]$. Each rank-one section of the on its first dimension specifies a set of subscripts for the . Each element of the array section is an element of the selected by one of those rank-one sections, in the same position in the array section as the rank-one section is in the ." "NOTE 6.11a Assume array A3 has dimensions (10,10,10). Assume a rank-two array [ 3 4 ] S2 = reshape ( [ 3, 6, 5, 4, 7, 8 ], [ 3, 2 ] ) = | 6 7 |. Then [ 5 8 ] the extent of the first dimension of S2 is 3, and S2 is therefore allowed as a subscript for A3. A3(S2) is a rank-one array section consisting of A3(3,6,5) and A3(4,7,8). The array [ A3(3,6,5), A3(4,7,8) ] has the same shape and values as A3(S2), but it is a copy of A3(S2), and it cannot appear in a variable-definition context. Assume array B has dimension (10). Assume a rank-three array S3 = reshape ( [ 3, 6, 5, 4, 7, 8 ], [ 1, 3, 2 ] ). Then the extent of the first dimension of S3 is 1 and S3 is therefore allowed as a subscript for. B(S3) is a rank-two array with elements [ B(3) B(4) ] | B(6) B(7) |. These are elements of B, not copies of their values. [ B(5) B(8) ] The array constructed by reshape ( [B(3), B(6), B(5), B(4), B(7), B(8)], [ 3, 2 ] ) is an array of the same shape and values as B(S3), but it is a copy of B(S3), and it cannot appear in a variable-definition context." {Define "vector subscript" to include subscripting by an array that has extent greater than one:} [128:1+ 6.5.3.3.2p1-] Insert a paragraph "A vector subscript is an array that is a subscript for a single dimension, or an array that specifies subscripts for all dimensions and has rank greater than one." [128:5 6.5.3.3.2p3] after "vector subscript" insert "is an array of rank one that". [128:6+ 6.5.3.3.2p3+] Insert a paragraph: "If a vector subscript is an array of rank greater than one and any two rank-one sections of the on its first dimension have the same sequences of values, an array section specified by that subscript is not definable and shall not be defined or become undefined." [130:15+ R631+] Add an alternative in R631: " <> ( ) \smudge \smudge [ ]" [130:20+ R635+] Insert syntax rules: "R635a <> [ : ] "R635b <> "R635c <> " [130:30+ C633+] Insert a constraint: "C633a (R635a) If and both appear, at least one of them shall be a rank-one array; otherwise, shall be a rank-one array array. The extent of the array (or arrays) shall be a constant equal to the rank of the (5.5.8.2.2)." [130:31 C633] After "" insert "or ". [130:33 C634] Replace "" with "neither nor ". [132:2 6.7.1.2p1] Replace "is specified" with "or appears". [132:5-6 6.7.1.2p1] Replace the final sentence of 6.7.1.2p1 with new paragraphs: "If is an array, each element specifes the upper bound of the corresponding dimension of . Otherwise it specifies all upper bounds of . If appears and is an array, each element specifes the lower bound of the corresponding dimension of . If appears and is a scalar it specifies all lower bounds of . If does not appear, the lower bound of each dimension is 1. "If the upper bound in any dimension is less than the corresponding lower bound, the extent in that dimension is zero and the array has zero size." [161:34+ R733] Insert an alternative " <> ( : ) => " [161:35+ R733] Insert an alternative " <> \smudge \smudge( : ) => " [162:8+ C717+] Insert constraints: "C717a (R733) If appears it shall be a rank-one array. If is not an assumed-rank entity, the extent of shall be a constant equal to the rank of (5.5.8.2.2)." C717b (R733) At least one of and shall be a rank-one array. If is not an assumed-rank entity, the extent of the array (or arrays) shall be a constant equal to the rank of the (5.5.8.2.2)." {If no other part of this proposal is accepted, replace the proposal for SELECT RANK with the following edits, and the second edit above for C539 on page 101:} [162:8+ C717+] Insert constraints: "C717c (R733) If is an assumed-rank entity, neither nor shall appear. "C717d (R733) If is of assumed rank, either shall be of assumed rank, shall be a scalar, or shall appear." [163:23+ 7.2.2.3p3+] Insert paragraphs: "If is a scalar and is an assumed-rank object that is a scalar, becomes associated with . If is a scalar and is an assumed-rank object that is an array, becomes associated with the first element of , in array element order. "If is an assumed-rank entity and neither nor appear, its rank becomes the rank of the . If is an assumed-rank entity and either or appears, its rank becomes the extent of whichever of or is an array; if they both appear, either one shall be a scalar, or they shall have the same extents." [163:35 7.2.2.3p9] Replace "; the" with ". If and appear they specify both bounds, and thus the extents, of all dimensions of the . If the pointer target is an assumed-rank entity the extent of whichever of or are arrays shall be equal to the rank of the pointer target (5.5.8.2.2); otherwise the" Replace ", and" with ". The pointer target". [164:1 7.2.2.3p9] After insert "or and . [164:5 7.2.2.3p10] replace "it" with "or appears and does not appear, or ". Replace "; otherwise," with ". If appears the extent of shall be equal to the rank of the pointer target (5.5.8.2.2). If neither nor appears,".