Re-enabling --no-local compilations

Re-enabling --no-local compilations

This is a stab in the dark -- I didn't want to back out
more of Samuel's last checkin than I had to, and started
by looking at the changes to ChapelArray.chpl since that
is where the compiler was complaining for --no-local calls,
and seem to have found that commenting out the increment
of _count in _initialize() causes things to work again.
(Fingers crossed).

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

var privatizeLock$: sync int;

def _supportsPrivatization(value) param
  return _privatization & value.supportsPrivatization();

def _newArrayDomainSharedCode(param isArray: bool, value) {
  if _supportsPrivatization(value) {
    privatizeLock$.writeEF(true);
    var n = __primitive("chpl_numPrivateClasses");
    for loc in Locales {
      if loc != here {
        on loc {
          var mine = value.privatize1();
          __primitive("chpl_setPrivateClass", mine);
          mine.privatize2(n);
        }
      } else {
        __primitive("chpl_setPrivateClass", value);
        value.privatize2(n);
      }
    }
    privatizeLock$.readFE();
    if isArray then
      return new _array(n, value);
    else
      return new _domain(n, value);
  } else {
    if isArray then
      return new _array(value, value);
    else
      return new _domain(value, value);
  }
}

def _newArray(value) {
  return _newArrayDomainSharedCode(true, value);
}

def _newDomain(value) {
  return _newArrayDomainSharedCode(false, value);
}

def _getDomain(value) {
  if _supportsPrivatization(value) {
    return new _domain(value.pid, value);
  } else {
    return new _domain(value, value);
  }
}

//
// Support for domain types
//
pragma "has runtime type"
def chpl__buildDomainRuntimeType(dist, param rank: int, type idxType = int(32),
                       param stridable: bool = false) type
  return _newDomain(dist.newArithmeticDomain(rank, idxType, stridable));

pragma "has runtime type"
def chpl__buildDomainRuntimeType(dist, type idxType) type
 where !__primitive("isEnumType", idxType) && idxType != opaque && idxType != _OpaqueIndex
  return _newDomain(dist.newAssociativeDomain(idxType));

pragma "has runtime type"
def chpl__buildDomainRuntimeType(dist, type idxType) type
 where __primitive("isEnumType", idxType)
  return _newDomain(dist.newEnumeratedDomain(idxType));

pragma "has runtime type"
def chpl__buildDomainRuntimeType(dist, type idxType) type
 where idxType == _OpaqueIndex
  return _newDomain(dist.newOpaqueDomain(idxType));

// This function has no 'has runtime type' pragma since the idxType of
// opaque domains is _OpaqueIndex, not opaque.  This function is
// essentially a wrapper around the function that actually builds up
// the runtime type.
def chpl__buildDomainRuntimeType(dist, type idxType) type
 where idxType == opaque
  return chpl__buildDomainRuntimeType(dist, _OpaqueIndex);

pragma "has runtime type"
def chpl__buildSparseDomainRuntimeType(dist, dom: domain) type
  return _newDomain(dist.newSparseDomain(dom.rank, dom._value.idxType, dom));

def chpl__convertValueToRuntimeType(dom: domain) type
 where dom._value:BaseArithmeticDomain
  return chpl__buildDomainRuntimeType(dom._value.dist, dom._value.rank,
                            dom._value.idxType, dom._value.stridable);

def chpl__convertValueToRuntimeType(dom: domain) type
 where dom._value:BaseSparseDomain
  return chpl__buildSparseDomainRuntimeType(dom._value.dist, dom._value.parentDom);

def chpl__convertValueToRuntimeType(dom: domain) type
where !dom._value:BaseArithmeticDomain && !dom._value:BaseSparseDomain
  return chpl__buildDomainRuntimeType(dom._value.dist, dom._value.idxType);

//
// Support for array types
//
pragma "has runtime type"
def chpl__buildArrayRuntimeType(dom: domain, type eltType) type
  return dom.buildArray(eltType);

def chpl__convertValueToRuntimeType(arr: []) type
  return chpl__buildArrayRuntimeType(arr.domain, arr.eltType);

//
// Support for subdomain types
//
// Note the domain of a subdomain is not yet part of the runtime type
//
def chpl__buildSubDomainType(dom: domain) type
  return chpl__convertValueToRuntimeType(dom);

//
// Support for domain expressions, e.g., [1..3, 1..3]
//
def chpl__buildDomainExpr(x: domain)
  return x;

def chpl__buildDomainExpr(ranges: range(?) ...?rank) {
  for param i in 2..rank {
    if ranges(1).eltType != ranges(i).eltType then
      compilerError("domain has mixed dimensional type");
    if ranges(i).boundedType != BoundedRangeType.bounded then
      compilerError("domain has dimension of unbounded range");
  }
  var d: domain(rank, ranges(1).eltType, chpl__anyStridable(ranges));
  d.setIndices(ranges);
  return d;
}

//
// Support for index types
//
def chpl__buildIndexType(param rank: int, type idxType) type where rank == 1 {
  var x: idxType;
  return x;
}

def chpl__buildIndexType(param rank: int, type idxType) type where rank > 1 {
  var x: rank*idxType;
  return x;
}

def chpl__buildIndexType(param rank: int) type
  return chpl__buildIndexType(rank, int);

def chpl__buildIndexType(d: domain) type
  return chpl__buildIndexType(d.rank, d._value.idxType);

def chpl__buildIndexType(type idxType) type where idxType == opaque
  return _OpaqueIndex;

def isArithmeticDomain(d: domain) param {
  def isArithmeticDomainClass(dc: BaseArithmeticDomain) param return true;
  def isArithmeticDomainClass(dc) param return false;
  return isArithmeticDomainClass(d._value);
}

def isAssociativeDomain(d: domain) param {
  def isAssociativeDomainClass(dc: BaseAssociativeDomain) param return true;
  def isAssociativeDomainClass(dc) param return false;
  return isAssociativeDomainClass(d._value);
}

def isEnumDomain(d: domain) param {
  def isEnumDomainClass(dc: BaseEnumDomain) param return true;
  def isEnumDomainClass(dc) param return false;
  return isEnumDomainClass(d._value);
}

def isOpaqueDomain(d: domain) param {
  def isOpaqueDomainClass(dc: BaseOpaqueDomain) param return true;
  def isOpaqueDomainClass(dc) param return false;
  return isOpaqueDomainClass(d._value);
}

def isSparseDomain(d: domain) param {
  def isSparseDomainClass(dc: BaseSparseDomain) param return true;
  def isSparseDomainClass(dc) param return false;
  return isSparseDomainClass(d._value);
}

//
// Domain wrapper record
//
pragma "domain"
pragma "has runtime type"
record _domain {
  var _valueField;
  var _valueTypeField; // stores type of privatized domains
  var _promotionType: index(rank, _value.idxType);

  def initialize() {
    //    _valueField._count += 1;
  }

  def _value {
    if _supportsPrivatization(_valueTypeField) {
      var tc = _valueTypeField;
      var id = _valueField;
      var pc = __primitive("chpl_getPrivateClass", tc, id);
      return pc;
    } else {
      return _valueField;
    }
  }

  def ~_domain () {
    _value.destroyDom();
  }

  def dist return _value.dist;

  def rank param {
    if isArithmeticDomain(this) || isSparseDomain(this) then
      return _value.rank;
    else
      return 1;
  }

  pragma "inline"
  def these() {
    return _value.these();
  }

  def this(ranges: range(?) ...rank)
    return _newDomain(_value.slice(chpl__anyStridable(ranges), ranges));

  def this(args ...rank) where _validRankChangeArgs(args, _value.idxType) {
    var ranges = _getRankChangeRanges(args);
    param rank = ranges.size, stridable = chpl__anyStridable(ranges);
    return _newDomain(_value.rankChange(rank, stridable, args));
  }

  def dim(d : int) return _value.dim(d);

  def dimIter(param d, ind) {
    for i in _value.dimIter(d, ind) do yield i;
  }

  def buildArray(type eltType) {
    var x = _value.buildArray(eltType);
    var cnt = _value._count; // lock
    _value._arrs.append(x);
    _value._count = cnt + 1; // unlock
    return _newArray(x);
  }

  def clear() {
    _value.clear();
  }

  def create() {
    if _value.idxType != _OpaqueIndex then
      compilerError("domain.create() only applies to opaque domains");
    return _value.create();
  }

  def add(i) {
    _value.add(i);
  }

  def remove(i) {
    _value.remove(i);
  }

  def numIndices return _value.numIndices;
  def low return _value.low;
  def high return _value.high;

  def member(i) return _value.member(i);
  def order(i) return _value.order(i);
  def position(i) return _value.position(i);

  def expand(i: _value.idxType ...rank) return expand(i);
  def expand(i: rank*_value.idxType) return _newDomain(_value.expand(i));
  def expand(i: _value.idxType) where rank > 1 return _newDomain(_value.expand(i));

  def exterior(i: _value.idxType ...rank) return exterior(i);
  def exterior(i: rank*_value.idxType) return _newDomain(_value.exterior(i));

  def interior(i: _value.idxType ...rank) return interior(i);
  def interior(i: rank*_value.idxType) return _newDomain(_value.interior(i));

  def translate(i: _value.idxType ...rank) return translate(i);
  def translate(i: rank*_value.idxType) return _newDomain(_value.translate(i));

  def chpl__unTranslate(i: _value.idxType ...rank) return chpl__unTranslate(i);
  def chpl__unTranslate(i: rank*_value.idxType) return _newDomain(_value.chpl__unTranslate(i));

  def subBlocks {
    for d in _value.subBlocks do
      yield d;
  }

  def setIndices(x) {
    _value.setIndices(x);
  }

  def getIndices()
    return _value.getIndices();

  def writeThis(f: Writer) {
    f.write(_value);
  }

  // associative array interface

  def sorted() {
    for i in _value.sorted() {
      yield i;
    }
  }
}

def +(d: domain, i: index(d)) {
  return d.translate(i);
}

def +(i, d: domain) where i: index(d) {
  return d.translate(i);
}

def -(d: domain, i: index(d)) {
  return d.chpl__unTranslate(i);
}

//
// Array wrapper record
//
pragma "array"
pragma "has runtime type"
record _array {
  var _valueField;
  var _valueTypeField; // stores type of privatized arrays
  var _promotionType: _value.eltType;

  def _value {
    if _supportsPrivatization(_valueTypeField) {
      var tc = _valueTypeField;
      var id = _valueField;
      var pc = __primitive("chpl_getPrivateClass", tc, id);
      return pc;
    } else {
      return _valueField;
    }
  }

  def ~_array() {
    delete _value;
  }

  def eltType type return _value.eltType;
  def _dom return _getDomain(_value.dom);
  def rank param return this.domain.rank;

  pragma "inline"
  def this(i: rank*_value.idxType) var where rank > 1
    return _value(i);

  pragma "inline"
  def this(i: _value.idxType ...rank) var where rank > 1
    return _value(i);

  pragma "inline"
  def this(i: _value.idxType) var where rank == 1
    return _value(i);

  //
  // requires dense domain implementation that returns a tuple of
  // ranges via the getIndices() method; domain indexing is difficult
  // in the domain case because it has to be implemented on a
  // domain-by-domain basis; this is not terribly difficult in the
  // dense case because we can represent a domain by a tuple of
  // ranges, but in the sparse case, is there a general
  // representation?
  //
  pragma "valid var"
  def this(d: domain) var where d.rank == rank
    return this((...d.getIndices()));

  pragma "valid var"
  def this(ranges: range(?) ...rank) var {
    if boundsChecking then
      _value.checkSlice(ranges);
    return _newArray(_value.slice(_dom((...ranges))._value));
  }

  pragma "valid var"
  def this(args ...rank) var where _validRankChangeArgs(args, _value.idxType) {
    if boundsChecking then
      _value.checkRankChange(args);
    var ranges = _getRankChangeRanges(args);
    param rank = ranges.size, stridable = chpl__anyStridable(ranges);
    return _newArray(_value.rankChange(rank, stridable, args));
  }

  pragma "inline"
  def these() var {
    return _value.these();
  }

  def numElements return _dom.numIndices; // assume dom name

  def reindex(d: domain) where rank == 1 {
    var x = _value.reindex(d._value);
    return _newArray(x);
  }

  def reindex(d: domain) where rank != 1 {
    var x = _value.reindex(d._value);
    return _newArray(x);
  }

  def writeThis(f: Writer) {
    f.write(_value);
  }

  // sparse array interface

  def IRV var {
    return _value.IRV;
  }

  // associative array interface

  def sorted() {
    for i in _value.sorted() {
      yield i;
    }
  }
}

//
// Helper functions
//

// computes || reduction over stridable of ranges
def chpl__anyStridable(ranges, param d: int = 1) param {
  for param i in 1..ranges.size do
    if ranges(i).stridable then
      return true;
  return false;
}

// given a tuple args, returns true if the tuple contains only
// integers and ranges; that is, it is a valid argument list for rank
// change
def _validRankChangeArgs(args, type idxType) param {
  def _validRankChangeArg(type idxType, r: range(?)) param return true;
  def _validRankChangeArg(type idxType, i: idxType) param return true;
  def _validRankChangeArg(type idxType, x) param return false;

  def help(param dim: int) param {
    if !_validRankChangeArg(idxType, args(dim)) then
      return false;
    else if dim < args.size then
      return help(dim+1);
    else
      return true;
  }

  return help(1);
}

def _getRankChangeRanges(args) {
  def isRange(r: range(?)) param return 1;
  def isRange(r) param return 0;
  def _tupleize(x) {
    var y: 1*x.type;
    y(1) = x;
    return y;
  }
  def collectRanges(param dim: int) {
    if dim > args.size then
      compilerError("domain slice requires a range in at least one dimension");
    if isRange(args(dim)) then
      return collectRanges(dim+1, _tupleize(args(dim)));
    else
      return collectRanges(dim+1);
  }
  def collectRanges(param dim: int, x: _tuple) {
    if dim > args.size {
      return x;
    } else if dim < args.size {
      if isRange(args(dim)) then
        return collectRanges(dim+1, ((...x), args(dim)));
      else
        return collectRanges(dim+1, x);
    } else {
      if isRange(args(dim)) then
        return ((...x), args(dim));
      else
        return x;
    }
  }
  return collectRanges(1);
}

//
// Support for += and -= over domains
//
def chpl__isDomain(x: domain) param return true;
def chpl__isDomain(x) param return false;

//
// Assignment of domains and arrays
//
def =(a: domain, b: domain) {
  for e in a._value._arrs do
    e.reallocate(b);
  a._value.setIndices(b._value.getIndices());
  return a;
}

def =(a: domain, b: _tuple) {
  for ind in 1..b.size {
    a.add(b(ind));
  }
  return a;
}

def =(d: domain, r: range(?)) {
  d = [r];
  return d;
}

def =(a: domain, b) {  // b is iteratable
  a._value.clearForIteratableAssign();
  for ind in b {
    a.add(ind);
  }
  return a;
}

def _copy(a: domain) {
  var b: a.type;
  b.setIndices(a.getIndices());
  return b;
}

pragma "inline" def =(a: [], b) {
  for (i,bb) in (a._dom,b) do
    a(i) = bb;
  return a;
}

def =(a: [], b: _tuple) {
  a._value.tupleInit(b);
  return a;
}

def _desync(type t) where t: _syncvar || t: _singlevar {
  var x: t;
  return x.value;
}

def _desync(type t) where !(t: _syncvar|| t: _singlevar) {
  var x: t;
  return x;
}

def =(a: [], b: _desync(a.eltType)) {
  for i in a._dom do
    a(i) = b;
  return a;
}

def _copy(a: []) {
  var b : [a._dom] a.eltType;
  b = a;
  return b;
}

def by(a: domain, b) {
  var x = a._value.strideBy(b);
  return _newDomain(x);
}

//
// index for all opaque domains
//
class _OpaqueIndex { }

//
// Swap operators for arrays and domains
//
pragma "inline" def _chpl_swap(x: [], y: []) {
  for (i,j) in (x.domain, y.domain) do
    x(i) <=> y(j);
}

pragma "inline" def _chpl_swap(x: domain, y: domain) {
  const t = y;
  y = x;
  x = t;
}

//
// reshape function
//
def reshape(A: [], D: domain) {
  var B: [D] A.eltType;
  for (i,a) in (D,A) do
    B(i) = a;
  return B;
}

def _callSupportsAlignedFollower(A) param where A: BaseArray
  return A.supportsAlignedFollower();

def _callSupportsAlignedFollower(A) param where !(A: BaseArray)
  return false;

def _callSupportsAlignedFollower() param
  return false;

//
// module support for iterators
//
enum iterator {leader, follower};

def iteratorIndex(ic: _iteratorClass) {
  ic.advance();
  return ic.getValue();
}

pragma "expand tuples with values"
def iteratorIndex(t: _tuple) {
  pragma "expand tuples with values"
  def iteratorIndexHelp(t: _tuple, param dim: int) {
    if dim == t.size-1 then
      return _build_tuple_always_allow_ref(iteratorIndex(t(dim)),
                                           iteratorIndex(t(dim+1)));
    else
      return _build_tuple_always_allow_ref(iteratorIndex(t(dim)),
                                           (...iteratorIndexHelp(t, dim+1)));
  }

  return iteratorIndexHelp(t, 1);
}

def iteratorIndexType(x) type {
  return iteratorIndex(x).type;
}

def _iteratorClass.writeThis(f: Writer) {
  var first: bool = true;
  for e in this {
    if !first then
      f.write(" ");
    else
      first = false;
    f.write(e);
  }
}

def =(ic: _iteratorClass, xs) {
  for (e, x) in (ic, xs) do
    e = x;
  return ic;
}

def =(ic: _iteratorClass, x: iteratorIndexType(ic)) {
  for e in ic do
    e = x;
  return ic;
}

def _copy(ic: _iteratorClass) {
  return _ic_copy_help(_ic_copy_recursive(ic));

  def _ic_copy_recursive(ic) {
    for e in ic do
      yield _copy(e);
  }

  def _ic_copy_help(ic) {
    var i = 1, size = 4;
    var D = [1..size];

    // note that _getIterator is called in order to copy the iterator
    // class since for arrays we need to iterate once to get the
    // element type (at least for now); this also means that if this
    // iterator has side effects, we will see them; a better way to
    // handle this may be to get the static type (not initialize the
    // array) and use a primitive to set the array's element; that may
    // also handle skyline arrays
    var A: [D] iteratorIndexType(_getIterator(ic));

    for e in ic {
      if i > size {
        size = size * 2;
        D = [1..size];
      }
      A(i) = e;
      i = i + 1;
    }
    D = [1..i-1];
    return A;
  }
}

pragma "inline" pragma "iterator class copy"
def _getIterator(ic: _iteratorClass)
  return ic;

pragma "inline" pragma "ref" def _getIterator(x)
  return x.these();

pragma "inline" def _getIterator(x: _tuple) {
  pragma "inline" def _getIteratorHelp(x: _tuple, param dim: int) {
    if dim == x.size-1 then
      return (_getIterator(x(dim)), _getIterator(x(dim+1)));
    else
      return (_getIterator(x(dim)), (..._getIteratorHelp(x, dim+1)));
  }
  return _getIteratorHelp(x, 1);
}

def _getIterator(type t) {
  compilerError("cannot iterate over a type");
}

pragma "inline"
def _toLeader(iterator: _iteratorClass)
  return __primitive("to leader", iterator);

pragma "inline"
def _toLeader(x: _tuple)
  return _toLeader(x(1));

pragma "inline"
def _toLeader(x)
  return _toLeader(x.these());

pragma "inline"
def _toFollower(iterator: _iteratorClass, leaderIndex)
  return __primitive("to follower", iterator, leaderIndex);

//
// If aligned is passed as an argument (true from alignment version of
// _toFollower on tuple) then grab the aligned version of the array's
// iterator if the array supports aligned followers
//
pragma "inline"
def _toFollower(iterator: _iteratorClass, leaderIndex, param aligned: bool) {
  return __primitive("to follower", iterator, leaderIndex, aligned);
}

pragma "inline"
def _toFollower(x: _tuple, leaderIndex) {
  pragma "inline" def _toFollowerHelp(x: _tuple, leaderIndex, param dim: int) {
    if dim == x.size-1 then
      return (_toFollower(x(dim), leaderIndex),
              _toFollower(x(dim+1), leaderIndex));
    else
      return (_toFollower(x(dim), leaderIndex),
              (..._toFollowerHelp(x, leaderIndex, dim+1)));
  }
  return _toFollowerHelp(x, leaderIndex, 1);
}

//
// The alignment version uses a compiler analysis to pass a tuple of
// types according to whether the arrays in the tuple x have the same
// distribution as the leader or not.  If they do, the component type
// is passed as Distribution, otherwise as BaseArray.
//
pragma "inline"
def _toFollower(x: _tuple, leaderIndex, type alignment) {
  pragma "inline" def _toFollowerHelp(x: _tuple, leaderIndex, param dim: int) {
    if dim == x.size-1 {
      type tdim = alignment(dim);
      type tdimp1 = alignment(dim+1);
      if tdim == Distribution & tdimp1 == Distribution {
        return (_toFollower(x(dim), leaderIndex, true),
                _toFollower(x(dim+1), leaderIndex, true));
      } else if tdim == Distribution {
        return (_toFollower(x(dim), leaderIndex, true),
                _toFollower(x(dim+1), leaderIndex));
      } else if tdimp1 == Distribution {
        return (_toFollower(x(dim), leaderIndex),
                _toFollower(x(dim+1), leaderIndex, true));
      } else {
        return (_toFollower(x(dim), leaderIndex),
                _toFollower(x(dim+1), leaderIndex));
      }
    } else {
      type tdim = alignment(dim);
      if tdim == Distribution {
        return (_toFollower(x(dim), leaderIndex, true),
                (..._toFollowerHelp(x, leaderIndex, dim+1)));
      } else {
        return (_toFollower(x(dim), leaderIndex),
                (..._toFollowerHelp(x, leaderIndex, dim+1)));
      }
    }
  }
  return _toFollowerHelp(x, leaderIndex, 1);
}

// sjd: is this ever called?
pragma "inline"
def _toFollower(x, leaderIndex)
  return _toFollower(x.these(), leaderIndex);

var privatizeLock$: sync int;

def _supportsPrivatization(value) param
  return _privatization & value.supportsPrivatization();

def _newArrayDomainSharedCode(param isArray: bool, value) {
  if _supportsPrivatization(value) {
    privatizeLock$.writeEF(true);
    var n = __primitive("chpl_numPrivateClasses");
    for loc in Locales {
      if loc != here {
        on loc {
          var mine = value.privatize1();
          __primitive("chpl_setPrivateClass", mine);
          mine.privatize2(n);
        }
      } else {
        __primitive("chpl_setPrivateClass", value);
        value.privatize2(n);
      }
    }
    privatizeLock$.readFE();
    if isArray then
      return new _array(n, value);
    else
      return new _domain(n, value);
  } else {
    if isArray then
      return new _array(value, value);
    else
      return new _domain(value, value);
  }
}

def _newArray(value) {
  return _newArrayDomainSharedCode(true, value);
}

def _newDomain(value) {
  return _newArrayDomainSharedCode(false, value);
}

def _getDomain(value) {
  if _supportsPrivatization(value) {
    return new _domain(value.pid, value);
  } else {
    return new _domain(value, value);
  }
}

//
// Support for domain types
//
pragma "has runtime type"
def chpl__buildDomainRuntimeType(dist, param rank: int, type idxType = int(32),
                       param stridable: bool = false) type
  return _newDomain(dist.newArithmeticDomain(rank, idxType, stridable));

pragma "has runtime type"
def chpl__buildDomainRuntimeType(dist, type idxType) type
 where !__primitive("isEnumType", idxType) && idxType != opaque && idxType != _OpaqueIndex
  return _newDomain(dist.newAssociativeDomain(idxType));

pragma "has runtime type"
def chpl__buildDomainRuntimeType(dist, type idxType) type
 where __primitive("isEnumType", idxType)
  return _newDomain(dist.newEnumeratedDomain(idxType));

pragma "has runtime type"
def chpl__buildDomainRuntimeType(dist, type idxType) type
 where idxType == _OpaqueIndex
  return _newDomain(dist.newOpaqueDomain(idxType));

// This function has no 'has runtime type' pragma since the idxType of
// opaque domains is _OpaqueIndex, not opaque.  This function is
// essentially a wrapper around the function that actually builds up
// the runtime type.
def chpl__buildDomainRuntimeType(dist, type idxType) type
 where idxType == opaque
  return chpl__buildDomainRuntimeType(dist, _OpaqueIndex);

pragma "has runtime type"
def chpl__buildSparseDomainRuntimeType(dist, dom: domain) type
  return _newDomain(dist.newSparseDomain(dom.rank, dom._value.idxType, dom));

def chpl__convertValueToRuntimeType(dom: domain) type
 where dom._value:BaseArithmeticDomain
  return chpl__buildDomainRuntimeType(dom._value.dist, dom._value.rank,
                            dom._value.idxType, dom._value.stridable);

def chpl__convertValueToRuntimeType(dom: domain) type
 where dom._value:BaseSparseDomain
  return chpl__buildSparseDomainRuntimeType(dom._value.dist, dom._value.parentDom);

def chpl__convertValueToRuntimeType(dom: domain) type
where !dom._value:BaseArithmeticDomain && !dom._value:BaseSparseDomain
  return chpl__buildDomainRuntimeType(dom._value.dist, dom._value.idxType);

//
// Support for array types
//
pragma "has runtime type"
def chpl__buildArrayRuntimeType(dom: domain, type eltType) type
  return dom.buildArray(eltType);

def chpl__convertValueToRuntimeType(arr: []) type
  return chpl__buildArrayRuntimeType(arr.domain, arr.eltType);

//
// Support for subdomain types
//
// Note the domain of a subdomain is not yet part of the runtime type
//
def chpl__buildSubDomainType(dom: domain) type
  return chpl__convertValueToRuntimeType(dom);

//
// Support for domain expressions, e.g., [1..3, 1..3]
//
def chpl__buildDomainExpr(x: domain)
  return x;

def chpl__buildDomainExpr(ranges: range(?) ...?rank) {
  for param i in 2..rank {
    if ranges(1).eltType != ranges(i).eltType then
      compilerError("domain has mixed dimensional type");
    if ranges(i).boundedType != BoundedRangeType.bounded then
      compilerError("domain has dimension of unbounded range");
  }
  var d: domain(rank, ranges(1).eltType, chpl__anyStridable(ranges));
  d.setIndices(ranges);
  return d;
}

//
// Support for index types
//
def chpl__buildIndexType(param rank: int, type idxType) type where rank == 1 {
  var x: idxType;
  return x;
}

def chpl__buildIndexType(param rank: int, type idxType) type where rank > 1 {
  var x: rank*idxType;
  return x;
}

def chpl__buildIndexType(param rank: int) type
  return chpl__buildIndexType(rank, int);

def chpl__buildIndexType(d: domain) type
  return chpl__buildIndexType(d.rank, d._value.idxType);

def chpl__buildIndexType(type idxType) type where idxType == opaque
  return _OpaqueIndex;

def isArithmeticDomain(d: domain) param {
  def isArithmeticDomainClass(dc: BaseArithmeticDomain) param return true;
  def isArithmeticDomainClass(dc) param return false;
  return isArithmeticDomainClass(d._value);
}

def isAssociativeDomain(d: domain) param {
  def isAssociativeDomainClass(dc: BaseAssociativeDomain) param return true;
  def isAssociativeDomainClass(dc) param return false;
  return isAssociativeDomainClass(d._value);
}

def isEnumDomain(d: domain) param {
  def isEnumDomainClass(dc: BaseEnumDomain) param return true;
  def isEnumDomainClass(dc) param return false;
  return isEnumDomainClass(d._value);
}

def isOpaqueDomain(d: domain) param {
  def isOpaqueDomainClass(dc: BaseOpaqueDomain) param return true;
  def isOpaqueDomainClass(dc) param return false;
  return isOpaqueDomainClass(d._value);
}

def isSparseDomain(d: domain) param {
  def isSparseDomainClass(dc: BaseSparseDomain) param return true;
  def isSparseDomainClass(dc) param return false;
  return isSparseDomainClass(d._value);
}

//
// Domain wrapper record
//
pragma "domain"
pragma "has runtime type"
record _domain {
  var _valueField;
  var _valueTypeField; // stores type of privatized domains
  var _promotionType: index(rank, _value.idxType);

  def initialize() {
    _valueField._count += 1;
  }

  def _value {
    if _supportsPrivatization(_valueTypeField) {
      var tc = _valueTypeField;
      var id = _valueField;
      var pc = __primitive("chpl_getPrivateClass", tc, id);
      return pc;
    } else {
      return _valueField;
    }
  }

  def ~_domain () {
    _value.destroyDom();
  }

  def dist return _value.dist;

  def rank param {
    if isArithmeticDomain(this) || isSparseDomain(this) then
      return _value.rank;
    else
      return 1;
  }

  pragma "inline"
  def these() {
    return _value.these();
  }

  def this(ranges: range(?) ...rank)
    return _newDomain(_value.slice(chpl__anyStridable(ranges), ranges));

  def this(args ...rank) where _validRankChangeArgs(args, _value.idxType) {
    var ranges = _getRankChangeRanges(args);
    param rank = ranges.size, stridable = chpl__anyStridable(ranges);
    return _newDomain(_value.rankChange(rank, stridable, args));
  }

  def dim(d : int) return _value.dim(d);

  def dimIter(param d, ind) {
    for i in _value.dimIter(d, ind) do yield i;
  }

  def buildArray(type eltType) {
    var x = _value.buildArray(eltType);
    var cnt = _value._count; // lock
    _value._arrs.append(x);
    _value._count = cnt + 1; // unlock
    return _newArray(x);
  }

  def clear() {
    _value.clear();
  }

  def create() {
    if _value.idxType != _OpaqueIndex then
      compilerError("domain.create() only applies to opaque domains");
    return _value.create();
  }

  def add(i) {
    _value.add(i);
  }

  def remove(i) {
    _value.remove(i);
  }

  def numIndices return _value.numIndices;
  def low return _value.low;
  def high return _value.high;

  def member(i) return _value.member(i);
  def order(i) return _value.order(i);
  def position(i) return _value.position(i);

  def expand(i: _value.idxType ...rank) return expand(i);
  def expand(i: rank*_value.idxType) return _newDomain(_value.expand(i));
  def expand(i: _value.idxType) where rank > 1 return _newDomain(_value.expand(i));

  def exterior(i: _value.idxType ...rank) return exterior(i);
  def exterior(i: rank*_value.idxType) return _newDomain(_value.exterior(i));

  def interior(i: _value.idxType ...rank) return interior(i);
  def interior(i: rank*_value.idxType) return _newDomain(_value.interior(i));

  def translate(i: _value.idxType ...rank) return translate(i);
  def translate(i: rank*_value.idxType) return _newDomain(_value.translate(i));

  def chpl__unTranslate(i: _value.idxType ...rank) return chpl__unTranslate(i);
  def chpl__unTranslate(i: rank*_value.idxType) return _newDomain(_value.chpl__unTranslate(i));

  def subBlocks {
    for d in _value.subBlocks do
      yield d;
  }

  def setIndices(x) {
    _value.setIndices(x);
  }

  def getIndices()
    return _value.getIndices();

  def writeThis(f: Writer) {
    f.write(_value);
  }

  // associative array interface

  def sorted() {
    for i in _value.sorted() {
      yield i;
    }
  }
}

def +(d: domain, i: index(d)) {
  return d.translate(i);
}

def +(i, d: domain) where i: index(d) {
  return d.translate(i);
}

def -(d: domain, i: index(d)) {
  return d.chpl__unTranslate(i);
}

//
// Array wrapper record
//
pragma "array"
pragma "has runtime type"
record _array {
  var _valueField;
  var _valueTypeField; // stores type of privatized arrays
  var _promotionType: _value.eltType;

  def _value {
    if _supportsPrivatization(_valueTypeField) {
      var tc = _valueTypeField;
      var id = _valueField;
      var pc = __primitive("chpl_getPrivateClass", tc, id);
      return pc;
    } else {
      return _valueField;
    }
  }

  def ~_array() {
    delete _value;
  }

  def eltType type return _value.eltType;
  def _dom return _getDomain(_value.dom);
  def rank param return this.domain.rank;

  pragma "inline"
  def this(i: rank*_value.idxType) var where rank > 1
    return _value(i);

  pragma "inline"
  def this(i: _value.idxType ...rank) var where rank > 1
    return _value(i);

  pragma "inline"
  def this(i: _value.idxType) var where rank == 1
    return _value(i);

  //
  // requires dense domain implementation that returns a tuple of
  // ranges via the getIndices() method; domain indexing is difficult
  // in the domain case because it has to be implemented on a
  // domain-by-domain basis; this is not terribly difficult in the
  // dense case because we can represent a domain by a tuple of
  // ranges, but in the sparse case, is there a general
  // representation?
  //
  pragma "valid var"
  def this(d: domain) var where d.rank == rank
    return this((...d.getIndices()));

  pragma "valid var"
  def this(ranges: range(?) ...rank) var {
    if boundsChecking then
      _value.checkSlice(ranges);
    return _newArray(_value.slice(_dom((...ranges))._value));
  }

  pragma "valid var"
  def this(args ...rank) var where _validRankChangeArgs(args, _value.idxType) {
    if boundsChecking then
      _value.checkRankChange(args);
    var ranges = _getRankChangeRanges(args);
    param rank = ranges.size, stridable = chpl__anyStridable(ranges);
    return _newArray(_value.rankChange(rank, stridable, args));
  }

  pragma "inline"
  def these() var {
    return _value.these();
  }

  def numElements return _dom.numIndices; // assume dom name

  def reindex(d: domain) where rank == 1 {
    var x = _value.reindex(d._value);
    return _newArray(x);
  }

  def reindex(d: domain) where rank != 1 {
    var x = _value.reindex(d._value);
    return _newArray(x);
  }

  def writeThis(f: Writer) {
    f.write(_value);
  }

  // sparse array interface

  def IRV var {
    return _value.IRV;
  }

  // associative array interface

  def sorted() {
    for i in _value.sorted() {
      yield i;
    }
  }
}

//
// Helper functions
//

// computes || reduction over stridable of ranges
def chpl__anyStridable(ranges, param d: int = 1) param {
  for param i in 1..ranges.size do
    if ranges(i).stridable then
      return true;
  return false;
}

// given a tuple args, returns true if the tuple contains only
// integers and ranges; that is, it is a valid argument list for rank
// change
def _validRankChangeArgs(args, type idxType) param {
  def _validRankChangeArg(type idxType, r: range(?)) param return true;
  def _validRankChangeArg(type idxType, i: idxType) param return true;
  def _validRankChangeArg(type idxType, x) param return false;

  def help(param dim: int) param {
    if !_validRankChangeArg(idxType, args(dim)) then
      return false;
    else if dim < args.size then
      return help(dim+1);
    else
      return true;
  }

  return help(1);
}

def _getRankChangeRanges(args) {
  def isRange(r: range(?)) param return 1;
  def isRange(r) param return 0;
  def _tupleize(x) {
    var y: 1*x.type;
    y(1) = x;
    return y;
  }
  def collectRanges(param dim: int) {
    if dim > args.size then
      compilerError("domain slice requires a range in at least one dimension");
    if isRange(args(dim)) then
      return collectRanges(dim+1, _tupleize(args(dim)));
    else
      return collectRanges(dim+1);
  }
  def collectRanges(param dim: int, x: _tuple) {
    if dim > args.size {
      return x;
    } else if dim < args.size {
      if isRange(args(dim)) then
        return collectRanges(dim+1, ((...x), args(dim)));
      else
        return collectRanges(dim+1, x);
    } else {
      if isRange(args(dim)) then
        return ((...x), args(dim));
      else
        return x;
    }
  }
  return collectRanges(1);
}

//
// Support for += and -= over domains
//
def chpl__isDomain(x: domain) param return true;
def chpl__isDomain(x) param return false;

//
// Assignment of domains and arrays
//
def =(a: domain, b: domain) {
  for e in a._value._arrs do
    e.reallocate(b);
  a._value.setIndices(b._value.getIndices());
  return a;
}

def =(a: domain, b: _tuple) {
  for ind in 1..b.size {
    a.add(b(ind));
  }
  return a;
}

def =(d: domain, r: range(?)) {
  d = [r];
  return d;
}

def =(a: domain, b) {  // b is iteratable
  a._value.clearForIteratableAssign();
  for ind in b {
    a.add(ind);
  }
  return a;
}

def _copy(a: domain) {
  var b: a.type;
  b.setIndices(a.getIndices());
  return b;
}

pragma "inline" def =(a: [], b) {
  for (i,bb) in (a._dom,b) do
    a(i) = bb;
  return a;
}

def =(a: [], b: _tuple) {
  a._value.tupleInit(b);
  return a;
}

def _desync(type t) where t: _syncvar || t: _singlevar {
  var x: t;
  return x.value;
}

def _desync(type t) where !(t: _syncvar|| t: _singlevar) {
  var x: t;
  return x;
}

def =(a: [], b: _desync(a.eltType)) {
  for i in a._dom do
    a(i) = b;
  return a;
}

def _copy(a: []) {
  var b : [a._dom] a.eltType;
  b = a;
  return b;
}

def by(a: domain, b) {
  var x = a._value.strideBy(b);
  return _newDomain(x);
}

//
// index for all opaque domains
//
class _OpaqueIndex { }

//
// Swap operators for arrays and domains
//
pragma "inline" def _chpl_swap(x: [], y: []) {
  for (i,j) in (x.domain, y.domain) do
    x(i) <=> y(j);
}

pragma "inline" def _chpl_swap(x: domain, y: domain) {
  const t = y;
  y = x;
  x = t;
}

//
// reshape function
//
def reshape(A: [], D: domain) {
  var B: [D] A.eltType;
  for (i,a) in (D,A) do
    B(i) = a;
  return B;
}

def _callSupportsAlignedFollower(A) param where A: BaseArray
  return A.supportsAlignedFollower();

def _callSupportsAlignedFollower(A) param where !(A: BaseArray)
  return false;

def _callSupportsAlignedFollower() param
  return false;

//
// module support for iterators
//
enum iterator {leader, follower};

def iteratorIndex(ic: _iteratorClass) {
  ic.advance();
  return ic.getValue();
}

pragma "expand tuples with values"
def iteratorIndex(t: _tuple) {
  pragma "expand tuples with values"
  def iteratorIndexHelp(t: _tuple, param dim: int) {
    if dim == t.size-1 then
      return _build_tuple_always_allow_ref(iteratorIndex(t(dim)),
                                           iteratorIndex(t(dim+1)));
    else
      return _build_tuple_always_allow_ref(iteratorIndex(t(dim)),
                                           (...iteratorIndexHelp(t, dim+1)));
  }

  return iteratorIndexHelp(t, 1);
}

def iteratorIndexType(x) type {
  return iteratorIndex(x).type;
}

def _iteratorClass.writeThis(f: Writer) {
  var first: bool = true;
  for e in this {
    if !first then
      f.write(" ");
    else
      first = false;
    f.write(e);
  }
}

def =(ic: _iteratorClass, xs) {
  for (e, x) in (ic, xs) do
    e = x;
  return ic;
}

def =(ic: _iteratorClass, x: iteratorIndexType(ic)) {
  for e in ic do
    e = x;
  return ic;
}

def _copy(ic: _iteratorClass) {
  return _ic_copy_help(_ic_copy_recursive(ic));

  def _ic_copy_recursive(ic) {
    for e in ic do
      yield _copy(e);
  }

  def _ic_copy_help(ic) {
    var i = 1, size = 4;
    var D = [1..size];

    // note that _getIterator is called in order to copy the iterator
    // class since for arrays we need to iterate once to get the
    // element type (at least for now); this also means that if this
    // iterator has side effects, we will see them; a better way to
    // handle this may be to get the static type (not initialize the
    // array) and use a primitive to set the array's element; that may
    // also handle skyline arrays
    var A: [D] iteratorIndexType(_getIterator(ic));

    for e in ic {
      if i > size {
        size = size * 2;
        D = [1..size];
      }
      A(i) = e;
      i = i + 1;
    }
    D = [1..i-1];
    return A;
  }
}

pragma "inline" pragma "iterator class copy"
def _getIterator(ic: _iteratorClass)
  return ic;

pragma "inline" pragma "ref" def _getIterator(x)
  return x.these();

pragma "inline" def _getIterator(x: _tuple) {
  pragma "inline" def _getIteratorHelp(x: _tuple, param dim: int) {
    if dim == x.size-1 then
      return (_getIterator(x(dim)), _getIterator(x(dim+1)));
    else
      return (_getIterator(x(dim)), (..._getIteratorHelp(x, dim+1)));
  }
  return _getIteratorHelp(x, 1);
}

def _getIterator(type t) {
  compilerError("cannot iterate over a type");
}

pragma "inline"
def _toLeader(iterator: _iteratorClass)
  return __primitive("to leader", iterator);

pragma "inline"
def _toLeader(x: _tuple)
  return _toLeader(x(1));

pragma "inline"
def _toLeader(x)
  return _toLeader(x.these());

pragma "inline"
def _toFollower(iterator: _iteratorClass, leaderIndex)
  return __primitive("to follower", iterator, leaderIndex);

//
// If aligned is passed as an argument (true from alignment version of
// _toFollower on tuple) then grab the aligned version of the array's
// iterator if the array supports aligned followers
//
pragma "inline"
def _toFollower(iterator: _iteratorClass, leaderIndex, param aligned: bool) {
  return __primitive("to follower", iterator, leaderIndex, aligned);
}

pragma "inline"
def _toFollower(x: _tuple, leaderIndex) {
  pragma "inline" def _toFollowerHelp(x: _tuple, leaderIndex, param dim: int) {
    if dim == x.size-1 then
      return (_toFollower(x(dim), leaderIndex),
              _toFollower(x(dim+1), leaderIndex));
    else
      return (_toFollower(x(dim), leaderIndex),
              (..._toFollowerHelp(x, leaderIndex, dim+1)));
  }
  return _toFollowerHelp(x, leaderIndex, 1);
}

//
// The alignment version uses a compiler analysis to pass a tuple of
// types according to whether the arrays in the tuple x have the same
// distribution as the leader or not.  If they do, the component type
// is passed as Distribution, otherwise as BaseArray.
//
pragma "inline"
def _toFollower(x: _tuple, leaderIndex, type alignment) {
  pragma "inline" def _toFollowerHelp(x: _tuple, leaderIndex, param dim: int) {
    if dim == x.size-1 {
      type tdim = alignment(dim);
      type tdimp1 = alignment(dim+1);
      if tdim == Distribution & tdimp1 == Distribution {
        return (_toFollower(x(dim), leaderIndex, true),
                _toFollower(x(dim+1), leaderIndex, true));
      } else if tdim == Distribution {
        return (_toFollower(x(dim), leaderIndex, true),
                _toFollower(x(dim+1), leaderIndex));
      } else if tdimp1 == Distribution {
        return (_toFollower(x(dim), leaderIndex),
                _toFollower(x(dim+1), leaderIndex, true));
      } else {
        return (_toFollower(x(dim), leaderIndex),
                _toFollower(x(dim+1), leaderIndex));
      }
    } else {
      type tdim = alignment(dim);
      if tdim == Distribution {
        return (_toFollower(x(dim), leaderIndex, true),
                (..._toFollowerHelp(x, leaderIndex, dim+1)));
      } else {
        return (_toFollower(x(dim), leaderIndex),
                (..._toFollowerHelp(x, leaderIndex, dim+1)));
      }
    }
  }
  return _toFollowerHelp(x, leaderIndex, 1);
}

// sjd: is this ever called?
pragma "inline"
def _toFollower(x, leaderIndex)
  return _toFollower(x.these(), leaderIndex);


Added a return statement after a halt to the range.this method.  This
should fix three GASnet regressions.

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

//
// syntactic bridge code for bounded ranges
//
def _build_range(param bt: BoundedRangeType, low: int, high: int)
  return range(int, bt, false, low, high);
def _build_range(param bt: BoundedRangeType, low: uint, high: uint)
  return range(uint, bt, false, low, high);
def _build_range(param bt: BoundedRangeType, low: int(64), high: int(64))
  return range(int(64), bt, false, low, high);
def _build_range(param bt: BoundedRangeType, low: uint(64), high: uint(64))
  return range(uint(64), bt, false, low, high);
def _build_range(param bt: BoundedRangeType, low, high) {
  compilerError("range bounds are not integral");
}

//
// syntactic bridge code for unbounded ranges
//
def _build_range(param bt: BoundedRangeType, bound: int)
  return range(int, bt, false, bound, bound);
def _build_range(param bt: BoundedRangeType, bound: uint)
  return range(uint, bt, false, bound, bound);
def _build_range(param bt: BoundedRangeType, bound: int(64))
  return range(int(64), bt, false, bound, bound);
def _build_range(param bt: BoundedRangeType, bound: uint(64))
  return range(uint(64), bt, false, bound, bound);
def _build_range(param bt: BoundedRangeType)
  return range(int, bt, false);
def _build_range(param bt: BoundedRangeType, bound) {
  compilerError("range bound is not integral");
}

//
// range type implementation
//
//   paramterized by how it is bounded and by an integral element type
//
record range {
  type eltType = int;                            // element type
  param boundedType: BoundedRangeType = bounded; // bounded or not
  param stridable: bool = false;                 // range can be strided
  var _low : eltType = 1;                        // lower bound
  var _high : eltType = 0;                       // upper bound
  var _stride : int = 1;                         // integer stride of range
  var _promotionType : eltType;                  // enables promotion

  def low: eltType return _low;
  def high: eltType return _high;
  def stride: int return _stride;

  def this(subrange: range(?eltType, ?boundedness, ?stridable)) {
    if (stride != 1 || _stride != 1) {
      halt("range slicing not supported for strided ranges yet");
    }
    if ((boundedType == bounded) && (_high < _low)) then
      return range(eltType, bounded, stridable:bool, _low:eltType, _high:eltType, _stride:eltType);
//    Why can't above return statement return this?  A function
//    resolution error results if return this is used, complaining
//    that there are multiple return types.
    if (boundedness == bounded) {
      if (subrange.low >= low && subrange.high <= high) {
        return range(eltType, bounded, stridable, subrange.low, subrange.high,
                     subrange.stride);
      } else {
        halt("range slice out of bounds: ", subrange);
        return range(eltType, bounded, stridable);
      }
    } else if (boundedness == boundedLow) {
      return range(eltType, bounded, stridable, subrange.low, _high,
                   subrange.stride);
    } else if (boundedness == boundedHigh) {
      return range(eltType, bounded, stridable, _low, subrange.high,
                   subrange.stride);
    } else if (boundedness == boundedNone) {
      return range(eltType, bounded, stridable, _low, _high, subrange.stride);
    } else {
      compilerError("unexpected boundedness case in range.this()");
    }
  }

  def these() {
    if boundedType != bounded {
      if stridable {
        var i = if _stride > 0 then _low else _high;
        while true {
          yield i;
          i = i + _stride:eltType;
        }
      } else {
        var i = _low;
        while true {
          yield i;
          i = i + 1;
        }
      }
    } else {
      if stridable {
        var i = if _stride > 0 then _low else _high;
        while _low <= i && i <= _high {
          yield i;
          i = i + _stride:eltType;
        }
      } else {
        var i: eltType;
        for __primitive("c for loop", i, _low, _high, 1) {
          yield i;
        }
      }
    }
  }

  def length {
    if boundedType != bounded then
      compilerError("unable to determine length of unbounded range");
    return
      (if _stride > 0
        then (_high - _low + _stride:eltType) / _stride:eltType
        else (_low - _high + _stride:eltType) / _stride:eltType);
  }
}

def =(r1: range(stridable=?stridable), r2) {
  if !stridable then
    if r2.stride != 1 then
      halt("non-stridable range assigned non-unit stride");
  r1._low = r2._low;
  r1._high = r2._high;
  r1._stride = r2._stride;
  return r1;
}

def by(s : range, i : int) {
  if i == 0 then
    halt("illegal stride of 0");
  var as = range(s.eltType, s.boundedType, true, s._low, s._high, s._stride * i);
  if s._low > s._high then return as;

  if as._stride < 0 then
    as._low = as._low + (as._high - as._low) % (-as._stride):as.eltType;
  else
    as._high = as._high - (as._high - as._low) % (as._stride):as.eltType;
  if as.boundedType == boundedLow then
    if as._stride < 0 then
      halt("error: unbounded range has negative stride and lower bound");
  if as.boundedType == boundedHigh then
    if as._stride > 0 then
      halt("error: unbounded range has positive stride and upper bound");
  return as;
}

def _in(s : range, i : s.eltType) {
  if s.boundedType != bounded then
    compilerError("_in undefined on unbounded ranges");
  return i >= s._low && i <= s._high &&
    (i - s._low) % abs(s._stride):s.eltType == 0;
}

// really slow --- REWRITE
def _in(s1: range, s2: range) {
  if (s1.boundedType != bounded) | (s2.boundedType != bounded) then
    compilerError("_in undefined on unbounded ranges");
  for i in s2 do
    if !_in(s1, i) then
      return false;
  return true;
}

def range.writeThis(f: Writer) {
  if (boundedType == bounded) | (boundedType == boundedLow) then
    f.write(_low);
  f.write("..");
  if (boundedType == bounded) | (boundedType == boundedHigh) then
    f.write(_high);
  if _stride != 1 then
    f.write(" by ", _stride);
}

pragma "inline" def string.substring(s: range) {
  if s.boundedType != bounded then
    compilerError("substring indexing undefined on unbounded ranges");
  if s._stride != 1 then
    return __primitive("string_strided_select", this, s._low, s._high, s._stride);
  else
    return __primitive("string_select", this, s._low, s._high);
}

def range._translate(i : int) {
  if boundedType != bounded then
    compilerError("translate is not supported on unbounded ranges");
  return _low+i.._high+i by _stride;
}

def range._interior(i : int) {
  if boundedType != bounded then
    compilerError("interior is not supported on unbounded ranges");
  var x = _low.._high by _stride;
  if (i < 0) {
    x = _low.._low-1-i by _stride;
  } else if (i > 0) {
    x = _high+1-i.._high by _stride;
  }
  return x;
}

def range._exterior(i : int) {
  if boundedType != bounded then
    compilerError("exterior is not supported on unbounded ranges");
  var x = _low.._high by _stride;
  if (i < 0) {
    x = _low+i.._low-1 by _stride;
  } else if (i > 0) {
    x = _high+1.._high+i by _stride;
  }
  return x;
}

def range._expand(i : int) {
  if boundedType != bounded then
    compilerError("expand is not supported on unbounded ranges");
  return _low-i.._high+i by _stride;
}

def _intersect(a: range, b: range) {
  if (a.boundedType != bounded) | (b.boundedType != bounded) then
    compilerError("insersection not defined on unbounded ranges");
  var g, x: int;
  (g, x) = _extended_euclid(a._stride, b._stride);
  var gg = g:a.eltType;
  var xx = x:a.eltType;
  var as = (a._stride):a.eltType;
  if abs(a._low - b._low) % gg != 0 then
    return 1..0:a.eltType by 1;
  var low = max(a._low, b._low);
  var high = min(a._high, b._high);
  var stride = a._stride * b._stride / g;
  var alignment = a._low + (b._low - a._low) * xx * as / gg;
  if alignment == 0 then
    alignment = stride:a.eltType;
  low = low + low % alignment;
  return low..high by stride;
}

// Extended-Euclid (Knuth Volume 2 --- Section 4.5.2)
// given two non-negative integers u and v
// returns (gcd(u, v), x) where x is set such that u*x + v*y = gcd(u, v)
def _extended_euclid(u: int, v: int) {
  var u1 = 1;
  var u2 = 0;
  var u3 = u;
  var v1 = 0;
  var v2 = 1;
  var v3 = v;
  while v3 != 0 {
    var q = u3 / v3;
    var t1 = u1 - v1 * q;
    var t2 = u2 - v2 * q;
    var t3 = u3 - v3 * q;
    u1 = v1;
    u2 = v2;
    u3 = v3;
    v1 = t1;
    v2 = t2;
    v3 = t3;
  }
  return (u3, u1);
}

def _build_open_interval_upper(r: range) {
  return range(r.eltType, r.boundedType, r.stridable, r._low, r._high-1);
}

def =(a: _domain, b: range) {
  const bdom = _build_domain(b);
  a = bdom;
  return a;
}

/* Would like to define these as follows:

def +(r: range, s: integral) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

but because we don't distinguish "better" functions between promotion
and generics, it doesn't work -- see the arrayVsPromotion and
rangeVsPromotion futures for examples of this.

Alternatively, we might like to do:

def +(r: range, s: r.eltType) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

but this doesn't allow an int(32) range to be added to an int(64)
integer, which seems useful/important/congruous to integer addition.
So, I'm cloning manually. */

def +(r: range, s: int) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

def -(r: range, s: int) {
  return range((r._low-s).type, r.boundedType, r.stridable, r._low-s, r._high-s, r._stride);
}

def *(r: range, s: int) {
  return range((r._low*s).type, r.boundedType, stridable=true, r._low*s, r._high*s, r._stride*s);
}

def /(r: range, s: int) {
  return range((r._low/s).type, r.boundedType, stridable=true, r._low/s, r._high/s, r._stride/s);
}

def +(s:int, r: range) {
  return range((s+r._low).type, r.boundedType, r.stridable, s+r._low, s+r._high, r._stride);
}

def -(s:int, r: range) {
  return range((s-r._low).type, r.boundedType, r.stridable, s-r._low, s-r._high, r._stride);
}

def *(s:int, r: range) {
  return range((s*r._low).type, r.boundedType, stridable=true, s*r._low, s*r._high, s*r._stride);
}

def /(s:int, r: range) {
  return range((s/r._low).type, r.boundedType, stridable=true, s/r._low, s/r._high, s/r._stride);
}

def +(r: range, s: uint) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

def -(r: range, s: uint) {
  return range((r._low-s).type, r.boundedType, r.stridable, r._low-s, r._high-s, r._stride);
}

def *(r: range, s: uint) {
  return range((r._low*s).type, r.boundedType, stridable=true, r._low*s, r._high*s, r._stride*s);
}

def /(r: range, s: uint) {
  return range((r._low/s).type, r.boundedType, stridable=true, r._low/s, r._high/s, r._stride/s);
}

def +(s:uint, r: range) {
  return range((s+r._low).type, r.boundedType, r.stridable, s+r._low, s+r._high, r._stride);
}

def -(s:uint, r: range) {
  return range((s-r._low).type, r.boundedType, r.stridable, s-r._low, s-r._high, r._stride);
}

def *(s:uint, r: range) {
  return range((s*r._low).type, r.boundedType, stridable=true, s*r._low, s*r._high, s*r._stride);
}

def /(s:uint, r: range) {
  return range((s/r._low).type, r.boundedType, stridable=true, s/r._low, s/r._high, s/r._stride);
}

def +(r: range, s: int(64)) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

def -(r: range, s: int(64)) {
  return range((r._low-s).type, r.boundedType, r.stridable, r._low-s, r._high-s, r._stride);
}

def *(r: range, s: int(64)) {
  return range((r._low*s).type, r.boundedType, stridable=true, r._low*s, r._high*s, r._stride*s);
}

def /(r: range, s: int(64)) {
  return range((r._low/s).type, r.boundedType, stridable=true, r._low/s, r._high/s, r._stride/s);
}

def +(s:int(64), r: range) {
  return range((s+r._low).type, r.boundedType, r.stridable, s+r._low, s+r._high, r._stride);
}

def -(s:int(64), r: range) {
  return range((s-r._low).type, r.boundedType, r.stridable, s-r._low, s-r._high, r._stride);
}

def *(s:int(64), r: range) {
  return range((s*r._low).type, r.boundedType, stridable=true, s*r._low, s*r._high, s*r._stride);
}

def /(s:int(64), r: range) {
  return range((s/r._low).type, r.boundedType, stridable=true, s/r._low, s/r._high, s/r._stride);
}

def +(r: range, s: uint(64)) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

def -(r: range, s: uint(64)) {
  return range((r._low-s).type, r.boundedType, r.stridable, r._low-s, r._high-s, r._stride);
}

def *(r: range, s: uint(64)) {
  return range((r._low*s).type, r.boundedType, stridable=true, r._low*s, r._high*s, r._stride*s);
}

def /(r: range, s: uint(64)) {
  return range((r._low/s).type, r.boundedType, stridable=true, r._low/s, r._high/s, r._stride/s);
}

def +(s:uint(64), r: range) {
  return range((s+r._low).type, r.boundedType, r.stridable, s+r._low, s+r._high, r._stride);
}

def -(s:uint(64), r: range) {
  return range((s-r._low).type, r.boundedType, r.stridable, s-r._low, s-r._high, r._stride);
}

def *(s:uint(64), r: range) {
  return range((s*r._low).type, r.boundedType, stridable=true, s*r._low, s*r._high, s*r._stride);
}

def /(s:uint(64), r: range) {
  return range((s/r._low).type, r.boundedType, stridable=true, s/r._low, s/r._high, s/r._stride);
}

//
// syntactic bridge code for bounded ranges
//
def _build_range(param bt: BoundedRangeType, low: int, high: int)
  return range(int, bt, false, low, high);
def _build_range(param bt: BoundedRangeType, low: uint, high: uint)
  return range(uint, bt, false, low, high);
def _build_range(param bt: BoundedRangeType, low: int(64), high: int(64))
  return range(int(64), bt, false, low, high);
def _build_range(param bt: BoundedRangeType, low: uint(64), high: uint(64))
  return range(uint(64), bt, false, low, high);
def _build_range(param bt: BoundedRangeType, low, high) {
  compilerError("range bounds are not integral");
}

//
// syntactic bridge code for unbounded ranges
//
def _build_range(param bt: BoundedRangeType, bound: int)
  return range(int, bt, false, bound, bound);
def _build_range(param bt: BoundedRangeType, bound: uint)
  return range(uint, bt, false, bound, bound);
def _build_range(param bt: BoundedRangeType, bound: int(64))
  return range(int(64), bt, false, bound, bound);
def _build_range(param bt: BoundedRangeType, bound: uint(64))
  return range(uint(64), bt, false, bound, bound);
def _build_range(param bt: BoundedRangeType)
  return range(int, bt, false);
def _build_range(param bt: BoundedRangeType, bound) {
  compilerError("range bound is not integral");
}

//
// range type implementation
//
//   paramterized by how it is bounded and by an integral element type
//
record range {
  type eltType = int;                            // element type
  param boundedType: BoundedRangeType = bounded; // bounded or not
  param stridable: bool = false;                 // range can be strided
  var _low : eltType = 1;                        // lower bound
  var _high : eltType = 0;                       // upper bound
  var _stride : int = 1;                         // integer stride of range
  var _promotionType : eltType;                  // enables promotion

  def low: eltType return _low;
  def high: eltType return _high;
  def stride: int return _stride;

  def this(subrange: range(?eltType, ?boundedness, ?stridable)) {
    if (stride != 1 || _stride != 1) {
      halt("range slicing not supported for strided ranges yet");
    }
    if ((boundedType == bounded) && (_high < _low)) then
      return range(eltType, bounded, stridable:bool, _low:eltType, _high:eltType, _stride:eltType);
//    Why can't above return statement return this?  A function
//    resolution error results if return this is used, complaining
//    that there are multiple return types.
    if (boundedness == bounded) {
      if (subrange.low >= low && subrange.high <= high) {
        return range(eltType, bounded, stridable, subrange.low, subrange.high,
                     subrange.stride);
      } else {
        halt("range slice out of bounds: ", subrange);
      }
    } else if (boundedness == boundedLow) {
      return range(eltType, bounded, stridable, subrange.low, _high,
                   subrange.stride);
    } else if (boundedness == boundedHigh) {
      return range(eltType, bounded, stridable, _low, subrange.high,
                   subrange.stride);
    } else if (boundedness == boundedNone) {
      return range(eltType, bounded, stridable, _low, _high, subrange.stride);
    } else {
      compilerError("unexpected boundedness case in range.this()");
    }
  }

  def these() {
    if boundedType != bounded {
      if stridable {
        var i = if _stride > 0 then _low else _high;
        while true {
          yield i;
          i = i + _stride:eltType;
        }
      } else {
        var i = _low;
        while true {
          yield i;
          i = i + 1;
        }
      }
    } else {
      if stridable {
        var i = if _stride > 0 then _low else _high;
        while _low <= i && i <= _high {
          yield i;
          i = i + _stride:eltType;
        }
      } else {
        var i: eltType;
        for __primitive("c for loop", i, _low, _high, 1) {
          yield i;
        }
      }
    }
  }

  def length {
    if boundedType != bounded then
      compilerError("unable to determine length of unbounded range");
    return
      (if _stride > 0
        then (_high - _low + _stride:eltType) / _stride:eltType
        else (_low - _high + _stride:eltType) / _stride:eltType);
  }
}

def =(r1: range(stridable=?stridable), r2) {
  if !stridable then
    if r2.stride != 1 then
      halt("non-stridable range assigned non-unit stride");
  r1._low = r2._low;
  r1._high = r2._high;
  r1._stride = r2._stride;
  return r1;
}

def by(s : range, i : int) {
  if i == 0 then
    halt("illegal stride of 0");
  var as = range(s.eltType, s.boundedType, true, s._low, s._high, s._stride * i);
  if s._low > s._high then return as;

  if as._stride < 0 then
    as._low = as._low + (as._high - as._low) % (-as._stride):as.eltType;
  else
    as._high = as._high - (as._high - as._low) % (as._stride):as.eltType;
  if as.boundedType == boundedLow then
    if as._stride < 0 then
      halt("error: unbounded range has negative stride and lower bound");
  if as.boundedType == boundedHigh then
    if as._stride > 0 then
      halt("error: unbounded range has positive stride and upper bound");
  return as;
}

def _in(s : range, i : s.eltType) {
  if s.boundedType != bounded then
    compilerError("_in undefined on unbounded ranges");
  return i >= s._low && i <= s._high &&
    (i - s._low) % abs(s._stride):s.eltType == 0;
}

// really slow --- REWRITE
def _in(s1: range, s2: range) {
  if (s1.boundedType != bounded) | (s2.boundedType != bounded) then
    compilerError("_in undefined on unbounded ranges");
  for i in s2 do
    if !_in(s1, i) then
      return false;
  return true;
}

def range.writeThis(f: Writer) {
  if (boundedType == bounded) | (boundedType == boundedLow) then
    f.write(_low);
  f.write("..");
  if (boundedType == bounded) | (boundedType == boundedHigh) then
    f.write(_high);
  if _stride != 1 then
    f.write(" by ", _stride);
}

pragma "inline" def string.substring(s: range) {
  if s.boundedType != bounded then
    compilerError("substring indexing undefined on unbounded ranges");
  if s._stride != 1 then
    return __primitive("string_strided_select", this, s._low, s._high, s._stride);
  else
    return __primitive("string_select", this, s._low, s._high);
}

def range._translate(i : int) {
  if boundedType != bounded then
    compilerError("translate is not supported on unbounded ranges");
  return _low+i.._high+i by _stride;
}

def range._interior(i : int) {
  if boundedType != bounded then
    compilerError("interior is not supported on unbounded ranges");
  var x = _low.._high by _stride;
  if (i < 0) {
    x = _low.._low-1-i by _stride;
  } else if (i > 0) {
    x = _high+1-i.._high by _stride;
  }
  return x;
}

def range._exterior(i : int) {
  if boundedType != bounded then
    compilerError("exterior is not supported on unbounded ranges");
  var x = _low.._high by _stride;
  if (i < 0) {
    x = _low+i.._low-1 by _stride;
  } else if (i > 0) {
    x = _high+1.._high+i by _stride;
  }
  return x;
}

def range._expand(i : int) {
  if boundedType != bounded then
    compilerError("expand is not supported on unbounded ranges");
  return _low-i.._high+i by _stride;
}

def _intersect(a: range, b: range) {
  if (a.boundedType != bounded) | (b.boundedType != bounded) then
    compilerError("insersection not defined on unbounded ranges");
  var g, x: int;
  (g, x) = _extended_euclid(a._stride, b._stride);
  var gg = g:a.eltType;
  var xx = x:a.eltType;
  var as = (a._stride):a.eltType;
  if abs(a._low - b._low) % gg != 0 then
    return 1..0:a.eltType by 1;
  var low = max(a._low, b._low);
  var high = min(a._high, b._high);
  var stride = a._stride * b._stride / g;
  var alignment = a._low + (b._low - a._low) * xx * as / gg;
  if alignment == 0 then
    alignment = stride:a.eltType;
  low = low + low % alignment;
  return low..high by stride;
}

// Extended-Euclid (Knuth Volume 2 --- Section 4.5.2)
// given two non-negative integers u and v
// returns (gcd(u, v), x) where x is set such that u*x + v*y = gcd(u, v)
def _extended_euclid(u: int, v: int) {
  var u1 = 1;
  var u2 = 0;
  var u3 = u;
  var v1 = 0;
  var v2 = 1;
  var v3 = v;
  while v3 != 0 {
    var q = u3 / v3;
    var t1 = u1 - v1 * q;
    var t2 = u2 - v2 * q;
    var t3 = u3 - v3 * q;
    u1 = v1;
    u2 = v2;
    u3 = v3;
    v1 = t1;
    v2 = t2;
    v3 = t3;
  }
  return (u3, u1);
}

def _build_open_interval_upper(r: range) {
  return range(r.eltType, r.boundedType, r.stridable, r._low, r._high-1);
}

def =(a: _domain, b: range) {
  const bdom = _build_domain(b);
  a = bdom;
  return a;
}

/* Would like to define these as follows:

def +(r: range, s: integral) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

but because we don't distinguish "better" functions between promotion
and generics, it doesn't work -- see the arrayVsPromotion and
rangeVsPromotion futures for examples of this.

Alternatively, we might like to do:

def +(r: range, s: r.eltType) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

but this doesn't allow an int(32) range to be added to an int(64)
integer, which seems useful/important/congruous to integer addition.
So, I'm cloning manually. */

def +(r: range, s: int) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

def -(r: range, s: int) {
  return range((r._low-s).type, r.boundedType, r.stridable, r._low-s, r._high-s, r._stride);
}

def *(r: range, s: int) {
  return range((r._low*s).type, r.boundedType, stridable=true, r._low*s, r._high*s, r._stride*s);
}

def /(r: range, s: int) {
  return range((r._low/s).type, r.boundedType, stridable=true, r._low/s, r._high/s, r._stride/s);
}

def +(s:int, r: range) {
  return range((s+r._low).type, r.boundedType, r.stridable, s+r._low, s+r._high, r._stride);
}

def -(s:int, r: range) {
  return range((s-r._low).type, r.boundedType, r.stridable, s-r._low, s-r._high, r._stride);
}

def *(s:int, r: range) {
  return range((s*r._low).type, r.boundedType, stridable=true, s*r._low, s*r._high, s*r._stride);
}

def /(s:int, r: range) {
  return range((s/r._low).type, r.boundedType, stridable=true, s/r._low, s/r._high, s/r._stride);
}

def +(r: range, s: uint) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

def -(r: range, s: uint) {
  return range((r._low-s).type, r.boundedType, r.stridable, r._low-s, r._high-s, r._stride);
}

def *(r: range, s: uint) {
  return range((r._low*s).type, r.boundedType, stridable=true, r._low*s, r._high*s, r._stride*s);
}

def /(r: range, s: uint) {
  return range((r._low/s).type, r.boundedType, stridable=true, r._low/s, r._high/s, r._stride/s);
}

def +(s:uint, r: range) {
  return range((s+r._low).type, r.boundedType, r.stridable, s+r._low, s+r._high, r._stride);
}

def -(s:uint, r: range) {
  return range((s-r._low).type, r.boundedType, r.stridable, s-r._low, s-r._high, r._stride);
}

def *(s:uint, r: range) {
  return range((s*r._low).type, r.boundedType, stridable=true, s*r._low, s*r._high, s*r._stride);
}

def /(s:uint, r: range) {
  return range((s/r._low).type, r.boundedType, stridable=true, s/r._low, s/r._high, s/r._stride);
}

def +(r: range, s: int(64)) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

def -(r: range, s: int(64)) {
  return range((r._low-s).type, r.boundedType, r.stridable, r._low-s, r._high-s, r._stride);
}

def *(r: range, s: int(64)) {
  return range((r._low*s).type, r.boundedType, stridable=true, r._low*s, r._high*s, r._stride*s);
}

def /(r: range, s: int(64)) {
  return range((r._low/s).type, r.boundedType, stridable=true, r._low/s, r._high/s, r._stride/s);
}

def +(s:int(64), r: range) {
  return range((s+r._low).type, r.boundedType, r.stridable, s+r._low, s+r._high, r._stride);
}

def -(s:int(64), r: range) {
  return range((s-r._low).type, r.boundedType, r.stridable, s-r._low, s-r._high, r._stride);
}

def *(s:int(64), r: range) {
  return range((s*r._low).type, r.boundedType, stridable=true, s*r._low, s*r._high, s*r._stride);
}

def /(s:int(64), r: range) {
  return range((s/r._low).type, r.boundedType, stridable=true, s/r._low, s/r._high, s/r._stride);
}

def +(r: range, s: uint(64)) {
  return range((r._low+s).type, r.boundedType, r.stridable, r._low+s, r._high+s, r._stride);
}

def -(r: range, s: uint(64)) {
  return range((r._low-s).type, r.boundedType, r.stridable, r._low-s, r._high-s, r._stride);
}

def *(r: range, s: uint(64)) {
  return range((r._low*s).type, r.boundedType, stridable=true, r._low*s, r._high*s, r._stride*s);
}

def /(r: range, s: uint(64)) {
  return range((r._low/s).type, r.boundedType, stridable=true, r._low/s, r._high/s, r._stride/s);
}

def +(s:uint(64), r: range) {
  return range((s+r._low).type, r.boundedType, r.stridable, s+r._low, s+r._high, r._stride);
}

def -(s:uint(64), r: range) {
  return range((s-r._low).type, r.boundedType, r.stridable, s-r._low, s-r._high, r._stride);
}

def *(s:uint(64), r: range) {
  return range((s*r._low).type, r.boundedType, stridable=true, s*r._low, s*r._high, s*r._stride);
}

def /(s:uint(64), r: range) {
  return range((s/r._low).type, r.boundedType, stridable=true, s/r._low, s/r._high, s/r._stride);
}


Add note to definition of ENOERR indicating that it represents the state where no error has occurred.

/*
 * 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.
 */

/* BASIC TYPES */
use SysCTypes;

extern type c_float = real(32);
extern type c_double = real(64);
/*extern type c_wchar_t = uint(32); */
extern type off_t = int(64);
extern type mode_t = uint(32);
extern type socklen_t = int(32);

// C File type
//type c_file = _file;

// stdin/stdout/sterr
//extern proc chpl_cstdin():_file;
extern proc chpl_cstdout():_file;
extern proc chpl_cstderr():_file;
extern proc chpl_cnullfile():_file;

// system error number.
extern type syserr; // = c_int, opaque so we can manually override ==,!=,etc
extern type err_t = c_int;
// When to use syserr and when to use err_t?
// err_t is a system error code (a c_int by a nicer name).
// syserr is an enhanced error that might also include an
// error message. All user-facing Chapel library code,
// or user Chapel code, should generally use syserr.
// When wrapping functions or declaring them in C,
// use err_t to indicate that a function is returning
// an error code.

// system file descriptor.
extern type fd_t = c_int;

// NULL
extern const c_nil:c_void_ptr;
// To generate legal C prototypes, we have to manually instantiate this
// prototype for each pointer type that might be associated with 'x'.
pragma "no prototype"
extern proc is_c_nil(x):bool;

// local C pointer class used in C integration.
// Similar to _ddata from ChapelBase, but differs
// from _ddata because it can never be wide.
pragma "data class"
pragma "no object"
pragma "no default functions"
pragma "no wide class"
class c_ptr {
  type eltType;
  inline proc this(i: integral) ref {
    return __primitive("array_get", this, i);
  }
  inline proc deref() ref {
    return __primitive("array_get", this, 0);
  }
}

inline proc =(ref a:c_ptr, b:c_ptr) { __primitive("=", a, b); }

inline proc =(ref a:c_ptr, b:_nilType) { __primitive("=", a, nil); }

inline proc _cast(type t, x) where t:c_ptr && x:_nilType {
  return __primitive("cast", t, x);
}
inline proc _cast(type t, x) where t:c_ptr && x.type:c_ptr {
  return __primitive("cast", t, x);
}
inline proc _cast(type t, x) where t:c_void_ptr && x.type:c_ptr {
  return __primitive("cast", t, x);
}

inline proc c_calloc(type eltType, size: integral) {
  var ret:c_ptr(eltType);
  __primitive("array_alloc", ret, eltType, size);
  init_elts(ret, size, eltType);
  return ret;
}

inline proc c_free(data: c_ptr) {
  __primitive("array_free", data);
}

inline proc ==(a: c_ptr, b: c_ptr) where a.eltType == b.eltType {
  return __primitive("ptr_eq", a, b);
}
inline proc ==(a: c_ptr, b: _nilType) {
  return __primitive("ptr_eq", a, nil);
}
inline proc ==(a: _nilType, b: c_ptr) {
  return __primitive("ptr_eq", nil, b);
}

inline proc !=(a: c_ptr, b: c_ptr) where a.eltType == b.eltType {
  return __primitive("ptr_neq", a, b);
}
inline proc !=(a: c_ptr, b: _nilType) {
  return __primitive("ptr_neq", a, nil);
}
inline proc !=(a: _nilType, b: c_ptr) {
  return __primitive("ptr_neq", nil, b);
}

inline proc _cond_test(x: c_ptr) return x != nil;

inline proc !(x: c_ptr) return x == nil;
extern proc c_pointer_return(ref x:?t):c_ptr(t);

inline proc c_ptrTo(arr: []) where isRectangularArr(arr) && arr.rank == 1 {
  return c_pointer_return(arr[arr.domain.low]);
}
inline proc c_ptrTo(ref x:?t):c_ptr(t)
{
  if isArrayType(t) then
    compilerError("c_ptrTo unsupported array type");
  if isDomainType(t) then
    compilerError("c_ptrTo domain type not supported");
  // Other cases should be avoided, e.g. sync vars
  return c_pointer_return(x);
}

// error numbers

extern proc qio_err_eq(a:syserr, b:syserr):c_int;
extern proc qio_err_to_int(a:syserr):int(32);
extern proc qio_int_to_err(a:int(32)):syserr;
extern proc qio_err_iserr(a:syserr):c_int;

// No error occurred
inline proc ENOERR return 0:err_t;

// When err_t is no longer just int(32), will need to add cases for err_t too.
inline proc ==(a: syserr, b: syserr) return (qio_err_eq(a,b) != 0:c_int);
inline proc ==(a: syserr, b: int(32)) return (qio_err_to_int(a) == b:int(32));
inline proc ==(a: syserr, b: int(64)) return (qio_err_to_int(a) == b:int(32));
inline proc ==(a: int(32), b: syserr) return (a:int(32) == qio_err_to_int(b));
inline proc ==(a: int(64), b: syserr) return (a:int(32) == qio_err_to_int(b));
inline proc !=(a: syserr, b: syserr) return !(a == b);
inline proc !=(a: syserr, b: int(32)) return !(a == b);
inline proc !=(a: syserr, b: int(64)) return !(a == b);
inline proc !=(a: int(32), b: syserr) return !(a == b);
inline proc !=(a: int(64), b: syserr) return !(a == b);
inline proc !(a: syserr) return (qio_err_iserr(a) == 0:c_int);
inline proc _cond_test(a: syserr) return (qio_err_iserr(a) != 0:c_int);
inline proc _cast(type t, x: syserr) where t == int(32)
  return qio_err_to_int(x);
inline proc _cast(type t, x: syserr) where t == int(64)
  return qio_err_to_int(x):int(64);
inline proc _cast(type t, x: int(32)) where t == syserr
  return qio_int_to_err(x);
inline proc _cast(type t, x: int(64)) where t == syserr
  return qio_int_to_err(x:int(32));
pragma "trivial assignment"
inline proc =(ref ret:syserr, x:syserr) { __primitive("=", ret, x); }
inline proc =(ref ret:syserr, x:int(32))
{ __primitive("=", ret, qio_int_to_err(x)); }
inline proc =(ref ret:syserr, x:int(64))
{ __primitive("=", ret, qio_int_to_err(x:int(32))); }
inline proc =(ref ret:err_t, x:syserr)
{ __primitive("=", ret, qio_err_to_int(x):err_t); }

// end of file
extern proc chpl_macro_int_EEOF():err_t;
inline proc EEOF return chpl_macro_int_EEOF():err_t;
extern proc chpl_macro_int_ESHORT():err_t;
inline proc ESHORT return chpl_macro_int_ESHORT():err_t;
extern proc chpl_macro_int_EFORMAT():err_t;
inline proc EFORMAT return chpl_macro_int_EFORMAT():err_t;

// system error numbers
extern const E2BIG:err_t;
extern const EACCES:err_t;
extern const EADDRINUSE:err_t;
extern const EADDRNOTAVAIL:err_t;
extern const EAFNOSUPPORT:err_t;
extern const EAGAIN:err_t;
extern const EALREADY:err_t;
extern const EBADE:err_t;
extern const EBADF:err_t;
extern const EBADFD:err_t;
extern const EBADMSG:err_t;
extern const EBADR:err_t;
extern const EBADRQC:err_t;
extern const EBADSLT:err_t;
extern const EBUSY:err_t;
extern const ECANCELED:err_t;
extern const ECHILD:err_t;
extern const ECHRNG:err_t;
extern const ECOMM:err_t;
extern const ECONNABORTED:err_t;
extern const ECONNREFUSED:err_t;
extern const ECONNRESET:err_t;
extern const EDEADLK:err_t;
extern const EDESTADDRREQ:err_t;
extern const EDOM:err_t;
extern const EDQUOT:err_t;
extern const EEXIST:err_t;
extern const EFAULT:err_t;
extern const EFBIG:err_t;
extern const EHOSTDOWN:err_t;
extern const EHOSTUNREACH:err_t;
extern const EIDRM:err_t;
extern const EILSEQ:err_t;
extern const EINPROGRESS:err_t;
extern const EINTR:err_t;
extern const EINVAL:err_t;
extern const EIO:err_t;
extern const EISCONN:err_t;
extern const EISDIR:err_t;
extern const EISNAM:err_t;
extern const EKEYEXPIRED:err_t;
extern const EKEYREJECTED:err_t;
extern const EKEYREVOKED:err_t;
extern const EL2HLT:err_t;
extern const EL2NSYNC:err_t;
extern const EL3HLT:err_t;
extern const EL3RST:err_t;
extern const ELIBACC:err_t;
extern const ELIBBAD:err_t;
extern const ELIBMAX:err_t;
extern const ELIBSCN:err_t;
extern const ELIBEXEC:err_t;
extern const ELOOP:err_t;
extern const EMEDIUMTYPE:err_t;
extern const EMFILE:err_t;
extern const EMLINK:err_t;
extern const EMSGSIZE:err_t;
extern const EMULTIHOP:err_t;
extern const ENAMETOOLONG:err_t;
extern const ENETDOWN:err_t;
extern const ENETRESET:err_t;
extern const ENETUNREACH:err_t;
extern const ENFILE:err_t;
extern const ENOBUFS:err_t;
extern const ENODATA:err_t;
extern const ENODEV:err_t;
extern const ENOENT:err_t;
extern const ENOEXEC:err_t;
extern const ENOKEY:err_t;
extern const ENOLCK:err_t;
extern const ENOLINK:err_t;
extern const ENOMEDIUM:err_t;
extern const ENOMEM:err_t;
extern const ENOMSG:err_t;
extern const ENONET:err_t;
extern const ENOPKG:err_t;
extern const ENOPROTOOPT:err_t;
extern const ENOSPC:err_t;
extern const ENOSR:err_t;
extern const ENOSTR:err_t;
extern const ENOSYS:err_t;
extern const ENOTBLK:err_t;
extern const ENOTCONN:err_t;
extern const ENOTDIR:err_t;
extern const ENOTEMPTY:err_t;
extern const ENOTSOCK:err_t;
extern const ENOTSUP:err_t;
extern const ENOTTY:err_t;
extern const ENOTUNIQ:err_t;
extern const ENXIO:err_t;
extern const EOPNOTSUPP:err_t;
extern const EOVERFLOW:err_t;
extern const EPERM:err_t;
extern const EPFNOSUPPORT:err_t;
extern const EPIPE:err_t;
extern const EPROTO:err_t;
extern const EPROTONOSUPPORT:err_t;
extern const EPROTOTYPE:err_t;
extern const ERANGE:err_t;
extern const EREMCHG:err_t;
extern const EREMOTE:err_t;
extern const EREMOTEIO:err_t;
extern const ERESTART:err_t;
extern const EROFS:err_t;
extern const ESHUTDOWN:err_t;
extern const ESPIPE:err_t;
extern const ESOCKTNOSUPPORT:err_t;
extern const ESRCH:err_t;
extern const ESTALE:err_t;
extern const ESTRPIPE:err_t;
extern const ETIME:err_t;
extern const ETIMEDOUT:err_t;
extern const ETXTBSY:err_t;
extern const EUCLEAN:err_t;
extern const EUNATCH:err_t;
extern const EUSERS:err_t;
extern const EWOULDBLOCK:err_t;
extern const EXDEV:err_t;
extern const EXFULL:err_t;

/*
 * 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.
 */

/* BASIC TYPES */
use SysCTypes;

extern type c_float = real(32);
extern type c_double = real(64);
/*extern type c_wchar_t = uint(32); */
extern type off_t = int(64);
extern type mode_t = uint(32);
extern type socklen_t = int(32);

// C File type
//type c_file = _file;

// stdin/stdout/sterr
//extern proc chpl_cstdin():_file;
extern proc chpl_cstdout():_file;
extern proc chpl_cstderr():_file;
extern proc chpl_cnullfile():_file;

// system error number.
extern type syserr; // = c_int, opaque so we can manually override ==,!=,etc
extern type err_t = c_int;
// When to use syserr and when to use err_t?
// err_t is a system error code (a c_int by a nicer name).
// syserr is an enhanced error that might also include an
// error message. All user-facing Chapel library code,
// or user Chapel code, should generally use syserr.
// When wrapping functions or declaring them in C,
// use err_t to indicate that a function is returning
// an error code.

// system file descriptor.
extern type fd_t = c_int;

// NULL
extern const c_nil:c_void_ptr;
// To generate legal C prototypes, we have to manually instantiate this
// prototype for each pointer type that might be associated with 'x'.
pragma "no prototype"
extern proc is_c_nil(x):bool;

// local C pointer class used in C integration.
// Similar to _ddata from ChapelBase, but differs
// from _ddata because it can never be wide.
pragma "data class"
pragma "no object"
pragma "no default functions"
pragma "no wide class"
class c_ptr {
  type eltType;
  inline proc this(i: integral) ref {
    return __primitive("array_get", this, i);
  }
  inline proc deref() ref {
    return __primitive("array_get", this, 0);
  }
}

inline proc =(ref a:c_ptr, b:c_ptr) { __primitive("=", a, b); }

inline proc =(ref a:c_ptr, b:_nilType) { __primitive("=", a, nil); }

inline proc _cast(type t, x) where t:c_ptr && x:_nilType {
  return __primitive("cast", t, x);
}
inline proc _cast(type t, x) where t:c_ptr && x.type:c_ptr {
  return __primitive("cast", t, x);
}
inline proc _cast(type t, x) where t:c_void_ptr && x.type:c_ptr {
  return __primitive("cast", t, x);
}

inline proc c_calloc(type eltType, size: integral) {
  var ret:c_ptr(eltType);
  __primitive("array_alloc", ret, eltType, size);
  init_elts(ret, size, eltType);
  return ret;
}

inline proc c_free(data: c_ptr) {
  __primitive("array_free", data);
}

inline proc ==(a: c_ptr, b: c_ptr) where a.eltType == b.eltType {
  return __primitive("ptr_eq", a, b);
}
inline proc ==(a: c_ptr, b: _nilType) {
  return __primitive("ptr_eq", a, nil);
}
inline proc ==(a: _nilType, b: c_ptr) {
  return __primitive("ptr_eq", nil, b);
}

inline proc !=(a: c_ptr, b: c_ptr) where a.eltType == b.eltType {
  return __primitive("ptr_neq", a, b);
}
inline proc !=(a: c_ptr, b: _nilType) {
  return __primitive("ptr_neq", a, nil);
}
inline proc !=(a: _nilType, b: c_ptr) {
  return __primitive("ptr_neq", nil, b);
}

inline proc _cond_test(x: c_ptr) return x != nil;

inline proc !(x: c_ptr) return x == nil;
extern proc c_pointer_return(ref x:?t):c_ptr(t);

inline proc c_ptrTo(arr: []) where isRectangularArr(arr) && arr.rank == 1 {
  return c_pointer_return(arr[arr.domain.low]);
}
inline proc c_ptrTo(ref x:?t):c_ptr(t)
{
  if isArrayType(t) then
    compilerError("c_ptrTo unsupported array type");
  if isDomainType(t) then
    compilerError("c_ptrTo domain type not supported");
  // Other cases should be avoided, e.g. sync vars
  return c_pointer_return(x);
}

// error numbers

extern proc qio_err_eq(a:syserr, b:syserr):c_int;
extern proc qio_err_to_int(a:syserr):int(32);
extern proc qio_int_to_err(a:int(32)):syserr;
extern proc qio_err_iserr(a:syserr):c_int;

inline proc ENOERR return 0:err_t;

// When err_t is no longer just int(32), will need to add cases for err_t too.
inline proc ==(a: syserr, b: syserr) return (qio_err_eq(a,b) != 0:c_int);
inline proc ==(a: syserr, b: int(32)) return (qio_err_to_int(a) == b:int(32));
inline proc ==(a: syserr, b: int(64)) return (qio_err_to_int(a) == b:int(32));
inline proc ==(a: int(32), b: syserr) return (a:int(32) == qio_err_to_int(b));
inline proc ==(a: int(64), b: syserr) return (a:int(32) == qio_err_to_int(b));
inline proc !=(a: syserr, b: syserr) return !(a == b);
inline proc !=(a: syserr, b: int(32)) return !(a == b);
inline proc !=(a: syserr, b: int(64)) return !(a == b);
inline proc !=(a: int(32), b: syserr) return !(a == b);
inline proc !=(a: int(64), b: syserr) return !(a == b);
inline proc !(a: syserr) return (qio_err_iserr(a) == 0:c_int);
inline proc _cond_test(a: syserr) return (qio_err_iserr(a) != 0:c_int);
inline proc _cast(type t, x: syserr) where t == int(32)
  return qio_err_to_int(x);
inline proc _cast(type t, x: syserr) where t == int(64)
  return qio_err_to_int(x):int(64);
inline proc _cast(type t, x: int(32)) where t == syserr
  return qio_int_to_err(x);
inline proc _cast(type t, x: int(64)) where t == syserr
  return qio_int_to_err(x:int(32));
pragma "trivial assignment"
inline proc =(ref ret:syserr, x:syserr) { __primitive("=", ret, x); }
inline proc =(ref ret:syserr, x:int(32))
{ __primitive("=", ret, qio_int_to_err(x)); }
inline proc =(ref ret:syserr, x:int(64))
{ __primitive("=", ret, qio_int_to_err(x:int(32))); }
inline proc =(ref ret:err_t, x:syserr)
{ __primitive("=", ret, qio_err_to_int(x):err_t); }

// end of file
extern proc chpl_macro_int_EEOF():err_t;
inline proc EEOF return chpl_macro_int_EEOF():err_t;
extern proc chpl_macro_int_ESHORT():err_t;
inline proc ESHORT return chpl_macro_int_ESHORT():err_t;
extern proc chpl_macro_int_EFORMAT():err_t;
inline proc EFORMAT return chpl_macro_int_EFORMAT():err_t;

// system error numbers
extern const E2BIG:err_t;
extern const EACCES:err_t;
extern const EADDRINUSE:err_t;
extern const EADDRNOTAVAIL:err_t;
extern const EAFNOSUPPORT:err_t;
extern const EAGAIN:err_t;
extern const EALREADY:err_t;
extern const EBADE:err_t;
extern const EBADF:err_t;
extern const EBADFD:err_t;
extern const EBADMSG:err_t;
extern const EBADR:err_t;
extern const EBADRQC:err_t;
extern const EBADSLT:err_t;
extern const EBUSY:err_t;
extern const ECANCELED:err_t;
extern const ECHILD:err_t;
extern const ECHRNG:err_t;
extern const ECOMM:err_t;
extern const ECONNABORTED:err_t;
extern const ECONNREFUSED:err_t;
extern const ECONNRESET:err_t;
extern const EDEADLK:err_t;
extern const EDESTADDRREQ:err_t;
extern const EDOM:err_t;
extern const EDQUOT:err_t;
extern const EEXIST:err_t;
extern const EFAULT:err_t;
extern const EFBIG:err_t;
extern const EHOSTDOWN:err_t;
extern const EHOSTUNREACH:err_t;
extern const EIDRM:err_t;
extern const EILSEQ:err_t;
extern const EINPROGRESS:err_t;
extern const EINTR:err_t;
extern const EINVAL:err_t;
extern const EIO:err_t;
extern const EISCONN:err_t;
extern const EISDIR:err_t;
extern const EISNAM:err_t;
extern const EKEYEXPIRED:err_t;
extern const EKEYREJECTED:err_t;
extern const EKEYREVOKED:err_t;
extern const EL2HLT:err_t;
extern const EL2NSYNC:err_t;
extern const EL3HLT:err_t;
extern const EL3RST:err_t;
extern const ELIBACC:err_t;
extern const ELIBBAD:err_t;
extern const ELIBMAX:err_t;
extern const ELIBSCN:err_t;
extern const ELIBEXEC:err_t;
extern const ELOOP:err_t;
extern const EMEDIUMTYPE:err_t;
extern const EMFILE:err_t;
extern const EMLINK:err_t;
extern const EMSGSIZE:err_t;
extern const EMULTIHOP:err_t;
extern const ENAMETOOLONG:err_t;
extern const ENETDOWN:err_t;
extern const ENETRESET:err_t;
extern const ENETUNREACH:err_t;
extern const ENFILE:err_t;
extern const ENOBUFS:err_t;
extern const ENODATA:err_t;
extern const ENODEV:err_t;
extern const ENOENT:err_t;
extern const ENOEXEC:err_t;
extern const ENOKEY:err_t;
extern const ENOLCK:err_t;
extern const ENOLINK:err_t;
extern const ENOMEDIUM:err_t;
extern const ENOMEM:err_t;
extern const ENOMSG:err_t;
extern const ENONET:err_t;
extern const ENOPKG:err_t;
extern const ENOPROTOOPT:err_t;
extern const ENOSPC:err_t;
extern const ENOSR:err_t;
extern const ENOSTR:err_t;
extern const ENOSYS:err_t;
extern const ENOTBLK:err_t;
extern const ENOTCONN:err_t;
extern const ENOTDIR:err_t;
extern const ENOTEMPTY:err_t;
extern const ENOTSOCK:err_t;
extern const ENOTSUP:err_t;
extern const ENOTTY:err_t;
extern const ENOTUNIQ:err_t;
extern const ENXIO:err_t;
extern const EOPNOTSUPP:err_t;
extern const EOVERFLOW:err_t;
extern const EPERM:err_t;
extern const EPFNOSUPPORT:err_t;
extern const EPIPE:err_t;
extern const EPROTO:err_t;
extern const EPROTONOSUPPORT:err_t;
extern const EPROTOTYPE:err_t;
extern const ERANGE:err_t;
extern const EREMCHG:err_t;
extern const EREMOTE:err_t;
extern const EREMOTEIO:err_t;
extern const ERESTART:err_t;
extern const EROFS:err_t;
extern const ESHUTDOWN:err_t;
extern const ESPIPE:err_t;
extern const ESOCKTNOSUPPORT:err_t;
extern const ESRCH:err_t;
extern const ESTALE:err_t;
extern const ESTRPIPE:err_t;
extern const ETIME:err_t;
extern const ETIMEDOUT:err_t;
extern const ETXTBSY:err_t;
extern const EUCLEAN:err_t;
extern const EUNATCH:err_t;
extern const EUSERS:err_t;
extern const EWOULDBLOCK:err_t;
extern const EXDEV:err_t;
extern const EXFULL:err_t;


Changed default value for "shift" so that it will not result in a
runtime error for Block distribution (bounding box values out of index
type bounds).

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

use driver;
config const shift = o5-1;

const TDom1D: domain(1) distributed Dist1D = Space1 - (shift);
const TDom2D: domain(2) distributed Dist2D = Space2 - (shift,shift);
const TDom3D: domain(3) distributed Dist3D = Space3 - (shift,shift,shift);
const TDom4D: domain(4) distributed Dist4D = Space4 - (shift,shift,shift,shift);
const TDom2D64: domain(2,int(64)) distributed Dist2D64 = Space2D64 - (shift:int(64),shift:int(64));

var TA1D: [TDom1D] int;
var TA2D: [TDom2D] int;
var TA3D: [TDom3D] int;
var TA4D: [TDom4D] int;
var TA2D64: [TDom2D64] int;

const TD1D: domain(1) = Space1 - (o5);
const TD2D: domain(2) = Space2 - (o5,o5);
const TD3D: domain(3) = Space3 - (o5,o5,o5);
const TD4D: domain(4) = Space4 - (o5,o5,o5,o5);
const TD2D64: domain(2,int(64)) = Space2D64 - (o5:int(64),o5:int(64));

def foo(TD: domain, A: [TD] int, TA) {
  var errs = 0;
  var offset = if (TD.rank==1) then o5-shift else fill(TD.rank, o5-shift);
  for i in [TD] do
    if A[i].locale != TA[i+offset].locale {
      writeln("A[",i,"] Incorrect reindex");
      errs += 1;
    }
  return errs;
}

for e in TA1D do e = next();
writeln("TA1D: ", foo(TD1D, TA1D, TA1D), " errors");

for e in TA2D do e = next();
writeln("TA2D: ", foo(TD2D, TA2D, TA2D), " errors");

for e in TA3D do e = next();
writeln("TA3D: ", foo(TD3D, TA3D, TA3D), " errors");

for e in TA4D do e = next();
writeln("TA4D: ", foo(TD4D, TA4D, TA4D), " errors");

for e in TA2D64 do e = next();
writeln("TA2D64: ", foo(TD2D64, TA2D64, TA2D64), " errors");

use driver;
config const shift = o5+66;

const TDom1D: domain(1) distributed Dist1D = Space1 - (shift);
const TDom2D: domain(2) distributed Dist2D = Space2 - (shift,shift);
const TDom3D: domain(3) distributed Dist3D = Space3 - (shift,shift,shift);
const TDom4D: domain(4) distributed Dist4D = Space4 - (shift,shift,shift,shift);
const TDom2D64: domain(2,int(64)) distributed Dist2D64 = Space2D64 - (shift:int(64),shift:int(64));

var TA1D: [TDom1D] int;
var TA2D: [TDom2D] int;
var TA3D: [TDom3D] int;
var TA4D: [TDom4D] int;
var TA2D64: [TDom2D64] int;

const TD1D: domain(1) = Space1 - (o5);
const TD2D: domain(2) = Space2 - (o5,o5);
const TD3D: domain(3) = Space3 - (o5,o5,o5);
const TD4D: domain(4) = Space4 - (o5,o5,o5,o5);
const TD2D64: domain(2,int(64)) = Space2D64 - (o5:int(64),o5:int(64));

def foo(TD: domain, A: [TD] int, TA) {
  var errs = 0;
  var offset = if (TD.rank==1) then o5-shift else fill(TD.rank, o5-shift);
  for i in [TD] do
    if A[i].locale != TA[i+offset].locale {
      writeln("A[",i,"] Incorrect reindex");
      errs += 1;
    }
  return errs;
}

for e in TA1D do e = next();
writeln("TA1D: ", foo(TD1D, TA1D, TA1D), " errors");

for e in TA2D do e = next();
writeln("TA2D: ", foo(TD2D, TA2D, TA2D), " errors");

for e in TA3D do e = next();
writeln("TA3D: ", foo(TD3D, TA3D, TA3D), " errors");

for e in TA4D do e = next();
writeln("TA4D: ", foo(TD4D, TA4D, TA4D), " errors");

for e in TA2D64 do e = next();
writeln("TA2D64: ", foo(TD2D64, TA2D64, TA2D64), " errors");