X3J3/94-009 r2 11-Jul-94 TECHNICAL PROPOSALS This document contains technical proposals for revisions to Fortran. This is an internal working document of X3J3 and is regularly revised. These technical proposals are all in response to requirements defined by WG5. It requires a vote by X3J3 to add a proposal to this document or to change the status of one of the proposals. There are currently three possible status values for a proposal. D - Draft This status indicates that the general concept of a proposal has been adopted, but that the proposal needs further work. A - Approved This status indicates that a proposal has been approved and is ready for incorporation into the draft standard (document 007). I - Incorporated This status indicates that a proposal has been incorporated into the draft standard. No proposals yet have this status. The target date for a proposal can be either 95, 2k, or unspecified. List of Proposals Number Status Target date Title 001 A 95 Changes to the MAXLOC and MINLOC intrinsics 002 A 95 NAMELIST comments 003 A 95 Minimal field widths 004 A 95 FORALL 005 A 95 PURE procedures 005a A 95 Rationale for FORALL and PURE (belongs as part of 004 and 005) 006 A 95 Object Initialization 007 A 95 Language evolution 008 A 95 Conflicts with IEEE 754/854 009 A 95 CPU time 010 A 95 Nested WHERE 011 A 95 Specification Functions 012 D U Enable ------------------------------------------------------------------------------ Number: 001 Title: Changes to the MAXLOC and MINLOC Intrinsics (B9 Item A5) Status: Approved Target date: 95 Last revision: Feb 94 X3J3 reference: 94-037 Technical Description: HPF modified the MAXLOC and MINLOC intrinsic functions to include an optional argument, DIM, which specifies the dimension along which the search is to be performed. This includes this functionality in Fortran 9x. Discussion: The HPF proposal creates an unfortunate incompatibility with Fortran 90. The incompatibility is a result of the new argument being inserted between the original first and second arguments. This was probably done for consistency with the argument location in the MAXVAL and MINVAL intrinsics. To avoid this incompatibility with Fortran 90, these functions are specified so that the two optional arguments may occur in either order. This places the burden on the processor to determine the order of the arguments (if the second argument is a scalar of type integer it is the DIM argument and if it is of type logical and conformable with the ARRAY argument it is the MASK argument). For consistency, this allowance for either order of the two optional arguments is extended to MAXVAL, MINVAL, PRODUCT, and SUM. As part of this proposal, a Fortran 90 compatibility section has been added. It does not replace the Fortran 77 compatibility section and it assumes that Fortran 9x will be upward compatible from Fortran 90. Both of these issues are yet to be decided and if the text below is accepted, it may require revision when these decisions are made. Detailed Edits: [3/3+]: Add the following section: 1.4.1 Fortran 90 Compatibility Except as noted in this section, this International Standard is an upward compatible extension to the preceding Fortran International Standard, ISO/IEC 1539:1991, informally known as Fortran 90, and a standard- conforming processor for this International Standard is a standard-conforming processor for Fortran 90. Any standard-conforming Fortran 90 program remains standard-conforming under this International Standard. The following Fortran 90 features have different interpretations in this International Standard: (1) The interfaces to the MAXLOC, MAXVAL, MINLOC, MINVAL, PRODUCT, and SUM intrinsics have been extended by this standard. This may conflict with a program that has supplied a generic interface to these intrinsics. [3/4]: Change "1.4.1" to "1.4.2". [219/6]: Add "DIM ," before "MASK" and add "or MAXLOC (ARRAY, MASK, DIM)" to the end of the line. [219/7]: Add "DIM ," before "MASK". [219/8]: Add "along dimension DIM" after "ARRAY". [219/12+]: Add the following description of the DIM argument: DIM (optional) must be scalar and of type integer with a value in the range 1 <= DIM <= n, where n is the rank of ARRAY. The corresponding actual argument must not be an optional dummy argument. [219/14]: Change "; it" to ". If DIM is absent the result". [219/15]: Before "." add "; otherwise, the result is an array of rank n-1 and shape (d(1), ..., d(DIM-1), d(DIM+1), ..., d(n)), where (d(1), ..., d(n)) is the shape of ARRAY". [219/17]: Change "If MASK is absent, the result" to "The result of MAXLOC (ARRAY)". [219/24]: Change "If MASK is present, the result" to "The result of MAXLOC (ARRAY, MASK = MASK)". [219/31+]: Add the following case to the description of the result value: Case (iii): If ARRAY has rank one, MAXLOC (ARRAY, DIM = DIM [, MASK = MASK]) has a value equal to that of MAXLOC (ARRAY [, MASK = MASK]). Otherwise, the value of element (s(1), ..., s(DIM-1), s(DIM+1), ..., s(n)) of MAXLOC (ARRAY, DIM = DIM [, MASK = MASK]) is equal to MAXLOC (ARRAY (s(1), s(2), ..., s(DIM-1), :, s(DIM+1), ..., s(n)) [, MASK = MASK (s(1), s(2), ..., s(DIM-1), :, s(DIM+1), ..., s(n)) ] ). [219/36+]: Add the following case to the examples: Case (iii): The value of MAXLOC ((/ 5, -9, 3 /), DIM=1) is 1. If B has the value | 1 3 -9 | | 2 2 6 |, MAXLOC (B, DIM=1) is [ 2 1 2 ] and MAXLOC (B, DIM=2) is [ 2 3 ]. Note that this is true even if B has a declared lower bound other than 1. [219/37]: Add "or MAXVAL (ARRAY, MASK, DIM)" to the end of the line. [220/22,24]: Change "DIM" to "DIM = DIM". [220/22,24]: Change "MASK" to "MASK = MASK". [221/23]: Add "DIM ," before "MASK" and add "or MINLOC (ARRAY, MASK, DIM)" to the end of the line. [221/24]: Add "DIM ," before "MASK". [221/25]: Add "along dimension DIM" after "ARRAY". [221/29+]: Add the following description of the DIM argument: DIM (optional) must be scalar and of type integer with a value in the range 1 <= DIM <= n, where n is the rank of ARRAY. The corresponding actual argument must not be an optional dummy argument. [221/31]: Change "; it" to ". If DIM is absent the result". [221/32]: Before "." add "; otherwise, the result is an array of rank n-1 and shape (d(1), ..., d(DIM-1), d(DIM+1), ..., d(n)), where (d(1), ..., d(n)) is the shape of ARRAY". [221/34]: Change "If MASK is absent, the result" to "The result of MAXLOC (ARRAY)". [222/6]: Change "If MASK is present, the result" to "The result of MAXLOC (ARRAY, MASK = MASK)". [222/13+]: Add the following case to the description of the result value: Case (iii): If ARRAY has rank one, MINLOC (ARRAY, DIM = DIM [, MASK = MASK]) has a value equal to that of MINLOC (ARRAY [, MASK = MASK]). Otherwise, the value of element (s(1), ..., s(DIM-1), s(DIM+1), ..., s(n)) of MINLOC (ARRAY, DIM = DIM [, MASK]) is equal to MINLOC (ARRAY (s(1), s(2), ..., s(DIM-1), :, s(DIM+1), ..., s(n)) [, MASK = MASK (s(1), s(2), ..., s(DIM-1), :, s(DIM+1), ..., s9n)) ] ). [222/18+]: Add the following case to the examples: Case (iii): The value of MINLOC ((/ 5, -9, 3 /), DIM=1) is 2. If B has the value | 1 3 -9 | | 2 2 6 |, MINLOC (B, DIM=1) is [ 1 2 1 ] and MINLOC (B, DIM=2) is [ 3 1 ]. Note that this is true even if B has a declared lower bound other than 1. [222/19]: Add "or MINVAL (ARRAY, MASK, DIM)" to the end of the line. [223/1,3]: Change "DIM" to "DIM = DIM". [223/1,3]: Change "MASK" to "MASK = MASK". [226/22]: Add "or PRODUCT (ARRAY, MASK, DIM)" to the end of the line. [227/5,7]: Change "DIM" to "DIM = DIM". [227/5,7]: Change "MASK" to "MASK = MASK". [235/5]: Add "or SUM (ARRAY, MASK, DIM)" to the end of the line. [235/27,29]: Change "DIM" to "DIM = DIM". [235/27,29]: Change "MASK" to "MASK = MASK". [Rationale]: Add the following sections to the new rationale: R13.13.65 MAXLOC Fortran 90 specified the MAXLOC intrinsic with only the ARRAY and MASK arguments. HPF added the DIM argument between the original two arguments for consistency with the MAXVAL intrinsic. This creates an incompatibility with Fortran 90 unless MAXLOC is specified as a generic interface with two specific interfaces: the first matching Fortran 90 and the second adding a non-optional DIM argument as the second argument. At X3J3 meeting 127, it was decided that this Standard should allow the DIM and MASK arguments to be specified in either order. For consistency, this provision for DIM and MASK to be specified in either order was extended to the other intrinsics, MAXVAL, MINVAL, PRODUCT, and SUM, which have the same arguments. R13.13.66 MAXVAL MAXVAL was extended to allow the DIM and MASK arguments to be specified in either order as part of the extensions to MAXLOC and MINLOC (R13.13.65,R13.13.70). R13.13.70 MINLOC Fortran 90 specified the MINLOC intrinsic with only the ARRAY and MASK arguments. HPF added the DIM argument between the original two arguments for consistency with the MINVAL intrinsic. This creates an incompatibility with Fortran 90 unless MINLOC is specified as a generic interface with two specific interfaces: the first matching Fortran 90 and the second adding a non-optional DIM argument as the second argument. At X3J3 meeting 127, it was decided that this Standard should allow the DIM and MASK arguments to be specified in either order. For consistency, this provision for DIM and MASK to be specified in either order was extended to the other intrinsics, MAXVAL, MINVAL, PRODUCT, and SUM, which have the same arguments. R13.13.71 MINVAL MINVAL was extended to allow the DIM and MASK arguments to be specified in either order as part of the extensions to MAXLOC and MINLOC (R13.13.65,R13.13.70). R13.13.81 PRODUCT PRODUCT was extended to allow the DIM and MASK arguments to be specified in either order as part of the extensions to MAXLOC and MINLOC (R13.13.65,R13.13.70). R13.13.103 SUM SUM was extended to allow the DIM and MASK arguments to be specified in either order as part of the extensions to MAXLOC and MINLOC (R13.13.65,R13.13.70). History: X3J3/93-275r1 (meeting 127) X3J3/94-037 (meeting 128) ------------------------------------------------------------------------------ Number: 002 Title: WG5 B9, B4.3: NAMELIST comments Status: Approved Target date: 95 Last revision: Feb 94 X3J3 reference: 94-021r1 Technical Description: Provide a mechanism to allow comments in namelist input records. Discussion: The straw votes taken at meeting 127 indicated a preference for allowing comments, of the "to end of line" variety. Comments are allowed before and after "name-value" subsequences as well as before the initial "&" defining a particular namelist group name. Detailed Edits: On page 151, section 10.9.1, change item 1 to read: 1) Optional blanks and namelist comments, On page 152, section 10.9.1.2, add the following paragraph after the 4th paragraph: A namelist comment may appear after any value separator except a slash. A namelist comment is also permitted to start in the first position of an input record except within a character literal constant. On page 154, renumber section 10.9.1.6 to be 10.9.1.7, and add a new 10.9.1.6: 10.9.1.6 Namelist Comments Except within a character literal constant, a "!" character after a value separator or in the first non-blank position of a namelist input record initiates a comment. The comment extends to the end of the current input record. The comment is ignored. A slash within the namelist comment does not terminate execution of the namelist input statement. History: WG5/N901, X3J3/93-204r4, item 4 in X3J3 SD004, WG5/N840, X3J3/93-272, X3J3/94-021 ---------------------------------------------------------------- Number: 003 Title: WG5 B9 item: B4.1. Minimal Field Widths Status: Approved Target date: 95 Last revision: Feb 94 X3J3 reference: 94-022r1 Technical Description: Allow a field width of zero for I, B, O, Z, and F edit descriptors (in formatted output) to request that the processor select the smallest field width which will avoid "*****"s (field overflow). For the I, B, O, and Z edit descriptors, no leading blanks are produced, and a leading "+" is never written. When an "m" (minimal printable digit count) is specified, the appropriate number of leading zeros is still produced, i.e., the processor will chose a width >= m. For the F edit descriptor, no leading blanks are produced, and a leading "+" is never written. The optional leading zero just before the decimal point is not produced unless d was specified to be zero. A field width of zero is not permitted for other edit descriptors. Discussion: The straw votes taken at meeting 127 indicated a preference for this approach, rather than new edit descriptors (EX/LT, item 10 in SD004) to toggle the desired behavior. The processor, when it sees a zero field width specified, choses the smallest possible value for the field width, such that, if the user had specified that particular value, the processor would have printed "useful" data (not "*"s), and chosing any smaller field width would have resulted in the processor printing "*"s (field width overflow). This feature provides the ability to reduce the number of characters in an output file. Also, the user can maximize how many values can be printed on a single line and easily viewed on a terminal, while avoiding overflow "****"s in the output fields. Detailed Edits: On page 136, change the 3rd constraint to be: Constraint: e must be positive. Add this constraint after the 3rd constraint on page 136: Constraint: w must be zero or positive for the I, B, O, Z, and F edit descriptors. w must be positive for all other edit descriptors. In section 10.5.1.1, in the first paragraph, insert the following before the "." ending the first sentence [139:34]: , except when w is zero. On input, w must not be zero. When w is zero, the processor selects the field width In section 10.5.1.1, add the following to the end of the 4th paragraph [139:46]: When w is zero, the processor choses a positive field width such that no leading blanks are produced, nor a leading plus, and the characters produced do not exceed the processor selected field width. In section 10.5.1.1, add the following to the end of the 5th paragraph [140:4]: When w is zero, the processor choses a positive field width such that no leading blanks are produced, and the characters produced do not exceed the processor selected field width. In section 10.5.1.1, in the 6th paragraph, change the phrase "value of w" to be [140:8]: value of w, except when w is zero In section 10.5.1.1, add the following to the end of the 6th paragraph [140:9]: When w is zero, the processor choses a positive field width such that no leading blanks are produced, nor a leading plus, and the characters produced do not exceed the processor selected field width. When m and w are both zero, and the value of the internal datum is zero, no characters are produced, regardless of the sign control in effect. In section 10.5.1.2.1, in the 1st paragraph, insert the following before the 1st ",": (except when w is zero) In section 10.5.1.2.1, in the 1st paragraph, insert the following after the last sentence: When w is zero, the processor selects the field width. In section 10.5.1.2.1, in the last paragraph, insert the following after the last sentence [140:36]: When w is zero, the processor choses a positive field width such that no leading blanks are produced, nor a leading plus, and the characters produced do not exceed the processor selected field width. End of EDITS History: WG5/N901, X3J3/93-204r4, items 9 and 10 in X3J3 SD004, X3J3/93-273, X3J3/94-022 ------------------------------------------------------------------------------ Number: 004 Title: FORALL Status: Approved Target date: 95 Last revision: May 94 X3J3 reference: 94-150r1 X3J3 94-150R1 TO: X3J3 FROM: Dick Hendrickson SUBJECT: FORALL proposal REFERENCE: 94-013, 94-054, 94-096, meeting 128 scribe notes, B9 resolution items A2 and A3 DATE: May 4, 1994 This is the FORALL proposal modified by the straw votes and discussion at meetings 128 and 129. The Rationale is in paper 94-097 which was passed at meeting 128 and covers both the FORALL and PURE procedure proposal. I did not do anything to resolve the copyright isues. As a result, I believe this text is still copyright by Rice University and copied here with their permission. It is unclear to me how to proceed with this. We can contact Rice and see if they will give us permission to include some of their text with- out acknowledgement. We can contact ANSI/ISO/??? and see if we can include a copyright notice in the text of the standard. We can rewrite the text to remove the dependence on Rice's material. It is also possible that using small parts of the text, and modifing it as much as I already have, re- moves any question of copyright "infringement". I believe that these issues are basically "editori- al" and that we should decide what we want to do on a technical basis and then get the words right. Leaving the words close to the HPF words for now allows us to see what we've done to their tech- nical content . As an unresolved editorial issue /edit should consider "merging" the text for WHERE and FORALL with the text in Chapter 8 describing blocks. /edit should probably also consider "merg- ing" the definitions and constraints for constructs which can have names. FORALL proposal. [add to 14.1.3 Statement entities after page 245, line 22. We need to define the index-name variables as statement entities to the forall statement or construct. This was not in the original HPF draft nor in the original paper. The intent is to say that the index name is purely local and its use does not affect the value of other variables with the same name in the rest of the program. This is the same as the implied Do index in an array constructor. Note that there are several other edits to this section from interpretations.] The name of a variable that appears as an index-name in a FORALL statement or FORALL con- struct has a scope of the statement or construct. It has the type and type parameters that it would have if it were the name of a variable in the scoping unit that includes the FORALL and this type must be INTEGER. Change the section name for 14.1.3, [245:15] to "Statement and construct entities". In [245:23-24] change the reference to "statement entities" to "statement or construct entities" twice. In 14.1.2, [241:23] change the reference to "statement entities" to "statement or construct entities". [Extend rule R215 for executable-construct to include the forall-construct and R216 to include the forall-stmt:] Page 8, add to R215 executable construct: or forall-construct Page 9, add to R216 action-stmt or forall-stmt [Add FORALL construct to the list of things that may be branch targets. This allows branching to a FORALL, but not to an END FORALL] Page 107, line 5: Add forall-construct-stmt to the list of possible branch targets. [Add at the end of the first paragraph in section 7.5:] Execution of a FORALL statement or FORALL construct controls the assignment to elements of arrays by using a set of index variables and a mask expression. [Add a new section to chapter 7 at the end 7.5.3 [page 94] after the WHERE assignment section, number the BNF rules continuously:] 7.5.4 Element array assignment - FORALL Element array assignment is used to mask the evaluation of expressions and assignment of values in assignment statements with selection by sets of index values and an optional mask expression. 7.5.4.1 The FORALL Construct The FORALL construct allows multiple assignments, masked array (WHERE) assignments, and nested FORALL statements and constructs to be controlled by a single forall-triplet-spec-list and scalar-mask. General Form of the FORALL Construct R781 forall-construct is [forall-construct-name:] FORALL forall-header forall-body-stmt [ forall-body-stmt ...] END FORALL [forall-construct-name] R782 forall-header is (forall-triplet-spec-list [,scalar- mask-expr]) R783 forall-triplet-spec is index-name = subscript:subscript[:stride] R784 forall-body-stmt is forall-assignment-stmt or where-stmt or where-construct or forall-stmt or forall-construct R785 forall-assignment-stmt is assignment-stmt or pointer-assignment-stmt Constraint: Any procedure referenced in the scalar-mask-expr of a forall-header, including one referenced by a defined operation, must be a pure procedure (12.xxx). Constraint: The scalar-mask-expr must be scalar and of type logical. {footnote 1} begin footnote 1 The scalar-mask-expr may depend on the index-name values as well as on the values of data items. This allows a wide range of masking operations. end footnote Constraint: A forall-body-stmt must not define any of the index-names. Constraint: The index-name must be a scalar integer variable. Constraint: A subscript or stride in a forall-triplet-spec must not contain a reference to any index-name in the forall-triplet-spec-list in which it appears. Constraint: If the forall-construct has a forall-construct-name the END FORALL statement must have the same forall-construct-name. If the END FORALL statement has a forall-construct-name. the forall-construct must have the same construct- name. Constraint: Any procedure referenced in a forall-body-stmt, including one referenced by a defined operation or assignment, must be a pure procedure. Constraint: A forall-body-stmt must not be a branch target. To determine the set of values that each index-name in the forall-header takes let: m1 be value of the first subscript ("lower bound"); m2 be value of the second subscript ("upper bound"); m3 be the stride; and max be INT((m2 - m1 + m3)/m3) If stride is missing, it is as if it were present with the value 1. Stride must not have the value 0. The set of values is m1 + (k-1) * m3, k = 1, 2, ..., max. If max <= 0 for some index-name, the statements within the forall-body are not executed. Each forall-assignment-stmt contained in a forall-construct assigns a value to a variable specified by the values of the index-name variables. A program must not assign multiple values to a variable by a single forall-assignment-stmt in a forall-construct. A program may, however, assign to the same variable in different forall-assignment-stmts in a forall-construct. For the purposes of this restriction, any assignment (including array assignment or assignment to a variable of derived type) to a data object is considered to assign to all subobjects contained in that object. {footnote 2} begin footnote 2 A syntactic consequence of the semantic rule that no two execution instances of a forall-assignment-stmt may assign to the same data object is that each of the index-name variables must appear on the left-hand side of a forall-assignment-stmt. The converse is not true (i.e., using all of the index-name variables on the left-hand side does not guarantee there will be no interference). Because the condition is not sufficient, it does not appear as a constraint. This restriction allows cases such as FORALL ( I = 1:10 ) A(INDEX(I)) = B(I) END FORALL if and only if INDEX(1:10) contains no repeated values. Note that it restricts FORALL behavior, but not syntax. Syntactic restric- tions to enforce this behavior would be either incomplete (i.e., allow undefined behavior) or exclude useful programs such as the above example. Statements can use the results of computations in lexically earlier statements, including computations done for other index-name val- ues. However, an assignment never uses a value assigned in the same statement by another index-name value combination. end footnote The scope of an index-name is the forall-construct itself(14.1.3). {footnote 3} footnote 3 The index variables inherit their type and type parameters from the host scope, but their use does not modify any host variables of the same name. Given a sequence such as: INTEGER X REAL XX REAL A(5,4) X=-1 J=10 FORALL(X=1:5, J=1:4) A(X,J) = J END FORALL After execution of the FORALL the variables X and J have the values -1 and 10 and the columns of A have the values 1, 2, 3, and 4. It would be a syntax error to use XX as a FORALL index. end footnote 7.5.4.2 Interpretation of the FORALL Construct Execution of a FORALL construct consists of the following steps: Evaluation, in any order, of the subscript and stride expressions in the forall-trip- let-spec-list. The set of combinations of index-name values is then the Cartesian product of the sets defined by these triplets. Evaluation of the scalar-mask-expr for all combinations of index-name values. If the scalar mask expression is omitted, it is as if it were present with the value true. The mask elements may be evaluated in any order. The set of active combinations of index-name values is the subset of the combinations for which the scalar-mask- expr evaluates to .TRUE.. {footnote 4} Footnote 4 Right-hand sides and expressions on the left hand side of a forall- assignment-stmt are defined as evaluated only for combinations of index-names for which the scalar-mask-expr evaluates to .TRUE. This has implications when the computation might create an error condi- tion. For example, FORALL (I=1:N, Y(I).NE.0.0) X(I) = 1.0 / Y(I) END FORALL does not cause a division by zero nor does it assign any values to elements of X that correspond to zero elements of Y. end footnote Execution of the forall-body-stmts in the order they appear. Each statement is ex- ecuted completely (that is, for all active combinations of index-name values) ac- cording to the following interpretation: forall-assignment-stmts evaluate the expr and all expressions within vari- able (in the case of assignment-stmt) or target and all expressions within pointer-object (in the case of pointer-assignment-stmt) of the forall-assign- ment-stmt for all active combinations of index-name values. These evalua- tions may be done in any order. The expr values are then assigned to the corresponding variable (in the case of assignment-stmt) or the target values are associated with the corresponding pointer-object (in the case of pointer- assignment-stmt). The assignment or association operations may also be performed in any order. where-stmts and where-constructs evaluate their mask-expr for all active combinations of values of index-names. All elements of all masks may be evaluated in any order. The WHERE statements' assignment (or assign- ments within the WHERE block of the construct) are then executed in order using the above interpretation of array assignments within the FORALL, but the only array elements assigned are those selected by both the active index-name values and the WHERE mask. Finally, the assignments in the ELSEWHERE block are executed if that block is present. The assignments here are also treated as array assignments, but elements are only assigned if they are selected by both the active combinations and by the negation of the WHERE mask. forall-stmts and forall-constructs first evaluate the subscript and stride ex- pressions in the forall-triplet-spec-list for all active combinations of the out- er FORALL constructs. The set of valid combinations of index-names for the inner FORALL is then the union of the sets defined by these bounds and strides for each active combination of the outer index-names, the outer in- dex-names being included in the combinations generated for the inner FORALL. The scalar-mask-expression is then evaluated for all valid com- binations of the inner FORALL's index-names to produce the set of active combinations. If there is no scalar-mask-expression, it is as if it were present with the value true. Each statement in the inner FORALL is then executed for each active combination (of the inner FORALL), recursively following the interpretations given in this section. {footnote 5} foot note 5 In general, any expression in a FORALL is evaluated only for valid combinations of all surrounding index-names for which all the sca- lar-mask-exprs are true. Nested FORALL bounds and strides can depend on outer FORALL index- names. They cannot redefine those names, even temporarily. end footnote 7.5.4.3 General form of the element array assignment statement An element array assignment statement is a FORALL statement. R786 forall-stmt is FORALL forall-header forall-assignment-stmt A FORALL statement is equivalent to a FORALL construct containing a single forall-body-stmt that is a forall-assignment. {footnote 6} The scope of an index-name is the FORALL statement itself(14.1.3). FORALL statements cannot have construct names. footnote 6 A FORALL construct means roughly the same thing as does replicating the FORALL header in front of each array assignment statement in the block, except that any expressions in the FORALL header are evalu- ated only once, rather than being re-evaluated before each of the statements in the body. The exceptions to this rule are nested FORALL statements and WHERE statements, which introduce syntactic and functional complications into the copying. end footnote 7.5.4.4 FORALL Examples Example 1: FORALL (J=1:M, K=1:N) X(K,J) = Y(J,K) FORALL (K=1:N) X(K,1:M) = Y(1:M,K) These statements both copy columns 1 through N of array Y into rows 1 through N of array X. They are equivalent to X(1:N,1:M) = TRANSPOSE(Y(1:M,1:N)) Example 2: FORALL (I=1:N, J=1:N) X(I,J) = 1.0 / REAL(I+J-1) This FORALL sets array element X(I,J) to the value 1/(I+J-1) for values of I and J between 1 and N. Example 3: FORALL (I=1:N, J=1:N, Y(I,J).NE.0 .AND. I .NE. J) & X(I,J) = 1.0/Y(I,J) This statement takes the reciprocal of each non-zero non-diagonal element of array Y(1:N,1:N) and assigns it to the corresponding element of array X. Elements of Y that are zero or on the diagonal do not have their reciprocal taken, and no assignments are made to the corresponding elements of X. Example 4: FORALL (I=2:N-1) X(I) = (X(I-1) + 2*X(I) + X(I+1))/4 Has the same effect as the statement X(2:N-1) = (X(1:N-2) + 2*X(2:N-1) + X(3:N+1))/4 Example 5: FORALL (I=1:N) A(I,I) = X(I) This FORALL statement sets the elements of the main diagonal of matrix A to the elements of vec- tor X. Example 6: FORALL (K=1:5) J(K) = SUM(J(1:K)) This FORALL statement computes five partial sums of subarrays of J. (SUM is allowed in a FORALL because intrinsic functions are pure; see Section 12.xxx.) If before the FORALL J =(/ 1, 2, 3, 4, 5/) then after the FORALL J =(/1, 3, 6, 10, 15/) Example 7: FORALL ( I=2:N-1, J=2:N-1 ) A(I,J) = A(I,J-1) + A(I,J+1) + A(I-1,J) + A(I+1,J) B(I,J) = 1.0/A(I,J) END FORALL The assignment to array B uses the values of array A computed in the first statement, not the values before the FORALL began execution. Example 8: FORALL ( I=1:N-1 ) FORALL ( J=I+1:N ) A(I,J) = A(J,I) END FORALL This FORALL construct assigns the transpose of the lower triangle of array A (i.e., the section be- low the main diagonal) to the upper triangle of A. For example, if N=3 and A originally contained the values 0 3 6 1 4 7 2 5 8 then after the FORALL it would contain 0 1 2 1 4 5 2 5 8 This could also be achieved with a single FORALL statement FORALL ( I = 1:N-1, J=1:N, J >I) A(I,J) = A(J,I) Example 9: INTEGER A(5,4), B(5,4) FORALL ( I=1:5 ) WHERE ( A(I,:) .EQ. 0 ) A(I,:) = I B(I,:) = I / A(I,:) END FORALL This FORALL construct, when executed with the input array A = 0 0 0 0 1 1 1 0 2 2 0 2 1 0 2 3 0 0 0 0 will produce as results A = 1 1 1 1 1 1 1 2 2 2 3 2 1 4 2 3 5 5 5 5 and B = 1 1 1 1 2 2 2 1 1 1 1 1 4 1 2 1 1 1 1 1 Note that assignments to A in the WHERE block may affect computations in the ELSEWHERE block such as to B(1,1). ------------------------------------------------------------------------------ Number: 005 Title: Pure procedures Status: Approved Target date: 95 Last revision: May 94 X3J3 reference: 94-149r2 as amended (amended text not yet available) X3J3 94-149R2 TO: X3J3 FROM: Dick Hendrickson SUBJECT: Pure procedures REFERENCES: 94-013, 94-054, 94-098, meeting 128 scribe notes B9 resolution item A4 DATE: May 4, 1994 This is a modified version of 94-098 based on the discussions and scribe notes from meetings 128 and 129. The Rationale is in paper 94-097 which was passed at meeting 128 and covers both the FORALL and PURE procedure proposal. I did not do anything to resolve the copyright isues. As a result, I believe this text is still copyright by Rice University and copied here with their permission. It is unclear to me how to proceed with this. We can contact Rice and see if they will give us permission to include some of their text with- out acknowledgement. We can contact ANSI/ISO/??? and see if we can include a copyright notice in the text of the standard. We can rewrite the text to remove the dependence on Rice's material. It is also possible that using small parts of the text, and modifing it as much as I already have, re- moves any question of copyright "infringement". I believe that these issues are basically "editori- al" and that we should decide what we want to do on a technical basis and then get the words right. Leaving the words close to the HPF words for now allows us to see what we've done to their tech- nical content . PURE proposal [Add a new section to chapter 12 at an /editorially appropriate place.] 12.xxxx Pure Procedures 12.xxxx.1 Pure Procedure Declaration and Interface A pure procedure is a procedure that has no side effects; it does not change the status of any vari- ables known outside of its scope, except possibly for dummy arguments to a pure subroutine, and it does not perform any input or output to an external unit. Intrinsic functions are always pure. Intrinsic subroutines are pure if they are elemental (e.g., MVBITS) but not otherwise. No explicit declaration of this fact is permitted for intrinsic proce- dures. A statement function is pure if and only if all functions that it references are pure . The following constraints apply to pure functions or subroutines. Constraint: The specification-part of a pure function must specify that all dummy argu- ments have INTENT (IN) except procedure arguments and arguments with the POINTER attribute. Constraint: The specification-part of a pure subroutine must specify the intents of all dum- my arguments except procedure arguments, alternate return specifiers, and ar- guments with the POINTER attribute. Constraint: A local variable declared in the specification-part or internal-subprogram-part of a pure procedure must not have the SAVE attribute. {footnote 1} footnote 1 Variable initialization in a type-declaration-stmt or a data-stmt implies the SAVE attribute; therefore, such initialization is also disallowed. end footnote Constraint: If a procedure is used in a context that requires it to be pure, then its interface must be explicit in the scope of that use and that interface must specify the PURE keyword. {footnote 2} footnote 2 It is expected that most mathematical library procedures will be pure, this form of restriction allows these procedures to be used in contexts where they are not required to be pure without the need for an interface-block. end footnote Constraint: All internal procedures in a pure procedure must be pure. Constraint: In a pure procedure any variable which is in common or accessed by host or use association; is a dummy argument to a pure function, is a dummy argument with INTENT (IN) to a pure subroutine, or an object that is storage associated with any such variable or subobject thereof, must not be used in the following con- texts As the assignment variable of an assignment-stmt; As a DO variable or implied DO variable; As an input-item in a read-stmt from an internal file; As an internal-file-unit in a write-stmt; As an IOSTAT= or SIZE= specifier in an input or output statement with an internal file; In an assign-stmt; As the pointer-object of a pointer-assignment-stmt; As the target of a pointer-assignment-stmt; As the expr of an assignment-stmt whose assignment variable is of a de- rived type or is a pointer to a derived type, if the derived type has a point- er component at any level of component selection; As an allocate-object or stat-variable in an allocate-stmt or deallocate- stmt, or as a pointer-object in a nullify-stmt; or As an actual argument associated with a dummy argument with IN- TENT (OUT) or INTENT (INOUT) or with the POINTER attribute. Constraint: Any procedure referenced in a pure procedure, including one referenced via a defined operation or assignment, must be pure. Constraint: A pure procedure must not contain a print-stmt, open-stmt, close-stmt, back- space-stmt, endfile-stmt, rewind-stmt, or inquire-stmt. Constraint: A pure procedure must not contain a read-stmt or write-stmt whose io-unit is an external-file-unit or *. Constraint: A pure procedure must not contain a stop-stmt. The above constraints are designed to guarantee that a pure procedure is free from side effects (i.e., modifications of data visible outside the procedure), which means that it is safe to reference it in constructs such as a FORALL assignment-statement where there is no explicit order of evaluation. {footnote 3} footnote 3 The constraints on pure procedures may appear complicated, but it is not necessary for a programmer to be intimately familiar with them. From the programmer's point of view, these constraints can be summarized as follows: a pure procedure must not contain any op- eration that could conceivably result in an assignment or pointer assignment to a common variable, a variable accessed by use or host association, or an INTENT (IN) dummy argument, or perform any I/O or STOP operation. Note the use of the word conceivably; it is not sufficient for a pure procedure merely to be side-effect free in practice. For example, a function that contains an assignment to a global variable but in a block that is not executed in any invocation of the function is nevertheless not a pure function. The exclusion of functions of this nature is unavoidable if strict compile-time checking is to be used. In the choice between compile-time checking and flexibility, the committee decided in favor of enhanced check- ing. It is expected that most library procedures will conform to the con- straints required of pure procedures (by the very nature of library procedures), and so can be declared pure and referenced in FORALL statements and constructs and within user-defined pure procedures. It is also anticipated that most library procedures will not ref- erence global data, whose use may sometimes inhibit concurrent ex- ecution. See Annex X for further discussion of the constraints. end footnote Pure subroutines are included to allow subroutine calls from pure procedures in a safe way, and to allow forall-assignments to be defined assignments. The constraints for pure subroutines are based on the same principles as for pure functions, except that side effects to INTENT (OUT) and IN- TENT (INOUT) dummy arguments are permitted. Pointer dummy arguments are always treated as INTENT (INOUT). [Add PUREness to the list of procedure characteristics. Add after "subroutine" on line 36, page 165, section 12.2] "whether or not it is pure, " [Replace BNF rules on page 175 and 177 with:] R1217 prefix is prefix-spec [ prefix-spec ...] R1217A prefix-spec is type-spec or RECURSIVE or PURE Constraint: A prefix must contain at most one of each prefix-spec. R1220 subroutine-stmt is [ prefix ] SUBROUTINE subroutine-name [ ( [ dummy-arg-list ] ) ] Constraint: The prefix of a subroutine-stmt must not contain a type-spec. [To define interface specifications for pure procedures, the following constraints are added to Rule R1204 in Section 12.3.2.1 (defining interface-body)]: Constraint: An interface-body of a pure procedure must specify the intents of all dummy arguments except POINTER, alternate return, and procedure arguments. [To define pure procedure references, the following extra constraint is added to Rules R1209 and R1210 in Section 12.4.1 (defining function-reference and call-stmt):] Constraint: In a reference to a pure procedure, a procedure-name actual-arg must be the name of a pure procedure. {footnote 4} footnote 4 This constraint ensures that the purity of a procedure cannot be undermined by allowing it to call a non-pure procedure. end footnote Examples of Pure Procedure Usage Pure functions may be used in expressions in FORALL statements and constructs, unlike general functions which may have side effects. Several examples of this are given below. ! Intrinsic functions are always pure FORALL ( I = 1:N ) A(I,I) = LOG( ABS( A(I,I) ) ) Because a forall-assignment may be an array assignment, the pure function can have an array re- sult. Such functions may be particularly helpful for performing row-wise or column-wise opera- tions on an array. INTERFACE PURE FUNCTION F(X) REAL, DIMENSION(3) :: F REAL, DIMENSION(3), INTENT (IN) :: X END FUNCTION F END INTERFACE REAL V (3,10,10) ... FORALL (I=1:10, J=1:10) V(:,I,J) = F(V(:,I,J)) Because pure procedures have no constraints on their internal control flow (except that they may not use the STOP statement), they also provide a means for encapsulating more complex opera- tions than could otherwise be nested within a FORALL. For example, the fragment below per- forms an iterative algorithm on every element of an array. Note that different amounts of computation may be required for different inputs. PURE INTEGER FUNCTION ITER(X) COMPLEX, INTENT (IN) :: X COMPLEX XTMP INTEGER I I = 0 XTMP = -X DO WHILE (ABS(XTMP).LT.2.0 .AND. I.LT.1000) XTMP = XTMP * XTMP - X I = I + 1 END DO ITER = I END FUNCTION ... FORALL (I=1:N, J=1:M) & IX(I,J) = ITER(CMPLX(A+I*DA,B+J*DB)) [Add to appendix B, the deleted features appendix.] Constraint: A pure procedure must not contain a pause-stmt. {footnote 5} footnote 5 A pause requires some form of input or output and is disallowed for the same reasons that other I/O statements are disallowed. end footnote [Add to the annex as a description of the pure procedure constraints.] The constraints on pure procedures are limited to those necessary to check statically for freedom from side effects, for processor independence, and for lack of saved internal state. Subject to these restrictions, maximum functionality has been preserved in the definition of pure procedures. This has been done to make function calls in FORALL as widely available as possible, and so that quite general library procedures can be classi- fied as pure. A drawback of this flexibility is that pure procedures permit certain fea- tures whose use may hinder, and in the worst case prevent, concurrent ex- ecution in FORALL (that is, such references may have to be implemented by sequentialization). Foremost among these features are the access of glo- bal data, particularly distributed global data, and the fact that the ar- guments and, for a pure function, the result may be pointers or data structures with pointer components, including recursive data structures such as lists and trees. The programmer should be aware of the potential performance penalties of using such features. The constraint requiring explicit INTENT (IN) for function arguments de- clares behavior that is ensured by the following constraints. It is not technically necessary, but is included for consistency with the explicit declaration rules for defined operators. Note that POINTER arguments may not have the INTENT attribute; the restrictions ensure that POINTER ar- guments also behave as if they had INTENT (IN), for both the argument itself and the object pointed to. The constraint disallowing variables with the SAVE attribute ensures that a pure procedure does not retain an internal state between calls, which would allow side effects between calls to the same procedure The constraint giving the restrictions on use of global (common or ac- cessed by host or use association) variables and dummy arguments ensures that dummy arguments and global variables are not modified by the proce- dure. In the case of a dummy or global pointer, this applies to both its pointer association and its target value, so it cannot be subject to a pointer assignment or to an ALLOCATE, DEALLOCATE, or NULLIFY statement. These constraints imply that only local variables and the dummy function result variable can be subject to assignment or pointer assignment. In addition, a dummy or global data object cannot be the target of a point- er assignment (i.e., it cannot be used as the right hand side of a pointer assignment to a local pointer or to the result variable), for then its value could be modified via the pointer. (An alternative approach would be to allow such objects to be pointer targets, but disallow assignments to those pointers; syntactic constraints to allow this would be even more draconian than these.) In connection with the last point, it should be noted that an ordinary (as opposed to pointer) assignment to a variable of derived type that has a pointer component at any level of component selection may result in a pointer assignment to the pointer component of the variable. That is cer- tainly the case for an intrinsic assignment. In that case, the expression on the right hand side of the assignment has the same type as the assign- ment variable, and the assignment results in a pointer assignment of the pointer components of the expression result to the corresponding compo- nents of the variable (see section 7.5.1.5). However, it may also be the case for a defined assignment to such a variable, even if the data type of the expression has no pointer components; the defined assignment may still involve pointer assignment of part or all of the expression result to the pointer components of the assignment variable. Therefore, a dummy or global object cannot be used as the right hand side of any assignment to a variable of derived type with pointer components, for then it, or part of it, might be the target of a pointer assignment, in violation of the restriction mentioned above. The last two paragraphs only prevent the reference of a dummy or global object as the only object on the right hand side of a pointer assignment or an assignment to a variable with pointer components. There are no constraints on its reference as an operand, actual argument, subscript expression, etc., in these circumstances. Finally, a dummy or global data object cannot be used in a procedure ref- erence as an actual argument associated with a dummy argument of INTENT (OUT) or INTENT (INOUT) or with a dummy pointer, for then it may be mod- ified by the procedure reference. This constraint, like the others, can be statically checked, since any procedure referenced within a pure func- tion must be either a pure function, which does not modify its arguments, or a pure subroutine, whose interface must specify the INTENT or POINTER attributes of its arguments. Incidentally, notice that in this context it is assumed that an actual argument associated with a dummy pointer is modified, since Fortran does not allow its intent to be specified. The constraint that only pure procedures may be called ensures that all procedures called from a pure procedure are themselves side-effect free, except, in the case of subroutines, for modifying actual arguments asso- ciated with dummy pointers or dummy arguments with INTENT (OUT) or INTENT (INOUT). A constraint prevents external I/O and file operations, whose order would be non-deterministic in the context of concurrent execution. Note that internal I/O is allowed, provided that it does not modify global variables or dummy arguments. Finally, a constraint disallows STOP statements. A STOP brings execution to a halt, which is a rather drastic side effect. ------------------------------------------------------------------------------ Number: 005a Title: Rationale for FORALL and PURE Status: Approved Target date: 95 Last revision: Feb 94 X3J3 reference: 94-097 X3J3 94-097 TO: X3J3 FROM: Dick Hendrickson SUBJECT: Rationale for FORALL and PURE The following is the rationale section for the FORALL and PURE features. NOTE that the HPF document is copyrighted by Rice University. Rice has given free permission to copy from the document, but the copyright must be mentioned. Paper 94-013 should have mentioned this fact also. Rational: The FORALL statement and construct and PURE procedures were added to Fortran 95 to allow the majority of programs coded in High Performance Fortran (HPF) to run on a standard conforming Fortran 95 processor with little change. These added concepts are the major new syntatic features of HPF. HPF was primarily designed to allow programs to execute efficiently on multi-processor systems. Adding these features to Fortran 95 does not imply that a Fortran 95 processor is a multi-processor nor that any features of the language are safe or consistent on a multi-processor system. Some of the text describing the FORALL and PURE features was taken directly from the High Performance Fortran Language Specification, Version 1.0, May 3, 1993 c1993 Rice University, Houston Texas. The text was copied with the permission of Rice University. The purpose of the FORALL statement and construct is to provide a convenient syntax for simultaneous assignments to large groups of array elements. Such assignments lie at the heart of the data parallel computations that HPF is designed to express. The multiple assignment functionality it provides is very similar to that provided by the array assignment statement and the WHERE construct in Fortran 90. FORALL differs from these constructs in its syntax, which is intended to be more suggestive of local operations on each element of an array, and in its generality, which allows a larger class of array sections to be specified. In addition, a FORALL may invoke user-defined functions on the elements of an array, simulating Fortran 90 elemental function invocation (albeit with a different syntax). HPF defines a new procedure attribute, PURE, to declare the class of functions that may be invoked in this way. Both single-statement and block FORALL forms are defined in this section, as well as the PURE attribute and constraints arising from the use of PURE. Fortran 90 places several restrictions on array assignments. In particular, it requires that operands of the right side expressions be conformable with the left hand side array. These restrictions can be relaxed by introducing the element array assignment statement, usually referred to as the FORALL statement. This statement is used to specify an array assignment in terms of array elements or groups of array sections, possibly masked with a scalar logical expression. In functionality, it is similar to array assignment statements and WHERE statements. The FORALL statement essentially preserves the semantics of Fortran 90 array assignments and allows for convenient assignments like FORALL ( i=1:n, j=1:m ) a(i,j)=i+j as opposed to standard Fortran 90 a = SPREAD((/(i,i=1,n)/), DIM=2, NCOPIES=m) + & SPREAD((/(i,i=1,m)/), DIM=1, NCOPIES=n) It can also express more general array sections than the standard triplet notation for array expressions. For example, FORALL ( i = 1:n ) a(i,i) = b(i) assigns to the elements on the main diagonal of array a. It is important to note, however, that FORALL is not intended to be a general parallel construct; for example, it does not express pipelined computations or MIMD computation well. This was an explicit design decision made in order to simplify the construct and promote agreement on the statement's semantics. A PURE function is one that obeys certain syntactic constraints that ensure it produces no side effects. This means that the only effect of a pure function reference on the state of a program is to return a result---it does not modify the values, pointer associations, or data mapping of any of its arguments or global data, and performs no external I/O. A pure subroutine is one that produces no side effects except for modifying the values and/or pointer associations of INTENT (OUT) and INTENT (INOUT) arguments. These properties are declared by a new attribute (the PURE attribute) of the procedure. A pure procedure (i.e., function or subroutine) may be used in any way that a normal procedure can. However, a procedure is required to be pure if it is used in any of the following contexts: ! In the mask or body of a FORALL statement or construct; ! Within the body of a PURE procedure; or ! As an actual argument in a PURE procedure reference. The freedom from side effects of a pure function allows the function to be invoked concurrently in a FORALL without such undesirable consequences as nondeterminism, and additionally assists the efficient implementation of concurrent execution. Syntactic constraints (rather than semantic constraints on behavior) are used to enable compiler checking. ------------------------------------------------------------------------------ Number: 006 Title: B9/B1 Object Initialization Status: Approved Target date: 95 Last revision: May 94 X3J3 reference: 94-138r3 X3J3/94-138r3 To: X3J3 From: /OOF Subject: Text for X3J3/009 re Object Initialization (B1) References: WG5-N930 Resolutions of the Berchtesgaden WG5 Meeting, B9 WG5-N932 Requirement for the Initialization of Pointers and Objects X3J3/93-207 Pointer and Derived Type Initialization X3J3/93-204r4 B9 Implementation Plan X3J3/93-237 OOF Report from Meeting 126 X3J3/93-259 Proposal for Object Initialization (B1) X3J3/93-296 Constructors and Destructors plus Object Initialization (Tutorial) X3J3/94-030 OOF Report from Meeting 127 X3J3/94-031r2 Proposal for Object Initialization (B1) X3J3/94-081 Object Initialization and Memory Conservation (Overheads) Number: 006 Requirement Title: B9/B1 Object Initialization Status: Approved Technical Description: Currently all pointers are created with an undefined associa- tion status. There is a requirement to change this to allow some pointers to be created with a disassociated association status. The means chosen by straw vote within X3J3 to specify an initial association status of disassociated involves the appearance in ini- tialization contexts of a new intrinsic function NULL with a single optional argument. The syntax "=> NULL( )" may appear in a type declaration statement. The intrinsic function may also appear in a structure constructor to correspond with a pointer com- ponent. There is a further requirement to extend a type definition to contain the specification of a default initial value for a nonpointer component and the specification of disassociated status as the default for a pointer component. It is not necessary for a default value to be specified for each nonpointer component in a definition nor to change the initial as- sociation status of each pointer component from undefined to disassociated. If a com- ponent is of derived type, its initial state may be specified in the type definition of that type. Conversely, even though a derived-type component has an initial state specified in its type definition, the initial state may be overridden by the use of a structure con- structor for that type in the (higher-level) component specification. The effect of spec- ifying default initial values for nonpointer components and the disassociated status for pointer components is that whenever an object of the type is created, by declaration or allocation, it will be automatically initialized as indicated in the type definition. As is the case with objects of intrinsic type, it is possible to specify initial values for objects of derived type in type declarations and DATA statements. For an object of de- rived type, an initial value so specified overrides any default initialization contained in the type definition. An object of a derived type with default initialization specified must not appear in a DATA statement. Note that whereas initialization in a type dec- laration statement or a DATA statement implies that the object initialized has the SAVE attribute, specification of default initialization carries no such implication for objects of the type. The syntax needed to meet this requirement for nonpointer components, would seem to be a natural extension of the initialization mechanism used for an object in a type dec- laration. It is merely a matter of allowing = initialization to appear in a component specification. The means described above for initializing a pointer to have an initial sta- tus of disassociated can then be used to specify a default disassociated status for a point- er component. To summarize these extensions: - => NULL( ) can appear in a type declaration. - NULL([]) can appear in a structure constructor. - Initialization specifications that can appear in a type declaration statement can also appear in a component specification to specify default initialization. - Default initialization can be overridden by a higher level default initialization or by explicit initialization. Discussion: The specification of default initialization is a facility that is not available for objects of intrinsic type. The current proposal does not allow a pointer to have a default association status of de- fined, although there is no conceptual problem with doing this so long as the target has been declared with the TARGET and SAVE attributes. Detailed Edits: [94-006r0 was integrated into these edits. The only collision was item 87 as noted below.] [32:36+] add a new paragraph Default initialization is specified for a component of an object of de- rived type when initialization appears in the component declaration. The object will be initialized as specified in the derived type definition (14.7.3, 14.7.5) even if the definition is private or inaccessible. Unlike explicit initialization, default initialization does not imply that the object has the SAVE attribute. Default initialization does not apply to dummy arguments unless they have INTENT (OUT). [33:29-30] replace with R429 component-decl is component-name [ ( component-array-spec ) ] [ * char-length ] [ component-initialization ] R429a component-initialization is = initialization-expr or => NULL ( ) [33:38+] add constraints Constraint: If component-initialization appears, a double colon separa- tor must appear before the component-decl-list. Constraint: If => appears in component-initialization, the POINTER attribute must appear in the component-attr-spec-list. If = appears in component-initialization, the POINTER attribute must not appear in the component-attr-spec-list. Constraint: If an object with default initialization is specified in a com- mon block, the common block must be saved, and if an object with de- fault initialization is specifed in the specification part of a module, the object must be saved. Note that objects in named common may be initially defined only in a block data program unit (5.5.2.4). Objects with default initialization must not appear in blank common. [34:1-2] replace with The double colon separator in a component-def-stmt is required if the DIMENSION attribute, the POINTER attribute, or component-initial- ization is specified; otherwise, it is optional. If initialization-expr appears, an object of the type becomes defined with the default initial value determined from initialization-expr unless the default initial value is overridden by explicit initialization. The ini- tialization-expr is evaluated in the scoping unit of the type definition in accordance with the rules of intrinsic assignment (7.5.1.4). [34:6+] add Note that default initialization of an array component may be specified by a constant expression consisting of an array constructor, or of a single scalar that becomes the value of each array element. A component is a pointer if its component-attr-spec-list contains the POINTER attribute. Pointers have an association status of "undefined", "disassociated", or "associated". If no default initialization is specified, the initial status is "undefined". Pointer nullification sets the status of a pointer to "disassociated". To specify that the default initialization of a pointer component is to be "disassociated", the pointer assignment symbol (=>) must be followed by a reference to the intrinsic function NULL( ) with no argument. No mechanism is provided to specify a de- fault initial status of "associated". [35:30] insert after "component." The type definition may specify that in objects declared to be of this type, such a pointer is initially disassociated. [35:33] replace with TYPE(NODE), POINTER :: NEXT_NODE => NULL( ) [35:35+] Add It is not required that initialization be specified for each component of a derived type. For example: TYPE DATE INTEGER DAY CHARACTER (5) MONTH INTEGER :: YEAR = 1994 ! Partial default initialization END TYPE DATE If a component is of intrinsic type and is not a pointer, a default initial value may be specified by an initialization expression. If the component is an array, the initialization expression must be conformable; it may be a scalar or an array constructor (4.5). If the component is a pointer, a limited form of pointer assignment (7.5.2) may be used to specify that in objects of the type, the pointer component is initially disassociated. If the component is of derived type and does not have the pointer at- tribute, its default initial value may be specified in the type definition for that derived type or by a structure constructor that may override any lower-level default initialization. In the following example, the default initial value for the YEAR compo- nent of TODAY is overridden by explicit initialization in the type dec- laration statement: TYPE (DATE), PARAMETER :: TODAY = DATE (21, "Feb.", 1995) The default initial value of a component of derived type may be overrid- den by a higher level default initialization. For example: TYPE SINGLE_SCORE TYPE(DATE) :: PLAY_DAY = TODAY INTEGER SCORE TYPE(SINGLE_SCORE), POINTER :: NEXT => NULL( ) END TYPE SINGLE_SCORE TYPE(SINGLE_SCORE) SETUP The PLAY_DAY component of SETUP receives its initial value from TODAY overriding the lower-level initialization for the YEAR compo- nent. Arrays of structures may be declared whose elements are partially or to- tally initialized by default. For example: TYPE MEMBER CHARACTER (20) NAME INTEGER :: TEAM_NO, HANDICAP = 0 TYPE (SINGLE_SCORE), POINTER :: HISTORY => NULL( ) END TYPE MEMBER TYPE (MEMBER) LEAGUE (36) ! Array of partially ! initialized elements TYPE (MEMBER):: ORGANIZER=MEMBER ("I. Manage",1,5,NULL( )) ORGANIZER is explicitly initialized, overriding the default initializa- tion for an object of type MEMBER. Allocated objects may also be ini- tialized partially or totally. For example: ALLOCATE (ORGANIZER % HISTORY) ! A partially initialized ! object of type ! SINGLE_SCORE is created. [37:11] replace "constant expressions" with constant expressions or pointer nullifications [39:36-37] replace with R504 entity-decl is object-name [ ( array-spec ) ] [ * char-length ] [ initialization ] [39:38+] add R504a initialization is = initialization-expr or => NULL ( ) [40:1] = initialization-expr -> initialization [40:3] The = initialization-expr -> initialization [40:5] delete "a pointer," [40:6+] add constraint Constraint: If => appears in initialization, the object must have the POINTER attribute. If = appears in initialization, the ob- ject must not have the POINTER attribute. [40:34] = initialization-expr -> initialization [40:44] an = initialization-expr -> explicit initialization. [41:8+] add paragraph If entity-decl contains a reference to the NULL intrinsic function, ob- ject-name must be a pointer, and its initial association status is disasso- ciated. [41:9-10] change sentence to [ includes edit from defect item 87] The presence of initialization implies that object-name is saved, except for an object-name in a named common block or an object-name with the PARAMETER attribute. [41:22+] add TYPE(CHAIN), POINTER :: HEAD => NULL( ) [44:6+] add TYPE(NODE), PARAMETER :: DEFAULT = NODE(0, NULL( )) [44:30] add before period, "except for components of an object of derived type for which default initialization has been specified". [51:35+] add sentence, "If an object or subobject has been specified with default initialization in a type definition, it must not appear in a data-stmt-ob- ject-list." [76:22+] add The intrinsic function NULL returns a disassociated pointer. A disasso- ciated pointer has no shape but does have rank. The data type, type pa- rameters, and rank of the result of the intrinsic function NULL when it appears without an argument are determined by the pointer that becomes associated with the result. If the intrinsic function appears on the right of a pointer assignment statement, the type, type parameters, and rank of the result are those of the pointer on the left. If the intrinsic function appears in initialization for an object in a type declaration statement, the type, type parameters, and rank of the result are those of the object. If the intrinsic function appears as a default initialization specification in a component-decl, the type, type parameters, and rank of the result are those of the component. If the intrinsic function appears in a structure constructor, the type, type parameters, and rank are determined by the corresponding pointer component. If the intrinsic function appears as an actual argument in a procedure reference, the type, type parameters, and rank of the result are those of the corresponding dummy argument. The optional argument is required when the intrinsic function NULL ap- pears as an actual argument in a reference to a generic procedure if the argument type, type parameters, and rank are required to resolve the ref- erence. For example: INTERFACE GEN SUBROUTINE S1 (J, PI) INTEGER J INTEGER, POINTER :: PI END SUBROUTINE S1 SUBROUTINE S2 (K, PR) INTEGER K REAL, POINTER :: PR END SUBROUTINE S2 END INTERFACE REAL, POINTER :: REAL_PTR CALL GEN (7, NULL (REAL_PTR) ) ! Invokes S2 [77:23+] add new item to list (5a) A reference to the transformational intrinsic function NULL, [78:5] add new item to list (5a) A reference to the transformational intrinsic function NULL, [79:10+] add new item to list (8a) The transformational NULL, [92:17] Replace "If the target is a pointer that is disassociated," with "If the tar- get is a pointer that is disassociated or a reference to the NULL intrinsic function," and delete "also". [92:28+] add PTR => NULL ( ) [187:32] change title to 13.8.10 Pointer association status functions [187:33] The function -> The function NULL returns a disassociated pointer. The inquiry function [192:13] change title to 13.10.20 Pointer association status functions [192:14] Association status or comparison -> Association status inquiry or com- parison [192:15+] add NULL (MOLD) Returns disassociated pointer Optional MOLD [225:19+] add 13.13.77a NULL (MOLD) Optional Argument. MOLD Description. Returns a disassociated pointer. Class. Transformational function. Argument. MOLD must be a pointer and may be of any type. Its point- er association status may be undefined, disassociated, or associated. If its status is associated, the target need not be defined with a value. Result Type, Type Parameters, and Rank. Determined by context (7.1.4.1) if MOLD is not present; otherwise, the same as MOLD. Result. The result is a pointer with disassociated association status. Example. REAL, POINTER, DIMENSION(:) :: VEC => NULL( ) sets the initial association status of VEC to disassociated. [243:13] add new paragraph Note that if the intrinsic function NULL appears as an actual argument in a reference to a generic procedure, the argument MOLD may be re- quired to resolve the reference (7.1.4.1). [246:35] becomes -> is [246:35+] add (and reletter remaining items) (a) The pointer is explicitly initialized in a type declaration (5.1) (b) Default initialization is specified for the pointer in a type definition (4.4) [249:38+] add new item to the list and adjust the list appropriately (3) Components of SAVEd variables for which default initialization is specified, and [251:6+] add new items to the list and adjust the list appropriately (17) Allocation of an object of a derived type, in which default initial- ization is specified for some components, causes those components of the object to become defined. (19) Invocation of a procedure that contains a nonSAVEd local object that is not a dummy argument and is of a derived type in which default initialization is specified for some components, causes those compo- nents of the object to become defined. (20) Invocation of a procedure that has an INTENT (OUT) dummy ar- gument of a derived type that specifies default initialization for some components, causes those components of the dummy argument to be- come defined. [256:10+] add new glossary item default initialization (4.4) : If initialization is specified in a type defi- nition, an object of the type will be automatically initialized. Nonpoint- er components may be initialized with values by default; pointer components may be initially disassociated by default. Default initializa- tion is not provided for objects of intrinsic type. [256:42+] add new glossary item explicit initialization : Explicit initialization may be specified for ob- jects of intrinsic or derived type in type declaration statements or DATA statements. An object of a derived type that specifies default initializa- tion may not appear in a DATA statement. [268:2-3] replace with INTEGER :: VAL = 0 TYPE(CELL), POINTER :: NEXT_CELL => NULL( ) [268:5] replace with TYPE(CELL), TARGET :: HEAD ! Automatically initialized [268:9] delete [268:15] delete Add to new Rationale Section: 4.4 Derived types The prime motivation for adding a means to specify default initialization for objects of derived type is a need to eliminate situations in which dynamic memory becomes un- available. This can occur in applications that manipulate objects of derived type with pointer components. Most memory leakage can be avoided if it is possible to specify that pointers be created with an initial status of disassociated. In order to allow the ini- tial status of a pointer to be specified as disassociated in declarations, structure con- structors, or type definitions, a new intrinsic function, NULL, with a single optional argument is provided. When the intrinsic function NULL appears in a type definition, the optional argument must not appear. When the intrinsic function NULL appears elsewhere, the argument is optional if the type, type parameters, and rank of the re- quired disassociated pointer are apparent from the context. If this is not the case, a pointer object name must appear as the argument to indicate the type, type parameters, and rank of the required disassociated pointer. The argument acts as a mold. Such an argument may be necessary when a disassociated pointer is used as an actual argument in a generic procedure reference (7.1.4.1). An example of the initialization of a pointer as disassociated is: REAL, POINTER, DIMENSION (:) :: VEC => NULL( ) The following code fragment illustrates the memory leakage problem: MODULE CHARACTER_VARYING TYPE VARYING PRIVATE CHARACTER, POINTER :: CHARS(:) END TYPE VARYING ! Generic interfaces for assignment, concatenation, conversion, etc. ... CONTAINS SUBROUTINE VS_ASS_VS (VAR, EXPR) ! Assignment subroutine TYPE(VARYING), INTENT(OUT) :: VAR TYPE(VARYING), INTENT(IN) :: EXPR ALLOCATE (VAR % CHARS (1:SIZE(EXPR % CHARS))) VAR % CHARS = EXPR % CHARS END SUBROUTINE VS_ASS_VS ... END MODULE CHARACTER_VARYING MODULE VOCABULARY USE CHARACTER_VARYING PRIVATE TYPE(VARYING), PUBLIC :: WORDS (5000) ! Words in random order WORDS(1) = "attack" WORDS(2) = "at" WORDS(3) = "dawn" ... END MODULE VOCABULARY PROGRAM DECIPHER_MESSAGE USE CHARACTER_VARYING USE VOCABULARY ! Get WORDS TYPE(VARYING) MSG ! To collect message INTEGER MSG_WDS(100) ! Indices to WORDS INTEGER N, I ! No. of indices, loop index READ *, N, MSG_WDS MSG = "" ! Set to empty string DO I = 1, N MSG = MSG // WORDS(MSG_WDS(I)) ! Collect message END DO ... END PROGRAM DECIPHER_MESSAGE Suppose the string of indices read into MSG_WDS is 125, 2, 3005, 7, 333, 4002, 66, 222, 2, 6, 901 and at the conclusion of the loop, MSG contains "meeting at five on morning of may eighteen at abandoned mine". Dynamic memory will contain the fol- lowing: meeting meeting at meeting at five meeting at five on meeting at five on morning . . . Because the pointer VAR % CHARS in the subroutine VS_ASS_VS may be undefined, it cannot be tested for association so that space no longer needed can be released. In applications manipulating objects of derived type with pointer components, most mem- ory leakage can be avoided if initialization of pointers in the derived type can be spec- ified in the type definition. Objects of the type can then be initialized automatically when created by either declaration or allocation. If the module CHARACTER_VARY- ING can be specified as: MODULE CHARACTER_VARYING TYPE VARYING PRIVATE CHARACTER, POINTER :: CHARS(:) => NULL( ) END TYPE VARYING ! Generic interfaces for assignment, concatenation, conversion, etc. ... CONTAINS SUBROUTINE VS_ASS_VS (VAR, EXPR) ! Assignment subroutine TYPE(VARYING), INTENT(OUT) :: VAR TYPE(VARYING), INTENT(IN) :: EXPR IF (ASSOCIATED (VAR % CHARS)) DEALLOCATE (VAR % CHARS) ALLOCATE (VAR % CHARS (1:SIZE(EXPR % CHARS))) VAR % CHARS = EXPR % CHARS END SUBROUTINE VS_ASS_VS ... END MODULE CHARACTER_VARYING Then at the conclusion of the loop, dynamic memory would not be needlessly cluttered. The previous standard allowed pointer assignment to occur when an object of a type containing a pointer is defined with a structure constructor; see the example in section 4.4.4 [37:17-26]. It is only a small extension to allow pointer nullification in derived- type constant expressions used for named constants or data initialization. For example: TYPE LINK REAL :: VALUE TYPE(LINK), POINTER :: NEXT END TYPE LINK TYPE(LINK) :: HEAD = LINK(0.0, NULL( )) TYPE(LINK), PARAMETER :: DEFAULT = LINK(0.0, NULL( )) TYPE(LINK) :: END_OF_CHAIN = DEFAULT This language extension does not completely solve the memory leakage problem; for that, an automatic destructor is needed that would be invoked for local pointers and structures with pointer components when the procedure in which they are created ter- minates. Such a facility is not included in this standard; it could be provided automat- ically by a processor that strove to conserve dynamic memory. For reasons of determinancy and portability, an object for which default initialization is specified is not allowed to appear in a DATA statement. In traditional implementa- tions, a compiler passes along initialization information for nondynamic variables to a loader, which is frequently designed to handle object code from several different lan- guages. There could thus be no guarantee that initialization in a DATA statement would override the default initialization specified in a type definition. History: WG5-N930 Resolution of the Berchtesgaden WG5 Meeting WG5-N932 Requirement for the Initialization of Pointers and Objects X3J3/93-207 Pointer and Derived Type Initialization X3J3/93-259 Proposal for Object Initialization X3J3/94-031r2 Proposal for Object Initialization - moved to X3J3/009 with status "X3J3 consideration in progress" by unanimous consent X3J3/94-138r3 Text for X3J3/009 re Object Initialization (B1) moved to X3J3/009 (replacing previous text) with status "Approved" by unanimous consent ------------------------------------------------------------------------------ Number: 007 Title: Language evolution (B9 Item B4.2) Status: Approved Target date: 95 Last revision: May 94 X3J3 reference: x3j3.1994-310 email ballot Introduction ------------ At meeting 128, X3J3 approved the following two proposals. 1. The following Fortran 90 features shall be deleted from the revised language: Real and double precision DO variables Branching to END IF PAUSE ASSIGN, assigned GO TO, assigned formats cH edit descriptor 2. The following Fortran 90 features shall be deemed obsolescent in the revised language: Computed GO TO Statement functions DATA statements amongst executables Assumed length character functions Fixed form source Assumed size arrays CHARACTER* form of CHARACTER declaration The following specifies the edits necessary to implement these decisions. Proposed edits are represented using the form of the Technical Corrigenda, that is using location both relative to section and paragraph (for the benefit of those without line-numbered copies of Fortran 90) and by page and line number, shown in square brackets. The edits are ordered by topic, rather than sequentially overall, except that the replacement Annex B is presented as a whole, in order to facilitate consistency of style. Where comments are made, they are shown within square brackets. Edits for the font of text describing obsolescent features have been proposed only for annexes A and C. It would be tedious in the extreme for Annex B, which discusses deleted and obsolescent features, to have every reference to an obsolescent feature in a different font. Edits implementing deletion --------------------------- D1. Edits relating to the deletion of real DO variables In section 8.1.4.1.1, rule R821 [100:34-35]: Change "scalar-numeric-expr" to "scalar-int-expr", three times. In rule R822 [100:37]: Change "scalar-variable" to "scalar-int-variable". In rule R822, first constraint [100:38-39] : Delete ", default real, or double precision real" ; Delete the second constraint which follows rule R822 [100:40-41]. In section 8.1.4.4.1, third line, [102:22]: Change "scalar-numeric-expr" to "scalar-int-expr", three times. Replace the section numbered (1) [102:24-29] by: "The initial parameter m1, the terminal parameter m2, and the incrementation parameter m3 are established by evaluating scalar-int- expr1, scalar-int-expr2, and scalar-int-expr3, respectively, including, if necessary, conversion to the kind type parameter of the do-variable according to the rules for numeric conversion (Table 7.9). If scalar-int- expr3 does not appear, m3 is of type default integer and its value is 1. The value m3 must not be zero." In section 9.4.2, rule R918 [123:27-28]: Change "scalar-numeric-expr" to "scalar-int-expr", three times. In rule R918, second constraint [123:30] : Delete ", default real, or double precision real" ; Text for Annex B.1 is shown at B.1.1 below. D2. Edits relating to the deletion of branching to END IF In the second paragraph of section 8.1.2.2, second line [96:36]: Add "only" before "from within" and delete ", and also from outside the construct". In the third paragraph of section 8.2, [107:7-8]: Add "only" before "from within" and delete the text ", and also from outside the construct". [This is then consistent with the wording for the CASE construct]. Text for Annex B.1 is shown at B.1.2 below. D3. Edits related to deletion of the PAUSE statement In section 2.1, rule R216 [9:31]: Delete the line "or pause-stmt". Delete all of section 8.5 [108:32-37]. Text for Annex B.1 is shown at B.1.3 below. D4. Edits relating to deletion of ASSIGN, assigned GO TO, assigned formats In section 2.1, rule R216 [9:29-30]: Delete the lines "or assign-stmt" and "or assigned-go-to-stmt". In section 8.1.4.1.2, rule R829, first constraint [101:20-21]: Add "or" before "an arithmetic-if-stmt" and delete "or an assigned-go-to-stmt". In section 8.1.4.1.2, rule R833, first constraint [101:33-34]: Add "or" before "an arithmetic-if-stmt" and delete "or an assigned-go-to-stmt". Delete section 8.2.4 [107:30-108:11] and renumber section 8.2.5 accordingly. In section 9.4.1.1, rule R913 [121:5]: Delete the line "or scalar-default-int-variable". Delete the first paragraph following the constraint for rule R913 [121:8-9], that is delete, "The scalar-default-int-variable must have been assigned (8.2.4) the statement label of a FORMAT statement that appears in the same scoping unit as the format." In section 14.7.5 [250:18-19]: Delete the section numbered (6) and renumber accordingly. In section 14.7.5 [250:33-34]: In the section numbered (11) delete the text, ", except that variables associated with the variable in an ASSIGN statement become undefined when the ASSIGN statement is executed" In section 14.7.6 [251:20-21]: Delete the section numbered (2) and renumber accordingly. Text for Annex B.1 is shown at B.1.4 below. D5. Edits relating to the deletion of the cH edit descriptor In section 10.2.1: Delete the second line of rule R1016. [137:16] Delete rule R1017 and the first three constraints following it. [137:17-20] Delete the penultimate paragraph in the section, that is, "In the H edit descriptor, c specifies the number of characters following the H." [137:28] In the last paragraph, delete the words, "except for the characters following the H in the H edit descriptor and". [137:30] Delete section 10.7.2 [148:4-6]. Text for Annex B.1 is shown at B.1.5 below. Edits implementing the obsolescence of features ----------------------------------------------- O1. Edits related to making computed GO TO obsolescent The following should be in obsolescent font: In section 2.1, rule R216, the line "or computed-goto-stmt" [9:6]; Section 8.2.3 [107:21-29]. Text for Annex B.2 is shown at B.2.1 below. O2. Edits related to making statement functions obsolescent The following should be in obsolescent font: In section 2.1, rule R207, the line "or stmt-function-stmt" [8:12]; In section 2.3.1, figure 2.1 the text "Statement Function Statements" [11:29]; In section 2.3.2, table 2.1, the text "Statement Function" [12:17]; In section 5.1, rule R505, second constraint, the text "or a statement function" [39:42]; In section 5.1.1.5, the paragraph, "The length specified for a character- valued statement function or statement function dummy argument of type character must be an integer constant expression." [43:6-7]; In section 11.3, rule 1106, second constraint, the text "a stmt-function- stmt," [157:21]; In section 11.3, penultimate paragraph, the text "statement function definitions," [157:27]; In section 12.1.2, the text ", or a statement function" [163:18]; In section 12.1.2.2.1, item numbered (2), the text "in a stmt-function- stmt," [164:4]; In section 12.1.2.2.1, item numbered (11), the text "or in a stmt- function-stmt," [164:15-16]; Section 12.1.2.4 [165:33-34]; In section 12.3.1, the sentence "The interface of a statement function is always implicit." [166:27]; In section 12.3.2.1, rule R1206, first constraint, the text ", or stmt- function-stmt" [167:29-30]; In section 12.4.1, rule R1214, fourth constraint, the text "or of a statement function" [172:7-8]; In section 12.5.2.4, first paragraph, the sentence "When a statement function is invoked, an instance of that statement function is created." [177:29 - added in corrigendum]; In section 12.5.2.4, second paragraph, the text "or statement function" (three times) [177:31-34]; In section 12.5.2.5, the entire paragraph "In a subprogram, a name that appears as a dummy argument in an ENTRY statement must not appear in the expression of a statement function unless the name is also a dummy argument of the statement function, appears in a FUNCTION or SUBROUTINE statement, or appears in an ENTRY statement that precedes the statement function statement." [178:39-42]; Section 12.5.4 [182:1-32]; In section 14.1.2, item numbered (1), the text "statement functions," [241:24]; In section 14.1.2.4, item numbered (2)(b), the text "or statement function" [243:30-31]; In section 14.1.2.4.2, item numbered (3), the text "or statement function" [244:29]; In section 14.1.3, the entire first paragraph [245:16-18]; In Annex A, definition of dummy argument, the text ", or a statement function statement" [256:30]; In Annex A, definition of entity, the text "a statement function" [256:38]; In Annex A, definition of implicit interface, the text ", or a statement function" [257:33]; In Annex A, definition of procedure, the text ", or a statement function" [259:21]; In Annex A, all of the definition of statement function [260:21-22]. Text for Annex B.2 is shown at B.2.2 below. O3. Edits relating to making obsolescent DATA statements among executables The following should be in obsolescent font: In section 2.1, rule 209, the line "or data-stmt" [8:17]; In section 2.3.1, figure 2.1, the text "DATA Statements" where it is alongside "Executable Constructs" [11:32-33]; In section 2.3.2, first paragraph, the text "DATA statement," [12:3]. [A paragraph in section 12.1.2.2.1 [164:23-25] also relates to positioning of DATA statements but does not need obsolescent font.] Text for Annex B.2 is shown at B.2.3 below. O4. Edits related to making obsolescent assumed length character functions In section 5.1.1.5, rule R509, constraint, delete the text, "if the function is an internal or module function, array-valued, pointer-valued, or recursive" and insert, in obsolescent font, "unless it is an external or dummy function that is neither array-valued, pointer-valued, nor recursive" [42:36-37]; The following should be in obsolescent font: In section 5.1.1.5, the paragraph numbered (3) [43:1-5]; In section 12.2.2, the last sentence, i.e. "If the length of a character data object is assumed, this is a characteristic." [166:16]; In section 12.3.1.1, paragraph (2)(d) [167:3-4]; In section 12.3.2.1.1, first paragraph, the text, "and the function result must not have assumed character length" [169:18-19]; In Annex A, definition of characteristics item (5), the text ", and whether the character length is assumed" [255:18]; Text for Annex B.2 is shown at B.2.4 below. O5. Edits related to making fixed form source obsolescent The following should be in obsolescent font: In section 3.3, fourth paragraph, the texts "and fixed" and "and fixed form" [21:39]; Section 3.3.2, including all subsections [23:23-24:14]; In section 4.3.2.1, in the definition of representable character, all of the item numbered (1) [30:35-36]; In section 8.1, the pre-penultimate paragraph, all of the final sentence, that is "In fixed source form, the name preceding the construct must be placed after column 6." [95:20-21]; In section C.3.1, all of item (1) [264:28]; Section C.3.4 [265:5-33]; Section C.4.2, [265:37-40]. [the reasoning behind the last two is that if fixed source form did not exist, the paragraphs would not exist; therefore the entire paragraphs should be in obsolescent font.] Text for Annex B.2 is shown at B.2.5 below. O6. Edits related to making obsolescent assumed size arrays The following should be in obsolescent font: In section 5.1.2.4, rule R512, the line "or assumed-size-spec" [45:11]; Section 5.1.2.4.4 [47:1-29]; In section 6.2.1, third paragraph, second sentence [63:34-35]; In section 6.2.2, rule R621, second constraint [64:14-15]; In section 6.2.2.3.1, second paragraph [65:49]; In section 7.1.1.1, rule R702, second constraint [71:3]; In section 7.5.1.1, rule R735, constraint [89:12]; In section 9.4.2, rule R918, first constraint [123:29]; In section 12.2.1.1, last line, the text "size," [166:6]; In section 12.4.1.1, penultimate paragraph, the text "an assumed-size array or" [173:27-28]; In section 12.4.1.4, the text "or assumed-size array" [174:16]; also the last sentence [174:18:20]; [also change "assumed size" to "assumed-size" as this is the only occurrence of the former.] In section 13.8.1, first paragraph, last sentence [186:21-22]; In section 13.8.1, second paragraph, last sentence [186:24-25]; In section 13.13.95, definition of Argument, last sentence, [232:29-30]; In section 13.13.99, definition of argument ARRAY, last sentence, [233:30-32]; In section 13.13.111, definition of argument ARRAY, last sentence, [238:26-28]; In Annex A, all of the definition of assumed-size array [254:29-30]; In Annex A, definition of characteristics item (3), the text "size," [255:13]. Further, in the example in section 5.1.2.4, array S should be removed from the SUBROUTINE statement and the related REAL statement should be deleted since it is not policy to use obsolescent features in examples. [45:14 & 20]. Similarly the example in 5.2.5 [50:37] should be changed to be, say, ... C(:) Text for Annex B.2 is shown at B.2.6 below. O7. Edits related to making obsolescent CHARACTER*char-length The following should be in obsolescent font: In section 5.1.1.4, rule R507, the line "or * char-length[,]" [42:19]. [It appears that "*char-length" is used in section 5 where it is not clear without close study whether it refers to a type-spec or an entity-decl. However, there seems to be only the one place (rule R507) that requires obsolescent font.] In section 5.1.1.5, in the last line, delete "*10" [43:12]. Text for Annex B.2 is shown at B.2.7 below. Other related edits ------------------- In the Foreword, at the end of the second paragraph, [xii] add "The designation FORTRAN 66 is used to signify the first Fortran standard, ANS X3.9-1966 (published as USAS X3.9-1966) or ISO 1539-1972."; In section C.9.7, last sentence, replace "ANSI X3.9-1966 (FORTRAN 66)" by "FORTRAN 66". [This is because the term FORTRAN 66 is used in the Introduction (once), in Annex C several times, and is needed in the revised Annex B, but the only reference is hidden in C.9.7. Perhaps the bit about USAS is not needed - it is relevant only if a library has the standard catalogued under the title on the document. Fortran 66 was developed by an ASA committee but ASA was renamed USASI on August 24, 1966.] In section 1.6, replace the first sentence [5:21-22] by "This International Standard protects the users' investment in existing software by including all but five of the language elements of Fortran 90 that are not processor independent."; In the remainder of section 1.6 and subsections, replace "FORTRAN 77" by "Fortran 90" four times [5:24, 5:25, 5:28, 5:31]; In section 1.6, third sentence, replace "none" by "five" [5:23]. Delete the content of section B.1 [262:3-6] and replace by the following. B.1 Deleted features The deleted features are those features of Fortran 90 that are redundant and are considered largely unused. Section 1.6.1 describes the nature of the deleted features. The deleted features in this International Standard are: (1) Real and double precision DO control variables The ability present in FORTRAN 77, and for consistency also in Fortran 90, for a do-variable to be of type real or double precision in addition to type integer, has been deleted. (2) Branching to an END IF statement from outside its block In FORTRAN 77, and for consistency also in Fortran 90, it was possible to branch to an END IF statement from outside the IF construct; this has been deleted. (3) PAUSE statement The PAUSE statement, present in FORTRAN 66, FORTRAN 77 and for consistency also in Fortran 90, has been deleted. (4) ASSIGN and assigned GO TO statements and assigned format specifiers The ASSIGN statement and the related assigned GO TO statement, present in FORTRAN 66, FORTRAN 77 and for consistency also in Fortran 90, have been deleted. Further, the ability to use an assigned integer as a format, present in FORTRAN 77 and Fortran 90, has been deleted. (5) cH edit descriptor In FORTRAN 77, and for consistency also in Fortran 90, there was an alternative form of character string edit descriptor, which had been the only such form in FORTRAN 66; this has been deleted. Recommendations are given in the following sections for those processors which extend the standard by implementing each of the deleted features. [replacement text in subsections of B.1 below is copied from Fortran 90] B.1.1 Real and Double Precision DO-Variables Replace rules R821 and R822 in section 8.1.4.1.1 by the following: "R821 loop-control is [ , ] do-variable = scalar-numeric-expr , n n scalar-numeric-expr [ , scalar-numeric-expr ] or [ , ] WHILE ( scalar-logical-expr ) R822 do-variable is scalar-variable Constraint: The do-variable must be a named scalar variable of type integer, default real, or double precision real. Constraint: Each scalar-numeric-expr in loop-control must be of type integer, default real, or double precision real." Replace the first part of section 8.1.4.4.1, up and excluding the paragraph numbered (2), by the following: "When the DO statement is executed, the DO construct becomes active. If loop-control is [ , ] do-variable = scalar-numeric-expr1 , scalar-numeric-expr2 [ , scalar-numeric-expr3 ] the following steps are performed in sequence: (1) The initial parameter m1, the terminal parameter m2, and the incrementation parameter m3 are established by evaluating scalar-numeric- expr1, scalar-numeric-expr2, and scalar-numeric-expr3, respectively, including, if necessary, conversion to the type and kind type parameter of the do-variable according to the rules for numeric conversion (Table 7.9). If scalar-numeric-expr3 does not appear, m3 is of type default integer and its value is 1. The value m3 must not be zero." B.1.2 Branching to an END IF statement from outside its IF block In section 8.1.2.2, second paragraph, change the second sentence to be, "It is permissible to branch to an END IF statement from within the IF construct, and also from outside the construct." In section 8.2, change the third paragraph to read, "It is permissible to branch to an END IF statement from within its IF construct, and also from outside the construct." B.1.3 PAUSE statement The definition of the statement is: pause-stmt is PAUSE [ stop-code ] Execution of a PAUSE statement causes a suspension of execution of the executable program. Execution must be resumable. At the time of suspension of execution, the stop code, if any, is available in a processor-dependent manner. Leading zero digits in the stop code are not significant. Resumption of execution is not under control of the program. If execution is resumed, the execution sequence continues as though a CONTINUE statement were executed. For completeness, "or pause-stmt" should be added to rule R216 in section 2.1. B.1.4 ASSIGN and assigned GO TO statements and assigned FORMAT specifiers The definitions of the ASSIGN and assigned GO TO statements are: assign-stmt is ASSIGN label TO scalar-int-variable Constraint: The label must be the statement label of a branch target statement or format-stmt that appears in the same scoping unit as the assign-stmt. Constraint: scalar-int-variable must be named and of type default integer. assigned-goto-stmt is GO TO scalar-int-variable [ [ , ] ( label-list ) ] Constraint: Each label in label-list must be the statement label of a branch target statement that appears in the same scoping unit as the assigned-goto-stmt. Constraint: scalar-int-variable must be named and of type default integer. Execution of an ASSIGN statement causes a statement label to be assigned to an integer variable. While defined with a statement label value, the integer variable may be referenced only in the context of an assigned GO TO statement or as a format specifier in an input/output statement. An integer variable defined with a statement label value may be redefined with a statement label value or an integer value. When an input/output statement containing the integer variable as a format specifier (9.4.1.1) is executed, the integer variable must be defined with the label of a FORMAT statement. At the time of execution of an assigned GO TO statement, the integer variable must be defined with the value of a statement label of a branch target statement that appears in the same scoping unit. Note that the variable may be defined with a statement label value only by an ASSIGN statement in the same scoping unit as the assigned GO TO statement. The execution of the assigned GO TO statement causes a transfer of control so that the branch target statement identified by the statement label currently assigned to the integer variable is executed next. If the parenthesized list is present, the statement label assigned to the integer variable must be one of the statement labels in the list. A label may appear more than once in the label list of an assigned GOTO statement." Further, "assigned-go-to-stmt" should be added to the lists of prohibited statements in the first constraints to rules R829 and R833 in section 8.4.1.1. For completeness, "assigned-stmt" and "assigned-go-to-stmt" should be added to rule R216 in section 2.1. In section 14.7.5, the following section should be added: "Execution of an ASSIGN statement causes the variable in the statement to become defined with a statement label value." In section 14.7.5, the sentence in section (10???), "When a numeric storage unit becomes defined, all associated numeric storage units of the same type become defined." should have the following qualification added at the end, ", except that variables associated with the variable in an ASSIGN statement become undefined when the ASSIGN statement is executed" In section 14.7.6, the following section should be added: "Execution of an ASSIGN statement causes the variable in the statement to become undefined as an integer. Variables that are associated with the variable also become undefined." Use of assigned integers as formats In section 9.4.1.1 add to rule R913: "or scalar-default-int-variable" with the qualification that the scalar-default-int-variable must have been assigned the statement label of a FORMAT statement that appears in the same scoping unit as the format. B.1.5 cH Edit Descriptor In section 10.2.1, add the following line to rule R1016: " or cH rep-char [rep-char] ..." Add the following new rule with constraints, which logically follows rule R1016: " c is int-literal-constant Constraint: c must be positive. Constraint: c must not have a kind parameter specified for it. Constraint: The rep-char in the cH form must be of default character type." In the H edit descriptor, c specifies the number of characters following the H. If a processor is capable of representing letters in both upper and lower case, the edit descriptors are without regard to case except for the characters following the H in the H edit descriptor and the characters in the character constants. Delete all of section B2, with subsections, [262:7-263:32] and replace by the following: B.2 Obsolescent features The obsolescent features are those features of Fortran 90 that are redundant and for which better methods are available in Fortran 90. Section 1.6.2 describes the nature of the obsolescent features. The obsolescent features in this International Standard are: (1) Computed GO TO statement - see B.2.1 (2) Statement functions - see B.2.2 (3) DATA statements amongst executable statements - see B.2.3 (4) Assumed length character functions - see B.2.4 (5) Fixed form source - see B.2.5 (6) Assumed size arrays - see B.2.6 (7) CHARACTER* form of CHARACTER declaration - see B.2.7 B.2.1 Computed GO TO statement The computed GO TO has been superseded by the CASE construct, which is a generalized, easier to use and more efficient means of expressing the same computation. B.2.2 Statement functions Statement functions are subject to a number of non-intuitive restrictions and are a potential source of error since their syntax is easily confused with that of an assignment statement. The internal function is a more generalized form of the statement function and completely supersedes it. B.2.3 DATA statements amongst executables The statement ordering rules of FORTRAN 66, and hence of FORTRAN 77 and Fortran 90 for compatibility, allowed DATA statements to appear anywhere in a program unit after the specification statements. The ability to position DATA statements amongst executable statements is very rarely used, is unnecessary and is a potential source of error. B.2.4 Assumed character length functions Assumed character length for functions is an irregularity in the language since elsewhere in Fortran the philosophy is that the attributes of a function result depend only on the actual arguments of the invocation and on any data accessible by the function through host or use association. This facility may be replaced by the use of a subroutine whose arguments correspond to the function result and the function arguments. B.2.5 Fixed form source Fixed form source was designed when the principal machine-readable input medium for new programs was punched cards. Now that new and amended programs are generally entered via keyboards with screen displays, it is an unnecessary overhead, and is potentially error-prone, to have to locate positions 6, 7 or 72 on a line. Free form source was designed expressly for this more modern technology. It is a simple matter for a software tool to convert from fixed to free form source. B.2.6 Assumed-size arrays Assumed-size arrays have been used for a wide variety of purposes in Fortran. The introduction of automatic arrays, assumed-shape arrays and deferred-shape arrays has given significantly increased functionality and allows the programmer to specify these requirements more directly and more securely. B.2.7 CHARACTER* form of CHARACTER declaration Fortran 90 had two different forms of specifying the length selector in CHARACTER declarations. The older form (CHARACTER*char-length) was an unnecessary redundancy. ------------------------------------------------------------------------------ Number: 008 Title: B9/B2 Conflicts with IEEE 754/854 Status: Approved Target date: 95 Last revision: May 94 X3J4 reference: 94-189r2 To: X3J3 94-189r2 page 1 of 2 From: Stan Whitlock Subj: B9/B2 Conflicts with IEEE 754/854 Date: 13-May-1994 Rationale --------- These edits remove perceived conflicts in F90 with the IEC 559 (IEEE 754/854) standard. Technical Description --------- ----------- If a processor supports IEC 559, -0. is distinct from +0. and certain computations like 0./0. or 0.**0. produce results, not errors. The edits below allow the SIGN intrinsic function to distinguish between -0. and +0., allow a -0 in formatted output, and do not disallow 0./0. or 0.**0.. Edits to the Standard ----- -- --- -------- 27:1-3 Delete this text. 27:11+ Add the text: The integer type includes a zero value, which is considered neither negative nor positive. The value of a signed integer zero is the same as the value of an unsigned integer zero. 28:29+ Add the text: The real type includes a zero value, which is generally considered neither negative nor positive. The value of a signed real zero is the same as the value of an unsigned real zero except, possibly, when used as the second argument to the SIGN intrinsic function. 80:1-3 Replace the first two sentences with: The execution of any numeric operation whose result is not defined by the arithmetic used by the processor is prohibited. 80:1-3 Delete the word "also" from the third sentence. 139:23-24 Delete the sentence: However, the processor must not produce a negative signed zero in a formatted output record. 233:5 Replace the line with Result value. Case (i): If B > 0, the value of the result is |A|. Case (ii): If B < 0, the value of the result is -|A|. Case (iii): If B is of type integer and B=0, the value of the result is |A|. Case (iv): If the processor can distinguish between positive and negative real zero, If B is positive real zero, the value of the result is |A|. If B is negative real zero, the value of the result is -|A|. Otherwise, B is of type real, B=0, and the value of the result is |A|. [Notes to Editor: - "Result value." above is bold. - "Case (i)", "Case (ii)", "Case (iii)", and "Case (iv)" above are italic. ] 3:3+ in the new section 1.4.1 (see 94-009 item #1), add a new item: (2) If the processor can distinguish between positive and negative real zero, the behavior of the SIGN intrinsic function when the second argument is negative real zero has been changed by this standard. [End of proposal] ------------------------------------------------------------------------------ Number: 009 Title: CPU time Status: Approved Target date: 95 Last revision: May 94 X3J3 reference: 94-170r5 To: X3J3 94/170r5 From: John Reid Subject: B9/C1 - CPU time Date: 19 May 1994 Rationale This feature is provided to allow the assessment of what processor resources a piece of code consumed during execution. Technical description This feature is provided as an intrinsic subroutine that has a single argument in which the time in seconds is returned. A subroutine is chosen for consistency with DATE_AND_TIME and because all the intrinsic functions of Fortran 90 have a result that is uniquely determined by the values of the arguments. Edits to the standard 188/4. Add: 'The subroutine CPU_TIME returns the processor time consumed during execution.' 192/16+ Add: CPU_TIME (TIME) Processor time. 203/0+ Add: 13.13.24a CPU_TIME (TIME) Description. Returns the processor time. Class. Subroutine. Argument. TIME must be scalar and of type real. It is an INTENT(OUT) argument that is set to a processor-dependent approximation to the processor time in seconds. If the processor cannot return a meaningful time, the value is set to zero. Example. REAL T1,T2 : CALL CPU_TIME(T1) : ! Code to be timed. CALL CPU_TIME(T2) WRITE(*,*) 'Time taken by code was ',T2-T1,' seconds' writes the processor time taken by a piece of code. [Footnote: A processor for which a single result is inadequate (for example, a parallel processor) might choose to provide an additional version for which TIME is an array. The exact definition of the time is left imprecise because of the variability in what different processors are able to provide. The primary purpose is to compare different algorithms on the same computer or discover which parts of a calculation on a computer are the most expensive. The start time is left imprecise because the purpose is to time sections of code, as in the example. Most computer systems have multiple concepts of time. One common concept is that of time expended by the processor for a given program. this may or may not include system overhead, and has no obvious connection to elapsed "wall clock" time. End footnote] ------------------------------------------------------------------------------ Number: 010 Title: Nested WHERE Status: Approved Target date: 95 Last revision: May 94 X3J3 reference: 94-154r2 To: X3J3 From: /parallel Subject: A Second Proposal for Nested WHEREs. ------------------------------------------------------------------- 1. Introduction. The WHERE construct may contain only assignment-stmts in both both F90 and F95. It is the only F90 construct which cannot be named, (R215) and the only construct which cannot contain blocks. F95 adds the FORALL construct in a similar category - it can be named, but it can't contain blocks. It can contain WHERE constructs and other FORALL constructs. This proposal allows WHERE constructs to be named and to con- tain FORALLs and other WHEREs. The result is that the language is more regular, and that some nested IF constructs can be translated to array notation without forming complicated mask expressions.. 2. Details. 2.1 Nested WHEREs The proposal is to remove a restriction of Rule 739 that a where-construct-stmt may not contain a where-construct- stmt. That is a construct of the form WHERE (mask1) vvv...... WHERE (mask2) www.... ELSEWHERE (mask3) xxx.... ENDWHERE ELSEWHERE zzz.... ENDWHERE should be allowed. Thus, not only can WHERE constructs be nested but an ELSE WHERE, syntactically and seman- tically analogous to ELSE, has been introduced. The meaning may be understood by rewrite rules. First rewrite every WHERE statement into a WHERE construct: WHERE(m) WHERE (m) sss becomes sss END WHERE Next eliminate all occurrences of ELSE WHERE(..) WHERE (m1) WHERE (m1) xxx xxx ELSE WHERE (m2) becomes ELSE yyy WHERE (m2) END WHERE yyy END WHERE END WHERE note that xxx & yyy represent any sequences of statements, so long as the original WHERE , ELSEWHERE, and END WHERE match, and the ELSE WHERE is the first ELSE WHERE of the construct (that is yyy may contain additional ELSE WHERE(..) (or ELSEWHERE) statements of the construct.). Next, eliminate ELSEWHERE: WHERE(m) temp = m xxx WHERE (temp) ELSE becomes xxx yyy END WHERE END WHERE WHERE (.NOT. temp) yyy END WHERE Finally, eliminate nested WHERE constructs and statements: WHERE (m1) temp = m1 xxx WHERE (temp) WHERE (m2) xxx yyy becomes END WHERE END WHERE WHERE (temp .AND. (m2)) zzz yyy END WHERE END WHERE WHERE (temp) zzz END WHERE 2.2 WHEREs with nested FORALLs A FORALL within a WHERE may be understood as a shorthand for an omitted enclosing FORALL which describes a mask to be applied to the inner FORALL. Thus, an example, REAL A(100,100), B(100,100),c(100) WHERE (C .NE.0.0) C = 1.0/C FORALL (J=1:99) a(:,J) = (B(:,J) + B(J+1,:)) * C END WHERE is similar to FORALL (J=1:100, C(I) .NE.0.0) C(I) = 1.0/C(I) FORALL (J=1:99) a(I,J) = (B(I,J) + B(J+1,I) * C(I) END FORALL The effect is to constrain all the assignment-stmts in the FORALL to be the same shape as the WHERE mask, just as usual. The arrays on the LHS of the FORALL will be of higher rank than the WHERE mask. 2.3 Edits to the Standard. Page 93. Rules R739 through R743 are replaced by R739a where-construct is where-construct-stmt [where-body-construct]... [ masked-elsewhere-stmt [where-body-construct]...]... [ elsewhere-stmt] [where-body-construct]...]... end-where-stmt R740 where-construct-stmt is [where-construct-name:] WHERE (mask-expr) R740a where-body-construct is where-assignment-stmt or where-stmt or where-construct R740b where-assignment-stmt is assignment-stmt or forall-construct R741 mask-expr is logical-expr R742a masked-elsewhere-stmt is ELSEWHERE (mask-expr) R742b elsewhere-stmt is ELSEWHERE R743 end-where-stmt is END WHERE [where-construct-name] a rule number with the suffix 'a' or 'b' indicates a new or revised rule. Page 93. 7.5.3.1, Add a new constraint ' If the where-construct-stmt is identified by a where-construct-name, the corresponding end-where- stmt must specify the same where-construct-name. If the where-construct-stmt is not identified by a where-construct-name, the corresponding end-where-stmt must not specify a where-construct- name.' Page 93. 7.5.3.2, 1st paragraph, (pink interpretation page) [93:21] add after '... arrays of the same shape.' ' If a where-construct contains a where-stmt, a masked-elsewhere-stmt or another where-construct then each mask-expr within the where-construct must be the same shape.' Page 93. 7.5.3.2, 2nd paragraph [93:25] Replace the last sentence 'Each assignment-stmt...'with ' Each where-construct-stmt acts as if it has a controlling mask. Each statement within a where-construct is evaluated, in sequence, as if it were controlled by WHERE (control mask). The control mask for an outermost WHERE is the mask-expr.. The control mask of an inner WHERE is the conjunction of the mask-expr with the control mask of the enclosing where- construct, masked-elsewhere-stmt, or elsewhere-stmt . Within a where-construct if an ELSEWHERE is encountered the control mask becomes (.NOT. control mask) .AND. mask-expr, if any.' page 93. 7.5.3.2, 5th paragraph. 1st sentence. Replace 'only a WHERE statement or a WHERE construct' with ' only a WHERE statement or an outermost WHERE construct' Page 93, 7.5.3.1 Throughout, replace 'assignment-stmt' with 'where-assignment-stmt' Page 93, 7.5.3.2 Throughout, replace 'assignment-stmt' with 'where-assignment-stmt' Add a footnote ' As the expressions within a forall-construct must conform with the mask-expr the array which receives the result of the forall will be of higher rank than the mask-expr.' ----------------------------------------------------------------------------- Number: 011 Title: Specification Functions Status: Approved Target date: 95 Last revision: May 94 X3J3 reference: 94-173r2 94-173r2 To: X3J3 From: Len Moss Subject: B9/C3 - Specification Functions Note: This proposal makes use of the term "nonconstant specifica- tion expression" in the same way it is currently used in the stan- dard (e.g., to distinguish automatic and nonautomatic data objects). However, this term is not explicitly defined in the standard and the /JOR subgroup believes that the implied defini- tion, namely, a specification expression that is not also a con- stant expression, is incorrect in a number of contexts. As pointed out in 94-127, the formal definition of the term "constant expres- sion" does not appear to serve any useful purpose: the critical definition is that for "initialization expression". As actually used in the document, the phrase "nonconstant specification expres- sion" could better be defined as "a specification expression that is not also an initialization expression". The /JOR subgroup there- fore recommends that one of the following changes be made: 1) pro- vide somewhere (probably in 7.1.6.2) a formal definition of "nonconstant specification expression" in terms of initialization expressions; 2)\x11change the term to something ("noninitialization specification expression"?) that better suggests the correct def- inition; or, 3)\x11fix the concepts of constant and initialization ex- pressions along the lines proposed in 94-127. Proposal Rationale: A significant number of useful applications will be facilitated by the ability to perform more complicated calculations when specify- ing data objects than are permitted with Fortran 90. This will be very substantially achieved by allowing a restricted class of non- intrinsic functions in certain specification expressions. Technical Description: This feature permits a restricted class of user-defined functions, called "specification functions", to be referenced in nonconstant specification expressions. The restrictions are: · the functions must be pure; · the functions must not be internal; · the functions must not be recursive; · the arguments of such functions when used in specification ex- pressions must be restricted expressions; · the functions must not appear in any context which requires a constant specification expression, e.g., any specification not in a subprogram or an interface body, in a common or equiv- alence specification, or a component specification; and, · any object whose specification depends on such a function is an automatic object and hence cannot be saved or initialized. Edits: 5.1 [40/41] Before "If" add the sentence, A specification expression is considered to be noncon- stant if it involves a reference to a specification function. 7.1.6.2 [78/37+] At the beginning of this section, add a new paragraph followed by a footnote: A function is a specification function if it is a pure function, is not an internal function and is not de- fined with the RECURSIVE keyword. {Note: Specification functions are nonintrinsic functions that can be used in specification expressions (7.1.6.2) to de- termine the attributes of data objects. The requirement that they be pure ensures that they cannot have side effects that could affect other objects being declared in the same speci- fication-part. The requirement that they not be internal en- sures that they cannot inquire, via host association, about other objects being declared in the same specification part. Some requirement against direct recursion is necessary: since specification expressions must be evaluated before the first executable statement, there would be no way to break such a recursion. Indirect recursion in specification functions ap- pears to be possible but difficult to implement, and of little value to the user, and so there is a general prohibition against recursive specification functions.} 7.1.6.2 [79/16] Insert before the last item in the numbered list (and renumber the last item) the following new item: (10) A reference to a specification function where each argument is a restricted expression. End Proposal ------------------------------------------------------------------------------ Number: 012 Title: Enable Status: Draft Target date: unspecified Last revision: May 94 X3J3 reference: 94-147r3 To: X3J3 From: John Reid Subject: Enable proposal Date: 16 June 1994 1. RATIONALE If an operator invokes a process (in hardware or in a procedure for a defined operator) and hits a problem with which it cannot deal, such as overflow, it needs to quit and ask the caller to do something else. A simple example of this proposal is ENABLE (OVERFLOW) : ... = X*Y ... HANDLE : END ENABLE If the multiply is intrinsic and an overflow occurs, a transfer of control is made to the block of code following the HANDLE statement. Similarly, if the multiply is a defined operator, it can be arranged that the OVERFLOW signals in comparable circumstances. The handle block may contain very carefully written code that is slow to execute but circumvents the problem, or may arrange for a graceful termination. 2. TECHNICAL SPECIFICATION For dealing with exceptional events, this proposal involves the addition of integer-valued conditions, a new construct, and some new statements. The conditions may be user defined or intrinsic. The intrinsic values are all positive. For the definition of the intrinsic conditions, see the proposed new section 15 at the end of this paper. Also, there are more examples in the proposed new sub-section 8.1.5.5. The enable construct has the general form enable statement enable block [handle statement handle block] end enable statement Nesting of enable constructs is permitted. An enable or handle block may itself contain an enable-construct. Also, nesting with other constructs is permitted, subject to the usual rules for proper nesting of constructs. The enable statement lists the names of the conditions to be handled by the construct. If any of these conditions signals during the execution of the enable block, control is transferred to the handle block. A simple example is the following: ! Example 1 ENABLE (OVERFLOW) ! First try a fast algorithm for inverting a matrix. : HANDLE ! Fast algorithm failed; use slow one. : END ENABLE Here, the code in the enable block takes no precautions against overflow and will usually execute correctly. Should it fail with overflow, the alternative algorithm is used instead. The transfer to the handle block is imprecise in order to allow for optimizations such as vectorization. Any variable that is defined or redefined in a statement of the enable block becomes undefined. In Example 1, a copy of the matrix itself would need to be available for the slow algorithm. The transfer may be made more precise by adding within the enable block a nested enable construct without a handler. If any of the conditions of the inner construct is signaling when its enable statement is executed, control is transferred to the handle block. This reduces the imprecision to the statements within the inner construct or outside it. Adding such a construct to the code of Example 1 gives: ! Example 2 ENABLE (OVERFLOW) ! First try a fast algorithm for inverting a matrix. : ! Code that cannot signal overflow DO K = 1, N ENABLE (OVERFLOW) : END ENABLE END DO ENABLE (OVERFLOW) : END ENABLE HANDLE ! Alternative code which knows that K-1 steps have executed normally. : END ENABLE Note that the enable, handle, and end-enable statements provide effective barriers to code migration by an optimizing compiler. If there is no handler for a signaling condition (for example, if a condition signals outside any enable construct for the condition), a transfer of control as for a return statement takes place in a procedure or as for a stop statement takes place in a main program. The condition continues to signal. When any enable statement is encountered, the conditions it names are tested. If any are signaling, a transfer of control to the next outer handler for a signaling condition (or a return or stop) takes place. This ensures that all the conditions are quiet on entering the enable block. Upon normal completion of the handle block, any of the handled conditions that is signaling is reset to quiet. There is an option on the enable statement to specify that some of the conditions enabled are 'immediate'. Any construct of the enable block that might signal one of the immediate conditions is treated as if it were followed by an enable construct for the condition with an empty body and no handler. An example of such an enable statement is ENABLE, IMMEDIATE (OVERFLOW) For some conditions (mainly those that may require additional code, for example, BOUND_ERROR), the processor is required to signal the condition only within the statements of the enable block. Whether such a condition signals outside any enable block for the condition is processor dependent. There is no requirement to signal such a condition in a procedure that is called from within an enable block. There is a facility for making a specified condition signal with a specified value. This is done with the SIGNAL statement. An example is SIGNAL(OVERFLOW, -3) ! Negative values of intrinsic conditions can be set this way. It causes a transfer to the handler if in an enable block for the condition or a return (stop in a main program) otherwise. This may also be used to set a condition quiet. For example, SIGNAL(ALL, 0) sets all conditions quiet. In this case, there is no transfer of control. In a handler, if it is desired to resignal the signaling conditions, this can be achieved with the resignal statement: RESIGNAL A transfer of control to the next outer handler for a signaling condition (or a return or stop) occurs without the values of the conditions changing. There is a facility for finding the value of a condition. This is done with the CONDITION_INQUIRE statement. An example is CONDITION_INQUIRE(OVERFLOW, I) which stores the value of the overflow condition in the variable I. Another form of the statement: CONDITION_INQUIRE(CHAR_ARRAY) returns the names of the conditions that are signaling in the character array variable CHAR_ARRAY. Each condition has a default integer value with global scope. There is no possibility of name conflict with other entities since condition names can occur only on ENABLE, SIGNAL, and CONDITION_INQUIRE statements. User names are permitted. A future enhancement might allow the declaration of conditions as private to a module and allow the renaming of conditions on the USE statement. If a condition is still signaling when the program stops, the processor must issue a warning on the default output unit. Neither a handle statement nor an end-enable statement is permitted to be a branch target. A handle-block is intended for execution only following the signaling of a condition that it handles, and an end-enable statement is not a sensible target because it would permit skipping the handling of a condition. 3. EDITS TO THE STANDARD 6/18+. Add IEC 559:1989, (also ANSI/IEEE 754-1985, IEEE standard for binary floating-point arithmetic). ....................................................................... 8/45+. Add <> ....................................................................... 10/4-24. Add to R216 (in alphabetic positions) the lines <> <> <> ....................................................................... 12/50. After 'CASE constructs,', add 'ENABLE constructs,'. ....................................................................... 12/53+. Add: (4) Execution of a signal or resignal statement (8.1.5.4) may | change the execution sequence. | (5) Execution of an enable statement (8.1.5.1) may change the execution sequence. ....................................................................... 15/33+ Add <<2.4.8 Condition>> A <> is a default integer flag associated with the occurrence of an exceptional event. The value 0 corresponds to the quiet state and this is its initial value. Nonzero values correspond to signaling states. Negative values can occur only through execution of the SIGNAL statement. There is one value for all scoping units and it may be found by execution of a CONDITION_INQUIRE statement or altered by execution of the SIGNAL statement. [Footnote: The reason for specifying that conditions have integer values is that this leaves open the possibility of providing detailed information about the condition. This will be useful when a procedure (for example, in a library) signals a condition so that it can indicate the cause of the problem. The intrinsic values are forced to be positive so that a negative value can be seen to be created by source code and not by the system.] [Footnote: Although multitasking is not part of Fortran 90, X3J3 has considered the interaction of this proposal with multitasking extensions. Its model is that each virtual processor has a flag for each condition. Condition handling is permissible within a pure procedure. Enable, handle, and end-enable statements act as barriers and a transfer of control takes place if any processor is signaling.] ..................................................................... 22/23+ Add to the Blanks Optional column: END ENABLE ....................................................................... 67/39. After 'terminated', add 'unless the ALLOCATION_ERROR condition is enabled'. ....................................................................... 68/40. After 'terminated', add 'unless the DEALLOCATION_ERROR condition is enabled'. ....................................................................... 80/2. After 'program', add ', except in an enable block for a suitable condition'. ....................................................................... 95/10+ Add (4) ENABLE construct ....................................................................... 95/19. Delete 'three'. ........................................................................ 107/0+. Add <<8.1.5 Condition handling>> A condition has a name with global scope and a default integer value. The value zero corresponds to the normal or 'quiet' state and nonzero values correspond to exceptional circumstances. All conditions have initial value zero. A condition may be intrinsic (15). A condition that is not intrinsic is user defined and can take nonzero values only through execution of a SIGNAL statement. The processor is required to signal an intrinsic condition if the associated circumstance occurs during execution of an intrinsic operation or an intrinsic procedure call specified in the scope of an enable block for the condition. Some conditions are also required to signal when the circumstance occurs outside an enable block, but whether other conditions signal outside an enable block is processor dependent. Which is which is specified in 15. When an intrinsic condition signals, it has a positive value. [Footnote: The proposal allows the in-lining of procedures with no change to the enable constructs. The effect is as if any condition enabled in the calling procedure but not in the called procedure is a condition that always signals.] [Footnote. On many processors, it is expected that some conditions will cause no alteration to the flow of control when they signal and that they will be tested only when the enable block completes or another enable statement is encountered. Thus the overheads of testing the condition are confined precisely to the places where the programmer has requested a test. On other processors, this may be very expensive. They may instead cause a transfer of control to the handler (or a return or stop) as soon as the condition signals or soon thereafter.] [Footnote: If additional code is needed (for example, for integer overflow), this is required only within the scope of the enable block.] <<8.1.5.1. The enable construct>> The ENABLE construct specifies a set of conditions, an enable block, and (optionally) a handle block. The handle block is executed only if execution of the enable block leads to the signaling of one or more of the conditions. R835a <> [ ] R835b <> [:] # # ENABLE [()] # # [,IMMEDIATE ()] R835c <> R835d <> HANDLE [] R835e <> R835f <> END ENABLE [] Constraint: If the of an is identified by an , the corresponding must specify the same . If the of an is not identified by an , the corresponding must not specify an . If the is identified by an , the corresponding must specify the same . Constraint: A condition name must not appear more than once in an . An may be a branch target statement (8.2). [Footnote: Neither a handle statement nor an end-enable statement is permitted to be a branch target. A handle-block is intended for execution only following the signaling of a condition that it handles, and an end-enable statement is not a sensible target because it would permit skipping the handling of a condition.] [Footnote: Nesting of enable constructs is permitted. An enable or handle block may itself contain an enable-construct. Also, nesting with other constructs is permitted, subject to the usual rules for proper nesting of constructs.] Execution of an enable statement causes a transfer of control if any of the conditions specified is signaling. If the enable statement is nested in an enable block for one of these signaling conditions and the block has a handler, the transfer is to the next outer such handler. Otherwise, it is as for return if in a subprogram, or a stop | if in a main program. The values of the conditions are not altered. The value of each condition enabled by the construct is set to the quiet value upon completion of execution of the . If a transfer of control out of the occurs, the conditions retain their values. <<8.1.5.2 Enable construct>> Execution of an begins with the first executable construct of the , and continues to the end of the block unless a branching statement is executed or an enabled condition is signaled. If a condition enabled by the construct is signaling on completion of execution of the , control is transferred to the . Transfer of control to the may also take place sooner after the signaling of the condition. If the contains no nested enable constructs for the condition, any variable that might be defined or redefined by execution of a statement of the enable block is undefined. If the contains one or more nested enable constructs for the condition, the variables that are undefined are those that might be defined or redefined by execution of a certain subset of the statements of the enable block. The subset consists of statements that lie within an enable block for the condition but do not lie within any enable constru Any construct of the enable block that might signal one or more of the conditions in the immediate list on the enable statement is treated as if it were followed by an for the condition with an empty block and no handler. Execution of the completes the execution of the . [Footnote: The transfer to the handle block is imprecise in order to allow for optimizations such as vectorization. As a consequence, some variables become undefined. In Example 3 of 8.1.5.6, a copy of the matrix itself would need to be available for the slow algorithm.] If no condition enabled by the construct is signaling on completion of execution of the , the execution of the entire construct is complete. [Footnote: Nested enable constructs without handlers can be employed to reduce the imprecision of an interrupt. Note that enable, handle, and end-enable statements provide effective barriers to code migration by an optimizing compiler.] <<8.1.5.3 Signaling conditions that are not enabled>> A processor may signal a condition while executing a statement that is not in an enable block for the condition. If in a subprogram, a return is executed without alteration of the values of the conditions. If in a main program, a stop is executed and the processor must issue a warning on the default output unit. [Footnote: On return to the caller, the condition will be signaling. If the invocation is within an enable block for the condition, there will be a transfer to the handler (or a return or stop), but not necessarily until the execution of the block is complete. If the invocation is not within an enable block for the condition, there may be a return (or stop) at once, or the processor may continue executing.] <<8.1.5.4 Signal and resignal statements>> R835g <> SIGNAL (,) Constraint: If the condition name is DEFAULT, IO, FLOATING, INTEGER, or ALL, the must be the literal constant 0. The SIGNAL statement changes the value of the condition it names to that of the expression it contains. If the value is nonzero, it causes a transfer of control. If the statement is in a handling enable block for the condition, the transfer is to the handler of the next outer such enable construct. Otherwise, it is as for a return if in a subprogram, or a stop if in a main program. R835h <> RESIGNAL The RESIGNAL statement causes a transfer of control if any condition is signaling. If the statement is in an enable block for a signaling | condition and the block has a handler, the transfer is to the next | outer such handler. Otherwise, it is as for a return if in a | such enable construct. Otherwise, it is as for a return if in a subprogram, or a stop if in a main program. The values of the conditions are not altered. [Footnote: A RESIGNAL statement has the same interpretation as the pair | of statements | ENABLE (ALL) | END ENABLE ] | <<8.1.5.5 Examples of ENABLE constructs>> Example 1: MODULE MATRIX ! Module for matrix multiplication of real arrays of rank 2. INTERFACE OPERATOR(.mul.) | MODULE PROCEDURE MULT END INTERFACE CONTAINS FUNCTION MULT(A,B) REAL, INTENT(IN) :: A(:,:),B(:,:) REAL MULT(SIZE(A,1),SIZE(B,2) ENABLE (INTRINSIC, OVERFLOW) MULT = MATMUL(A, B) HANDLE SIGNAL(MULT, 1) END ENABLE END FUNCTION MULT END MODULE MATRIX This module provides matrix multiplication for real arrays of rank 2. If there is insufficient storage for the necessary temporary array, it signals the condition INSUFFICIENT_STORAGE. If an INTRINSIC or OVERFLOW condition occurs, it signals the condition MULT with value 1. Example 2: IO_CHECK: ENABLE (IO_ERROR, END_OF_FILE) : READ (*, '(I5)') I READ (*, '(I5)', END = 90) J : 90 J = 0 HANDLE CONDITION_INQUIRE(END_OF_FILE,K) IF (K/=0) THEN WRITE (*, *) 'Unexpected END-OF-FILE when reading ', & 'the real data for a finite element' ELSE CONDITION_INQUIRE(IO_ERROR,K) IF (K /= 0) THEN WRITE (*, *) 'I/O error when reading ', & 'the real data for a finite element' END IF END IF STOP END ENABLE IO_CHECK In this example, if an input/output error occurs in either of the READ statements or if an end-of-file is encountered in the first READ statement, the appropriate condition will be signaled and the handler will receive control, print a message, and terminate the program. However, if an end-of-file is encountered in the second READ statement, no condition will be signaled and control will be transferred to the statement indicated in the END= specifier. Example 3: ENABLE (DEFAULT) ! First try the "fast" algorithm for inverting a matrix: MATRIX1 = FAST_INV (MATRIX) HANDLE ! "Fast" algorithm failed; try "slow" one: SIGNAL (DEFAULT, 0) ENABLE (ALL) MATRIX1 = SLOW_INV (MATRIX) HANDLE WRITE (*, *) 'Cannot invert matrix' STOP END ENABLE END ENABLE In this example, the function FAST_INV may cause an condition to signal. If it does, another try is made with SLOW_INV. If this still fails, a message is printed and the program stops. Note the use of nested enable blocks. Example 4: ENABLE (OVERFLOW) ! First try a fast algorithm for inverting a matrix. : ! Code that cannot signal overflow DO K = 1, N ENABLE(OVERFLOW) : END ENABLE END DO ENABLE(OVERFLOW) : END ENABLE HANDLE ! Alternative code which knows that K-1 steps have executed normally. : END ENABLE Here the code for matrix inversion is in line and the transfer is made more precise by adding to the enable block two enable constructs without handlers. Example 5: The following subroutine finds a zero of on an interval []. It is limited to take one second of real time as measured by the system clock. If it fails to obtain the requested accuracy after this time, the condition SOLVER signals with the value -1. SUBROUTINE ZERO_SOLVER (A, B, X, TOLERANCE, F) REAL A, B, X, TOLERANCE INTERFACE; REAL FUNCTION F(X); REAL X; END INTERFACE INTEGER COUNT, RATE, START ! Local variables CALL SYSTEM_CLOCK(START, RATE) : ! The following code is executed every iteration CALL SYSTEM_CLOCK(COUNT) ! If time has run out, return, signaling condition SOLVER. IF (COUNT > START+RATE) THEN SIGNAL (SOLVER,-1) END IF : END SUBROUTINE ZERO_SOLVER The application code handles the exception in a way that only it knows. An example is: : ENABLE(SOLVER) CALL ZERO_SOLVER (A, B, X, TOLERANCE, F) HANDLE ! Exceeded the amount of time, TIME. Fix up and go on. : END ENABLE : Example 6: REAL FUNCTION CABS (Z) COMPLEX Z ! Calculate the complex absolute value, using a scaled algorithm ! if the straightforward calculation underflows or overflows. Set the ! overflow condition to the value -1 if the result is too large to ! be representable. REAL S, ZI, ZR INTRINSIC REAL, AIMAG, SQRT, ABS, MAX ZR = REAL(Z) ZI = AIMAG(Z) quick: ENABLE(OVERFLOW, UNDERFLOW) ! This is the quick and usual calculation. CABS = SQRT(ZR**2 + ZI**2) HANDLE quick ! Will try again using a scaled equivalent method. S = MAX(ABS(ZR),ABS(ZI)) SIGNAL (OVERFLOW,0) ; SIGNAL (UNDERFLOW,0) slow: ENABLE(OVERFLOW, UNDERFLOW) CABS = S*SQRT( (ZR/S)**2 + (ZI/S)**2 ) HANDLE slow CONDITION_INQUIRE(OVERFLOW,K) IF (K/= 0) THEN ! The result is too large to be representable. SIGNAL(OVERFLOW, -1) ELSE CONDITION_INQUIRE(UNDERFLOW,K) IF (K/= 0) CABS = S END IF END ENABLE slow END ENABLE quick END FUNCTION CABS This illustrates the setting of a special condition value when the problem really has a result that overflows. Example 7: MODULE LIBRARY ... CONTAINS SUBROUTINE B ... X = Y*Z(I) ! No condition enabled. IF(X>10.)SIGNAL(LIBRARY_ERROR, 1) ... END SUBROUTINE B END MODULE LIBRARY SUBROUTINE A USE LIBRARY ENABLE (OVERFLOW, LIBRARY_ERROR) CALL B HANDLE ... END ENABLE END SUBROUTINE A This illustrates the use of a library module that may signal the condition LIBRARY_ERROR. The signal statement causes a transfer to the handler in the calling subroutine A. This also illustrates the effect of an intrinsic condition that is not enabled. An overflow in Y*Z(I) would cause OVERFLOW to signal and hence a transfer to the handler in the calling subroutine A. An out-of-range subscript value I might or might not signal BOUND_ERROR, but it would not be handled by subroutine A. ....................................................................... 107/5. After '' add 'an ,'. ....................................................................... 122/17-18. Replace sentence by If an error condition (9.4.3) occurs during execution of an input/output statement that lies in an enable block for the IO_ERROR condition or contains an ERR= specifier: ....................................................................... 122/25. After 'continues with' add 'the handle block or' ....................................................................... 122/27-28. Replace sentence by If an end-of-file condition (9.4.3) occurs and no error condition (9.4.3) occurs during execution of an input/output statement that lies in an enable block for the END_OF_FILE condition or contains an END= specifier: ....................................................................... 122/34. After 'continues with' add 'the handle block or' ....................................................................... 122/37-38. Replace sentence by If an end-of-record condition (9.4.3) occurs and no error condition (9.4.3) occurs during execution of an input/output statement that lies in an enable block for the END_OF_RECORD condition or contains an EOR= specifier: ....................................................................... 123/6. After 'continues with' add 'the handle block or' ........................................................................ 125/10. Before 'contains' add 'is not in a enable block for the IO_ERROR condition and '. ........................................................................ 125/11. Before 'contains' add 'is not in a enable block for the END_OF_FILE condition and '. ........................................................................ 125/13. Before 'contains' add 'is not in a enable block for the END_OF_RECORD condition and '. ........................................................................ <<15. CONDITIONS>> In this section, the conditions supported by the standard and a statement for obtaining the value of a condition are specified. The CONDITION_INQUIRE statement returns the value of a condition. R835i <> CONDITION_INQUIRE (, # # [STAT=]) <> CONDITION_INQUIRE () R835j <> Constraint: The condition name must not be DEFAULT, IO, FLOATING, INTEGER, or ALL. Constraint: The must be an array. The STAT= variable is defined with the value 0 if the condition named is quiet and a nonzero value otherwise. Negative values can occur only following execution of a SIGNAL statement. The is defined with the names of signaling conditions and blanks according to the rules of default assignment. If there are conditions signaling, the first elements are defined with the names of these conditions and the remaining elements are given the value blank. If there are more signaling conditions than the length of the array, all elements are defined with condition names and which are chosen is processor dependent. <<15.1 User condition>> If a condition is not intrinsic, it is a user condition. Such a condition can be set only by a SIGNAL statement. <<15.2 Storage and addressing conditions>> ALLOCATION_ERROR This occurs when the processor is unable to perform an allocation requested by an ALLOCATE statement (6.3.1) containing no STAT= specifier. It is not signaled by an ALLOCATE statement containing a STAT= specifier. The signaling values are the same as the STAT values. It signals outside enable blocks. DEALLOCATION_ERROR This occurs when the processor detects an error when executing a DEALLOCATE statement (6.3.1) containing no STAT= specifier. It is not signaled when executing a DEALLOCATE statement containing a STAT= specifier. The signaling values are the same as the STAT values. It signals outside enable blocks. INSUFFICIENT_STORAGE This indicates that the processor is unable to find sufficient storage to continue execution. It may occur prior to the execution of the first executable statement of a main program or procedure and it may occur during the execution of an executable statement. It need not signal if ALLOCATION_ERROR signals. It signals outside enable blocks. BOUND_ERROR This occurs when an array subscript, array section subscript, or substring range violates its bounds. This does not include violations of the requirements derived from the size of an assumed-size array. Whether it signals outside enable blocks is processor dependent. SHAPE This occurs when an array operation or assignment does not conform in shape. Whether it signals outside enable blocks is processor dependent. MANY_ONE This occurs when a many-one array section (6.2.2.3.2) appears on the left of the equals in an assignment statement or as an input item in a READ statement. Whether it signals outside enable blocks is processor dependent. NOT_PRESENT This occurs when a dummy argument that is not present is accessed as if it were present; that is, when one of the restrictions of 12.5.2.8 is violated. Whether it signals outside enable blocks is processor dependent. UNDEFINED This occurs when a value that is required for an operation is detected by the processor to be undefined. Whether it signals outside enable blocks is processor dependent. [Footnote: This wording is intended to allow the processor to be as thorough as it chooses with respect to the detection of undefined values.] <<15.3 Input/output conditions>> IO_ERROR This occurs when an input/output error (9.4.3) is encountered in an input/output statement containing no IOSTAT= or ERR= specifier. It is not signaled when executing an input/output statement containing an IOSTAT= or ERR= specifier. The signaling values are the same as the IOSTAT values. It signals outside enable blocks. END_OF_FILE This occurs when an end-of-file condition (9.4.3) is encountered in an input statement containing no IOSTAT= or END= specifier. It is not signaled when executing an input statement containing an IOSTAT= or ERR= specifier. It signals outside enable blocks. END_OF_RECORD This occurs when an end-of-record condition (9.4.3) is encountered in an input statement containing no IOSTAT= or EOR= specifier. It is not signaled when executing an input statement containing an IOSTAT= or ERR= specifier. It signals outside enable blocks. <<15.4 Floating-point conditions>> OVERFLOW This condition occurs when the result for an intrinsic real or complex operation has a very large processor-dependent absolute value. It signals outside enable blocks. Enabling INTRINSIC may cause this condition to signal. UNDERFLOW This condition occurs when the result for an intrinsic real or complex operation has a very small processor-dependent absolute value. A processor that does not conform to IEC 559:1989 is required to set this condition when requested to do so by a SIGNAL statement, but is not required to set it otherwise. Whether it signals outside enable blocks is processor dependent. DIVIDE_BY_ZERO This condition occurs when a real or complex division has a nonzero numerator and a zero denominator. It signals outside enable blocks. INEXACT This condition occurs when the result of a real or complex operation is not exact. A processor that does not conform to IEC 559:1989 is required to set this condition when requested to do so by a SIGNAL statement, but is not required to set it otherwise. Whether it signals outside enable blocks is processor dependent. INVALID This condition occurs when a real or complex operation is invalid. A processor that does not conform to IEC 559:1989 is required to set this condition for real or complex division of zero by zero and when requested to do so by a SIGNAL statement, but is not required to set it otherwise. Whether it signals outside enable blocks is processor dependent. <<15.5 Integer conditions>> INTEGER_OVERFLOW This condition occurs when the result for an intrinsic integer operation has a very large processor-dependent absolute value. Whether it signals outside enable blocks is processor dependent. INTEGER_DIVIDE_BY_ZERO This condition occurs when an integer division has a zero denominator. Whether it signals outside enable blocks is processor dependent. <<15.6 Intrinsic procedure condition>> INTRINSIC This condition indicates that an intrinsic procedure has been unsuccessful. An unsuccessful intrinsic procedure may signal other conditions. Whether it signals outside enable blocks is processor dependent. If an intrinsic procedure is an actual argument in a procedure call within an enable block for the INTRINSIC condition, the condition must signal if the procedure is invoked through the argument association. <<15.7 Combination conditions>> Each of the following conditions may be specified on an enable statement or a signal statement and is equivalent to specifying a list of conditions. DEFAULT This condition is equivalent to the list: ALLOCATION_ERROR, DEALLOCATION_ERROR, INSUFFICIENT_STORAGE, IO_ERROR, END_OF_FILE, END_OF_RECORD, OVERFLOW, DIVIDE_BY_ZERO, INTEGER_DIVIDE_BY_ZERO, INTRINSIC, any user-defined condition. IO This condition is equivalent to listing all the input/output conditions. FLOATING This condition is equivalent to listing all the floating-point conditions. INTEGER This condition is equivalent to listing the two integer conditions. ALL This condition is equivalent to listing all the conditions.