J3/05-009r1
Date: 14-Mar-2005
To: J3
From: JOR/Stan Whitlock
Subject: 009 - Features under consideration by J3 for F03+
At J3 meeting #170, the F03+ New Features spreadsheet 04-423r1
showed that 31 tasks were "done". The papers specifying the
specifications and syntax for these features are gathered here,
using the form specified by WG5 for a Journal of Requirements
entry, in J3 standing document 009.
At J3 meeting #171, the F03+ New Features spreadsheet 05-145r3
showed that 18 more tasks were "done". The papers specifying the
specifications and syntax for those features are added here,
finalizing the 009r1 for WG5 consideration at the J3 #172/WG5
joint meeting in May-2005 in Delft.
------------------------------------------------------------------
009 - Features under consideration by J3 for F03+
[Keep this text document to 70 characters per line]
Repos Impact ABC: J3 Prior J3 F03+ New Features
itory # on Std Rating ity Brief Description
J3-001 3 B 9 Stop - exit code
J3-002 3 B 1 Get logical I/O unit number
J3-003 4 C Execute External program intrinsic
J3-004 4 B 5 STORAGE_SIZE intrinsic {cf N1539}
J3-005 3 B 7 C_sizeof
J3-006 3 B 7 Finding Logical & Character Kinds
J3-007 4 B 0 Construct names Local to Construct
J3-008 3 A Rewrite attribute requirements
J3-009 5 B 5 Avoid obtaining a logical unit for
opening
J3-010 3 B 13 Allow empty CONTAINS part
J3-011 5 C Coroutines (again)
J3-012 5 B 6 Allocatable/Pointer in Generic Resolve
J3-013 4 B 1 Internal Procedures as actual args
J3-014 6 A Parameterized Modules
J3-015 4 B 3 Updating Complex parts
J3-016 4 C Disassoc/dealloc actual => not Present
J3-017 4 B 8 Default for Optional Dummy
J3-018 4 C Non-null Initial Targets
J3-019 4 A Math Intrinsics: complex trig
J3-020 3 A Type( Intrinsic-type)
J3-021 4 C Resolve generic without invoking a
procedure or evaluating arguments
J3-022 4 B 0 Polymorphic allocatable in
intrinsic assignment
J3-023 3 B 10 Size/shape of Parameter Array
J3-024 3 B 8 Exit from any labelled Construct
J3-025 3 B 8 Name Optional on END module &
internal subprog
J3-026 3 B 3 Atan/Atan2
J3-027 3 A Ascii in LGE etc
J3-028 3 B 7 Public #116: Forward Allocatable
J3-029 3 B 2 More information about GET_COMMAND
[_ARGUMENT] failure
J3-030 3 C Simplified Kind Selection
J3-031 4 B 1 .ANDTHEN. & .ORELSE.
J3-032 3 B 5 Findloc
J3-033 3 C Compiler Version
J3-034 3 B 10 Mold on Allocate
J3-035 3 B 6 Proposed f2k+ MTE on semicolons
J3-036 4 C Use, Except
J3-037 4 B 6 Pointers and Targets
J3-038 4 B 10 Libm: Bessel, erf, gamma, hypot
J3-039 4 B 2 Rank > 7
J3-040 4 B 6 Compute if actual arg is present
J3-041 4 B 6 Interoperability of pointers,
allocatables, and assumed-shape
arrays
J3-042 4 B 6 Interoperability of optional arguments
J3-043 5 A Pointers to contiguous mem
J3-044 4 B 6 New Intents
J3-045 5 A Same Assumed Shape declaration
J3-046 5 A DO CONCURRENT construct
J3-047 7 B 2 TYPELESS objects
J3-048 4 B 1 Writing Comma Separated Value CSV
files
J3-049 4 B 1 Select between expressions
- Impact on Std: using John Reid's scale in N1594:
3: very minor technical change
4: minor technical change
5: takes > 2 J3 meetings to do
6: takes > 1 year to do
7: takes > 2 years to do
- ABC: J3 Rating: at J3 meeting #171, J3 prioritized for WG5:
A=must do
B=may do if there is time
C=no resources to be applied
didn't count undecided
- Priority: tasks rated B were given a priority order, larger
to be done first
------------------------------------------------------------------
Number: J3-001
Title: Enhanced STOP
Submitted By: J3
Status: Specification complete
References: 04-007 8.4 STOP Statement page 170
04-107, 04-319r2
Basic Functionality:
Trivially enhance the STOP statement for modern processors
Rationale:
The current STOP statement is vaguely defined, and has not been
updated in accordance with modern practice. Furthermore, its
syntax is peculiarly limited, going back to Fortran 66 days.
Estimated Impact:
At 167, J3/JoR estimated the impact as "Trivial". This is
recorded in 04-265r1.
Discussion:
Modern practice suggests that
(a) the stop code should be written to the standard error unit
(b) an integer stop code should be returned as the process exit
status.
There are four peculiarities of STOP syntax:
(1) An integer stop code is limited to 5 digits.
(2) An integer stop code must be a literal constant, it cannot
be a named constant.
(3) A stop code must be a literal or named constant, it cannot
be a constant (i.e. initialization) expression.
(4) A stop code must be constant, it cannot be a non-constant
expression.
This paper advocates lifting all of these restrictions. Lifting
all of them probably has less impact (or at least no more impact)
than releasing some of them, as the processor can then simply use
its normal expression evaluation mechanism.
Detailed Specification:
(1) The stop code shall be allowed to be a scalar initialization
expression of type default integer or default character.
(2) Recommend that the stop code be displayed on ERROR_UNIT.
(3) Recommend that if the stop code is of integer type, it should
be used as the process exit status (if the processor even has
such a concept).
(4) Note that the processor might use only a portion of such a
stop code for the exit status.
History:
Paper 04-102 meeting 167 Submitted
04-319r2 169 Accepted as complete
------------------------------------------------------------------
Number: J3-002
Title: GET_IO_UNIT
Submitted By: J3
Status: Specification complete
References: 04-107, 04-186, 04-328
Basic Functionality:
Add an procedure to ISO_FORTRAN_ENV to return a logical
unit number which may be opened.
Rationale:
Logical unit numbers are processor-dependent, some method
of getting one should be supported.
Some programs (for example, multithreaded programs)
may want units to be distributed according to a rule
(for example, 1000 times thread number plus offset).
Thus, some flexibility should be part of this intrinsic.
Estimated Impact:
The impact was estimated by J3/JoR at 167 as Trivial.
Detailed Specification:
See paper 04-327 regards possible renumbering
of 13.8.2. These edits assume that paper passes.
[360:33++] Add:
"13.8.2.2.x GET_IO_UNIT( UNIT, [ NOTUNIT, MINUNIT,
MAXUNIT, IOSTAT, IOMSG ] )
*Description.* Return values that exist,
are not connected to an external file,
and can be connected to an external file.
*Class.* Subroutine.
*Arguments.*
UNIT shall be of type integer and may be of
any rank. It is an INTENT(OUT) argument. It is
assigned values of logical
units that exist, are not connected to an
external file, and can be connected to an
external file. It shall not be assigned a value
equal to INPUT_UNIT, OUTPUT_UNIT or ERROR_UNIT.
If it is scalar, one value is
returned; if it is an array, SIZE(UNIT) unique
values are returned.
NOTUNIT shall be of type integer. It shall
(optional) be a scalar or a rank 1 array. It is
an INTENT(IN) argument. The value of UNIT,
or an element of UNIT if it is an array,
shall not be equal to the value of NOTUNIT,
or any element of NOTUNIT if it is an array.
MINUNIT shall be a scalar of type integer.
(optional) It is an INTENT(IN) argument. The value
of UNIT, or an element of UNIT if it is
an array, shall not be less than the value
of MINUNIT.
MAXUNIT shall be a scalar of type integer.
(optional) It is an INTENT(IN) argument. The value
of UNIT, or an element of UNIT if it is
an array, shall not be greater than the
value of MAXUNIT.
IOSTAT shall be a scalar of type default integer.
(optional) It is an INTENT(OUT) argument. It is
assigned the value zero if the variable
associated with UNIT contains valid
values and assigned a
processor-dependent positive value otherwise.
IOMSG shall be a scalar of type default character.
(optional) It is an INTENT(INOUT) argument. It is
assigned a processor-dependent error message
if the value of the variable associated with
the IOSTAT argument indicates an error
occurred. Otherwise, its value is unchanged."
History:
Paper 04-107 meeting 167 Submitted {same as 04-186}
04-328 168 Accepted as complete
------------------------------------------------------------------
Number: J3-003
Title: EXECUTE_COMMAND_LINE
Submitted By: J3
Status: Specification complete
References: 04-106, 04-329r3
Basic Functionality:
Add a procedure to ISO_FORTRAN_ENV
to cause an external program to execute.
Rationale:
Most processors provide a means to execute an external
program, but the syntax varies. Furthermore, some processors
may support only synchronous execution of external programs,
so this processor limitation must be taken into account.
Some programs may want to execute another program
to generate an input file or to operate jointly via
a pipe, thus program control over synchronous versus
asynchronous execution should be supplied to some extent.
Estimated Impact:
The impact was estimated by J3 at 167 as Small.
Detailed Specification:
Executes a command line externally to the program.
Whether the command line is interpreted by a shell
is unspecified. Require synchronous execution and
allow asynchronous execution. If synchronous execution,
allow recovery of the executed process exit status.
Allow processor-dependent error conditions.
See paper 04-327 regards possible renumbering
of 13.8.2. These edits assume that paper passes.
[360:33++] Add:
"13.8.2.2.x EXECUTE_COMMAND_LINE( COMMAND, [ WAIT,
EXITSTAT, CMDSTAT, CMDMSG ] )
*Description.* Execute the command line identified
by the string COMMAND. The processor must
support synchronous and may support
asynchronous execution of the external program.
*Class.* Subroutine.
*Arguments.*
COMMAND shall be of type default character and
shall be a scalar. It is an INTENT(IN)
argument. It identifies the command line
to be executed. The interpretation is
processor-dependent.
WAIT shall be of type default logical and shall
(optional) be a scalar. It is an INTENT(IN) argument.
When present and true, EXECUTE_COMMAND_LINE
returns after the indicated command line
has completed execution. When present and
false, EXECUTE_COMMAND_LINE returns after
the indicated command line has started
execution. When not present, the effect is
as if present with a value of true.
EXITSTAT shall be of type default integer and shall
(optional) be a scalar. It is an INTENT(INOUT) argument.
It shall not be present if WAIT is
present with a value of false. If WAIT is
present with a value of true, the value of
EXITSTAT is the processor-dependent exit
status of the command line, if available.
Otherwise, the value is unchanged.
CMDSTAT shall be of type default integer and shall
(optional) be a scalar. It is an INTENT(OUT) argument.
It is assigned the value zero if
no error occurred during EXECUTE_COMMAND_LINE
and assigned a processor-dependent
positive value otherwise. If an error occurs
and CMDSTAT is not present, execution of
the program terminates. If the processor
does not support the concept of command
lines, the value is 1.
CMDMSG shall be of type default character and shall
(optional) be a scalar. It is an INTENT(INOUT) argument.
It is assigned a processor-dependent error
message if the value of the variable
associated with the CMDSTAT argument
indicates an error occurred. Otherwise,
the value of CMDMSG is unchanged."
History:
Paper 04-106 meeting 167 Submitted
04-329r3 169 Accepted as complete
------------------------------------------------------------------
Number: J3-004
Title: STORAGE_SIZE
Submitted By: J3
Status: Specification complete
References: 04-120, 04-342
Basic Functionality:
Add a procedure to ISO_FORTRAN_ENV
to return the size in bits of its argument.
Rationale:
There are situations where a program needs to know
the size of an entity.
Estimated Impact:
The impact was estimated by J3 at 167 as Small.
Detailed Specification:
A procedure to return the size in bits of its argument.
See paper 04-327 regards possible renumbering
of 13.8.2. These edits assume that paper passes.
[125:41+] Add list item
"(4+) the intrinsic module function STORAGE_SIZE,"
[360:33+++] Add section
"13.8.2.2.x STORAGE_SIZE (X [, KIND])
*Description.* Returns the storage size in bits for a
nonpointer nonallocatable scalar
of the declared type of X.
*Class.* Inquiry function.
*Arguments.*
X may be of intrinsic or derived type. It
shall not be polymorphic. If it is
of derived type, that type shall be
a SEQUENCE or interoperable type and
shall have no allocatable ultimate
components. If its type has
any deferred type parameters, it shall
be a pointer that is associated or
an allocatable object that is
allocated. It may be a scalar or an array.
KIND (optional) shall be a scalar integer initialization
expression.
*Result Characteristics.* Integer scalar.
If KIND is present, the kind
type parameter is that
specified by the value
of KIND; otherwise, the kind
type parameter is that
of default integer type.
*Result Value.* The result value is the size in bits
of the storage unit (16.4.3.1)
in a storage association context
for a nonpointer nonallocatable scalar
with the declared type and
type parameters of X.
*Example.* STORAGE_SIZE(1.0) returns the number of bits
required to store an entity of type default
real."
History:
Paper 04-120 meeting 167 Submitted {also N1539}
04-342 169 Accepted as complete
------------------------------------------------------------------
Number: J3-005
Title: C_SIZEOF
Submitted By: J3
Status: Specification complete
References: 04-104, 04-344r1
Basic Functionality:
Add a procedure to ISO_C_BINDING to return the size of its
argument as per C sizeof.
Rationale:
There are situations where a program needs to know
the size of an entity, as expressed in C.
Estimated Impact:
The impact was estimated by J3 at 167 as Small.
Detailed Specification:
A procedure to return the size of its argument as per C.
[125:41+] Add list item
"(4++) the intrinsic module function C_SIZEOF,"
[395:31+++] (after the Note) Add section
"15.1.2.6 C_SIZEOF (X)
*Description.* Returns the size, as defined
by the C sizeof operator (Section
6.5.3.4 of the C International Standard),
of the argument X.
*Class.* Inquiry function.
*Arguments.*
X X shall have interoperable type and type
parameters. It may be a scalar or an array
that is not assumed-size.
*Result Characteristics.* Integer scalar
of kind C_SIZE_T (15.2.1).
*Result Value.* The result value is the size of X
as defined by the sizeof operator (Section
6.5.3.4 of the C International Standard)
of the companion C processor. If
the companion processor is not a C processor,
the result value is processor dependent."
History:
Paper 04-104 meeting 167 Submitted
04-344r1 169 Accepted as complete
------------------------------------------------------------------
Number: J3-006
Title: Find all available logical and character kinds
Submitted By: J3
Status: Specification complete
References: 04-121, 04-346r2
Basic Functionality:
Add constants to iso_fortran_env which specify
all available logical kind values and
all available character kind names.
Rationale:
A program (subject or not to preprocessing) or
an automatic code generator may have a preferred kind
or a preferred ranking of possibly available kinds
for entities of logical and character type. Currently,
the only means available is to read the documentation
and manually add the specific values needed.
For example, a very large frequently used but infrequently
updated logical array may be best expressed as an array
of the smallest kind of logical. Default logical may exhaust
the processor's fastest cache, leaving no space for numerical
data. What is the smallest logical available?
There is no automatically available answer now.
Estimated Impact:
The impact was estimated by JoR at 167 to be trivial.
Only iso_fortran_env is affected.
Detailed Specification:
[360:4a+]
"13.8.2.1- CHARACTER_KIND_NAMES
The values of the default character rank 1 array
CHARACTER_KIND_NAMES are the names, when any trailing
blanks are removed, which may be passed
to the SELECTED_CHAR_KIND procedure to obtain
a valid kind value.
The lower bound of CHARACTER_KIND_NAMES is one; the size
of CHARACTER_KIND_NAMES is the number of character names
supported by the processor. The names are stored
in non-decreasing order of storage size of objects
of the corresponding kind."
[360:26+] Add
"13.8.2.6+ LOGICAL_KIND_VALUES
The values of the default integer rank 1 array
LOGICAL_KIND_VALUES are the kind values of all available
logical kinds.
The lower bound of LOGICAL_KIND_VALUES is one; the size
of LOGICAL_KIND_VALUES is the number of logical kind
values supported by the processor. The values are
stored in non-decreasing order of storage size
of objects of the corresponding kind."
History:
Paper 04-121 meeting 167 Submitted
04-346r2 169 Accepted as complete
------------------------------------------------------------------
Number: J3-007
Title: Construct Name Local to Construct
Submitted By: J3
Status: Specification complete
References: 04-158, 04-348r1
Basic Functionality:
Make a construct name be local to its construct.
Rationale:
Construct names are only referenced from within the construct.
Therefore, it makes sense to use a construct scope for the name.
Further, within a local scope, a construct name might naturally
be desirable more than once. For example, within a local scope,
an if-block might naturally be named "check_iostat" following
more than one statement containing an iostat specifier, or more
than one do-construct might be naturally named "all_rows",
"all_columns", or "all_planes", etc.
Of course, for cycle and exit to work properly, nested constructs
must all have names unique within the nest.
Estimated Impact:
3 or 4.
Detailed Specification:
(1) Define a construct name to have construct scope.
(2) Remove construct names from all local entity classes, so that
it can be the same as any local name and any global name.
(3) Nested constructs shall not have the same name. (Note: after
removal from local entities, this needs to be explicitly stated
in the standard.)
Incomplete Illustrative Edits:
[406:4-5] remove "named constructs,"
[409:29+] add new paragraph
"The name of a named construct has a scope of that
construct. It may be the same as any local identifier or
global identifier. The of a contained named
construct shall not be the same as a of any
of its containing named constructs."
History:
Paper 04-158 meeting 167 Submitted
04-348r1 169 Accepted as complete
------------------------------------------------------------------
Number: J3-008
Title: Rewrite attribute requirements
Submitted by: Malcolm Cohen
Status: Specification complete
References: 04-359
Basic Functionality:
None.
Rationale:
The current method of specifying the requirements on various
attributes, such as EXTERNAL and POINTER, is too hard to
understand and too prone to error.
Estimated impact:
Non-trivial Editorial.
Detailed Specification:
Rewrite the attribute specification parts of chapters 5 and 12
so that
(1) the syntax just says what attribute it provides
(2) there is a separate attribute section which
(a) contains the requirements (like "must be a dummy
argument for VALUE")
(b) describes the effects.
History:
Paper 04-359 meeting 169 Submitted
04-359 170 Accepted as complete
------------------------------------------------------------------
Number: J3-009
Title: IO_UNIT standard derived type
Submitted By: J3
Status: Specification complete
References: 04-369
Requirements:
Have a mechanism for i/o units that
- does not confuse i/o units with integers (improved
abstraction)
- does not require the user to manage their use (ease of use)
- avoids clashes between user-written code and existing
third-party libraries
- avoids race conditions in multi-threaded programs, without
requiring the routine being used in a multi-threaded program
to have different code (viz explicit calls to locking routines)
from when it is being used without a threading library.
Basic Functionality:
Add a derived type to ISO_FORTRAN_ENV to represent an i/o unit.
Allow values of this type to be used everywhere that a unit number
can be used.
Rationale:
Logical unit numbers are processor-dependent, managing their
use is difficult. Integer values are not a good model of a file
handle.
Simply finding a currently unused integer value is not
sufficiently powerful to avoid known problems with clashes and
race conditions - having a standard intrinsic to return an unused
unit number can not help in this regard, no matter how
sophisticated we make the intrinsic.
Estimated Impact:
Not Quite Trivial.
Detailed Specification:
(1) That a standard derived type, in the intrinsic module
ISO_FORTRAN_ENV, be provided to represent file handles. This
derived type is referred to as IO_UNIT hereafter.
(2) That the IO_UNIT type be opaque.
(3) That OPEN not be required to take a file unit number, but
allowed to return an IO_UNIT value instead.
(4) That an IO_UNIT value be usable in place of a
in all other i/o statements.
(5) That derived-type i/o subroutines not be modified; these will
continue to receive some processor-determined negative number
for the unit - because these are supplied by the processor
and therefore cannot clash with user-determined unit numbers,
this is not a problem.
Syntax:
(1) That the derived type be named IO_UNIT.
(2a) That the UNIT= specifier on the OPEN be allowed to take a
TYPE(IO_UNIT) variable instead of an integer value,
or
(2b) That a new specifier IO_UNIT= be allowed on
OPEN if the UNIT= specifier is omitted.
Edits:
would be premature in the absence of an agreed base document.
Sections needing modification are:
9.4.0 The unit definition
9.4.5 the description of OPEN
13.8.2 to mention the derived type.
History:
Paper 04-369 meeting 169 Submitted
04-369 170 Accepted as complete
------------------------------------------------------------------
Number: J3-010
Title: Allow empty CONTAINS part
Submitted by: J3
Status: Specification complete
References: 04-189, 04-379
Basic Functionality:
Allow empty CONTAINS part
Rationale:
Is there a good reason that a module, procedure or type
definition has to have procedure definitions after the CONTAINS
statement? What would be hurt by allowing not to have any?
Sometimes when programs are generated automatically, they end up
with an empty CONTAINS part, and then you have to go fix it
manually, or whine (ineffectually) to the unsympathetic guys
who wrote the processor (if they're still in business), for which
you have no source code. It's also not unreasonable to start
off development of a module or type with an empty CONTAINS part,
with the intent of filling it in later.
Estimated Impact:
Trivial. Change a few syntax rules. No new words needed
anywhere. Estimated at J3 meeting 169 to be at 3 on the JKR
scale.
Detailed Specification:
Allow an empty CONTAINS part in external and module procedures,
modules, and derived type definitions.
History:
Paper 04-189 meeting 167 Submitted
04-379 170 Accepted as complete
------------------------------------------------------------------
Number: J3-011
Title: Coroutines
Submitted by: J3
Status: Specification complete
References: 04-345, 04-380r2
Basic Functionality:
Provide for coroutines.
Rationale:
In many cases when a "library" procedure needs access to
user-provided code, the user-provided code needs access to data
of which the library procedure is unaware. There are at least
three ways by which the user-provided code can gain access to
these entities:
o The user-provided code can be implemented as a procedure
that is invoked by the library procedure, with the extra data
stored in globally-accessible variables.
o The user-provided code can be implemented as a procedure that
takes a dummy argument of extensible type, which procedure is
invoked by the library procedure, with the extra entities in
an extension of that type.
o The library procedure can provide for "reverse communication",
that is, when it needs access to user-provided code it returns
instead of calling a procedure. When the user-provided code
reinvokes the library procedure, it somehow finds its way back
to the appropriate place.
Each of these solutions has drawbacks. Entities that are needlessly
public increase maintenance expense. If the user-provided procedure
expects to find its extra data in an extension of the type of an
argument passed through the library procedure, the dummy argument
has to be polymorphic, and the user-provided code has to execute a
SELECT TYPE construct to access the extension. Reverse
communication causes a mess that requires GO TO statements to
resume the library procedure where it left off, which in turn
requires one to simulate conventional control structures using GO
TO statements. This reduces reliability and increases development
and maintenance costs.
Reverse communication is, however, a blunt-force simulation of a
well-behaved control structure that has been well-known to computer
scientists for decades: The "coroutine". Coroutines would allow
user-provided code needed by library procedures more easily to gain
access to data of which the library procedure is unaware, without
causing the disruption of the control structure of the library
procedure that reverse communication now causes.
Coroutines are useful to implement "iterator" procedures, that can
be used both to enumerate the elements of a data structure and to
control iteration of a loop that is processing those elements.
Estimated Impact:
Minor additions to Subclause 2.3.4 and Section 12.
Estimated at J3 meeting 169 to be at 5 on the JKR scale.
Detailed Specification:
Provide two new statements, which we here call SUSPEND and RESUME.
Provide a new form of subprogram, the "coroutine", that cannot
contain an ENTRY statement, and is the only subprogram in which
a SUSPEND statement is allowed. A coroutine requires an explicit
interface.
Coroutines can stand on their own, or be type-bound procedures or
actual arguments. They can be procedure pointer targets, provided
the pointer has explicit interface. Generic coroutines are
allowed, provided the is . Recursive
and internal coroutines are allowed.
When a coroutine is invoked by a CALL statement, execution continues
with the coroutine's first executable construct. When a coroutine
executes a SUSPEND statement, execution continues after the CALL
or RESUME statement that initiated or resumed its execution; when
a RESUME statement is executed, execution resumes after the SUSPEND
statement. When a coroutine executes a RETURN or END statement,
execution continues after the CALL or RESUME statement that
initiated or resumed its execution, and it is an error if one
later attempts to RESUME it without first calling it.
A type-bound coroutine shall be initiated using a variable, and
resumed using the same variable. A coroutine that is initiated
using a pointer shall be resumed using the same pointer. Otherwise,
a coroutine shall be resumed from the same scoping unit in which
it is initiated.
Data entities:
Variables within a coroutine can have the SAVE attribute, with
the usual implications.
Unsaved local variables within a coroutine retain their definition
status and values from SUSPEND to RESUME. Automatic objects in
addition retain their bounds and length parameter values. The
specification part is not elaborated upon resumption. If a
coroutine references a module or common block, it is considered
to continue to reference it between SUSPEND and RESUME.
A change in the value of a variable between SUSPEND and RESUME
does not affect the bounds or length parameter values of automatic
variables within the coroutine.
Argument association does survive execution of a SUSPEND statement.
Activation records:
The above rules guarantee that coroutines can be reentrant. The
following paragraphs suggest one way to implement those rules.
When a coroutine suspends execution by executing a SUSPEND
statement, its activation record is saved. When a coroutine is
resumed, its activation record is restored. Therefore there is no
restriction on where a SUSPEND statement is allowed to appear among
the executable constructs.
A type-bound coroutine's activation record is saved in and restored
from an extension of the variable by which its execution is
initiated or resumed, i.e., in X, if it is referenced as X%C. If a
coroutine is accessed by a procedure pointer, its activation record
is saved in the pointer. Otherwise, the processor stores the
activation record locally (so CALL and RESUME have to be in the
same scoping unit).
History:
Paper 03-258r1 meeting 166 Submitted in section 1.1
04-149r1 167
04-345 169
04-380r2 170 Accepted as complete
------------------------------------------------------------------
Number: J3-012
Title: Use ALLOCATABLE and POINTER attributes in generic resolution
Submitted By: J3
Status: Specification complete
References: 04-170, 04-381
Basic Functionality:
Use ALLOCATABLE and POINTER attributes in generic resolution
Rationale:
I have a generic interface ALLOCATE_TEST that allocates an object,
tests the status, and prints an error message if an error occurs.
I cannot have a specific interface for a to-be-allocated argument
that has the POINTER attribute, and another for a to-be-allocated
argument with the same type, kind type parameters and rank that
has the ALLOCATABLE attribute. So I need different generic names
for allocatable objects and pointer objects. If I change an
object from pointer to allocatable or vice-versa, I have to track
down all of the ALLOCATE_TEST invocations for that variable and
change them to the other one. Avoiding this labor was one of the
justifications for the generic facility.
Estimated Impact:
Minor. Estimated at J3 meeting 169 to be at 5 on the JKR scale.
It is more likely at 3 on the JKR scale, since it appears that the
only place where edits are necessary is 407:29.
Detailed Specification:
Allow the POINTER and ALLOCATABLE attributes to be used as the last
resort for generic resolution: If the only difference between two
specific interfaces is that in one there is a dummy argument that
has neither the POINTER nor ALLOCATABLE attribute, and the
corresponding argument in the other one has one of those attributes,
the interface is ambiguous. If one has the POINTER attribute and
the corresponding one has the ALLOCATABLE attribute the interface
is not ambiguous, at least so far as that pair of specific
procedures is concerned.
If a dummy argument has the POINTER or ALLOCATABLE attribute, the
corresponding actual argument is required to have the same
attribute. Therefore this change would not invalidate any existing
program.
History:
Paper 04-170 meeting 167 Submitted
04-381 170 Accepted as complete
------------------------------------------------------------------
Number: J3-013
Title: Internal subprograms as actual arguments and procedure
pointer targets
Submitted By: J3
Status: Specification complete
References: 04-148, 03-258r1, section 1.7, 04-382r1
Basic Functionality:
Allow internal subprograms as actual arguments and procedure
pointer targets
Rationale:
In many cases where one uses a subprogram as an actual argument,
it needs access to entities of which the procedure to which it
is passed is unaware. If the actual argument were an internal
subprogram, it could access these extra entities by host
association.
Since the 2003 standard does not require the TARGET attribute
for a nonpointer dummy procedure that is a procedure pointer
target, we cannot simultaneously allow internal procedures to
be actual arguments and prohibit them to be procedure pointer
targets.
Estimated Impact:
Small. Minor changes necessary in Sections 7, 12 and 16, and
maybe Annex C. Estimated at J3 meeting 169 to be at 4 on the
JKR scale.
Detailed Specification:
Allow an internal subprogram to be an actual argument:
There are two possibilities concerning the host of the internal
subprogram:
o Allow the host of the internal subprogram to be recursive.
Make it clear that accesses by host association from the
internal subprogram to entities of its host are accesses to
entities in the instance of its host as of the instant the
internal subprogram was used as an actual argument, not to
entities in the instance of its host as of the instant the
internal subprogram is invoked.
o Require that the host of the internal subprogram is not
recursive. In this case, there can only be one instance of
the procedure defined by the host subprogram. This restriction
could later be relaxed. Many processors may relax it as an
extension.
Allow an internal subprogram to be a procedure pointer target:
Similar considerations regarding recursive hosts apply. It is
unavoidable that the same restriction applies to internal
subprograms used as procedure pointer targets and used as
actual arguments.
If internal subprograms of recursive hosts are allowed to be
procedure pointers, make it clear that the instance of the host
to which accesses from the internal subprogram to that host by
host association refer, when it is invoked by way of the pointer,
is the instance as of the instant the procedure was associated
with the pointer, which is not necessarily the instance as of
the instant the internal subprogram is invoked via the pointer.
Make sure that a procedure pointer associated with an internal
subprogram becomes undefined when the instance of the procedure
defined by its host subprogram that was in existence at the
instant the pointer association was established ceases to exist.
History:
Paper 04-148 meeting 167 Submitted
04-382r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-014
Title: Parameterized module facility
Submitted By: J3
Status: Specification complete
References: 04-153, 04-383r1
Basic Functionality:
Provide a facility whereby a module or subprogram can be developed
in a generic form, and then applied to any appropriate type.
Rationale:
Many algorithms can be applied to more than one type. Many
algorithms that can only be applied to one type can be applied to
more than one kind. It is tedious, expensive, and error prone -
especially during maintenance - to develop algorithms that are
identical except for type declarations to operate on different
types or kinds.
Generic modules are useful to package types together with their
type-bound procedures, so that when they are instantiated, they
are consistent. This cannot be guaranteed for parameterized types.
Estimated Impact:
Moderate to extensive, depending on how it's done. The solution
proposed here can be implemented mostly with changes in Section 11,
and perhaps a few changes in Section 4. Estimated at J3 meeting
169 to be at 6 on the JKR scale.
Detailed Specification:
Provide a variety of module called a "generic module". A generic
module is a template or pattern for generating specific instances.
It has "generic parameters" but is otherwise structurally similar
to a nongeneric module. A generic parameter can be a type, a data
object, a procedure, a generic interface, a nongeneric module, or
a generic module.
By substituting concrete values for its generic parameters, one
can create an "instance of a generic module". Entities from
generic modules cannot be accessed by use association. Rather,
entities can be accessed from instances of them. Instances of
generic modules have all of the properties of nongeneric modules,
except that they are always local entities of the scoping units
in which they are instantiated.
Provide a means to create instances of generic modules by
substituting concrete values for their generic parameters
Provide a means to access entities from instances of generic
modules by use association.
It is proposed at this time that generic modules do not have
submodules.
8.1 Priority for features
The features of generic modules depend primarily upon what
varieties of entities are allowed as generic parameters.
The priority of what should be allowed for generic parameters
and their corresponding instance parameters is, with most
important first:
---------------------------------------------------
Generic parameter Associated instance parameter
===================================================
Type Type
---------------------------------------------------
Data entity Initialization expression
Variable
---------------------------------------------------
Specific procedure Specific procedure
---------------------------------------------------
Generic interface Generic interface
---------------------------------------------------
Non-generic module Non-generic module
---------------------------------------------------
Generic module Generic module
---------------------------------------------------
To fit the proposal within the development schedule, it may
be necessary to reduce the present scope of the proposal.
If so, less-important features should be removed before
more-important ones.
8.2 Definition of a generic module -- general principles
A generic module may stand on its own as a global entity,
or may be a local entity defined within a program, module or
subprogram. It shall not be defined within another generic
module. If it is defined within another scoping unit, instances
of it access that scoping unit by host association. This is
useful if a particular scoping unit is the only place where
it's needed, or if instances need to share an entity such as
a type, procedure or variable.
A second axis of simplification is to prohibit generic modules
to be defined within other scoping units. If this is prohibited,
instances should nonetheless not access scoping units where they
are instantiated by host association, so as to preserve the
possibility to extend to the functionality described here at a
later time.
The MODULE statement that introduces a generic module differs
from one that introduces a nongeneric module by having a list
of generic parameter names.
The "interface" of a generic module is the list of the sets of
characteristics of its generic parameters. The interface shall
be explicitly declared, that is, the variety of entity of each
generic parameter, and the characteristics required of its
associated actual parameter when an instance is created, shall
be declared. There shall be no optional parameters. Generic
parameters and their associated instance parameters are described
in detail in section 8.4 below.
Other than the appearance of generic parameters in the MODULE
statement, and their declarations, generic modules are
structurally similar to nongeneric modules, as defined by R1104:
R1104 <>
[ ]
[ ]
although it may be necessary to relax statement-ordering
restrictions a little bit.
8.3 Instantiation of a generic module and use of the instance --
general principles
An instance of a generic module is created by the appearance of
a USE statement that refers to that generic module, and provides
concrete values for each of the generic module's generic
parameters. These concrete values are called "instance
parameters". The instance parameters in the USE statement
correspond to the module's generic parameters either by position
or by name, in the same way as for arguments in procedure
references or component specifiers in structure constructors.
The characteristics of each instance parameter shall be
consistent with the corresponding generic parameter.
By substituting the concrete values of instance parameters for
corresponding generic parameters, an "instance" of a generic
module is created, or "instantiated". An instance of a generic
module is a module, but it is a local entity of the scoping unit
where it is instantiated. It does not, however, access by host
association the scoping unit where it is instantiated. Rather,
it accesses by host association the scoping unit where the
generic module is defined.
Each local entity within an instance of a generic module is
distinct from the corresponding entity in a different instance,
even if both instances are instantiated with identical instance
parameters.
A generic module shall not be an instance parameter of an
instance of itself, either directly or indirectly.
A generic module may be instantiated and accessed in two ways:
o By instantiating it and giving it a name, and then accessing
entities from the named instance by use association. Named
instances are created by a USE statement of the form
USE ::
where a is of the form
=> , and
is of the form
( ).
In this case, the and are not
permitted - since this does not access the created instance
by use association.
Entities are then accessed from those instances by USE
statements that look like R1109:
R1109 <> USE [ [ , ] :: ] \smudge
\smudge [ , ]
<> USE [ [ , ] :: ] \smudge
\smudge , ONLY : [ ]
but with replaced by .
o By instantiating it without giving it a name, and accessing
entities from that instance within the same statement. In this
case, the USE statement looks like , but with
replaced by .
In either case, a could either be prohibited, or
required with a new value such as GENERIC or INSTANCE.
Alternatively, a new statement such as INSTANTIATE might be used
instead of the above-described variations on the USE statement,
at least in the named-instance case. In the anonymous-instance
case it would be desirable to use the USE statement, to preserve
functionality of and without needing to
describe them all over again for a new statement.
Since instances are essentially modules, but are always local
entities within the program units where they are instantiated, it
seems fatuous to prohibit nongeneric modules within other program
units. It would be reasonable to limit the nesting depth, as we
do for subprograms. For example, it would be reasonable to prohibit
either a generic module or a nongeneric module to be defined within
an internal or generic module.
8.4 Generic parameters and associated instance parameters
A generic parameter may be a type, a data entity, a specific
procedure, a generic interface, a nongeneric module, or a generic
module.
Declarations of generic parameters may depend upon other generic
parameters, but there shall not be a circular dependence between
them, except by way of pointer or allocatable components of generic
parameters that are types.
8.4.1 Generic parameters as types
If a generic parameter is a type, it shall be declared by a type
definition having the same syntax as a derived type definition.
The type definition may include component definitions. The types
and type parameters of the components may themselves be specified
by other generic parameters. The type definition may include
type-bound procedures. Characteristics of these type-bound
procedures may depend upon generic parameters.
If the generic parameter is a type, the corresponding instance
parameter shall be a type. If the generic parameter has components,
the instance parameter shall at least have components with the same
names, types, type parameters and ranks. If the generic parameter
has type parameters, the instance parameter shall at least have
type parameters with the same names and attributes. Type parameters
of the instance parameter that correspond to type parameters of
the generic parameter shall be specified by a colon, as though
they were deferred in an object of the type - even if they are
KIND parameters, and any others shall have values given by
initialization expressions. If the generic parameter has type-bound
specific procedures or type-bound generics, the corresponding
instance parameter shall at least have type-bound specifics and
generics that are consistent, except that if a specific procedure
binding to the generic parameter has the ABSTRACT attribute the
instance parameter need not have a specific binding of the same
name because it is only used to provide an interface for a generic
binding; it shall not be accessed by the specific name. Instance
parameters that are intrinsic types shall be considered to be
derived types with no accessible components. Intrinsic operations
and intrinsic functions are available in every scoping unit, so it
is not necessary to assume that intrinsic operations and intrinsic
functions are bound to the type.
8.4.2 Generic parameters as data objects
If a generic parameter is a data object, it shall be declared by
a type declaration statement. Its type and type parameters may
be generic parameters. If it is necessary that the actual
parameter to be provided when the generic module is instantiated
shall be an initialization expression, the generic parameter shall
have the KIND attribute, no matter what its type - even a type
specified by another generic parameter.
If the generic parameter is a data object, the corresponding
instance parameter's type, kind and rank shall be the same as
specified for the generic parameter.
If the generic parameter is a data object with the KIND attribute,
the corresponding instance parameter shall be an initialization
expression.
If the generic parameter is a data object without the KIND
attribute, the corresponding instance parameter shall be a
variable. Every expression within the variable shall be an
initialization expression. The instance has access to the
variable by some newly-defined variety of association (or maybe
by storage association) --- instantiation does not create a new
one with the same characteristics.
8.4.3 Generic parameters as procedures or generic interfaces
If a generic parameter is a procedure or a generic interface, its
interface shall be declared explicitly. Its characteristics may
depend upon generic parameters.
If the generic parameter is a procedure, the corresponding instance
parameter shall be a procedure having characteristics consistent
with the interface for the generic parameter, which interface may
depend upon other generic parameters.
If the generic parameter is a generic interface, the corresponding
instance parameter shall be a generic identifier, whose interface
shall have at least specifics consistent with specific interfaces
within the generic parameter's generic interface. The instance
parameter need not have the same generic identifier as the generic
parameter. If a specific interface within the generic parameter's
generic interface has the ABSTRACT attribute, the instance parameter
need not have a specific procedure with the same name, but it shall
have a specific procedure with the same characteristics. In this
case, the specific procedure within the generic parameter's generic
interface cannot be accessed by the specified name as a specific
procedure, either within an instance or from one by use association.
8.4.4 Generic parameters as generic or nongeneric modules
If a generic parameter is a generic module, The interface of that
parameter shall be declared.
If the generic parameter is a generic module, the corresponding
instance parameter shall be a generic module, having an interface
consistent with the generic parameter.
If the generic parameter is a nongeneric module, the corresponding
instance parameter shall be a nongeneric module, which may be an
internal module or an instance of a generic module.
8.5 Instantiation of a generic module and use of the instance - fine
points
If a generic module is defined within a module, it can have the
PRIVATE attribute. This means it cannot be accessed by use
association, which in turn means that it cannot be instantiated
outside of the module where it is defined. Rather, it will be
instantiated some fixed number of times within that module, which
instances might or might not be accessible by use association.
A similar situation holds, of course, if a generic module is defined
within a scoping unit that is not a module.
If the generic module is an internal generic module, it shall be
accessible in the scoping unit where the USE statement that
instantiates it appears. This may require that it be made available
by USE association from a module within which it is defined. That
is, two USE statements may be necessary: One to access the generic
module, and another to instantiate it.
If a generic module has a generic parameter that is a generic
module, and the generic parameter is public, four USE statements
might appear: One to access the generic module, one to instantiate
it, one to access the generic parameter that is a generic module
from that instance, and yet another to instantiate that generic
module. This could be prohibited, for example by prohibiting
generic parameters that are generic modules to be public, but why?
An instance parameter is accessible by use association from an
instance of a generic module by using the identifier of the
corresponding generic parameter, unless the generic parameter's
identifier is private.
Where a module is instantiated, the and
facilities of the USE statement can be used as well. Processors
could exploit an to avoid instantiating all of a module
if only part of it is ultimately used. Suppose for example that
one has a generic BLAS module from which one wants only a double
precision L2-norm routine. One might write
USE BLAS(kind(0.0d0)), only: DNRM2 => GNRM2
where GNRM2 is the specific name of the L2-norm routine in the
generic module, and DNRM2 is the local name of the double
precision instance of it created by instantiating the module. If
is not used, every entity in the module is instantiated,
and all public entities are accessed from the instance by use
association, exactly as is currently done for a USE statement
without an .
If a named instance is created, access to it need not be in the
same scoping unit as the instantiation; it is only necessary that
the name of the instance be accessible. Indeed, the instance might
be created in one module, its name accessed from that module by
use association, and entities from it finally accessed by use
association by way of that accessed name.
8.6 Examples of proposed syntax for definition
The following subsections illustrate how to define modules.
8.6.1 Sort module hoping for < routine
Here's an example of the beginning of a generic sort module in
which the processor can't check that there's an accessible <
operator with an appropriate interface until the generic module
is instantiated. There's no requirement on the parameters of the
generic type "MyType". The only way the instance can get the <
routine is if it is intrinsic, by host association from the scoping
unit where the generic module is defined, or if it is bound to the
type given by the instance parameter (recall that instances do not
access by host association the scoping unit where they're
instantiated). Aleks advocates that this one is illegal. The
primary difference would be in the quality of message announced in
the event "MyType" does not have a suitable < operator.
module Sorting ( MyType )
type :: MyType
end type MyType
....
8.6.2 Sort module with < specified by module parameter generic
interface
The < operator is given by a generic parameter. When the module is
instantiated, a generic identifier for an interface with a specific
consistent with the LESS shown here, shall be provided as an
instance parameter.
module SortingP ( MyType, Operator()
(with the obvious semantics), the instantiated sort routine would
sort into reverse order.
8.6.3 Sort module with < specified by type-bound generic interface
This illustrates a generic parameter that is a type that is required
to have a particular type-bound generic. The type shall have a
type-bound generic with a particular interface, but if entities are
declared by reference to the name "MyType" or a local name for it
after it is accessed from an instance, the specific type-bound
procedure cannot be invoked by name; it can only be accessed by way
of the type-bound generic. The ABSTRACT attribute does this. It's
only allowed in the definitions of types that are generic
parameters.
module SortingTBP ( MyType )
type :: MyType
contains
procedure(less), abstract :: Less
! Can't do "foobar%less".
! "Less" is only a handle for the interface for the
! "operator( Less
! Type shall have this generic operator
end type MyType
! Same explicit interface for "less" as in previous example
....
8.6.4 Module with type having at least a specified component
module LinkedLists ( MyType )
type :: MyType
type(myType), pointer :: Next! "next" component is required.
! Type is allowed to have other components, and TBPs.
end type MyType
....
8.6.5 Module with type having separately-specified kind parameter
module LinkedLists ( MyType, ItsKind )
type :: MyType(itsKind)
integer, kind :: itsKind
end type MyType
integer, kind :: ItsKind
....
8.6.6 BLAS definition used in instantiation examples in 8.7
module BLAS ( KIND )
integer, kind :: KIND
interface NRM2; module procedure GNRM2; end interface NRM2
....
contains
pure real(kind) function GNRM2 ( Vec )
....
8.6.7 Ordinary module with private instance count and internal
generic module
module ModuleWithInternalGeneric
integer, private :: HowManyInstances
module InternalGeneric ( MyType )
! Instances of InternalGeneric access HowManyInstances
! by host association
....
8.7 Examples of proposed syntax for instantiation
The following subsections illustrate how to instantiate a generic
module.
8.7.1 Instantiating a stand-alone generic module
Instantiate a generic module BLAS with KIND(0.0d0) and access every
public entity from the instance:
use BLAS(kind(0.0d0))
Instantiate a generic module BLAS with KIND(0.0d0) and access only
the GNRM2 function from the instance:
use BLAS(kind(0.0d0)), only: GNRM2
Instantiate a generic module BLAS with KIND(0.0d0) and access only
the GNRM2 function from the instance, with local name DNRM2:
use BLAS(kind(0.0d0)), only: DNRM2 => GNRM2
8.7.2 Instantiate within a module, and then use from that module
This is the way to get only one single-precision and only one
double precision instance of BLAS; instantiating them wherever
they are needed results in multiple instances. This also
illustrates two ways to make generic interfaces using specific
procedures in generic modules. The first one creates the generic
interface from specific procedures accessed from the instances:
module DBLAS
use BLAS(kind(0.0d0))
end module DBLAS
module SBLAS
use BLAS(kind(0.0e0))
end module SBLAS
module B
use DBLAS, only: DNRM2 => GNRM2
use SBLAS, only: SNRM2 => GNRM2
interface NRM2
module procedure DNRM2, SNRM2
end interface
end module B
In the second one the generic module has the generic interface
named NRM2 that includes the GNRM2 specific:
module DBLAS
use BLAS(kind(0.0d0))
end module DBLAS
module SBLAS
use BLAS(kind(0.0e0))
end module SBLAS
module B
use DBLAS, only: NRM2 ! Generic; GNRM2 specific not accessed
use SBLAS, only: NRM2, & ! Generic
& SNRM2 => GNRM2 ! Specific
end module B
8.7.3 Instantiate and access twice in one scoping unit, augmenting
generic interface
module B
use BLAS(kind(0.0d0)), only: NRM2
! Generic; GNRM2 specific not accessed
use BLAS(kind(0.0e0)), only: NRM2, & ! Generic NRM2 grows here
& SNRM2 => GNRM2 ! Specific
end module B
The method in 8.7.2 above might be desirable so as not accidentally
to have multiple identical instances of BLAS in different scoping
units.
8.7.4 Instantiate and give the instance a name, then access from it
! Instantiate BLAS with kind(0.0d0) and call the instance DBLAS,
! which is a local module.
use :: DBLAS => BLAS(kind(0.0d0))
! Access GNRM2 from the instance DBLAS and call it DNRM2 here
use DBLAS, only: DNRM2 => GNRM2
8.7.5 Instantiate two named instances in one module, then use one
elsewhere
module BlasInstances
! Instantiate instances but do not access from them
! by use association
use :: DBLAS => BLAS(kind(0.0d0)), SBLAS => BLAS(kind(0.0d0))
end module BlasInstances
module NeedsSBlasNRM2
use BlasInstances, only: SBLAS
! gets the SBLAS instance module, not its contents
use SBLAS, only: SNRM2 => GNRM2 ! Accesses GNRM2 from SBLAS
end module NeedsSBlasNRM2
8.7.6 Instantiate sort module with generic interface instance
parameter
type :: OrderedType
...
end type OrderedType
interface operator ( Quicksort
....
8.7.7 Instantiate sort module with TBP Less
use SortingTBP(real(kind(0.0d0))), &
& only: DoubleQuicksort => Quicksort
Notice that this depends on < being a "type-bound generic" that is
bound to the intrinsic double precision type. Here's one with a
user-defined type that has a user-defined type-bound < operator.
type MyType
! My components here
contains
procedure :: MyLess => Less
generic operator ( < ) => myLess
end type MyType
use SortingTBP(myType), only: MyTypeQuicksort => Quicksort
The interface for LESS is given in 0.6.2.
Notice that the USE statement comes _after_ the type definition
and the TBP's function definition.
8.8 Example of consistent type and TBP
This example illustrates how to create a type with type-and-kind
consistent type-bound procedures, for any kind. This cannot
be guaranteed by using parameterized types.
module SparseMatrices ( Kind )
integer, kind :: Kind
type Matrix
! Stuff to find nonzero elements...
real(kind) :: Element
contains
procedure :: FrobeniusNorm
....
end type
contains
subroutine FrobeniusNorm ( TheMatrix, TheNorm )
type(matrix), intent(in) :: TheMatrix
real(kind), intent(out) :: TheNorm
....
end subroutine FrobeniusNorm
....
end module SparseMatrices
....
use SparseMatrices(selected_real_kind(28,300)), & ! Quad precision
& only: QuadMatrix_T => Matrix, QuadFrobenius => Frobenius, &
& QuadKind => Kind
! Access instance parameter by way of generic parameter
....
type(quadMatrix_t) :: QuadMatrix
real(quadKind) :: TheNorm
....
call quadFrobenius ( quadMatix, theNorm )
History:
Paper 03-264r1 meeting 166 Submitted
04-153 167
04-383r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-015
Title: Updating complex parts
Submitted By: J3
Status: Specification complete
References: 04-165, 04-384r1
Basic Functionality:
Provide a syntax that allows to update the real and imaginary
parts of a complex variable without updating the whole thing
Rationale:
It's not unusual to need to do this.
Estimated Impact:
Very minor. Estimated at meeting 169 to be 4 on the JKR scale.
Detailed Specification:
Specify that the real and imaginary parts of a complex variable
can be accessed by using component-like syntax, with "component"
names REAL and AIMAG.
History:
Paper 03-258r1 meeting 166 Section 2.2.5
04-165 167 Submitted
04-255 167
04-384r1 255 Accepted as complete
------------------------------------------------------------------
Number: J3-016
Title: Disassociated or deallocated actual argument associated with
nonpointer nonallocatable optional dummy argument is considered
not to be present
Submitted By: J3
Status: Specification complete
References: 04-178, 04-385
Basic Functionality:
A disassociated or deallocated actual argument associated with a
nonpointer nonallocatable optional dummy argument is considered
not to be present.
Rationale:
I have a procedure that has numerous pointers that are associated,
or not, depending on input parameters. These are in turn passed
to some subroutines that do (or do not do) some computations
depending on whether the dummy arguments are associated. This,
of course, requires the dummy arguments to be pointers, which
degrades the generality of the procedure, and may have undesirable
implications for optimization.
It would be better if I could use optional nonpointer dummy
arguments to decide whether to do these computations. In order to
achieve this effect by using N optional dummy arguments I need an
IF ... ELSE IF ... END IF construct with 2**N branches.
Estimated Impact:
Nearly trivial -- a minor change in definition of "present".
Estimated at meeting 169 to be 4 on the JKR scale.
Detailed Specification:
Allow to associate a deallocated allocatable actual argument, or a
disassociated pointer actual argument, with an optional nonpointer
nonallocatable dummy argument, in which case the dummy argument is
considered to be absent. In Fortran 2003, this is an error.
History:
Paper 03-258r1 meeting 166 Section 2.4.3.1
04-178 167 Submitted
04-385 170 Accepted as complete
------------------------------------------------------------------
Number: J3-017
Title: Default initial values for absent optional dummy arguments
Submitted By: J3
Status: Specification complete
References: 04-179, 04-386r2
Basic Functionality:
Default initial values for absent optional dummy arguments
Rationale:
A frequently requested feature is to be able to specify a default
initial value for absent optional dummy arguments.
Estimated Impact:
Minor; most changes are in Section 12. Estimated at J3 meeting
169 to be at 4 on the JKR scale.
Detailed Specification:
Provide a specification for a default initial value for an absent
optional dummy scalar, or dummy array that is not an assumed-size
array. The specification has exactly the same syntax as an
initialization, but with a constraint that the expression shall
be a restricted expression rather than an initialization
expression. (The restrictions on specification expressions at
[04-007:126:7-19] would need to be applied to restricted
expressions in general instead of just to specification
expressions.)
If an optional dummy argument has a default initialization
specified and the associated actual argument is absent, the
initializer is evaluated on entry to the procedure, and then
becomes associated with the dummy argument. The VALUE
attribute may be specified as well. Optional dummy arguments
with initializers cannot have INTENT(INOUT) or INTENT(OUT).
For an optional dummy argument that has default initialization:
(1) Its assumed nonkind type parameters and extents, and dynamic
type if it is polymorphic, are taken from the initializer.
(2) If it is not a pointer the value is assigned as if by intrinsic
assignment.
(3) If it is allocatable, it is assumed to be unallocated before
initialization.
(4) If it is a pointer, the default initializer shall have the
POINTER or TARGET attribute, and the association is established
as if by pointer assignment.
History:
Paper 03-258r1 meeting 166 Section 2.4.3.2
04-179 167 Submitted
04-386r2 170 Accepted as complete
------------------------------------------------------------------
Number: J3-018
Title: Non-null initial targets for pointers
Submitted By: J3
Status: Specification complete
References: 04-202, 04-387r1
Basic Functionality:
Allow initial targets for pointers that are other than NULL().
Rationale:
It would be useful to be able to initialize pointers to targets
other than NULL(). This is especially true for procedure
pointers.
Estimated Impact:
Minor. It was estimated to be at 3 on the JKR scale at meeting
169, but it is now clear that the project is a bit more
complicated than originally envisioned. It was judged at J3
meeting 170 to be at 4 on the JKR scale.
Detailed Specification:
Allow the initial target for a data pointer to be an accessible
nonpointer nonallocatable variable with the SAVE attribute.
Every expression within the variable shall be an initialization
expression.
Allow the initial target for a procedure pointer to be an
accessible external or module procedure, or an intrinsic procedure
listed in subclause 13.6 and not marked with a bullet (or the
result of resolving a generic without invoking a procedure if the
proposal in 04-391 succeeds).
The initial target shall satisfy all the requirements for pointer
assignment (e.g. the TARGET attribute, type conformance, etc.).
This feature shall be available both for named pointers and for
pointer components. Pointer components may be default initialized
to have an initial target.
The target may be accessed by use or host association. If it is
declared in the same scoping unit it need not have been previously
declared; this facilitates initialization to a "sentinel" object.
(See note 4.36 1/2 in section 8.1 in 04-387.)
History:
Paper 03-258r1 meeting 166 Section 2.12.2
04-202 167 Submitted
04-351 169
04-387r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-019
Title: More mathematical functions
Submitted By: J3
Status: Specification complete
References: 04-184, 04-388r1
Basic Functionality:
More mathematical functions.
Rationale:
Mathematical functions for complex type are occasionally needed.
The only ones that are available for complex type are ABS, COS,
EXP, LOG, and SIN. The other mathematical functions that are
provided for real type are useful in practice for complex type
as well. Inverse hyperbolic functions and other functions are
useful. Simple identities for complex argument exist, but it
is a burden to expect users to look them up, and processors
might be able to produce more efficient implementations. For
inverse hyperbolic functions, there are simple identities
involving square root and logarithm, but these can have
substantial cancellation error for some ranges of values, so
it is important to be careful in their implementation.
Processors would presumably include careful intrinsic
implementations of these functions.
Estimated Impact:
Minor but tedious. Estimated at meeting 169 to be 4 on the
JKR scale.
Detailed Specification:
Provide ACOS, ASIN, ATAN, COSH, SINH, TAN and TANH for complex
type. Provide inverse hyperbolic functions, including for
complex type. In the case of TAN, specify that the real part
of the argument is regarded as a value in radians.
History:
Paper 03-258r1 meeting 166 Section 2.4.4.3
04-184r1 167 Submitted
04-388r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-020
Title: Allow TYPE ( )
Submitted By: J3
Status: Specification complete
References: 04-161, 04-389r1
Basic Functionality:
Allow TYPE ( ).
Rationale:
For regularity and symmetry, allow TYPE ( ).
Estimated Impact:
Trivial. Estimated at meeting 169 to be at 3 on the JKR scale.
Detailed Specification:
Allow TYPE ( ) to declare entities of
intrinsic type.
History:
Paper 03-258r1 meeting 166 Section 2.2.1
04-161 167 Submitted
04-389r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-021
Title: Resolve generic without invoking a procedure or evaluating
arguments
Submitted By: J3
Status: Specification complete
References: 04-273, 04-391r1
Basic Functionality:
Given examplars of actual arguments, resolve a generic name to
a specific procedure without invoking the procedure or evaluating
its arguments.
Rationale:
With care and diligence, one can develop a program so that
related sets of variables, constants and function results are
parameterized by a single kind type parameter. In order to change
the kind of that set of entities, one need only change one named
constant's definition - almost: Generic procedures cannot be
actual arguments or procedure pointer targets. Thus, if one needs
to change the program, in addition to changing the single named
constant definition, one needs to find all places where a specific
procedure that operates on the entities in question is an actual
argument or procedure pointer target, and manually edit those
appearances.
It would be helpful to have a facility to resolve a generic name
to a specific procedure without evaluating any arguments or
invoking a procedure.
Estimated Impact:
Minor. Processors already know how to do generic resolution.
Estimated at meeting 169 to be at 4 on the JKR scale.
Detailed Specification:
Given examplars of actual arguments, resolve a generic name to a
specific procedure without invoking the procedure or evaluating
its arguments.
There are at least two ways to do this. One is to provide a
syntax that is suggestive of procedure reference, but does
resolution instead. One possibility for this is to enclose an
actual argument list in square brackets or curly brackets
instead of round brackets. E.g.,
call solver ( myVec, myJacobian, myModel[myVec,myJacobian] )
Another is to provide an entity that looks like an intrinsic
function but that has the important distinction that its
arguments aren't evaluated. Indeed, this entity that has the
appearance of a function reference isn't even invoked during
program execution. It is entirely resolved to a procedure by
the processor during translation. E.g.,
call solver ( myVec, myJacobian, resolve(myModel,myVec,myJacobian) )
RESOLVE would be a an inquiry "function" that takes a
as its first "argument," and doesn't evaluate
its other arguments - because it's an inquiry function.
It should be possible to resolve a type-bound generic
reference, e.g., RESOLVE(A%B).
No matter what syntax is used, it should be allowed to use
the result either as an actual argument or a procedure pointer
target.
History:
Paper 04-273 meeting 168 Submitted
04-391r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-022
Title: Allow a polymorphic allocatable variable in intrinsic
assignment
Submitted By: J3
Status: Specification complete
References: 04-354r1, 04-392
Basic Functionality:
Allow a polymorphic allocatable variable in intrinsic assignment.
Rationale:
We allow intrinsic assignment to change the extent or length type
parameters of an allocatable variable in an assignment. Why not
the type if it's also polymorphic? Surely that would be equally
valuable. After all, it can be done with a DEALLOCATE statement
followed by an ALLOCATE statement with a SOURCE= specifier. Why
not allow the clearer intrinsic assignment statement?
Estimated Impact:
Trivial for the standard, probably in the trivial-to-small range
for processors. Estimated at meeting 169 to be at 4 on the JKR
scale.
Detailed Specification:
Allow a polymorphic allocatable variable in intrinsic assignment.
Require to have the same rank as a polymorphic .
If is allocated and polymorphic, deallocate it (as we
do now if any bounds or length type parameters differ). Then
allocate it with the same dynamic type, type parameters and bounds
as . Or, we could say "if the dynamic type of is
different from the dynamic type of , deallocate ".
It is necessary to specify which one because if we do the first,
processors could not choose to do the second as a polite
optimization without making finalization indeterminate. There
could be a middle ground that mumbles about finalizers.
History:
Paper 04-354r1 meeting 169 Submitted
04-392 170 Accepted as complete
------------------------------------------------------------------
Number: J3-023
Title: Named rank-one array constant's extent from its
.
Submitted By: J3
Status: Specification complete
References: 01-180, 04-101, 04-394r1
Basic Functionality:
As with the length of a character named constant, allow a
rank-one array named constant to get its extent from the
.
Rationale:
There was a good reason that a provision was made for named
constants of character type to get their lengths from their
s. For the same reason, it would be
useful if a rank-one array named constant could get its extent
from its .
Estimated Impact:
Small effect in 5.1.2.5.2, or maybe a short new subclause in
5.1.2.5, to explain how an array named constant gets its extent
from its (see item (2) in the list at the
end of 4.4.4).
Estimated at meeting 169 to be at 3 on the JKR scale.
Detailed Specification:
Allow a rank-one array named constant to get its extent from
the extent of its . Use
for the dimension specification.
See 01-180 for an example.
History:
Paper 01-180 meeting 156
04-101 167 Submitted
04-394r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-024
Title: EXIT from any labeled construct
Submitted By: J3
Status: Specification complete
References: 04-156, 04-395r1
Basic Functionality:
Allow EXIT from any labeled construct.
Rationale:
Some algorithms cannot be expressed in Fortran 2003 without GOTO
statements or extra tests, but they could be expressed with EXIT
if it could be applied to any labeled construct. For example,
here's a routine that says "call R if X is not an element of the
set S, which is represented by elements of A(1:NUM_IN_SET)".
With an extra test:
do i = 1, num_in_set
if ( x == a(i) ) exit
end do ! i
if ( i > num_in_set ) call r
or, with GOTO:
do i = 1, num_in_set
if ( x == a(i) ) go to 10
end do ! i
go to 20
10 call r
20 continue
or, with a more general EXIT:
o: if ( .true. ) then
do i = 1, num_in_set
if ( x == a(i) ) exit o
end do ! i
call r
end if o
Estimated Impact:
Trivial to minor -- a few lines in 8.1.6.4.4. Estimated at
meeting 169 to be at 3 on the JKR scale.
Detailed Specification:
Allow an EXIT statement with a that is the
same as the name of any enclosing construct, not just a DO
construct. When the EXIT statement is executed, execution of
the named construct is terminated. For compatibility, an EXIT
statement without a continues to refer to
the nearest enclosing DO construct.
History:
Paper 03-258r1 meeting 166 Section 2.1.2
04-109 167
04-156r1 167 Submitted
04-395r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-025
Title: Allow SUBROUTINE or FUNCTION to be optional
on END statements for module and internal subprograms
Submitted By: J3
Status: Specification complete
References: 04-177, 04-396r1
Basic Functionality:
Allow SUBROUTINE or FUNCTION to be optional on END
statements for module and internal subprograms.
Rationale:
Module procedures are required to end with END SUBROUTINE
or END FUNCTION . This is generally a good thing, but it
makes it impossible to convert a Fortran 77 external procedure to
a module procedure by using INCLUDE.
Estimated Impact:
Trivial. Estimated at meeting 169 to be at 3 on the JKR scale.
Detailed Specification:
To cater for the desire that a Fortran 77 external procedure could
be made into a module procedure using INCLUDE, allow the SUBROUTINE
or FUNCTION part to be optional on an
or statement. For consistency, allow them to be
optional for internal subprograms as well.
History:
Paper 03-258r1 meeting 166 Section 2.4.2
04-177 167 Submitted
04-396r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-026
Title: ATAN with two arguments works like ATAN2
Submitted By: J3
Status: Specification complete
References: 04-183, 04-397
Basic Functionality:
Define an alternative ATAN that works like ATAN2.
Rationale:
ATAN is generic. It is surprising to students that they need
to use ATAN2 just because they have the two-argument formulation.
Estimated Impact:
Minor: One more description for an existing intrinsic function -
and we already have the description. Estimated at meeting 169 to
be at 3 on the JKR scale.
Detailed Specification:
Provide a specification for how ATAN works with two arguments,
based on how ATAN2 works.
History:
Paper 03-258r1 meeting 166 Section 2.4.4.2
04-183 167 Submitted
04-397 170 Accepted as complete
------------------------------------------------------------------
Number: J3-027
Title: ASCII arguments for LGE etc
Submitted By: J3
Status: Specification complete
References: 04-185, 04-398
Basic Functionality:
Allow ASCII arguments for LGE etc.
Rationale:
Now that ASCII kind characters are required by the standard, it is
nothing short of bizarre that the four functions to compare
character strings according to the ASCII collating sequence, viz.
LGE, LGT, LLE and LLT, do not permit arguments of ASCII kind.
If one has a program with some character variables of default kind
that are compared by using these functions, and their kind needs to
be changed to ASCII, one has to find the invocations of these
functions and replace them by the equivalent relational operators.
This is an unnecessary maintenance expense.
Estimated Impact:
Trivial. Estimated at meeting 169 to be at 3 on the JKR scale.
Detailed Specification:
Allow ASCII kind arguments for LGE, LGT, LLE and LLT.
History:
Paper 03-258r1 meeting 166 Section 2.4.4.5, 04-185
04-185 167 Submitted
04-398 170 Accepted as complete
------------------------------------------------------------------
Number: J3-028
Title: Allow forward type for allocatable components
Submitted by: J3
Status: Specification complete
References: Pub-116, 04-226, 04-399
Basic Functionality:
Do not require the type of an allocatable component to be defined
before the type containing the allocatable component.
Rationale:
Mutually recursive types can be related by components having
the POINTER attribute, which allows the types of the components
to be defined after the type definition in which the components
appear. Some mutually recursive types could be related by
components having the ALLOCATABLE attribute, except that is
presently prohibited. ALLOCATABLE is preferable to POINTER
whenever possible. We should make every effort to make
ALLOCATABLE as widely usable as possible.
Estimated Impact:
Easy to implement, improves performance, trivial change in the
standard. Estimated at meeting 169 to be at 3 on the JKR scale.
Detailed Specification:
Do not require the type of an allocatable component to be defined
before the type containing the allocatable component.
The following suggested edits illustrate the magnitude of the
proposal:
In Constraint 438, replace "the POINTER attribute is not" by
"neither the POINTER nor ALLOCATABLE attribute is" and delete
"shall be CLASS(*) or" (Constraint 437 requires either the
POINTER or ALLOCATABLE attribute for a component declared with
the CLASS keyword).
In Constraint 439, insert "or ALLOCATABLE" after "POINTER".
History:
Paper 04-226 meeting 167 Submitted as Pub-116
04-399 170 Accepted as complete
------------------------------------------------------------------
Number: J3-029
Title: More information about GET_COMMAND[_ARGUMENT] failure
Submitted By: J3
Status: Specification complete
References: 04-352, 04-400
Basic Functionality:
Provide more information if GET_COMMAND or GET_COMMAND_ARGUMENT
fails.
Rationale:
It would be useful to know more precisely why GET_COMMAND or
GET_COMMAND_ARGUMENT fails.
Estimated Impact:
Trivial for standard, probably trivial-to-small for processors.
Estimated at meeting 169 to be at 3 on the JKR scale.
Detailed Specification:
Set the STATUS argument of GET_COMMAND to -2 if the processor
does not support the concept of a command line.
Set the STATUS argument of GET_COMMAND_ARGUMENT to -2 if the
value of the NUMBER argument is negative or more than the number
of command arguments.
History:
Paper 04-352 meeting 169 Submitted
04-400 170 Accepted as complete
------------------------------------------------------------------
Number: J3-030
Title: Simplified means to select the most commonly desired real
and integer kinds
Submitted By: J3
Status: Specification complete
References: 04-240, 04-407r1
Basic Functionality:
Provide a simplified means to select the most commonly desired
real and integer kinds.
Rationale:
Several possible approaches were outlined in 04-240. I propose
that we adopt the approach that is intermediate in complexity,
namely that the standard define named constants for the most
commonly desired real and integer kinds.
The approach of standardizing some named constants seems
adequately simple without being restrictive or raising
compatibility issues. It also has the advantage of being
completely trivial to implement.
My proposal is restricted to kinds with exact sizes. Adding
too many options would increase the complexity of the choice
to be made by users and would result in issues of interoperability
of codes where different users made different choices of how
to specify the kinds. Note that the existing selected_*_kind
intrinsics provide the capability of specifying minimum
requirements and could be extended in many ways (although
that is not proposed here). Exact sizes are the simplest
and most commonly requested requirement, and one that the
standard currently provides no facility for (except in C
interop, which has it only for integers - nor for reals).
I also restrict the proposal to integers and reals because
they are the common cases. User specification of specific
sizes for logical kinds is rare (and even more rare when you
rule out the cases where logical is being used as a synonym
for unsigned integer, which is a nonstandard and nonportable
practice anyway). User specification of character kinds is
also rare.
Estimated Impact:
3 on the JKR scale.
Detailed Specification:
The standard will specify the names of several named constants
in the ISO_FORTRAN_ENV intrinsic module. These named constants
will have kind values for the representations described below.
Named constants provided will be for the kinds of integers whose
storage sizes are exactly 8, 16, 32, and 64 bits, and for the
kinds of reals whose storage sizes are exactly 32, 64, and 128 bits.
Additionally, named constants will be provided for the kinds of
default integer, default real, and double precision real.
If the processor supports more than one representation with the
specified size, it is processor-dependent which of those
representations the named constant corresponds to.
If the processsor does not support a particular representation,
the value of the corresponding named constant will be one of
two negative values specified by the standard. If the processor
does not support a representation with the exact size requested
or with any larger size, the value shall be -1. If the processor
does not support a representation with the exact size requested,
but does support a representation with a larger size, the value
shall be -2.
This proposal does not require the compiler to support any
particular kind. Nor does this proposal specify the kind values,
which remain processor-dependent.
This syntax suggestion is purely illustrative for now:
int8_kind, int16_kind, int32_kind, int64_kind
real32_kind, real64_kind, real128_kind
int_default_kind, real_default_kind, real_double_kind
History:
Paper 04-240 meeting 167 Submitted
04-407r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-031
Title: ANDTHEN and ORELSE pseudo-functions
Submitted By: J3
Status: Specification complete
References: 04-193, 04-410r1
Basic Functionality:
Guarantee short-circuit evaluation of AND and OR operations.
Rationale:
There has been considerable e-mail discussion of a way to perform
short-circuiting of tests, usually to allow writing things simply
and to avoid common user errors. Various forms of an .ANDTHEN.
operator have been proposed. A canonical example is
I > 0 .AND. I < 10 .ANDTHEN. A(I) /= 0
the .ANDTHEN. guarantees that A(I) won't be referenced if I is out
of range. Paper 04-390 provides more rationale.
Much of the discussion has centered on the priority of the new
operators. Should they be: highest, lowest, the same or
different, or the same as .AND. and .OR.? Reasonably compelling
arguments have been made for all of the possibilities. This
proposal replaces the operators with functions and thus resolves
the priority issue.
The functions are called pseudo-functions to emphasize that they
are different from normal functions. An alternate name could be
"selector functions". They can be used anyplace that an ordinary
function can be used, including in declarations, if they follow
whatever normal rules apply to that use.
The functionality guarantees that the argument expressions will be
evaluated in the listed order, left to right, one at a time, and
that argument evaluation will stop when the function result can
be determined, and that exceptions and side effects won't occur
for un-required evaluations. They effectively require
short-circuiting.
Estimated Impact:
4 on the JKR scale.
Detailed Specification:
Add two new elemental pseudo-functions
ANDTHEN (A1 ,A2 [, A3, ...AN] )
ORELSE (A1 ,A2 [, A3, ...AN] )
Arguments:
A1, ...AN Logical, of any kind, they must be conformable
The arguments are evaluated in sequence, left to right, one at a
time. Evaluation of the arguments stops when ANDTHEN encounters a
FALSE value, ORELSE encounters a TRUE value, or when the last
argument has been evaluated. The result of the function is the
value of the last argument actually evaluated. (This is equivalent
to the AND or OR, respectively, of all of the evaluated arguments.)
Entities in arguments which are not evaluated need not be defined,
present, allocated, evaluatable, etc, nor may the processor generate
any side-effects or exceptions from these arguments. Note that for
elemental usage, different result elements will usually evaluate
different sets of arguments.
Examples:
IF ( ANDTHEN(I > 0, I<10, A(I) > 0 ) ) A(I) = log(A(I))
WHERE ( ANDTHEN( X > 0.0, log(X) < Tol) ) ...
IF ( ANDTHEN( PRESENT(X), X==0) ) Print *, "X must not be zero!"
The function can be usefully combined with the "IF" function from
paper 04-357r1
Local_value = IF ( ANDTHEN ( present(X), X /= 0.0), X, 1.0) )
REAL :: Temp ( IF ( ANDTHEN (present(x), size(x)>100), size(x), &
& 100) )
History:
Paper 04-193 meeting 167 Submitted
04-390 170
04-410r1 170 Accepted as complete
------------------------------------------------------------------
Number: J3-032
Title: FINDLOC
Submitted By: J3
Status: For Consideration
References: J3/03-106, Public Comment by Jean Vezina
Basic Functionality:
Intrinsic returns location of first element containing
a specified value (which may be .true. or .false.),
searching from the first or last element of an array.
Rationale:
Considered in response to a public comment, this formulation
is modeled on the MINLOC/MAXLOC procedures. Rather than
propose two procedures, a BACK= is proposed modeled after
similar argument to the character search routines INDEX, SCAN,
and VERIFY. The BACK= is used to distinguish forward and
backward searches, this may result is coding convenience
or in more compact code.
Estimated Impact:
The impact score was 3 on the John Reid scale at 167.
Detailed Specification:
FINDLOC( ARRAY= , VALUE=
[, DIM= s-i-e, BACK= s-l-e, KIND= i-i-e])
may be of any intrinsic TKR.
shall be a scalar and shall be == compatible with ,
or if both are logical.
shall be an array.
DIM and KIND are defined as per MAXLOC and MINLOC.
DIM selects the dimension(s) to be scanned, KIND
sets the kind value of the result.
BACK is defined as per INDEX, SCAN, and VERIFY.
If present with the value of .TRUE., the array
search scans backwards from the last element
of the array, and the indices returned are those
of the last element whose value equals the .
Returns the indices of the first element of
where the value of an element is equal to the scalar
specified by the VALUE argument. If is type logical,
the test is .eqv. value. Otherwise, the test
is == value.
If BACK= is present and the s-l-e evaluates to
true, returns the index of the first element
whose value is starting with the last element
and searching backwards (so it returns the last element overall).
Example: given
integer, dimension( 3) :: i = [ 3, 5, 5]
integer, dimension( 1) :: idx
idx = findloc( i, value= 5)
assigns [2] to idx.
For symmetry, it may be desirable to add
a BACK= to MAXLOC and MINLOC. However, this paper
does not propose to do so.
History:
Paper 04-113 meeting 167 Submitted
05-124r3 171 Accepted as complete
------------------------------------------------------------------
Number: J3-033
Title: Document Processor Version
Submitted By: J3
Status: For Consideration
References:
Basic Functionality:
Add to iso_fortran_env a processor defined
character constant rank-1 array
of processor-defined length, containing
processor specified version information.
Rationale:
Many times, after a suspected compiler bug has been detected,
the next step is to check a bug database. This lookup
needs the compiler's version information to succeed. Today,
this comes from a "-V" or "-version" command line option,
or some other processor dependent means. Even when the bug
is an application error, knowing the compiler version
which first detected it is often helpful.
Benchmarks and verifications also must document the exact
processor used to compile the application.
Estimated Impact:
The Estimate is 3 on the John Reid scale.
Processors would have to make their version strings
available via a name in iso_fortran_env.
Vendors might actually benefit from more detailed
bug reports.
Detailed Specification:
Add to iso_fortran_env a default character constant
rank-1 array named processor_version.
This will contain the processor-dependent
version information.
A Note is added to recognize that a sufficiently
clever user may subvert simple implementations
of this proposal by "mix-and-match"ing components
of a processor. However, such actions are so far
beyond the standard that nothing may be done
beyond this simple warning.
If defined by standard Fortran, it's declaration
might appear similar to:
character( len= 72), dimension( 3), parameter :: &
processor_version = [ 'Acme Fortran 2008 v 8.2a', &
'Acme SuperLinker v 5.6c', &
'Acme RTL v 3.4e' ]
A programmer could add:
write(*,*) ( trim( processor_version( i), &
i = 1, size( processor_version))
to an application to document the processor in use
in the application's preconnected output file.
Perhaps add a Note detailing that the usefulness
of this feature may be subverted by users who mix-and-
match components from several releases of a processor.
History:
Paper 04-137 meeting 167 Submitted
05-123r2 171 Accepted as complete
------------------------------------------------------------------
Number: J3-034
Title: Add MOLD to ALLOCATE
Submitted by: J3
Status: For Consideration
References: J3/02-274, J3/03-254, J3/04-152
Basic Functionality:
A MOLD argument should be added to ALLOCATE similar to the SOURCE
argument, which would only give the type of the allocated data, but
not the contents. This would allow one to allocate an array of a
given type given only a scalar of that type, which is needed to
design custom allocators for various dynamic data structures.
Rationale:
Certain dynamic data-structures strain the memory allocator to a
maximum, requesting allocation and deallocation of lots of nodes
(i.e., small allocations), while in actuality not really changing
the total allocated memory much. To deal with such situations
efficiently across a variety of compilers and usage patterns, it is
best to include as part of the dynamic data structure a memory
"allocator". Such an allocator can be made type-independent by
using a scalar mold to give the type of the allocation only, but
not the contents.
There are other similar situations where it is desired to allocate
a new object of unknown dynamic type, and rather then clone the
contents of another object, perform default initialization on the
newly allocated object. This is very similar to the "new" operator
in C++.
The current SOURCE in ALLOCATE is not appropriate because it does a
clone operation:
1. "source-variable is then assigned to allocate-object by intrinsic
assignment for objects whose declared type is the dynamic type of
source-variable"
and there is also the restriction:
2. "The source-variable shall be a scalar or have the same rank as
allocate-object"
which means that one cannot allocate a whole array given just a
scalar as a type template (mold).
The alternative is to use a SELECT TYPE construct, which requires
1. The names of the desired types are accessible, and
2. One must know in advance all desired dynamic types.
Objections to these two requirements were the reason to add SOURCE
to the Fortran 2003 requirements.
Estimated Impact:
This feature has a modest impact on both the standard and compilers.
This is very simple to incorporate into the standard (Aleks Donev
proposed detailed edits earlier).
Implementation wise, the only difference with SOURCE is that
default initialization needs to be performed on a polymorphic
variable, i.e., without knowing the type at compile-time. That is,
one must have the run time support to default-initialize a variable
given its type descriptor and address. This already needs to be
done for polymorphic INTENT(OUT) (see 270:38-41 in draft 03-007r2)
variables, so the run-time support neccessary for it needs to be in
compilers already.
Detailed Specification:
Add a MOLD keyword to the ALLOCATE statement. The allocated object
shall have the same dynamic type as the object specified by MOLD.
Unlike SOURCE, use default initialization instead of intrinsic
assignment for the value of the allocated object. Require the mold
to be a scalar even if the allocation is for an array. MOLD and
SOURCE shall not both appear.
Therefore:
CLASS(base_type), POINTER :: var1, var2
TYPE, EXTENDS(base_type) :: dynamic_type_of_var2
END TYPE
TYPE (dynamic_type_of_var2), TARGET :: var3
var2 => var3
ALLOCATE(var1, MOLD=var2)
should be equivalent to:
SELECT TYPE ( var2 )
...
TYPE IS ( dynamic_type_of_var2 )
ALLOCATE(dynamic_type_of_var2::var1)
END SELECT
History:
Paper 04-152 meeting 167 Submitted
05-157 171 Accepted as complete
------------------------------------------------------------------
Number: J3-035
Title: Beginning a source line with a semicolon
Submitted By: J3
Status: For consideration
Basic Functionality:
Remove the restriction against beginning a source line with a
semicolon.
Rationale:
This restriction is stated in 3.3.1.3 (for free source form)
and 3.3.2.4 (for fixed source form) of Fortran 2003.
This restriction was not in the original F90, but was added
by F90 corrigendum 3. It remained in F95.
It is an unnecessary restriction: removing it simplies the
standard.
Estimated Impact:
It is row #39 in spreadsheet 05-145. It received a Hate-Love
vote of 0-0-13-2 and was judged an impact of 3 on the Reid scale.
Detailed Specification:
Remove the restriction against beginning a source line with a
semicolon as stated in section 3.3.1.3 (for free source form)
and 3.3.2.4 (for fixed source form) of Fortran 2003.
History:
Paper 04-282 meeting 168 Submitted
05-161 171 Accepted as complete
------------------------------------------------------------------
Number: J3-036
Title: USE, EXCEPT:
Submitted By: J3
Status: For Consideration
References: J3/03-106, J3/04-114
Basic Functionality:
A syntax to list names not to have use association
when using a module.
Rationale:
When using a module with many public names, a few may be
unwanted. Specifying those few is easier than naming
the many wanted names, and less ugly than fanciful renames.
Estimated Impact:
4 on the John Reid scale at 167
Detailed Specification:
Add a clause to the USE statement
specifying names not available via use association.
If EXCEPT: is present, ONLY must not be present,
and there can be no renames (in the ). (It makes no
sense to say "don't use this name, and call it 'foo'".)
If any USE statement for a given module in a scoping unit
has an EXCEPT, all use statements for that module
in that scoping unit must have an EXCEPT clause.
The effective EXCEPT list is the concatenation
of all the EXCEPT lists naming the given module.
History:
Paper 03-106 meeting ??? ???
04-114 167 Submitted
05-135r2 171 Accepted as complete
------------------------------------------------------------------
Number: J3-037
Title: Pointers and Targets
Submitted By: J3
Status: For Consideration
References: 04-131
Basic Functionality:
Improve aliasing analysis by indicating pointers to targets and
targets of pointers.
Rationale:
Compilers must generate code which allows data to be kept in the
fastest memory closest to functional units for highly optimized code
sequences. Conservative assumptions regarding aliasing prevent it,
providing information to allow more aggressive analysis allows it.
Estimated Impact:
Compilers would have to recognize lists in two new places and they
should be able to detect textual falsehoods, but they need not use
this information when generating code. High quality implementations
will do so. A forward reference must be accepted, because both
pointer and target cannot be declared in the same statement. If no
other accepted feature proposal provides for such forwared
references, this proposal implicitly contains a proposal to allow
such forward references.
Detailed Specification:
Allow the programmer to list the targets of pointers and the
pointers to targets, as follows:
Modify the TARGET declaration syntax by optionally placing a
parenthesized list of pointers after it. For example:
real, target( pa) :: ta
This indicates that only pointer pa will be associated with target
ta. The variable pa shall have the pointer attribute and have
characteristics such that it could be associated with ta. If pa is
declared subsequently, that declaration shall confirm the required
characteristics.
Modify the POINTER declaration syntax analogously:
real, pointer( ta) :: pa
This indicates that pointer pa will only be associated with target
ta. The variable ta shall have the target attribute and have
characteristics such that it is a valid target for pa. If ta is
declared subsequently, that declaration shall confirm the required
characteristics.
A set of declarations with pointer or target lists shall not be
inconsistent.
Note that for the two example declarations above, one (pa or ta)
must contain a forward reference. The circumstances where one
declaration of the two above is allowed to be in a different
compilation unit should be resolved by J3.
The POINTER and TARGET statements are modified to allow the same
new syntax as the corresponding attribute specifiers.
In general,
TARGET [ ( ) ]
and
POINTER [ ( ) ]
Examples:
! targets of a pointer
real, pointer( t1, t2) :: ptr
real, target :: t1, t2
real, target :: tgt
! accepted:
ptr => t2
! not accepted:
ptr => tgt
! -----------------------------
! pointer to a target
real, pointer :: ptr
real, target( ptr) :: t1, t2
real, target :: tgt
! accepted:
ptr => t2
! not accepted:
ptr => tgt
! -----------------------------
! symmetrically constrained declarations
real, pointer( t1, t2) :: ptr
real, target( ptr) :: t1, t2
History:
Paper 04-131 meeting 167 Submitted
05-160 171 Accepted as completed
------------------------------------------------------------------
Number: J3-038
Title: C libm functions as Fortran intrinsics
Submitted By: J3
Status: For Consideration
References:
C99 7.12 Mathematics page 211 et seq.
Unix Programmer's Manual, Volume 2, System calls
and Library Routines (3m)
Basic Functionality:
Add the Bessel functions, hypot, and error functions
to the Fortran intrinsic function set for real arguments.
Rationale:
Fortran is mainly used for numerical problems, supplying
mathematical functions of proven utility will assist Fortran is
continuing as the premier mathematical programming language in the
world today.
Estimated Impact:
The estimated impact at 167 was 4 on the John Reid scale.
These are proposed intrinsic functions, no other feature is
affected. Impact on vendors is minimal, as most vendors support
these functions anyway for their C/C++ compilers.
Detailed Specification:
Add subsections to Section 13 detailing the Fortran names for these
procedures. (The C names should not be used due to the common
usage, in Fortran, of names such as j0 etc.)
The functions are (the C names):
Bessel functions (j0, j1, jn, y0, y1, yn)
Error Functions (erf, erfc)
Hypotenuse (hypot)
Gamma and log gamma (tgamma, lgamma)
The detailed mathematical specification of these procedures is
given in the references above. The intention is to allow the vendor
to use the procedure supplied by libm, so the exact specification
is left to libm, which is most likely what the applications
programmer wants.
Since Fortran does not support the concept of external variables,
the signgam variable of lgamma may be defined as an optional
intent(out) argument.
Edits would include adding to the list in 13.5.2:
BESSEL_J0
BESSEL_J1
BESSEL_JN
BESSEL_Y0
BESSEL_Y1
BESSEL_YN
COMP_ERROR_FUNC
ERROR_FUNC
GAMMA_FUNC
HYPOT
LOG_GAMMA_FUNC
History:
Paper 04-246 meeting 167 Submitted
05-132r2 171 Accepted as complete
------------------------------------------------------------------
Number: J3-039
Title: Rank > 7
Submitted By: J3
Status: For Consideration
Basic Functionality:
Relax the restriction on the maximum rank of an array.
Rationale:
The limit of seven dimensions was set when Fortran was first
published in 1957 and has never been changed. Requests for
increasing this limit have been made by international bodies for
years. See the previous WG5 repository N1189, Numbers 24 (from
the Russian Fortran Working Group) and Number 24a (from X3J3,
JOR 95-004r1, item 067).
Estimated Impact: (Listed as 4 on the JKR scale)
The standard would require changes in at least four places. This
will not impact any existing code. Any other impact should be
apparent only when arrays of rank greater than seven are declared
and referenced.
Detailed Specification:
Increase the maximum permitted rank for arrays.
Changes would be needed to the following places in F2003:
[18:5] An array may have up to seven dimensions ...
[78:4] C541 (R510) The maximum rank is seven.
(repeated in Annex D, page 517)
[108:6+] Table 6.1
[353:19] The rank of SOURCE shall be less than 7.
History:
Aug 95, J3 Meeting 134: Change max 255 to > 7
approved by US TAG for F2000 as medium priority
WG5-N1189 (20 June 1996)
Paper 05-144r2 meeting 171 Accepted as complete
------------------------------------------------------------------
Number: J3-040
Title: Compute if actual argument is present
Submitted By: J3
Status: For consideration.
Basic Functionality:
Provide a mechanism to compute whether an actual argument is present
Rationale:
If the presence of an argument controls whether a calculation is
performed, and if the desire to perform the calculation is
determined by the results of other calculations, one needs to be
able to compute whether the argument is present or absent. In
Fortran 2003, the way to do this is with an IF construct. But with
n arguments, one needs a 2^n-way if-elseif...-else-endif construct
with a different one of the 2^n possible combinations of present
actual arguments in each branch. It would be more convenient if
one could use a syntactic form for an actual argument to calculate
whether it is present. It is important that the desired entity,
not the value of it, is the actual argument. Otherwise, it would
not be useful where the associated dummy argument does not have
INTENT(IN).
Estimated Impact:
This is part of the proposal in J3 paper 04-393, whose antecedent
was 04-357r1. At J3 meeting 169, the proposal in 04-357r1 was
judged to be at 4 on the JKR scale. Surely this proposal, being
only part of the previous one, is not larger.
Detailed Specification:
Provide a mechanism to compute whether an actual argument is
present.
If the condition specifies that the actual argument is present, to
be useful in the case the desired entity is not an expression, or
is a procedure argument, it, rather than the value of it, must
become the actual argument. No matter what syntax is used, if
there is no special description it cannot be called a function or
operation, because the result would be a value separate from the
desired entity itself.
If the condition specifies that the actual argument is absent,
neither the entity that would otherwise become the actual argument,
nor any expressions within it, shall be evaluated. That the
condition specifies the entity is considered to be absent might be
a proxy for the nonexistence of values necessary for these
evaluations.
Examples:
Several syntaxes are possible. Two under consideration are similar
to a function reference, and similar to an operator.
CALL MY_SUB ( A, IF(PRESENT(B),B(:,I)) )
or
CALL MY_SUB ( A, PRESENT(B) ? B(:,I) )
History:
Paper 04-393r1 meeting 170 Submitted
05-103r1 171 Accepted as complete
------------------------------------------------------------------
Number: J3-041
Title: Interoperability of pointers, allocatables, and
assumed-shape arrays
Submitted By: J3
Status: For consideration
Reference: 04-371r2
Basic Functionality:
to C Interop that allow arguments that are pointers,
allocatables, and assumed-shape arrays to be interoperable.
Rationale:
C interoperability provides a mechanism to share array data between
Fortran and C. However, even with C interop, it is still necessary
for users to implement a translation layer between C and Fortran
assumed-shape array data structures. Under some circumstances, it
may even be necessary to make temporary copies of array data in
this translation layer.
In the translation layer, for each array-valued parameter in a
BIND(C) procedure, a user needs to pass the address of the array
as well as each value of the array shape as integer procedure
parameters. For BIND(C) procedures taking many array arguments,
the resulting argument list can be exceptionally long. In addition,
data marshaling in the translation layer can be a performance hit.
Estimated Impact:
Small impact for the standard and probably small to moderate
impact for the processors.
Detailed Specification:
The processor will be required to supply, for each companion C
processor, a C header file and C functions (or macros) implementing
the C prototypes shown below. In C, descriptors for assumed-shape,
allocatable, and Fortran pointer objects are represented by opaque
types. The C functions specified by these prototypes allow C
programmers to create and destroy memory for descriptors, functions
to get and set parameters in a descriptor, and functions to allocate
and deallocate the memory described by the descriptors.
Separate opaque types are defined for the assumed-shape,
allocatable, and pointer cases. Type and function names containing
_ASSUMED_ are used with assumed-shape arguments, names containing
_ALLOC_ are used with allocatable arguments, and names containing
_POINTER_ are used with pointer arguments. The rank may be
specified as 0 for allocatable and pointer descriptors, in which
case the corresponding Fortran object shall be a scalar. If the
rank is 0, the pointers to the shape and stride arrays in the same
reference are not used and may have any value. If the base_addr
parameter in the FDesc_Alloc_Create or FDesc_Alloc_Reset functions
is NULL, the resulting descriptor represents an unallocated object.
If the base_addr parameter in the FDesc_Pointer_Create or
FDesc_Pointer_Reset is NULL, the resulting descriptor represents an
unassociated pointer.
A C function calling a Fortran procedure with the BIND(C) attribute
will pass a pointer to an array descriptor as the actual argument
corresponding to an assumed-shape, allocatable, or pointer dummy
argument. Depending on the details of the processor's Fortran
descriptors, the procedure may be required to merge additional
information into the descriptor based on the declaration of the
dummy argument, or to create a local representation based on the
information in the descriptor. If the dummy argument is
deallocated, allocated, or has its pointer association status
changed in the procedure, the descriptor shall be modified to
reflect the new state of the argument.
A C function that is called from a Fortran procedure will be passed
a pointer to a descriptor of the type appropriate for the
corresponding dummy argument in the interface for the called
function.
Such an argument must have interoperable type and type parameters.
/**
* FDesc.h - name of include file declaring descriptor typedefs
* and prototypes
*/
/**
*
* An opaque type for the size of extents.
*
* F_extent_t
*
*/
/**
* Opaque descriptor types.
*
* FDesc_Alloc_t
* FDesc_Pointer_t
* FDesc_Assumed_t
*
*/
/**
* Allocation, deallocation and reset routines for descriptors
*/
/**
* Create a descriptor and initialize its data.
*
* Memory for the descriptor must be freed by a subsequent call to
* FDesc_Alloc_Destroy, FDesc_Pointer_Destroy, or FDesc_Assumed_Destroy.
*
* @param fdesc contains address of descriptor on return.
* @param base_addr the base address of the array or scalar object.
* @param elem_size the size of an array element or scalar object (in bytes).
* @param rank the rank of the array; 0 if object is scalar.
* @param shape array[rank] containing the array shape.
* @param stride array[rank] containing the distance between successive
* array elements for each dimension (in bytes).
* @return 0 if successful (nonzero on error).
*/
int FDesc_Alloc_Create(FDesc_Alloc_t * restrict fdesc,
void * restrict base_addr,
size_t elem_size,
unsigned int rank,
const F_extent_t shape[restrict],
const size_t stride[restrict]
);
int FDesc_Pointer_Create(FDesc_Pointer_t * restrict fdesc,
void * base_addr,
size_t elem_size,
unsigned int rank,
const F_extent_t shape[restrict],
const size_t stride[restrict]
);
int FDesc_Assumed_Create(FDesc_Assumed_t * restrict fdesc,
void * base_addr,
size_t elem_size,
unsigned int rank;
const F_extent_t shape[restrict]
);
/**
* Set the elements of a descriptor.
*
* @param fdesc address of descriptor.
* @param base_addr the base address of the array or scalar object.
* @param shape array[rank] containing the array shape (in elements).
* If base_addr is NULL, the contents of shape are ignored
* and the descriptor shape values are set to 0.
* @param stride array[rank] containing the distance between successive
* array elements for each dimension (in bytes).
* If base_addr is NULL, the contents of stride are ignored
* and the descriptor stride values are set to 0.
* @return 0 if successful (nonzero on error).
*/
int FDesc_Alloc_Reset(FDesc_Alloc_t * restrict fdesc,
void * restrict base_addr,
const F_extent_t shape[restrict],
const size_t stride[restrict]
);
int FDesc_Pointer_Reset(FDesc_Pointer_t * restrict fdesc,
void * base_addr,
const F_extent_t shape[restrict],
const size_t stride[restrict]
);
/**
* Frees memory for a descriptor.
*
* @param fdesc address of a descriptor.
* @return 0 if successful (nonzero on error).
*/
int FDesc_Alloc_Destroy(FDesc_Alloc_t * restrict fdesc);
int FDesc_Pointer_Destroy(FDesc_Pointer_t * restrict fdesc);
int FDesc_Assumed_Destroy(FDesc_Assumed_t * restrict fdesc);
/**
* Routines to allocate and deallocate array or scalar object memory
*/
/**
* Returns a value appropriate for use as base_addr in Create and
* and Reset routines.
*
* @param size amount of memory to allocate, in bytes.
* @return pointer to allocated memory, or NULL if the
* memory allocation fails.
*/
void * FDesc_Alloc_Allocate(size_t size);
void * FDesc_Pointer_Allocate(size_t size);
void * FDesc_Assumed_Allocate(size_t size);
/**
* Frees memory previously allocated with FDesc_Alloc_Allocate,
* FDesc_Pointer_Allocate, or FDesc_Assumed_Allocate.
* FDesc_Alloc_Deallocate and FDesc_Pointer_Deallocate may be
* used to deallocate memory previously allocated by a Fortran
* procedure.
*
* @param fdesc address of descriptor. The base_addr in the
* descriptor is set to NULL on return.
* @return 0 is successful (nonzero on error).
*/
int FDesc_Alloc_Deallocate(FDesc_Alloc_t * restrict fdesc);
int FDesc_Pointer_Deallocate(FDesc_Pointer_t * restrict fdesc);
int FDesc_Assumed_Deallocate(FDesc_Assumed_t * restrict fdesc);
/**
* Accessors
*/
/** Returns true if the pointer is associated (false otherwise). */
_Bool FDesc_Associated(FDesc_Pointer_t fdesc);
/** Returns true if the object is allocated (false otherwise). */
_Bool FDesc_Allocated(FDesc_Alloc_t fdesc);
/** Returns the rank of the array described by a descriptor */
int FDesc_Alloc_Rank(FDesc_Alloc_t fdesc);
int FDesc_Pointer_Rank(FDesc_Pointer_t fdesc);
int FDesc_Assumed_Rank(FDesc_Assumed_t fdesc);
/**
* Return the address, shape, and stride information in a descriptor.
*
* @param fdesc the descriptor.
* @param base_addr contains the address of the array or scalar object on return.
* @param shape array[rank] containing the array shape on return
* (in elements). If the rank is 0, shape is not returned.
* @param stride array[rank] containing the distance between successive
* array elements for each dimension (in bytes) on return.
* If rank is 0, stride is not returned.
* @return 0 if successful (nonzero on error).
*/
int FDesc_Alloc_Get(FDesc_Alloc_t fdesc,
void ** restrict base_addr,
F_extent_t shape[restrict],
size_t stride[restrict]
);
int FDesc_Pointer_Get(FDesc_Pointer_t fdesc,
void ** base_addr,
F_extent_t shape[restrict],
size_t stride[restrict]
);
int FDesc_Assumed_Get(FDesc_Assumed_t fdesc,
void ** base_addr,
F_extent_t shape[restrict],
size_t stride[restrict]
);
/** End of FDesc.h */
History:
Paper 04-371r2 meeting 169 Submitted
05-159 171 Accepted as complete
------------------------------------------------------------------
Number: J3-042
Title: Interoperability of optional arguments
Submitted By: J3
Status: For consideration
Basic Functionality:
Extension to C Interop that allows optional arguments to be
interoperable.
Rationale:
If C functions have a mechanism to indicate and detect missing
optional arguments, the class of Fortran subprograms that
interoperate with C would be significantly expanded.
Estimated Impact:
Small impact for the standard and probably small to moderate
impact for the processors.
Detailed Specification:
The VALUE attribute is not allowed for optional dummy arguments in a
BIND(C) interface.
A C function specifies a missing actual argument in a function
reference by passing a NULL data pointer as the argument value if
the corresponding dummy argument is a data object, or a NULL
procedure pointer as the argument value if the corresponding dummy
argument is a procedure. If the function being referenced is a
Fortran procedure, the corresponding dummy argument must have the
OPTIONAL attribute, and the procedure must have the BIND(C)
attribute.
A Fortran subprogram with the BIND(C) attribute specifies a missing
actual argument in a subroutine call or function reference by
passing C_NULL_PTR by value for a missing data argument and
C_NULL_FUNPTR by value for a missing procedure argument. The
OPTIONAL attribute must be specified for the corresponding dummy
argument. The C function can detect a missing argument by
comparing its value to NULL.
History:
Paper 04-373 meeting 169 Submitted
171 Accepted as complete
------------------------------------------------------------------
Number: J3-043
Title: contiguous pointers
Submitted By: J3
Status: For Consideration
References: J3/04-132
Basic Functionality:
Provide a method to indicate that the target of a pointer or an
actual argument is contiguous.
Rationale:
Many unnecessary operations happen because compilers cannot
determine that a data item occupies contiguous memory. For
example, contiguous memory is needed to pass an array to a
procedure with an implicit interface. Certain optimizations are
possible if the compiler knows that the memory stride for the
left-most subscript is 1, or if a whole array occupies a contiguous
memory block. Thus, the mere use of pointers often results in
substantially suboptimal code. If the compiler knew that the
pointer was constrained to point to contiguous memory, very much
better code could be generated. Similar optimization problems exist
for assumed-shape dummy arguments.
Estimated Impact:
The effort was estimated as 5 on the John Reid scale at M167.
Detailed Specification:
Provide a declaration attribute, CONTIGUOUS, that specifies that
the pointer being declared will only be associated with a target
occupying a storage sequence or that an assumed-shape dummy
argument is associated with a contiguous actual argument. For
example,
real, pointer, contiguous :: sptr(:)
real, contiguous, dimension(:,:) :: d
If the variable is a dummy argument with the pointer attribute, the
target of the associated actual argument shall be a storage
sequence. If the variable is an assumed-shape array, the associated
actual argument shall be a storage sequence or a pointer associated
with a target that is a storage sequence.
A corresponding CONTIGUOUS :: statement is also
provided.
History:
Paper 04-132 meeting 167 Submitted
05-149r2 171 Accepted as complete
------------------------------------------------------------------
Number: J3-044
Title: New Intents
Submitted By: J3
Status: For Consideration
References: J3/04-135
Basic Functionality:
Add a new intent for dummy arguments:
INTENT(SCRATCH) specifies that the dummy argument is undefined on
entry and return. The argument may be used for scratch work space
only. Compilers may be able to optimize this argument aggressively.
Rationale:
Many older Fortran programs have dummy arguments which are used for
scratch work space only. Any use of existing argument intents
gives wrong information to the compiler. Also, in the process of
converting scratch work arrays in common blocks to allocatable
dummy arguments, there is no proper intent for 'scratch' variables.
An optimizing compiler could scalarize a dummy argument array
known to be scratch. Also, final values of the dummy argument do
not need to be stored.
Estimated Impact:
The impact was rated as 5 on the John Reid scale at 167. Lowered
to 4 at meeting 171.
Detailed Specification:
A new INTENT(SCRATCH) attribute is proposed.
The actual argument associated with a dummy argument with the
INTENT(SCRATCH) attribute shall be definable. The dummy argument is
undefined upon entry to the procedure and becomes undefined upon
exit from the procedure.
History:
Paper 04-135 meeting 167 Submitted
05-147r2 171 Accepted as complete
------------------------------------------------------------------
Number: J3-045
Title: Same shape arrays
Submitted By: J3
Status: For Consideration
References: J3/04-136
Basic Functionality:
Provide syntax to specify that an array has the same shape and
bounds as a specified array.
Rationale:
Compilers will be able to generate more efficient code when they
can assume that several arrays all have the same shape and bounds.
It is also a convenience to programmers, especially for the
declaration of automatic arrays with the same shape and bounds as a
dummy argument.
Estimated Impact:
The effort was estimated as 5 on the John Reid scale at 167.
Detailed Specification:
A new declaration attribute, BOUNDS(), is provided to
specify that the variable being declared has the same shape and
bounds as the specified . If is an
assumed-shape array, the variable is an assumed-shape array if it
is a dummy argument; otherwise the variable is an explicit-shape
array. If is a deferred-shape array, the variable is a
deferred-shape array if it is a dummy argument or has the pointer
or allocatable attributes; otherwise the variable is an
explicit-shape array. If is an explicit-shape array,
the variable is an explicit-shape array. If the variable and
are both assumed-shape dummy arguments, the associated
actual arguments shall have the same shape. If the variable and
are both deferred-shape dummy arguments, the
associated actual arguments shall have the same shape and bounds.
The bounds of shall be previously specified in the
same scoping unit, or shall be accessible by USE or
host association. If the is a pointer, it shall be
associated at entry to the scoping unit containing the declaration.
If the is allocatable, it shall be allocated at entry
to the scoping unit containing the declaration.
The bounds of the variable being declared are not affected by
subsequent changes to the bounds of .
A corresponding BOUNDS() :: statement
is also supplied.
For example,
real, dimension(:,:,:) :: a
real, bounds(a) :: b ! instead of real,dimension(:,:,:) :: b
History:
Paper 04-136 meeting 167 Submitted
05-148r1 171 Accepted as complete
------------------------------------------------------------------
Number: J3-046
Title: DO CONCURRENT Construct
Submitted By: J3
Status: For Consideration
References: J3/04-243
Basic Functionality:
The DO CONCURRENT construct is a new form of the block DO construct
using loop control syntax like that of FORALL. It would allow the
iterations of the loop to be executed in any order. Restrictions on
the statements in the loop block are required, but the restrictions
are significantly fewer than for FORALL constructs.
Rationale:
The performance of most modern processors is enhanced, sometimes
significantly, if the number of memory references is reduced. This
is typically accomplished by keeping more of the program data in
processor registers, especially during iterations of a loop. Data
from different loop iterations may be held in independent parts of
a multi-word register (vectorization), in disjoint subsets of a
single register set (loop unrolling), or in the register sets of
several different processors or processor cores of a multi-threaded
processor (parallel execution). Many modern computer systems can
already take advantage of all of these optimization methods, and
trends in computer system architecture suggest these optimization
techniques will be even more important in the future. The DO
CONCURRENT construct is designed to allow compilers to better use
these optimizations.
These optimizations rely on the values contained in registers being
the same as the associated values in memory when the corresponding
variables are referenced during execution of the construct. This is
the case if there is no associated memory value during execution of
the construct, or if the nature of cross iteration data dependencies
is properly limited.
Compared to the FORALL construct, the DO CONCURRENT construct
allows a much larger class of statements within the block,
including calls to pure subroutines and some branches. DO
CONCURRENT constructs also avoid the iteration space temporaries
that FORALL requires in cases where the compiler cannot prove there
are no cross iteration dependencies. If there really are
dependencies, FORALL may be the better option, but in a large
number of cases, there are no actual dependencies and DO CONCURRENT
will provide much better performance.
The DO CONCURRENT construct provides a way for the programmer to
specify that the aggressive optimizations described above are
allowed. It is cleaner and more portable than the current method of
using directives that have difference spellings and meanings among
vendors.
Estimated Impact:
Specifications of the new syntax and restrictions on the statements
in the construct block are needed in section 8.1.6. Additions in
section 16 to subsections on variable definition and undefinition,
and pointer association status are also needed. Implementation in
compilers should be simple, as many compilers already support
similar features through directives. At a minimum, a compiler could
convert the construct to a set of ordinary DO loops, possibly with
an added IF test. The original proposal in 04-243 was rated as an
impact of 5 on the JKR scale. This proposal is somewhat simpler
than the original because it leverages the existing block DO
construct.
Detailed Specification:
The syntax for DO CONCURRENT specifies a new for the
existing that uses the FORALL header syntax:
[,] CONCURRENT
The scope rules for an in the are the
same as in a FORALL construct (7.4.4.1).
The values of the index variables for the iterations of the
construct are determined by the rules for the index variables of
the FORALL construct (7.4.4.2.1 and 7.4.4.2.2). The number of
distinct index value tuples is the iteration count for the
construct. The order in which the iterations are executed is
indeterminant.
A statement in the loop range shall not cause a branch out of the
loop range. The loop range shall not contain an EXIT statement that
would cause the DO CONCURRENT construct to terminate.
A variable that is referenced in an iteration of a DO CONCURRENT
construct shall either be previously defined during that iteration,
or shall not be defined during any other iteration. A variable that
is defined in more than one iteration becomes undefined when
execution of the construct completes.
A pointer that is referenced in an iteration of a DO CONCURRENT
construct either shall be previously pointer associated during that
iteration, or shall not become pointer associated in the loop
range. A pointer that is pointer associated in more than one
iteration has a processor dependent association status when the
execution of the construct completes.
An allocatable object that is allocated in more than one iteration
of a DO CONCURRENT construct shall be subsequently deallocated
during the same iteration in which it was allocated. An object
that is allocated or deallocated in only one iteration of a
concurrent shall not be deallocated, allocated, referenced, or
defined in a different iteration.
An input/output statement in a DO CONCURRENT construct shall not
write data to a file record or position in one iteration and read
from the same record or position in a different iteration.
Procedures referenced in the loop range of a DO CONCURRENT
construct shall be PURE. If the IEEE_EXCEPTIONS intrinsic module is
accessible, references to the IEEE_GET_FLAG, IEEE_SET_HALTING_MODE,
and IEEE_GET_HALTING_MODE subroutines shall not appear in the loop
range.
Note: The restrictions on referencing variables defined in an
iteration apply to any procedure invoked by the loop.
Note 12.44 in section 12.6 (Pure procedures) should be updated to
include the DO CONCURRENT construct as well as the FORALL construct.
History:
Paper 04-243 meeting 167 Submitted
05-133r2 171 Accepted as complete
------------------------------------------------------------------
Number: J3-047
Title: TYPELESS objects in Fortran
Submitted By: J3
Status: For consideration
References: 03-278, 04-244
Basic Functionality:
Objects declared as TYPELESS have kind and rank attributes, but are
treated as only a sequence of bits, without the higher abstractions
associated with the traditional Fortran intrinsic types. A method
for declaring objects as TYPELESS is provided as well as rules on
how such objects interact with existing Fortran objects. Associated
intrinsic procedures are also provided.
Rationale:
Fortran currently lacks support for variables that represent a
sequence of bits independent of the interpretations imposed by the
traditional numeric, logical, and character data types. Various
features have been added to Fortran to facilitate handling
sequences of bits by overloading the INTEGER data type, and through
vendor extensions. This has lead to limitations in the usefulness
of these features as well as awkward wording in the Fortran
standard text. Adding a new intrinsic type specifier, TYPELESS,
would simplify and enhance the use of Fortran for certain types of
non-numeric problems, such as pattern matching, searching and
sorting, and low level bit manipulation, as well as allowing for
more clarity in the text of the standard. TYPELESS also provides a
way to standardize several common Fortran language extensions, and
provides a rational method for dealing with BOZ constants.
Estimated Impact:
Several edits to the standard would be required to incorporate this
feature, though each would be straightforward. Implementation of
the feature in compilers should be technically simple. It is rated
as a 7 on the JKR scale.
Detailed Specification:
Discussion of typeless objects requires a concept of the size of an
object in number of bits. The term bit_size in lower case letters
is used in this proposal. The name BIT_SIZE in upper case letters
refers to the intrinsic function.
Declarations and constants
--------------------------
The typeless type has values that are contiguous, ordered sequences
of bits. The bit_size is the number of bits in the sequence. A
processor shall provide typeless sizes with bit_size values
corresponding to the storage sizes of each of the INTEGER kinds
provided, as well as the storage sizes of twice and four times the
size of the default INTEGER storage size. Each provided bit_size is
characterized by a value for a type parameter called the kind type
parameter. The kind type parameter is of type default integer. The
kind type parameter of a typeless object is returned by the
intrinsic inquiry function KIND. The number of bits of a typeless
object is returned by the intrinsic function BIT_SIZE. The
intrinsic function SELECTED_TYPELESS_KIND returns a kind value
based on the specified number of bits.
The type specifier for the typeless type uses the keyword TYPELESS.
If the kind parameter is not specified, the default kind value is
KIND(TYPELESS(0)), and the type specified is default typeless.
Any typeless value may be represented as a .
(The f03 description of BOZ constants, [37:1-18], would be moved
to the typeless subsection of 4.4, and constraint C410 deleted.)
The digits of octal constants represent triples of bits, and the
digits of hexadecimal constants represent quartets of bits,
according to their numerical representations as binary integers,
with leading zero bits where needed. (Alternatively, a table of the
translations could be provided in the standard.)
A trailing is allowed for a BOZ constant.
A nonpointer scalar object of type default typeless occupies a
single numeric storage unit. The category of numeric sequence types
is expanded to include default typeless.
Assignment
----------
A typeless intrinsic assignment statement is an intrinsic
assignment statement for which the variable or the expression is
typeless. Intrinsic assignment of a typeless expression to a
typeless, integer, real, or complex variable of the same bit_size
moves the bits from the expression value to the variable without
data conversions. Intrinsic assignment of a typeless, integer,
real, or complex expression to a typeless variable of the same
bit_size transfers the bits from the expression value to the
variable without data conversion. If the expression value has a
smaller bit_size than that of the variable, the expression value is
padded with bits of zero on the left so that the bit_sizes are
equal. If the expression value has a larger bit_size than that of
the variable, the expression value is truncated on the left to the
bit_size of the variable.
The typeless intrinsic assignment rules apply to data
initializations in declaration statements, DATA statements, and
default component initializations.
Note: Typeless assignment is not always the same as the result of
the TRANSFER intrinsic. The TRANSFER operation is based on the
memory image of the data, while typeless assignment is based on the
data values. For example, if S is an 32-bit integer array of size
8, and R is a 64-bit typeless array of size 8, R = TRANSFER(S,R)
will result in the values of S packed into the first 4 elements of
R. The way in which this packing is done will be different on
little endian and big endian machines. The typeless assignment, R
= S, will result in all 8 elements of R being defined, where R(i)
contains the bits from S(i) in the lower 32 bits, and 0 in the
upper 32 bits. Typeless assignment does not depend on which endian
the processors memory system uses.
Intrinsic operations
--------------------
The .and., .or., .xor., and .not. operators are defined for typeless
operands. .xor. is the exclusive or operation. The computations are
bitwise operations. The result of the expression evaluation is
typeless. If the operands are of unequal bit_size, the smaller is
padded on the left with zero bits before the operation is performed.
Optional feature: Extend the use of .and., .or., .xor., and .not. to
integer, real, and complex operands, with an
implied cast of those operands to typeless before
the operation is performed.
The .eq., .ne., .lt., .le., .gt., .ge., ==, /=, , and >=
operators are defined for typeless operands. If the operands are
of unequal KIND, the smaller is padded on the left with zero bits
before the operation is performed. Operands A and B are equal if
their corresponding bits are the same, and are unequal otherwise.
If A and B are unequal, and the leftmost unequal corresponding bit
of A is 1 and of B is 0, then A > B, otherwise A < B.
Optional feature: Extend the above relational operators to the case
where one operand is typeless and the other is
real, integer, or complex, with an implied cast
of the operand that is not typeless to typeless
before the operation is performed.
The numeric intrinsic operations are not defined for typeless
objects. To use a typeless object as an operand of a numeric
intrinsic operator, it must first be cast to an appropriate type
with a type conversion intrinsic function. The type conversion
functions are described later.
Formatted Input and Output
--------------------------
The format specifiers for typeless objects are I, B, O, and Z. For
output, if the .d part of the Bw.d, Ow.d, or Zw.d specifier is
omitted, the value assumed for d is >= 1 and large enough to
represent the bits in the io list item excluding leading 0 bits.
For the I format specifier, the object value is interpreted as an
unsigned base 10 integer. For input using the B, O, and Z edit
descriptors, the character string shall consist of binary, octal,
or hexadecimal digits in the respective input field. For input
using the I format, the input character string shall consist of an
unsigned decimal integer.
For list directed output, the format used is Zw.d where d is
(bit_size of the io list item + 3)/4 and w = d+1. For list directed
input, hexadecimal constants are valid for typeless io list items.
The number of bits required to represent the input value shall be
less than or equal to the bit_size of the corresponding io list
item. If it is less, the io list item is padded with zero bits on
the left.
Procedure actual and dummy arguments and pointers
-------------------------------------------------
Two objects have "compatible kind parameters" if they have the same
bit_sizes.
TYPELESS pointers can point to targets with compatible kind
parameters.
TYPELESS dummy arguments of non-intrinsic procedures are compatible
with actual arguments having compatible kind parameters.
Note: This feature can significantly simplify the interfaces for
procedures that move data in memory, but do not perform any
operations on the data. Classic examples include dusty-deck codes
containing MOVE or COPY routines, as well as some MPI library
routines written in C with dummy arguments of type void.
Modification of existing language intrinsics:
---------------------------------------------
Section 13.3 of the standard, describing Bit Models, is modified to
apply to typeless quantities. The specifications for several
intrinsic procedures are modified to allow typeless actual
arguments. Several of these have result values described in terms
of the bit model in section 13.3. Minimal changes would be needed
in those cases.
The I argument of ACHAR shall be of type integer or typeless. If I
is typeless, it is interpreted as an unsigned integer value.
The I argument of BIT_SIZE shall be of type integer or typeless.
The I argument of CHAR shall be of type integer or typeless. If I is
typeless, it is interpreted as an unsigned integer value.
The X and Y arguments of CMPLX shall be of type integer, real,
complex, or typeless. Note that typeless is a generalization and
replacement for the current "or a ".
The A arguments of DBLE shall be of type integer, real, complex, or
typeless. Note that typeless is a generalization and replacement for
the current "or a ".
The X argument of HUGE shall be of type integer, real, or typeless.
If X is typeless, the result value has all bits set to 1.
The I and J arguments of IAND, IEOR, and IOR shall be of type
integer or typeless, and have the same bit_size. The result is of
type integer if one of the arguments is integer, and typeless
otherwise.
The I argument of BTEST, IBCLR, IBITS, and IBSET shall be of type
integer or typeless.
The A argument of INT shall be of type integer, real, complex, or
typeless. Note that typeless is a generalization and replacement for
the current "or a ". If A is typeless, the
result value is that of an intrinsic assignment of A to an integer
variable of the specified KIND.
The I arguments of ISHFT and ISHFTC shall be of type integer or
typeless.
The X argument of KIND is specified as "any intrinsic type", so no
change is needed.
The A* arguments of MAX and MIN shall be of type integer, real,
character, or typeless. If the arguments are typeless, the meaning
of "largest" in the result value description is as specified by the
> operator for typeless values.
The ARRAY arguments of MAXLOC, MINLOC, MAXVAL, and MINVAL shall be
of type integer, real, character, or typeless.
The FROM and TO arguments of MVBITS shall be of type integer or
typeless.
The I argument of NOT shall be of type integer or typeless.
The A argument of REAL shall be of type integer, real, complex, or
typeless. Note that typeless is a generalization and replacement for
the current "or a ". If A is typeless, the
result value is that of an intrinsic assignment of A to a real
variable of the specified KIND.
Possible modifications to other intrinsic procedures:
-----------------------------------------------------
Several other intrinsic functions could be reasonably extended to
allow typeless arguments.
Changes to PRODUCT, SUM, DOT_PRODUCT, and MATMUL should be included
or omitted from the proposal as a group.
PRODUCT: The result value is an .and. reduction of the specified
elements of the typeless ARRAY argument.
SUM: The result value is an .xor. reduction of the specified
elements of the typeless ARRAY argument.
DOT_PRODUCT: The result value is SUM(VECTOR_A .and. VECTOR_B) for
typeless arguments VECTOR_A and VECTOR_B.
MATMUL: The value of each result element is SUM(MATRIX_A( ) .and.
MATRIX_B( )) where the argument subscripts are as specified for the
other argument types, and MATRIX_A and MATRIX_B are typeless. Note
that this is not the same as bit-matrix-multiply operation. That
could be added as a separate pair of intrinsics (for the .or. and
.xor. variants), but it is not currently part of the typeless
proposal.
The RANDOM_NUMBER subroutine could allow a typeless HARVEST argument
which would return with a value consisting of a random pattern of
bits.
New intrinsic functions:
------------------------
SELECTED_TYPELESS_KIND(Z) : Result: default scalar integer
Z : scalar integer
Z is a number of bits. The returned KIND value is that of the
smallest typeless kind that can contain Z bits. If no kind is
provided for the requested value of Z, the result is -1.
Note: The default typeless kind is
SELECTED_TYPELESS_KIND(BIT_SIZE(0))
TYPELESS(A[,KIND]) : Result: typeless
A : integer, real, complex, or typeless
KIND : integer initialization expression
The result is a typeless value with the same bit pattern as the
argument A, possible padded with zero bits on the left, or
truncated on the left if the bit_sizes of A and the result are not
equal. TYPELESS is an elemental function, and it cannot be passed
as an actual argument. If KIND is present, the kind type parameter
of the result is that specified by the value of KIND; otherwise the
kind type parameter of the result is that of default typeless.
POPCNT(I) : Result: integer, in range [0..bit_size(I)]
I : typeless or integer
The result is the number of bits set to 1 in the argument. This
function is adopted from HPF and extended to allow typeless
arguments. POPCNT is an elemental function, and it cannot be passed
as an actual argument. If I is integer, the result KIND is the
same as that of I. If I is typeless, the result KIND is that of an
integer with the same bit_size as the argument.
POPPAR(I) : Result: integer, 0 or 1
I : typeless or integer
The result is 0 if the number of bits set to 1 in the argument is
even, and 1 if the number of bits set to 1 in the argument is odd.
This function is adopted from HPF and extended to allow typeless
arguments. POPPAR is an elemental function, and it cannot be passed
as an actual argument. If I is integer, the result KIND is the
same as that of I. If I is typeless, the result KIND is that of an
integer with the same bit_size as the argument.
LEADZ(I) : Result: integer, in range [0..bit_size(I)]
I : typeless or integer
The result is the number of leading 0 bits in the argument. This
function is adopted from HPF and extended to allow typeless
arguments. LEADZ is an elemental function, and it cannot be passed
as an actual argument. If I is integer, the result KIND is the
same as that of I. If I is typeless, the result KIND is that of an
integer with the same bit_size as the argument.
TRAILZ(I) : Result: integer, in range [0..bit_size(I)]
I : typeless or integer
The result is the number of trailing 0 bits in the argument. TRAILZ
is an elemental function, and it cannot be passed as an actual
argument. If I is integer, the result KIND is the same as that of
I. If I is typeless, the result KIND is that of an integer with the
same bit_size as the argument.
SHIFTL(I,SHIFT) : Result: typeless
I : typeless or integer
SHIFT : integer, >= 0
The result is the value I shifted left by SHIFT bits, with 0 bits
filled on the right. If SHIFT > BIT_SIZE(I), the result is zero.
SHIFTL is an elemental function, and it cannot be passed as an
actual argument. If I is typeless, the result KIND is the same as
that of I. If I is integer, the result KIND is that of a typeless
value with the same bit_size as the argument.
SHIFTR(I,SHIFT) : Result: typeless
I : typeless or integer
SHIFT : integer, >= 0
The result is the value I shifted right by SHIFT bits, with 0 bits
filled on the left. If SHIFT > BIT_SIZE(I), the result is zero.
SHIFTR is an elemental function, and it cannot be passed as an
actual argument. If I is typeless, the result KIND is the same as
that of I. If I is integer, the result KIND is that of a typeless
value with the same bit_size as the argument.
SHIFTA(I,SHIFT) : Result: typeless
I : typeless or integer
SHIFT : integer, >= 0
The result is the value I shifted right by SHIFT bits, with copies
of the leftmost bit filled on the left. If SHIFT > BIT_SIZE(I), the
result is zero if the leftmost bit of I is 0, or HUGE(TYPELESS(I))
if the leftmost bit of I is 1. SHIFTA is an elemental function, and
it cannot be passed as an actual argument. If I is typeless, the
result KIND is the same as that of I. If I is integer, the result
KIND is that of a typeless value with the same bit_size as the
argument.
DSHIFTL(I,J,SHIFT) : Result: typeless
I : typeless or integer
J : same type and kind as I
SHIFT : integer, 0 <= SHIFT <= BIT_SIZE(I)
The result is the value of I shifted left by SHIFT bits, with the
rightmost SHIFT bits of I replaced by the leftmost SHIFT bits of J.
This is equivalent to concatenating I and J, shifting the combined
value left SHIFT bits, and keeping the left half. If I and J are
the same, the result is the same as a left circular shift. DSHIFTL
is an elemental function, and it cannot be passed as an actual
argument. If I is typeless, the result KIND is the same as that of
I. If I is integer, the result KIND is that of a typeless value
with the same bit_size as the argument.
DSHIFTR(I,J,SHIFT) : Result: typeless
I : typeless or integer
J : same type and kind as I
SHIFT : integer, 0 <= SHIFT <= BIT_SIZE(I)
The result is the value of J shifted right by SHIFT bits, and the
leftmost SHIFT bits of J replaced by the rightmost SHIFT bits of I.
This is equivalent to concatenating I and J, shifting the combined
value right SHIFT bits, and keeping the right half. If I and J are
the same, the result is the same as a right circular shift. DSHIFTR
is an elemental function, and it cannot be passed as an actual
argument. If I is typeless, the result KIND is the same as that of
I. If I is integer, the result KIND is that of a typeless value
with the same bit_size as the argument.
MASKL(I[,KIND]) : Result: typeless
I : integer, in range [0..bit_size(result)]
KIND : integer initialization expression
The result is a typeless value with the leftmost I bits set to 1
and the remaining bits set to 0. The value of I shall be >= 0 and
<= the bit_size of the result. MASKL is an elemental function, and
it cannot be passed as an actual argument. If KIND is present, the
kind type parameter of the result is that specified by the value of
KIND; otherwise the kind type parameter of the result is that of
default typeless.
MASKR(I[,KIND] ) : Result: typeless
I : integer, in range [0..bit_size(result)]
KIND : integer initialization expression
The result is a typeless value with the rightmost I bits set to 1
and the remaining bits set to 0. The value of I shall be >= 0 and
<= the bit_size of the result. MASKL is an elemental function, and
it cannot be passed as an actual argument. If KIND is present, the
kind type parameter of the result is that specified by the value of
KIND; otherwise the kind type parameter of the result is that of
default typeless.
MERGE_BITS(I,J,MASK) : Result: typeless
I : typeless
J : typeless, same kind as I
MASK : typeless, same kind as I
The result of a typeless value with bits from I if the
corresponding bits in MASK are 1 and the bits from J if the
corresponding bits in MASK are 0. Equivalent to (I .and. MASK)
.or. (J .and. (.not. MASK)) MERGE_BITS is an elemental function,
and it cannot be passed as an actual argument. The kind type
parameter of the result is the same as the kind type parameter of
I.
Interoperation with C:
----------------------
Typeless objects interoperate with C objects of the same bit_size,
including C unsigned integer objects. If a typeless object is the
actual argument corresponding to an unsigned integer dummy argument
of a C function, or the unsigned integer result of a C function is
assigned to a typeless variable, the I format can be used to output
the correct form of the C value.
History:
Paper 03-278r1 meeting 166 Initial proposal
04-244 167 Updated proposal
169 Spreadsheet version
05-150r1 171 Accepted as complete
------------------------------------------------------------------
Number: J3-048
Title: Write CSV files Using LDIO
Submitted By: J3
Status: For Consideration
References: 04-007 10.9
Basic Functionality:
Provide a quick and easy way to write files using the CSV (Comma
Separated Value) format.
Rationale:
CSV files (a/k/a Comma Separated Value) files are used by
spreadsheets and "higher level math" programs such as Mathematica,
MATLAB and Maple. These programs provide easy access to graphics
and other mathematically oriented amenities.
List directed input treats the comma as a separator, but the
separator is optionally blank or comma on output. If the separator
is blank, one or more blanks may be between values. A way to make
the optional separator a comma allows an easy way to write CSV
files, providing easy communications to spreadsheet programs and
other higher level math programs with built-in graphics, algebraic
manipulation, and other amenities useful with numeric programs, but
absent in standard Fortran.
CSV files are formatted, the simplest format from the user's
perspective is List Directed. So modify LDIO to serve CSV.
Estimated Impact:
Rather minor, the RTL must already reckon where to place a
separator in LDIO output, and must already recognize comma on LDIO
input.
Detailed Specification:
The idea is to modify list directed output as little as possible to
gain connectivity from Fortran programs to desktop applications via
CSV format.
The proposed solution is:
Add a new ACCESS form, ACCESS='CSV' which on output (and has no
effect on input)
1. Implies ACCESS='STREAM', and
2. When list directed, requires that the processor
not print the "r*" form of repeated values, and
3. When listed directed, disallows blanks as separator
(which means comma or semicolon is used as per
decimal mode), and
4. When listed directed, allows blanks on either side
of the separator as at present, and
5. When listed directed, disallows new records being
created (so one write gives one record), and
6. Allows explicit formats to be used as needed.
History:
Paper 05-108 meeting 171 Submitted
05-108r1 171 Accepted as complete
------------------------------------------------------------------
Number: J3-049
Title: Embed a decision within an expression
Submitted By: J3
Status: For consideration
Reference: 03-258r1, section 2.8.1; 04-192, 04-357r1 04-393
Basic Functionality:
Provide a mechanism to embed a decision within an expression
Rationale
If one needs to embed one of several values within an expression,
depending upon a condition, the available methods are
o Nearly duplicate the statement containing the expression with a
different entity within the different instances and select
between them using the condition,
o Copy one of the values into a temporary variable depending upon
the condition and use that temporary variable within the
expression, or
o Associate a pointer with one of the variables depending on the
condition --- if the entities to be selected are variables.
In the first case, assuming m alternatives for each of n entities
within the statement, m^n instances of the statement are needed.
In the second case, the program must endure the expenses of an
auxiliary variable and the time to copy it, both of which could be
substantial in the array case. In the third case, which only works
if the values are variables, the variables have to have the pointer
or target attribute, which could have negative implications for
optimization.
The same considerations apply if one needs to associate one of
several entities as an actual argument. It's even worse in the
case of using a temporary variable if the associated dummy argument
does not have INTENT(IN), because one needs to do the selection and
copying twice.
It would be useful to be able to embed a decision within an
expression. This would avoid all of the problems outlined above.
In the case of an actual argument or a target in a pointer
assignment, it would be useful to allow procedures or procedure
pointers to be the alternative entities.
Estimated Impact:
This is part of the proposal in J3 paper 04-393, whose antecedent
was 04-357r1. At J3 meeting 169, the proposal in 04-357r1 was
judged to be at 4 on the JKR scale. Surely this proposal, being
only part of the previous one, is not larger.
Detailed Specification:
Provide a mechanism, called here a "conditional form", to embed a
decision within an expression. The syntax shall provide for a
condition and two alternative entities.
If an actual argument is a conditional form, and the alternatives
are either variables or procedures, to be useful the selected
entity itself, rather than the value of it, must become the actual
argument. Indeed, in the case of an argument that is a procedure,
it does not have a value. No matter what syntax is used, if there
is no special description it cannot be called a function reference
or an operation, because the result would be a value separate from
the desired entity itself. One might think that it would be
acceptable to call it a function reference or operation that
returns a pointer associated with the appropriate alternative
entity, but that won't work either, because of the absurd outcome
of interp F95/74. That would also require the alternatives to have
the target attribute, which would have negative implications for
optimization. Maybe a new term that doesn't carry the baggage of
"pointer" or "target", such as "referent", could be used to
describe the result, allowing the form to be called a function
reference or an operation. That seems like a lot of work to invest
for one purpose.
It is important that the alternative that is not selected, and all
expressions within it, are not evaluated. The condition that
selects between the alternatives may be a proxy indicating the
nonexistence of values necessary for these evaluations.
If one of the alternative entities has the pointer attribute and
the other does not, the one that does not shall have the target
attribute, and the result has the target attribute. If the
alternative that has the pointer attribute is selected, the result
is its target.
Otherwise, the alternative entities shall have the same
characteristics. If one of them is the NULL intrinsic without an
argument, the result characteristics are inferred from the other.
If they are both the NULL intrinsic without an argument, the result
characteristics are inferred from the context of the appearance of
the conditional form, exactly as would be the case if the NULL
intrinsic had appeared on its own instead.
Examples:
Several syntaxes are possible. Two under consideration are similar
to a function reference, and similar to an operator.
A = B + IF ( X > 0.0, SQRT(X), 0.0 )
or
A = B + X > 0.0 ? SQRT(X) : 0.0
History:
Paper 04-192 meeting 167 Submitted
04-357r1 169 Kicked around
04-393 170 Kicked around some more
05-104r1 171 Accepted as complete
------------------------------------------------------------------