
$maxrank = 3 ;

@subTypes = ('T', 'S', 'B') ;   # Scalar, triplet or block

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

// Type-secure C++ interface for multi-dimensional arrays.

extern "C" {
  #include "armci.h"
}

void malloc_rm(void* ptrs [], MPI_Comm *apg_comm, const int bytes) ;
void free_rm(void* ptrs [], MPI_Comm *apg_comm) ;


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
//                                                                     //
// template classes `SectionRMR': Add subscripting operations to       //
//                                `SectionRM_'.                        //
//                                                                     //
// template classes `ArrayRMR': Add element allocation to `SectionRMR' //
//                                                                     //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

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

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

  for($sig = 0 ; $sig < (1 << $R) ; $sig++) {

    # Compute parameters of signature for this instance...

    $numSs = 0 ;
    $mask = 1 ;
    $numSects = 1 ;
    for($r = 0 ; $r < $R ; $r++) {
      if($sig & $mask) {
        $dimType[$r] = 'S' ;
        $numSubs[$r] = 2 ;
        $numSs++ ;
      }
      else {
        $dimType[$r] = 'D' ;
        $numSubs[$r] = 2 ;
        #$numSubs[$r] = 3 ;  # allowing for block subscripts
      }
      $numSects *= $numSubs[$r] ;
      $mask = $mask << 1 ;
    }

    if($numSs) {
      $SIG = join("", @dimType) ;
    }
    else {
      $SIG = "" ;
    }

    ############################################################
    #
    # Section subclass header...
    #
    ############################################################

    if($sig == 0) {  # Signature involves no sequential dimensions
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
class SectionRM$R : public Section$R<T> {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    }
    else {           # Signature involves some sequential dimensions

      if($numSs == 1) {
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
class SectionRM$R$SIG : public virtual Section$R<T> {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
      }
      else {

        # enumerate immediate, non-virtual bases...

        $numBases = 0 ;
        for($r = 0 ; $r < $R ; $r++) {
          if($dimType[$r] eq 'S') {
            if($numSs > 1) {
              $dimType[$r] = 'D' ;
              $BSIG = join("", @dimType) ;
              $dimType[$r] = 'S' ;
            }
            else {
              $BSIG = "" ;
            }
            $bases[$numBases] = "Section$R$BSIG<T>" ;
            $numBases++ ;
          }
        }

        $BASES = &repeat(',\npublic $bases[$r]', "", $numBases) ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
class SectionRM$R$SIG : &{private virtual Section$R<T>$BASES&} {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
      }
    }

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public :
  // Constructors

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

    ############################################################
    #
    # Section copy constructor
    #
    ############################################################

    if($sig) {

      # Signature involves some sequential dimensions

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  // (Due to explicit call to constructor for virtual base class,
  //  following constructors are ineffective if invoked from constructor
  //  of derived-class object).

  SectionRM$R$SIG(const SectionRM$R$SIG<T>& a) : SectionRM$R<T>(a) {}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    }
    else {

      # Signature involves no sequential dimensions

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  SectionRM$R(const SectionRM$R<T>& a) : &{Section$R<T>(a),
                                           offset(a.offset), ptrs(a.ptrs)&} {}

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

    ############################################################
    #
    # Section general constructor
    #
    ############################################################

    $RNGS = &repeat('const Range& x_$r,', "\n", $R) . ($R ? " " : "") ;

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

    $XS   = &repeat('x_$r,', "\n", $R) . ($R ? " " : "") ;

    $SS   = &repeat('str_$r,', "\n", $R) . ($R ? " " : "") ;

    if($sig) {  # Signature involves some sequential dimensions

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  SectionRM$R$SIG(&{${RNGS}const Group& p,
                    ${STRS}T* _data,
                    const int offset, void** ptrs,
                    const int disp&}) : SectionRM$R<T>(&{${XS}p,
                                                         ${SS}_data + disp,
                                                         offset + disp, ptrs&}) {}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    }
    else {      # Signature involves no sequential dimensions

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  SectionRM$R(&{${RNGS}const Group& p,
                ${STRS}T* _data,
                const int _offset, void** _ptrs,
                const int disp&}) : &{Section$R<T>(&{${XS}p,
                                                     ${SS}_data + disp&}),
                                      offset(_offset + disp), ptrs(_ptrs)&} {}

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

    ########################################################### 
    #
    # Simple subscripting operator
    #
    ############################################################

    for($r = 0 ; $r < $R ; $r++) {
      if($dimType[$r] eq 'D') {
        $args[$r] = "const Location& i_$r" ;
        $offs[$r] = "map($r).offset(i_$r)" ;
      }
      else {
        $args[$r] = "const int i_$r" ;
        $offs[$r] = "map($r).offset(rng($r)(i_$r))" ;
      }
    }

    $ARGS = &repeat('$args[$r]', ",\n", $R) ;

    $OFFS = $R ? &repeat('$offs[$r]', " +\n", $R) : "0" ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  // Simple subscripting

  T& operator()(&{$ARGS&}) const {
    return dat() [&{$OFFS&}] ;
  }

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

    ############################################################
    #
    # Section subscripting methods
    #
    ############################################################

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  // Section subscripting

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

    for($sect = 0 ; $sect < $numSects ; $sect++) {

      # Compute `sect' argument types for this instance...

      $residue = $sect ;
      for($r = 0 ; $r < $R ; $r++) {
        $subType[$r] = $subTypes[$residue % $numSubs[$r]] ;
        $residue /= $numSubs[$r] ;
      }

      # Compute result type...

      $resR     = 0 ;
      $resNumSs = 0 ;
      for($r = 0 ; $r < $R ; $r++) {
        if($subType[$r] eq 'T') {
          $resDimType[$resR] = $dimType[$r] ;
          if($dimType[$r] eq 'S') {
            $resNumSs++ ;
          }
          $resR++ ;
        }
      }

      if($resNumSs) {
        $resSIG = join("", @resDimType[0 .. $resR - 1]) ;
      }
      else {
        $resSIG = "" ;
      }

      # Print section member...
      
      $t = 0 ;
      $s = 0 ;
      $d = 0 ;
      for($r = 0 ; $r < $R ; $r++) {
        if($subType[$r] eq 'T') {
          $args[$r] = "const Trip& i_$r" ;
          $rngs[$t] = "rng($r)(i_$r)" ;
          $strs[$t] = "str($r)" ;
          $t++ ;
        }
        if($subType[$r] eq 'S') {
          if($dimType[$r] eq 'D') {
            $args[$r] = "const Location& i_$r" ;
            $divs[$d] = "i_$r" ;
            $offs[$s] = "map($r).offset(i_$r)" ;
            $d++ ;
          }
          else {
            $args[$r] = "const int i_$r" ;
            $offs[$s] = "map($r).offset(rng($r)(i_$r))" ;
          }
          $s++ ;
        }
      }

      $ARGS = &repeat('$args[$r]', ",\n", $R) ;

      $RNGS = &repeat('$rngs[$r]', ",\n", $t) . ($t ? ", " : "") ;

      $DIVS = &repeat(' / $divs[$r]', "", $d) ;

      $STRS = &repeat('$strs[$r]', ",\n", $t) . ($t ? ", " : "") ;

      $OFFS = $s ? &repeat('$offs[$r]', " +\n", $s) : "0" ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  SectionRM$resR$resSIG<T> sect(&{$ARGS&}) const {
    return SectionRM$resR$resSIG<T>(&{${RNGS}grp()$DIVS,
                                      ${STRS}dat(),
                                      offset, ptrs,
                                      $OFFS&}) ;
  }

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    }
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
protected :
  SectionRM$R$SIG() {}  // Used by subclasses.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    if($sig eq 0) {
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  SectionRM$R(const Group& p) : Section$R<T>(p) {}
      // Used by Array classes to initialize virtual base.

public :
  int offset ;
  void** ptrs ;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    }
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
} ;


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

    ############################################################
    #
    # Print Array subclass header...
    #
    ############################################################

    if($sig) {  # Signature involves some sequential dimensions
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
class ArrayRM$R$SIG : public SectionRM$R$SIG<T>, private virtual SectionRM$R<T> {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    }
    else {
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
template<class T>
class ArrayRM$R$SIG : public SectionRM$R<T> {
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    }

    ############################################################
    #
    # Array general constructor
    #
    ############################################################

    for($r = 0 ; $r < $R ; $r++) {
      if($dimType[$r] eq 'D') {
        $args [$r] = "const Range& x_$r" ;
        $maps [$r] = <<EOF ;
    maps [$r] = Map(x_$r, size) ;
    size *= x_$r.volume() ;
EOF
      }
      else {
        $args [$r] = "const int n_$r" ;
        $strs [$r] = <<EOF ;
    maps [$r] = Map(CollapsedRange(n_$r), size) ;
    size *= n_$r ;
EOF
      }
    }

    $ARGS = &repeat('$args[$r],', "\n", $R) . ($R ? " " : "") ;

    $MAPS = &repeat('$maps[$r]', "", $R) ;

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public:

  ArrayRM$R$SIG(&{${ARGS}const Group& p = apg&}) : SectionRM$R<T>(p) {

    int size = 1 ;
$MAPS
    ptrs = new void* [AdlibNProcs()] ;
    malloc_rm(ptrs, &comm, sizeof(T) * size) ;
    data = (T*) ptrs [AdlibLocId()] ;

    offset = 0 ;
  }

  ~ArrayRM$R$SIG() {
    free_rm(ptrs, &comm) ;
    delete [] ptrs ;
  }

private :

  ArrayRM$R$SIG(const ArrayRM$R$SIG& a) : SectionRM$R$SIG(a) {}  // Prohibit copying.

  MPI_Comm comm ;  // Used by 'malloc_rm', 'free_rm'
} ;

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

# ---------------------------------------------------------------
#
# Things to do:
#
#   There seem to be various problems with the classes with sequential
#   dimensions.

