Subject: hpff-doc: mapping-base.tex

From: Piyush Mehrotra <[email-masked]>
Date: Thu, 6 Jun 1996 13:38:20 -0500 (CDT)

---------------------------------------------------------------------------
[email-masked] is a mailing list for HPF 2.0 language specification
authors and editors.  Instructions for adding or deleting yourself from this
list appear at the bottom of this message.
---------------------------------------------------------------------------

% File: mapping-base.tex

% Contents:
% Mapping constructs for local variables for HPF 2.0 document,
% including
%       DISTRIBUTE
%       ALIGN
%       SEQUENCE
%       some of pointer mappings
%       equivalence of mappings

% Revision history:
% May-10-96     Created by Charles Koelbel, Rice University
%               (from HPF 1.1 document and HPF 2.0 proposals)
% May-22-96     Chapter updated by Piyush Mehrotra
%

\chapter{Data Mapping}
\label{ch-mapping-base}

{\em
Comments on this chpater should be directed to 
Piyush Mehrotra ({\tt [email-masked]}), 
Carl Offner ({\tt [email-masked]}), 
Guy Steele ({\tt [email-masked]})
and {\tt [email-masked]}.
Please use ``{\tt Comments on Mapping}'' as the {\tt Subject:}
line.
\par
}
\begin{new}
  {\em This chapter is based on the old chapter on Data Mappings.
I have removed all references to dynamic remapping of data
({\tt DYNAMIC, REDISTRIBUTE} and {\tt REALIGN}),
including those in the model section. Also
removed all references to mapping of aggregate covers 
and sequential objects from t eh section on storage and sequence association.
I have also replaced all
references to Fortran 90 with plain Fortran. -- PM}
\end{new}

HPF data alignment and distributions directives allow the
programmer to advise the compiler
how to assign array elements to processor memories.
This chapter discusses the basic data mapping features applicable,
particularly those that are meaningful within a single scoping unit.
Chapter~\ref{ch-mapping-subr} will discuss mapping features that apply
when mapped variables are passed as subprogram arguments.

\section{Model}

HPF adds directives to Fortran to allow the user to advise the
compiler on the allocation of data objects to processor memories.  The
model is that there is a two-level mapping of data objects to memory
regions, referred to as ``abstract processors.''  Data objects
(typically array elements) are first {\it aligned} relative to one
another; this group of arrays is then {\it distributed} onto a
rectilinear arrangement of abstract processors.  (The implementation
then uses the same number, or perhaps some smaller number, of physical
processors to implement these abstract processors.  This mapping of
abstract processors to physical processors is
implementation-dependent.)

The following diagram illustrates the model:

\begin{center}

\setlength{\unitlength}{0.01in}
\begin{picture}(600,240)(0,30)
\thicklines
\put(100,150){\circle{50}}
\put(242,150){\circle{50}}
\put(383,150){\circle{50}}
\put(525,150){\circle{50}}
\put(125,150){\vector(1,0){92}}
\put(267,150){\vector(1,0){91}}
\put(408,150){\vector(1,0){92}}
\put(56,190){\shortstack{Arrays or\strut\\other objects\strut}}
\put(192,190){\shortstack{Group of\strut\\aligned objects\strut}}
\put(328,190){\shortstack{Abstract\strut\\processors as a\strut
                \\user-declared\strut\\Cartesian mesh\strut}}
\put(494,190){\shortstack{Physical\strut\\processors\strut}}
\put(150,100){\tt ALIGN}
\put(270,100){\tt DISTRIBUTE}
\put(400,50){\shortstack{Optional\strut\\implementation-\strut
                \\dependent\strut\\directive\strut}}
\end{picture}

\end{center}

The underlying assumptions are that an operation on two or more data
objects is likely to be carried out much faster if they all reside in
the same processor, and that it may be possible to carry out many
such operations concurrently if they can be performed on different
processors.

Fortran provides a number of features, notably array syntax, that
make it easy for a compiler to determine that many operations may be
carried out concurrently.  The HPF directives provide a way to inform
the compiler of the recommendation that certain data objects should
reside in the same processor: if two data objects are mapped (via the
two-level mapping of alignment and distribution) to the same abstract
processor, it is a strong recommendation to the implementation that
they ought to reside in the same physical processor.  There is also a
provision for recommending that a data object be stored in multiple
locations, which may complicate any updating of the object but makes
it faster for multiple processors to read the object.

There is a clear separation between directives that serve as
specification statements and directives that serve as executable
statements (in the sense of the Fortran standards).  Specification
statements are carried out on entry to a program unit, as
if all at once; only then are executable statements carried out.
(While it is often convenient to think of specification statements as
being handled at compile time, some of them contain specification
expressions, which are permitted to depend on run-time quantities
such as dummy arguments, and so the values of these expressions may
not be available until run time, specifically the very moment that
program control enters the scoping unit.)

The basic concept is that every array (indeed, every object) is created 
with {\em some\/} alignment to an entity, which in turn has {\em some\/} 
distribution onto {\em some\/} arrangement of abstract processors.  
If the specification statements contain
explicit specification directives specifying the alignment of an
array {\tt A} with respect to another array {\tt B}, then the
distribution of {\tt A} will be dictated by the distribution of {\tt
B}; otherwise, the distribution of {\tt A} itself may be specified
explicitly.  In either case, any such explicit declarative
information is used when the array is created.  

\begin{implementors}
This model gives a better picture of the actual amount of work that
needs to be done than a model that says ``the array is created in some
default location, and then realigned and/or redistributed if there is
an explicit directive.''  Using {\tt ALIGN} and {\tt DISTRIBUTE}
specification directives doesn't have to cause any more work at run
time than using the implementation defaults.
\end{implementors}

In the case of an allocatable object, we say that the object is
created whenever it is allocated.  Specification directives for
allocatable objects 
may appear in the
{\it specification-part} of a program unit, but take effect each time the
array is created, rather than on entry to the scoping unit.

Alignment is considered an {\em attribute\/} (in the Fortran sense)
of a data object.  If an object {\tt A} is aligned 
with an object {\tt B}, which in turn is already aligned
to an object {\tt C}, this is regarded as an alignment of {\tt A} with
{\tt C} directly, with {\tt B} serving only as an intermediary at the
time of specification.
We say that {\tt A} is {\it immediately aligned} with {\tt
B} but {\it ultimately aligned} with {\tt C}.  If an object is not
explicitly aligned with another object, we say that it is ultimately
aligned with itself.  The alignment relationships form a tree with
everything ultimately aligned to the object at the root of the tree;
however, the tree is always immediately ``collapsed'' so that every
object is related directly to the root.  

Every object which is the root of an alignment tree has an associated 
{\em template\/} or index space.  Typically, this template has the same 
rank and size in each dimension as the object associated with it.  (The 
most important exception to this rule is dummy arguments with the {\tt 
INHERIT} attribute, described in Section~\ref{INHERIT-SECTION}.)  
We often refer to ``the template for an array,'' which means the 
template of the object to which the array is ultimately aligned.  (When 
an explicit {\tt TEMPLATE} (see Section~\ref{TEMPLATE-SECTION}) is 
used, this may be simply the template to which the array is explicitly 
aligned.)
        
The {\em distribution\/} step of the HPF model technically applies to 
the template of an array, although because of the close relationship 
noted above we often speak loosely of the distribution of an array.  
Distribution partitions the template among a set of abstract processors 
according to a given pattern.  The combination of alignment (from arrays 
to templates) and distribution (from templates to processors) thus 
determines the relationship of an array to the processors; we refer to 
this relationship as the {\em mapping\/} of the array.  (These remarks 
also apply to a scalar, which may be regarded as having an index space 
whose sole position is indicated by an empty list of subscripts.)

Every object is created as if according to some complete set of
specification directives; if the program does not include complete
specifications for the mapping of some object, the compiler provides
defaults.  By default an object is not aligned with any other object;
it is ultimately aligned with itself.  The default distribution is
implementation-dependent, but must be expressible as explicit
directives for that implementation.  
Identically declared
objects need not be provided with identical default distribution
specifications; the compiler may, for example, take into account the
contexts in which objects are used in executable code.  The programmer
may force identically declared objects to have identical distributions
by specifying such distributions explicitly.  (On the other hand,
identically declared processor arrangements {\it are} guaranteed to
represent ``the same processors arranged the same way.''  This is
discussed in more detail in Section~\ref{PROCESSORS-SECTION}.)

Sometimes it is desirable to consider a large index space with
which several smaller arrays are to be aligned, but not to
declare any array that spans the entire index space.
HPF allows one to declare a {\tt TEMPLATE}, which is like an array
whose elements have no content and therefore occupy no storage;
it is merely an abstract index space that can be distributed and
with which arrays may be aligned.

An object is considered to be {\it explicitly mapped}
if it appears in an HPF mapping directive within the scoping
unit in which it is declared;  otherwise it is
{\it implicitly mapped}. A mapping directive is an {\tt ALIGN},
or {\tt DISTRIBUTE},  
or {\tt INHERIT}
directive, or any directive that confers an alignment, a
distribution, or the {\tt INHERIT} 
attribute.

\section{Syntax of Data Alignment and Distribution Directives}

Specification directives in HPF have two forms: specification
statements, analogous to the {\tt DIMENSION} and {\tt ALLOCATABLE}
statements of Fortran;
and an attribute form analogous to type declaration statements
in Fortran using the ``{\tt ::}'' punctuation.

The attribute form allows more than one attribute to be described
in a single directive.  HPF goes beyond Fortran in not requiring
that the first attribute, or indeed any of them, be a type specifier.

                                                                        \BNF
combined-directive         \IS  combined-attribute-list :: combined-decl-list

combined-attribute         \IS  ALIGN align-attribute-stuff
                           \OR  DISTRIBUTE dist-attribute-stuff
                           \OR  INHERIT
                           \OR  TEMPLATE
                           \OR  PROCESSORS
                           \OR  DIMENSION ( explicit-shape-spec-list )
combined-decl-list       \IS hpf-entity [(explicit-shape spec-list)]
                            \OR object-name
hpf-entity                       \IS processors-name
                            \OR template-name
                                                                        \FNB

The {\tt INHERIT} attribute is related to subroutine call conventions
and will be discussed in Section~\ref{ch-mapping-subr}.
\begin{constraints}

\item The same {\it combined-attribute} must not appear more 
than once in a given {\it combined-directive}.

\item If the {\tt DIMENSION} attribute appears in a {\it
combined-directive}, any entity to which it applies must be declared
with the HPF {\tt TEMPLATE} or {\tt PROCESSORS} type specifier.

\end{constraints}

The following rules constrain the declaration of various attributes,
whether in separate directives or in a combined-directive.

If the {\tt DISTRIBUTE} attribute is present, then every name declared in the
{\it combined-decl-list} is considered to be a {\it distributee} and is subject
to the constraints listed in section~\ref{DISTRIBUTE-SECTION}.

If the {\tt ALIGN} attribute is present, then every name declared in the
{\it entity-decl-list} is considered to be an {\it alignee} and is subject
to the constraints listed in section~\ref{ALIGN-SECTION}.

The HPF keywords {\tt PROCESSORS} and {\tt TEMPLATE} play the role of
type specifiers in declaring processor arrangements and templates.
The HPF keywords {\tt ALIGN}, {\tt DISTRIBUTE}, 
and {\tt INHERIT} play the role of attributes.  Attributes referring to
processor arrangements, to templates, or to entities with other types
(such as {\tt REAL}) may be combined in an HPF directive without
having the type specifier appear.

No entity may be given a particular attribute more than once.

Dimension information may be specified after an {\it hpf-entity} or in a
{\tt DIMENSION} attribute.  If both are present, the one after the
{\it object-name} overrides the {\tt DIMENSION} attribute (this is consistent
with the Fortran standard).  For example, in:
                                                                        \CODE
!HPF$ TEMPLATE,DIMENSION(64,64) :: A,B,C(32,32),D
                                                                        \EDOC
{\tt A}, {\tt B}, and {\tt D} are \( 64 \times 64 \) templates; {\tt C}
is \( 32 \times 32 \).

Directives mapping a variable must be in the same module scoping unit
where the variable is declared.  

If a specification expression includes a reference to the value of
an element of an array specified in the same specification-part,
any explicit mapping or {\tt INHERIT} attribute for the array
must be completely specified in prior specification-directives.
(This restriction is inspired by and extends
section 7.1.6.2 of the Fortran standard, which states in part:
If a specification expression includes a reference to the value of
an element of an array specified in the same specification-part,
the array bounds must be specified in a prior declaration.)

A comment on asterisks: The asterisk character ``{\tt *}'' appears
in the syntax rules for HPF alignment and distribution directives
in three distinct roles:
\begin{itemize}
\item  When a lone asterisk appears as a member of a parenthesized
list, it indicates either a collapsed mapping, wherein many
elements of an array may be mapped to the same abstract processor,
or a replicated mapping, wherein each element of an array may be mapped
to many abstract processors.   See the syntax rules for {\it align-source}
and {\it align-subscript} (see Section \ref{ALIGN-SECTION})
and for {\it dist-format} (see Section \ref{DISTRIBUTE-SECTION}).

\item When an asterisk appears in an {\it align-subscript-use}
expression, it represents the usual integer multiplication operator.

\item When an asterisk appears before a left parenthesis ``{\tt (}''
or after the keyword {\tt WITH} or {\tt ONTO}, it indicates that the
directive constitutes an assertion about the {\it current} mapping
of a dummy argument on entry to a subprogram, rather than a request
for a {\it desired} mapping of that dummy argument.  This use of
the asterisk may appear {\it only} in directives that apply to
dummy arguments (see Chapter~\ref{ch-mapping-subr}).

\end{itemize}

The first two of these uses are discussed in this chapter.  The last
is a subprogram interface issue and will be detailed in
Chapter~\ref{ch-mapping-subr}.

\section{DISTRIBUTE Directive}
\label{DISTRIBUTE-SECTION}

The {\tt DISTRIBUTE} directive specifies a mapping of data objects
to abstract processors in a processor arrangement.
For example,
                                                                        \CODE
      REAL SALAMI(10000)
!HPF$ DISTRIBUTE SALAMI(BLOCK)
                                                                        \EDOC
specifies that the array {\tt SALAMI} should be distributed across
some set of abstract processors by slicing it uniformly into blocks of
contiguous elements.  If there are 50 processors, the directive
implies that the array should be divided into groups of 200 elements,
with {\tt SALAMI(1:200)} mapped to the first processor,
{\tt SALAMI(201:400)} mapped to the second processor, and so on.
If there is only one processor, the entire array is mapped to that processor
as a single block of 10000 elements.

The block size may be specified explicitly:
                                                                        \CODE
      REAL WEISSWURST(10000)
!HPF$ DISTRIBUTE WEISSWURST(BLOCK(256))
                                                                        \EDOC
This specifies that groups of exactly 256 elements should be
mapped to successive abstract processors.
(There must be at least \( \lceil 10000/256 \rceil = 40 \) abstract processors
if the directive is to be satisfied.  The fortieth processor
will contain a partial block of only 16 elements, namely
{\tt WEISSWURST(9985:10000)}.)

HPF also provides a cyclic distribution format:
                                                                        \CODE
      REAL DECK_OF_CARDS(52)
!HPF$ DISTRIBUTE DECK_OF_CARDS(CYCLIC)
                                                                        \EDOC
If there are 4 abstract processors,
the first processor will contain {\tt DECK_OF_CARDS(1:49:4)},
the second processor will contain {\tt DECK_OF_CARDS(2:50:4)},
the third processor will contain {\tt DECK_OF_CARDS(3:51:4)},
and the fourth processor will contain {\tt DECK_OF_CARDS(4:52:4)}.
Successive array elements are dealt out to successive abstract processors
in round-robin fashion.

Distributions may be specified independently for each dimension of a
multidimensional array:
                                                                        \CODE
      INTEGER CHESS_BOARD(8,8), GO_BOARD(19,19)
!HPF$ DISTRIBUTE CHESS_BOARD(BLOCK, BLOCK)
!HPF$ DISTRIBUTE GO_BOARD(CYCLIC,*)
                                                                        \EDOC
The {\tt CHESS_BOARD} array will be carved up into contiguous
rectangular patches, which will be distributed onto a two-dimensional
arrangement of abstract processors.  The {\tt GO_BOARD} array will have its
rows distributed cyclically over a one-dimensional arrangement of
abstract processors.  (The ``{\tt *}'' specifies that {\tt GO_BOARD} is not to
be distributed along its second axis; thus an entire row is to be
distributed as one object.  This is sometimes called ``on-processor''
distribution.)

The {\tt DISTRIBUTE} directive may appear only in the {\it specification-part}
of a scoping unit  
and can contain only a {\it specification-expr} as the
argument to a {\tt BLOCK} or {\tt CYCLIC} option.

Formally, the syntax of the {\tt DISTRIBUTE}
directive is:

                                                                        \BNF
distribute-directive       \IS  DISTRIBUTE distributee dist-directive-stuff

dist-directive-stuff       \IS  dist-format-clause [ dist-onto-clause ]

dist-attribute-stuff       \IS  dist-directive-stuff
                           \OR  dist-onto-clause
distributee                \IS  object-name
                           \OR  template-name

dist-format-clause         \IS  ( dist-format-list )
                           \OR  * ( dist-format-list )
                           \OR  *

dist-format                \IS  BLOCK  [ ( int-expr ) ]
                           \OR  CYCLIC [ ( int-expr ) ]
                           \OR  *

dist-onto-clause           \IS  ONTO dist-target

dist-target                \IS  processors-name
                           \OR  * processors-name
                           \OR  *
                                                                        \FNB

The full syntax is given here for completeness, however some of the
forms will only be discussed in Chapter~\ref{ch-mapping-subr}.  These
``interprocedural'' forms are:
\begin{itemize}
\item The last two options of rule~\ref{dist-format-clause-rule} (containing
the {\tt *} form)
\item The last two options of rule~\ref{dist-target-rule} (containing
the {\tt *} form)
\end{itemize}

\begin{constraints}
\item An {\it object-name} mentioned as a {\it distributee}
must be a simple name and not a subobject designator.

\item An {\it object-name} mentioned as a {\it distributee} may not
appear as an {\it alignee}.

\item An {\it object-name} mentioned as a {\it distributee} may not
have the {\tt POINTER} attribute.

\item If a {\it dist-format-list} is specified, its length must
equal the rank of each {\it distributee}.

\item If both a {\it dist-format-list} and a {\it processors-name} appear, the
number of elements of the {\it dist-format-list} that are not ``{\tt *}''
must equal the rank of the named processor arrangement.

\item If a {\it processors-name} appears but not a {\it dist-format-list}, the
rank of each {\it distributee}
must equal the rank of the named processor arrangement.

\item If either the {\it dist-format-clause} or the {\it dist-target}
in a {\tt DISTRIBUTE} directive begins with ``{\tt *}'' then every {\it distributee}
must be a dummy argument.

\item Any {\it int-expr} appearing in a {\it dist-format} of a
{\tt DISTRIBUTE} directive must be a {\it specification-expr}.

\end{constraints}

Note that the possibility of a {\tt DISTRIBUTE} directive of the form
                                                                        \ICODE
!HPF$ DISTRIBUTE dist-attribute-stuff :: distributee-list
                                                                        \EDOC
is covered by syntax rule \ref{combined-directive-rule} for a
{\it combined-directive}.

Examples:
                                                                        \CODE
!HPF$ DISTRIBUTE D1(BLOCK)
!HPF$ DISTRIBUTE (BLOCK,*,BLOCK) ONTO SQUARE:: D2,D3,D4
                                                                        \EDOC

The meanings of the alternatives for {\it dist-format} are given below.

Define the ceiling division function {\tt CD(J,K)~=~(J+K-1)/K} (using
Fortran integer arithmetic with truncation toward zero.)

Define the ceiling remainder function {\tt CR(J,K)~=~J-K*CD(J,K)}.

The dimensions of a processor arrangement appearing as a {\it
dist-target} are said to {\it correspond} in left-to-right order with
those dimensions of a {\it distributee} for which the corresponding
{\it dist-format} is not {\tt *}.  In the example above, processor
arrangement {\tt SQUARE} must be two-dimensional; its first dimension
corresponds to the first dimensions of {\tt D2}, {\tt D3}, and {\tt D4}
and its second dimension corresponds to the third dimensions of {\tt
D2}, {\tt D3}, and {\tt D4}.

Let \(d\) be the size of a {\it distributee} in a certain dimension and
let \(p\) be the size of the processor arrangement in the corresponding
dimension.  For simplicity, assume all dimensions have a lower bound of
1.  Then {\tt BLOCK(\(m\))} means that a {\it distributee} position
whose index along that dimension is \(j\) is mapped to an abstract
processor whose index along the corresponding dimension of the
processor arrangement is {\tt CD(\(j\),\(m\))} (note that \(m \times p
\geq d\) must be true), and is position number {\tt
\(m\)+CR(\(j\),\(m\))} among positions mapped to that abstract
processor.  The first {\it distributee} position in abstract processor
\(k\) along that axis is position number {\tt 1+\(m\)*(\(k\)-1)}.

The block size \(m\) must be a positive integer.

{\tt BLOCK} by definition means the same as {\tt
BLOCK(CD(\(d\),\(p\)))}.

{\tt CYCLIC(\(m\))} means that a {\it distributee} position whose index
along that dimension is \(j\) is mapped to an abstract processor whose
index along the corresponding dimension of the processor arrangement is
{\tt 1+MODULO(CD(\(j\),\(m\))-1,\(p\))}.  The first {\it distributee}
position in abstract processor \(k\) along that axis is position number
{\tt 1+\(m\)*(\(k\)-1)}.

The block size \(m\) must be a positive integer.

{\tt CYCLIC} by definition means the same as {\tt CYCLIC(1)}.

{\tt CYCLIC(\(m\))} and {\tt BLOCK(\(m\))} imply the same distribution
when \( m \times p \geq d \), but {\tt BLOCK(\(m\))} additionally
asserts that the distribution will not wrap around in a cyclic manner,
which a compiler cannot determine at compile time if \(m\) is not
constant.  Note that {\tt CYCLIC} and {\tt BLOCK} (without argument
expressions) do not imply the same distribution unless \( p \geq d \),
a degenerate case in which the block size is 1 and the distribution
does not wrap around.

Suppose that we have 16 abstract processors and an array of length 100:
                                                                        \CODE
!HPF$ PROCESSORS SEDECIM(16)
      REAL CENTURY(100)
                                                                        \EDOC
Distributing the array {\tt BLOCK} (which in this case would mean
the same as {\tt BLOCK(7)}):
                                                                        \CODE
!HPF$ DISTRIBUTE CENTURY(BLOCK) ONTO SEDECIM
                                                                        \EDOC
results in this mapping of array elements onto abstract processors:
\begin{center}
\setlength{\unitlength}{0.01in}
\begin{picture}(560,200)(0,0)
\put(0,175){\makebox(35,25){\small\rm 1}}
\put(35,175){\makebox(35,25){\small\rm 2}}
\put(70,175){\makebox(35,25){\small\rm 3}}
\put(105,175){\makebox(35,25){\small\rm 4}}
\put(140,175){\makebox(35,25){\small\rm 5}}
\put(175,175){\makebox(35,25){\small\rm 6}}
\put(210,175){\makebox(35,25){\small\rm 7}}
\put(245,175){\makebox(35,25){\small\rm 8}}
\put(280,175){\makebox(35,25){\small\rm 9}}
\put(315,175){\makebox(35,25){\small\rm 10}}
\put(350,175){\makebox(35,25){\small\rm 11}}
\put(385,175){\makebox(35,25){\small\rm 12}}
\put(420,175){\makebox(35,25){\small\rm 13}}
\put(455,175){\makebox(35,25){\small\rm 14}}
\put(490,175){\makebox(35,25){\small\rm 15}}
\put(525,175){\makebox(35,25){\small\rm 16}}
\thinlines
\multiput(0,25)(0,25){6}{\line(1,0){560}}
\thicklines
\multiput(0,0)(0,175){2}{\line(1,0){560}}
\multiput(0,0)(35,0){17}{\line(0,1){175}}
\put(0,150){\makebox(35,25){\tt 1}}
\put(0,125){\makebox(35,25){\tt 2}}
\put(0,100){\makebox(35,25){\tt 3}}
\put(0,75){\makebox(35,25){\tt 4}}
\put(0,50){\makebox(35,25){\tt 5}}
\put(0,25){\makebox(35,25){\tt 6}}
\put(0,0){\makebox(35,25){\tt 7}}
\put(35,150){\makebox(35,25){\tt 8}}
\put(35,125){\makebox(35,25){\tt 9}}
\put(35,100){\makebox(35,25){\tt 10}}
\put(35,75){\makebox(35,25){\tt 11}}
\put(35,50){\makebox(35,25){\tt 12}}
\put(35,25){\makebox(35,25){\tt 13}}
\put(35,0){\makebox(35,25){\tt 14}}
\put(70,150){\makebox(35,25){\tt 15}}
\put(70,125){\makebox(35,25){\tt 16}}
\put(70,100){\makebox(35,25){\tt 17}}
\put(70,75){\makebox(35,25){\tt 18}}
\put(70,50){\makebox(35,25){\tt 19}}
\put(70,25){\makebox(35,25){\tt 20}}
\put(70,0){\makebox(35,25){\tt 21}}
\put(105,150){\makebox(35,25){\tt 22}}
\put(105,125){\makebox(35,25){\tt 23}}
\put(105,100){\makebox(35,25){\tt 24}}
\put(105,75){\makebox(35,25){\tt 25}}
\put(105,50){\makebox(35,25){\tt 26}}
\put(105,25){\makebox(35,25){\tt 27}}
\put(105,0){\makebox(35,25){\tt 28}}
\put(140,150){\makebox(35,25){\tt 29}}
\put(140,125){\makebox(35,25){\tt 30}}
\put(140,100){\makebox(35,25){\tt 31}}
\put(140,75){\makebox(35,25){\tt 32}}
\put(140,50){\makebox(35,25){\tt 33}}
\put(140,25){\makebox(35,25){\tt 34}}
\put(140,0){\makebox(35,25){\tt 35}}
\put(175,150){\makebox(35,25){\tt 36}}
\put(175,125){\makebox(35,25){\tt 37}}
\put(175,100){\makebox(35,25){\tt 38}}
\put(175,75){\makebox(35,25){\tt 39}}
\put(175,50){\makebox(35,25){\tt 40}}
\put(175,25){\makebox(35,25){\tt 41}}
\put(175,0){\makebox(35,25){\tt 42}}
\put(210,150){\makebox(35,25){\tt 43}}
\put(210,125){\makebox(35,25){\tt 44}}
\put(210,100){\makebox(35,25){\tt 45}}
\put(210,75){\makebox(35,25){\tt 46}}
\put(210,50){\makebox(35,25){\tt 47}}
\put(210,25){\makebox(35,25){\tt 48}}
\put(210,0){\makebox(35,25){\tt 49}}
\put(245,150){\makebox(35,25){\tt 50}}
\put(245,125){\makebox(35,25){\tt 51}}
\put(245,100){\makebox(35,25){\tt 52}}
\put(245,75){\makebox(35,25){\tt 53}}
\put(245,50){\makebox(35,25){\tt 54}}
\put(245,25){\makebox(35,25){\tt 55}}
\put(245,0){\makebox(35,25){\tt 56}}
\put(280,150){\makebox(35,25){\tt 57}}
\put(280,125){\makebox(35,25){\tt 58}}
\put(280,100){\makebox(35,25){\tt 59}}
\put(280,75){\makebox(35,25){\tt 60}}
\put(280,50){\makebox(35,25){\tt 61}}
\put(280,25){\makebox(35,25){\tt 62}}
\put(280,0){\makebox(35,25){\tt 63}}
\put(315,150){\makebox(35,25){\tt 64}}
\put(315,125){\makebox(35,25){\tt 65}}
\put(315,100){\makebox(35,25){\tt 66}}
\put(315,75){\makebox(35,25){\tt 67}}
\put(315,50){\makebox(35,25){\tt 68}}
\put(315,25){\makebox(35,25){\tt 69}}
\put(315,0){\makebox(35,25){\tt 70}}
\put(350,150){\makebox(35,25){\tt 71}}
\put(350,125){\makebox(35,25){\tt 72}}
\put(350,100){\makebox(35,25){\tt 73}}
\put(350,75){\makebox(35,25){\tt 74}}
\put(350,50){\makebox(35,25){\tt 75}}
\put(350,25){\makebox(35,25){\tt 76}}
\put(350,0){\makebox(35,25){\tt 77}}
\put(385,150){\makebox(35,25){\tt 78}}
\put(385,125){\makebox(35,25){\tt 79}}
\put(385,100){\makebox(35,25){\tt 80}}
\put(385,75){\makebox(35,25){\tt 81}}
\put(385,50){\makebox(35,25){\tt 82}}
\put(385,25){\makebox(35,25){\tt 83}}
\put(385,0){\makebox(35,25){\tt 84}}
\put(420,150){\makebox(35,25){\tt 85}}
\put(420,125){\makebox(35,25){\tt 86}}
\put(420,100){\makebox(35,25){\tt 87}}
\put(420,75){\makebox(35,25){\tt 88}}
\put(420,50){\makebox(35,25){\tt 89}}
\put(420,25){\makebox(35,25){\tt 90}}
\put(420,0){\makebox(35,25){\tt 91}}
\put(455,150){\makebox(35,25){\tt 92}}
\put(455,125){\makebox(35,25){\tt 93}}
\put(455,100){\makebox(35,25){\tt 94}}
\put(455,75){\makebox(35,25){\tt 95}}
\put(455,50){\makebox(35,25){\tt 96}}
\put(455,25){\makebox(35,25){\tt 97}}
\put(455,0){\makebox(35,25){\tt 98}}
\put(490,150){\makebox(35,25){\tt 99}}
\put(490,125){\makebox(35,25){\tt 100}}
\end{picture}
\end{center}
Distributing the array {\tt BLOCK(8)}:
                                                                        \CODE
!HPF$ DISTRIBUTE CENTURY(BLOCK(8)) ONTO SEDECIM
                                                                        \EDOC
results in this mapping of array elements onto abstract processors:
\begin{center}
\setlength{\unitlength}{0.01in}
\begin{picture}(560,225)(0,0)
\put(0,200){\makebox(35,25){\small\rm 1}}
\put(35,200){\makebox(35,25){\small\rm 2}}
\put(70,200){\makebox(35,25){\small\rm 3}}
\put(105,200){\makebox(35,25){\small\rm 4}}
\put(140,200){\makebox(35,25){\small\rm 5}}
\put(175,200){\makebox(35,25){\small\rm 6}}
\put(210,200){\makebox(35,25){\small\rm 7}}
\put(245,200){\makebox(35,25){\small\rm 8}}
\put(280,200){\makebox(35,25){\small\rm 9}}
\put(315,200){\makebox(35,25){\small\rm 10}}
\put(350,200){\makebox(35,25){\small\rm 11}}
\put(385,200){\makebox(35,25){\small\rm 12}}
\put(420,200){\makebox(35,25){\small\rm 13}}
\put(455,200){\makebox(35,25){\small\rm 14}}
\put(490,200){\makebox(35,25){\small\rm 15}}
\put(525,200){\makebox(35,25){\small\rm 16}}
\thinlines
\multiput(0,25)(0,25){7}{\line(1,0){560}}
\thicklines
\multiput(0,0)(0,200){2}{\line(1,0){560}}
\multiput(0,0)(35,0){17}{\line(0,1){200}}
\put(0,175){\makebox(35,25){\tt 1}}
\put(0,150){\makebox(35,25){\tt 2}}
\put(0,125){\makebox(35,25){\tt 3}}
\put(0,100){\makebox(35,25){\tt 4}}
\put(0,75){\makebox(35,25){\tt 5}}
\put(0,50){\makebox(35,25){\tt 6}}
\put(0,25){\makebox(35,25){\tt 7}}
\put(0,0){\makebox(35,25){\tt 8}}
\put(35,175){\makebox(35,25){\tt 9}}
\put(35,150){\makebox(35,25){\tt 10}}
\put(35,125){\makebox(35,25){\tt 11}}
\put(35,100){\makebox(35,25){\tt 12}}
\put(35,75){\makebox(35,25){\tt 13}}
\put(35,50){\makebox(35,25){\tt 14}}
\put(35,25){\makebox(35,25){\tt 15}}
\put(35,0){\makebox(35,25){\tt 16}}
\put(70,175){\makebox(35,25){\tt 17}}
\put(70,150){\makebox(35,25){\tt 18}}
\put(70,125){\makebox(35,25){\tt 19}}
\put(70,100){\makebox(35,25){\tt 20}}
\put(70,75){\makebox(35,25){\tt 21}}
\put(70,50){\makebox(35,25){\tt 22}}
\put(70,25){\makebox(35,25){\tt 23}}
\put(70,0){\makebox(35,25){\tt 24}}
\put(105,175){\makebox(35,25){\tt 25}}
\put(105,150){\makebox(35,25){\tt 26}}
\put(105,125){\makebox(35,25){\tt 27}}
\put(105,100){\makebox(35,25){\tt 28}}
\put(105,75){\makebox(35,25){\tt 29}}
\put(105,50){\makebox(35,25){\tt 30}}
\put(105,25){\makebox(35,25){\tt 31}}
\put(105,0){\makebox(35,25){\tt 32}}
\put(140,175){\makebox(35,25){\tt 33}}
\put(140,150){\makebox(35,25){\tt 34}}
\put(140,125){\makebox(35,25){\tt 35}}
\put(140,100){\makebox(35,25){\tt 36}}
\put(140,75){\makebox(35,25){\tt 37}}
\put(140,50){\makebox(35,25){\tt 38}}
\put(140,25){\makebox(35,25){\tt 39}}
\put(140,0){\makebox(35,25){\tt 40}}
\put(175,175){\makebox(35,25){\tt 41}}
\put(175,150){\makebox(35,25){\tt 42}}
\put(175,125){\makebox(35,25){\tt 43}}
\put(175,100){\makebox(35,25){\tt 44}}
\put(175,75){\makebox(35,25){\tt 45}}
\put(175,50){\makebox(35,25){\tt 46}}
\put(175,25){\makebox(35,25){\tt 47}}
\put(175,0){\makebox(35,25){\tt 48}}
\put(210,175){\makebox(35,25){\tt 49}}
\put(210,150){\makebox(35,25){\tt 50}}
\put(210,125){\makebox(35,25){\tt 51}}
\put(210,100){\makebox(35,25){\tt 52}}
\put(210,75){\makebox(35,25){\tt 53}}
\put(210,50){\makebox(35,25){\tt 54}}
\put(210,25){\makebox(35,25){\tt 55}}
\put(210,0){\makebox(35,25){\tt 56}}
\put(245,175){\makebox(35,25){\tt 57}}
\put(245,150){\makebox(35,25){\tt 58}}
\put(245,125){\makebox(35,25){\tt 59}}
\put(245,100){\makebox(35,25){\tt 60}}
\put(245,75){\makebox(35,25){\tt 61}}
\put(245,50){\makebox(35,25){\tt 62}}
\put(245,25){\makebox(35,25){\tt 63}}
\put(245,0){\makebox(35,25){\tt 64}}
\put(280,175){\makebox(35,25){\tt 65}}
\put(280,150){\makebox(35,25){\tt 66}}
\put(280,125){\makebox(35,25){\tt 67}}
\put(280,100){\makebox(35,25){\tt 68}}
\put(280,75){\makebox(35,25){\tt 69}}
\put(280,50){\makebox(35,25){\tt 70}}
\put(280,25){\makebox(35,25){\tt 71}}
\put(280,0){\makebox(35,25){\tt 72}}
\put(315,175){\makebox(35,25){\tt 73}}
\put(315,150){\makebox(35,25){\tt 74}}
\put(315,125){\makebox(35,25){\tt 75}}
\put(315,100){\makebox(35,25){\tt 76}}
\put(315,75){\makebox(35,25){\tt 77}}
\put(315,50){\makebox(35,25){\tt 78}}
\put(315,25){\makebox(35,25){\tt 79}}
\put(315,0){\makebox(35,25){\tt 80}}
\put(350,175){\makebox(35,25){\tt 81}}
\put(350,150){\makebox(35,25){\tt 82}}
\put(350,125){\makebox(35,25){\tt 83}}
\put(350,100){\makebox(35,25){\tt 84}}
\put(350,75){\makebox(35,25){\tt 85}}
\put(350,50){\makebox(35,25){\tt 86}}
\put(350,25){\makebox(35,25){\tt 87}}
\put(350,0){\makebox(35,25){\tt 88}}
\put(385,175){\makebox(35,25){\tt 89}}
\put(385,150){\makebox(35,25){\tt 90}}
\put(385,125){\makebox(35,25){\tt 91}}
\put(385,100){\makebox(35,25){\tt 92}}
\put(385,75){\makebox(35,25){\tt 93}}
\put(385,50){\makebox(35,25){\tt 94}}
\put(385,25){\makebox(35,25){\tt 95}}
\put(385,0){\makebox(35,25){\tt 96}}
\put(420,175){\makebox(35,25){\tt 97}}
\put(420,150){\makebox(35,25){\tt 98}}
\put(420,125){\makebox(35,25){\tt 99}}
\put(420,100){\makebox(35,25){\tt 100}}
\end{picture}
\end{center}
Distributing the array {\tt BLOCK(6)} is not HPF-conforming because
\(6 \times 16 < 100\).

Distributing the array {\tt CYCLIC} (which means exactly
the same as {\tt CYCLIC(1)}):
                                                                        \CODE
!HPF$ DISTRIBUTE CENTURY(CYCLIC) ONTO SEDECIM
                                                                        \EDOC
results in this mapping of array elements onto abstract processors:
\begin{center}
\setlength{\unitlength}{0.01in}
\begin{picture}(560,200)(0,0)
\put(0,175){\makebox(35,25){\small\rm 1}}
\put(35,175){\makebox(35,25){\small\rm 2}}
\put(70,175){\makebox(35,25){\small\rm 3}}
\put(105,175){\makebox(35,25){\small\rm 4}}
\put(140,175){\makebox(35,25){\small\rm 5}}
\put(175,175){\makebox(35,25){\small\rm 6}}
\put(210,175){\makebox(35,25){\small\rm 7}}
\put(245,175){\makebox(35,25){\small\rm 8}}
\put(280,175){\makebox(35,25){\small\rm 9}}
\put(315,175){\makebox(35,25){\small\rm 10}}
\put(350,175){\makebox(35,25){\small\rm 11}}
\put(385,175){\makebox(35,25){\small\rm 12}}
\put(420,175){\makebox(35,25){\small\rm 13}}
\put(455,175){\makebox(35,25){\small\rm 14}}
\put(490,175){\makebox(35,25){\small\rm 15}}
\put(525,175){\makebox(35,25){\small\rm 16}}
\thinlines
\multiput(0,25)(0,25){6}{\line(1,0){560}}
\thicklines
\multiput(0,0)(0,175){2}{\line(1,0){560}}
\multiput(0,0)(35,0){17}{\line(0,1){175}}
\put(0,150){\makebox(35,25){\tt 1}}
\put(35,150){\makebox(35,25){\tt 2}}
\put(70,150){\makebox(35,25){\tt 3}}
\put(105,150){\makebox(35,25){\tt 4}}
\put(140,150){\makebox(35,25){\tt 5}}
\put(175,150){\makebox(35,25){\tt 6}}
\put(210,150){\makebox(35,25){\tt 7}}
\put(245,150){\makebox(35,25){\tt 8}}
\put(280,150){\makebox(35,25){\tt 9}}
\put(315,150){\makebox(35,25){\tt 10}}
\put(350,150){\makebox(35,25){\tt 11}}
\put(385,150){\makebox(35,25){\tt 12}}
\put(420,150){\makebox(35,25){\tt 13}}
\put(455,150){\makebox(35,25){\tt 14}}
\put(490,150){\makebox(35,25){\tt 15}}
\put(525,150){\makebox(35,25){\tt 16}}
\put(0,125){\makebox(35,25){\tt 17}}
\put(35,125){\makebox(35,25){\tt 18}}
\put(70,125){\makebox(35,25){\tt 19}}
\put(105,125){\makebox(35,25){\tt 20}}
\put(140,125){\makebox(35,25){\tt 21}}
\put(175,125){\makebox(35,25){\tt 22}}
\put(210,125){\makebox(35,25){\tt 23}}
\put(245,125){\makebox(35,25){\tt 24}}
\put(280,125){\makebox(35,25){\tt 25}}
\put(315,125){\makebox(35,25){\tt 26}}
\put(350,125){\makebox(35,25){\tt 27}}
\put(385,125){\makebox(35,25){\tt 28}}
\put(420,125){\makebox(35,25){\tt 29}}
\put(455,125){\makebox(35,25){\tt 30}}
\put(490,125){\makebox(35,25){\tt 31}}
\put(525,125){\makebox(35,25){\tt 32}}
\put(0,100){\makebox(35,25){\tt 33}}
\put(35,100){\makebox(35,25){\tt 34}}
\put(70,100){\makebox(35,25){\tt 35}}
\put(105,100){\makebox(35,25){\tt 36}}
\put(140,100){\makebox(35,25){\tt 37}}
\put(175,100){\makebox(35,25){\tt 38}}
\put(210,100){\makebox(35,25){\tt 39}}
\put(245,100){\makebox(35,25){\tt 40}}
\put(280,100){\makebox(35,25){\tt 41}}
\put(315,100){\makebox(35,25){\tt 42}}
\put(350,100){\makebox(35,25){\tt 43}}
\put(385,100){\makebox(35,25){\tt 44}}
\put(420,100){\makebox(35,25){\tt 45}}
\put(455,100){\makebox(35,25){\tt 46}}
\put(490,100){\makebox(35,25){\tt 47}}
\put(525,100){\makebox(35,25){\tt 48}}
\put(0,75){\makebox(35,25){\tt 49}}
\put(35,75){\makebox(35,25){\tt 50}}
\put(70,75){\makebox(35,25){\tt 51}}
\put(105,75){\makebox(35,25){\tt 52}}
\put(140,75){\makebox(35,25){\tt 53}}
\put(175,75){\makebox(35,25){\tt 54}}
\put(210,75){\makebox(35,25){\tt 55}}
\put(245,75){\makebox(35,25){\tt 56}}
\put(280,75){\makebox(35,25){\tt 57}}
\put(315,75){\makebox(35,25){\tt 58}}
\put(350,75){\makebox(35,25){\tt 59}}
\put(385,75){\makebox(35,25){\tt 60}}
\put(420,75){\makebox(35,25){\tt 61}}
\put(455,75){\makebox(35,25){\tt 62}}
\put(490,75){\makebox(35,25){\tt 63}}
\put(525,75){\makebox(35,25){\tt 64}}
\put(0,50){\makebox(35,25){\tt 65}}
\put(35,50){\makebox(35,25){\tt 66}}
\put(70,50){\makebox(35,25){\tt 67}}
\put(105,50){\makebox(35,25){\tt 68}}
\put(140,50){\makebox(35,25){\tt 69}}
\put(175,50){\makebox(35,25){\tt 70}}
\put(210,50){\makebox(35,25){\tt 71}}
\put(245,50){\makebox(35,25){\tt 72}}
\put(280,50){\makebox(35,25){\tt 73}}
\put(315,50){\makebox(35,25){\tt 74}}
\put(350,50){\makebox(35,25){\tt 75}}
\put(385,50){\makebox(35,25){\tt 76}}
\put(420,50){\makebox(35,25){\tt 77}}
\put(455,50){\makebox(35,25){\tt 78}}
\put(490,50){\makebox(35,25){\tt 79}}
\put(525,50){\makebox(35,25){\tt 80}}
\put(0,25){\makebox(35,25){\tt 81}}
\put(35,25){\makebox(35,25){\tt 82}}
\put(70,25){\makebox(35,25){\tt 83}}
\put(105,25){\makebox(35,25){\tt 84}}
\put(140,25){\makebox(35,25){\tt 85}}
\put(175,25){\makebox(35,25){\tt 86}}
\put(210,25){\makebox(35,25){\tt 87}}
\put(245,25){\makebox(35,25){\tt 88}}
\put(280,25){\makebox(35,25){\tt 89}}
\put(315,25){\makebox(35,25){\tt 90}}
\put(350,25){\makebox(35,25){\tt 91}}
\put(385,25){\makebox(35,25){\tt 92}}
\put(420,25){\makebox(35,25){\tt 93}}
\put(455,25){\makebox(35,25){\tt 94}}
\put(490,25){\makebox(35,25){\tt 95}}
\put(525,25){\makebox(35,25){\tt 96}}
\put(0,0){\makebox(35,25){\tt 97}}
\put(35,0){\makebox(35,25){\tt 98}}
\put(70,0){\makebox(35,25){\tt 99}}
\put(105,0){\makebox(35,25){\tt 100}}
\end{picture}
\end{center}
Distributing the array {\tt CYCLIC(3)}:
                                                                        \CODE
!HPF$ DISTRIBUTE CENTURY(CYCLIC(3)) ONTO SEDECIM
                                                                        \EDOC
results in this mapping of array elements onto abstract processors:
\begin{center}
\setlength{\unitlength}{0.01in}
\begin{picture}(560,250)(0,0)
\put(0,225){\makebox(35,25){\small\rm 1}}
\put(35,225){\makebox(35,25){\small\rm 2}}
\put(70,225){\makebox(35,25){\small\rm 3}}
\put(105,225){\makebox(35,25){\small\rm 4}}
\put(140,225){\makebox(35,25){\small\rm 5}}
\put(175,225){\makebox(35,25){\small\rm 6}}
\put(210,225){\makebox(35,25){\small\rm 7}}
\put(245,225){\makebox(35,25){\small\rm 8}}
\put(280,225){\makebox(35,25){\small\rm 9}}
\put(315,225){\makebox(35,25){\small\rm 10}}
\put(350,225){\makebox(35,25){\small\rm 11}}
\put(385,225){\makebox(35,25){\small\rm 12}}
\put(420,225){\makebox(35,25){\small\rm 13}}
\put(455,225){\makebox(35,25){\small\rm 14}}
\put(490,225){\makebox(35,25){\small\rm 15}}
\put(525,225){\makebox(35,25){\small\rm 16}}
\thinlines
\multiput(0,25)(0,25){8}{\line(1,0){560}}
\thicklines
\multiput(0,0)(0,225){2}{\line(1,0){560}}
\multiput(0,0)(35,0){17}{\line(0,1){225}}
\put(0,200){\makebox(35,25){\tt 1}}
\put(0,175){\makebox(35,25){\tt 2}}
\put(0,150){\makebox(35,25){\tt 3}}
\put(35,200){\makebox(35,25){\tt 4}}
\put(35,175){\makebox(35,25){\tt 5}}
\put(35,150){\makebox(35,25){\tt 6}}
\put(70,200){\makebox(35,25){\tt 7}}
\put(70,175){\makebox(35,25){\tt 8}}
\put(70,150){\makebox(35,25){\tt 9}}
\put(105,200){\makebox(35,25){\tt 10}}
\put(105,175){\makebox(35,25){\tt 11}}
\put(105,150){\makebox(35,25){\tt 12}}
\put(140,200){\makebox(35,25){\tt 13}}
\put(140,175){\makebox(35,25){\tt 14}}
\put(140,150){\makebox(35,25){\tt 15}}
\put(175,200){\makebox(35,25){\tt 16}}
\put(175,175){\makebox(35,25){\tt 17}}
\put(175,150){\makebox(35,25){\tt 18}}
\put(210,200){\makebox(35,25){\tt 19}}
\put(210,175){\makebox(35,25){\tt 20}}
\put(210,150){\makebox(35,25){\tt 21}}
\put(245,200){\makebox(35,25){\tt 22}}
\put(245,175){\makebox(35,25){\tt 23}}
\put(245,150){\makebox(35,25){\tt 24}}
\put(280,200){\makebox(35,25){\tt 25}}
\put(280,175){\makebox(35,25){\tt 26}}
\put(280,150){\makebox(35,25){\tt 27}}
\put(315,200){\makebox(35,25){\tt 28}}
\put(315,175){\makebox(35,25){\tt 29}}
\put(315,150){\makebox(35,25){\tt 30}}
\put(350,200){\makebox(35,25){\tt 31}}
\put(350,175){\makebox(35,25){\tt 32}}
\put(350,150){\makebox(35,25){\tt 33}}
\put(385,200){\makebox(35,25){\tt 34}}
\put(385,175){\makebox(35,25){\tt 35}}
\put(385,150){\makebox(35,25){\tt 36}}
\put(420,200){\makebox(35,25){\tt 37}}
\put(420,175){\makebox(35,25){\tt 38}}
\put(420,150){\makebox(35,25){\tt 39}}
\put(455,200){\makebox(35,25){\tt 40}}
\put(455,175){\makebox(35,25){\tt 41}}
\put(455,150){\makebox(35,25){\tt 42}}
\put(490,200){\makebox(35,25){\tt 43}}
\put(490,175){\makebox(35,25){\tt 44}}
\put(490,150){\makebox(35,25){\tt 45}}
\put(525,200){\makebox(35,25){\tt 46}}
\put(525,175){\makebox(35,25){\tt 47}}
\put(525,150){\makebox(35,25){\tt 48}}
\put(0,125){\makebox(35,25){\tt 49}}
\put(0,100){\makebox(35,25){\tt 50}}
\put(0,75){\makebox(35,25){\tt 51}}
\put(35,125){\makebox(35,25){\tt 52}}
\put(35,100){\makebox(35,25){\tt 53}}
\put(35,75){\makebox(35,25){\tt 54}}
\put(70,125){\makebox(35,25){\tt 55}}
\put(70,100){\makebox(35,25){\tt 56}}
\put(70,75){\makebox(35,25){\tt 57}}
\put(105,125){\makebox(35,25){\tt 58}}
\put(105,100){\makebox(35,25){\tt 59}}
\put(105,75){\makebox(35,25){\tt 60}}
\put(140,125){\makebox(35,25){\tt 61}}
\put(140,100){\makebox(35,25){\tt 62}}
\put(140,75){\makebox(35,25){\tt 63}}
\put(175,125){\makebox(35,25){\tt 64}}
\put(175,100){\makebox(35,25){\tt 65}}
\put(175,75){\makebox(35,25){\tt 66}}
\put(210,125){\makebox(35,25){\tt 67}}
\put(210,100){\makebox(35,25){\tt 68}}
\put(210,75){\makebox(35,25){\tt 69}}
\put(245,125){\makebox(35,25){\tt 70}}
\put(245,100){\makebox(35,25){\tt 71}}
\put(245,75){\makebox(35,25){\tt 72}}
\put(280,125){\makebox(35,25){\tt 73}}
\put(280,100){\makebox(35,25){\tt 74}}
\put(280,75){\makebox(35,25){\tt 75}}
\put(315,125){\makebox(35,25){\tt 76}}
\put(315,100){\makebox(35,25){\tt 77}}
\put(315,75){\makebox(35,25){\tt 78}}
\put(350,125){\makebox(35,25){\tt 79}}
\put(350,100){\makebox(35,25){\tt 80}}
\put(350,75){\makebox(35,25){\tt 81}}
\put(385,125){\makebox(35,25){\tt 82}}
\put(385,100){\makebox(35,25){\tt 83}}
\put(385,75){\makebox(35,25){\tt 84}}
\put(420,125){\makebox(35,25){\tt 85}}
\put(420,100){\makebox(35,25){\tt 86}}
\put(420,75){\makebox(35,25){\tt 87}}
\put(455,125){\makebox(35,25){\tt 88}}
\put(455,100){\makebox(35,25){\tt 89}}
\put(455,75){\makebox(35,25){\tt 90}}
\put(490,125){\makebox(35,25){\tt 91}}
\put(490,100){\makebox(35,25){\tt 92}}
\put(490,75){\makebox(35,25){\tt 93}}
\put(525,125){\makebox(35,25){\tt 94}}
\put(525,100){\makebox(35,25){\tt 95}}
\put(525,75){\makebox(35,25){\tt 96}}
\put(0,50){\makebox(35,25){\tt 97}}
\put(0,25){\makebox(35,25){\tt 98}}
\put(0,0){\makebox(35,25){\tt 99}}
\put(35,50){\makebox(35,25){\tt 100}}
\end{picture}
\end{center}

Note that it is perfectly permissible for an array to be distributed so
that some processors have no elements.  Indeed, an array may be ``distributed''
so that all elements reside on one processor.  For example,
                                                                        \CODE
!HPF$ DISTRIBUTE CENTURY(BLOCK(256)) ONTO SEDECIM
                                                                        \EDOC
results in having only one non-empty block---a partially-filled one at that,
having only 100 elements---on processor 1, with processors 2 through 16
having no elements of the array.

A {\tt DISTRIBUTE} directive must not cause
any data object associated with the {\it distributee} via storage association
({\tt COMMON} or {\tt EQUIVALENCE}) to be mapped such that storage
units of a scalar data object are split across more than one abstract processor.
See Section \ref{sequence} for further discussion of storage association.

The statement form of a {\tt DISTRIBUTE} 
directive
may be considered an abbreviation for an attributed form that
happens to mention only one {\it distributee}; for example,
                                                                        \ICODE
!HPF$ DISTRIBUTE distributee ( dist-format-list ) ONTO dist-target
                                                                        \EDOC
is equivalent to
                                                                        \ICODE
!HPF$ DISTRIBUTE ( dist-format-list ) ONTO dist-target :: distributee
                                                                        \EDOC
Note that, to prevent syntactic ambiguity,
the {\it dist-format-clause} must be present in the statement
form, so in general the statement form of the directive may not be
used to specify the mapping of scalars.

If the {\it dist-format-clause} is omitted from the attributed form,
then the language processor may make an arbitrary choice of distribution
formats for each template or array.  So the directive
                                                                        \CODE
!HPF$ DISTRIBUTE ONTO P :: D1,D2,D3
                                                                        \EDOC
means the same as
                                                                        \CODE
!HPF$ DISTRIBUTE ONTO P :: D1
!HPF$ DISTRIBUTE ONTO P :: D2
!HPF$ DISTRIBUTE ONTO P :: D3
                                                                        \EDOC
to which a compiler, perhaps taking into account patterns of use of
{\tt D1}, {\tt D2}, and {\tt D3} within the code, might choose
to supply three distinct distributions such as, for example,
                                                                        \CODE
!HPF$ DISTRIBUTE D1(BLOCK, BLOCK) ONTO P
!HPF$ DISTRIBUTE D2(CYCLIC, BLOCK) ONTO P
!HPF$ DISTRIBUTE D3(BLOCK(43),CYCLIC) ONTO P
                                                                        \EDOC
Then again, the compiler might happen to choose the same
distribution for all three arrays.

In either the statement form or the attributed form,
if the {\tt ONTO} clause is present, it specifies the processor arrangement
that is the target of the distribution.
If the {\tt ONTO}  clause is omitted, then a implementation-dependent
processor arrangement is chosen arbitrarily for each {\it distributee}.
So, for example,
                                                                        \CODE
      REAL, DIMENSION(1000) :: ARTHUR, ARNOLD, LINUS, LUCY
!HPF$ PROCESSORS EXCALIBUR(32)
!HPF$ DISTRIBUTE (BLOCK) ONTO EXCALIBUR :: ARTHUR, ARNOLD
!HPF$ DISTRIBUTE (BLOCK) :: LINUS, LUCY
                                                                        \EDOC
causes the arrays {\tt ARTHUR} and {\tt ARNOLD} to have the same mapping,
so that corresponding elements reside in the same abstract processor,
because they are the same size and distributed in the same way ({\tt BLOCK})
onto the same processor arrangement ({\tt EXCALIBUR}).
However, {\tt LUCY} and {\tt LINUS} do not necessarily have the same
mapping because they might, depending on the implementation,
be distributed onto differently chosen processor arrangements;
so corresponding elements of {\tt LUCY} and {\tt LINUS} might not
reside on the same abstract processor.  (The {\tt ALIGN} directive provides
a way to ensure that two arrays have the same mapping without having
to specify an explicit processor arrangement.)

In a given environment, for some distributions, there may be no 
appropriate processor arrangement.

\section{ALIGN Directive}
\label{ALIGN-SECTION}

The {\tt ALIGN} directive is used to specify that certain data objects
are to be mapped in the same way as certain other data objects.
Operations between aligned data objects are likely to be more efficient
than operations between data objects that are not known to be aligned
(because two objects that are aligned are intended to be mapped to the
same abstract processor).  The {\tt ALIGN} directive is designed to
make it particularly easy to specify explicit mappings for all the
elements of an array at once.  While objects can be aligned in some
cases through careful use of matching {\tt DISTRIBUTE} directives, {\tt
ALIGN} is more general and frequently more convenient.

The {\tt ALIGN} directive may appear only in the {\it
specification-part} of a scoping unit
and can contain only a {\it specification-expr} as a
{\it subscript} or in a {\it subscript-triplet}.

Formally, the syntax of {\tt ALIGN} 
is as follows:

                                                                        \BNF
align-directive            \IS  ALIGN alignee align-directive-stuff

align-directive-stuff      \IS  ( align-source-list ) align-with-clause

align-attribute-stuff      \IS  [ ( align-source-list ) ] align-with-clause

alignee                    \IS  object-name

align-source               \IS  :
                           \OR  *
                           \OR  align-dummy

align-dummy                \IS  scalar-int-variable
                                                                        \FNB
\begin{constraints}
\item An {\it object-name} mentioned as an {\it alignee}
must be a simple name and not a subobject designator.

\item An {\it object-name} mentioned as an {\it alignee} may not
appear as a {\it distributee}.

\item An {\it object-name} mentioned as an {\it alignee} may not
have the {\tt POINTER} attribute.

\item  If the {\it alignee} is scalar,
the {\it align-source-list} (and its surrounding parentheses)
must not appear.  In this case
the statement form of the directive is not allowed.

\item If the {\it align-source-list} is present, its length must equal the
rank of the alignee.

\item An {\it align-dummy} must be a named variable.

\item An object may not have both the {\tt INHERIT} attribute and
the {\tt ALIGN} attribute.  
\end{constraints}

Note that the possibility of an {\tt ALIGN} directive of the form
                                                                        \ICODE
!HPF$ ALIGN align-attribute-stuff :: alignee-list
                                                                        \EDOC
is covered by syntax rule \ref{combined-directive-rule} for a
{\it combined-directive}.

The statement form of an {\tt ALIGN} 
directive
may be considered an abbreviation of an attributed form that
happens to mention only one {\it alignee}:
                                                                        \ICODE
!HPF$ ALIGN alignee ( align-source-list ) WITH align-spec
                                                                        \EDOC
is equivalent to
                                                                        \ICODE
!HPF$ ALIGN ( align-source-list ) WITH align-spec :: alignee
                                                                        \EDOC

If the {\it align-source-list} is omitted from the attributed form and
the {\it  alignee}s are not scalar, the {\it align-source-list} is
assumed to consist of a parenthesized list of ``{\tt :}'' entries,
equal in number to the rank of the {\it alignees}.  Similarly, if the
{\it align-subscript-list} is omitted from the {\it align-spec} in
either form, it is assumed to consist of a parenthesized list of ``{\tt
:}'' entries, equal in number to the rank of the {\it align-target}.
So the directive

                                                                        \CODE
!HPF$ ALIGN WITH B :: A1, A2, A3
                                                                        \EDOC
means
                                                                        \CODE
!HPF$ ALIGN (:,:) WITH B(:,:) :: A1, A2, A3
                                                                        \EDOC
which in turn means the same as
                                                                        \CODE
!HPF$ ALIGN A1(:,:) WITH B(:,:)
!HPF$ ALIGN A2(:,:) WITH B(:,:)
!HPF$ ALIGN A3(:,:) WITH B(:,:)
                                                                        \EDOC

\noindent
because an attributed-form directive that mentions more than one {\it alignee}
is equivalent to a series of identical directives, one for each {\it alignee};
all {\it  alignee}s must have the
same rank.  With this understanding, we will assume below, for the
sake of simplifying the description, that an {\tt ALIGN}
directive has a single {\it alignee}.

Each {\it align-source} corresponds to one axis of the {\it alignee}, and is
specified as either ``{\tt :}'' or ``{\tt *}'' or a dummy variable:

\begin{itemize}

\item
If it is ``{\tt :}'', then positions along that axis will be spread out
across the matching axis of the {\it align-spec} (see below).

\item
If it is ``{\tt *}'', then that axis is {\it collapsed}: positions along
that axis make no difference in determining the corresponding
position within the {\it align-target}.  (Replacing the ``{\tt *}'' with
a dummy variable name not used anywhere else in the directive would
have the same effect; ``{\tt *}'' is merely a convenience that saves the
trouble of inventing a variable name and makes it clear that no
dependence on that dimension is intended.)

\item
A dummy variable is considered to range over all valid
index values for that dimension of the {\it alignee}.

\end{itemize}

The {\tt WITH} clause of an {\tt ALIGN} has the following syntax:
                                                                        \BNF
align-with-clause          \IS  WITH align-spec

align-spec                 \IS  align-target [ ( align-subscript-list ) ]
                           \OR  * align-target [ ( align-subscript-list ) ]

align-target               \IS  object-name
                           \OR  template-name

align-subscript            \IS  int-expr
                           \OR  align-subscript-use
                           \OR  subscript-triplet
                           \OR  *

align-subscript-use    \IS  [ [ int-level-two-expr ] add-op ] align-add-operand
                           \OR  align-subscript-use add-op int-add-operand

align-add-operand          \IS  [ int-add-operand * ] align-primary
                           \OR  align-add-operand * int-mult-operand

align-primary              \IS  align-dummy
                           \OR  ( align-subscript-use )

int-add-operand            \IS  add-operand

int-mult-operand           \IS  mult-operand 

int-level-two-expr           \IS  level-2-expr
                                                                        \FNB

The full syntax is given here for completeness, however some of the
forms will only be discussed in Chapter~\ref{ch-mapping-subr}.  These
``interprocedural'' forms are:
\begin{itemize}
\item The second option of  rule~\ref{align-spec-rule} (containing
the {\tt *} form)
\end{itemize}

\begin{constraints}

\item An {\it object-name} mentioned as an {\it align-target}
must be a simple name and not a subobject designator.

\item An {\it align-target} may not have the {\tt OPTIONAL} attribute.

\item If the {\it align-spec} in an {\tt ALIGN} directive begins with
``{\tt *}'' then every {\it alignee} must be a dummy argument.

\item  Each {\it align-dummy} may appear at most once in an
{\it align-subscript-list}.

\item  An {\it align-subscript-use} expression may contain at most one
occurrence of an {\it align-dummy}.

\item  An {\it align-dummy} may not appear anywhere in the {\it
align-spec} except where explicitly permitted to appear by virtue of
the grammar shown above.  Paraphrased, one may construct an {\it
align-subscript-use} by starting with an {\it align-dummy} and then
doing additive and multiplicative things to it with any integer
expressions that contain no {\it align-dummy}.

\item A {\it subscript} in an {\it align-subscript} may not contain
occurrences of any {\it align-dummy}.

\item An {\it int-add-operand}, {\it int-mult-operand}, or {\it
int-level-two-expr} must be of type integer.

\end{constraints}

The syntax rules for an {\it align-subscript-use} take account of
operator precedence issues, but the basic idea is simple: an {\it
align-subscript-use} is intended to be a linear function of a single
occurrence of an {\it align-dummy}.

For example, the following {\it align-subscript-use} expressions
are valid, assuming that {\tt J}, {\tt K}, and {\tt M}
are {\it align-dummy}s and {\tt N} is not an {\it align-dummy}:

\begin{flushleft}\tt
\begin{tabular}{l@{\quad}l@{\quad}l@{\quad}l@{\quad}l@{\quad}l}
J   &  J+1      &  3-K    &  2*M    &  N*M        &  100-3*M    \\
-J  &  +J       &  -K+3   &  M+2**3 &  M+N    &  -(4*7+IOR(6,9))*K-(13-5/3) \\
M*2 &  N*(M-N)  & 2*(J+1) &  5-K+3  &  10000-M*3  &  2*(3*(K-1)+13)-100
\end{tabular}
\end{flushleft}

The following expressions are not valid {\it align-subscript-use} expressions:
\begin{flushleft}\tt
\begin{tabular}{l@{\quad}l@{\quad}l@{\quad}l@{\quad}l@{\quad}l}
J+J  &  J-J      &  3*K-2*K   &  M*(N-M)  &  2*J-3*J+J & 2*(3*(K-1)+13)-K \\
J*J  &  J+K      &  3/K       &  2**M     &  M*K       &  K-3*M    \\
K-J  &  IOR(J,1) &  -K/3      &  M*(2+M)  &  M*(M-N)   &  2**(2*J-3*J+J)
\end{tabular}
\end{flushleft}

The {\it align-spec} must contain exactly as many {\it subscript-triplets}
as the number of colons (``{\tt :}'') appearing in the {\it align-source-list}.
These are matched up in corresponding left-to-right order, ignoring,
for this purpose, any {\it align-source} that is not a colon and
any {\it align-subscript} that is not a {\it subscript-triplet}.
Consider a dimension of the {\it alignee} for which a colon appears as
an {\it align-source} and
let the lower and upper bounds of that array be {\it LA} and {\it UA}.
Let the corresponding subscript triplet be
{\it LT\/}:{\it UT\/}:{\it ST} or its equivalent.
Then the colon could be replaced by a new, as-yet-unused
dummy variable, say {\tt J}, and the subscript triplet by the expression
{\tt (J-{\it LA})*{\it ST}+{\it LT}}
without affecting the meaning of the directive.  Moreover, the axes
must conform, which means that
\[ \max(0,UA-LA+1) \ = \  \max(0,\lceil (UT-LT+1) / ST \rceil) \]
must be true. (This is entirely analogous to the treatment of array
assignment.)

To simplify the remainder of the discussion,
we assume that every colon in the {\it align-source-list}
has been replaced by new dummy variables
in exactly the fashion just described,
and that every ``{\tt *}'' in the {\it align-source-list}
has likewise been replaced by an otherwise unused dummy variable.
For example,
                                                                        \CODE
!HPF$ ALIGN A(:,*,K,:,:,*) WITH B(31:,:,K+3,20:100:3)
                                                                        \EDOC
may be transformed into its equivalent
                                                                        \CODE
!HPF$ ALIGN A(I,J,K,L,M,N) WITH B(I-LBOUND(A,1)+31,       &
!HPF$            L-LBOUND(A,4)+LBOUND(B,2),K+3,(M-LBOUND(A,5))*3+20)
                                                                        \EDOC
with the attached requirements
\begin{center}
{\tt SIZE(A,1)~.EQ.~UBOUND(B,1)-30}     \\
{\tt SIZE(A,4)~.EQ.~SIZE(B,2)}          \\
{\tt SIZE(A,5)~.EQ.~(100-20+3)/3}
\end{center}
Thus we need consider further only the case where every {\it align-source}
is a dummy variable and no {\it align-subscript} is a {\it subscript-triplet}.

Each dummy variable is considered to range over all valid
index values for the corresponding dimension of the {\it alignee}.
Every combination of possible values for the index variables selects
an element of the {\it alignee}.
The {\it align-spec} indicates a corresponding element (or section) of
the {\it align-target} with which that element of the {\it alignee} should be
aligned; this indication may be a function of the index values, but
the nature of this function is syntactically restricted (as discussed above)
to linear functions
in order to limit the complexity of the implementation.
Each {\it align-dummy} variable may appear at
most once in the {\it align-spec} and only in certain rigidly prescribed
contexts.  The result is that each
{\it align-subscript} expression may contain at most one {\it align-dummy}
variable and the expression is constrained to be a linear function of that
variable.  (Therefore skew alignments are not possible.)

An asterisk ``{\tt *}'' as an {\it align-subscript}
indicates a replicated representation.  Each element of the {\it alignee}
is aligned with every position along that axis of the {\it align-target}.

\begin{rationale}
It may seem strange to use ``{\tt *}'' to mean both collapsing and
replication; the rationale is that ``{\tt *}'' always stands conceptually
for a dummy variable that appears
nowhere else in the statement and ranges over the set of indices for
the indicated dimension. Thus, for example,
                                                                        \CODE
!HPF$ ALIGN A(:) WITH D(:,*)
                                                                        \EDOC
means that a copy of {\tt A} is aligned with every column of {\tt D}, because
it is conceptually equivalent to
                                                                        \ICODE
      for every legitimate index j, align A(:) with D(:,j)
                                                                        \EDOC
just as
                                                                        \CODE
!HPF$ ALIGN A(:,*) WITH D(:)
                                                                        \EDOC
is conceptually equivalent to
                                                                        \ICODE
      for every legitimate index j, align A(:,j) with D(:)
                                                                        \EDOC
Note, however, that while HPF syntax allows
                                                                        \CODE
!HPF$ ALIGN A(:,*) WITH D(:)
                                                                        \EDOC
to be written in the alternate form
                                                                        \CODE
!HPF$ ALIGN A(:,J) WITH D(:)
                                                                        \EDOC
it does {\it not} allow
                                                                        \CODE
!HPF$ ALIGN A(:) WITH D(:,*)
                                                                        \EDOC
to be written in the alternate form
                                                                        \CODE
!HPF$ ALIGN A(:) WITH D(:,J)
                                                                        \EDOC
because that has another meaning (only a variable appearing
in the {\it align-source-list}
following the {\it alignee} is understood to be an {\it align-dummy},
so the current value of the variable {\tt J} is used, thus aligning
{\tt A} with a single column of {\tt D}).

Replication allows an optimizing compiler to arrange to read
whichever copy is closest.  (Of course, when a replicated data object
is written, all copies must be updated, not just one copy.  Replicated
representations are very useful for use as small lookup
tables, where it is much faster to have a copy in each physical
processor but without giving it an extra
dimension that is logically unnecessary to the algorithm.)
\end{rationale}

By applying the transformations given above, all cases of an {\it
align-subscript} may be conceptually reduced to either an {\it
int-expr} (not involving an {\it align-dummy}) or an {\it
align-subscript-use} and the {\it align-source-list} may be reduced to
a list of index variables with no ``{\tt *}'' or ``{\tt:}''.  An {\it
align-subscript-list} may then be evaluated for any specific
combination of values for the {\it align-dummy} variables simply by
evaluating each {\it align-subscript} as an expression.  The resulting
subscript values must be legitimate subscripts for the {\it
align-target}.  (This implies that the {\it alignee} is not allowed to
``wrap around'' or ``extend past the edges'' of an {\it align-target}.)
The selected element of the {\it alignee} is then considered to be
aligned with the indicated element of the {\it align-target};  more
precisely, the selected element of the {\it alignee} is considered to
be ultimately aligned with the same object with which the indicated
element of the {\it align-target} is currently ultimately aligned
(possibly itself).

More examples of {\tt ALIGN} directives:
                                                                        \CODE
      INTEGER D1(N)
      LOGICAL D2(N,N)
      REAL, DIMENSION(N,N):: X,A,B,C,AR1,AR2A,P,Q,R,S
!HPF$ ALIGN X(:,*) WITH D1(:)
!HPF$ ALIGN (:,*) WITH D1:: A,B,C,AR1,AR2A
!HPF$ ALIGN WITH D2, DYNAMIC:: P,Q,R,S
                                                                        \EDOC
Note that, in a {\it alignee-list}, the alignees must all have the same
rank but need not all have the same shape; the extents need match only
for dimensions that correspond to colons in the {\it align-source-list}.
This turns out to be an extremely important convenience;
one of the most common cases in current practice is aligning arrays that
match in distributed (``parallel'') dimensions but may differ in
collapsed (``on-processor'') dimensions:
                                                                        \CODE

      REAL A(3,N), B(4,N), C(43,N), Q(N)
!HPF$ DISTRIBUTE Q(BLOCK)
!HPF$ ALIGN (*,:) WITH Q:: A,B,C
                                                                        \EDOC
Here there are processors (perhaps {\tt N} of
them) and arrays of different sizes (3, 4, 43) within each
processor are required.  As far as HPF is concerned,
 the numbers 3, 4, and 43 may be different,
because those axes will be collapsed.  Thus array elements with
indices differing only along that axis will all be aligned with the
same element of {\tt Q} (and thus be specified as residing in the same
processor).

In the following examples, each directive in the group means
the same thing, assuming that corresponding axis upper and lower bounds match:
                                                                        \CODE
!Second axis of X is collapsed
!HPF$ ALIGN X(:,*) WITH D1(:)
!HPF$ ALIGN X(J,*) WITH D1(J)
!HPF$ ALIGN X(J,K) WITH D1(J)

!Replicated representation along second axis of D3
!HPF$ ALIGN X(:,:) WITH D3(:,*,:)
!HPF$ ALIGN X(J,K) WITH D3(J,*,K)

!Transposing two axes
!HPF$ ALIGN X(J,K) WITH D2(K,J)
!HPF$ ALIGN X(J,:) WITH D2(:,J)
!HPF$ ALIGN X(:,K) WITH D2(K,:)
!But there isn't any way to get rid of *both* index variables;
! the subscript-triplet syntax alone cannot express transposition.

!Reversing both axes
!HPF$ ALIGN X(J,K) WITH D2(M-J+1,N-K+1)
!HPF$ ALIGN X(:,:) WITH D2(M:1:-1,N:1:-1)

!Simple case
!HPF$ ALIGN X(J,K) WITH D2(J,K)
!HPF$ ALIGN X(:,:) WITH D2(:,:)
!HPF$ ALIGN (J,K) WITH D2(J,K):: X
!HPF$ ALIGN (:,:) WITH D2(:,:):: X
!HPF$ ALIGN WITH D2:: X
                                                                        \EDOC

\section{Allocatable Arrays and Pointers}
\label{ALLOCATABLE-SECTION}

A variable with the {\tt ALLOCATABLE} attribute may appear
as an {\it alignee}
in an {\tt ALIGN} directive or as a {\it distributee} in a {\tt DISTRIBUTE}
directive.  Such directives do not take effect immediately, however; they
take effect each time the array is allocated by an {\tt ALLOCATE} statement,
rather than on entry to the scoping unit.
The values of all specification expressions in such a directive
are determined once on entry to the scoping unit
and may be used multiple times (or not at all).
For example:
                                                                        \CODE
      SUBROUTINE MILLARD_FILLMORE(N,M)
      REAL, ALLOCATABLE, DIMENSION(:) :: A, B
!HPF$ ALIGN B(I) WITH A(I+N)
!HPF$ DISTRIBUTE A(BLOCK(M*2))
      N = 43
      M = 91
      ALLOCATE(A(27))
      ALLOCATE(B(13))
      ...
                                                                        \EDOC
The values of the expressions {\tt N} and {\tt M*2}
on entry to the subprogram are conceptually retained by the
{\tt ALIGN} and {\tt DISTRIBUTE} directives for later use at allocation time.
When the array {\tt A} is allocated, it is distributed with a block size
equal to the retained value of {\tt M*2}, not the value 182.
When the array {\tt B} is allocated, it is aligned relative to {\tt A}
according to the retained value of {\tt N}, not its new value 43.

Note that it would have been incorrect in the {\tt MILLARD_FILLMORE} example
to perform the two {\tt ALLOCATE} statements in the opposite order.
In general, when an object {\tt X} is created it may be aligned to another
object {\tt Y} only if {\tt Y} has already been created or allocated.
The following example illustrates several related cases.
                                                                        \CODE
      SUBROUTINE WARREN_HARDING(P,Q)
      REAL P(:)
      REAL Q(:)
      REAL R(SIZE(Q))
      REAL, ALLOCATABLE :: S(:),T(:)
!HPF$ ALIGN P(I) WITH T(I)                        !Nonconforming
!HPF$ ALIGN Q(I) WITH *T(I)                       !Nonconforming
!HPF$ ALIGN R(I) WITH T(I)                        !Nonconforming
!HPF$ ALIGN S(I) WITH T(I)
      ALLOCATE(S(SIZE(Q)))                        !Nonconforming
      ALLOCATE(T(SIZE(Q)))
                                                                        \EDOC
The {\tt ALIGN} directives are not HPF-conforming because the array {\tt T}
has not yet been allocated at the time that the various alignments
must take place.  The four cases differ slightly in their details.
The arrays {\tt P} and {\tt Q} already exist on entry to the
subroutine, but because {\tt T} is not yet allocated, one cannot
correctly prescribe the alignment of {\tt P} or describe the
alignment of {\tt Q} relative to {\tt T}.  (See Chapter~\ref{ch-mapping-subr}
for a discussion of prescriptive and descriptive directives.)
The array {\tt R} is created on subroutine entry and its size
can correctly depend on the {\tt SIZE} of {\tt Q}, but the alignment
of {\tt R} cannot be specified in terms of the alignment of {\tt T}
any more than its size can be specified in terms of the size of {\tt T}.
It {\it is} permitted to have an alignment directive for {\tt S}
in terms of {\tt T}, because the alignment action does not take place
until {\tt S} is allocated; however, the first {\tt ALLOCATE}
statement is nonconforming because {\tt S} needs to be aligned
but at that point in time {\tt T} is still unallocated.

When an array is allocated, it will be aligned to an existing template
if there is an explicit {\tt ALIGN} directive for the allocatable
variable.  If there is no explicit {\tt ALIGN} directive, then the array
will be ultimately aligned with itself.  It is forbidden for any
other object to be ultimately aligned to an array at the time the
array becomes undefined by reason of deallocation.  All this applies
regardless of whether the name originally used in the {\tt ALLOCATE}
statement when the array was created had the {\tt ALLOCATABLE} attribute or
the {\tt POINTER} attribute.

Pointers cannot be explicitly mapped in HPF and thus
can be associated with objects which are not explicilty mapped.
When used for allocation, the compiler may
choose any arbitrary mapping for data allocated through the pointer.
Explicit mapping of pointers is allowed under the approved extensions - see
Section~\ref{POINTERS-SECTION} for details.
Also, the the relationship of pointers and sequence attributes is
described in Section~\ref{sequence}. 

\section{PROCESSORS Directive}
\label{PROCESSORS-SECTION}

The {\tt PROCESSORS} directive declares one or more rectilinear
processor arrangements, specifying for each one its name, its rank
(number of dimensions), and the extent in each dimension.  It may
appear only in the {\it specification-part} of a scoping unit.  Every
dimension of a processor arrangement must have nonzero extent;
therefore a processor arrangement cannot be empty.

In the language of section 14.1.2 of the Fortran standard, processor
arrangements are local entities of class (1); therefore a processor
arrangement may not have the same name as a variable, named constant,
internal procedure, etc., in the same scoping unit.  Names of processor
arrangements obey the same rules for host and use association as other
names in the long list in section 12.1.2.2.1 of the Fortran
standard.

A processor arrangement declared in a module has the default accessibility
of the module.

\begin{rationale}
Because the name of a processor arrangement is not a first-class entity
in HPF, but must appear only in directives, it cannot appear in an
{\it access-stmt} ({\tt PRIVATE} or {\tt PUBLIC}).
If directives ever become full-fledged Fortran statements rather
than structured comments, then it would be appropriate to allow
the accessibility of a processor arrangement to be controlled
by listing its name in an {\it access-stmt}.
\end{rationale}

If two processor arrangements have the same shape, then corresponding
elements of the two arrangements are understood to refer to the same
abstract processor.  (It is anticipated that
implementation-dependent directives provided by some HPF
implementations could overrule the default correspondence of processor
arrangements that have the same shape.)

If directives collectively specify that two objects be mapped to the
same abstract processor at a given instant during the program
execution, the intent is that the two objects be mapped to the same
physical processor at that instant.

The intrinsic functions {\tt NUMBER_OF_PROCESSORS} and {\tt
PROCESSORS_SHAPE} may be used to inquire about the total number of
actual physical processors used to execute the program.  This
information may then be used to calculate appropriate sizes for the
declared abstract processor arrangements.

                                                                        \BNF
processors-directive       \IS  PROCESSORS processors-decl-list

processors-decl            \IS  processors-name [ ( explicit-shape-spec-list ) ]
                                                                        \FNB

Examples:

                                                                        \CODE
!HPF$ PROCESSORS P(N)
!HPF$ PROCESSORS Q(NUMBER_OF_PROCESSORS()),       &
!HPF$            R(8,NUMBER_OF_PROCESSORS()/8)
!HPF$ PROCESSORS BIZARRO(1972:1997,-20:17)
!HPF$ PROCESSORS SCALARPROC
                                                                        \EDOC

\noindent
If no shape is specified, then the declared processor arrangement is
conceptually scalar.

\begin{rationale}
A scalar processor arrangement may be useful as a way of
indicating that certain scalar data should be kept together but need
not interact strongly with distributed data.  Depending on the
implementation architecture, data distributed onto such a processor
arrangement may reside in a single ``control'' or ``host'' processor
(if the machine has one), or may reside in an arbitrarily chosen
processor, or may be replicated over all processors.  For target
architectures that have a set of computational processors and a
separate scalar host computer, a natural implementation is to map
every scalar processor arrangement onto the host processor.  For
target architectures that have a set of computational processors but
no separate scalar ``host'' computer, data mapped to a scalar
processor arrangement might be mapped to some arbitrarily chosen
computational processor or replicated onto all computational
processors.
\end{rationale}

An HPF compiler is required to accept any
{\tt PROCESSORS} declaration in which the product of the extents of each
declared processor arrangement is equal to the number of physical
processors that would be returned by the call {\tt NUMBER_OF_PROCESSORS()}.
It must also accept all declarations of scalar {\tt PROCESSOR}
arrangements.  Other cases may be handled as well, depending on the
implementation.

For compatibility with the Fortran attribute syntax, an optional
``{\tt ::}'' may be inserted.  The shape may also be specified with the
{\tt DIMENSION} attribute:
                                                                        \CODE
!HPF$ PROCESSORS :: RUBIK(3,3,3)
!HPF$ PROCESSORS, DIMENSION(3,3,3) :: RUBIK
                                                                        \EDOC
As in Fortran, an {\it explicit-shape-spec-list} in a {\it processors-decl}
will override an explicit {\tt DIMENSION} attribute:
                                                                        \CODE
!HPF$ PROCESSORS, DIMENSION(3,3,3) ::      &
!HPF$            RUBIK, RUBIKS_REVENGE(4,4,4), SOMA
                                                                        \EDOC
Here {\tt RUBIKS_REVENGE} is \( 4 \times 4 \times 4 \) while
{\tt RUBIK} and {\tt SOMA} are each \( 3 \times 3 \times 3 \).
(By the rules enunciated above, however, such a statement
may not be completely portable because no HPF language processor is
required to handle shapes of total sizes 27 and 64 simultaneously.)

Returning from a subprogram causes all processor arrangements
declared local to that subprogram to become undefined.  It is
not HPF-conforming for any array or template to be distributed onto a processor
arrangement at the time the processor arrangement becomes undefined
unless at least one of two conditions holds:

\begin{itemize}

\item The array or template itself becomes undefined at the same time
by virtue of returning from the subprogram.

\item Whenever the subprogram is called, the processor arrangement
is always locally defined in the same way, with identical lower bounds,
and identical upper bounds.

\begin{rationale}
Note that the second condition is slightly less stringent than requiring
all expressions to be constant.  This allows calls to
{\tt NUMBER_OF_PROCESSORS} or {\tt PROCESSORS_SHAPE} to appear
without violating the condition.
\end{rationale}

\end{itemize}

Variables in {\tt COMMON} or having the {\tt SAVE} attribute may be
mapped to a locally declared processor arrangement, but because the
first condition cannot hold for such variables (they don't become
undefined), the second condition must be observed.
This allows {\tt COMMON} variables to work properly through the customary
strategy of putting identical declarations in each scoping unit that
needs to use them, while allowing the processor arrangements to which
they may be mapped to depend on the value returned
by {\tt NUMBER_OF_PROCESSORS}. (See Section~\ref{sequence} for
further information on mapping common variables.)

\begin{implementors}
It may be desirable to have a way for the user to specify at compile
time the number of physical processors on which the program is to be
executed.  This might be specified either by a implementation-dependent
directive, for example, or through the programming environment (for
example, as a UNIX command-line argument).  Such facilities are
beyond the scope of the HPF specification, but as food for thought we
offer the following illustrative hypothetical examples:
                                                                        \CODE
!Declaration for multiprocessor by ABC Corporation
!ABC$ PHYSICAL PROCESSORS(8)
!Declaration for mpp by XYZ Incorporated
!XYZ$ PHYSICAL PROCESSORS(65536)
!Declaration for hypercube machine by PDQ Limited
!PDQ$ PHYSICAL PROCESSORS(2,2,2,2,2,2,2,2,2,2)
!Declaration for two-dimensional grid machine by TLA GmbH
!TLA$ PHYSICAL PROCESSORS(128,64)
!One of the preceding might affect the following
!HPF$ PROCESSORS P(NUMBER_OF_PROCESSORS())
                                                                        \EDOC

It may furthermore be desirable to have a way for the user to specify
the precise mapping of the processor arrangement declared in a
{\tt PROCESSORS} statement to the physical processors of the executing
hardware.  Again, this might be specified either by a
implementation-dependent directive or through the programming
environment (for example, as a UNIX command-line argument); 
such facilities are beyond the scope of the HPF specification, but as
food for thought we offer the following illustrative hypothetical
example:
                                                                        \CODE
!PDQ$ PHYSICAL PROCESSORS(2,2,2,2,2,2,2,2,2,2,2,2,2)
!HPF$ PROCESSORS G(8,64,16)
!PDQ$ MACHINE LAYOUT G(:GRAY(0:2),:GRAY(6:11),:BINARY(3:5,12))
                                                                        \EDOC
This might specify that the first dimension of {\tt G} should use hypercube
axes 0, 1, 2 with a Gray-code ordering; the second dimension should
use hypercube axes 6 through 11 with a Gray-code ordering; and the
third dimension should use hypercube axes 3, 4, 5, and 12 with a
binary ordering.
\end{implementors}

\section{TEMPLATE Directive}
\label{TEMPLATE-SECTION}

The {\tt TEMPLATE} directive declares one or more templates, specifying for
each the name, the rank (number of dimensions), and the extent in each
dimension.  It must appear in the {\it specification-part} of a scoping unit.

In the language of section 14.1.2 of the Fortran standard,
templates are local entities of class (1); therefore a template may
not have the same name as a variable, named constant, internal
procedure, etc., in the same scoping unit.  Template names obey the
rules for host and use association as other names in the
list in section 12.1.2.2.1 of the Fortran standard.

A template declared in a module has the default accessibility
of the module.

\begin{rationale}
Because the name of a template is not a first-class entity
in HPF, but must appear only in directives, it cannot appear in an
{\it access-stmt} ({\tt PRIVATE} or {\tt PUBLIC}).
If directives ever become full-fledged Fortran statements rather
than structured comments, then it would be appropriate to allow
the accessibility of a template to be controlled
by listing its name in an {\it access-stmt}.
\end{rationale}

A template is simply an abstract space of indexed positions; it can
be considered as an ``array of nothings'' (as compared to an ``array of
integers,'' say).
%%%If an array is a cat, then a template is a Cheshire
%%%cat, and the index space is the grin.
A template may be used as an abstract {\it align-target} that may
then be distributed.
                                                                        \BNF
template-directive             \IS  TEMPLATE template-decl-list

template-decl              \IS  template-name [ ( explicit-shape-spec-list ) ]

                                                                        \FNB

Examples:
                                                                        \CODE
!HPF$ TEMPLATE A(N)
!HPF$ TEMPLATE B(N,N), C(N,2*N)
!HPF$ TEMPLATE DOPEY(100,100),SNEEZY(24),GRUMPY(17,3,5)
                                                                        \EDOC

If the ``{\tt ::}'' syntax is used, then the declared templates may optionally
be distributed in the same {\it combined-directive}.  In this case
all templates declared by the
directive must have the same rank so that the {\tt DISTRIBUTE} attribute
will be meaningful.  The {\tt DIMENSION} attribute may also be used.
                                                                        \CODE
!HPF$ TEMPLATE, DISTRIBUTE(BLOCK,*) ::    &
!HPF$                              WHINEY(64,64),MOPEY(128,128)
!HPF$ TEMPLATE, DIMENSION(91,91) :: BORED,WHEEZY,PERKY
                                                                        \EDOC

Templates are useful in the particular situation where one must align
several arrays relative to one another but there is no need to
declare a single array that spans the entire index space of interest.
For example, one might want four \( N \times N \) arrays aligned to the four
corners of a template of size \( (N+1) \times (N+1) \): 
                                                                        \CODE
!HPF$ TEMPLATE, DISTRIBUTE(BLOCK, BLOCK) :: EARTH(N+1,N+1)
      REAL, DIMENSION(N,N) :: NW, NE, SW, SE
!HPF$ ALIGN NW(I,J) WITH EARTH( I , J )
!HPF$ ALIGN NE(I,J) WITH EARTH( I ,J+1)
!HPF$ ALIGN SW(I,J) WITH EARTH(I+1, J )
!HPF$ ALIGN SE(I,J) WITH EARTH(I+1,J+1)
                                                                        \EDOC
Templates may also be useful in making assertions about the mapping of
dummy arguments (see Chapter~\ref{ch-mapping-subr}).

Unlike arrays, templates cannot be in {\tt COMMON}.  So two templates
declared in different scoping units will always be distinct, even if
they are given the same name.  The only way for two program units to
refer to the same template is to declare the template in a module that
is then used by the two program units.

Templates are not passed through the subprogram argument interface.
The template to which a dummy argument is aligned is always distinct
from the template to which the actual argument is aligned, though it
may be a copy (see Section \ref{INHERIT-SECTION}).  On exit from a
subprogram, an HPF implementation arranges that the actual argument is
aligned with the same template with which it was aligned before the
call.

Returning from a subprogram causes all templates declared local to that
subprogram to become undefined.  It is not HPF-conforming for any
variable to be aligned to a template at the time the template becomes
undefined unless at least one of two conditions holds:

\begin{itemize}

\item The variable itself becomes undefined at the same time by virtue
of returning from the subprogram.

\item Whenever the subprogram is called, the template is always locally
defined in the same way, with identical lower bounds, identical upper
bounds, and identical distribution information (if any) onto
identically defined processor arrangements (see Section
\ref{PROCESSORS-SECTION}).

\begin{rationale}
(Note that this second condition is slightly less stringent than
requiring all expressions to be constant.  This allows calls to {\tt
NUMBER_OF_PROCESSORS} or {\tt PROCESSORS_SHAPE} to appear without
violating the condition.)
\end{rationale}

\end{itemize}

\noindent
Variables in {\tt COMMON} or having the {\tt SAVE} attribute may be
mapped to a locally declared template, but because the first condition
cannot hold for such variable (they don't become undefined), the second
condition must be observed.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Material from the old chapter 7
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Storage and Sequence Association}
\label{sequence}

HPF allows the mapping of
data objects across multiple processors in order to improve 
parallel performance.  Fortran specifies
relationships between the storage for data objects associated 
through {\tt COMMON} and {\tt EQUIVALENCE} statements, and the order of 
array elements during association at procedure boundaries
between actual arguments and dummy arguments.
Otherwise, the location of data is not constrained by the
language.

{\tt COMMON} and {\tt EQUIVALENCE} statements constrain the alignment
of different data items based on the underlying model
of storage units and storage sequences:

\begin{quotation}
{\em Storage association is the association of two or more
data objects that occurs when two or more storage sequences 
share or are aligned with one or more storage units.}

--- Fortran Standard (14.6.3.1)

\end{quotation}
The model of storage association is a single linearly 
addressed memory, based on the traditional single address 
space, single memory unit architecture. This model can cause 
severe inefficiencies on architectures where storage for 
data objects is mapped.

Sequence association refers to the order of array elements 
that Fortran requires when an array expression or array 
element is associated with a dummy array argument:

\begin{quotation}
{\em The rank and shape of the actual argument need not agree 
with the rank and shape of the dummy argument, \ldots}

--- Fortran Standard (12.4.1.4)

\end{quotation}
As with storage association, sequence association
is a natural concept only in systems with
a linearly addressed memory.

As an aid to porting FORTRAN 77 codes, HPF allows codes that 
rely on sequence and storage association to be valid in HPF.
Some modification to existing FORTRAN 77 codes may 
nevertheless be necessary.
This section explains the relationship between HPF data 
mapping and sequence and storage association.

\subsection{Storage Association}

\subsubsection{Definitions}

\label{sequence-defs}

\begin{enumerate}

\item {\tt COMMON} blocks are either {\it sequential}
or {\it nonsequential}, as determined by either explicit 
directive or compiler default.  A sequential {\tt COMMON} block 
has a single common  block storage sequence (Fortran Standard 5.5.2.1).

\item An {\it aggregate variable group}
is a collection of variables whose individual storage
sequences are parts of a single storage sequence.

Variables associated by {\tt EQUIVALENCE} statements
or by a combination of {\tt EQUIVALENCE} and {\tt COMMON} statements
form an aggregate variable group. The variables of a
sequential {\tt COMMON} block form a single aggregate variable
group.

\item The {\it size} of an aggregate variable group is the 
number of storage units in the group's storage sequence 
(Fortran Standard 14.6.3.1).

\item  \label{seq-var} Data objects are either
{\it sequential} or {\it nonsequential}.
A data object is {\it sequential} if and only if any of the
following holds:

\begin{enumerate}

\item it appears in a sequential {\tt COMMON} block;

\item it is a member of an aggregate variable group;

\item it is an assumed-size array;

\item it is a component of a derived type with
the Fortran {\tt SEQUENCE} attribute; or

\item it is declared to be sequential in an HPF {\tt SEQUENCE} 
directive.

\end{enumerate}

A sequential object can be storage associated or
sequence associated;  nonsequential objects cannot.

\item A {\tt COMMON} block contains a sequence of {\it components}.
Each component is either an aggregate
variable group, or a variable that is not a member of any
aggregate variable group.
Sequential {\tt COMMON} blocks contain a single component.
Nonsequential {\tt COMMON} blocks may
contain several components that  may be
sequential variables or aggregate variable groups or
may be nonsequential.

\end{enumerate}

\subsubsection{Examples of Definitions}

                                                                \CODE
      IMPLICIT REAL (A-Z)
      COMMON /FOO/ A(100), B(100), C(100), D(100), E(100)
      DIMENSION X(100), Y(150), Z(200)

!Example 1:
      EQUIVALENCE ( A(1), Z(1) )
!Four components: (A, B), C, D, E
!Sizes are: 200, 100, 100, 100

!Example 2:
      EQUIVALENCE ( A(51), X(1) ) ( B(100), Y(1) )
!Two components (A, B, C, D), E
!Sizes are: 400, 100

!Example 3:
!HPF$ SEQUENCE /FOO/
!The COMMON has one component, (A, B, C, D, E) 
!Size is 500
                                                                \EDOC
\noindent
The {\tt COMMON} block {\tt /FOO/} is nonsequential
in Examples 1 and 2.
Aggregate variable groups are shown as components in 
parentheses.  

\subsection {Sequence Directive}

A {\tt SEQUENCE} directive is defined to allow a user to declare 
explicitly that data objects or {\tt COMMON}  blocks are to be treated 
by the compiler as sequential.  ({\tt COMMON} blocks are by default 
nonsequential.  Data objects are
nonsequential unless Definition~\ref{seq-var} applies.) 
Some implementations may supply an  optional compilation 
environment where the {\tt SEQUENCE} directive is applied by
default.  For completeness in such an environment, HPF 
defines a {\tt NO SEQUENCE} directive to allow a user to 
establish that the usual
nonsequential default should apply to a scoping unit, or selected
data objects and {\tt COMMON} blocks within the scoping unit.

                                        \BNF
sequence-directive  \IS    SEQUENCE [ [ :: ] association-name-list ]
                    \OR NO SEQUENCE [ [ :: ] association-name-list ]

association-name        \IS object-name
                        \OR / [ common-block-name ]  /
                                        \FNB

\begin{constraints}

\item An object name or {\tt COMMON} block name may appear at most once
in a {\it sequence-directive} within any scoping unit.

\item Only one sequence directive with no {\it association-name-list}
is permitted in the same scoping unit.

\end{constraints}

A pointer declared with the {\tt SEQUENCE} attribute can be only be
associated with sequential objects.

\subsubsection {Storage Association Rules}

\begin{enumerate}

\item A {\it sequence-directive} with an empty {\it
association-name-list}  is treated as if it contained the name of all
implicitly mapped objects and {\tt COMMON} blocks in the scoping unit
which cannot otherwise be determined to be sequential or nonsequential
by their language context.

\item A sequential object may not be explicitly mapped.

\item No explicit mapping may be given for a component of a derived
type having the Fortran {\tt SEQUENCE} attribute. 
Note
that this rule is applicable only under the approved extensions
since components of derived types cannot be explicitly mapped in HPF.

\item No explicit mapping may be given for a dummy argument that
is an assumed size array.

\item If a {\tt COMMON} block is nonsequential, then all of the
following must hold:

\begin{enumerate}

\item Every occurrence of the {\tt COMMON}  block has exactly the 
same number of components with each corresponding component 
having a storage sequence of exactly the same size;

\item If a component is a nonsequential variable in {\it any}
occurrence of the {\tt COMMON} block, then it must be
nonsequential with identical  type, shape, and mapping
attributes in {\it every}  occurrence of the {\tt COMMON} block; and

\item Every occurrence of the {\tt COMMON}  block must be 
nonsequential.

\end{enumerate}

\end{enumerate}

\subsubsection{Storage Association Discussion}
\begin{users}
Under these rules, variables in a {\tt COMMON} block can be mapped 
as long as the components of the {\tt COMMON} block are the same in 
every scoping unit that declares the {\tt COMMON} block. 

Correct Fortran programs will not necessarily
be correct without modification in HPF.
The use of
{\tt EQUIVALENCE} with {\tt COMMON} blocks can impact the
mappability of data
objects in subtle ways. To allow maximum 
optimization for performance, the HPF default for data objects is to 
consider them mappable.
In order to get correct separate compilation for
subprograms that use {\tt COMMON} blocks with different aggregate
variable groups in different scoping units, it will be 
necessary to insert the HPF {\tt SEQUENCE} directive.  

As a check-list 
for a user to determine the status of a data object or {\tt COMMON} block,
the following questions can be applied, in order:

\begin{itemize}

\item Does the object appear in some explicit language context
which dictates sequential (e.g. {\tt EQUIVALENCE}) or nonsequential
(e.g. array-valued function result variable)?

\item If not, does the object appear in an explicit mapping
directive?

\item If not, does the object or {\tt COMMON} block name appear in the 
list of names on a {\tt SEQUENCE} or {\tt NO SEQUENCE} directive?

\item If not, does the scoping unit contain a nameless {\tt SEQUENCE}
 or {\tt NO SEQUENCE}?

\item If not, is the compilation affected by some special 
implementation-dependent environment which dictates that names
default to {\tt SEQUENCE}?

\item If not, then the compiler will  consider the object or {\tt COMMON}
block name non-sequential and is free to apply data mapping
optimizations disregarding Fortran sequence and storage association.

\end{itemize}

\end{users}

\begin{implementors}
In order to protect the user and to facilitate portability of 
older codes, two implementation options are strongly 
recommended. First, every implementation should supply some 
mechanism to verify that the type and shape of every mappable 
array and the sizes of aggregate variable groups in  {\tt COMMON} blocks 
are the same in every scoping unit unless the {\tt COMMON}  blocks are  
declared to be sequential. This same check should
also verify that identical mappings have been selected for 
the variables in {\tt COMMON}  blocks.  Implementations without 
interprocedural information can use a link-time check. The 
second implementation option recommended is a  
mechanism to declare that data objects and {\tt COMMON} blocks for
a given compilation should be considered sequential unless 
declared otherwise. The purpose of this feature is to permit 
compilation of large old libraries or  subprograms where 
storage association is known to exist without requiring that 
the code be modified to apply the HPF
{\tt SEQUENCE} directive to every {\tt COMMON} block.
\end{implementors}
---------------------------------------------------------------------------
To (un)subscribe to this list, send mail to [email-masked].
Leave the subject line blank, and in the body put the line
(un)subscribe <email-address>
---------------------------------------------------------------------------