J3/13-329r1
To: J3
From: Malcolm Cohen
Subject: UK-08 - Generalized reduction intrinsic
Date: 2013 October 16
Requirements and rationale
--------------------------
See N1975.
Specification
--------------
Add an intrinsic function that reduces an array by a user-defined
operation.
Similarly to the other reduction intrinsic functions,
(a) reduction of a single dimension shall be provided, and
(b) use of a logical mask array shall be supported.
The array to be reduced may be of any intrinsic or derived type. The
result for reduction of a single element shall be that element. The result
for reduction of zero elements shall be specifiable, and if not specified
this result shall be processor dependent.
The user-defined operation should be mathematically associative but need
not be computationally associative. In order to facilitate reduction of
arrays of such things as quaternions and matrices, commutativity will not
be required; in this, REDUCE will be different from CO_REDUCE. When more
than two elements are being reduced, the operation may be associatively
applied to elements and intermediate results in any order that does not
commute (swap) operands.
For users who require evaluation in strict array element order, we could
add an ORDERED=.TRUE. argument with that effect; to be most effective the
actual argument should be required to be constant. However, we do not
think that this case warrants the extra complication (and therefore it is
not part of the specifications).
Syntax
------
REDUCE ( ARRAY, OPERATION, DIM [, MASK ] [, IDENTITY]) or
REDUCE ( ARRAY, OPERATION [, MASK ] [, IDENTITY])
The OPERATION function shall be pure, but need not be elemental.
Edits (relative to 10-007r1)
----------------------------
[intro] Add a new extension description
"The new intrinsic function REDUCE performs user-specified array
reductions."
[322] Add at the appropriate place in Table 3.1:
"REDUCE & ( ARRAY, OPERATION, DIM [, MASK ] [, IDENTITY]) or
( ARRAY, OPERATION [, MASK] [, IDENTITY]) &
T & General reduction of array \\".
{NB: The line breaks here are immaterial, "&" indicates tab to the next
column, "\\" means end of that row.}
[382:2+] Add new subclause following 13.7.138:
"13.7.138a REDUCE ( ARRAY, OPERATION, DIM [, MASK ] [, IDENTITY]) or
REDUCE ( ARRAY, OPERATION [, MASK] [, IDENTITY])
<> General reduction of array.
<> Transformational function.
<>
ARRAY shall be an array of any type.
OPERATION shall be a pure function with two arguments of the same type
and type parameters as ARRAY. Its result shall have the same
type and type parameters as ARRAY. The arguments and result
shall not be polymorphic. OPERATION should implement a
mathematically associative operation. It need not be
commutative.
DIM shall be an integer scalar with a value in the range
1 <= DIM <= , where is the rank of ARRAY.
MASK (optional) shall be of type logical and shall be conformable
with ARRAY.
IDENTITY (optional) shall be scalar with the same type and type
parameters as ARRAY.
<> The result is of the same type and kind type
parameter as ARRAY. It is scalar if DIM is 1; otherwise, the result has
rank -1 and shape [d_1, d_2, ... , d_DIM-1, d_DIM+1, ... , d_n] where
[d_1, d_2, ... , d_n] is the shape of ARRAY.
<>
Case (i): The result of REDUCE (ARRAY, OPERATION) over the sequence of
values in ARRAY is the result of an iterative process. While
the sequence has more than one element, each iteration
involves the execution of r = OPERATION(x,y) for adjacent x
and y in the sequence, and the subsequent replacement of x and
y with r. The process continues until the sequence has only
one element which is the value of the reduction. If the
initial sequence is empty, the result has the value IDENTITY
if IDENTITY is present, and is processor dependent otherwise.
If OPERATION is not computationally associative, the value of
the result is processor dependent.
Case (ii): The result of REDUCE (ARRAY, OPERATION, MASK = MASK) is as
for Case (i) except that the initial value of the sequence is
only those elements of ARRAY for which the corresponding
element of MASK is true.
Case (iii): If ARRAY has rank one,
REDUCE (ARRAY, OPERATION, DIM = DIM [, MASK = MASK]) has a
value equal to that of
REDUCE (ARRAY, OPERATION [,MASK = MASK]).
Otherwise, the value of element
(s_1, s_2, ... , s_DIM-1, s_DIM+1, ... , s_n) of
REDUCE (ARRAY, OPERATION, DIM = DIM [ , MASK = MASK])
is equal to
REDUCE (ARRAY (s_1, s_2, ... , s_DIM-1, :, s_DIM+1,
... ,s_n), OPERATION [, MASK=MASK(s_1, s_2, ... , s_DIM-1,
:, s_DIM+1, ... , s_n)]).
<>
The following examples all use the function MY_MULT, which returns the
product of its two integer arguments.
Case (i): The value of REDUCE ([1, 2, 3], MY_MULT) is 6.
Case (ii): REDUCE (C, MY_MULT, MASK= C > 0, IDENTITY=1) forms the
product of the positive elements of C.
Case (iii): If B is the array 1 3 5
2 4 6
REDUCE (B, MY_MULT, DIM = 1) is [2, 12, 30] and
REDUCE (B, MY_MULT, DIM = 2) is [15, 48]."
===END===