To: J3 J3/21-203
From: Malcolm Cohen
Subject: Ramifications of 21-178 (integration issue?)
Date: 2021-October-25
1. Introduction
21-178 notes that IEEE_GET_FLAG and IEEE_GET_HALTING_MODE are described
inconsistently, in one place as (impure) elemental, and another as simple
(which includes pure) elemental.
21-202 is an interp request, because these are impure elemental in the
current standard F2018, but pure in F2003.
Looking closer at the subroutines defined by the IEEE modules, however,
reveals some inconsistencies. This paper addresses those inconsistencies.
2. Inconsistent?
(A) The "inquiry" subroutines.
Obviously (?) IEEE_GET_FLAG and IEEE_GET_HALTING_MODE are performing a kind
of inquiry, and have no side-effect, so it is perfectly reasonable that
they are considered to be pure.
Looking at IEEE_GET_ROUNDING_MODE and IEEE_GET_UNDERFLOW_MODE, we see that
these are classed as IMPURE subroutines, despite on the face of it having
no side-effect.
Similarly IEEE_GET_MODES and IEEE_GET_STATUS have no side-effect, and would
be safe to use in a parallel execution context, but they too are classified
as impure.
(B) The setting subroutines
The halting modes (one per exception) are restored on return from a
procedure that invoked IEEE_SET_HALTING_MODE. This means that
IEEE_SET_HALTING_MODE does not cause the invoking procedure to have a
side-effect that is visible in its caller. (If halting actually happens,
that will bring down the whole program down which is a pretty big side-
effect, but this is consistent with other means of error termination.)
It is further noted that these routines are only safe for pure procedures,
and not for other parallel contexts such as DO CONCURRENT, where indeed
they are prohibited despite being pure.
The rounding and underflow modes, like the halting modes, are likewise
restored on return from a procedure that invokes IEEE_SET_ROUNDING_MODE
or IEEE_SET_UNDERFLOW_MODE (or IEEE_SET_MODES), and therefore by the same
reasoning as for IEEE_SET_HALTING_MODE, they are safe to use in a parallel
execution context. Safer actually, as changing the underflow or rounding
mode does not potentially create an additional opportunity for termination!
Similarly, IEEE_SET_MODES merely sets all the modes in one call, so one
would expect that to be pure if the individual mode settings were pure.
Similarly, IEEE_SET_STATUS merely sets the flags and modes, and these will
be restored on exit from the procedure, so it is hard to see what is impure
about it.
3. Missing functionality
Having IEEE_SET_ROUNDING_MODE impure makes it virtually impossible to do
effective interval arithmetic in user-defined pure procedures.
By "effective", I mean the upper and lower bounds do not get unnecessarily
wider. Without the ability to set the rounding mode, the bounds will almost
always need to be made 2 ulps wider with ever operation.
4. Analysis
The IEEE modules were developed immediately after Fortran 95 was produced,
and PURE was completely new and easy to forget about.
That IEEE_GET_FLAG and IEEE_GET_HALTING_MODE are pure could be merely an
accident: because there are several exceptions, it makes sense for these
to operate elementally, and thus be described as elemental.
That is, it looks very much like the current purity/impurity state is a
mere happenstance occasioned by the plurality of exceptions and the
singularity of the rounding mode and the underflow mode.
5. Recommendation (specs/syntax)
All of these mode subroutines should be pure and simple, and forbidden
inside DO CONCURRENT like IEEE_GET_HALTING_MODE is.
Formally, the procedures
IEEE_GET_ROUNDING_MODE
IEEE_SET_ROUNDING_MODE
IEEE_GET_UNDERFLOW_MODE
IEEE_SET_UNDERFLOW_MODE
in IEEE_ARITHMETIC, and
IEEE_GET_MODES
IEEE_SET_MODES
IEEE_GET_STATUS
IEEE_SET_STATUS
in IEEE_EXCEPTIONS,
shall be specified to be pure and simple.
There is no new syntax.
6. Edits to 21-007r2
[xiii] Introduction, "Intrinsic procedures and modules" bullet,
insert somewhere
"The subroutines IEEE_GET_ROUNDING_MODE, IEEE_GET_UNDERFLOW_MODE,
IEEE_SET_ROUNDING_MODE, and IEEE_SET_UNDERFLOW_MODE from the intrinsic
module IEEE_ARITHMETIC, are now considered to be pure and simple.
The subroutines IEEE_GET_MODES, IEEE_GET_STATUS, IEEE_SET_MODES, and
IEEE_SET_STATUS from the intrinsic module IEEE_EXCEPTIONS, are now
considered to be pure and simple."
{Describe this.
Should we break this up into separate bullets for intrinsic procedures
and intrinsic modules? It is looking rather wall-of-texty.}
[195:38-39] 11.1.7.5 Additional semantics for DO CONCURRENT constructs,
C1144 "A reference to..."
add the three routines IEEE_GET_STATUS, IEEE_SET_MODES and
IEEE_SET_STATUS to the list in the constraint and alphabetize,
making the whole contraint read:
"C1144 A reference to the procedure IEEE_GET_FLAG, IEEE_GET_HALTING_MODE,
IEEE_GET_STATUS, IEEE_SET_HALTING_MODE, IEEE_SET_MODES, or
IEEE_SET_STATUS from the intrinsic module IEEE_EXCEPTIONS, shall
not appear within a DO CONCURRENT construct."
{Omitting IEEE_GET_MODES is safe because the modes cannot be changed.}
[196:1+] Immediately after that constraint, insert new constraint
"C1144a A reference to the procedure IEEE_SET_ROUNDING_MODE or
IEEE_SET_UNDERFLOW_MODE from the intrinsic module IEEE_ARITHMETIC
shall not appear within a DO CONCURRENT construct."
{Prohibit mode changes where we can see them.}
[466:9] 17.10 Summary of the procedures, p3,
delete line "S indicates... impure subroutine,".
{Will no longer be used.}
[466] In Table 17.2 IEEE_ARITHMETIC module procedure summary,
change all four lines with class "S" to class "SS".
[467] In Table 17.3 IEEE_EXCEPTIONS module procedure summary,
change all four lines with class "S" to class "SS".
[470:10] 17.11.7 IEEE_GET_MODES (MODES), p2 Class,
"Subroutine" -> "Simple subroutine".
[470:25] 17.11.8 IEEE_GET_ROUNDING_MODE (ROUND_VALUE [, RADIX]), p2 Class,
"Subroutine" -> "Simple subroutine".
[471:3] 17.11.9 IEEE_GET_STATUS (STATUS_VALUE), p2 Class,
"Subroutine" -> "Simple subroutine".
[471:16] 17.11.10 IEEE_GET_UNDERFLOW_MODE (GRADUAL), p2 Class,
"Subroutine" -> "Simple subroutine".
[483:30] 17.11.41 IEEE_SET_MODES (MODES), p2 Class,
"Subroutine" -> "Simple subroutine".
[484:7] 17.11.42 IEEE_SET_ROUNDING_MODE (ROUND_VALUE [, RADIX]), p2 Class,
"Subroutine" -> "Simple subroutine".
[484:28] 17.11.43 IEEE_SET_STATUS (STATUS_VALUE), p2 Class,
"Subroutine" -> "Simple subroutine".
[485:3] 17.11.44 IEEE_SET_UNDERFLOW_MODE (GRADUAL), p2 Class,
"Subroutine" -> "Simple subroutine".
===END===