ISO/IEC/JTC1/SC22/WG5-N1624 Repository of Requirements Version of 25 April 2005 (WG5 Standing Document 5 - supersedes N1613) This standing document is the vehicle by which WG5 manages the specification of requirements for future revisions of the Fortran standard. It is a working document of WG5. The Status: field is one of the following: For Consideration, Being Investigated, Accepted, Accepted with changes, Not accepted for the next revision, Rejected (reasons must be given), Being Developed. Status must not change from Accepted to Being Developed until the Specification field is complete. This field contains all relevant material for the chosen development body. If the status is Being Developed, an additional field is supplied: Target Date for Completion. The Severity Level is defined in N1594. When a proposed revision is adopted as a standard, Standing Document 5 is frozen and a new repository is started. Items are transferred to the new repository only if requested by a member body or if so decided by WG5. ------------------- Contents of Repository (Reference number, severity level, title) J3-001 3 Enhanced STOP J3-002 3 GET_IO_UNIT J3-003 4 EXECUTE_COMMAND_LINE J3-004 3 STORAGE_SIZE J3-005 3 C_SIZEOF J3-006 3 Find all available logical and character kinds J3-007 3/4 Construct Name Local to Construct J3-008 3 Rewrite attribute requirements J3-009 4 IO_UNIT standard derived type J3-010 3 Allow empty CONTAINS part J3-011 5 Coroutines J3-012 4 Use ALLOCATABLE and POINTER attributes in generic resolution J3-013 4 Internal subprograms as actual arguments and procedure pointer targets J3-014 6 Parameterized module facility J3-015 4 Updating complex parts J3-016 4 Disassociated or deallocated actual argument associated with nonpointer nonallocatable optional dummy argument is considered not to be present J3-017 4 Default initial values for absent optional dummy arguments J3-018 4 Non-null initial targets for pointers J3-019 4 More mathematical functions J3-020 3 Allow TYPE ( ) J3-021 4 Resolve generic without invoking a procedure or evaluating arguments J3-022 4 Allow a polymorphic allocatable variable in intrinsic assignment J3-023 3 Named rank-one array constant's extent from its . J3-024 3 EXIT from any labeled construct J3-025 3 Allow SUBROUTINE or FUNCTION to be optional on END statements for module and internal subprograms J3-026 3 ATAN with two arguments works like ATAN2 J3-027 3 ASCII arguments for LGE etc J3-028 3 Allow forward type for allocatable components J3-029 3 More information about GET_COMMAND[_ARGUMENT] failure J3-030 3 Simplified means to select the most commonly desired real and integer kinds J3-031 4 ANDTHEN and ORELSE pseudo-functions RU-001 3 Remove restriction on the maximum rank of arrays RU-002 3 Extend the semantics of the EXIT statement RU-003 4 Extend the obsolescent features list RU-004 >4 Subset of Fortran Standard which does not include redundant features RU-005 4/5 Extend a set of array intrinsic functions RU-006 2 Give a table with attribute compatibility UK-001 6 Co-array Fortran for parallel programming UK-002 3 Decimal floating point arithmetic UK-003 4 Conformance to IEEE 754R UK-004 3 KIND environment specification UK-005 4 Long Integers UK-006 4 Multiple Nonzero-Rank Part References UK-007 4 Pointer function references as actual arguments UK-008 4 Pointer function references as lhs in assignment UK-009 3 Use procedureness in generic resolution UK-010 3/4 Partial initialization of PARAMETERs ------------------- Changes from N1613: RU-001 to RU-006 and UK-005 to UK-010 are new. UK-001 is revised. ------------------- Number: J3-001 Title: Enhanced STOP Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-007 8.4 STOP Statement page 170 04-107, 04-319r2 Basic Functionality: Trivially enhance the STOP statement for modern processors Rationale: The current STOP statement is vaguely defined, and has not been updated in accordance with modern practice. Furthermore, its syntax is peculiarly limited, going back to Fortran 66 days. Estimated Impact: At 167, J3/JoR estimated the impact as "Trivial". This is recorded in 04-265r1. Discussion: Modern practice suggests that (a) the stop code should be written to the standard error unit (b) an integer stop code should be returned as the process exit status. There are four peculiarities of STOP syntax: (1) An integer stop code is limited to 5 digits. (2) An integer stop code must be a literal constant, it cannot be a named constant. (3) A stop code must be a literal or named constant, it cannot be a constant (i.e. initialization) expression. (4) A stop code must be constant, it cannot be a non-constant expression. This paper advocates lifting all of these restrictions. Lifting all of them probably has less impact (or at least no more impact) than releasing some of them, as the processor can then simply use its normal expression evaluation mechanism. Detailed Specification: (1) The stop code shall be allowed to be a scalar initialization expression of type default integer or default character. (2) Recommend that the stop code be displayed on ERROR_UNIT. (3) Recommend that if the stop code is of integer type, it should be used as the process exit status (if the processor even has such a concept). (4) Note that the processor might use only a portion of such a stop code for the exit status. History: Paper 04-102 meeting 167 Submitted 04-319r2 169 Accepted as complete ------------------------------------------------------------------ Number: J3-002 Title: GET_IO_UNIT Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-107, 04-186, 04-328 Basic Functionality: Add an procedure to ISO_FORTRAN_ENV to return a logical unit number which may be opened. Rationale: Logical unit numbers are processor-dependent, some method of getting one should be supported. Some programs (for example, multithreaded programs) may want units to be distributed according to a rule (for example, 1000 times thread number plus offset). Thus, some flexibility should be part of this intrinsic. Estimated Impact: The impact was estimated by J3/JoR at 167 as Trivial. Detailed Specification: See paper 04-327 regards possible renumbering of 13.8.2. These edits assume that paper passes. [360:33++] Add: "13.8.2.2.x GET_IO_UNIT( UNIT, [ NOTUNIT, MINUNIT, MAXUNIT, IOSTAT, IOMSG ] ) *Description.* Return values that exist, are not connected to an external file, and can be connected to an external file. *Class.* Subroutine. *Arguments.* UNIT shall be of type integer and may be of any rank. It is an INTENT(OUT) argument. It is assigned values of logical units that exist, are not connected to an external file, and can be connected to an external file. It shall not be assigned a value equal to INPUT_UNIT, OUTPUT_UNIT or ERROR_UNIT. If it is scalar, one value is returned; if it is an array, SIZE(UNIT) unique values are returned. NOTUNIT shall be of type integer. It shall (optional) be a scalar or a rank 1 array. It is an INTENT(IN) argument. The value of UNIT, or an element of UNIT if it is an array, shall not be equal to the value of NOTUNIT, or any element of NOTUNIT if it is an array. MINUNIT shall be a scalar of type integer. (optional) It is an INTENT(IN) argument. The value of UNIT, or an element of UNIT if it is an array, shall not be less than the value of MINUNIT. MAXUNIT shall be a scalar of type integer. (optional) It is an INTENT(IN) argument. The value of UNIT, or an element of UNIT if it is an array, shall not be greater than the value of MAXUNIT. IOSTAT shall be a scalar of type default integer. (optional) It is an INTENT(OUT) argument. It is assigned the value zero if the variable associated with UNIT contains valid values and assigned a processor-dependent positive value otherwise. IOMSG shall be a scalar of type default character. (optional) It is an INTENT(INOUT) argument. It is assigned a processor-dependent error message if the value of the variable associated with the IOSTAT argument indicates an error occurred. Otherwise, its value is unchanged." History: Paper 04-107 meeting 167 Submitted {same as 04-186} 04-328 168 Accepted as complete ------------------------------------------------------------------ Number: J3-003 Title: EXECUTE_COMMAND_LINE Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-106, 04-329r3 Basic Functionality: Add a procedure to ISO_FORTRAN_ENV to cause an external program to execute. Rationale: Most processors provide a means to execute an external program, but the syntax varies. Furthermore, some processors may support only synchronous execution of external programs, so this processor limitation must be taken into account. Some programs may want to execute another program to generate an input file or to operate jointly via a pipe, thus program control over synchronous versus asynchronous execution should be supplied to some extent. Estimated Impact: The impact was estimated by J3 at 167 as Small. Detailed Specification: Executes a command line externally to the program. Whether the command line is interpreted by a shell is unspecified. Require synchronous execution and allow asynchronous execution. If synchronous execution, allow recovery of the executed process exit status. Allow processor-dependent error conditions. See paper 04-327 regards possible renumbering of 13.8.2. These edits assume that paper passes. [360:33++] Add: "13.8.2.2.x EXECUTE_COMMAND_LINE( COMMAND, [ WAIT, EXITSTAT, CMDSTAT, CMDMSG ] ) *Description.* Execute the command line identified by the string COMMAND. The processor must support synchronous and may support asynchronous execution of the external program. *Class.* Subroutine. *Arguments.* COMMAND shall be of type default character and shall be a scalar. It is an INTENT(IN) argument. It identifies the command line to be executed. The interpretation is processor-dependent. WAIT shall be of type default logical and shall (optional) be a scalar. It is an INTENT(IN) argument. When present and true, EXECUTE_COMMAND_LINE returns after the indicated command line has completed execution. When present and false, EXECUTE_COMMAND_LINE returns after the indicated command line has started execution. When not present, the effect is as if present with a value of true. EXITSTAT shall be of type default integer and shall (optional) be a scalar. It is an INTENT(INOUT) argument. It shall not be present if WAIT is present with a value of false. If WAIT is present with a value of true, the value of EXITSTAT is the processor-dependent exit status of the command line, if available. Otherwise, the value is unchanged. CMDSTAT shall be of type default integer and shall (optional) be a scalar. It is an INTENT(OUT) argument. It is assigned the value zero if no error occurred during EXECUTE_COMMAND_LINE and assigned a processor-dependent positive value otherwise. If an error occurs and CMDSTAT is not present, execution of the program terminates. If the processor does not support the concept of command lines, the value is 1. CMDMSG shall be of type default character and shall (optional) be a scalar. It is an INTENT(INOUT) argument. It is assigned a processor-dependent error message if the value of the variable associated with the CMDSTAT argument indicates an error occurred. Otherwise, the value of CMDMSG is unchanged." History: Paper 04-106 meeting 167 Submitted 04-329r3 169 Accepted as complete ------------------------------------------------------------------ Number: J3-004 Title: STORAGE_SIZE Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-120, 04-342 Basic Functionality: Add a procedure to ISO_FORTRAN_ENV to return the size in bits of its argument. Rationale: There are situations where a program needs to know the size of an entity. Estimated Impact: The impact was estimated by J3 at 167 as Small. Detailed Specification: A procedure to return the size in bits of its argument. See paper 04-327 regards possible renumbering of 13.8.2. These edits assume that paper passes. [125:41+] Add list item "(4+) the intrinsic module function STORAGE_SIZE," [360:33+++] Add section "13.8.2.2.x STORAGE_SIZE (X [, KIND]) *Description.* Returns the storage size in bits for a nonpointer nonallocatable scalar of the declared type of X. *Class.* Inquiry function. *Arguments.* X may be of intrinsic or derived type. It shall not be polymorphic. If it is of derived type, that type shall be a SEQUENCE or interoperable type and shall have no allocatable ultimate components. If its type has any deferred type parameters, it shall be a pointer that is associated or an allocatable object that is allocated. It may be a scalar or an array. KIND (optional) shall be a scalar integer initialization expression. *Result Characteristics.* Integer scalar. If KIND is present, the kind type parameter is that specified by the value of KIND; otherwise, the kind type parameter is that of default integer type. *Result Value.* The result value is the size in bits of the storage unit (16.4.3.1) in a storage association context for a nonpointer nonallocatable scalar with the declared type and type parameters of X. *Example.* STORAGE_SIZE(1.0) returns the number of bits required to store an entity of type default real." History: Paper 04-120 meeting 167 Submitted {also N1539} 04-342 169 Accepted as complete ------------------------------------------------------------------ Number: J3-005 Title: C_SIZEOF Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-104, 04-344r1 Basic Functionality: Add a procedure to ISO_C_BINDING to return the size of its argument as per C sizeof. Rationale: There are situations where a program needs to know the size of an entity, as expressed in C. Estimated Impact: The impact was estimated by J3 at 167 as Small. Detailed Specification: A procedure to return the size of its argument as per C. [125:41+] Add list item "(4++) the intrinsic module function C_SIZEOF," [395:31+++] (after the Note) Add section "15.1.2.6 C_SIZEOF (X) *Description.* Returns the size, as defined by the C sizeof operator (Section 6.5.3.4 of the C International Standard), of the argument X. *Class.* Inquiry function. *Arguments.* X X shall have interoperable type and type parameters. It may be a scalar or an array that is not assumed-size. *Result Characteristics.* Integer scalar of kind C_SIZE_T (15.2.1). *Result Value.* The result value is the size of X as defined by the sizeof operator (Section 6.5.3.4 of the C International Standard) of the companion C processor. If the companion processor is not a C processor, the result value is processor dependent." History: Paper 04-104 meeting 167 Submitted 04-344r1 169 Accepted as complete ------------------------------------------------------------------ Number: J3-006 Title: Find all available logical and character kinds Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-121, 04-346r2 Basic Functionality: Add constants to iso_fortran_env which specify all available logical kind values and all available character kind names. Rationale: A program (subject or not to preprocessing) or an automatic code generator may have a preferred kind or a preferred ranking of possibly available kinds for entities of logical and character type. Currently, the only means available is to read the documentation and manually add the specific values needed. For example, a very large frequently used but infrequently updated logical array may be best expressed as an array of the smallest kind of logical. Default logical may exhaust the processor's fastest cache, leaving no space for numerical data. What is the smallest logical available? There is no automatically available answer now. Estimated Impact: The impact was estimated by JoR at 167 to be trivial. Only iso_fortran_env is affected. Detailed Specification: [360:4a+] "13.8.2.1- CHARACTER_KIND_NAMES The values of the default character rank 1 array CHARACTER_KIND_NAMES are the names, when any trailing blanks are removed, which may be passed to the SELECTED_CHAR_KIND procedure to obtain a valid kind value. The lower bound of CHARACTER_KIND_NAMES is one; the size of CHARACTER_KIND_NAMES is the number of character names supported by the processor. The names are stored in non-decreasing order of storage size of objects of the corresponding kind." [360:26+] Add "13.8.2.6+ LOGICAL_KIND_VALUES The values of the default integer rank 1 array LOGICAL_KIND_VALUES are the kind values of all available logical kinds. The lower bound of LOGICAL_KIND_VALUES is one; the size of LOGICAL_KIND_VALUES is the number of logical kind values supported by the processor. The values are stored in non-decreasing order of storage size of objects of the corresponding kind." History: Paper 04-121 meeting 167 Submitted 04-346r2 169 Accepted as complete ------------------------------------------------------------------ Number: J3-007 Title: Construct Name Local to Construct Submitted By: J3 Status: Specification complete Severity Level : 3/4 References: 04-158, 04-348r1 Basic Functionality: Make a construct name be local to its construct. Rationale: Construct names are only referenced from within the construct. Therefore, it makes sense to use a construct scope for the name. Further, within a local scope, a construct name might naturally be desirable more than once. For example, within a local scope, an if-block might naturally be named "check_iostat" following more than one statement containing an iostat specifier, or more than one do-construct might be naturally named "all_rows", "all_columns", or "all_planes", etc. Of course, for cycle and exit to work properly, nested constructs must all have names unique within the nest. Estimated Impact: 3 or 4. Detailed Specification: (1) Define a construct name to have construct scope. (2) Remove construct names from all local entity classes, so that it can be the same as any local name and any global name. (3) Nested constructs shall not have the same name. (Note: after removal from local entities, this needs to be explicitly stated in the standard.) Incomplete Illustrative Edits: [406:4-5] remove "named constructs," [409:29+] add new paragraph "The name of a named construct has a scope of that construct. It may be the same as any local identifier or global identifier. The of a contained named construct shall not be the same as a of any of its containing named constructs." History: Paper 04-158 meeting 167 Submitted 04-348r1 169 Accepted as complete ------------------------------------------------------------------ Number: J3-008 Title: Rewrite attribute requirements Submitted by: Malcolm Cohen Status: Specification complete Severity Level : 3 References: 04-359 Basic Functionality: None. Rationale: The current method of specifying the requirements on various attributes, such as EXTERNAL and POINTER, is too hard to understand and too prone to error. Estimated impact: Non-trivial Editorial. Detailed Specification: Rewrite the attribute specification parts of chapters 5 and 12 so that (1) the syntax just says what attribute it provides (2) there is a separate attribute section which (a) contains the requirements (like "must be a dummy argument for VALUE") (b) describes the effects. History: Paper 04-359 meeting 169 Submitted 04-359 170 Accepted as complete ------------------------------------------------------------------ Number: J3-009 Title: IO_UNIT standard derived type Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-369 Requirements: Have a mechanism for i/o units that - does not confuse i/o units with integers (improved abstraction) - does not require the user to manage their use (ease of use) - avoids clashes between user-written code and existing third-party libraries - avoids race conditions in multi-threaded programs, without requiring the routine being used in a multi-threaded program to have different code (viz explicit calls to locking routines) from when it is being used without a threading library. Basic Functionality: Add a derived type to ISO_FORTRAN_ENV to represent an i/o unit. Allow values of this type to be used everywhere that a unit number can be used. Rationale: Logical unit numbers are processor-dependent, managing their use is difficult. Integer values are not a good model of a file handle. Simply finding a currently unused integer value is not sufficiently powerful to avoid known problems with clashes and race conditions - having a standard intrinsic to return an unused unit number can not help in this regard, no matter how sophisticated we make the intrinsic. Estimated Impact: Not Quite Trivial. Detailed Specification: (1) That a standard derived type, in the intrinsic module ISO_FORTRAN_ENV, be provided to represent file handles. This derived type is referred to as IO_UNIT hereafter. (2) That the IO_UNIT type be opaque. (3) That OPEN not be required to take a file unit number, but allowed to return an IO_UNIT value instead. (4) That an IO_UNIT value be usable in place of a in all other i/o statements. (5) That derived-type i/o subroutines not be modified; these will continue to receive some processor-determined negative number for the unit - because these are supplied by the processor and therefore cannot clash with user-determined unit numbers, this is not a problem. Syntax: (1) That the derived type be named IO_UNIT. (2a) That the UNIT= specifier on the OPEN be allowed to take a TYPE(IO_UNIT) variable instead of an integer value, or (2b) That a new specifier IO_UNIT= be allowed on OPEN if the UNIT= specifier is omitted. Edits: would be premature in the absence of an agreed base document. Sections needing modification are: 9.4.0 The unit definition 9.4.5 the description of OPEN 13.8.2 to mention the derived type. History: Paper 04-369 meeting 169 Submitted 04-369 170 Accepted as complete ------------------------------------------------------------------ Number: J3-010 Title: Allow empty CONTAINS part Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-189, 04-379 Basic Functionality: Allow empty CONTAINS part Rationale: Is there a good reason that a module, procedure or type definition has to have procedure definitions after the CONTAINS statement? What would be hurt by allowing not to have any? Sometimes when programs are generated automatically, they end up with an empty CONTAINS part, and then you have to go fix it manually, or whine (ineffectually) to the unsympathetic guys who wrote the processor (if they're still in business), for which you have no source code. It's also not unreasonable to start off development of a module or type with an empty CONTAINS part, with the intent of filling it in later. Estimated Impact: Trivial. Change a few syntax rules. No new words needed anywhere. Estimated at J3 meeting 169 to be at 3 on the JKR scale. Detailed Specification: Allow an empty CONTAINS part in external and module procedures, modules, and derived type definitions. History: Paper 04-189 meeting 167 Submitted 04-379 170 Accepted as complete ------------------------------------------------------------------ Number: J3-011 Title: Coroutines Submitted By: J3 Status: Specification complete Severity Level : 5 References: 04-345, 04-380r2 Basic Functionality: Provide for coroutines. Rationale: In many cases when a "library" procedure needs access to user-provided code, the user-provided code needs access to data of which the library procedure is unaware. There are at least three ways by which the user-provided code can gain access to these entities: o The user-provided code can be implemented as a procedure that is invoked by the library procedure, with the extra data stored in globally-accessible variables. o The user-provided code can be implemented as a procedure that takes a dummy argument of extensible type, which procedure is invoked by the library procedure, with the extra entities in an extension of that type. o The library procedure can provide for "reverse communication", that is, when it needs access to user-provided code it returns instead of calling a procedure. When the user-provided code reinvokes the library procedure, it somehow finds its way back to the appropriate place. Each of these solutions has drawbacks. Entities that are needlessly public increase maintenance expense. If the user-provided procedure expects to find its extra data in an extension of the type of an argument passed through the library procedure, the dummy argument has to be polymorphic, and the user-provided code has to execute a SELECT TYPE construct to access the extension. Reverse communication causes a mess that requires GO TO statements to resume the library procedure where it left off, which in turn requires one to simulate conventional control structures using GO TO statements. This reduces reliability and increases development and maintenance costs. Reverse communication is, however, a blunt-force simulation of a well-behaved control structure that has been well-known to computer scientists for decades: The "coroutine". Coroutines would allow user-provided code needed by library procedures more easily to gain access to data of which the library procedure is unaware, without causing the disruption of the control structure of the library procedure that reverse communication now causes. Coroutines are useful to implement "iterator" procedures, that can be used both to enumerate the elements of a data structure and to control iteration of a loop that is processing those elements. Estimated Impact: Minor additions to Subclause 2.3.4 and Section 12. Estimated at J3 meeting 169 to be at 5 on the JKR scale. Detailed Specification: Provide two new statements, which we here call SUSPEND and RESUME. Provide a new form of subprogram, the "coroutine", that cannot contain an ENTRY statement, and is the only subprogram in which a SUSPEND statement is allowed. A coroutine requires an explicit interface. Coroutines can stand on their own, or be type-bound procedures or actual arguments. They can be procedure pointer targets, provided the pointer has explicit interface. Generic coroutines are allowed, provided the is . Recursive and internal coroutines are allowed. When a coroutine is invoked by a CALL statement, execution continues with the coroutine's first executable construct. When a coroutine executes a SUSPEND statement, execution continues after the CALL or RESUME statement that initiated or resumed its execution; when a RESUME statement is executed, execution resumes after the SUSPEND statement. When a coroutine executes a RETURN or END statement, execution continues after the CALL or RESUME statement that initiated or resumed its execution, and it is an error if one later attempts to RESUME it without first calling it. A type-bound coroutine shall be initiated using a variable, and resumed using the same variable. A coroutine that is initiated using a pointer shall be resumed using the same pointer. Otherwise, a coroutine shall be resumed from the same scoping unit in which it is initiated. Data entities: Variables within a coroutine can have the SAVE attribute, with the usual implications. Unsaved local variables within a coroutine retain their definition status and values from SUSPEND to RESUME. Automatic objects in addition retain their bounds and length parameter values. The specification part is not elaborated upon resumption. If a coroutine references a module or common block, it is considered to continue to reference it between SUSPEND and RESUME. A change in the value of a variable between SUSPEND and RESUME does not affect the bounds or length parameter values of automatic variables within the coroutine. Argument association does survive execution of a SUSPEND statement. Activation records: The above rules guarantee that coroutines can be reentrant. The following paragraphs suggest one way to implement those rules. When a coroutine suspends execution by executing a SUSPEND statement, its activation record is saved. When a coroutine is resumed, its activation record is restored. Therefore there is no restriction on where a SUSPEND statement is allowed to appear among the executable constructs. A type-bound coroutine's activation record is saved in and restored from an extension of the variable by which its execution is initiated or resumed, i.e., in X, if it is referenced as X%C. If a coroutine is accessed by a procedure pointer, its activation record is saved in the pointer. Otherwise, the processor stores the activation record locally (so CALL and RESUME have to be in the same scoping unit). History: Paper 03-258r1 meeting 166 Submitted in section 1.1 04-149r1 167 04-345 169 04-380r2 170 Accepted as complete ------------------------------------------------------------------ Number: J3-012 Title: Use ALLOCATABLE and POINTER attributes in generic resolution Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-170, 04-381 Basic Functionality: Use ALLOCATABLE and POINTER attributes in generic resolution Rationale: I have a generic interface ALLOCATE_TEST that allocates an object, tests the status, and prints an error message if an error occurs. I cannot have a specific interface for a to-be-allocated argument that has the POINTER attribute, and another for a to-be-allocated argument with the same type, kind type parameters and rank that has the ALLOCATABLE attribute. So I need different generic names for allocatable objects and pointer objects. If I change an object from pointer to allocatable or vice-versa, I have to track down all of the ALLOCATE_TEST invocations for that variable and change them to the other one. Avoiding this labor was one of the justifications for the generic facility. Estimated Impact: Minor. Estimated at J3 meeting 169 to be at 5 on the JKR scale. It is more likely at 3 on the JKR scale, since it appears that the only place where edits are necessary is 407:29. Detailed Specification: Allow the POINTER and ALLOCATABLE attributes to be used as the last resort for generic resolution: If the only difference between two specific interfaces is that in one there is a dummy argument that has neither the POINTER nor ALLOCATABLE attribute, and the corresponding argument in the other one has one of those attributes, the interface is ambiguous. If one has the POINTER attribute and the corresponding one has the ALLOCATABLE attribute the interface is not ambiguous, at least so far as that pair of specific procedures is concerned. If a dummy argument has the POINTER or ALLOCATABLE attribute, the corresponding actual argument is required to have the same attribute. Therefore this change would not invalidate any existing program. History: Paper 04-170 meeting 167 Submitted 04-381 170 Accepted as complete ------------------------------------------------------------------ Number: J3-013 Title: Internal subprograms as actual arguments and procedure pointer targets Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-148, 03-258r1, section 1.7, 04-382r1 Basic Functionality: Allow internal subprograms as actual arguments and procedure pointer targets Rationale: In many cases where one uses a subprogram as an actual argument, it needs access to entities of which the procedure to which it is passed is unaware. If the actual argument were an internal subprogram, it could access these extra entities by host association. Since the 2003 standard does not require the TARGET attribute for a nonpointer dummy procedure that is a procedure pointer target, we cannot simultaneously allow internal procedures to be actual arguments and prohibit them to be procedure pointer targets. Estimated Impact: Small. Minor changes necessary in Sections 7, 12 and 16, and maybe Annex C. Estimated at J3 meeting 169 to be at 4 on the JKR scale. Detailed Specification: Allow an internal subprogram to be an actual argument: There are two possibilities concerning the host of the internal subprogram: o Allow the host of the internal subprogram to be recursive. Make it clear that accesses by host association from the internal subprogram to entities of its host are accesses to entities in the instance of its host as of the instant the internal subprogram was used as an actual argument, not to entities in the instance of its host as of the instant the internal subprogram is invoked. o Require that the host of the internal subprogram is not recursive. In this case, there can only be one instance of the procedure defined by the host subprogram. This restriction could later be relaxed. Many processors may relax it as an extension. Allow an internal subprogram to be a procedure pointer target: Similar considerations regarding recursive hosts apply. It is unavoidable that the same restriction applies to internal subprograms used as procedure pointer targets and used as actual arguments. If internal subprograms of recursive hosts are allowed to be procedure pointers, make it clear that the instance of the host to which accesses from the internal subprogram to that host by host association refer, when it is invoked by way of the pointer, is the instance as of the instant the procedure was associated with the pointer, which is not necessarily the instance as of the instant the internal subprogram is invoked via the pointer. Make sure that a procedure pointer associated with an internal subprogram becomes undefined when the instance of the procedure defined by its host subprogram that was in existence at the instant the pointer association was established ceases to exist. History: Paper 04-148 meeting 167 Submitted 04-382r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-014 Title: Parameterized module facility Submitted By: J3 Status: Specification complete Severity Level : 6 References: 04-153, 04-383r1 Basic Functionality: Provide a facility whereby a module or subprogram can be developed in a generic form, and then applied to any appropriate type. Rationale: Many algorithms can be applied to more than one type. Many algorithms that can only be applied to one type can be applied to more than one kind. It is tedious, expensive, and error prone - especially during maintenance - to develop algorithms that are identical except for type declarations to operate on different types or kinds. Generic modules are useful to package types together with their type-bound procedures, so that when they are instantiated, they are consistent. This cannot be guaranteed for parameterized types. Estimated Impact: Moderate to extensive, depending on how it's done. The solution proposed here can be implemented mostly with changes in Section 11, and perhaps a few changes in Section 4. Estimated at J3 meeting 169 to be at 6 on the JKR scale. Detailed Specification: Provide a variety of module called a "generic module". A generic module is a template or pattern for generating specific instances. It has "generic parameters" but is otherwise structurally similar to a nongeneric module. A generic parameter can be a type, a data object, a procedure, a generic interface, a nongeneric module, or a generic module. By substituting concrete values for its generic parameters, one can create an "instance of a generic module". Entities from generic modules cannot be accessed by use association. Rather, entities can be accessed from instances of them. Instances of generic modules have all of the properties of nongeneric modules, except that they are always local entities of the scoping units in which they are instantiated. Provide a means to create instances of generic modules by substituting concrete values for their generic parameters Provide a means to access entities from instances of generic modules by use association. It is proposed at this time that generic modules do not have submodules. 0.1 Priority for features The features of generic modules depend primarily upon what varieties of entities are allowed as generic parameters. The priority of what should be allowed for generic parameters and their corresponding instance parameters is, with most important first: --------------------------------------------------- Generic parameter Associated instance parameter =================================================== Type Type --------------------------------------------------- Data entity Initialization expression Variable --------------------------------------------------- Specific procedure Specific procedure --------------------------------------------------- Generic interface Generic interface --------------------------------------------------- Non-generic module Non-generic module --------------------------------------------------- Generic module Generic module --------------------------------------------------- To fit the proposal within the development schedule, it may be necessary to reduce the present scope of the proposal. If so, less-important features should be removed before more-important ones. 0.2 Definition of a generic module -- general principles A generic module may stand on its own as a global entity, or may be a local entity defined within a program, module or subprogram. It shall not be defined within another generic module. If it is defined within another scoping unit, instances of it access that scoping unit by host association. This is useful if a particular scoping unit is the only place where it's needed, or if instances need to share an entity such as a type, procedure or variable. A second axis of simplification is to prohibit generic modules to be defined within other scoping units. If this is prohibited, instances should nonetheless not access scoping units where they are instantiated by host association, so as to preserve the possibility to extend to the functionality described here at a later time. The MODULE statement that introduces a generic module differs from one that introduces a nongeneric module by having a list of generic parameter names. The "interface" of a generic module is the list of the sets of characteristics of its generic parameters. The interface shall be explicitly declared, that is, the variety of entity of each generic parameter, and the characteristics required of its associated actual parameter when an instance is created, shall be declared. There shall be no optional parameters. Generic parameters and their associated instance parameters are described in detail in section 8.4 below. Other than the appearance of generic parameters in the MODULE statement, and their declarations, generic modules are structurally similar to nongeneric modules, as defined by R1104: R1104 <> [ ] [ ] although it may be necessary to relax statement-ordering restrictions a little bit. 0.3 Instantiation of a generic module and use of the instance -- general principles An instance of a generic module is created by the appearance of a USE statement that refers to that generic module, and provides concrete values for each of the generic module's generic parameters. These concrete values are called "instance parameters". The instance parameters in the USE statement correspond to the module's generic parameters either by position or by name, in the same way as for arguments in procedure references or component specifiers in structure constructors. The characteristics of each instance parameter shall be consistent with the corresponding generic parameter. By substituting the concrete values of instance parameters for corresponding generic parameters, an "instance" of a generic module is created, or "instantiated". An instance of a generic module is a module, but it is a local entity of the scoping unit where it is instantiated. It does not, however, access by host association the scoping unit where it is instantiated. Rather, it accesses by host association the scoping unit where the generic module is defined. Each local entity within an instance of a generic module is distinct from the corresponding entity in a different instance, even if both instances are instantiated with identical instance parameters. A generic module shall not be an instance parameter of an instance of itself, either directly or indirectly. A generic module may be instantiated and accessed in two ways: o By instantiating it and giving it a name, and then accessing entities from the named instance by use association. Named instances are created by a USE statement of the form USE :: where a is of the form => , and is of the form ( ). In this case, the and are not permitted - since this does not access the created instance by use association. Entities are then accessed from those instances by USE statements that look like R1109: R1109 <> USE [ [ , ] :: ] \smudge \smudge [ , ] <> USE [ [ , ] :: ] \smudge \smudge , ONLY : [ ] but with replaced by . o By instantiating it without giving it a name, and accessing entities from that instance within the same statement. In this case, the USE statement looks like , but with replaced by . In either case, a could either be prohibited, or required with a new value such as GENERIC or INSTANCE. Alternatively, a new statement such as INSTANTIATE might be used instead of the above-described variations on the USE statement, at least in the named-instance case. In the anonymous-instance case it would be desirable to use the USE statement, to preserve functionality of and without needing to describe them all over again for a new statement. Since instances are essentially modules, but are always local entities within the program units where they are instantiated, it seems fatuous to prohibit nongeneric modules within other program units. It would be reasonable to limit the nesting depth, as we do for subprograms. For example, it would be reasonable to prohibit either a generic module or a nongeneric module to be defined within an internal or generic module. 0.4 Generic parameters and associated instance parameters A generic parameter may be a type, a data entity, a specific procedure, a generic interface, a nongeneric module, or a generic module. Declarations of generic parameters may depend upon other generic parameters, but there shall not be a circular dependence between them, except by way of pointer or allocatable components of generic parameters that are types. 0.4.1 Generic parameters as types If a generic parameter is a type, it shall be declared by a type definition having the same syntax as a derived type definition. The type definition may include component definitions. The types and type parameters of the components may themselves be specified by other generic parameters. The type definition may include type-bound procedures. Characteristics of these type-bound procedures may depend upon generic parameters. If the generic parameter is a type, the corresponding instance parameter shall be a type. If the generic parameter has components, the instance parameter shall at least have components with the same names, types, type parameters and ranks. If the generic parameter has type parameters, the instance parameter shall at least have type parameters with the same names and attributes. Type parameters of the instance parameter that correspond to type parameters of the generic parameter shall be specified by a colon, as though they were deferred in an object of the type - even if they are KIND parameters, and any others shall have values given by initialization expressions. If the generic parameter has type-bound specific procedures or type-bound generics, the corresponding instance parameter shall at least have type-bound specifics and generics that are consistent, except that if a specific procedure binding to the generic parameter has the ABSTRACT attribute the instance parameter need not have a specific binding of the same name because it is only used to provide an interface for a generic binding; it shall not be accessed by the specific name. Instance parameters that are intrinsic types shall be considered to be derived types with no accessible components. Intrinsic operations and intrinsic functions are available in every scoping unit, so it is not necessary to assume that intrinsic operations and intrinsic functions are bound to the type. 0.4.2 Generic parameters as data objects If a generic parameter is a data object, it shall be declared by a type declaration statement. Its type and type parameters may be generic parameters. If it is necessary that the actual parameter to be provided when the generic module is instantiated shall be an initialization expression, the generic parameter shall have the KIND attribute, no matter what its type - even a type specified by another generic parameter. If the generic parameter is a data object, the corresponding instance parameter's type, kind and rank shall be the same as specified for the generic parameter. If the generic parameter is a data object with the KIND attribute, the corresponding instance parameter shall be an initialization expression. If the generic parameter is a data object without the KIND attribute, the corresponding instance parameter shall be a variable. Every expression within the variable shall be an initialization expression. The instance has access to the variable by some newly-defined variety of association (or maybe by storage association)~--- instantiation does not create a new one with the same characteristics. 0.4.3 Generic parameters as procedures or generic interfaces If a generic parameter is a procedure or a generic interface, its interface shall be declared explicitly. Its characteristics may depend upon generic parameters. If the generic parameter is a procedure, the corresponding instance parameter shall be a procedure having characteristics consistent with the interface for the generic parameter, which interface may depend upon other generic parameters. If the generic parameter is a generic interface, the corresponding instance parameter shall be a generic identifier, whose interface shall have at least specifics consistent with specific interfaces within the generic parameter's generic interface. The instance parameter need not have the same generic identifier as the generic parameter. If a specific interface within the generic parameter's generic interface has the ABSTRACT attribute, the instance parameter need not have a specific procedure with the same name, but it shall have a specific procedure with the same characteristics. In this case, the specific procedure within the generic parameter's generic interface cannot be accessed by the specified name as a specific procedure, either within an instance or from one by use association. 0.4.4 Generic parameters as generic or nongeneric modules If a generic parameter is a generic module, The interface of that parameter shall be declared. If the generic parameter is a generic module, the corresponding instance parameter shall be a generic module, having an interface consistent with the generic parameter. If the generic parameter is a nongeneric module, the corresponding instance parameter shall be a nongeneric module, which may be an internal module or an instance of a generic module. 0.5 Instantiation of a generic module and use of the instance - fine points If a generic module is defined within a module, it can have the PRIVATE attribute. This means it cannot be accessed by use association, which in turn means that it cannot be instantiated outside of the module where it is defined. Rather, it will be instantiated some fixed number of times within that module, which instances might or might not be accessible by use association. A similar situation holds, of course, if a generic module is defined within a scoping unit that is not a module. If the generic module is an internal generic module, it shall be accessible in the scoping unit where the USE statement that instantiates it appears. This may require that it be made available by USE association from a module within which it is defined. That is, two USE statements may be necessary: One to access the generic module, and another to instantiate it. If a generic module has a generic parameter that is a generic module, and the generic parameter is public, four USE statements might appear: One to access the generic module, one to instantiate it, one to access the generic parameter that is a generic module from that instance, and yet another to instantiate that generic module. This could be prohibited, for example by prohibiting generic parameters that are generic modules to be public, but why? An instance parameter is accessible by use association from an instance of a generic module by using the identifier of the corresponding generic parameter, unless the generic parameter's dentifier is private. Where a module is instantiated, the and facilities of the USE statement can be used as well. Processors could exploit an to avoid instantiating all of a module if only part of it is ultimately used. Suppose for example that one has a generic BLAS module from which one wants only a double precision L2-norm routine. One might write USE BLAS(kind(0.0d0)), only: DNRM2 = GNRM2 where GNRM2 is the specific name of the L2-norm routine in the generic module, and DNRM2 is the local name of the double precision instance of it created by instantiating the module. If is not used, every entity in the module is instantiated, and all public entities are accessed from the instance by use association, exactly as is currently done for a USE statement without an . If a named instance is created, access to it need not be in the same scoping unit as the instantiation; it is only necessary that the name of the instance be accessible. Indeed, the instance might be created in one module, its name accessed from that module by use association, and entities from it finally accessed by use association by way of that accessed name. 0.6 Examples of proposed syntax for definition The following subsections illustrate how to define modules. 0.6.1 Sort module hoping for < routine Here's an example of the beginning of a generic sort module in which the processor can't check that there's an accessible < operator with an appropriate interface until the generic module is instantiated. There's no requirement on the parameters of the generic type "MyType". The only way the instance can get the < routine is if it is intrinsic, by host association from the scoping unit where the generic module is defined, or if it is bound to the type given by the instance parameter (recall that instances do not access by host association the scoping unit where they're instantiated). Aleks advocates that this one is illegal. The primary difference would be in the quality of message announced in the event "MyType" does not have a suitable < operator. module Sorting ( MyType ) type :: MyType end type MyType .... 0.6.2 Sort module with < specified by module parameter generic interface The < operator is given by a generic parameter. When the module is instantiated, a generic identifier for an interface with a specific consistent with the LESS shown here, shall be provided as an instance parameter. module SortingP ( MyType, Operator(<) ) type :: MyType end type MyType interface operator (<) pure logical abstract function Less ( A, B ) ! "less" is purely an abstraction type(myType), intent(in) :: A, B end function Less end interface .... The ABSTRACT attribute for the LESS function means that the associated instance parameter for OPERATOR(<) only needs to have a specific with the specified interface, but the name isn't required to be LESS. Indeed, LESS can't be accessed by that name within "SortingP" or by use association from an instance of "SortingP". The instance parameter corresponding to OPERATOR(<) need not have the same generic identifier. For example, if it's OPERATOR(>) (with the obvious semantics), the instantiated sort routine would sort into reverse order. 0.6.3 Sort module with < specified by type-bound generic interface This illustrates a generic parameter that is a type that is required to have a particular type-bound generic. The type shall have a type-bound generic with a particular interface, but if entities are declared by reference to the name "MyType" or a local name for it after it is accessed from an instance, the specific type-bound procedure cannot be invoked by name; it can only be accessed by way of the type-bound generic. The ABSTRACT attribute does this. It's only allowed in the definitions of types that are generic parameters. module SortingTBP ( MyType ) type :: MyType contains procedure(less), abstract :: Less ! Can't do "foobar%less". ! "Less" is only a handle for the interface for the ! "operator(<)" generic generic operator(<) => Less ! Type shall have this generic operator end type MyType ! Same explicit interface for "less" as in previous example .... 0.6.4 Module with type having at least a specified component module LinkedLists ( MyType ) type :: MyType type(myType), pointer :: Next! "next" component is required. ! Type is allowed to have other components, and TBPs. end type MyType .... 0.6.5 Module with type having separately-specified kind parameter module LinkedLists ( MyType, ItsKind ) type :: MyType(itsKind) integer, kind :: itsKind end type MyType integer, kind :: ItsKind .... 0.6.6 BLAS definition used in instantiation examples in 8.7 module BLAS ( KIND ) integer, kind :: KIND interface NRM2; module procedure GNRM2; end interface NRM2 .... contains pure real(kind) function GNRM2 ( Vec ) .... 0.6.7 Ordinary module with private instance count and internal generic module module ModuleWithInternalGeneric integer, private :: HowManyInstances module InternalGeneric ( MyType ) ! Instances of InternalGeneric access HowManyInstances ! by host association .... 0.7 Examples of proposed syntax for instantiation The following subsections illustrate how to instantiate a generic module. 0.7.1 Instantiating a stand-alone generic module Instantiate a generic module BLAS with KIND(0.0d0) and access every public entity from the instance: use BLAS(kind(0.0d0)) Instantiate a generic module BLAS with KIND(0.0d0) and access only the GNRM2 function from the instance: use BLAS(kind(0.0d0)), only: GNRM2 Instantiate a generic module BLAS with KIND(0.0d0) and access only the GNRM2 function from the instance, with local name DNRM2: use BLAS(kind(0.0d0)), only: DNRM2 => GNRM2 0.7.2 Instantiate within a module, and then use from that module This is the way to get only one single-precision and only one double precision instance of BLAS; instantiating them wherever they are needed results in multiple instances. This also illustrates two ways to make generic interfaces using specific procedures in generic modules. The first one creates the generic interface from specific procedures accessed from the instances: module DBLAS use BLAS(kind(0.0d0)) end module DBLAS module SBLAS use BLAS(kind(0.0e0)) end module SBLAS module B use DBLAS, only: DNRM2 => GNRM2 use SBLAS, only: SNRM2 => GNRM2 interface NRM2 module procedure DNRM2, SNRM2 end interface end module B In the second one the generic module has the generic interface named NRM2 that includes the GNRM2 specific: module DBLAS use BLAS(kind(0.0d0)) end module DBLAS module SBLAS use BLAS(kind(0.0e0)) end module SBLAS module B use DBLAS, only: NRM2 ! Generic; GNRM2 specific not accessed use SBLAS, only: NRM2, & ! Generic & SNRM2 => GNRM2 ! Specific end module B 0.7.3 Instantiate and access twice in one scoping unit, augmenting generic interface module B use BLAS(kind(0.0d0)), only: NRM2 ! Generic; GNRM2 specific not accessed use BLAS(kind(0.0e0)), only: NRM2, & ! Generic NRM2 grows here & SNRM2 => GNRM2 ! Specific end module B The method in 8.7.2 above might be desirable so as not accidentally to have multiple identical instances of BLAS in different scoping units. 0.7.4 Instantiate and give the instance a name, then access from it ! Instantiate BLAS with kind(0.0d0) and call the instance DBLAS, ! which is a local module. use :: DBLAS => BLAS(kind(0.0d0)) ! Access GNRM2 from the instance DBLAS and call it DNRM2 here use DBLAS, only: DNRM2 => GNRM2 0.7.5 Instantiate two named instances in one module, then use one elsewhere module BlasInstances ! Instantiate instances but do not access from them ! by use association use :: DBLAS => BLAS(kind(0.0d0)), SBLAS => BLAS(kind(0.0d0)) end module BlasInstances module NeedsSBlasNRM2 use BlasInstances, only: SBLAS ! gets the SBLAS instance module, not its contents use SBLAS, only: SNRM2 => GNRM2 ! Accesses GNRM2 from SBLAS end module NeedsSBlasNRM2 0.7.6 Instantiate sort module with generic interface instance parameter type :: OrderedType ... end type OrderedType interface operator (<) pure logical function Less ( A, B ) type(orderedType), intent(in) :: A, B end function Less end interface ! Notice relaxed statement ordering. use SortingP(orderedType,operator(<)), & & only: OrderedTypeQuicksort => Quicksort .... 0.7.7 Instantiate sort module with TBP Less use SortingTBP(real(kind(0.0d0))), & & only: DoubleQuicksort => Quicksort Notice that this depends on < being a "type-bound generic" that is bound to the intrinsic double precision type. Here's one with a user-defined type that has a user-defined type-bound < operator. type MyType ! My components here contains procedure :: MyLess => Less generic operator ( < ) => myLess end type MyType use SortingTBP(myType), only: MyTypeQuicksort => Quicksort The interface for LESS is given in 0.6.2. Notice that the USE statement comes _after_ the type definition and the TBP's function definition. 0.8 Example of consistent type and TBP This example illustrates how to create a type with type-and-kind consistent type-bound procedures, for any kind. This cannot be guaranteed by using parameterized types. module SparseMatrices ( Kind ) integer, kind :: Kind type Matrix ! Stuff to find nonzero elements... real(kind) :: Element contains procedure :: FrobeniusNorm .... end type contains subroutine FrobeniusNorm ( TheMatrix, TheNorm ) type(matrix), intent(in) :: TheMatrix real(kind), intent(out) :: TheNorm .... end subroutine FrobeniusNorm .... end module SparseMatrices .... use SparseMatrices(selected_real_kind(28,300)), & ! Quad precision & only: QuadMatrix_T => Matrix, QuadFrobenius => Frobenius, & & QuadKind => Kind ! Access instance parameter by way of generic parameter .... type(quadMatrix_t) :: QuadMatrix real(quadKind) :: TheNorm .... call quadFrobenius ( quadMatix, theNorm ) History: Paper 03-264r1 meeting 166 Submitted 04-153 167 04-383r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-015 Title: Updating complex parts Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-165, 04-384r1 Basic Functionality: Provide a syntax that allows to update the real and imaginary parts of a complex variable without updating the whole thing Rationale: It's not unusual to need to do this. Estimated Impact: Very minor. Estimated at meeting 169 to be 4 on the JKR scale. Detailed Specification: Specify that the real and imaginary parts of a complex variable can be accessed by using component-like syntax, with "component" names REAL and AIMAG. History: Paper 03-258r1 meeting 166 Section 2.2.5 04-165 167 Submitted 04-255 167 04-384r1 255 Accepted as complete ------------------------------------------------------------------ Number: J3-016 Title: Disassociated or deallocated actual argument associated with nonpointer nonallocatable optional dummy argument is considered not to be present Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-178, 04-385 Basic Functionality: A disassociated or deallocated actual argument associated with a nonpointer nonallocatable optional dummy argument is considered not to be present. Rationale: I have a procedure that has numerous pointers that are associated, or not, depending on input parameters. These are in turn passed to some subroutines that do (or do not do) some computations depending on whether the dummy arguments are associated. This, of course, requires the dummy arguments to be pointers, which degrades the generality of the procedure, and may have undesirable implications for optimization. It would be better if I could use optional nonpointer dummy arguments to decide whether to do these computations. In order to achieve this effect by using N optional dummy arguments I need an IF ... ELSE IF ... END IF construct with 2**N branches. Estimated Impact: Nearly trivial -- a minor change in definition of "present". Estimated at meeting 169 to be 4 on the JKR scale. Detailed Specification: Allow to associate a deallocated allocatable actual argument, or a disassociated pointer actual argument, with an optional nonpointer nonallocatable dummy argument, in which case the dummy argument is considered to be absent. In Fortran 2003, this is an error. History: Paper 03-258r1 meeting 166 Section 2.4.3.1 04-178 167 Submitted 04-385 170 Accepted as complete ------------------------------------------------------------------ Number: J3-017 Title: Default initial values for absent optional dummy arguments Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-179, 04-386r2 Basic Functionality: Default initial values for absent optional dummy arguments Rationale: A frequently requested feature is to be able to specify a default initial value for absent optional dummy arguments. Estimated Impact: Minor; most changes are in Section 12. Estimated at J3 meeting 169 to be at 4 on the JKR scale. Detailed Specification: Provide a specification for a default initial value for an absent optional dummy scalar, or dummy array that is not an assumed-size array. The specification has exactly the same syntax as an initialization, but with a constraint that the expression shall be a restricted expression rather than an initialization expression. (The restrictions on specification expressions at [04-007:126:7-19] would need to be applied to restricted expressions in general instead of just to specification expressions.) If an optional dummy argument has a default initialization specified and the associated actual argument is absent, the initializer is evaluated on entry to the procedure, and then becomes associated with the dummy argument. The VALUE attribute may be specified as well. Optional dummy arguments with initializers cannot have INTENT(INOUT) or INTENT(OUT). For an optional dummy argument that has default initialization: (1) Its assumed nonkind type parameters and extents, and dynamic type if it is polymorphic, are taken from the initializer. (2) If it is not a pointer the value is assigned as if by intrinsic assignment. (3) If it is allocatable, it is assumed to be unallocated before initialization. (4) If it is a pointer, the default initializer shall have the POINTER or TARGET attribute, and the association is established as if by pointer assignment. History: Paper 03-258r1 meeting 166 Section 2.4.3.2 04-179 167 Submitted 04-386r2 170 Accepted as complete ------------------------------------------------------------------ Number: J3-018 Title: Non-null initial targets for pointers Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-202, 04-387r1 Basic Functionality: Allow initial targets for pointers that are other than NULL(). Rationale: It would be useful to be able to initialize pointers to targets other than NULL(). This is especially true for procedure pointers. Estimated Impact: Minor. It was estimated to be at 3 on the JKR scale at meeting 169, but it is now clear that the project is a bit more complicated than originally envisioned. It was judged at J3 meeting 170 to be at 4 on the JKR scale. Detailed Specification: Allow the initial target for a data pointer to be an accessible nonpointer nonallocatable variable with the SAVE attribute. Every expression within the variable shall be an initialization expression. Allow the initial target for a procedure pointer to be an accessible external or module procedure, or an intrinsic procedure listed in subclause 13.6 and not marked with a bullet (or the result of resolving a generic without invoking a procedure if the proposal in 04-391 succeeds). The initial target shall satisfy all the requirements for pointer assignment (e.g. the TARGET attribute, type conformance, etc.). This feature shall be available both for named pointers and for pointer components. Pointer components may be default initialized to have an initial target. The target may be accessed by use or host association. If it is declared in the same scoping unit it need not have been previously declared; this facilitates initialization to a "sentinel" object. (See note 4.36 1/2 in section 8.1 in 04-387.) History: Paper 03-258r1 meeting 166 Section 2.12.2 04-202 167 Submitted 04-351 169 04-387r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-019 Title: More mathematical functions Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-184, 04-388r1 Basic Functionality: More mathematical functions. Rationale: Mathematical functions for complex type are occasionally needed. The only ones that are available for complex type are ABS, COS, EXP, LOG, and SIN. The other mathematical functions that are provided for real type are useful in practice for complex type as well. Inverse hyperbolic functions and other functions are useful. Simple identities for complex argument exist, but it is a burden to expect users to look them up, and processors might be able to produce more efficient implementations. For inverse hyperbolic functions, there are simple identities involving square root and logarithm, but these can have substantial cancellation error for some ranges of values, so it is important to be careful in their implementation. Processors would presumably include careful intrinsic implementations of these functions. Estimated Impact: Minor but tedious. Estimated at meeting 169 to be 4 on the JKR scale. Detailed Specification: Provide ACOS, ASIN, ATAN, COSH, SINH, TAN and TANH for complex type. Provide inverse hyperbolic functions, including for complex type. In the case of TAN, specify that the real part of the argument is regarded as a value in radians. History: Paper 03-258r1 meeting 166 Section 2.4.4.3 04-184r1 167 Submitted 04-388r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-020 Title: Allow TYPE ( ) Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-161, 04-389r1 Basic Functionality: Allow TYPE ( ). Rationale: For regularity and symmetry, allow TYPE ( ). Estimated Impact: Trivial. Estimated at meeting 169 to be at 3 on the JKR scale. Detailed Specification: Allow TYPE ( ) to declare entities of intrinsic type. History: Paper 03-258r1 meeting 166 Section 2.2.1 04-161 167 Submitted 04-389r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-021 Title: Resolve generic without invoking a procedure or evaluating arguments Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-273, 04-391r1 Basic Functionality: Given examplars of actual arguments, resolve a generic name to a specific procedure without invoking the procedure or evaluating its arguments. Rationale: With care and diligence, one can develop a program so that related sets of variables, constants and function results are parameterized by a single kind type parameter. In order to change the kind of that set of entities, one need only change one named constant's definition - almost: Generic procedures cannot be actual arguments or procedure pointer targets. Thus, if one needs to change the program, in addition to changing the single named constant definition, one needs to find all places where a specific procedure that operates on the entities in question is an actual argument or procedure pointer target, and manually edit those appearances. It would be helpful to have a facility to resolve a generic name to a specific procedure without evaluating any arguments or invoking a procedure. Estimated Impact: Minor. Processors already know how to do generic resolution. Estimated at meeting 169 to be at 4 on the JKR scale. Detailed Specification: Given examplars of actual arguments, resolve a generic name to a specific procedure without invoking the procedure or evaluating its arguments. There are at least two ways to do this. One is to provide a syntax that is suggestive of procedure reference, but does resolution instead. One possibility for this is to enclose an actual argument list in square brackets or curly brackets instead of round brackets. E.g., call solver ( myVec, myJacobian, myModel[myVec,myJacobian] ) Another is to provide an entity that looks like an intrinsic function but that has the important distinction that its arguments aren't evaluated. Indeed, this entity that has the appearance of a function reference isn't even invoked during program execution. It is entirely resolved to a procedure by the processor during translation. E.g., call solver ( myVec, myJacobian, resolve(myModel,myVec,myJacobian) ) RESOLVE would be a an inquiry "function" that takes a as its first "argument," and doesn't evaluate its other arguments - because it's an inquiry function. It should be possible to resolve a type-bound generic reference, e.g., RESOLVE(A%B). No matter what syntax is used, it should be allowed to use the result either as an actual argument or a procedure pointer target. History: Paper 04-273 meeting 168 Submitted 04-391r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-022 Title: Allow a polymorphic allocatable variable in intrinsic assignment Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-354r1, 04-392 Basic Functionality: Allow a polymorphic allocatable variable in intrinsic assignment. Rationale: We allow intrinsic assignment to change the extent or length type parameters of an allocatable variable in an assignment. Why not the type if it's also polymorphic? Surely that would be equally valuable. After all, it can be done with a DEALLOCATE statement followed by an ALLOCATE statement with a SOURCE= specifier. Why not allow the clearer intrinsic assignment statement? Estimated Impact: Trivial for the standard, probably in the trivial-to-small range for processors. Estimated at meeting 169 to be at 4 on the JKR scale. Detailed Specification: Allow a polymorphic allocatable variable in intrinsic assignment. Require to have the same rank as a polymorphic . If is allocated and polymorphic, deallocate it (as we do now if any bounds or length type parameters differ). Then allocate it with the same dynamic type, type parameters and bounds as . Or, we could say "if the dynamic type of is different from the dynamic type of , deallocate ". It is necessary to specify which one because if we do the first, processors could not choose to do the second as a polite optimization without making finalization indeterminate. There could be a middle ground that mumbles about finalizers. History: Paper 04-354r1 meeting 169 Submitted 04-392 170 Accepted as complete ------------------------------------------------------------------ Number: J3-023 Title: Named rank-one array constant's extent from its . Submitted By: J3 Status: Specification complete Severity Level : 3 References: 01-180, 04-101, 04-394r1 Basic Functionality: As with the length of a character named constant, allow a rank-one array named constant to get its extent from the . Rationale: There was a good reason that a provision was made for named constants of character type to get their lengths from their s. For the same reason, it would be useful if a rank-one array named constant could get its extent from its . Estimated Impact: Small effect in 5.1.2.5.2, or maybe a short new subclause in 5.1.2.5, to explain how an array named constant gets its extent from its (see item (2) in the list at the end of 4.4.4). Estimated at meeting 169 to be at 3 on the JKR scale. Detailed Specification: Allow a rank-one array named constant to get its extent from the extent of its . Use for the dimension specification. See 01-180 for an example. History: Paper 01-180 meeting 156 04-101 167 Submitted 04-394r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-024 Title: EXIT from any labeled construct Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-156, 04-395r1 Basic Functionality: Allow EXIT from any labeled construct. Rationale: Some algorithms cannot be expressed in Fortran 2003 without GOTO statements or extra tests, but they could be expressed with EXIT if it could be applied to any labeled construct. For example, here's a routine that says "call R if X is not an element of the set S, which is represented by elements of A(1:NUM\_IN\_SET)". With an extra test: do i = 1, num_in_set if ( x == a(i) ) exit end do ! i if ( i > num_in_set ) call r or, with GOTO: do i = 1, num_in_set if ( x == a(i) ) go to 10 end do ! i go to 20 10 call r 20 continue or, with a more general EXIT: o: if ( .true. ) then do i = 1, num_in_set if ( x == a(i) ) exit o end do ! i call r end if o Estimated Impact: Trivial to minor -- a few lines in 8.1.6.4.4. Estimated at meeting 169 to be at 3 on the JKR scale. Detailed Specification: Allow an EXIT statement with a that is the same as the name of any enclosing construct, not just a DO construct. When the EXIT statement is executed, execution of the named construct is terminated. For compatibility, an EXIT statement without a continues to refer to the nearest enclosing DO construct. History: Paper 03-258r1 meeting 166 Section 2.1.2 04-109 167 04-156r1 167 Submitted 04-395r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-025 Title: Allow SUBROUTINE or FUNCTION to be optional on END statements for module and internal subprograms Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-177, 04-396r1 Basic Functionality: Allow SUBROUTINE or FUNCTION to be optional on END statements for module and internal subprograms. Rationale: Module procedures are required to end with END SUBROUTINE or END FUNCTION . This is generally a good thing, but it makes it impossible to convert a Fortran 77 external procedure to a module procedure by using INCLUDE. Estimated Impact: Trivial. Estimated at meeting 169 to be at 3 on the JKR scale. Detailed Specification: To cater for the desire that a Fortran 77 external procedure could be made into a module procedure using INCLUDE, allow the SUBROUTINE or FUNCTION part to be optional on an or statement. For consistency, allow them to be optional for internal subprograms as well. History: Paper 03-258r1 meeting 166 Section 2.4.2 04-177 167 Submitted 04-396r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-026 Title: ATAN with two arguments works like ATAN2 Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-183, 04-397 Basic Functionality: Define an alternative ATAN that works like ATAN2. Rationale: ATAN is generic. It is surprising to students that they need to use ATAN2 just because they have the two-argument formulation. Estimated Impact: Minor: One more description for an existing intrinsic function - and we already have the description. Estimated at meeting 169 to be at 3 on the JKR scale. Detailed Specification: Provide a specification for how ATAN works with two arguments, based on how ATAN2 works. History: Paper 03-258r1 meeting 166 Section 2.4.4.2 04-183 167 Submitted 04-397 170 Accepted as complete ------------------------------------------------------------------ Number: J3-027 Title: ASCII arguments for LGE etc Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-185, 04-398 Basic Functionality: Allow ASCII arguments for LGE etc. Rationale: Now that ASCII kind characters are required by the standard, it is nothing short of bizarre that the four functions to compare character strings according to the ASCII collating sequence, viz. LGE, LGT, LLE and LLT, do not permit arguments of ASCII kind. If one has a program with some character variables of default kind that are compared by using these functions, and their kind needs to be changed to ASCII, one has to find the invocations of these functions and replace them by the equivalent relational operators. This is an unnecessary maintenance expense. Estimated Impact: Trivial. Estimated at meeting 169 to be at 3 on the JKR scale. Detailed Specification: Allow ASCII kind arguments for LGE, LGT, LLE and LLT. History: Paper 03-258r1 meeting 166 Section 2.4.4.5, 04-185 04-185 167 Submitted 04-398 170 Accepted as complete ------------------------------------------------------------------ Number: J3-028 Title: Allow forward type for allocatable components Submitted By: J3 Status: Specification complete Severity Level : 3 References: Pub-116, 04-226, 04-399 Basic Functionality: Do not require the type of an allocatable component to be defined before the type containing the allocatable component. Rationale: Mutually recursive types can be related by components having the POINTER attribute, which allows the types of the components to be defined after the type definition in which the components appear. Some mutually recursive types could be related by components having the ALLOCATABLE attribute, except that is presently prohibited. ALLOCATABLE is preferable to POINTER whenever possible. We should make every effort to make ALLOCATABLE as widely usable as possible. Estimated Impact: Easy to implement, improves performance, trivial change in the standard. Estimated at meeting 169 to be at 3 on the JKR scale. Detailed Specification: Do not require the type of an allocatable component to be defined before the type containing the allocatable component. The following suggested edits illustrate the magnitude of the proposal: In Constraint 438, replace "the POINTER attribute is not" by "neither the POINTER nor ALLOCATABLE attribute is" and delete "shall be CLASS(*) or" (Constraint 437 requires either the POINTER or ALLOCATABLE attribute for a component declared with the CLASS keyword). In Constraint 439, insert "or ALLOCATABLE" after "POINTER". History: Paper 04-226 meeting 167 Submitted as Pub-116 04-399 170 Accepted as complete ------------------------------------------------------------------ Number: J3-029 Title: More information about GET_COMMAND[_ARGUMENT] failure Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-352, 04-400 Basic Functionality: Provide more information if GET_COMMAND or GET_COMMAND_ARGUMENT fails. Rationale: It would be useful to know more precisely why GET_COMMAND or GET_COMMAND_ARGUMENT fails. Estimated Impact: Trivial for standard, probably trivial-to-small for processors. Estimated at meeting 169 to be at 3 on the JKR scale. Detailed Specification: Set the STATUS argument of GET_COMMAND to -2 if the processor does not support the concept of a command line. Set the STATUS argument of GET_COMMAND_ARGUMENT to -2 if the value of the NUMBER argument is negative or more than the number of command arguments. History: Paper 04-352 meeting 169 Submitted 04-400 170 Accepted as complete ------------------------------------------------------------------ Number: J3-030 Title: Simplified means to select the most commonly desired real and integer kinds Submitted By: J3 Status: Specification complete Severity Level : 3 References: 04-240, 04-407r1 Basic Functionality: Provide a simplified means to select the most commonly desired real and integer kinds. Rationale: Several possible approaches were outlined in 04-240. I propose that we adopt the approach that is intermediate in complexity, namely that the standard define named constants for the most commonly desired real and integer kinds. The approach of standardizing some named constants seems adequately simple without being restrictive or raising compatibility issues. It also has the advantage of being completely trivial to implement. My proposal is restricted to kinds with exact sizes. Adding too many options would increase the complexity of the choice to be made by users and would result in issues of interoperability of codes where different users made different choices of how to specify the kinds. Note that the existing selected_*_kind intrinsics provide the capability of specifying minimum requirements and could be extended in many ways (although that is not proposed here). Exact sizes are the simplest and most commonly requested requirement, and one that the standard currently provides no facility for (except in C interop, which has it only for integers - nor for reals). I also restrict the proposal to integers and reals because they are the common cases. User specification of specific sizes for logical kinds is rare (and even more rare when you rule out the cases where logical is being used as a synonym for unsigned integer, which is a nonstandard and nonportable practice anyway). User specification of character kinds is also rare. Estimated Impact: 3 on the JKR scale. Detailed Specification: The standard will specify the names of several named constants in the ISO_FORTRAN_ENV intrinsic module. These named constants will have kind values for the representations described below. Named constants provided will be for the kinds of integers whose storage sizes are exactly 8, 16, 32, and 64 bits, and for the kinds of reals whose storage sizes are exactly 32, 64, and 128 bits. Additionally, named constants will be provided for the kinds of default integer, default real, and double precision real. If the processor supports more than one representation with the specified size, it is processor-dependent which of those representations the named constant corresponds to. If the processsor does not support a particular representation, the value of the corresponding named constant will be one of two negative values specified by the standard. If the processor does not support a representation with the exact size requested or with any larger size, the value shall be -1. If the processor does not support a representation with the exact size requested, but does support a representation with a larger size, the value shall be -2. This proposal does not require the compiler to support any particular kind. Nor does this proposal specify the kind values, which remain processor-dependent. This syntax suggestion is purely illustrative for now: int8_kind, int16_kind, int32_kind, int64_kind real32_kind, real64_kind, real128_kind int_default_kind, real_default_kind, real_double_kind History: Paper 04-240 meeting 167 Submitted 04-407r1 170 Accepted as complete ------------------------------------------------------------------ Number: J3-031 Title: ANDTHEN and ORELSE pseudo-functions Submitted By: J3 Status: Specification complete Severity Level : 4 References: 04-193, 04-410r1 Basic Functionality: Guarantee short-circuit evaluation of AND and OR operations. Rationale: There has been considerable e-mail discussion of a way to perform short-circuiting of tests, usually to allow writing things simply and to avoid common user errors. Various forms of an .ANDTHEN. operator have been proposed. A canonical example is I > 0 .AND. I < 10 .ANDTHEN. A(I) /= 0 the .ANDTHEN. guarantees that A(I) won't be referenced if I is out of range. Paper 04-390 provides more rational. Much of the discussion has centered on the priority of the new operators. Should they be: highest, lowest, the same or different, or the same as .AND. and .OR.? Reasonably compelling arguments have been made for all of the possibilities. This proposal replaces the operators with functions and thus resolves the priority issue. The functions are called pseudo-functions to emphasize that they are different from normal functions. An alternate name could be "selector functions". They can be used anyplace that an ordinary function can be used, including in declarations, if they follow whatever normal rules apply to that use. The functionality guarantees that the argument expressions will be evaluated in the listed order, left to right, one at a time, and that argument evaluation will stop when the function result can be determined, and that exceptions and side effects won't occur for un-required evaluations. They effectively require short-circuiting. Estimated Impact: 4 on the JKR scale. Detailed Specification: Add two new elemental pseudo-functions ANDTHEN (A1 ,A2 [, A3, ...AN] ) ORELSE (A1 ,A2 [, A3, ...AN] ) Arguments: A1, ...AN Logical, of any kind, they must be conformable The arguments are evaluated in sequence, left to right, one at a time. Evaluation of the arguments stops when ANDTHEN encounters a FALSE value, ORELSE encounters a TRUE value, or when the last argument has been evaluated. The result of the function is the value of the last argument actually evaluated. (This is equivalent to the AND or OR, respectively, of all of the evaluated arguments.) Entities in arguments which are not evaluated need not be defined, present, allocated, evaluatable, etc, nor may the processor generate any side-effects or exceptions from these arguments. Note that for elemental usage, different result elements will usually evaluate different sets of arguments. Examples: IF ( ANDTHEN(I > 0, I<10, A(I) > 0 ) ) A(I) = log(A(I)) WHERE ( ANDTHEN( X > 0.0, log(X) < Tol) ) ... IF ( ANDTHEN( PRESENT(X), X==0) ) Print *, "X must not be zero!" The function can be usefully combined with the "IF" function from paper 04-357r1 Local_value = IF ( ANDTHEN ( present(X), X /= 0.0), X, 1.0) ) REAL :: Temp ( IF ( ANDTHEN (present(x), size(x)>100), size(x), & & 100) ) History: J3/04-390, 04-193, 04-357R1 Paper 04-193 meeting 167 Submitted 04-390 170 04-410r1 170 Accepted as complete ------------------------------------------------------------------ Number: RU-001 Title: Remove the restriction on the maximum rank of arrays (or increase a maximum limit on the number of array dimensions). Submitted by: Russion Federation (GOST R) Status: For consideration Severity Level: 3 References: WG5-N1189, item 24 (WG5-N919). Basic Functionality: The rank of arrays may be arbitrary, but it must not be less than seven for the sake of portability. Rationale: Some applications require more than seven dimensions. Also this is useful for regularization of Fortran features. Estimated Impact: No effect on existing programs. Detailed Specification: History: Proposed for F95 by Russian Fortran WG in 1991. ------------------------------------------------------------------ Number: RU-002 Title: Extend the semantics of the EXIT statement Submitted by: Russion Federation (GOST R) Status: For consideration Severity Level: 3 References: WG5-N1189, item 25 (WG5-N919). Basic Functionality: Extend the semantics of the EXIT statement to allow its use for exit from any control construct. Rationale: This is useful for a more structured style and for regularization of Fortran features. Estimated Impact: No effect on existing programs. Requires very little change in existing processors. Detailed Specification: History: Proposed for F95 by Russian Fortran WG in 1991. ------------------------------------------------------------------ Number: RU-003 Title: Extend the obsolescent features list Submitted By: Russion Federation (GOST R) Status: For Consideration Severity Level: 4 References: WG5-N1102 Basic Functionality: Extend the obsolescent features list with following elements: the old forms for the relational operators, storage association, assumed-size arrays, DOUBLE PRECISION statement, ENTRY statement, BLOCK DATA subprogram, INCLUDE line, etc. Rationale: Estimated Impact: Additions to the Annex B. Detailed Specification: History: ------------------------------------------------------------------ Number: RU-004 Title: Subset of Fortran Standard which does not include redundant features Submitted By: Russion Federation (GOST R) Status: For Consideration Severity Level: More than 4 References: Basic Functionality: Define subset of Fortran Standard which does not include redundant features. Rationale: Fortran 2003 is a rather complicated language. Subset of Fortran standard should not contain the old, obsolete and redundant features. This would be useful for new Fortran users and for new Fortran applications. The F language plus some new features of Fortran 2003 may be used as a base for a such subset. Estimated Impact: No effect on existing programs. Detailed Specification: History: ------------------------------------------------------------------ Number: RU-005 Title: Extend a set of array intrinsic functions Submitted By: Russion Federation (GOST R) Status: For Consideration Severity Level: 4 (or 5) References: HPF Basic Functionality: Extend a set of array intrinsic functions, for example add some intrinsic functions of HPF. Rationale: The additional array intrinsic functions of HPF are useful for some applications (especially reduction functions). Estimated Impact: Additions to the Section 13. No effect on existing programs. Detailed Specification: History: ------------------------------------------------------------------ Number: RU-006 Title: Give a table with attribute compatibility Submitted By: Russion Federation (GOST R) Status: For Consideration Severity Level: 2 References: Basic Functionality: Give a table with attribute compatibility. Such a table should show which attributes may be used together to specify an entity. Rationale: Describing constraints on mutual using of specifications of attributes in type declaration statements is rather cumbersome (complicated). Such a table should contain all combinations of constraints. Estimated Impact: No effect on existing programs. Addition to the Section 5 (or to the Annex C). Detailed Specification: History: ------------------------------------------------------------------ Number: UK-001 (revision of 25 April 2005) Title: Co-arrays for parallel programming Submitted By: UK Status: For Consideration Severity Level: 6 References: ISO/IEC JTC1/SC22/WG5 N1317 Basic Functionality: Co-arrays provide a simple parallel extension of Fortran. The extension assumes the SPMD programming model with the program replicated a fixed number of times. Each copy is called an image. Normal subscripts refer to memory addresses within an image while a second set of subscripts refer to an image. Each image executes asynchronously with explicit synchronization provided by the programmer. For example, the statement REAL, DIMENSION(N)[*] :: X,Y declares that each image has two real arrays of size N. When an image executes the statement X(:) = Y(:)[Q] it makes a copy of the array Y from the memory of image Q into array X in the memory of the image executing the statement. A reference to X or Y without its second set of subscripts is a reference to the local array. Rationale: It is our belief that the wide adoption of this extension, compared with other parallel programming models, would lead to easier program development, faster execution times, and better program maintainability, particularly where the number of processes is large. Fortran 95 included language features needed by HPF in the expectation that HPF would become widely used for parallel programming. Unfortunately, this has not happened because HPF is difficult to implement and its performance in practice is often disappointing. Furthermore, its ability to represent complicated data distributions is limited. Instead MPI has become the de-facto standard for parallel programming. MPI is awkward to program and its performance tends to decay as the number of processes increases. MPI is essentially a library of C procedures, and the overhead from calling these procedures often limits scalability for programs that generate many small messages. In contrast, co-arrays add additional syntax to the language that requires support in the compiler. They allow the programmer to design complicated data distributions and to write customized communication patterns using a Fortran-like syntax. The lack of any external library call, coupled with the fact that the extension has been designed to be easy to implement, gives great scope for communications optimization compared with either HPF or MPI codes. Estimated Impact: Other features would be little affected since execution is normal and normal optimizations are applicable except where there is explicit co-array syntax. Uniprocessors would be required to recognize the syntax but can ignore most of it and, if asked, would indicate that the number of images is one. Detailed Specification: This is a revision of the previous specification, which simply referenced report RAL-TR-1998-060, an updated version of N1317. This report is still useful for further explanation and is available as ftp://ftp.numerical.rl.ac.uk/pub/reports/nrRAL98060.ps.gz This document is now self-contained. We have made some technical changes, each of which is highlighted with a note. In this proposal, we use the notation < ... > to represent bold font (definitions) and braces { ... } to represent italic (Fortran bnf). Fortran 2003 uses square brackets for array constructors, which does not conflict with square brackets indicating a co-array reference though it does mean that such a reference will not be as obvious as it was in Fortran 95. In this proposal, we use the Fortran 95 syntax for array constructors and reserve square bracket-syntax for co-arrays. We also use square brackets to indicate optional arguments. 1 Program images A Fortran program containing co-arrays executes as if it were replicated a number of times, the number of replications remaining fixed during execution of the program. Each copy is called an and each image executes asynchronously. A particular implementation may permit the number of images to be chosen at compile time, at link time, or at execute time. The number of images may be the same as the number of physical processors, or it may be more, or it may be less. The programmer may retrieve the number of images at run time by invoking the intrinsic function NUM_IMAGES(). Note: The model is that the program is written for any number of images and the actual number for a specific run is specified on the command line. This allows the program to be developed with fewer images that will be used in the eventual production runs. If the system is a uniprocessor, the compiler knows that the number of images is 1 and can take advantage of this. Thus the early testing of the program can be performed on a uniprocessor. For compilation on a multiprocessor, the vendor could supply a switch to specify that the number of images is 1, which would permit the optimizer to eliminate overhead associated with parallel execution. Each image is indexed by an . These form a sequence of integers running from one to NUM_IMAGES(). The programmer may retrieve the index of the invoking image through the intrinsic function THIS_IMAGE(). The programmer may retrieve the set of subscript values that correspond to the invoking image for a particular co-array by providing an optional argument to THIS_IMAGE (Section 10.3). The programmer may retrieve the index of the image that corresponds to a set of subscripts for a particular co-array through the intrinsic function IMAGE_INDEX (Section 10.3). The programmer controls the execution sequence in each image through explicit use of Fortran control constructs and through explicit use of intrinsic synchronization procedures. 2 Specifying data objects Each image has its own set of data objects, all of which may be accessed in the normal Fortran way. Some objects are declared with in square brackets immediately following dimensions in parentheses (round brackets) or in place of them. Such an object is a . These are examples of co-array declarations: REAL, DIMENSION(20)[20,*] :: A REAL :: C[*], D[*] CHARACTER :: B(20)[20,0:*] INTEGER :: IB(10)[*] TYPE(INTERVAL) :: S[20,*] Unless the array is allocatable (Section 6), the form for the dimensions in square brackets is the same as that for the dimensions in parentheses for an assumed-size array. The number of co-subscripts is limited to 7. The part of a co-array that resides on another image may be addressed by using subscripts in square brackets following any subscripts in parentheses, for example: A(5)[3,7] = IB(5)[3] D[3] = C A(:)[2,3] = C[1] Each such subscript must be a scalar integer expression (section subscripts are not permitted). Note: Change from RAL-TR-1998-060. Co-subscripts are now limited to scalars. This is a big change that substantially simplifies the extension. We call any object whose designator includes square brackets a . For each co-array, subscripts in square brackets are mapped to image indices in the same way as Fortran array subscripts are mapped to the position of the array element in array element order. On each image, the image index is available from the intrinsic THIS_IMAGE with no arguments, the set of subscript values for a co-array A that correspond to the image are available as THIS_IMAGE(A), and the image index that corresponds to a set of subscript values for a co-array A is available as IMAGE_INDEX(A,SUB). For example, on image 5, for the array declared as REAL :: A(10,20)[10,0:9,0:*] THIS_IMAGE() has the value 5 and THIS_IMAGE(A) has the value (\ 5,0,0 \). For the same example on image 213, THIS_IMAGE(A) has the value (\ 3,1,2 \). On any image, IMAGE_INDEX(A, (\ 5,0,0 \) ) has the value 5 and IMAGE_INDEX(A, (\3,1,2 \) has the value 213. Note: Change from RAL-TR-1998-060. The intrinsic function IMAGE_INDEX has been added. Note: On a shared-memory machine, we expect a co-array to be implemented as if it were an array of higher rank. The implementation would need to support the declaration of arrays of rank up to 14. On a distributed-memory machine with one physical processor for each image, a co-array may be stored from the same virtual address in each physical processor. On any machine, a co-array may be implemented in such a way that each image can calculate the virtual address of an element on another image relative to the array start address on that other image. An implementation might arrange for each co-array to be stored from the same virtual address in each image, but this is not required. The , , , , and of a co-array are given by the data in parentheses in its declaration or allocation. The , , and are given by the data in square brackets in its declaration or allocation. The co-size of a co-array is always equal to the number of images. The syntax and semantics mirror those of assumed-size arrays - the final extent is always indicated with an asterisk and a co-array has no final co-extent, no final upper bound, and no co-shape. For example, the co-array declared thus REAL, DIMENSION(10,20)[20,5,0:*] :: A has rank 2, co-rank 3, and shape (/10,20/); its lower co-bounds are 1, 1, 0. Note: Change from RAL-TR-1998-060. Now that co-subscripts are limited to scalars, it is better to use 'rank' for what was 'local rank', and similarly for the other terms. The actual argument corresponding to a dummy co-array must be a co-array or a subobject of a co-array, with no square brackets in its designator. It is not required to be the same object on all images. For example, the subroutine of the previous paragraph may be called at the same time thus on three images: CALL SOLVE (100,A) CALL SOLVE (200,B) CALL SOLVE (100,A(10)) Furthermore, each image independently defines the bounds and co- bounds. For example, the subroutine SUBROUTINE SOLVE(M,N,A) INTEGER :: M,N REAL :: A(M)[N,*] might be called simultaneously on two images with differing values of M and N. Note: We expect that the case with all images having the same co-array with the same bounds and co-bounds will occur very frequently, but the additional freedom (used with care) may be very useful. An example is when different teams of images are working independently. Note: Change from RAL-TR-1998-060. We previously required the dummy co-arrays to be identical. A co-array may be allocatable: SUBROUTINE SOLVE(N,A,B) INTEGER :: N REAL :: A(N)[*], B(N) REAL,ALLOCATABLE :: WORK(:)[:] Allocatable arrays are discussed in Section 6. Unless it is allocatable or a dummy argument, a co-array always has the SAVE attribute. Note: If a co-array is declared in a procedure, with a fixed size but without the SAVE attribute, there would need to be an implicit synchronization on entry to the procedure and return from it. Without this, there might be a reference from one image to non-existent data on another image. An allocatable array does not automatically have the SAVE attribute because a recursive procedure may need separate allocatable arrays at each level of recursion. Note: An acceptable alternative would be to require a co-array to be declared with the SAVE attribute unless it is is allocatable, a dummy argument, or declared in a main program. Automatic co-arrays are not permitted; for example, the co-array work in the above code fragment is not permitted to be declared thus SUBROUTINE SOLVE(N,A,B) INTEGER :: N REAL :: A(N)[*], B(N) REAL :: WORK(N)[*] ! Not permitted Note: Were automatic co-arrays permitted, it would be necessary to require image synchronization, both after memory is allocated on entry and before memory is deallocated on return. We would also need rules to ensure that the sizes are the same in all images. Effectively the arrays would be just like allocatables, except for not needing to write allocate syntax. A co-array is not permitted to be a constant. Note: This restriction is not necessary, but the feature would be useless since each image would hold exactly the same value. To ensure that data initialization is local (the same on each image), co-subscripts are not permitted in DATA statements. For example: REAL :: A(10)[*] DATA A(1) /0.0/ ! Permitted DATA A(1)[2] /0.0/ ! Not permitted A derived type is not permitted to have co-array components. Note: Were we to allow a co-array of a type with co-array components, we would be confronted with references such as Z[P]%X[Q]. A logical way to read such an expression would be: go to image P and find component X on image Q. This is logically equivalent to Z[Q]%X. A co-array is not permitted to be a pointer but a co-array may be of a derived type with pointer or allocatable components. The targets of such components are always local. Such a component or a subobject of such a component must not be associated as an actual argument with a dummy co-array since its shape may vary from image to image. Note: If a large array is needed on a subset of images, it is wasteful of memory to specify it directly as a co-array. Instead, it should be specified as an allocatable component of a co-array and allocated only on the images on which it is needed. Note: It has been suggested that we might allow a co-array to have the pointer attribute with the meaning that on each image it has a local target or is disassociated but access between images is exactly as for non-pointer co-arrays. This would add no extra functionality - just the minor convenience of allowing references such as A[P]%COMP(I:) being written as A(I:)[P]. 3 Accessing data objects Each object exists on every image, whether or not it is a co-array. In an expression, a reference without square brackets is always a reference to the object on the invoking image. For example, SIZE(IB) for the co-array IB declared at the start of Section 2 returns 10. The co-subscript list must map to a valid image index. For example, if there are 16 images and the co-array A is declared thus REAL :: A(10)[5,*] A(:)[1,4] is valid since it has co-subscript order value 16, but A(:)[2,4] is invalid. Square brackets attached to objects alert the reader to communication between images. Unless square brackets appear explicitly, all objects reside on the invoking image. Communication may take place, however, within a procedure that is referenced, which might be a defined operation or assignment. Note: Whether the executing image is selected in square brackets has no bearing on whether the executing image evaluates the expression or assignment. For example, the statement P[6] = 1 is executed by every image, not just image 6. If code is to be executed selectively, the Fortran IF or CASE statement is needed. For example, the code REAL :: P[*] ... IF (THIS_IMAGE(P)==1) THEN READ(6,*)P DO I = 2, NUM_IMAGES() P[I] = P END DO END IF CALL SYNC_ALL employs the first image to read data and broadcast it to other images. 4 Procedures A co-array subobject is permitted only in intrinsic operations, intrinsic assignments, and input/output lists. If a dummy argument is not a co-array, the value of a co-array subobject may be passed by using parentheses to make an expression, for example, C(1:P:2) = SIN( (D(1:P:2)[K]) ) Note: The behaviour is as if a copy of the section is made on the local image and this copy is passed to the procedure as an actual argument. If a dummy argument is a co-array, the interface must be explicit. The rules for resolving generic procedure references are based on the local properties and are therefore unchanged. Note: The rules cannot be extended to allow overloading of array and co-array versions since the syntactic form of an actual argument would be the same in the two cases. If a dummy argument is a co-array that is not allocatable, the co-rank and co-bounds are defined afresh and are completely independent of those of the actual argument. The actual argument must be the name of a co-array or a subobject of a co-array without any vector-valued subscripts, allocatable component selection, or pointer component selection. Note: It is intended to ensure that copy-in or copy-out does not take place for a dummy co-array. A dummy co-array may be of assumed size or assumed shape: SUBROUTINE SUBR(N,A,B) INTEGER :: N REAL :: A(N,*)[*], B(:,:)[*] If an assumed-shape array or a subobject of an assumed-shape array appears as an actual argument corresponding to a dummy co-array, the dummy co-array must be of assumed shape. If an array section appears as an actual argument corresponding to a dummy co-array that is not of assumed shape, the section must have elements whose subscript order values in its parent array consist of a sequence without gaps. Note: Change from RAL-TR-1998-060. These rules have been added to ensure that copy-in or copy-out does not take place. If a dummy argument is an allocatable co-array, the corresponding actual argument must be an allocatable co-array of the same rank and co-rank. Note: Change from RAL-TR-1998-060. Allocatable dummy co-arrays are permitted in view of allocatable dummy arguments being permitted in Fortran 2003. A function result is not permitted to be a co-array. Note: A co-array function result is like an automatic co-array and is disallowed for the same reasons. A pure or elemental procedure is not permitted to contain any co-array syntax. 5 Storage association COMMON and EQUIVALENCE statements are permitted for co-arrays and specify how the storage is arranged on each image (the same for every one). Therefore, co-array references are not permitted in an EQUIVALENCE statement. For example EQUIVALENCE (A[10],B[7]) ! Not allowed (compile-time constraint) is not permitted. Appearing in a COMMON or EQUIVALENCE statement has no effect on whether an object is a co-array; it is a co-array only if declared with square brackets. An EQUIVALENCE statement is not permitted to associate a co-array with an object that is not a co-array. For example INTEGER :: A,B[*] EQUIVALENCE (A,B) ! Not allowed (compile-time constraint) is not permitted. Note: The ban on associating a co-array with an object that is not a co-array is not necessary, but we see it as desirable to keep some separation between objects that are co-arrays and those that are not. A COMMON block that contains a co-array always has the SAVE attribute. Which objects in the COMMON block are co-arrays may vary between scoping units. Since blank COMMON may vary in size between scoping units, co-arrays are not permitted in blank COMMON. 6 Allocatable arrays A co-array may be allocatable. The ALLOCATE statement is extended so that the co-bounds can be specified, for example, REAL, ALLOCATABLE :: A(:)[:], S[:,:] : ALLOCATE ( ARRAY(10)[*], S[-1:34,0:*] ) The co-bounds must always be included in the allocate statement and the upper bound for the final co-dimension must always be an asterisk. For example, the following are not permitted (compile-time constraints): ALLOCATE( A(NUM_IMAGES()) ) ! Not allowed (no co-bounds) ALLOCATE( A(10)[NUM_IMAGES()] ) ! Not allowed (co-bound not *) Also, the values of all the local bounds are required to be the same on all images. For example, the following is not permitted (run-time constraint) ALLOCATE( A(THIS_IMAGE())[*] ) ! Not allowed (varying local bound) There is implicit synchronization of all images in association with each ALLOCATE statement that involves one or more co-arrays. Images do not commence executing subsequent statements until all images finish executing the ALLOCATE statement. Similarly, for DEALLOCATE, all images delay making the deallocations until they are all about to execute the DEALLOCATE statement. This synchronization is independent of those obtained by calling SYNC_ALL and SYNC_TEAM (see Sections 8 and 9). Note: Without these rules, an image might reference data on another image that has not yet been allocated or has already been deallocated. Note: Change from RAL-TR-1998-060. We now require all images to execute the same ALLOCATE statement and the same DEALLOCATE statement. This ensures that the co-arrays are allocated and deallocated in the same order on each image without imposing complicated extra rules. If the new rule is found in practice to be too restrictive, it could be relaxed in a revision of the language. Note: When an image executes an allocate statement, no communication is necessarily involved apart from any required for synchronization. The image allocates the local part and records how the corresponding parts on other images are to be addressed. The compiler, except perhaps in debug mode, is not required to enforce the rule that the bounds are the same on all images. Nor is the compiler responsible for detecting or resolving deadlock problems. For an allocatable co-array without the SAVE attribute there is an implicit deallocation (and associated synchronization) before the procedure in which it is declared is exited by execution of a RETURN statement or an END statement. Note: Change from RAL-TR-1998-060. Previously, it was the programmer's responsibility to explicitly deallocate such a co-array. We do not want the possibility of the allocation state becoming undefined. Anyway, it is awkward for the user to program this if there is more than one return statement. Note: An allocatable co-array may be given the SAVE attribute unless separate arrays are needed at each level of recursion in a recursive procedure. For allocation of such a co-array, each image must descend to the same level of recursion or deadlock may occur. In an array assignment of an array to an allocatable co-array, the shapes must agree. In an intrinsic assignment to a remote object of a type that has an allocatable component at any level of component selection, the component shapes must agree. Note: Change from RAL-TR-1998-060. This rule was not needed in Fortran 95. 7 Array pointers A co-array may be of a derived type with pointer or allocatable components. For example, if P is a pointer component, Z[Q]%P is a reference to the target of component P of Z on image Q. This target must reside on image Q and must have been established by an allocate statement executed on image Q or a pointer assignment executed on image Q. For example, R => Z[Q]%P ! Not allowed (compile-time constraint) is not permitted. There is no requirement for all these components to be allocated or associated or for them to have the same shape, so an allocatable or pointer component or a subobject of such a component is not permitted as an actual argument that corresponds to a co-array dummy argument. Note: Change from RAL-TR-1998-060. Previously, pointer components were severely restricted in order that they could be associated with co-array dummy arguments. Note: Change from RAL-TR-1998-060. Allocatable components added (not included in Fortran 95). Intrinsic assignments are not permitted for co-array subobjects of a derived type that has a pointer component, since they would involve a disallowed pointer assignment for the component: Z[Q] = Z ! Not allowed if Z has a pointer Z = Z[Q] ! component (compile-time constraint) Similarly, for a co-array of a derived type that has a pointer or allocatable component, it is illegal to allocate one of those components on another image: TYPE(SOMETHING), ALLOCATABLE :: T[:] ... ALLOCATE(T[*]) ! Allowed ALLOCATE(T%PTR(N)) ! Allowed ALLOCATE(T[Q]%PTR(N)) ! Not allowed (compile-time constraint) A co-array is permitted to be of a type that has a procedure pointer component or a type bound procedure. Such a procedure must not be invoked remotely; for example, the statement CALL A[P]%PROC(X) is not permitted. Note: Change from RAL-TR-1998-060. These were not part of Fortran 95. A possible future extension is for these to be used for remote procedure calls. 8 Execution control Most of the time, each image executes on its own as a Fortran program without regard to the execution of other images. It is the programmer's responsibility to ensure that whenever an image alters a co-array datum, no other image might still need the old value. Also, that whenever an image accesses a co-array datum, it is not an old value that needs to be updated by another image. The programmer uses invocations of the intrinsic synchronization procedures to do this, and the programmer should make no assumptions about the execution timing on different images. Note: This obligation on the programmer provides the compiler with scope for optimization. When constructing code for execution on an image, it may assume that it is the only image in execution until the next invocation of one of the intrinsic synchronization procedures and thus it may use all the optimization techniques available to a standard Fortran compiler. Note (cont): In particular, if the compiler employs temporary memory such as cache or registers (or even packets in transit between images) to hold co-array data, it must copy such data to memory that can be accessed by another image to make it visible to it. Also, if another image changes the co-array data, the executing image must recover the data from global memory to the temporary memory it is using. The intrinsic procedure SYNC_MEMORY is provided for both purposes. It is concerned only with data held in temporary memory on the executing image for co-arrays in the local scope. Given this fundamental intrinsic procedure, the other synchronization procedures can be programmed in Fortran (see Appendix 1), but the intrinsic versions are likely to be more efficient. In addition, the programmer may use it to express customized synchronization operations in Fortran. If data calculated on one image are to be accessed on another, the first image must call SYNC_MEMORY after the calculation is complete and the second must call SYNC_MEMORY before accessing the data. Synchronization is needed to ensure that SYNC_MEMORY is called on the first before SYNC_MEMORY is called on the second. Note: A compiler can hold co-arrays in temporary storage, such as cache or registers, between calls to SYNC_MEMORY. Note: If the local part of a co-array or a subobject of it is an actual argument corresponding to a dummy argument that is not a co-array, a copy may be passed to the procedure. To avoid the possibility of the original being altered by another image after the copy has been made, a synchronization may be needed ahead of the procedure invocation. Similarly, a synchronization is needed after return before any other image accesses the result. The subroutine SYNC_TEAM (see Section 10) provides synchronization for a team of images. The subroutine SYNC_ALL provides a shortened call for the important case where the team contains all the images. Each invocation of SYNC_TEAM or SYNC_ALL also has the effect of SYNC_MEMORY. The subroutine SYNC_ALL is not discussed further in this section. Note: No information is available about whether an action on one image occurs before or after an action on another image unless one is executed ahead of a synchronization call and the other is executed behind the corresponding synchronization call on the other. For example, while one image executes the statements between two invocations of SYNC_ALL, another image might be out of execution. Here is a example that imposes the fixed order 1, 2, ... on images: ME = THIS_IMAGE() NE = NUM_IMAGES() IF(ME>1) CALL SYNC_TEAM( ME-1 ) P[6] = P[6] + 1 IF(ME= CMEQ ) EXIT END DO END DO END SUBROUTINE WAIT_TEAM LOGICAL FUNCTION READY_TEAM(TEAM) INTEGER, INTENT(IN) :: TEAM(:) CALL SYNC_MEMORY DO K= 1,SIZE(TEAM) Q = TEAM(K) IF( C(Q) < C(ME)[Q]) EXIT END DO READY = K>SIZE(TEAM) END FUNCTION READY_TEAM SUBROUTINE SYNC_TEAM11(TEAM,WAIT) INTEGER, INTENT(IN) :: TEAM(:),WAIT(:) CALL NOTIFY_TEAM(TEAM) CALL WAIT_TEAM(WAIT) END SUBROUTINE SYNC_TEAM11 SUBROUTINE SYNC_TEAM1(TEAM) INTEGER, INTENT(IN) :: TEAM(:) CALL SYNC_TEAM11(TEAM,TEAM) END SUBROUTINE SYNC_TEAM1 SUBROUTINE SYNC_TEAM0(TEAM) INTEGER, INTENT(IN) :: TEAM CALL SYNC_TEAM1((/ME,TEAM/)) END SUBROUTINE SYNC_TEAM0 SUBROUTINE SYNC_TEAM10(TEAM,WAIT) INTEGER, INTENT(IN) :: TEAM(:) INTEGER, INTENT(IN) :: WAIT CALL SYNC_TEAM11(TEAM,(/WAIT/)) END SUBROUTINE SYNC_TEAM10 SUBROUTINE SYNC_TEAM00(TEAM,WAIT) INTEGER, INTENT(IN) :: TEAM INTEGER, INTENT(IN) :: WAIT CALL SYNC_TEAM11((/ME,TEAM/),(/WAIT/)) END SUBROUTINE SYNC_TEAM00 SUBROUTINE SYNC_TEAM01(TEAM,WAIT) INTEGER, INTENT(IN) :: TEAM INTEGER, INTENT(IN) :: WAIT(:) CALL SYNC_TEAM ((/ME,TEAM/),WAIT) END SUBROUTINE SYNC_TEAM01 SUBROUTINE SYNC_ALL CALL SYNC_TEAM (ALL,ALL) END SUBROUTINE SYNC_ALL SUBROUTINE SYNC_ALL1(WAIT) INTEGER, INTENT(IN) :: WAIT(:) CALL SYNC_TEAM(ALL,WAIT) END SUBROUTINE SYNC_ALL1 SUBROUTINE SYNC_ALL0(WAIT) INTEGER, INTENT(IN) :: WAIT CALL SYNC_TEAM(ALL,(/WAIT/)) END SUBROUTINE SYNC_ALL0 END MODULE SYNC Appendix 2. Module for THIS_IMAGE(ARRAY) and IMAGE_INDEX(ARRAY,SUB) The intrinsics THIS_IMAGE(ARRAY) and IMAGE_INDEX(ARRAY,SUB) cannot be coded in Fortran since ARRAY may be of any type and THIS_IMAGE(ARRAY) needs to know the index of the image on which the code is running. We therefore require the bounds to be specified as integer arrays and we require the image index for THIS_IMAGE(ARRAY). MODULE INDEX CONTAINS INTEGER FUNCTION IMAGE_INDEX(LBOUND,UBOUND,SUB) INTEGER,INTENT(IN) :: LBOUND(:),UBOUND(:),SUB(:) INTEGER :: I,N N = SIZE(SUB) IMAGE_INDEX = SUB(N) - LBOUND(N) DO I = N-1,1,-1 IMAGE_INDEX = IMAGE_INDEX*(UBOUND(I)-LBOUND(I)+1) + & SUB(I) - LBOUND(I) END DO IMAGE_INDEX = IMAGE_INDEX + 1 END FUNCTION IMAGE_INDEX INTEGER FUNCTION THIS_IMAGE(LBOUND,UBOUND,ME) RESULT(SUB) INTEGER,INTENT(IN) :: LBOUND(:),UBOUND(:),ME INTEGER :: SUB(SIZE(LBOUND)) INTEGER :: EXTENT,I,M,ML,N N = SIZE(SUB) M = ME - 1 DO I = 1,N-1 EXTENT = UBOUND(I)-LBOUND(I)+1 ML = M M = M/EXTENT SUB(I) = ML - M*EXTENT + LBOUND(I) END DO SUB(N) = M + LBOUND(N) END FUNCTION THIS_IMAGE END MODULE INDEX History: Presented by John Reid at the 1998 meeting of WG5 in Trollhattan. --------------------------------------------------------------------- Number: UK-002 Title: Decimal floating point arithmetic Submitted By: UK Status: For Consideration Severity Level: 3 References: 1. A Summary of Densely Packed Decimal encoding http://www2.hursley.ibm.com/decimal/DPDecimal.html 2. Draft changes to the C language for decimal arithmetic WG14-N1016 http://std.dkuug.dk/JTC1/SC22/WG14/www/documents Basic Functionality: To allow for decimal floating point arithmetic Rationale: Languages increasingly support decimal arithmetic in addition to binary or hexadecimal arithmetic, e.g. C#, COBOL, Visual Basic. Now that IBM are about to sell hardware with packed decimal floating point, C and C++ are preparing TRs to extend those languages to provide decimal floating-point facilities, principally for financial applications. In order to retain competitiveness and to maintain interoperability with C, Fortran should adopt comparable facilities. Estimated Impact: no effect on existing programs Detailed Specification: Current hardware developments give a form of packed decimal holding three decimal digits in ten bits. However this proposal for Fortran does not depend on the hardware format and allows for the possibility that within a single program unit some real variables may be held and operated upon in decimal form and some in binary or hexadecimal (or other radix) form, and that the default radix for the processor may be any of these. History: ---------------------------------------------------------------------- Number: UK-003 Title: Conformance to IEEE 754R (IEEE Standard for Floating-Point Arithmetic) Submitted By: UK Status: For Consideration Severity Level: 4 References: 1. IEEE 754R-200x (IEEE Standard for Floating-Point Arithmetic) This is still being developed. The March 2004 document is at http://www.validlab.com/754R/drafts/754r.pdf 2. Draft changes to the C language for decimal arithmetic WG14-N1016 http://std.dkuug.dk/JTC1/SC22/WG14/www/documents Basic Functionality: To allow for decimal floating point arithmetic in conformance with IEEE 754R Rationale: Other languages, notably C and C++, are being extended to accommodate features of IEEE 754R, principally for decimal floating point arithmetic. In order to retain interoperability with C, Fortran should adopt comparable facilities. Estimated Impact: no effect on existing programs Detailed Specification: This proposal is dependent on facilities to specify decimal arithmetic being adopted separately. It is necessarily an outline specification as IEEE 754R is not yet complete. 1. Add reference to IEEE 754R in section 1.9. 2. Add new intrinsic procedures as required by IEEE 754R section 5 (Operations) and Appendix L (Language extensions) to section 14 of the Fortran base language. Depending on details in the final form of IEEE 754R, some procedures may be added to section 13. References to the term "IEEE arithmetic", which occur mainly in section 14 but also in sections 7, 13 and 15, may need to be redefined. History: ---------------------------------------------------------------------- Number: UK-004 Title: KIND environment specification Submitted By: UK Status: For Consideration Severity Level: 3 References: Basic Functionality: Provide prespecified parameter arrays in FORTRAN_ENV that define the number (size of array) and available kind values for each intrinsic type. Rationale: For many programs it would be useful if it were possible to find the number of different kinds available for the intrinsic types and the actual kind values assigned by the processor. Estimated Impact: Little or no effect on existing programs Detailed Specification: I would expect there to be declarations like the following defined in ISO_FORTRAN_ENV INTEGER,PARAMETER:: FP_KINDS(3) = (/4,8,16/), & INT_KINDS(2) = (/4,2/), & CHAR_KINDS(1)= (/1/)... An additional requirement would be that FP_KINDS(1) must be the value for KIND(0.0E0) and FP_KINDS(2) that of KIND(0.0D0). Similarly the first element in each array must contain the kind value for the default intrinsic type. An inquiry as to the SIZE(FP_KINDS) will return the information as to the number of floating point, etc. representation methods available. History: ---------------------------------------------------------------------- Number: UK-005 Title: Long Integers Submitted by: UK Status: For Consideration Severity Level: 4 References: Basic Functionality: Require the support of long integers declared thus: integer, parameter :: long = selected_int_kind(18) integer (long) :: l,m,n Rationale: Long integers are needed increasingly in large programs, but if we make the above declaration in a program we cannot be sure that it will compile. Estimated Impact: No new syntax is involved, so the edits to the standard will be very simple - just a few sentences for the requirement and perhaps a note. Most compilers already support long integers and would need no change. Detailed Specification: Require the support of integers whose kind type parameter value is selected_int_kind(18). History: ---------------------------------------------------------------------- Number: UK-006 Title: Multiple Nonzero-Rank Part References Submitted By: UK Status: For Consideration Severity Level: 4 References: J3/03-253 Basic Functionality: Allow array sections that are 'arrays of arrays', for example, a(:,:)%comp(:,:) while maintaining the rule that no pointer or allocatable component can occur after a part that has nonzero rank. Rationale: These are not allowed because when such an array is passed to a dummy argument dum, a(i,j)%comp(k,l) corresponds to dum(k,l,i,j) and the more array parts there are, the more confusing it is seen to be. However, programmers would soon get used to the rule and it is not hard to state. The constraint means a significant loss of functionality. It disallows the use of all the powerful array syntax and intrinsics for data stored inside derived types. Estimated Impact: The edits needed to implement this are small and localized to Section 6.1.2. References with multiple non-zero part-refs are treated in all respects like data-refs with just a single non-zero rank part-ref, namely, they are array sections. The implementation of this feature does require some nontrivial work. However, the steps involved are very similar to the way current data-refs and array pointers/sections are handled. Detailed Specification: The main edits needed are the following: [105:12]. In C614, delete "There shall not be more then one with nonzero rank.". [105:14]. Change line to "The rank of a is the sum of the ranks of the s with nonzero rank, if any; otherwise, the rank is zero." [105:15+]. Add paragraph: "The shape of a is the rank-1 array obtained by concatenating the shapes of the nonzero rank s in backward order, that is, starting from the final ." History: ---------------------------------------------------------------------- Number: UK-007 Title: Pointer function references as actual arguments Submitted by: UK Status: For Consideration Severity Level: 4 References: N1612 interp (F95) 000074 Basic Functionality: Allow references to functions returning an associated pointer to appear as actual arguments associated with INTENT(OUT) dummies. This is parallel to the way regular pointers are treated. Example: FUNCTION storage(key) RESULT(loc) INTEGER, INTENT(IN) :: key REAL, POINTER :: loc loc=>... END FUNCTION ! Make the following legal CALL RANDOM_NUMBER(storage(10)) Rationale: The proposed change makes the language more symmetrical. It arose from considering interpretation request F95/000074, entitled "TARGET dummy arguments and POINTER expressions", for which it was decided that in Fortran 2003 function results are not definable even when they are pointers associated with a TARGET. However, the functionality of allowing code like the one in the example above is needed in the language. Also there is inconsistency with the way pointer variables are treated. Estimated Impact: As interp 000074 showed, the standard is already a little murky on whether function results are definable, so changes to the standard will be small. The cost for implementations will be small. Detailed Specification: The text which describes argument association has problems in that it often confuses the actual argument with the "thing" that the dummy is associated with. Once that text is clarified the above example should become legal. History: Based on a proposal by Aleksander Donev ---------------------------------------------------------------------- Number: UK-008 Title: Pointer function references as lhs in assignment Submitted by: UK Severity Level: 4 Status: For Consideration References: N1612 interp (F95/) 000074 Basic Functionality: Allow references to functions returning an associated pointer to appear as the lhs of assignment statement, where the value of the target is changed. This is parallel to the way regular pointers are treated. Example: FUNCTION storage(key) RESULT(loc) INTEGER, INTENT(IN) :: key REAL, POINTER :: loc loc=>... END FUNCTION ! Make the following legal storage(5)=0.5 Rationale: The proposed change makes the language more symmetrical. It arose from considering interpretation request F95/000074, entitled "TARGET dummy arguments and POINTER expressions". The proposed change also brings in a very useful functionality: it allows one to change between different data structures with little to no change in the source code. Consider an example of a dictionary data structure, where the keys are INTEGER and the data values are REAL. A simple implementation might use an array to store the values: TYPE :: Dictionary_t REAL, DIMENSION(:), ALLOCATABLE :: storage ... END TYPE Later however, a more sophisticated data-structure (say a hash-table) that conserves memory may be implemented, substituting the array with a pointer-valued function which returns a pointer to the storage location corresponding to the key: TYPE :: Dictionary_t REAL, DIMENSION(:), ALLOCATABLE :: storage CONTAINS PROCEDURE :: storage ! See previous function END TYPE FUNCTION storage(dictionary, key) RESULT(loc) CLASS(Dictionary_t), INTENT(INOUT) :: dictionary INTEGER, INTENT(IN) :: key REAL, POINTER :: loc loc=>... END FUNCTION The text of the code will need minor changes: TYPE(Dictionary_t) :: dictionary ... dictionary%storage(5)=0.5 Another example in numerical problems includes switching from full to sparse storage for a matrix without having to change all the references. Estimated Impact: The proposed change requires introducing new syntax rules. However it is simple in nature. The cost to implementations will be low. Detailed Specification: Add a second form of in 7.4.1.1 in R734: is = is or where is a and is a pointer History: Based on a proposal by Aleksander Donev ---------------------------------------------------------------------- Number: UK-009 Title: Use procedureness in generic resolution Submitted By: UK Status: For Consideration Severity Level: 3 Reference: Basic Functionality: Allow the procedureness of an argument to be used to disambiguate generic procedure references. Rationale: One can always tell whether a name (or designator) is that of a procedure or of a data object. Users complain that since THEY can tell the difference, why can the compiler not? Estimated Impact: Localized change to 16.2.3. Small effect on implementations. Detailed Specification: Allow whether an argument is a procedure to be used to disambiguate generic procedure references. Deciding which specific procedure to invoke already takes account of this (it requires that the actual arguments be "consistent" with the specific), all we have to do is to allow a generic set to include specifics whose only difference is whether an argument is a procedure. History: ---------------------------------------------------------------------- Number: UK-010 Title: Partial initialization of PARAMETERs Submitted By: UK Status: For Consideration Severity Level: 3-4 (depending on technical approach). Reference: Basic Functionality: Allow independent subobjects of a PARAMETER to be initialized by separate statements. Rationale: A frequently-heard complaint is the awkwardness of being required to initialize (inevitably huge) PARAMETER arrays in a single statement. Estimated Impact: The edits will mostly be local to clause 5, depending on the approach taken. Detailed Specification: Allow independent subobjects of a PARAMETER to be initialized by separate statements. To keep it simple, no access to the value of a PARAMETER should be allowed until all of it has been initialized. This could be done as simply as allowing PARAMETERs to be initialized in DATA statements, but other approaches might have technical merit. Suggested Syntax: Three possible syntaxes for this feature are described here, with their advantages and disadvantages listed. (1) Allow the DATA statement to be used on PARAMETERs. + Easy to standardize (gives a severity level of 3). + Easy to implement (compilers can already parse DATA statements). + Easy to learn (users already know about DATA). + Identical treatment of variables and parameters. - Cannot use expressions in the initializers. - Some people think DATA is old-fashioned. (2) Extend the syntax of the PARAMETER statement; in particular, allow " = ". + No new keyword needed. + Users recognize that PARAMETER is about parameters. + Can use expressions in the initializers. - Not as easy to standardize/implement/learn (severity 4). - Does not allow expressions to initialize subobjects of variables. - Some people think the PARAMETER statement is old-fashioned. (3) Do it with a new statement, e.g. "FUNKY :: = ". + Could handle variables/parameters consistently. + Syntax less "quirky" than DATA. - Not as easy to standardize/implement/learn (severity 4). - DATA will still be quirky anyway. Note: The only technical disadvantage of the simplest approach (use DATA) is the lack of expression initializers. This could be overcome by extending the syntax of DATA, e.g. to allow DATA(A(1:10) = [(i,i=1,10)]) History: ----------------------------------------------------------------------