Adding Tim to the addlib

Adding Tim to the addlib

/** Git Intro!
 *
 * The Chapel team's intro to git version control. The core team members should
 * update their name tuple in the array below.
 */

// To play Chapel adlibs, fill out your tuple with a programming language, a
// feeling, and a verb.
//
// name
//         programming language
//                 feeling
//                         verb
const TheTeam = [
  ("Ben", "", "", ""),
  ("Brad", "", "", ""),
  ("David", "", "", ""),
  ("Greg", "", "", ""),
  ("Kyle", "", "", ""),
  ("Lydia", "", "", ""),
  ("Michael", "", "", ""),
  ("Elliot", "", "", ""),
  ("Simon", "", "", ""),
  ("Sung", "", "", ""),
  ("Thomas", "Python", "ecstatic", "<3"),
  ("Tim", "C", "very very very very happy", "like"),
  ("TMac", "", "", ""),
  ("Tom", "", "", ""),
  ("Vass", "", "", "")
];

// Prologue
writeln("Chapel Adlibs!");
writeln("--------------");
writeln();

// Print the adlibs!
for (name, lang, feeling, verb) in TheTeam {
  writef("My name is %s. I used to use %s for all my problems.\nNow, I use Chapel and feel %s! I %s Chapel.\n",
         name, lang, feeling, verb);
  writeln();
}

/** Git Intro!
 *
 * The Chapel team's intro to git version control. The core team members should
 * update their name tuple in the array below.
 */

// To play Chapel adlibs, fill out your tuple with a programming language, a
// feeling, and a verb.
//
// name
//         programming language
//                 feeling
//                         verb
const TheTeam = [
  ("Ben", "", "", ""),
  ("Brad", "", "", ""),
  ("David", "", "", ""),
  ("Greg", "", "", ""),
  ("Kyle", "", "", ""),
  ("Lydia", "", "", ""),
  ("Michael", "", "", ""),
  ("Elliot", "", "", ""),
  ("Simon", "", "", ""),
  ("Sung", "", "", ""),
  ("Thomas", "Python", "ecstatic", "<3"),
  ("Tim", "", "", ""),
  ("TMac", "", "", ""),
  ("Tom", "", "", ""),
  ("Vass", "", "", "")
];

// Prologue
writeln("Chapel Adlibs!");
writeln("--------------");
writeln();

// Print the adlibs!
for (name, lang, feeling, verb) in TheTeam {
  writef("My name is %s. I used to use %s for all my problems.\nNow, I use Chapel and feel %s! I %s Chapel.\n",
         name, lang, feeling, verb);
  writeln();
}


Now Thomas is ecstatic.

Now Thomas is ecstatic.

(cherry picked from commit 3035ac7563e01d65c221df763be326f618f7a0dd)

/** Git Intro!
 *
 * The Chapel team's intro to git version control. The core team members should
 * update their name tuple in the array below.
 */

// To play Chapel adlibs, fill out your tuple with a programming language, a
// feeling, and a verb.
//
// name
//         programming language
//                 feeling
//                         verb
const TheTeam = [
  ("Ben", "", "", ""),
  ("Brad", "xfig", "liberated", "begat"),
  ("David", "", "", ""),
  ("Greg", "", "", ""),
  ("Kyle", "C", "well", "like"),
  ("Lydia", "", "", ""),
  ("Michael", "", "", ""),
  ("Elliot", "", "", ""),
  ("Simon", "", "", ""),
  ("Sung", "", "", ""),
  ("Thomas", "Python", "ecstatic", "<3"),
  ("Tim", "", "", ""),
  ("TMac", "", "", ""),
  ("Tom", "", "", ""),
  ("Vass", "", "", "")
];

// Prologue
writeln("Chapel Adlibs!");
writeln("--------------");
writeln();

// Print the adlibs!
for (name, lang, feeling, verb) in TheTeam {
  writef("My name is %s. I used to use %s for all my problems.\nNow, I use Chapel and feel %s! I %s Chapel.\n",
         name, lang, feeling, verb);
  writeln();
}

/** Git Intro!
 *
 * The Chapel team's intro to git version control. The core team members should
 * update their name tuple in the array below.
 */

// To play Chapel adlibs, fill out your tuple with a programming language, a
// feeling, and a verb.
//
// name
//         programming language
//                 feeling
//                         verb
const TheTeam = [
  ("Ben", "", "", ""),
  ("Brad", "xfig", "liberated", "begat"),
  ("David", "", "", ""),
  ("Greg", "", "", ""),
  ("Kyle", "C", "well", "like"),
  ("Lydia", "", "", ""),
  ("Michael", "", "", ""),
  ("Elliot", "", "", ""),
  ("Simon", "", "", ""),
  ("Sung", "", "", ""),
  ("Thomas", "Python", "happy", "<3"),
  ("Tim", "", "", ""),
  ("TMac", "", "", ""),
  ("Tom", "", "", ""),
  ("Vass", "", "", "")
];

// Prologue
writeln("Chapel Adlibs!");
writeln("--------------");
writeln();

// Print the adlibs!
for (name, lang, feeling, verb) in TheTeam {
  writef("My name is %s. I used to use %s for all my problems.\nNow, I use Chapel and feel %s! I %s Chapel.\n",
         name, lang, feeling, verb);
  writeln();
}


Make tree.chpl clean up after itself. [trivial}

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@22363 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

/*
 * This test constructs a binary tree in parallel and assigns a unique
 * id to each node.  It then computes the sum of the id's in parallel.
 *
 */

//
// configuration constant indicating the height of the tree to
// construct.  Override using --treeHeight=<height>.
//
config const treeHeight: uint = 4;

//
// a simple binary tree node class
//
class node {
  var id: int;
  var left, right: node;
  proc ~node() {
    if left then delete left;
    if right then delete right;
  }
}

//
// the main routine builds the tree and then sums its values
//
proc main() {
  var root = buildTree();
  writeln("sum=", sum(root));
  delete root;
}

//
// buildTree() is a recursive routine that uses a cobegin to create a
// node's children in parallel.  It uses the monotonically decreasing
// height variable to control the recursion.
//
proc buildTree(height: uint = treeHeight, id: int = 1): node {
  var newNode = new node(id);

  if height > 1 {
    cobegin {
      newNode.left  = buildTree(height-1, id + 1);
      newNode.right = buildTree(height-1, id + (1 << (height-1)));
    }
  }

  return newNode;
}

//
// sum() walks the tree in parallel using a cobegin, computing the sum
// of the node IDs using a postorder traversal.
//
proc sum(n: node): int {
  var total = n.id;

  if n.left != nil {
    var sumLeft, sumRight: int;
    cobegin ref(sumLeft, sumRight) {
      sumLeft = sum(n.left);
      sumRight = sum(n.right);
    }
    total += (sumLeft + sumRight);
  }
  return total;
}

/*
 * This test constructs a binary tree in parallel and assigns a unique
 * id to each node.  It then computes the sum of the id's in parallel.
 *
 */

//
// configuration constant indicating the height of the tree to
// construct.  Override using --treeHeight=<height>.
//
config const treeHeight: uint = 4;

//
// a simple binary tree node class
//
class node {
  var id: int;
  var left, right: node;
}

//
// the main routine builds the tree and then sums its values
//
proc main() {
  var root = buildTree();
  writeln("sum=", sum(root));
}

//
// buildTree() is a recursive routine that uses a cobegin to create a
// node's children in parallel.  It uses the monotonically decreasing
// height variable to control the recursion.
//
proc buildTree(height: uint = treeHeight, id: int = 1): node {
  var newNode = new node(id);

  if height > 1 {
    cobegin {
      newNode.left  = buildTree(height-1, id + 1);
      newNode.right = buildTree(height-1, id + (1 << (height-1)));
    }
  }

  return newNode;
}

//
// sum() walks the tree in parallel using a cobegin, computing the sum
// of the node IDs using a postorder traversal.
//
proc sum(n: node): int {
  var total = n.id;

  if n.left != nil {
    var sumLeft, sumRight: int;
    cobegin ref(sumLeft, sumRight) {
      sumLeft = sum(n.left);
      sumRight = sum(n.right);
    }
    total += (sumLeft + sumRight);
  }
  return total;
}


Fixed spots in DefaultRectangularArr where 'low' should have been 'alignedLow'.

Also added bounds checking for the _ddata member of DefaultRectangularArr
(by storing the number of elements allocated into it).
All tests passed this checking (with COMM=none), so I commented it out
(because they probably would affect performance).
We might want to enable them, say, when running nightly valgrind testing.

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@18573 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

use DSIUtil;
config param debugDefaultDist = false;
config param debugDataPar = false;

class DefaultDist: BaseDist {
  proc dsiNewRectangularDom(param rank: int, type idxType, param stridable: bool)
    return new DefaultRectangularDom(rank, idxType, stridable, this);

  proc dsiNewAssociativeDom(type idxType)
    return new DefaultAssociativeDom(idxType, this);

  proc dsiNewOpaqueDom(type idxType)
    return new DefaultOpaqueDom(this);

  proc dsiNewSparseDom(param rank: int, type idxType, dom: domain)
    return new DefaultSparseDom(rank, idxType, this, dom);

  proc dsiIndexLocale(ind) return this.locale;

  proc dsiClone() return this;

  proc dsiAssign(other: this.type) { }

  proc dsiCreateReindexDist(newSpace, oldSpace) return this;
  proc dsiCreateRankChangeDist(param newRank, args) return this;
}

//
// Note that the replicated copies are set up in ChapelLocale on the
// other locales.  This just sets it up on this locale.
//
pragma "private" var defaultDist = new dmap(new DefaultDist());

class DefaultRectangularDom: BaseRectangularDom {
  param rank : int;
  type idxType;
  param stridable: bool;
  var dist: DefaultDist;
  var ranges : rank*range(idxType,BoundedRangeType.bounded,stridable);

  proc linksDistribution() param return false;
  proc dsiLinksDistribution()     return false;

  proc DefaultRectangularDom(param rank, type idxType, param stridable, dist) {
    this.dist = dist;
  }

  proc dsiClear() {
    var emptyRange: range(idxType, BoundedRangeType.bounded, stridable);
    for param i in 1..rank do
      ranges(i) = emptyRange;
  }

  // function and iterator versions, also for setIndices
  proc dsiGetIndices() return ranges;

  proc dsiSetIndices(x) {
    if ranges.size != x.size then
      compilerError("rank mismatch in domain assignment");
    if ranges(1).idxType != x(1).idxType then
      compilerError("index type mismatch in domain assignment");
    ranges = x;
  }

  iter these_help(param d: int) {
    if d == rank - 1 {
      for i in ranges(d) do
        for j in ranges(rank) do
          yield (i, j);
    } else {
      for i in ranges(d) do
        for j in these_help(d+1) do
          yield (i, (...j));
    }
  }

  iter these_help(param d: int, block) {
    if d == block.size - 1 {
      for i in block(d) do
        for j in block(block.size) do
          yield (i, j);
    } else {
      for i in block(d) do
        for j in these_help(d+1, block) do
          yield (i, (...j));
    }
  }

  iter these() {
    if rank == 1 {
      for i in ranges(1) do
        yield i;
    } else {
      for i in these_help(1) do
        yield i;
    }
  }

  iter these(param tag: iterator) where tag == iterator.leader {
    if debugDefaultDist then
      writeln("*** In domain/array leader code:"); // this = ", this);
    const numTasks = if dataParTasksPerLocale==0 then here.numCores
                     else dataParTasksPerLocale;
    const ignoreRunning = dataParIgnoreRunningTasks;
    const minIndicesPerTask = dataParMinGranularity;
    if debugDataPar {
      writeln("### numTasks = ", numTasks);
      writeln("### ignoreRunning = ", ignoreRunning);
      writeln("### minIndicesPerTask = ", minIndicesPerTask);
    }

    if debugDefaultDist then
      writeln("    numTasks=", numTasks, " (", ignoreRunning,
              "), minIndicesPerTask=", minIndicesPerTask);

    var (numChunks, parDim) = _computeChunkStuff(numTasks, ignoreRunning,
                                                 minIndicesPerTask, ranges);
    if debugDefaultDist then
      writeln("    numChunks=", numChunks, " parDim=", parDim,
              " ranges(", parDim, ").length=", ranges(parDim).length);

    if debugDataPar then writeln("### numChunks=", numChunks, " (parDim=", parDim, ")");

    if numChunks == 0 then return;	// Avoid problems with 0:uint(64) - 1 below.

    if (CHPL_TARGET_PLATFORM != "xmt") {
      if numChunks == 1 {
        if rank == 1 {
          yield tuple(0..ranges(1).length-1);
        } else {
          var block: rank*range(idxType);
          for param i in 1..rank do
            block(i) = 0..ranges(i).length-1;
          yield block;
        }
      } else {
        var locBlock: rank*range(idxType);
        for param i in 1..rank do
          locBlock(i) = 0:ranges(i).low.type..#(ranges(i).length);
        if debugDefaultDist then
          writeln("*** DI: locBlock = ", locBlock);
        coforall chunk in 0..numChunks-1 {
          var tuple: rank*range(idxType) = locBlock;
          const (lo,hi) = _computeBlock(locBlock(parDim).length,
                                        numChunks, chunk,
                                        locBlock(parDim).high);
          tuple(parDim) = lo..hi;
          if debugDefaultDist then
            writeln("*** DI[", chunk, "]: tuple = ", tuple);
          yield tuple;
        }
      }
    } else {

      var per_stream_i: uint(64) = 0;
      var total_streams_n: uint(64) = 0;

      var locBlock: rank*range(idxType);
      for param i in 1..rank do
        locBlock(i) = 0:ranges(i).low.type..#(ranges(i).length);

      __primitive_loop("xmt pragma forall i in n", per_stream_i,
                       total_streams_n) {

        var tuple: rank*range(idxType) = locBlock;
        const (lo,hi) = _computeBlock(ranges(parDim).length,
                                      total_streams_n, per_stream_i,
                                      (ranges(parDim).length-1));
        tuple(parDim) = lo..hi;
        yield tuple;
      }
    }
  }

  iter these(param tag: iterator, follower) where tag == iterator.follower {
    proc anyStridable(rangeTuple, param i: int = 1) param
      return if i == rangeTuple.size then rangeTuple(i).stridable
             else rangeTuple(i).stridable || anyStridable(rangeTuple, i+1);

    chpl__testPar("default rectangular domain follower invoked on ", follower);
    if debugDefaultDist then
      writeln("In domain follower code: Following ", follower);
    param stridable = this.stridable || anyStridable(follower);
    var block: rank*range(idxType=idxType, stridable=stridable);
    if stridable {
      for param i in 1..rank {
        const rStride = ranges(i).stride:idxType,
              fStride = follower(i).stride:idxType;
        if ranges(i).stride > 0 {
          const low = ranges(i).low + follower(i).low*rStride,
                high = ranges(i).low + follower(i).high*rStride,
                stride = (rStride * fStride):int;
          block(i) = low..high by stride;
        } else {
          const low = ranges(i).high + follower(i).high*rStride,
                high = ranges(i).high + follower(i).low*rStride,
                stride = (rStride * fStride): int;
          block(i) = low..high by stride;
        }
      }
    } else {
      for  param i in 1..rank do
        block(i) = ranges(i).low+follower(i).low:idxType..ranges(i).low+follower(i).high:idxType;
    }

    if rank == 1 {
      for i in block {
        __primitive("noalias pragma");
        yield i;
      }
    } else {
      for i in these_help(1, block) {
        __primitive("noalias pragma");
        yield i;
      }
    }
  }

  proc dsiMember(ind: rank*idxType) {
    for param i in 1..rank do
      if !ranges(i).member(ind(i)) then
        return false;
    return true;
  }

  proc dsiIndexOrder(ind: rank*idxType) {
    var totOrder: idxType;
    var blk: idxType = 1;
    for param d in 1..rank by -1 {
      const orderD = ranges(d).indexOrder(ind(d));
      if (orderD == -1) then return orderD;
      totOrder += orderD * blk;
      blk *= ranges(d).length;
    }
    return totOrder;
  }

  proc dsiDims()
    return ranges;

  proc dsiDim(d : int)
    return ranges(d);

  // optional, is this necesary? probably not now that
  // homogeneous tuples are implemented as C vectors.
  proc dsiDim(param d : int)
    return ranges(d);

  proc dsiNumIndices {
    var sum = 1:idxType;
    for param i in 1..rank do
      sum *= ranges(i).length;
    return sum;
    // WANT: return * reduce (this(1..rank).length);
  }

  proc dsiLow {
    if rank == 1 {
      return ranges(1).low;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).low;
      return result;
    }
  }

  proc dsiHigh {
    if rank == 1 {
      return ranges(1).high;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).high;
      return result;
    }
  }

  proc dsiAlignedLow {
    if rank == 1 {
      return ranges(1).alignedLow;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).alignedLow;
      return result;
    }
  }

  proc dsiAlignedHigh {
    if rank == 1 {
      return ranges(1).alignedHigh;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).alignedHigh;
      return result;
    }
  }

  proc dsiStride {
    if rank == 1 {
      return ranges(1).stride;
    } else {
      var result: rank*chpl__signedType(idxType);
      for param i in 1..rank do
        result(i) = ranges(i).stride;
      return result;
    }
  }

  proc dsiAlignment {
    if rank == 1 {
      return ranges(1).alignment;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).alignment;
      return result;
    }
  }

  proc dsiFirst {
    if rank == 1 {
      return ranges(1).first;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).first;
      return result;
    }
  }

  proc dsiLast {
    if rank == 1 {
      return ranges(1).last;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).last;
      return result;
    }
  }

  proc dsiBuildArray(type eltType) {
    return new DefaultRectangularArr(eltType=eltType, rank=rank, idxType=idxType,
                                    stridable=stridable, dom=this);
  }

  proc dsiBuildRectangularDom(param rank: int, type idxType, param stridable: bool,
                            ranges: rank*range(idxType,
                                               BoundedRangeType.bounded,
                                               stridable)) {
    var dom = new DefaultRectangularDom(rank, idxType, stridable, dist);
    for i in 1..rank do
      dom.ranges(i) = ranges(i);
    return dom;
  }
}

class DefaultRectangularArr: BaseArr {
  type eltType;
  param rank : int;
  type idxType;
  param stridable: bool;

  var dom : DefaultRectangularDom(rank=rank, idxType=idxType,
                                         stridable=stridable);
  var off: rank*idxType;
  var blk: rank*idxType;
  var str: rank*chpl__signedType(idxType);
  var origin: idxType;
  var factoredOffs: idxType;
  var data : _ddata(eltType);
  var noinit: bool = false;
  //var numelm: int = -1; // for correctness checking

  proc canCopyFromDevice param return true;

  // end class definition here, then defined secondary methods below

  // can the compiler create this automatically?
  proc dsiGetBaseDom() return dom;

  proc dsiDestroyData() {
    if dom.dsiNumIndices > 0 {
      pragma "no copy" pragma "no auto destroy" var dr = data;
      pragma "no copy" pragma "no auto destroy" var dv = __primitive("get ref", dr);
      pragma "no copy" pragma "no auto destroy" var er = __primitive("array_get", dv, 0);
      pragma "no copy" pragma "no auto destroy" var ev = __primitive("get ref", er);
      if (chpl__maybeAutoDestroyed(ev)) {
        for i in 0..dom.dsiNumIndices-1 {
          pragma "no copy" pragma "no auto destroy" var dr = data;
          pragma "no copy" pragma "no auto destroy" var dv = __primitive("get ref", dr);
          pragma "no copy" pragma "no auto destroy" var er = __primitive("array_get", dv, i);
          pragma "no copy" pragma "no auto destroy" var ev = __primitive("get ref", er);
          chpl__autoDestroy(ev);
        }
      }
    }
    delete data;
  }

  iter these() var {
    if rank == 1 {
      // This is specialized to avoid overheads of calling dsiAccess()
      if !dom.stridable {
        // This is specialized because the strided version disables the
        // "single loop iterator" optimization
        var first = getDataIndex(dom.dsiLow);
        var second = getDataIndex(dom.dsiLow+dom.ranges(1).stride:idxType);
        var step = (second-first):chpl__signedType(idxType);
        var last = first + (dom.dsiNumIndices-1) * step:idxType;
        for i in first..last by step do
          yield data(i);
      } else {
        const stride = dom.ranges(1).stride: idxType,
              start  = dom.ranges(1).first,
              first  = getDataIndex(start),
              second = getDataIndex(start + stride),
              step   = (second-first):chpl__signedType(idxType),
              last   = first + (dom.ranges(1).length-1) * step:idxType;
        if step > 0 then
          for i in first..last by step do
            yield data(i);
        else
          for i in last..first by step do
            yield data(i);
      }
    } else {
      for i in dom do
        yield dsiAccess(i);
    }
  }

  iter these(param tag: iterator) where tag == iterator.leader {
    for follower in dom.these(tag) do
      yield follower;
  }

  iter these(param tag: iterator, follower) var where tag == iterator.follower {
    if debugDefaultDist then
      writeln("*** In array follower code:"); // [\n", this, "]");
    for i in dom.these(tag=iterator.follower, follower) {
      __primitive("noalias pragma");
      yield dsiAccess(i);
    }
  }

  proc computeFactoredOffs() {
    factoredOffs = 0:idxType;
    for param i in 1..rank do {
      factoredOffs = factoredOffs + blk(i) * off(i);
    }
  }

  // change name to setup and call after constructor call sites
  // we want to get rid of all initialize functions everywhere
  proc initialize() {
    if noinit == true then return;
    for param dim in 1..rank {
      off(dim) = dom.dsiDim(dim).alignedLow;
      str(dim) = dom.dsiDim(dim).stride;
    }
    blk(rank) = 1:idxType;
    for param dim in 1..rank-1 by -1 do
      blk(dim) = blk(dim+1) * dom.dsiDim(dim+1).length;
    computeFactoredOffs();
    var size = blk(1) * dom.dsiDim(1).length;
    data = new _ddata(eltType);
    //assert(size >= 0);
    //assert(size:int(64) <= max(int):int(64));
    //numelm = size: int;
    data.init(size);
  }

  pragma "inline"
  proc getDataIndex(ind: idxType ...1) where rank == 1
    return getDataIndex(ind);

  pragma "inline"
  proc getDataIndex(ind: rank* idxType) {
    var sum = origin;
    if stridable {
      for param i in 1..rank do
        sum += (ind(i) - off(i)) * blk(i) / abs(str(i)):idxType;
    } else {
      for param i in 1..rank do
        sum += ind(i) * blk(i);
      sum -= factoredOffs;
    }
    return sum;
  }

  // only need second version because wrapper record can pass a 1-tuple
  pragma "inline"
  proc dsiAccess(ind: idxType ...1) var where rank == 1
    return dsiAccess(ind);

  pragma "inline"
  proc dsiAccess(ind : rank*idxType) var {
    if boundsChecking then
      if !dom.dsiMember(ind) then
        halt("array index out of bounds: ", ind);
    var dataInd = getDataIndex(ind);
    //assert(dataInd >= 0);
    //assert(numelm >= 0); // ensure it has been initialized
    //assert(dataInd: uint(64) < numelm: uint(64));
    return data(dataInd);
  }

  proc dsiReindex(d: DefaultRectangularDom) {
    var alias = new DefaultRectangularArr(eltType=eltType, rank=d.rank,
                                         idxType=d.idxType,
                                         stridable=d.stridable,
                                         dom=d, noinit=true);
    alias.data = data;
    //alias.numelm = numelm;
    for param i in 1..rank {
      alias.off(i) = d.dsiDim(i).low;
      alias.blk(i) = (blk(i) * dom.dsiDim(i).stride / str(i)) : d.idxType;
      alias.str(i) = d.dsiDim(i).stride;
    }
    alias.origin = origin:d.idxType;
    alias.computeFactoredOffs();
    return alias;
  }

  proc dsiSlice(d: DefaultRectangularDom) {
    var alias = new DefaultRectangularArr(eltType=eltType, rank=rank,
                                         idxType=idxType,
                                         stridable=d.stridable,
                                         dom=d, noinit=true);
    alias.data = data;
    //alias.numelm = numelm;
    alias.blk = blk;
    alias.str = str;
    alias.origin = origin;
    for param i in 1..rank {
      alias.off(i) = d.dsiDim(i).low;
      alias.origin += blk(i) * (d.dsiDim(i).low - off(i)) / str(i);
    }
    alias.computeFactoredOffs();
    return alias;
  }

  proc dsiRankChange(d, param newRank: int, param newStridable: bool, args) {
    proc isRange(r: range(?e,?b,?s,?a)) param return 1;
    proc isRange(r) param return 0;

    var alias = new DefaultRectangularArr(eltType=eltType, rank=newRank,
                                         idxType=idxType,
                                         stridable=newStridable,
                                         dom=d, noinit=true);
    alias.data = data;
    //alias.numelm = numelm;
    var i = 1;
    alias.origin = origin;
    for param j in 1..args.size {
      if isRange(args(j)) {
        alias.off(i) = d.dsiDim(i).low;
        alias.origin += blk(j) * (d.dsiDim(i).low - off(j)) / str(j);
        alias.blk(i) = blk(j);
        alias.str(i) = str(j);
        i += 1;
      } else {
        alias.origin += blk(j) * (args(j) - off(j)) / str(j);
      }
    }
    alias.computeFactoredOffs();
    return alias;
  }

  proc dsiReallocate(d: domain) {
    if (d._value.type == dom.type) {
      var copy = new DefaultRectangularArr(eltType=eltType, rank=rank,
                                          idxType=idxType,
                                          stridable=d._value.stridable,
                                          dom=d._value);
      for i in d((...dom.ranges)) do
        copy.dsiAccess(i) = dsiAccess(i);
      off = copy.off;
      blk = copy.blk;
      str = copy.str;
      origin = copy.origin;
      factoredOffs = copy.factoredOffs;
      dsiDestroyData();
      data = copy.data;
      //numelm = copy.numelm;
      delete copy;
    } else {
      halt("illegal reallocation");
    }
  }

  proc dsiLocalSlice(ranges) {
    halt("all dsiLocalSlice calls on DefaultRectangulars should be handled in ChapelArray.chpl");
  }
}

proc DefaultRectangularDom.dsiSerialWrite(f: Writer) {
  f.write("[", dsiDim(1));
  for i in 2..rank do
    f.write(", ", dsiDim(i));
  f.write("]");
}

proc DefaultRectangularArr.dsiSerialWrite(f: Writer) {
  proc recursiveArrayWriter(in idx: rank*idxType, dim=1, in last=false) {
    var makeStridePositive = if dom.ranges(dim).stride > 0 then 1 else -1;
    if dim == rank {
      var first = true;
      if debugDefaultDist then f.writeln(dom.ranges(dim));
      for j in dom.ranges(dim) by makeStridePositive {
        if first then first = false; else f.write(" ");
        idx(dim) = j;
        f.write(dsiAccess(idx));
      }
    } else {
      for j in dom.ranges(dim) by makeStridePositive {
        var lastIdx =  dom.ranges(dim).last;
        idx(dim) = j;
        recursiveArrayWriter(idx, dim=dim+1,
                             last=(last || dim == 1) && (j == lastIdx));
      }
    }
    if !last && dim != 1 then
      f.writeln();
  }
  const zeroTup: rank*idxType;
  recursiveArrayWriter(zeroTup);
}

use DSIUtil;
config param debugDefaultDist = false;
config param debugDataPar = false;

class DefaultDist: BaseDist {
  proc dsiNewRectangularDom(param rank: int, type idxType, param stridable: bool)
    return new DefaultRectangularDom(rank, idxType, stridable, this);

  proc dsiNewAssociativeDom(type idxType)
    return new DefaultAssociativeDom(idxType, this);

  proc dsiNewOpaqueDom(type idxType)
    return new DefaultOpaqueDom(this);

  proc dsiNewSparseDom(param rank: int, type idxType, dom: domain)
    return new DefaultSparseDom(rank, idxType, this, dom);

  proc dsiIndexLocale(ind) return this.locale;

  proc dsiClone() return this;

  proc dsiAssign(other: this.type) { }

  proc dsiCreateReindexDist(newSpace, oldSpace) return this;
  proc dsiCreateRankChangeDist(param newRank, args) return this;
}

//
// Note that the replicated copies are set up in ChapelLocale on the
// other locales.  This just sets it up on this locale.
//
pragma "private" var defaultDist = new dmap(new DefaultDist());

class DefaultRectangularDom: BaseRectangularDom {
  param rank : int;
  type idxType;
  param stridable: bool;
  var dist: DefaultDist;
  var ranges : rank*range(idxType,BoundedRangeType.bounded,stridable);

  proc linksDistribution() param return false;
  proc dsiLinksDistribution()     return false;

  proc DefaultRectangularDom(param rank, type idxType, param stridable, dist) {
    this.dist = dist;
  }

  proc dsiClear() {
    var emptyRange: range(idxType, BoundedRangeType.bounded, stridable);
    for param i in 1..rank do
      ranges(i) = emptyRange;
  }

  // function and iterator versions, also for setIndices
  proc dsiGetIndices() return ranges;

  proc dsiSetIndices(x) {
    if ranges.size != x.size then
      compilerError("rank mismatch in domain assignment");
    if ranges(1).idxType != x(1).idxType then
      compilerError("index type mismatch in domain assignment");
    ranges = x;
  }

  iter these_help(param d: int) {
    if d == rank - 1 {
      for i in ranges(d) do
        for j in ranges(rank) do
          yield (i, j);
    } else {
      for i in ranges(d) do
        for j in these_help(d+1) do
          yield (i, (...j));
    }
  }

  iter these_help(param d: int, block) {
    if d == block.size - 1 {
      for i in block(d) do
        for j in block(block.size) do
          yield (i, j);
    } else {
      for i in block(d) do
        for j in these_help(d+1, block) do
          yield (i, (...j));
    }
  }

  iter these() {
    if rank == 1 {
      for i in ranges(1) do
        yield i;
    } else {
      for i in these_help(1) do
        yield i;
    }
  }

  iter these(param tag: iterator) where tag == iterator.leader {
    if debugDefaultDist then
      writeln("*** In domain/array leader code:"); // this = ", this);
    const numTasks = if dataParTasksPerLocale==0 then here.numCores
                     else dataParTasksPerLocale;
    const ignoreRunning = dataParIgnoreRunningTasks;
    const minIndicesPerTask = dataParMinGranularity;
    if debugDataPar {
      writeln("### numTasks = ", numTasks);
      writeln("### ignoreRunning = ", ignoreRunning);
      writeln("### minIndicesPerTask = ", minIndicesPerTask);
    }

    if debugDefaultDist then
      writeln("    numTasks=", numTasks, " (", ignoreRunning,
              "), minIndicesPerTask=", minIndicesPerTask);

    var (numChunks, parDim) = _computeChunkStuff(numTasks, ignoreRunning,
                                                 minIndicesPerTask, ranges);
    if debugDefaultDist then
      writeln("    numChunks=", numChunks, " parDim=", parDim,
              " ranges(", parDim, ").length=", ranges(parDim).length);

    if debugDataPar then writeln("### numChunks=", numChunks, " (parDim=", parDim, ")");

    if numChunks == 0 then return;	// Avoid problems with 0:uint(64) - 1 below.

    if (CHPL_TARGET_PLATFORM != "xmt") {
      if numChunks == 1 {
        if rank == 1 {
          yield tuple(0..ranges(1).length-1);
        } else {
          var block: rank*range(idxType);
          for param i in 1..rank do
            block(i) = 0..ranges(i).length-1;
          yield block;
        }
      } else {
        var locBlock: rank*range(idxType);
        for param i in 1..rank do
          locBlock(i) = 0:ranges(i).low.type..#(ranges(i).length);
        if debugDefaultDist then
          writeln("*** DI: locBlock = ", locBlock);
        coforall chunk in 0..numChunks-1 {
          var tuple: rank*range(idxType) = locBlock;
          const (lo,hi) = _computeBlock(locBlock(parDim).length,
                                        numChunks, chunk,
                                        locBlock(parDim).high);
          tuple(parDim) = lo..hi;
          if debugDefaultDist then
            writeln("*** DI[", chunk, "]: tuple = ", tuple);
          yield tuple;
        }
      }
    } else {

      var per_stream_i: uint(64) = 0;
      var total_streams_n: uint(64) = 0;

      var locBlock: rank*range(idxType);
      for param i in 1..rank do
        locBlock(i) = 0:ranges(i).low.type..#(ranges(i).length);

      __primitive_loop("xmt pragma forall i in n", per_stream_i,
                       total_streams_n) {

        var tuple: rank*range(idxType) = locBlock;
        const (lo,hi) = _computeBlock(ranges(parDim).length,
                                      total_streams_n, per_stream_i,
                                      (ranges(parDim).length-1));
        tuple(parDim) = lo..hi;
        yield tuple;
      }
    }
  }

  iter these(param tag: iterator, follower) where tag == iterator.follower {
    proc anyStridable(rangeTuple, param i: int = 1) param
      return if i == rangeTuple.size then rangeTuple(i).stridable
             else rangeTuple(i).stridable || anyStridable(rangeTuple, i+1);

    chpl__testPar("default rectangular domain follower invoked on ", follower);
    if debugDefaultDist then
      writeln("In domain follower code: Following ", follower);
    param stridable = this.stridable || anyStridable(follower);
    var block: rank*range(idxType=idxType, stridable=stridable);
    if stridable {
      for param i in 1..rank {
        const rStride = ranges(i).stride:idxType,
              fStride = follower(i).stride:idxType;
        if ranges(i).stride > 0 {
          const low = ranges(i).low + follower(i).low*rStride,
                high = ranges(i).low + follower(i).high*rStride,
                stride = (rStride * fStride):int;
          block(i) = low..high by stride;
        } else {
          const low = ranges(i).high + follower(i).high*rStride,
                high = ranges(i).high + follower(i).low*rStride,
                stride = (rStride * fStride): int;
          block(i) = low..high by stride;
        }
      }
    } else {
      for  param i in 1..rank do
        block(i) = ranges(i).low+follower(i).low:idxType..ranges(i).low+follower(i).high:idxType;
    }

    if rank == 1 {
      for i in block {
        __primitive("noalias pragma");
        yield i;
      }
    } else {
      for i in these_help(1, block) {
        __primitive("noalias pragma");
        yield i;
      }
    }
  }

  proc dsiMember(ind: rank*idxType) {
    for param i in 1..rank do
      if !ranges(i).member(ind(i)) then
        return false;
    return true;
  }

  proc dsiIndexOrder(ind: rank*idxType) {
    var totOrder: idxType;
    var blk: idxType = 1;
    for param d in 1..rank by -1 {
      const orderD = ranges(d).indexOrder(ind(d));
      if (orderD == -1) then return orderD;
      totOrder += orderD * blk;
      blk *= ranges(d).length;
    }
    return totOrder;
  }

  proc dsiDims()
    return ranges;

  proc dsiDim(d : int)
    return ranges(d);

  // optional, is this necesary? probably not now that
  // homogeneous tuples are implemented as C vectors.
  proc dsiDim(param d : int)
    return ranges(d);

  proc dsiNumIndices {
    var sum = 1:idxType;
    for param i in 1..rank do
      sum *= ranges(i).length;
    return sum;
    // WANT: return * reduce (this(1..rank).length);
  }

  proc dsiLow {
    if rank == 1 {
      return ranges(1).low;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).low;
      return result;
    }
  }

  proc dsiHigh {
    if rank == 1 {
      return ranges(1).high;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).high;
      return result;
    }
  }

  proc dsiAlignedLow {
    if rank == 1 {
      return ranges(1).alignedLow;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).alignedLow;
      return result;
    }
  }

  proc dsiAlignedHigh {
    if rank == 1 {
      return ranges(1).alignedHigh;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).alignedHigh;
      return result;
    }
  }

  proc dsiStride {
    if rank == 1 {
      return ranges(1).stride;
    } else {
      var result: rank*chpl__signedType(idxType);
      for param i in 1..rank do
        result(i) = ranges(i).stride;
      return result;
    }
  }

  proc dsiAlignment {
    if rank == 1 {
      return ranges(1).alignment;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).alignment;
      return result;
    }
  }

  proc dsiFirst {
    if rank == 1 {
      return ranges(1).first;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).first;
      return result;
    }
  }

  proc dsiLast {
    if rank == 1 {
      return ranges(1).last;
    } else {
      var result: rank*idxType;
      for param i in 1..rank do
        result(i) = ranges(i).last;
      return result;
    }
  }

  proc dsiBuildArray(type eltType) {
    return new DefaultRectangularArr(eltType=eltType, rank=rank, idxType=idxType,
                                    stridable=stridable, dom=this);
  }

  proc dsiBuildRectangularDom(param rank: int, type idxType, param stridable: bool,
                            ranges: rank*range(idxType,
                                               BoundedRangeType.bounded,
                                               stridable)) {
    var dom = new DefaultRectangularDom(rank, idxType, stridable, dist);
    for i in 1..rank do
      dom.ranges(i) = ranges(i);
    return dom;
  }
}

class DefaultRectangularArr: BaseArr {
  type eltType;
  param rank : int;
  type idxType;
  param stridable: bool;

  var dom : DefaultRectangularDom(rank=rank, idxType=idxType,
                                         stridable=stridable);
  var off: rank*idxType;
  var blk: rank*idxType;
  var str: rank*chpl__signedType(idxType);
  var origin: idxType;
  var factoredOffs: idxType;
  var data : _ddata(eltType);
  var noinit: bool = false;

  proc canCopyFromDevice param return true;

  // end class definition here, then defined secondary methods below

  // can the compiler create this automatically?
  proc dsiGetBaseDom() return dom;

  proc dsiDestroyData() {
    if dom.dsiNumIndices > 0 {
      pragma "no copy" pragma "no auto destroy" var dr = data;
      pragma "no copy" pragma "no auto destroy" var dv = __primitive("get ref", dr);
      pragma "no copy" pragma "no auto destroy" var er = __primitive("array_get", dv, 0);
      pragma "no copy" pragma "no auto destroy" var ev = __primitive("get ref", er);
      if (chpl__maybeAutoDestroyed(ev)) {
        for i in 0..dom.dsiNumIndices-1 {
          pragma "no copy" pragma "no auto destroy" var dr = data;
          pragma "no copy" pragma "no auto destroy" var dv = __primitive("get ref", dr);
          pragma "no copy" pragma "no auto destroy" var er = __primitive("array_get", dv, i);
          pragma "no copy" pragma "no auto destroy" var ev = __primitive("get ref", er);
          chpl__autoDestroy(ev);
        }
      }
    }
    delete data;
  }

  iter these() var {
    if rank == 1 {
      // This is specialized to avoid overheads of calling dsiAccess()
      if !dom.stridable {
        // This is specialized because the strided version disables the
        // "single loop iterator" optimization
        var first = getDataIndex(dom.dsiLow);
        var second = getDataIndex(dom.dsiLow+dom.ranges(1).stride:idxType);
        var step = (second-first):chpl__signedType(idxType);
        var last = first + (dom.dsiNumIndices-1) * step:idxType;
        for i in first..last by step do
          yield data(i);
      } else {
        const stride = dom.ranges(1).stride: idxType,
              start  = if stride > 0 then dom.dsiLow else dom.dsiHigh,
              first  = getDataIndex(start),
              second = getDataIndex(start + stride),
              step   = (second-first):chpl__signedType(idxType),
              last   = first + (dom.dsiNumIndices-1) * step:idxType;
        if step > 0 then
          for i in first..last by step do
            yield data(i);
        else
          for i in last..first by step do
            yield data(i);
      }
    } else {
      for i in dom do
        yield dsiAccess(i);
    }
  }

  iter these(param tag: iterator) where tag == iterator.leader {
    for follower in dom.these(tag) do
      yield follower;
  }

  iter these(param tag: iterator, follower) var where tag == iterator.follower {
    if debugDefaultDist then
      writeln("*** In array follower code:"); // [\n", this, "]");
    for i in dom.these(tag=iterator.follower, follower) {
      __primitive("noalias pragma");
      yield dsiAccess(i);
    }
  }

  proc computeFactoredOffs() {
    factoredOffs = 0:idxType;
    for param i in 1..rank do {
      factoredOffs = factoredOffs + blk(i) * off(i);
    }
  }

  // change name to setup and call after constructor call sites
  // we want to get rid of all initialize functions everywhere
  proc initialize() {
    if noinit == true then return;
    for param dim in 1..rank {
      off(dim) = dom.dsiDim(dim).low;
      str(dim) = dom.dsiDim(dim).stride;
    }
    blk(rank) = 1:idxType;
    for param dim in 1..rank-1 by -1 do
      blk(dim) = blk(dim+1) * dom.dsiDim(dim+1).length;
    computeFactoredOffs();
    var size = blk(1) * dom.dsiDim(1).length;
    data = new _ddata(eltType);
    data.init(size);
  }

  pragma "inline"
  proc getDataIndex(ind: idxType ...1) where rank == 1
    return getDataIndex(ind);

  pragma "inline"
  proc getDataIndex(ind: rank* idxType) {
    var sum = origin;
    if stridable {
      for param i in 1..rank do
        sum += (ind(i) - off(i)) * blk(i) / abs(str(i)):idxType;
    } else {
      for param i in 1..rank do
        sum += ind(i) * blk(i);
      sum -= factoredOffs;
    }
    return sum;
  }

  // only need second version because wrapper record can pass a 1-tuple
  pragma "inline"
  proc dsiAccess(ind: idxType ...1) var where rank == 1
    return dsiAccess(ind);

  pragma "inline"
  proc dsiAccess(ind : rank*idxType) var {
    if boundsChecking then
      if !dom.dsiMember(ind) then
        halt("array index out of bounds: ", ind);
    return data(getDataIndex(ind));
  }

  proc dsiReindex(d: DefaultRectangularDom) {
    var alias = new DefaultRectangularArr(eltType=eltType, rank=d.rank,
                                         idxType=d.idxType,
                                         stridable=d.stridable,
                                         dom=d, noinit=true);
    alias.data = data;
    for param i in 1..rank {
      alias.off(i) = d.dsiDim(i).low;
      alias.blk(i) = (blk(i) * dom.dsiDim(i).stride / str(i)) : d.idxType;
      alias.str(i) = d.dsiDim(i).stride;
    }
    alias.origin = origin:d.idxType;
    alias.computeFactoredOffs();
    return alias;
  }

  proc dsiSlice(d: DefaultRectangularDom) {
    var alias = new DefaultRectangularArr(eltType=eltType, rank=rank,
                                         idxType=idxType,
                                         stridable=d.stridable,
                                         dom=d, noinit=true);
    alias.data = data;
    alias.blk = blk;
    alias.str = str;
    alias.origin = origin;
    for param i in 1..rank {
      alias.off(i) = d.dsiDim(i).low;
      alias.origin += blk(i) * (d.dsiDim(i).low - off(i)) / str(i);
    }
    alias.computeFactoredOffs();
    return alias;
  }

  proc dsiRankChange(d, param newRank: int, param newStridable: bool, args) {
    proc isRange(r: range(?e,?b,?s,?a)) param return 1;
    proc isRange(r) param return 0;

    var alias = new DefaultRectangularArr(eltType=eltType, rank=newRank,
                                         idxType=idxType,
                                         stridable=newStridable,
                                         dom=d, noinit=true);
    alias.data = data;
    var i = 1;
    alias.origin = origin;
    for param j in 1..args.size {
      if isRange(args(j)) {
        alias.off(i) = d.dsiDim(i).low;
        alias.origin += blk(j) * (d.dsiDim(i).low - off(j)) / str(j);
        alias.blk(i) = blk(j);
        alias.str(i) = str(j);
        i += 1;
      } else {
        alias.origin += blk(j) * (args(j) - off(j)) / str(j);
      }
    }
    alias.computeFactoredOffs();
    return alias;
  }

  proc dsiReallocate(d: domain) {
    if (d._value.type == dom.type) {
      var copy = new DefaultRectangularArr(eltType=eltType, rank=rank,
                                          idxType=idxType,
                                          stridable=d._value.stridable,
                                          dom=d._value);
      for i in d((...dom.ranges)) do
        copy.dsiAccess(i) = dsiAccess(i);
      off = copy.off;
      blk = copy.blk;
      str = copy.str;
      origin = copy.origin;
      factoredOffs = copy.factoredOffs;
      dsiDestroyData();
      data = copy.data;
      delete copy;
    } else {
      halt("illegal reallocation");
    }
  }

  proc dsiLocalSlice(ranges) {
    halt("all dsiLocalSlice calls on DefaultRectangulars should be handled in ChapelArray.chpl");
  }
}

proc DefaultRectangularDom.dsiSerialWrite(f: Writer) {
  f.write("[", dsiDim(1));
  for i in 2..rank do
    f.write(", ", dsiDim(i));
  f.write("]");
}

proc DefaultRectangularArr.dsiSerialWrite(f: Writer) {
  proc recursiveArrayWriter(in idx: rank*idxType, dim=1, in last=false) {
    var makeStridePositive = if dom.ranges(dim).stride > 0 then 1 else -1;
    if dim == rank {
      var first = true;
      if debugDefaultDist then f.writeln(dom.ranges(dim));
      for j in dom.ranges(dim) by makeStridePositive {
        if first then first = false; else f.write(" ");
        idx(dim) = j;
        f.write(dsiAccess(idx));
      }
    } else {
      for j in dom.ranges(dim) by makeStridePositive {
        var lastIdx =  dom.ranges(dim).last;
        idx(dim) = j;
        recursiveArrayWriter(idx, dim=dim+1,
                             last=(last || dim == 1) && (j == lastIdx));
      }
    }
    if !last && dim != 1 then
      f.writeln();
  }
  const zeroTup: rank*idxType;
  recursiveArrayWriter(zeroTup);
}


Move transpose(mTransition) out of loop.

/* Basic RBC model with full depreciation.
 *
 * Thomas Van Doren, Chapel Team
 * Seattle, July 7, 2014
 */

use Math;
use MatrixHelpers;
use Time;

// When true, print the elapsed time at the end.
config const printElapsed = true,
  gridCapital = 17820;

proc main() {
  // 0. Housekeeping
  var timer: Timer;
  timer.start();

  // 1. Calibration
  var aalpha = 1.0 / 3.0,  // Elasticity of output w.r.t. capital
    bbeta = 0.95;          // Discount factor

  // Productivity values
  var vProductivity = [0.9792, 0.9896, 1.0000, 1.0106, 1.0212];

  // Transition matrix
  // This creates a 1 dimensional array and then "reshapes" it into a 2
  // dimensional domain, 5x5 array.
  var mTransition = reshape([0.9727, 0.0273, 0.0000, 0.0000, 0.0000,
                             0.0041, 0.9806, 0.0153, 0.0000, 0.0000,
                             0.0000, 0.0082, 0.9837, 0.0082, 0.0000,
                             0.0000, 0.0000, 0.0153, 0.9806, 0.0041,
                             0.0000, 0.0000, 0.0000, 0.0273, 0.9727],
                            {1..5, 1..5});

  // 2. Steady State
  var capitalSteadyState = (aalpha * bbeta) ** (1 / (1 - aalpha)),
    outputSteadyState = capitalSteadyState ** aalpha,
    consumptionSteadyState = outputSteadyState - capitalSteadyState;

  writeln("Output = ", outputSteadyState,
          ", Capital = ", capitalSteadyState,
          ", Consumption = ", consumptionSteadyState, "\n");

  // We generate the grid of capital
  var nGridCapital = gridCapital,
    nGridProductivity = 5;
  var vGridCapital: [1..nGridCapital] real;
  forall (value, nCapital) in zip(vGridCapital, 0..) {
    value = 0.5*capitalSteadyState + 0.00001 * nCapital;
  }

  // 3. Required matrices and vectors.
  var gridProductivityDomain = {1..nGridCapital, 1..nGridProductivity};
  var mOutput, mValueFunction, mValueFunctionNew, mPolicyFunction,
    expectedValueFunction: [gridProductivityDomain] real;

  // 4. We pre-build output for each point in the grid.

  for (valueProductivity, nProductivity) in zip(vProductivity, 1..) {
    mOutput[1..nGridCapital, nProductivity] =
      valueProductivity * (vGridCapital ** aalpha);
  }

  // 5. Main iteration

  var maxDifference = 10.0,
    tolerance = 0.0000001,
    iteration = 0;

  var gridCapitalNextPeriod: int,
    valueHighSoFar, valueProvisional, consumption, capitalChoice: real;

  // Intermediate array, to be reused in dotProduct()/transpose() calls below.
  var mTransitionTranspose: [1..5, 1..5] real;
  transpose(mTransitionTranspose, mTransition);

  while (maxDifference > tolerance) {
    // expectedValueFunction = mValueFunction * transpose(mTransition)
    dotProduct(expectedValueFunction, mValueFunction, mTransitionTranspose);

    for nProductivity in 1..nGridProductivity {

      // We start from previous choice (monotonicity of policy function)
      gridCapitalNextPeriod = 1;

      for nCapital in 1..nGridCapital {
        valueHighSoFar = -100000.0;
        capitalChoice = vGridCapital[1];

        for nCapitalNextPeriod in gridCapitalNextPeriod..nGridCapital {
          consumption = mOutput[nCapital, nProductivity] - vGridCapital[nCapitalNextPeriod];
          valueProvisional = (1 - bbeta) * log(consumption) + bbeta *
            expectedValueFunction[nCapitalNextPeriod, nProductivity];

          if valueProvisional > valueHighSoFar {
            valueHighSoFar = valueProvisional;
            capitalChoice = vGridCapital[nCapitalNextPeriod];
            gridCapitalNextPeriod = nCapitalNextPeriod;
          } else {
            break;
          }

          mValueFunctionNew[nCapital, nProductivity] = valueHighSoFar;
          mPolicyFunction[nCapital, nProductivity] = capitalChoice;
        }
      }
    }

    maxDifference = max reduce abs(mValueFunctionNew - mValueFunction);
    mValueFunction = mValueFunctionNew;
    mValueFunctionNew = 0.0;

    iteration += 1;
    if (iteration % 10 == 0 || iteration == 1) {
      writeln("Iteration = ", iteration, ", Sup Diff = ", maxDifference);
    }
  }

  writeln("Iteration = ", iteration, ", Sup Diff = ", maxDifference, "\n");
  writeln("My check = ", mPolicyFunction[1000, 3], "\n");

  timer.stop();
  if printElapsed {
    writeln("Elapsed time is: ", timer.elapsed());
  }
}

/* Basic RBC model with full depreciation.
 *
 * Thomas Van Doren, Chapel Team
 * Seattle, July 7, 2014
 */

use Math;
use MatrixHelpers;
use Time;

// When true, print the elapsed time at the end.
config const printElapsed = true,
  gridCapital = 17820;

proc main() {
  // 0. Housekeeping
  var timer: Timer;
  timer.start();

  // 1. Calibration
  var aalpha = 1.0 / 3.0,  // Elasticity of output w.r.t. capital
    bbeta = 0.95;          // Discount factor

  // Productivity values
  var vProductivity = [0.9792, 0.9896, 1.0000, 1.0106, 1.0212];

  // Transition matrix
  // This creates a 1 dimensional array and then "reshapes" it into a 2
  // dimensional domain, 5x5 array.
  var mTransition = reshape([0.9727, 0.0273, 0.0000, 0.0000, 0.0000,
                             0.0041, 0.9806, 0.0153, 0.0000, 0.0000,
                             0.0000, 0.0082, 0.9837, 0.0082, 0.0000,
                             0.0000, 0.0000, 0.0153, 0.9806, 0.0041,
                             0.0000, 0.0000, 0.0000, 0.0273, 0.9727],
                            {1..5, 1..5});

  // 2. Steady State
  var capitalSteadyState = (aalpha * bbeta) ** (1 / (1 - aalpha)),
    outputSteadyState = capitalSteadyState ** aalpha,
    consumptionSteadyState = outputSteadyState - capitalSteadyState;

  writeln("Output = ", outputSteadyState,
          ", Capital = ", capitalSteadyState,
          ", Consumption = ", consumptionSteadyState, "\n");

  // We generate the grid of capital
  var nGridCapital = gridCapital,
    nGridProductivity = 5;
  var vGridCapital: [1..nGridCapital] real;
  forall (value, nCapital) in zip(vGridCapital, 0..) {
    value = 0.5*capitalSteadyState + 0.00001 * nCapital;
  }

  // 3. Required matrices and vectors.
  var gridProductivityDomain = {1..nGridCapital, 1..nGridProductivity};
  var mOutput, mValueFunction, mValueFunctionNew, mPolicyFunction,
    expectedValueFunction: [gridProductivityDomain] real;

  // 4. We pre-build output for each point in the grid.

  for (valueProductivity, nProductivity) in zip(vProductivity, 1..) {
    mOutput[1..nGridCapital, nProductivity] =
      valueProductivity * (vGridCapital ** aalpha);
  }

  // 5. Main iteration

  var maxDifference = 10.0,
    tolerance = 0.0000001,
    iteration = 0;

  var gridCapitalNextPeriod: int,
    valueHighSoFar, valueProvisional, consumption, capitalChoice: real;

  // Intermediate array, to be reused in dotProduct()/transpose() calls below.
  var transposeOut: [1..5, 1..5] real;

  while (maxDifference > tolerance) {
    // expectedValueFunction = mValueFunction * transpose(mTransition)
    transpose(transposeOut, mTransition);
    dotProduct(expectedValueFunction, mValueFunction, transposeOut);

    for nProductivity in 1..nGridProductivity {

      // We start from previous choice (monotonicity of policy function)
      gridCapitalNextPeriod = 1;

      for nCapital in 1..nGridCapital {
        valueHighSoFar = -100000.0;
        capitalChoice = vGridCapital[1];

        for nCapitalNextPeriod in gridCapitalNextPeriod..nGridCapital {
          consumption = mOutput[nCapital, nProductivity] - vGridCapital[nCapitalNextPeriod];
          valueProvisional = (1 - bbeta) * log(consumption) + bbeta *
            expectedValueFunction[nCapitalNextPeriod, nProductivity];

          if valueProvisional > valueHighSoFar {
            valueHighSoFar = valueProvisional;
            capitalChoice = vGridCapital[nCapitalNextPeriod];
            gridCapitalNextPeriod = nCapitalNextPeriod;
          } else {
            break;
          }

          mValueFunctionNew[nCapital, nProductivity] = valueHighSoFar;
          mPolicyFunction[nCapital, nProductivity] = capitalChoice;
        }
      }
    }

    maxDifference = max reduce abs(mValueFunctionNew - mValueFunction);
    mValueFunction = mValueFunctionNew;
    mValueFunctionNew = 0.0;

    iteration += 1;
    if (iteration % 10 == 0 || iteration == 1) {
      writeln("Iteration = ", iteration, ", Sup Diff = ", maxDifference);
    }
  }

  writeln("Iteration = ", iteration, ", Sup Diff = ", maxDifference, "\n");
  writeln("My check = ", mPolicyFunction[1000, 3], "\n");

  timer.stop();
  if printElapsed {
    writeln("Elapsed time is: ", timer.elapsed());
  }
}


example shows new keywords

example shows new keywords

/***********************************************************************
 * Chapel implementation of "99 bottles of beer"
 *
 * by Brad Chamberlain and Steve Deitz
 * 07/13/2006 in Knoxville airport while waiting for flight home from
 *            HPLS workshop
 * compiles and runs with chpl compiler version 1.12.0
 * for more information, contact: chapel_info@cray.com
 *
 *
 * Notes:
 * o as in all good parallel computations, boundary conditions
 *   constitute the vast bulk of complexity in this code (invite Brad to
 *   tell you about his zany boundary condition simplification scheme)
 * o uses type inference for variables, arguments
 * o relies on integer->string coercions
 * o uses named argument passing (for documentation purposes only)
 ***********************************************************************/

// allow executable command-line specification of number of bottles
// (e.g., ./a.out -snumBottles=999999)
config const numBottles = 99;
const numVerses = numBottles+1;

// a domain to describe the space of lyrics
var LyricsSpace: domain(1) = {1..numVerses};

// array of lyrics
var Lyrics: [LyricsSpace] string;

// parallel computation of lyrics array
[verse in LyricsSpace] Lyrics(verse) = computeLyric(verse);

// as in any good parallel language, I/O to stdout is serialized.
// (Note that I/O to a file could be parallelized using a parallel
// prefix computation on the verse strings' lengths with file seeking)
writeln(Lyrics);

// HELPER FUNCTIONS:

proc computeLyric(verseNum) {
  var bottleNum = numBottles - (verseNum - 1);
  var nextBottle = (bottleNum + numVerses - 1)%numVerses;
  return "\n" // disguise space used to separate elements in array I/O
    + describeBottles(bottleNum, startOfVerse=true) + " on the wall, "
    + describeBottles(bottleNum) + ".\n"
    + computeAction(bottleNum)
    + describeBottles(nextBottle) + " on the wall.\n";
}

proc describeBottles(bottleNum, startOfVerse:bool = false) {
  // NOTE: bool should not be necessary here (^^^^); working around bug
  var bottleDescription = if (bottleNum) then bottleNum:string
    else (if startOfVerse then "N"
            else "n")
           + "o more";
  return bottleDescription
    + " bottle" + (if (bottleNum == 1) then "" else "s")
    + " of beer";
}

proc computeAction(bottleNum) {
  return if (bottleNum == 0) then "Go to the store and buy some more, "
    else "Take one down and pass it around, ";
}

// Modules...
module M1 {
  var x = 10;

  var y = 13.0;
}

module M2 {
  use M1 except y;
  use M1 only y;
  proc main() {
    writeln("M2 -> M1 -> x " + x);
  }
}

// Classes, records, unions...
const PI: real = 3.14159;

record Point {
  var x, y: real;
}
var p: Point;
writeln("Distance from origin: " + sqrt(p.x ** 2 + p.y ** 2));
p = new Point(1.0, 2.0);
writeln("Distance from origin: " + sqrt(p.x ** 2 + p.y ** 2));

class Circle {
  var p: Point;
  var r: real;
}
var c = new Circle(r=2.0);
proc Circle.area()
  return PI * r ** 2;
writeln("Area of circle: " + c.area());

class Oval: Circle {
  var r2: real;
}
proc Oval.area()
  return PI * r * r2;

delete c;
c = nil;
c = new Oval(r=1.0, r2=2.0);
writeln("Area of oval: " + c.area());

// This is a valid decimal integer:
var x = 0000000000012;

union U {
  var i: int;
  var r: real;
}

// chapel ranges are awesome.
var r1 = 1..10,            // 1 2 3 4 5 6 7 8 9 10
  r2 = 10..1,              // no values in this range
  r3 = 1..10 by -1,        // 10 9 8 7 6 5 4 3 2 1
  r4 = 1..10 by 2,         // 1 3 5 7 9
  r5 = 1..10 by 2 align 0, // 2 4 6 8 10
  r6 = 1..10 by 2 align 2, // 2 4 6 8 10
  r7 = 1..10 # 3,          // 1 2 3
  r8 = 1..10 # -2,         // 9 10
  r9 = 1..100 # 10 by 2,   // 1 3 5 7 9
  ra = 1..100 by 2 # 10,   // 1 3 5 7 9 11 13 15 17 19
  rb = 1.. # 100 by 10;    // 1 11 21 31 41 51 61 71 81 91

// create a variable with default initialization
var myVarWithoutInit: real = noinit;
myVarWithoutInit = 1.0;

// Chapel has <~> operator for read and write I/O operations.
class IntPair {
  var x: int;
  var y: int;
  proc readWriteThis(f) {
    f <~> x <~> new ioLiteral(",") <~> y <~> new ioNewline();
  }
}
var ip = new IntPair(17,2);
write(ip);

var targetDom = {1..10},
  target: [targetDom] int;
coforall i in targetDom with (ref target) {
  target[i] = i ** 3;
}

var wideOpen = 0o777,
  mememe = 0o600,
  clique_y = 0O660,
  zeroOct = 0o0,
  minPosOct = 0O1;

private module M3 {
  private proc foo() {

  }

  private iter bar() {
    for i in 1..10 {
      yield i;
    }
  }

  private var x: int;

}
prototype module X {

  proc f() throws {
    throw new Error();
  }

  proc g() {
    try {
      f();
      try! f();
    } catch e {
      writeln("Caught ", e);
    }
  }

  proc int.add() { }

  g();

  override proc test() throws {
    var a = new borrowed IntPair();
    var b = new owned IntPair();
    var c = new shared IntPair();
    throw new unmanaged Error();
  }
}

/***********************************************************************
 * Chapel implementation of "99 bottles of beer"
 *
 * by Brad Chamberlain and Steve Deitz
 * 07/13/2006 in Knoxville airport while waiting for flight home from
 *            HPLS workshop
 * compiles and runs with chpl compiler version 1.12.0
 * for more information, contact: chapel_info@cray.com
 *
 *
 * Notes:
 * o as in all good parallel computations, boundary conditions
 *   constitute the vast bulk of complexity in this code (invite Brad to
 *   tell you about his zany boundary condition simplification scheme)
 * o uses type inference for variables, arguments
 * o relies on integer->string coercions
 * o uses named argument passing (for documentation purposes only)
 ***********************************************************************/

// allow executable command-line specification of number of bottles
// (e.g., ./a.out -snumBottles=999999)
config const numBottles = 99;
const numVerses = numBottles+1;

// a domain to describe the space of lyrics
var LyricsSpace: domain(1) = {1..numVerses};

// array of lyrics
var Lyrics: [LyricsSpace] string;

// parallel computation of lyrics array
[verse in LyricsSpace] Lyrics(verse) = computeLyric(verse);

// as in any good parallel language, I/O to stdout is serialized.
// (Note that I/O to a file could be parallelized using a parallel
// prefix computation on the verse strings' lengths with file seeking)
writeln(Lyrics);

// HELPER FUNCTIONS:

proc computeLyric(verseNum) {
  var bottleNum = numBottles - (verseNum - 1);
  var nextBottle = (bottleNum + numVerses - 1)%numVerses;
  return "\n" // disguise space used to separate elements in array I/O
    + describeBottles(bottleNum, startOfVerse=true) + " on the wall, "
    + describeBottles(bottleNum) + ".\n"
    + computeAction(bottleNum)
    + describeBottles(nextBottle) + " on the wall.\n";
}

proc describeBottles(bottleNum, startOfVerse:bool = false) {
  // NOTE: bool should not be necessary here (^^^^); working around bug
  var bottleDescription = if (bottleNum) then bottleNum:string
    else (if startOfVerse then "N"
            else "n")
           + "o more";
  return bottleDescription
    + " bottle" + (if (bottleNum == 1) then "" else "s")
    + " of beer";
}

proc computeAction(bottleNum) {
  return if (bottleNum == 0) then "Go to the store and buy some more, "
    else "Take one down and pass it around, ";
}

// Modules...
module M1 {
  var x = 10;

  var y = 13.0;
}

module M2 {
  use M1 except y;
  use M1 only y;
  proc main() {
    writeln("M2 -> M1 -> x " + x);
  }
}

// Classes, records, unions...
const PI: real = 3.14159;

record Point {
  var x, y: real;
}
var p: Point;
writeln("Distance from origin: " + sqrt(p.x ** 2 + p.y ** 2));
p = new Point(1.0, 2.0);
writeln("Distance from origin: " + sqrt(p.x ** 2 + p.y ** 2));

class Circle {
  var p: Point;
  var r: real;
}
var c = new Circle(r=2.0);
proc Circle.area()
  return PI * r ** 2;
writeln("Area of circle: " + c.area());

class Oval: Circle {
  var r2: real;
}
proc Oval.area()
  return PI * r * r2;

delete c;
c = nil;
c = new Oval(r=1.0, r2=2.0);
writeln("Area of oval: " + c.area());

// This is a valid decimal integer:
var x = 0000000000012;

union U {
  var i: int;
  var r: real;
}

// chapel ranges are awesome.
var r1 = 1..10,            // 1 2 3 4 5 6 7 8 9 10
  r2 = 10..1,              // no values in this range
  r3 = 1..10 by -1,        // 10 9 8 7 6 5 4 3 2 1
  r4 = 1..10 by 2,         // 1 3 5 7 9
  r5 = 1..10 by 2 align 0, // 2 4 6 8 10
  r6 = 1..10 by 2 align 2, // 2 4 6 8 10
  r7 = 1..10 # 3,          // 1 2 3
  r8 = 1..10 # -2,         // 9 10
  r9 = 1..100 # 10 by 2,   // 1 3 5 7 9
  ra = 1..100 by 2 # 10,   // 1 3 5 7 9 11 13 15 17 19
  rb = 1.. # 100 by 10;    // 1 11 21 31 41 51 61 71 81 91

// create a variable with default initialization
var myVarWithoutInit: real = noinit;
myVarWithoutInit = 1.0;

// Chapel has <~> operator for read and write I/O operations.
class IntPair {
  var x: int;
  var y: int;
  proc readWriteThis(f) {
    f <~> x <~> new ioLiteral(",") <~> y <~> new ioNewline();
  }
}
var ip = new IntPair(17,2);
write(ip);

var targetDom = {1..10},
  target: [targetDom] int;
coforall i in targetDom with (ref target) {
  target[i] = i ** 3;
}

var wideOpen = 0o777,
  mememe = 0o600,
  clique_y = 0O660,
  zeroOct = 0o0,
  minPosOct = 0O1;

private module M3 {
  private proc foo() {

  }

  private iter bar() {
    for i in 1..10 {
      yield i;
    }
  }

  private var x: int;

}
prototype module X {

  proc f() throws {
    throw new Error();
  }

  proc g() {
    try {
      f();
      try! f();
    } catch e {
      writeln("Caught ", e);
    }
  }

  proc int.add() { }

  g();
}


Added a trailing linefeed

Added a trailing linefeed

/*
 * Copyright 2004-2014 Cray Inc.
 * Other additional copyright holders may be indicated within.
 *
 * The entirety of this work is licensed under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// ChapelTaskID.chpl
//
pragma "no use ChapelStandard"
module ChapelTaskID {

  // Define a few operations over chpl_taskID_t
  inline proc =(ref a:chpl_taskID_t, b:chpl_taskID_t) {
    __primitive("=", a, b);
  }
  inline proc ==(a: chpl_taskID_t, b: chpl_taskID_t)
    return __primitive("==", a, b);
  inline proc _cast(type t, x: chpl_taskID_t) where t == int(64)
                                                    || t == uint(64)
    return __primitive("cast", t, x);

}


Add Thomas adlibs to GitIntro test.

Add Thomas adlibs to GitIntro test.

Used in presentation as demo/exercise.

/** Git Intro!
 *
 * The Chapel team's intro to git version control. The core team members should
 * update their name tuple in the array below.
 */

// To play Chapel adlibs, fill out your tuple with a programming language, a
// feeling, and a verb.
//
// name
//         programming language
//                 feeling
//                         verb
const TheTeam = [
  ("Ben", "", "", ""),
  ("Brad", "", "", ""),
  ("David", "", "", ""),
  ("Greg", "", "", ""),
  ("Kyle", "", "", ""),
  ("Lydia", "", "", ""),
  ("Michael", "", "", ""),
  ("Elliot", "", "", ""),
  ("Simon", "", "", ""),
  ("Sung", "", "", ""),
  ("Thomas", "Python", "gleeful", "<3"),
  ("Tim", "", "", ""),
  ("TMac", "", "", ""),
  ("Tom", "", "", ""),
  ("Vass", "", "", "")
];

// Prologue
writeln("Chapel Adlibs!");
writeln("--------------");
writeln();

// Print the adlibs!
for (name, lang, feeling, verb) in TheTeam {
  writef("My name is %s. I used to use %s for all my problems.\nNow, I use Chapel and feel %s! I %s Chapel.\n",
         name, lang, feeling, verb);
  writeln();
}

/** Git Intro!
 *
 * The Chapel team's intro to git version control. The core team members should
 * update their name tuple in the array below.
 */

// To play Chapel adlibs, fill out your tuple with a programming language, a
// feeling, and a verb.
//
// name
//         programming language
//                 feeling
//                         verb
const TheTeam = [
  ("Ben", "", "", ""),
  ("Brad", "", "", ""),
  ("David", "", "", ""),
  ("Greg", "", "", ""),
  ("Kyle", "", "", ""),
  ("Lydia", "", "", ""),
  ("Michael", "", "", ""),
  ("Elliot", "", "", ""),
  ("Simon", "", "", ""),
  ("Sung", "", "", ""),
  ("Thomas", "", "", ""),
  ("Tim", "", "", ""),
  ("TMac", "", "", ""),
  ("Tom", "", "", ""),
  ("Vass", "", "", "")
];

// Prologue
writeln("Chapel Adlibs!");
writeln("--------------");
writeln();

// Print the adlibs!
for (name, lang, feeling, verb) in TheTeam {
  writef("My name is %s. I used to use %s for all my problems.\nNow, I use Chapel and feel %s! I %s Chapel.\n",
         name, lang, feeling, verb);
  writeln();
}