\batchmode

\documentstyle{article}
\makeatletter








\def\PsfigVersion{1.9}

\makeatother
\newenvironment{tex2html_wrap}{}{}
\newwrite\lthtmlwrite
\def\lthtmltypeout#1{{\let\protect\string\immediate\write\lthtmlwrite{#1}}}%
\newbox\sizebox
\begin{document}
\pagestyle{empty}
\stepcounter{section}
\stepcounter{subsection}
\stepcounter{section}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{section}
\stepcounter{subsection}
{\newpage
\clearpage
\samepage \begin{figure}[hbtp]
\footnotesize
\begin{verbatim}class life_java {
  static public void main(String[] args) throws Exception {
    hpj HPJava = new hpj(args);

    int np = HPJava.num_processor();
    int id = HPJava.my_id();

    ... compute local `blockSize', `blockBase' (avoiding empty blocks).

    // `block' has `blockSize + 2' columns.  This allows for ghost cells.

    byte block[][] = new byte[blockSize+2][N];

    ... initialize local block with some pattern

    // Main update loop.

    int next = (id + 1) % np;
    int prev = (id + np - 1) % np;

    for(int iter = 0 ; iter < NITER ; iter++) {

      // Shift this block's upper edge into next neighbour's lower ghost edge

      HPJava.Output(next).write(block[blockSize]);
      HPJava.Output(next).flush();
      HPJava.Input(prev).read(block[0]);

      // Shift this block's lower edge into prev neighbour's upper ghost edge

      HPJava.Output(prev).write(block[1]);
      HPJava.Output(prev).flush();
      HPJava.Input(next).read(block[blockSize+1]);

      ... Calculate a block of neighbour sums.
      ... Update block of board values.
    }
  }
}\end{verbatim}

\end{figure}
}

{\newpage
\clearpage
\samepage \begin{figure}[hbtp]
\footnotesize
\begin{verbatim}    int sums[][] = new int[blockSize][N];

    ....

      //  Calculate block of neighbour sums.

      for(i = 0, ib = 1 ; i < blockSize ; i++, ib++)
        for(y = 0 ; y < N ; y++) {
          int y_n = (y+N-1) % N ;
          int y_p = (y+1) % N ;
          sums[i][y] =
              block[ib - 1][y_n] + block[ib - 1][y] + block[ib - 1][y_p] +
              block[ib]    [y_n] +                    block[ib]    [y_p] +
              block[ib + 1][y_n] + block[ib + 1][y] + block[ib + 1][y_p];
        }

      // Update block of board values.

      for(i = 0, ib = 1 ; i < blockSize ; i++, ib++)
        for(y = 0 ; y < N ; y++)
          switch (sums[i][y]) {
            case 2 : break;
            case 3 : block[ib][y] = 1; break;
            default: block[ib][y] = 0; break;
          }\end{verbatim}

\end{figure}
}

\stepcounter{subsection}
{\newpage
\clearpage
\samepage \begin{figure}[hbtp]
\footnotesize
\begin{verbatim}class Life {
  static public void main(String[] args) {
    MPI.Init(args);

    int np = MPI.WORLD.Size();
    int id = MPI.WORLD.Rank();

    ... compute local `blockSize', `blockBase' (avoiding empty blocks).

    // `block' has `blockSize + 2' columns.  This allows for ghost cells.

    byte block[][] = new byte[blockSize + 2][N] ;

    ... initialize local block with some pattern

    // Main update loop.

    int next = (id + 1) % np;
    int prev = (id + np - 1) % np;

    for(int iter = 0 ; iter < NITER ; iter++) {

      // Shift this block's upper edge into next neighbour's lower ghost edge

      MPI.WORLD.Send(block[blockSize], N, MPI.BYTE, next, 0);
      MPI.WORLD.Recv(block[0],         N, MPI.BYTE, prev, 0);

      // Shift this block's lower edge into prev neighbour's upper ghost edge

      MPI.WORLD.Send(block[1],             N, MPI.BYTE, prev, 0);
      MPI.WORLD.Recv(block[blockSize + 1], N, MPI.BYTE, next, 0);

      ... Calculate block of neighbour sums.
      ... Update block of board values.
    }

    MPI.Finalize();
  }
}\end{verbatim}

\end{figure}
}

\stepcounter{subsection}
{\newpage
\clearpage
\samepage \begin{figure}[hbtp]
\footnotesize
\begin{verbatim}class Life {
  void main(String args) {
    MPI.Init(args) ;

    int dims [] = new int [2] ;
    ... Set `dims', etc
    Cart p = new Cart(MPI.WORLD, dims, periods, false) ;

    int coords = new int [2] ;
    p.Get(dims, periods, coords) ;
    ... Compute local `blockSizeX', `blockBaseX', `blockSizeY', `blockBaseY'.

    // Create `block', allowing for ghost cells.

    int sX = blockSizeX + 2 ;
    int sY = blockSizeY + 2 ;
    block = new byte [sX * sY] ;
    ... Define initial state of Life board

    // Precompute parameters of shift communications.

    Datatype edgeXType = MPI.BYTE.Contiguous(sY) ;
    edgeXType.Commit() ;

    Datatype edgeYType = MPI.BYTE.Vector(sX, 1, sY) ;
    edgeYType.Commit() ;

    CartShift pX = p.shift(0,  1) ;
    CartShift nX = p.shift(0, -1) ;
    CartShift pY = p.shift(1,  1) ;
    CartShift nY = p.shift(1, -1) ;

    // Main update loop.

    for(int iter = 0 ; iter < NITER ; iter++) {
      ... Execute shifts.

      ... Calculate block of neighbour sums.
      ... Update block of board values.
    }

    MPI.Finalize();
  }
  ...
}\end{verbatim}

\end{figure}
}

{\newpage
\clearpage
\samepage \begin{figure}[hbtp]
\footnotesize
\begin{verbatim}      // Execute shifts...

      // Shift this block's upper x edge into next neighbour's lower ghost edge

      p.Sendrecv(block, blockSizeX * sY, 1, edgeXType, pX.dst, 0,
                 block, 0,               1, edgeXType, pX.src, 0) ;

      // Shift this block's lower x edge into prev neighbour's upper ghost edge 

      p.Sendrecv(block, sY,                    1, edgeXType, nX.dst, 0,
                 block, (blockSizeX + 1) * sY, 1, edgeXType, nX.src, 0) ;

      // Shift this block's upper y edge into next neighbour's lower ghost edge

      p.Sendrecv(block, blockSizeY, 1, edgeYType, pY.dst, 0,
                 block, 0,          1, edgeYType, pY.src, 0) ;

      // Shift this block's lower y edge into prev neighbour's upper ghost edge

      p.Sendrecv(block, 1,              1, edgeYType, nY.dst, 0,
                 block, blockSizeY + 1, 1, edgeYType, nY.src, 0) ;\end{verbatim}

\end{figure}
}

\stepcounter{section}
\stepcounter{subsection}
{\newpage
\clearpage
\samepage \begin{figure}[btp]
\footnotesize
\begin{verbatim}public class Life extends Node implements Runnable {
  ...

  public void run() {
    Procs p = new Procs(this, 2, 2) ;

    Range x = new Range(N, p, 0) ;
    Range y = new Range(N, p, 1) ;

    Array r = new Array(p, x, y) ;

    int s = r.seg();
    byte[] w = new byte[s];

    byte[] cn_ = new byte[s];
    byte[] cp_ = new byte[s];
    ... etc, create arrays for 8 neighbours

    // Initialize the Life board

    for(r.forall(); r.test(); r.next())
      w[r.sub()] = fun(r.idx(0), r.idx(1)) ;

    // Main loop

    for (int k=0; k<NITER; k++) {

      // Get neighbours

      shift(cn_, w, r, 0,  1, CYCLIC);
      shift(cp_, w, r, 0, -1, CYCLIC);
      ... etc, copy arrays for 8 neighbours

      // Life update rule

      for(r.forall(); r.test(); r.next()) {
        int i = r.sub() ;
        switch (cn_[i] + cp_[i] + c_n[i] + c_p[i] +
                cnn[i] + cnp[i] + cpn[i] + cpp[i]) {
          case 2 : break;
          case 3 : w[i] = 1; break;
          default: w[i] = 0; break;
        }
      }
    }
  }
}\end{verbatim}

\end{figure}
}

\stepcounter{subsection}
\stepcounter{section}

\end{document}
