
$maxrank = 3 ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// Array remote access and transformational functions.


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
//                                                                     //
// `synch'                                                             //
//                                                                     //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

inline void synch() {
  TreeSchedule spanTree ;
  :: spanTree(&spanTree, apg) ;

  spanTree.synch() ;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
//                                                                     //
// `get'                                                               //
//                                                                     //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

for($R = 0 ; $R <= $maxrank ; $R++) {

  $ARGS = &repeat('const int str_$r, ', "\n", $R) ;
  $STRS = &repeat('str_$r', ", ", $R) ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
inline void get(&{${ARGS}T* base, const SectionRM$R<T>& a&}) {
  Get schedule(Seq$R<int>($STRS), base, &a, a.offset, a.ptrs, sizeof(T)) ;

  schedule.gather() ;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

}

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
//                                                                     //
// `remap' and `writeHalo'                                             //
//                                                                     //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

for($R = 0 ; $R <= $maxrank ; $R++) {

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
inline void remapRM(const Section$R<T>& b, const SectionRM$R<T>& a) {
  RemapRM schedule(&b, b.dat(),
                   &a, a.offset, a.ptrs,
                   sizeof(T)) ;

  schedule.execute() ;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

#for($R = 1 ; $R <= $maxrank ; $R++) {
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#template<class T>
#inline void writeHalo(const Section$R<T>& src,
#                      const int* wlo, const int* whi, const Mode* modes = 0) {
#  WriteHalo schedule(&src, sizeof(T), wlo, whi, modes) ;
#
#  schedule.execute(src.dat()) ;
#}
#
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#}

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
//                                                                     //
// `gather', `scatter', `vecGather' and `vecScatter'.                  //
//                                                                     //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

// Simple gather

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

for($R = 1 ; $R <= $maxrank ; $R++) {
  for($S = 1 ; $S <= $maxrank ; $S++) {

    $SUBS = &repeat('const Section$S<int>& s_$r', ",\n", $R) ;
    $DADS = &repeat('&s_$r', ", ", $R) ;
    $DATS = &repeat('s_$r.dat()', ", ", $R) ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
inline void gatherRM(&{const Section$S<T>& b, const SectionRM$R<T>& a,
                       $SUBS&}) {
  GatherRM schedule(&b, b.dat(),
                    &a, a.offset, a.ptrs,
                    sizeof(T),
                    Seq$R<const DAD*>($DADS),
                    Seq$R<const int*>($DATS),
                    0, 0) ;

  schedule.execute() ;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  }
}

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// Masked gather

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

for($R = 1 ; $R <= $maxrank ; $R++) {
  for($S = 1 ; $S <= $maxrank ; $S++) {

    $SUBS = &repeat('const Section$S<int>& s_$r,\n', "", $R) ;
    $DADS = &repeat('&s_$r', ", ", $R) ;
    $DATS = &repeat('s_$r.dat()', ", ", $R) ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
inline void gatherRM(&{const Section$S<T>& b, const SectionRM$R<T>& a,
                       ${SUBS}const Section$S<int>& msk&}) {
  GatherRM schedule(&b, b.dat(),
                    &a, a.offset, a.ptrs,
                    sizeof(T),
                    Seq$R<const DAD*>($DADS),
                    Seq$R<const int*>($DATS),
                    &msk, msk.dat()) ;

  schedule.execute() ;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  }
}

#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#
#// Simple scatter
#
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#
#for($R = 1 ; $R <= $maxrank ; $R++) {
#  for($S = 1 ; $S <= $maxrank ; $S++) {
#
#    $SUBS = &repeat('const Section$S<int>& s_$r', ",\n", $R) ;
#    $DADS = &repeat('&s_$r', ", ", $R) ;
#    $DATS = &repeat('s_$r.dat()', ", ", $R) ;
#
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#template<class T>
#inline void scatterRM(&{const Section$S<T>& b, const SectionRM$R<T>& a,
#                        $SUBS&}) {
#  ScatterRM schedule(&b, b.dat(),
#                     &a, a.offset, a.ptrs,
#                     sizeof(T),
#                     Seq$R<const DAD*>($DADS),
#                     Seq$R<const int*>($DATS),
#                     0, 0) ;
#
#  schedule.execute() ;
#}
#
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#  }
#}
#
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#
#// Masked scatter
#
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#
#for($R = 1 ; $R <= $maxrank ; $R++) {
#  for($S = 1 ; $S <= $maxrank ; $S++) {
#
#    $SUBS = &repeat('const Section$S<int>& s_$r,\n', "", $R) ;
#    $DADS = &repeat('&s_$r', ", ", $R) ;
#    $DATS = &repeat('s_$r.dat()', ", ", $R) ;
#
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#template<class T>
#inline void scatterRM(&{const Section$S<T>& b, const SectionRM$R<T>& a,
#                        ${SUBS}const Section$S<int>& msk&}) {
#  ScatterRM schedule(&b, b.dat(),
#                     &a, a.offset, a.ptrs,
#                     sizeof(T),
#                     Seq$R<const DAD*>($DADS),
#                     Seq$R<const int*>($DATS),
#                     &msk, msk.dat()) ;
#
#  schedule.execute() ;
#}
#
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#  }
#}

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// Vector subscript gather.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

for($R = 1 ; $R <= $maxrank ; $R++) {

  $SUBS = &repeat('const Section1<int>* s_$r', ",\n", $R) ;
  $DADS = &repeat('s_$r', ", ", $R) ;
  $DATS = &repeat('s_$r ? s_$r->dat() : 0', ",\n", $R) ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
inline void vecGatherRM(&{const Section$R<T>& b, const SectionRM$R<T>& a,
                          $SUBS&}) {
  VecGatherRM schedule(&b, b.dat(),
                       &a, a.offset, a.ptrs,
                       sizeof(T),
                       Seq$R<const DAD*>($DADS),
                       Seq$R<const int*>(&{$DATS&})) ;

  schedule.execute() ;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// Vector subscript scatter.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

for($R = 1 ; $R <= $maxrank ; $R++) {

  $SUBS = &repeat('const Section1<int>* s_$r', ",\n", $R) ;
  $DADS = &repeat('s_$r', ", ", $R) ;
  $DATS = &repeat('s_$r ? s_$r->dat() : 0', ",\n", $R) ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
inline void vecScatterRM(&{const Section$R<T>& b, const SectionRM$R<T>& a,
                           $SUBS&}) {
  VecScatterRM schedule(&b, b.dat(),
                        &a, a.offset, a.ptrs,
                        sizeof(T),
                        Seq$R<const DAD*>($DADS),
                        Seq$R<const int*>(&{$DATS&})) ;

  schedule.execute() ;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}


# -------------------------------------------------------------
# Things to do
#
#   Eliminate various uses of `Seq' in favour of explicit declaration
#   of local vectors?


