To: J3 J3/19-219r1 From: Malcolm Cohen Subject: J3 Fortran interp letter ballot #35 - due 30-Sep-2019 Date: 2019-September-01 Enclosed in the next letter ballot on Fortran interpretations. This is a formal letter ballot; only one vote per principal member. An alternate member may vote if the principal member does not vote; in any case, comments are welcome from non-voting alternates and from members of WG5 that are not J3 members, and will be taken into consideration by J3/interp. The rules for interpretation handling by which we operate say: o J3 votes on the answer at a J3 meeting; a simple majority vote marks the answer as "passed by J3 meeting". o Between J3 meetings the chair of /interp sends a J3 letter ballot to J3 to approve interp answers that have been "passed by J3 meeting". The letter ballot runs for 30 days. An interp answer passes by a 2/3rds vote; a no vote must be accompanied by an explanation of the changes necessary to change the member's vote to yes. J3/interp reserves the right to recall an interp answer for more study even if the answer passes. 15 Fortran interpretations are currently "Passed by J3 meeting" after J3 meeting #219. This is the letter ballot phase to go from "Passed by J3 meeting" to "Passed by J3 letter ballot". ** This letter ballot period is lengthened slightly to avoid finishing ** on a weekend. The following Fortran interpretations are being balloted: Yes No Number Title --- --- F18/001 ACOSH principal value specification is wrong --- --- F18/002 Internal procedures in generic interface blocks --- --- F18/003 Pointer association of component of non-definable selector --- --- F18/004 Program execution sequence with failed images --- --- F18/005 Does INPUT_UNIT really identify the same unit as *? --- --- F18/006 Connection of INPUT_UNIT on different images --- --- F18/007 Problems with C_FUNLOC and C_F_PROCPOINTER being PURE --- --- F18/008 Contradictory assumed-rank requirements --- --- F18/009 Bad examples in IEEE_ARITHMETIC functions --- --- F18/010 Categories of pure procedures --- --- F18/011 Categories of elemental procedures --- --- F18/012 Internal procedure in a generic interface --- --- F18/013 TEAM_NUMBER arguments and intrinsic function are ambiguous --- --- F18/014 Type of OPERATION arguments to the REDUCE intrinsic --- --- F18/015 Example in C.6.8 is wrong The text of these interpretations is attached. Each interpretation starts with a row of "-"s. Please mark the above -Y- in the Yes column for "yes", -C- in the Yes column for "yes with comment", or -N- in the No column for a "no" answer {be sure to include your reasons with "no"} and send only the above text {not this entire mail message} with any comments to j3@j3-fortran.org by 11:59:59PM, PDT, Monday, 30-Sep-2019, in order to be counted. Thanks /Malcolm ---------------------------------------------------------------------- NUMBER: F18/001 TITLE: ACOSH principal value specification is wrong KEYWORDS: ACOSH DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Clause 16.9.5 ACOSH( X ) p5 Result Value has: "If the result is complex the imaginary part is expressed in radians and lies in the range 0 <= AIMAG (ACOSH (X)) <= {pi}". There is general agreement that the principal value of ACOSH should have the real part non-negative which means the imaginary part must range from -pi to +pi. Is this a mistake in the definition of ACOSH? ANSWER: Yes, this is a mistake. Edits are included to correct this error. This will be an incompatibility with Fortran 2008. EDITS to 18-007r1: [26:17+] 4.3.3 Fortran 2008 compatibility, p10+, insert new para "Fortran 2008 required ACOSH of a complex value to have the imaginary part non-negative and had no requirement on the real part. This document requires ACOSH of a complex value to have a non-negative real part and has no such requirement on the imaginary part." [340:34-35] 16.9.5 ACOSH, p5 Result Value, after "is complex" insert "the real part is non-negative and", change "range 0" to "range $-\pi$". Making the whole p5 read "Result Value. The result has a value equal to a processor- dependent approximation to the inverse hyperbolic cosine function of X. If the result is complex the real part is non- negative, and the imaginary part is expressed in radians and lies in the range $-\pi$ <= AIMAG (ACOSH (X)) <= $\pi$." SUBMITTED BY: Anton Shterenlikht HISTORY: 18-236 m217 Submitted 18-236r1 m217 Put into interp format, revised edits. 18-236r2 m217 Revised draft - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/002 TITLE: Internal procedures in generic interface blocks KEYWORDS: Internal procedure, generic interface block DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: An internal procedure is allowed in a GENERIC statement, but apparently it cannot appear in a generic interface block. Section 15.4.3.4.1 (12.4.3.4.1 in F2008) Generic identifiers p1 states "A generic interface block specifies a generic interface for each of the procedures in the interface block. The PROCEDURE statement lists procedure pointers, external procedures, dummy procedures, or module procedures that have this generic interface." Is the apparent prohibition of internal procedures in the PROCEDURE statement intended? ANSWER: No, this was not intended. An internal procedure should be allowed in a generic interface body. An edit is provided to correct this mistake. DISCUSSION: In F2003, Section 12.3.2.1 Interface Block has rule R1206 is [MODULE] PROCEDURE with constraint C1270 "A shall have an explicit interface and shall refer to an accessible procedure pointer, external procedure, dummy-procedure, or module procedure." Edits in paper 05-202r1 allowed internal procedures to be passed as actual arguments and to be targets of procedure pointers. This meant an internal procedure could be the target of a procedure pointer which was specified in a generic interface body. Paper 08-178 asked the question "What is the point of excluding internal procedure in C1207?" and replaced C1207 with "A shall be a nonintrinsic procedure that has an explicit interface." The normative text cited in the question was not modified. This was an oversight. EDIT to 18-007r1: [294:11-12] 15.4.3.4.1 Generic identifiers, p1, second sentence, Change "procedure pointers, external procedures, dummy procedures, or module procedures" to "nonintrinsic procedures with explicit interfaces". This makes the sentence read: "The PROCEDURE statement lists nonintrinsic procedures with explicit interfaces that have this generic interface." SUBMITTED BY: Jon Steidel HISTORY: 18-251 m217 Submitted 18-251r1 m217 Revised draft - Passed by J3 meeting n/a n/a Typos noted at meeting corrected by /Interp. ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/003 TITLE: Pointer association of component of non-definable selector KEYWORDS: Pointer association, Associate name DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Consider the following type :: T real, pointer :: X end type T type(t), external :: F real, target :: P associate ( A => F(42) ) nullify ( A%X ) !*** A%X => P !*** end associate The topic is whether the statements marked "!***" (the NULLIFY statement and the pointer assignment statement) conform to the standard. 11.1.3.3p5 ([175:18-21] of 18-007r1) has two requirements that are relevant to this topic: "The associating entity itself is a variable, but if the selector is not a definable variable, the associating entity is not definable and shall not be defined or become undefined. If a selector is not permitted to appear in a variable definition context (19.6.7), neither the associate name nor any subobject thereof shall appear in a variable definition context." With regards to the second sentence, neither NULLIFY nor a pointer assignment statement is a variable definition context (19.6.7, [516:12-30] lists fifteen variable definition context: neither statement appears in the list. Therefore it seems that this requirement is satisfied. With regards to the first sentence, the associate-name A "shall not be defined or become undefined". It appears that neither of these statements cause A to be defined or become undefined, because (a) An object of derived type is defined if and only all of its nonpointer components are defined (see 19.6.1p4, [511:11]). The pointer association status of the component A%X is thus irrelevant to the question of whether A is defined. (b) Neither statement appears anywhere in the giant lists of "Events that cause variables to become defined" (or "undefined") in 19.6.5 and 19.6.6. Therefore we must reluctantly conclude that the requirements of the first sentence also appear to be satisfied. Against this, it is certainly true that the *value* of A is affected by the statements in question: see 7.5.8 Derived-type values, which states that the "component value" of a pointer component is its association status, and "The set of values of a particular derived type consists of all possible sequences of the component values..." However, there is no rule in 11.1.3.3 about changing the values, even though it might seem contradictory that something that changes the value of an undefinable object would be permitted. So the question is, are the two statements standard-conforming? ANSWER: No, these statements were not intended to be standard-conforming. The lack of an explicit rule is an error in the standard. An edit is provided to correct this error. EDIT to 18-007r1: [175:21] 11.1.3.3 Other attributes of associate names, p5, After "variable definition context" insert " or a pointer association context", making the whole paragraph read: "The associating entity itself is a variable, but if the selector is not a definable variable, the associating entity is not definable and shall not be defined or become undefined. If a selector is not permitted to appear in a variable definition context (19.6.7), neither the associate name nor any subobject thereof shall appear in a variable definition context or pointer association context." {Prohibit the marked statements. The extra context is only relevant to pointer subobjects, but this need not be stated explicitly.} {This might appear to be an incompatibility since the explicit prohibition is missing from Fortran 2003 and 2008, and thus should require an edit to the "compatibility" subclauses in clause 4. However as it seems somewhat contradictory, it is argued that those standards do not establish an unambiguous interpretation of the code in question, so no compatibility issue arises.} SUBMITTED BY: Van Snyder HISTORY: 18-262r1 m217 Submitted 18-262r2 m217 Revised draft - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/004 TITLE: Program execution sequence with failed images KEYWORDS: Program execution, Termination of execution, Failed image, DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Consider execution of a program with more than one image, and some image has failed (perhaps by execution of FAIL IMAGE, or perhaps by some actual failure). Let us further suppose that all other images have initiated normal termination. According to 5.3.7 "Termination of execution", paragraph 1: "Termination of execution of the program occurs when all images have terminated execution." This text is unchanged from Fortran 2008, which did not have failed images. As an image that has failed "has ceased participating in program execution but has not terminated execution", it would seem that in this situation, execution of the program has not terminated. Should failed images cause execution of the program not to terminate? ANSWER: No, failed images have stopped participating in program execution and therefore their existence should not prevent program termination. That this definition is unchanged from Fortran 2008 is an oversight. An edit is supplied to correct this. EDIT to 18-007r1: [38:8] 5.3.7 Termination of execution, p1, After "when all images have" insert "failed or", making the last sentence of the paragraph read "Termination of execution of the program occurs when all images have terminated execution or failed." SUBMITTED BY: Malcolm Cohen HISTORY: 19-129 m218 Submitted 19-129r1 m218 Revised draft - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/005 TITLE: Does INPUT_UNIT really identify the same unit as *? KEYWORDS: Connection, INPUT_UNIT DEFECT TYPE: Interpretation STATUS: Passed by J3 meeting QUESTION: According to 16.10.2.13 INPUT_UNIT [429:8-9], "The value of the default integer scalar constant INPUT_UNIT identifies the same processor-dependent external unit preconnected for sequential formatted input as the one identified by an asterisk in a READ statement;" Consider the program: PROGRAM input_unit_test USE iso_fortran_env CHARACTER(80) line OPEN(input_unit,FILE='test.dat',ACTION='read') READ(input_unit,'(a)') line PRINT *,TRIM(line) READ(*,'(a)') line PRINT *,TRIM(line) END PROGRAM Furthermore, let us suppose the file test.dat contains the following two lines: dat line 1 dat line 2 and let us further suppose the file that was preconnected before the OPEN statement contains the following single line: inp line 1 Is the output of the program (1): dat line 1 dat line 2 or is it (2): dat line 1 inp line 1 ? The plain meaning of the words "identifies the same processor-dependent external unit... ...as the one identified by an asterisk in a READ" would seem to imply that (1) is expected, not (2); however, only some Fortran processors produce output (1), while others have been observed to produce output (2). ANSWER: Output (1) is correct. According to the quoted words, using INPUT_UNIT in a READ statement must have the same effect as UNIT=* (which is the same effect as not having a input/output control list). It is common for unit 5 to be effectively preconnected to stdin, but on some processors changing the connection of unit 5 (e.g. with an OPEN statement) does not affect unit=*. On such a processor, the value of INPUT_UNIT should not be equal to 5, but to whatever value, possibly negative, that will continue to connect to unit=*. EDIT to 18-007r1: None. SUBMITTED BY: Malcolm Cohen HISTORY: 19-130 m218 Submitted 19-130r1 m218 Revised draft - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/006 TITLE: Connection of INPUT_UNIT on different images KEYWORDS: Connection, INPUT_UNIT DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: According to 16.10.2.13 INPUT_UNIT [429:8-9], "The value of the default integer scalar constant INPUT_UNIT identifies the same processor-dependent external unit preconnected for sequential formatted input as the one identified by an asterisk in a READ statement;" and according to 12.5.1 Referring to a file [217:10-11], "In a READ statement, an io-unit that is an asterisk identifies an external unit that is preconnected for sequential formatted input on image 1 in the initial team only (12.6.4.3)." This leaves unanswered the status of the i/o unit identified by INPUT_UNIT on images other that 1. Plausible interpretations are: (a) it is not preconnected on other images; (b) it is preconnected, but to a processor-dependent file; (c) it is preconnected, but it is not standard-conforming for a program to use it; (d) it is preconnected, but it raises an i/o error condition if a program attempts to use it; (e) attempting to use INPUT_UNIT in any way, including connecting it to another file, is not conforming; (f) INPUT_UNIT may be connected to another file, but it is still processor-dependent whether it may be used; (g) on an image other than image 1, - it is processor-dependent whether it is preconnected, - if it is preconnected, * it is processor-dependent to what file, * it is processor-dependent whether use is permitted, - if it is subsequently connected, it is processor-dependent whether it may be used. Q1. What is the preconnection status of INPUT_UNIT on images other than image one? Q2. On an image other than image one, if INPUT_UNIT happens to be preconnected, may it be used? Q3. On an image other than image one, if INPUT_UNIT is connected to a different file by an OPEN statement, may it be used? Also, the definition text for INPUT_UNIT in 16.10.2.13 makes no mention of any caveat, but implies it is preconnected on every image. Perhaps this text could be clarified. ANSWER: A1. INPUT_UNIT (and thus the unit identified by an asterisk in a READ statement) was not intended to be preconnected on images other than image one in the initial team. An edit is supplied to correct this omission. A2. Moot. A3. Yes. EDITS to 18-007r1: [217:11] 12.5.1 Referring to a file, p4, After "on image 1 in the initial team only (12.6.4.3)" insert "; it is not preconnected on any other image". {Clarify preconnection state on images other than one.} {Editor notes that "image 1" should be "image one".} [429:9,10] 16.10.2.13 INPUT_UNIT, p1, Delete "preconnected for sequential formatted input". {This is a mere parenthetical remark which could confuse.} After "input/output control list (12.6.4.3)." insert new sentence "This unit is preconnected for sequential formatted input on image one in the initial team only, and is not preconnected on any other image." {Make this match clause 12.} SUBMITTED BY: Malcolm Cohen HISTORY: 19-131 m218 Submitted 19-131r1 m218 Revised draft - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/007 TITLE: Problems with C_FUNLOC and C_F_PROCPOINTER being PURE KEYWORDS: C_FUNLOC, C_F_PROCPOINTER, ISO_C_BINDING DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTIONS: 1) Regarding C_FUNLOC (X), In 15.7 Pure procedures, constraint C1590 is: "C1590 The specification-part of a pure subprogram shall specify that all its dummy procedures are pure." In 15.5.2.9 Actual arguments associated with dummy procedure entities, the first paragraph says "If the interface of a dummy procedure is explicit, its characteristics as a procedure (15.3.1) shall be the same as those of its effective argument, except that a pure effective argument may be associated with a dummy argument that is not pure and an elemental intrinsic actual procedure may be associated with a dummy procedure (which cannot be elemental)." If C_FUNLOC is PURE, then these together imply that the actual argument, X, has to be a PURE procedure. This is not stated in the specification of this function in 18.2.3.5. This has the effect of limiting the uses of C_FUNLOC compared to the specification in Fortran 2008. This is not indicated in 4.3.3 Fortran 2008 compatibility. Was this an intentional change, or was making C_FUNLOC PURE a mistake? 2) Regarding C_F_PROCPOINTER (CPTR, FPTR), a similar argument to that above implies that the INTENT(OUT) procedure pointer, FPTR, is a PURE procedure. However, there is no stated requirement that the input argument CPTR be PURE, and indeed there is no specification of what that even means if CPTR is a pointer to an interoperable C function. This suggests that C_F_PROCPOINTER provides a backdoor allowing an impure procedure to appear to be pure, invalidating the assumptions that are associated with a pure procedure. Was making C_F_PROCPOINTER a PURE a mistake? ANSWER: 1) Making C_F_PROCPOINTER PURE was a mistake. Edits are included to correct this error. 2) It was not an error to make C_FUNLOC PURE. Constraint C1590 does not apply to C_FUNLOC as it is an intrinsic module procedure, and as such is not defined by a subprogram. If a PURE procedure invokes C_FUNLOC, then the argument to C_FUNLOC must be a PURE procedure. However if an IMPURE procedure invokes C_FUNLOC, the actual argument to C_FUNLOC need not be a PURE procedure. An edit is provided to clarify this. EDITS to 18-007r1: [469:26-27] In 18.2.3 Procedures in the module, 18.2.3.1 General, second sentence, change "C_F_POINTER subroutine is" to "C_F_POINTER and C_F_PROCPOINTER subroutines are". Making the whole sentence read "The C_F_POINTER and C_F_PROCPOINTER subroutines are impure; all other procedures in the module are pure." [472:30] In 18.2.3.5 C_FUNLOC (X) after "object." add "If C_FUNLOC is called from a PURE procedure, X shall be a PURE procedure, otherwise it may be IMPURE." SUBMITTED BY: Bill Long HISTORY: 19-112 m218 Submitted 19-112r1 m218 Revised draft - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/008 TITLE: Contradictory assumed-rank requirements KEYWORDS: Assumed rank DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Paragraph 1 of subclause 8.5.8.7 (Assumed-rank entity) states that an assumed-rank entity is a dummy data object ... or the associate name of a RANK DEFAULT block in a SELECT RANK construct. C837 requires an assumed-rank entity to be a dummy data object. It does not permit an associate name of a RANK DEFAULT block in a SELECT RANK construct to have assumed rank. Is an associate name of a RANK DEFAULT block in a SELECT RANK construct permitted to have assumed rank? ANSWER: Yes, the associate name of a RANK DEFAULT block may have assumed rank. An edit is supplied to remove the contradiction. EDIT to 18-007r1: [101:13-14 C837 in 8.5.8.7 Assumed-rank entity] At the end of C837, after "or VALUE attribute", insert ", or the associate name of a RANK DEFAULT block in a SELECT RANK construct whose selector has assumed rank", making the whole constraint read: C837 An assumed-rank entity shall be a dummy data object that does not have the CODIMENSION or VALUE attribute, or the associate name of a RANK DEFAULT block in a SELECT RANK construct whose selector has assumed rank. SUBMITTED BY: Van Snyder HISTORY: 19-119 m218 Submitted 19-119r1 m218 Revised draft - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/009 TITLE: Bad examples in IEEE_ARITHMETIC functions KEYWORDS: IEEE_VALUE, IEEE_ARITHMETIC module, examples DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: In 17.11 the examples for IEEE_MAX_NUM, IEEE_MIN_NUM, IEEE_QUIET_compare functions, and IEEE_SIGNALING_compare functions all contain a call to IEEE_VALUE(IEEE_QUIET_NAN). IEEE_VALUE has two non-optional arguments, not one. Should calls to IEEE_VALUE in each of these examples have an additional X= argument? ANSWER: Yes, IEEE_VALUE has two non-optional arguments, X and CLASS. The X argument was mistakenly omitted. Edits are provided to fix these issues. EDITS to 18-007r1: [448:12] 17.11.17 IEEE_MAX_NUM p8 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [449:9] 17.11.19 IEEE_MIN_NUM p8 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [451:4] 17.11.24 IEEE_QUIET_EQ p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [451:18] 17.11.25 IEEE_QUIET_GE p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [451:32] 17.11.26 IEEE_QUIET_GT p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [452:10] 17.11.27 IEEE_QUIET_LE p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [452:24] 17.11.28 IEEE_QUIET_LT p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [452:38] 17.11.29 IEEE_QUIET_NE p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [457:37] 17.11.41 IEEE_SIGNALING_EQ p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [458:13] 17.11.42 IEEE_SIGNALING_GE p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [458:27] 17.11.43 IEEE_SIGNALING_GT p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [459:4] 17.11.44 IEEE_SIGNALING_LE p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [459:18] 17.11.45 IEEE_SIGNALING_LT p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" [459:32] 17.11.46 IEEE_SIGNALING_NE p7 Change "IEEE_VALUE (IEEE_QUIET_NAN)" to "IEEE_VALUE (1.0, IEEE_QUIET_NAN)" SUBMITTED BY: Jon Steidel HISTORY: 19-124 m218 Submitted - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/010 TITLE: Categories of pure procedures KEYWORDS: pure DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Subclause 15.7 Pure procedures begins with a list of categories of pure procedures. The list does not include procedure pointers or type-bound procedures. Dummy procedures are included in the list, and so dummy procedure pointers are allowed, but other procedure pointers are not. Q1. Can procedure pointers that are not dummy procedures be pure? Q2: Can type-bound procedures be pure? ANSWER: A1. Procedure pointers that are not dummy procedures are allowed to be pure. The absence of procedure pointers in the list in Subclause 15.7 is an oversight. An edit to correct the oversight is provided. A2. Type-bound procedures that are bound to pure procedures are pure. The absence of type-bound procedures in Subclause 15.7 is an oversight. An edit to correct the oversight is provided. EDITS to 18-007r1: [324:1, 15.7 "Pure procedures" p1] Replace "specified to be PURE, or" with "specified to be PURE, * a procedure pointer that has been specified to be PURE, * a type-bound procedure that is bound to a pure procedure, or" { Add missing entries to the list in Subclause 15.7. } SUBMITTED BY: Robert Corbett HISTORY: 19-151 m218 Submitted - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/011 TITLE: Categories of elemental procedures KEYWORDS: elemental DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: The list of categories of elemental procedures at the start of Subclause 15.8 "Elemental procedures" [325:11-12] is incomplete. Procedures that are defined to be elemental in intrinsic modules are not included. Type-bound procedures are not included. Dummy procedures and procedure pointers are not included, but there is evidence that those omissions were intentional. The standard intrinsic modules specify several procedures to be elemental. The omission of module procedures declared in intrinsic modules from the list in Subclause 15.8 creates a contradiction. Subclause 7.5.6.2 [80:5-8] and Subclause 7.5.7.3 [82:16] both assume that type-bound procedures may be elemental. Nonintrinsic elemental procedures cannot be used as actual arguments [301: 29, 15.5.1 "Syntax of a procedure reference" p1]. Elemental procedures specified in the standard intrinsic modules are generic, and so they cannot be passed as actual arguments. Elemental intrinsic procedures can be passed as actual arguments [309: 2-5, 15.5.2.9 "Actual arguments associated with dummy procedure entities" p1], but the text cited indicates that dummy procedures cannot be elemental. Procedure pointers pose a bit of a problem. A nonintrinsic elemental procedure cannot be the target of a pointer assignment [165:34, 10.2.2.2 "Syntax of the pointer assignment statement" ]. However, Subclause 10.2.2.4 "Pointer procedure assignment" paragraph 3 states If the pointer object has an explicit interface, its characteristics shall be the same as the pointer target except that the pointer target may be pure even if the pointer object is not pure and the pointer target may be an elemental intrinsic procedure even if the pointer object is not elemental. The final phrase suggests that a pointer object might be elemental, but it does not say that it can be elemental. Q1. Is a procedure in an intrinsic module that is specified to be elemental an elemental procedure? Q2. Can a type-bound procedure be elemental? Q3. Can a dummy procedure be specified to be elemental? Q4. Can a procedure pointer be specified to be elemental? ANSWER: A1. Procedures in intrinsic modules that are specified to be elemental are elemental. An edit is provided to correct the omission in Subclause 15.8. A2. A type-bound procedure that is bound to an elemental procedure is elemental. An edit is provided to correct the omission in Subclause 15.8. A3. A dummy procedure cannot be specified to be elemental. An edit is provided to make this restriction explicit. A4. A procedure pointer cannot be specified to be elemental. An edit is provided to make this restriction explicit. The edits provided are intended to make the impact on the existing standard small. More extensive changes are probably desirable, and could be made in a revision of the standard. In particular, the restrictions on dummy arguments and procedure pointers could be made constraints. EDITS to 18-007r1: [167:8] 10.2.4.4 Procedure pointer assignment, p3, Replace "elemental intrinsic procedure even if the pointer object is not elemental." with "elemental intrinsic procedure, even though the pointer object is not elemental." { Remove the suggestion that a procedure pointer might be elemental.} [325:11-12] 15.8.1 Elemental procedure declaration and interface, p1, Replace the sentence "An elemental procedure is ... an elemental subprogram." with "An elemental procedure is * an elemental intrinsic procedure (16.1), * a module procedure in an intrinsic module, if it is specified to be elemental, * a procedure that is defined by an elemental subprogram, or * a type-bound procedure that is bound to an elemental procedure." and insert a new paragraph following it: "A dummy procedure or procedure pointer shall not be specified to be ELEMENTAL." { Add missing items to the list in Subclause 15.8. Add a missing restriction to Subclause 15.8. } SUBMITTED BY: Robert Corbett HISTORY: 19-153 m218 Submitted 19-153r1 m218 Amended - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/012 TITLE: Internal procedure in a generic interface KEYWORDS: Internal procedure, Generic interface DEFECT TYPE: Clarification STATUS: Passed by J3 meeting QUESTION: In Fortran 2003, an internal subprogram was not allowed to define a specific procedure for a generic identifier: Fortran 2003 [285:14-15] C1207 (R1206) A shall have an explicit interface and shall refer to an accessible procedure pointer, external procedure, dummy procedure, or module procedure. Paper 08-178 proposed the new feature of permitting an internal procedure in this context, and this was included in Fortran 2008: [Fortran 2008 281:8] C1207 (R1206) A shall be a nonintrinsic procedure that has an explicit interface. However, this new feature was not mentioned in the Introduction of Fortran 2008, nor is it mentioned in Annex C.1 of Fortran 2018 (which lists Fortran 2008 features not originally mentioned in its Introduction). Should this be mentioned in Annex C.1? ANSWER: Yes, this new feature should be mentioned in Annex C.1. An edit is provided. EDIT: [528:22+] C.1 Fortran 2008 features not mentioned in its Introduction, p1, Insert an item at the end of the bullet list: "- An internal procedure name can appear in a in a generic interface block." SUBMITTED BY: Van Snyder HISTORY: 19-179 m219 Submitted - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/013 TITLE: TEAM_NUMBER arguments and intrinsic function are ambiguous KEYWORDS: NUM_IMAGES, IMAGE_INDEX, TEAM_NUMBER, teams DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Consider PROGRAM p n = NUM_IMAGES() n1 = MERGE(1,2,THIS_IMAGE()<2) n2 = MERGE(1,3,THIS_IMAGE()<3) FORM TEAM(n1,x) FORM TEAM(n2,y) IF (n1==1) THEN CHANGE TEAM (x) PRINT *,NUM_IMAGES(TEAM_NUMBER=1) !(A) PRINT *,NUM_IMAGES(TEAM_NUMBER=3) !(B) END TEAM END IF END PROGRAM According to 16.9.145 NUM_IMAGES, the TEAM_NUMBER argument "shall identify the initial team or a team whose parent is the same as that of the current team". However, at (A), there are two teams with team number 1 and the same parent, one created by the FORM TEAM with "n1", the other created by the FORM TEAM with "n2". At (B), there is only one team with team number 3 and the same parent as the current team, however, it is not a "sibling" team in that it was not created by the same FORM TEAM statement. Referring to the definition of the term "team number" at 3.145.4: "-1 which identifies the initial team, or positive integer that identifies a team within its parent team" which has the same flaw in that there could be multiple teams within the parent team that have that number. Q1. Was TEAM_NUMBER in NUM_IMAGES, and the "team number" definition, intended to limit the identification to teams created by corresponding FORM TEAM statement executions? Q2. The TEAM_NUMBER argument of IMAGE_INDEX suffers from similar wording. Was this also intended to be limited to "sibling" teams? ANSWER: Yes, this is the intention. Edits are provided. The edits use the terminology "corresponding" executions, as execution on more than one image can hardly be the "same" execution. The edits also use the term "sibling teams". As sibling teams are always created as a group, and really only have meaning when there are more than one, the plural form is probably most appropriate. EDITS: [20:27+] Terms and definitions: Insert after the definition of "parent team" "3.145.3+ sibling teams teams created by a single set of corresponding executions of the FORM TEAM statement (11.6.9)" [20:30] 3.145.4 team number, definition, change "within its parent team" -> "among its sibling teams" making the definition read "-1 which identifies the initial team, or a positive integer that identifies a team among its sibling teams (5.3.4) [same place] Append a (normative) note "Note 1 to entry: Teams are siblings when they were created by corresponding FORM TEAM statement executions." and index "sibling teams" here. {The Note should only be added if we don't make a separate team for sibling teams.} [36:23] 5.3.4 Program execution, para 2, final sentence Replace "Within its parent team," with "Among its sibling teams," making the whole sentence read "Among its sibling teams, each team is identified by its team_number; this is the integer value that was specified in the FORM TEAM statement." {This is just waffle, no need to index "sibling teams".} [131:18-19] In 9.6 Image selectors, p3 second sentence Replace "one of the teams that were formed by execution of the FORM TEAM statement for" with "a sibling team of" making the whole sentence read "If a TEAM_NUMBER= specifier appears in an image-selector and the current team is not the initial team, the value of scalar-int-expr shall be equal to the value of a team number for a sibling team of the current team, and the team of the image selector is that team; the object shall be an established coarray in an ancestor team of the current team, or an associating entity of the CHANGE TEAM construct." [204:35] 11.6.9 FORM TEAM statement, p1, change "creates new teams" to "creates a set of sibling teams" and index "sibling teams" here. This makes that whole paragraph read: "The FORM TEAM statement creates a set of sibling teams whose parent team is the current team." [380:12-13] In 16.9.97 IMAGE_INDEX, p3 TEAM_NUMBER Change "team whose parent is the same as that of the current team" to "sibling team of the current team" and index "sibling teams" here. making the whole argument read: "TEAM_NUMBER shall be an integer scalar. It shall identify the initial team or a sibling team of the current team." [401:24-25] 16.9.145 NUM_IMAGES, p3 Arguments, TEAM_NUMBER argument, Change "team whose parent is the same as that of the current team" to "sibling team of the current team" and index "sibling teams" here. This makes that whole argument read: "TEAM_NUMBER shall be an integer scalar. It shall identify the initial team or a sibling team of the current team." [421:9]16.9.189 TEAM_NUMBER([TEAM]), p5 Result Value, Change "within its parent team" to "among its sibling teams", and index "sibling teams" here. This makes that whole paragraph read: "The result has the value -1 if the specified team is the initial team; otherwise, the result value is equal to the positive integer that identifies the specified team among its sibling teams." SUBMITTED BY: Malcolm Cohen, Jon Steidel, and John Reid HISTORY: 19-190 m219 Submitted 19-190r1 m219 Merged with 19-178 - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/014 TITLE: Type of OPERATION arguments to the REDUCE intrinsic KEYWORDS: REDUCE, OPERATION, polymorphic, type DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Section 16.9.161 REDUCE p3 describes the arguments to the intrinsic subroutine CO_REDUCE. The description of the ARRAY argument states: "ARRAY shall be an array of any type." It describes the OPERATION argument as: "OPERATION shall be a pure function with exactly two arguments; each argument shall be a scalar, nonallocatable, nonpointer, nonoptional dummy data object with the same type and type parameters as ARRAY. If one argument has the ASYNCHRONUS, TARGET, or VALUE attribute, the other shall have that attribute. Its result shall be a non- polymorphic scalar and have the same type and type parameters as ARRAY. OPERATION should implement a mathematically associative operation. It need not be commutative." The function result of OPERATION cannot be polymorphic. The arguments to OPERATION must have the same type as its result, and thus cannot be polymorphic. However, ARRAY can be polymorphic. This means the dynamic type of ARRAY must be the same type as the arguments and result of OPERATION. This seems like an unfortunate requirement. Was it intended that the dynamic type of ARRAY be required to match the type and type parameters of the arguments of OPERATION? ANSWER: No, this requirement was not intended. Edits are provided to correct the problem. EDITS: [408:36] change "type and type parameters" to "declared type and type parameters" [408:39] change "type and type parameters" to "declared type and type parameters" so that the description of OPERATION reads: "shall be a pure function with exactly two arguments; each argument shall be a scalar, nonallocatable, nonpointer, nonoptional dummy data object with the same declared type and type parameters as ARRAY. If one argument has the ASYNCHRONOUS, TARGET, or VALUE attribute, the other shall have the attribute. Its result shall be a non-polymorphic scalar and have the same declared type and type parameters as ARRAY. OPERATION should implement a mathematically associative operation. It need not be commutative." [409:5] change "type and type parameters" to "declared type and type parameters" so that the first sentence of Result Characteristics reads: "The result is of the same declared type and type parameters as ARRAY." SUBMITTED BY: Jon Steidel HISTORY: 19-192 m219 Submitted 19-192r1 m219 Revised draft - Passed by J3 meeting ---------------------------------------------------------------------- ---------------------------------------------------------------------- NUMBER: F18/015 TITLE: Example in C.6.8 is wrong KEYWORDS: failed images DEFECT TYPE: Erratum STATUS: Passed by J3 meeting QUESTION: Q1. A: In the example in C.6.8, the assignments me[k] = failures(i) id[k] = 1 are made by image 1 and the assignments me = THIS_IMAGE () id = MERGE (1, 2, me<=images_used) are made by image k in unordered segments. Was this intended? B: In the example in C.6.8, the assignment me[k] = failures(i) is made by image 1 and me[k] is referenced on other images in the FORM TEAM statement in unordered segments. Was this intended? Q2. Suppose the program in C.6.8 is executed by 11 images, so 1 is intended to be a spare. If image 9 in the initial team fails immediately before it executes the first FORM TEAM statement, then image 10 in the initial team, which executes FORM TEAM with a team-number == 1 and NEW_INDEX == 10 (== me), will have specified a NEW_INDEX= value greater than the number of images in the new team. Should there be a test for this in the code? Q3. A: If a replacement image has failed, its image index will be the value of an element of the array failures, a replacement for it will be found, and the replacement will be placed in team 1. Was this intended? B: The value of images_used increases each time the setup loop is executed. However, the array failures will contain the image indices of all the failed images and allocate all of them fresh replacements. Was this intended? ANSWER: 1-A: No. An image control statement that provides segment ordering is needed. An edit is provided to correct this. 1-B: No. An edit is provided to correct this. 2: This is quite a low-probability event, so exiting with the error condition seems appropriate. An edit is provided. 3-A: No. An edit is provided to correct this. 3_B: No. It was intended to allocate replacements only for the newly failed images. Edits are provided to achieve this. The program would also be improved by declaring the integer k. EDITS to 18-007r1: All these edits are in C.6.8 "Example involving failed images". [544:2-3] Replace the statements "INTEGER, ALLOCATABLE :: failures (:) INTEGER :: images_used, i, images_spare, status" by the statements "INTEGER, ALLOCATABLE :: failures (:), old_failures (:), map (:) INTEGER :: images_used, failed, i, j, k, images_spare, status". [544:12+] After the statement "read_checkpoint = THIS_IMAGE () > images_used" add the statement "ALLOCATE ( old_failures(0), map(images_used+1:NUM_IMAGES()) )". [544:13] Replace "setup" with "outer". [544:15+] After the statement "id = MERGE (1, 2, me<=images_used)" add the statements "SYNC ALL (STAT = status ) IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer". [544:24-] Before the statement "DO i = 1, SIZE (failures)" add the statement "j = 1". [544:24+] After the statement "DO i = 1, SIZE (failures)" add the statements "IF (failures(i) > images_used) exit ! Note that the values returned ! by FAILED_IMAGES increase monotonically. failed = failures(i) IF (j <= SIZE (old_failures)) THEN IF (failed == old_failures(j) ) THEN j = j+1 CYCLE END IF END IF IF ( failed > NUM_IMAGES()-images_spare ) failed = map(failed)". [544:29-31] Change the statements " me [k] = failures(i) id [k] = 1 END DO" to " me [k] = failed id [k] = 1 map(k) = failed END DO old_failures = failures". [544:38-] Before the FORM TEAM statement add the statements "SYNC ALL (STAT = status) IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer". [544:38+] After the FORM TEAM statement add the statement "IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer". [545:15-16] Replace "setup" with "outer", twice. ............................ These edits make the whole example become: PROGRAM possibly_recoverable_simulation USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY:TEAM_TYPE, STAT_FAILED_IMAGE IMPLICIT NONE INTEGER, ALLOCATABLE :: failures (:), old_failures(:), map(:) INTEGER :: images_used, failed, i, j, k, images_spare, status INTEGER :: id [*], me [*] TYPE (TEAM_TYPE) :: simulation_team LOGICAL :: read_checkpoint, done [*] ! Keep 1% spare images if we have a lot, just 1 if 10-199 images, ! 0 if <10. images_spare = MAX(INT(0.01*NUM_IMAGES()),0,MIN(NUM_IMAGES()-10,1)) images_used = NUM_IMAGES () - images_spare read_checkpoint = THIS_IMAGE () > images_used ALLOCATE ( old_failures(0), map(images_used+1:NUM_IMAGES()) ) outer : DO me = THIS_IMAGE () id = MERGE (1, 2, me<=images_used) SYNC ALL (STAT = status) IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer ! ! Set up spare images as replacement for failed ones. ! IF (IMAGE_STATUS (1) == STAT_FAILED_IMAGE) & ERROR STOP "cannot recover" IF (me == 1) THEN failures = FAILED_IMAGES () k = images_used j = 1 DO i = 1, SIZE (failures) IF (failures(i) > images_used) EXIT ! Note that the values ! returned by FAILED_IMAGES increase monotonically. failed = failures(i) IF (j <= SIZE (old_failures)) THEN IF (failed == old_failures(j) ) THEN j = j+1 CYCLE END IF END IF IF( failed > NUM_IMAGES()-images_spare ) failed = map(failed) DO k = k+1, NUM_IMAGES () IF (IMAGE_STATUS (k) == 0) EXIT END DO IF (k > NUM_IMAGES ()) ERROR STOP "cannot recover" me [k] = failed id [k] = 1 map(k) = failed END DO old_failures = failures images_used = k END IF SYNC ALL (STAT = status) IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer ! ! Set up a simulation team of constant size. ! Team 2 is the set of spares, so does not participate in the ! simulation. ! FORM TEAM (id, simulation_team, NEW_INDEX=me, STAT=status) IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) EXIT outer simulation : CHANGE TEAM (simulation_team, STAT=status) IF (status == STAT_FAILED_IMAGE) EXIT simulation IF (TEAM_NUMBER () == 1) THEN iter : DO CALL simulation_procedure (read_checkpoint, status, done) ! The simulation_procedure: ! - sets up and performs some part of the simulation; ! - resets to the last checkpoint if requested; ! - sets status from its internal synchronizations; ! - sets done to .TRUE. when the simulation has completed. IF (status == STAT_FAILED_IMAGE) THEN read_checkpoint = .TRUE. EXIT simulation ELSE IF (done) EXIT iter END IF read_checkpoint = .FALSE. END DO iter END IF END TEAM (STAT=status) simulation SYNC ALL (STAT=status) IF (THIS_IMAGE () > images_used) done = done[1] IF (done) EXIT outer END DO outer IF (status/=0 .AND. status/=STAT_FAILED_IMAGE) & PRINT *,'Unexpected failure',status END PROGRAM possibly_recoverable_simulation ---------------------------------------------------------------------- ===END===