In the example given above the alignments illustated were ``identity mapping'' between array and template, and replicated alignments. More general alignment relations are possible.
For one thing, indices can be permuted:
DIMENSION B(N, N)
!HPF$ ALIGN B(I, J) WITH T(J, I)
maps B to T, but in a ``transposed'' manner: B (1, 2)
is mapped to T (2, 1), etc. More generally, a subscript of
an align target (not an alignee) can be a linear expression
in one of the alignment dummies (with integer expression coefficients).
For example
DIMENSION C(N / 2, N / 2)
!HPF$ ALIGN C(I, J) WITH T(N / 2 + I, 2 * J)
Figure 12 illustrates how C would be
aligned to T.
The rank of alignee and align-target do not have to match. A dimension of the alignee may be ``collapsed''; or some dimension of the align-target might be a constant--for example a scalar might be aligned to the first element of a one-dimensional template; or the alignee may be ``replicated'' over some dimensions of the template. As an example of collapsing:
DIMENSION D(N, N, N)
!HPF$ ALIGN D(I, J, K) WITH T(I, J)
The template element is independent of K. This means that
for fixed I, J, all elements of C differing only
in their third index mapped to the same template element.
Of course there are restrictions: as mentioned, the
expressions used to subscript a template must be linear in the alignment
dummies, with integer coefficients; each subscript can depend on at
most one of the alignment dummies (local to the ALIGN
directive); and each alignment dummy can appear in at most one of the subscript expressions for the template. Secondly, we should
say that there are various shorthand forms of the alignment directive
which were not described here--they don't add any new facilities.
The alignments described so far were all direct alignments
to templates. It is also allowed to align an array to another
array, using all the normal syntax of the ALIGN directive.
So the alignments of L_COL and U_ROW in the example
of the previous section could be written as
!HPF$ ALIGN L_COL(I) WITH A(I, *) !HPF$ ALIGN U_ROW(J) WITH A(*, J)In general, the meaning is that the alignee element is stored wherever the align-target array element is. Any such alignment can be written as an alignment to a template (provided the template is in scope). If there are several levels of indirection (array aligned to array aligned to array, etc) writing the ``ultimate alignment'' directly could be relatively complicated.
Finally, templates can be left completely implicit, with
DISTRIBUTE directives can applied directly to arrays. So, in
the example, the T directives could be omitted, and we could
add the directive
!HPF$ DISTRIBUTE A (CYCLIC, CYCLIC) ONTO PThe implicit template has the same shape as the array distributed. It is not allowed for any array to be both distributed in this way and to appear as an alignee in an
ALIGN directive. So
this idiom can always be regarded as shorthand for introduction of an
explicit template.
The last two conventions are particularly useful for procedure dummy arguments, because templates can't be explicitly passed through the subprogram interface.