Fixing some missing inout cases that I noticed in preparing slides for Don

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

type  c_int =  int(32),
     c_uint = uint(32),
       long =  int(64),
      c_ulong = uint(64);

_extern type __mpf_struct;
_extern type mpf_t = 1*__mpf_struct;
_extern type __mpz_struct;
_extern type mpz_t = 1*__mpz_struct;

_extern def mpz_init(inout X: mpz_t);
_extern def mpz_set_ui(inout ROP: mpz_t, OP: c_ulong);
_extern def mpz_mul_ui(inout ROP: mpz_t, inout OP1: mpz_t, OP2: c_ulong);
_extern def mpz_add_ui(inout ROP: mpz_t, inout OP1: mpz_t, OP2: c_ulong);
_extern def mpz_mul(inout ROP: mpz_t, inout OP1: mpz_t, inout OP2: mpz_t);
_extern def mpz_neg(inout ROP: mpz_t, inout OP: mpz_t);
_extern def mpz_clear(inout X: mpz_t);
_extern def mpz_tdiv_q(inout Q: mpz_t, inout N: mpz_t, inout D: mpz_t);
_extern def mpz_add(inout ROP: mpz_t, inout OP1: mpz_t, inout OP2: mpz_t);

_extern type mp_bitcnt_t = c_ulong;
_extern type size_t = int(64);

_extern def mpf_set_default_prec(PREC: mp_bitcnt_t);
_extern def mpz_sizeinbase(inout OP: mpz_t, BASE: c_int): size_t;

_extern def mpz_addmul_ui(inout ROP: mpz_t, inout OP1: mpz_t, OPT2: c_ulong);

_extern type double = real(64);

_extern def mpf_init(inout X: mpf_t);
_extern def mpf_set_z(inout ROP: mpf_t, inout OP: mpz_t);
_extern def mpf_get_prec(inout OP: mpf_t): mp_bitcnt_t;
_extern def mpf_get_d(inout OP: mpf_t): double;
_extern def mpf_set_d(inout ROP: mpf_t, OP: double);
_extern def mpf_set_prec_raw(inout ROP: mpf_t, PREC: mp_bitcnt_t);
_extern def mpf_ui_div(inout ROP: mpf_t, OP1: c_ulong, inout OP2: mpf_t);
_extern def mpf_mul(inout ROP: mpf_t, inout OP1: mpf_t, inout OP2: mpf_t);
_extern def mpf_ui_sub(inout ROP: mpf_t, OP1: c_ulong, inout OP2: mpf_t);
_extern def mpf_add(inout ROP: mpf_t, inout OP1: mpf_t, inout OP2: mpf_t);
_extern def mpf_sub(inout ROP: mpf_t, inout OP1: mpf_t, inout OP2: mpf_t);
_extern def mpf_mul_ui(inout ROP: mpf_t, inout OP1: mpf_t, OP2: c_ulong);
_extern def mpf_div_2exp(inout ROP: mpf_t, inout OP1: mpf_t, OP2: mp_bitcnt_t);
_extern def mpf_out_str(STREAM: _file, BASE: c_int, N_DIGITS: size_t, inout OP: mpf_t);
_extern def mpf_clear(inout X: mpf_t);

_extern def gmp_printf(fmt: string, arg...);
_extern def gmp_fprintf(fp: _file, fmt: string, arg...);

type  c_int =  int(32),
     c_uint = uint(32),
       long =  int(64),
      c_ulong = uint(64);

_extern type __mpf_struct;
_extern type mpf_t = 1*__mpf_struct;
_extern type __mpz_struct;
_extern type mpz_t = 1*__mpz_struct;

_extern def mpz_init(inout X: mpz_t);
_extern def mpz_set_ui(inout ROP: mpz_t, OP: c_ulong);
_extern def mpz_mul_ui(inout ROP: mpz_t, inout OP1: mpz_t, OP2: c_ulong);
_extern def mpz_add_ui(inout ROP: mpz_t, inout OP1: mpz_t, OP2: c_ulong);
_extern def mpz_mul(inout ROP: mpz_t, inout OP1: mpz_t, OP2: mpz_t);
_extern def mpz_neg(inout ROP: mpz_t, inout OP: mpz_t);
_extern def mpz_clear(inout X: mpz_t);
_extern def mpz_tdiv_q(inout Q: mpz_t, inout N: mpz_t, inout D: mpz_t);
_extern def mpz_add(inout ROP: mpz_t, inout OP1: mpz_t, inout OP2: mpz_t);

_extern type mp_bitcnt_t = c_ulong;
_extern type size_t = int(64);

_extern def mpf_set_default_prec(PREC: mp_bitcnt_t);
_extern def mpz_sizeinbase(inout OP: mpz_t, BASE: c_int): size_t;

_extern def mpz_addmul_ui(inout ROP: mpz_t, inout OP1: mpz_t, OPT2: c_ulong);

_extern type double = real(64);

_extern def mpf_init(inout X: mpf_t);
_extern def mpf_set_z(inout ROP: mpf_t, OP: mpz_t);
_extern def mpf_get_prec(inout OP: mpf_t): mp_bitcnt_t;
_extern def mpf_get_d(inout OP: mpf_t): double;
_extern def mpf_set_d(inout ROP: mpf_t, OP: double);
_extern def mpf_set_prec_raw(inout ROP: mpf_t, PREC: mp_bitcnt_t);
_extern def mpf_ui_div(inout ROP: mpf_t, OP1: c_ulong, inout OP2: mpf_t);
_extern def mpf_mul(inout ROP: mpf_t, inout OP1: mpf_t, inout OP2: mpf_t);
_extern def mpf_ui_sub(inout ROP: mpf_t, OP1: c_ulong, inout OP2: mpf_t);
_extern def mpf_add(inout ROP: mpf_t, inout OP1: mpf_t, inout OP2: mpf_t);
_extern def mpf_sub(inout ROP: mpf_t, inout OP1: mpf_t, inout OP2: mpf_t);
_extern def mpf_mul_ui(inout ROP: mpf_t, inout OP1: mpf_t, OP2: c_ulong);
_extern def mpf_div_2exp(inout ROP: mpf_t, inout OP1: mpf_t, OP2: mp_bitcnt_t);
_extern def mpf_out_str(STREAM: _file, BASE: c_int, N_DIGITS: size_t, inout OP: mpf_t);
_extern def mpf_clear(inout X: mpf_t);

_extern def gmp_printf(fmt: string, arg...);
_extern def gmp_fprintf(fp: _file, fmt: string, arg...);


Fixed flag error in test.

Fixed flag error in test.

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

config param rank = 1;
config param debug = false;
config param doVerboseComm = false;
config type myType = int;

config param doBlock = true;
config param doCyclic = true;
config param doBlockCyclic = false;

config const doLocal = false;

use BlockDist;
use CyclicDist;
use BlockCycDist;

// Stole this from the setupTargetLocalesArray()
const factors = _factor(rank, numLocales);
var ranges: rank*range;
for param i in 1..rank do
  ranges(i) = 0..#factors(i);
const D = {(...ranges)};

proc printCommDiagnosticsHere(s) {
  printCommDiagnostics(here.id, s);
}
proc printCommDiagnostics(id, s) {
  var diagnostics = getCommDiagnostics()(id);
  writeln(s, "(Locale", id, "): gets: ", diagnostics.get);
  writeln(s, "(Locale", id, "): puts: ", diagnostics.put);
  writeln(s, "(Locale", id, "): forks: ", diagnostics.fork);
  writeln(s, "(Locale", id, "): fast forks: ", diagnostics.fork_fast);
  writeln(s, "(Locale", id, "): nb forks: ", diagnostics.fork_nb);
}

proc nextN() return (here.id+1)%numLocales;
proc prevN() return (here.id+numLocales-1)%numLocales;

proc getIdx(loc) {
  if rank==1 {
    if debug then writeln("getIdx: ", loc, "=>", loc);
    return loc;
  } else {
    var dims = D.dims(); // assume zero-based in all dimensions
    var idx: rank*D._value.idxType;
    var cur = loc;
    for param i in 1..rank by -1 {
      if dims(i).high!= 0 {
        idx(i) = cur%(dims(i).high+1);
        cur /= dims(i).high+1;
      }
    }
    if debug then writeln("getIdx: ", loc, "=>", idx);
    return idx;
  }
}

proc doit(D, str) {
  var A: [D] myType;
  const s = "["+rank+"D "+str+"]";
  if debug then [i in D] writeln("A[", i, "] is on ", A[i].locale);

  for l in Locales {
    A = [i in D] -here.id;
    on l {
      if debug then writeln("on ", here, ":");
      var hereId = here.id;
      var hereIdx = getIdx(hereId);
      var nextId = nextN();
      var nextIdx = getIdx(nextId);
      var prevId = prevN();
      var prevIdx = getIdx(prevId);
      if doLocal {
        if doVerboseComm then startVerboseCommHere();
        resetCommDiagnosticsHere();
        startCommDiagnosticsHere();
        const c = A[hereIdx];
        stopCommDiagnosticsHere();
        if doVerboseComm then stopVerboseCommHere();
        printCommDiagnosticsHere(s+" Local read  ");
        if debug then writeln("hereId=", hereId, "c=", c);
      }

      if doVerboseComm then startVerboseCommHere();
      resetCommDiagnosticsHere();
      startCommDiagnosticsHere();
      const c = A[nextIdx];
      stopCommDiagnosticsHere();
      if doVerboseComm then stopVerboseCommHere();
      printCommDiagnosticsHere(s+" Remote read ");
      if debug then writeln("nextId=", nextId, " c=", c);

      if doLocal {
        if doVerboseComm then startVerboseCommHere();
        resetCommDiagnosticsHere();
        startCommDiagnosticsHere();
        A[hereIdx] = hereId;
        stopCommDiagnosticsHere();
        if doVerboseComm then stopVerboseCommHere();
        printCommDiagnosticsHere(s+" Local write ");
        if debug then writeln("hereId=", hereId,
                              " A[", hereIdx, "]=", A[hereIdx]);
      }

      if doVerboseComm then startVerboseCommHere();
      resetCommDiagnosticsHere();
      startCommDiagnosticsHere();
      A[prevIdx] = prevId;
      stopCommDiagnosticsHere();
      if doVerboseComm then stopVerboseCommHere();
      printCommDiagnosticsHere(s+" Remote write ");
      if debug then writeln("prevId=", prevId,
                            " A[", prevIdx, "]=", A[prevIdx]);
    }
    if debug then writeln(A);
  }
}

proc fillIt(stuff: ?stuffType) {
  var t: rank*stuffType;
  for param i in 1..rank do
    t(i) = stuff;
  return t;
}

const zeroT = fillIt(0);
const oneT = fillIt(1);

proc main() {
  writeln(rank, " dimensional array of ", typeToString(myType));

  if doBlock {
    writeln();
    const bD: domain(rank) dmapped new dmap (new Block(boundingBox=D)) = D;
    doit(bD, "Block");
  }

  if doCyclic {
    writeln();
    const cD: domain(rank) dmapped new dmap (new Cyclic(startIdx=zeroT)) = D;
    doit(cD, "Cyclic");
  }

  if doBlockCyclic {
    writeln();
    const bcD: domain(rank) dmapped new dmap (new BlockCyclic(rank=rank,idxType=int,startIdx=zeroT,blocksize=oneT)) = D;
    doit(bcD, "BlockCyclic");
  }

}

config param rank = 1;
config param debug = false;
config param doVerboseComm = false;
config type myType = int;

config param doBlock = true;
config param doCyclic = true;
config param doBlockCyclic = false;

config const doLocal = false;

use BlockDist;
use CyclicDist;
use BlockCycDist;

// Stole this from the setupTargetLocalesArray()
const factors = _factor(rank, numLocales);
var ranges: rank*range;
for param i in 1..rank do
  ranges(i) = 0..#factors(i);
const D = {(...ranges)};

proc printCommDiagnosticsHere(s) {
  printCommDiagnostics(here.id, s);
}
proc printCommDiagnostics(id, s) {
  var diagnostics = getCommDiagnostics()(id);
  writeln(s, "(Locale", id, "): gets: ", diagnostics.get);
  writeln(s, "(Locale", id, "): puts: ", diagnostics.put);
  writeln(s, "(Locale", id, "): forks: ", diagnostics.fork);
  writeln(s, "(Locale", id, "): fast forks: ", diagnostics.fork_fast);
  writeln(s, "(Locale", id, "): nb forks: ", diagnostics.fork_nb);
}

proc nextN() return (here.id+1)%numLocales;
proc prevN() return (here.id+numLocales-1)%numLocales;

proc getIdx(loc) {
  if rank==1 {
    if debug then writeln("getIdx: ", loc, "=>", loc);
    return loc;
  } else {
    var dims = D.dims(); // assume zero-based in all dimensions
    var idx: rank*D._value.idxType;
    var cur = loc;
    for param i in 1..rank by -1 {
      if dims(i).high!= 0 {
        idx(i) = cur%(dims(i).high+1);
        cur /= dims(i).high+1;
      }
    }
    if debug then writeln("getIdx: ", loc, "=>", idx);
    return idx;
  }
}

proc doit(D, str) {
  var A: [D] myType;
  const s = "["+rank+"D "+str+"]";
  if debug then [i in D] writeln("A[", i, "] is on ", A[i].locale);

  for l in Locales {
    A = [i in D] -here.id;
    on l {
      if debug then writeln("on ", here, ":");
      var hereId = here.id;
      var hereIdx = getIdx(hereId);
      var nextId = nextN();
      var nextIdx = getIdx(nextId);
      var prevId = prevN();
      var prevIdx = getIdx(prevId);
      if doLocal {
        if doVerboseComm then startVerboseCommHere();
        resetCommDiagnosticsHere();
        startCommDiagnosticsHere();
        const c = A[hereIdx];
        stopCommDiagnosticsHere();
        if doVerboseComm then stopVerboseCommHere();
        printCommDiagnosticsHere(s+" Local read  ");
        if debug then writeln("hereId=", hereId, "c=", c);
      }

      if doVerboseComm then startVerboseCommHere();
      resetCommDiagnosticsHere();
      startCommDiagnosticsHere();
      const c = A[nextIdx];
      stopCommDiagnosticsHere();
      if doVerboseComm then stopVerboseCommHere();
      printCommDiagnosticsHere(s+" Remote read ");
      if debug then writeln("nextId=", nextId, " c=", c);

      if doLocal {
        if doVerboseComm then startVerboseCommHere();
        resetCommDiagnosticsHere();
        startCommDiagnosticsHere();
        A[hereIdx] = hereId;
        stopCommDiagnosticsHere();
        if doVerboseComm then stopVerboseCommHere();
        printCommDiagnosticsHere(s+" Local write ");
        if debug then writeln("hereId=", hereId,
                              " A[", hereIdx, "]=", A[hereIdx]);
      }

      if doVerboseComm then startVerboseCommHere();
      resetCommDiagnosticsHere();
      startCommDiagnosticsHere();
      A[prevIdx] = prevId;
      stopCommDiagnosticsHere();
      if doVerboseComm then stopVerboseCommHere();
      printCommDiagnosticsHere(s+" Remote write ");
      if debug then writeln("prevId=", prevId,
                            " A[", prevIdx, "]=", A[prevIdx]);
    }
    if debug then writeln(A);
  }
}

proc fillIt(stuff: ?stuffType) {
  var t: rank*stuffType;
  for param i in 1..rank do
    t(i) = stuff;
  return t;
}

const zeroT = fillIt(0);
const oneT = fillIt(1);

proc main() {
  writeln(rank, " dimensional array of ", typeToString(myType));

  if doCyclic {
    writeln();
    const bD: domain(rank) dmapped new dmap (new Block(boundingBox=D)) = D;
    doit(bD, "Block");
  }

  if doCyclic {
    writeln();
    const cD: domain(rank) dmapped new dmap (new Cyclic(startIdx=zeroT)) = D;
    doit(cD, "Cyclic");
  }

  if doBlockCyclic {
    writeln();
    const bcD: domain(rank) dmapped new dmap (new BlockCyclic(rank=rank,idxType=int,startIdx=zeroT,blocksize=oneT)) = D;
    doit(bcD, "BlockCyclic");
  }

}


The callStackSize method for locales should return the call stack size
of the locale it is applied to, because as of r18427 the reported call
stack size could conceivably vary from locale to locale.

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

use DefaultRectangular;

class locale {
  const myRealm: realm;
  const chpl_id: int;
  const chpl_uid: int;
  const myNumCores: int;

  proc locale(r: realm = nil, id = -1, uid = -1,
             numCores = __primitive("chpl_coresPerLocale")) {
    if doneCreatingLocales {
      halt("locales cannot be created");
    }
    myRealm = r;
    chpl_id = id;
    chpl_uid = uid;
    myNumCores = numCores;
  }

  proc id {
    return chpl_id;
  }

  proc uid {
    return chpl_uid;
  }

  proc name {
    var locName: string;
    on this do locName = __primitive("chpl_localeName");
    return locName;
  }

  proc callStackSize: uint(64) {
    // Locales may have differing call stack sizes.
    _extern proc chpl_task_getCallStackSize(): uint(64);
    var retval: uint(64);
    on this do retval = chpl_task_getCallStackSize();
    return retval;
  }

  proc writeThis(f: Writer) {
    if (numRealms == 1) {
      f.write("LOCALE", id);
    } else {
      f.write("LOCALE", myRealm.id, "-", id);
    }
  }
}

proc chpl_setupLocale(uid) {
  var tmp: locale;
  on __primitive("chpl_on_locale_num", uid) {
    tmp = new locale(uid=uid);
    _here = tmp;
    if (defaultDist._value == nil) {
      defaultDist = new dmap(new DefaultDist());
    }
  }
  return tmp;
}

proc locale.numCores {
  return myNumCores;
}

proc chpl_int_to_locale(in id) {
  for r in Realms {
    if id < r.numLocales then
      return r.Locales[id];
    id -= r.numLocales;
  }
  halt("id out of range in chpl_int_to_locale()");
  return Realms[0].Locales[0];
}

proc locale.totalThreads() {
  var totalThreads: uint;

  on this do totalThreads = __primitive("chpl_numThreads");

  return totalThreads;
}

proc locale.idleThreads() {
  var idleThreads: uint;

  on this do idleThreads = __primitive("chpl_numIdleThreads");

  return idleThreads;
}

proc locale.queuedTasks() {
  var queuedTasks: uint;

  on this do queuedTasks = __primitive("chpl_numQueuedTasks");

  return queuedTasks;
}

proc locale.runningTasks() {
  var numTasks: uint;

  on this do numTasks = __primitive("chpl_numRunningTasks");

  return numTasks;
}

proc locale.blockedTasks() {
  var blockedTasks: int;

  on this do blockedTasks = __primitive("chpl_numBlockedTasks");

  return blockedTasks;
}

//
// multi-locale diagnostics/debugging support
//
_extern proc chpl_startVerboseComm();
_extern proc chpl_stopVerboseComm();
_extern proc chpl_startVerboseCommHere();
_extern proc chpl_stopVerboseCommHere();
_extern proc chpl_startCommDiagnostics();
_extern proc chpl_stopCommDiagnostics();
_extern proc chpl_startCommDiagnosticsHere();
_extern proc chpl_stopCommDiagnosticsHere();

proc startVerboseComm() { chpl_startVerboseComm(); }
proc stopVerboseComm() { chpl_stopVerboseComm(); }
proc startVerboseCommHere() { chpl_startVerboseCommHere(); }
proc stopVerboseCommHere() { chpl_stopVerboseCommHere(); }

proc startCommDiagnostics() { chpl_startCommDiagnostics(); }
proc stopCommDiagnostics() { chpl_stopCommDiagnostics(); }
proc startCommDiagnosticsHere() { chpl_startCommDiagnosticsHere(); }
proc stopCommDiagnosticsHere() { chpl_stopCommDiagnosticsHere(); }

// TODO: generalize this for multiple realms by returning a manhattan
// array
_extern proc chpl_numCommGets(): int(32);
_extern proc chpl_numCommPuts(): int(32);
_extern proc chpl_numCommForks(): int(32);
_extern proc chpl_numCommFastForks(): int(32);
_extern proc chpl_numCommNBForks(): int(32);

proc getCommDiagnostics(realmID: int(32) = 0) {
  var D: [Realms(realmID).LocaleSpace] 5*int;
  const r = Realms(realmID);
  for loc in r.Locales do on loc {
    const gets = chpl_numCommGets();
    const puts = chpl_numCommPuts();
    const forks = chpl_numCommForks();
    const fforks = chpl_numCommFastForks();
    const nbforks = chpl_numCommNBForks();
    D(loc.id) = (gets, puts, forks, fforks, nbforks);
  }
  return D;
}

config const
  memTrack: bool = false,
  memStats: bool = false,
  memLeaks: bool = false,
  memLeaksTable: bool = false,
  memMax: uint(64) = 0,
  memThreshold: uint(64) = 0,
  memLog: string = "";

pragma "no auto destroy"
config const
  memLeaksLog: string = "";

proc chpl_startTrackingMemory() {
  coforall r in Realms {
    if r.Locales(0) == here {
      coforall loc in r.Locales {
        if loc == here {
          __primitive("chpl_setMemFlags", memTrack, memStats, memLeaks, memLeaksTable, memMax, memThreshold, memLog, memLeaksLog);
        } else on loc {
            __primitive("chpl_setMemFlags", memTrack, memStats, memLeaks, memLeaksTable, memMax, memThreshold, memLog, memLeaksLog);
        }
      }
    } else {
      on r {
        coforall loc in r.Locales {
          if loc == here {
            __primitive("chpl_setMemFlags", memTrack, memStats, memLeaks, memLeaksTable, memMax, memThreshold, memLog, memLeaksLog);
          } else on loc {
              __primitive("chpl_setMemFlags", memTrack, memStats, memLeaks, memLeaksTable, memMax, memThreshold, memLog, memLeaksLog);
          }
        }
      }
    }
  }
}

use DefaultRectangular;

class locale {
  const myRealm: realm;
  const chpl_id: int;
  const chpl_uid: int;
  const myNumCores: int;

  proc locale(r: realm = nil, id = -1, uid = -1,
             numCores = __primitive("chpl_coresPerLocale")) {
    if doneCreatingLocales {
      halt("locales cannot be created");
    }
    myRealm = r;
    chpl_id = id;
    chpl_uid = uid;
    myNumCores = numCores;
  }

  proc id {
    return chpl_id;
  }

  proc uid {
    return chpl_uid;
  }

  proc name {
    var locName: string;
    on this do locName = __primitive("chpl_localeName");
    return locName;
  }

  proc callStackSize: uint(64) {
    _extern proc chpl_task_getCallStackSize(): uint(64);
    return chpl_task_getCallStackSize();
  }

  proc writeThis(f: Writer) {
    if (numRealms == 1) {
      f.write("LOCALE", id);
    } else {
      f.write("LOCALE", myRealm.id, "-", id);
    }
  }
}

proc chpl_setupLocale(uid) {
  var tmp: locale;
  on __primitive("chpl_on_locale_num", uid) {
    tmp = new locale(uid=uid);
    _here = tmp;
    if (defaultDist._value == nil) {
      defaultDist = new dmap(new DefaultDist());
    }
  }
  return tmp;
}

proc locale.numCores {
  return myNumCores;
}

proc chpl_int_to_locale(in id) {
  for r in Realms {
    if id < r.numLocales then
      return r.Locales[id];
    id -= r.numLocales;
  }
  halt("id out of range in chpl_int_to_locale()");
  return Realms[0].Locales[0];
}

proc locale.totalThreads() {
  var totalThreads: uint;

  on this do totalThreads = __primitive("chpl_numThreads");

  return totalThreads;
}

proc locale.idleThreads() {
  var idleThreads: uint;

  on this do idleThreads = __primitive("chpl_numIdleThreads");

  return idleThreads;
}

proc locale.queuedTasks() {
  var queuedTasks: uint;

  on this do queuedTasks = __primitive("chpl_numQueuedTasks");

  return queuedTasks;
}

proc locale.runningTasks() {
  var numTasks: uint;

  on this do numTasks = __primitive("chpl_numRunningTasks");

  return numTasks;
}

proc locale.blockedTasks() {
  var blockedTasks: int;

  on this do blockedTasks = __primitive("chpl_numBlockedTasks");

  return blockedTasks;
}

//
// multi-locale diagnostics/debugging support
//
_extern proc chpl_startVerboseComm();
_extern proc chpl_stopVerboseComm();
_extern proc chpl_startVerboseCommHere();
_extern proc chpl_stopVerboseCommHere();
_extern proc chpl_startCommDiagnostics();
_extern proc chpl_stopCommDiagnostics();
_extern proc chpl_startCommDiagnosticsHere();
_extern proc chpl_stopCommDiagnosticsHere();

proc startVerboseComm() { chpl_startVerboseComm(); }
proc stopVerboseComm() { chpl_stopVerboseComm(); }
proc startVerboseCommHere() { chpl_startVerboseCommHere(); }
proc stopVerboseCommHere() { chpl_stopVerboseCommHere(); }

proc startCommDiagnostics() { chpl_startCommDiagnostics(); }
proc stopCommDiagnostics() { chpl_stopCommDiagnostics(); }
proc startCommDiagnosticsHere() { chpl_startCommDiagnosticsHere(); }
proc stopCommDiagnosticsHere() { chpl_stopCommDiagnosticsHere(); }

// TODO: generalize this for multiple realms by returning a manhattan
// array
_extern proc chpl_numCommGets(): int(32);
_extern proc chpl_numCommPuts(): int(32);
_extern proc chpl_numCommForks(): int(32);
_extern proc chpl_numCommFastForks(): int(32);
_extern proc chpl_numCommNBForks(): int(32);

proc getCommDiagnostics(realmID: int(32) = 0) {
  var D: [Realms(realmID).LocaleSpace] 5*int;
  const r = Realms(realmID);
  for loc in r.Locales do on loc {
    const gets = chpl_numCommGets();
    const puts = chpl_numCommPuts();
    const forks = chpl_numCommForks();
    const fforks = chpl_numCommFastForks();
    const nbforks = chpl_numCommNBForks();
    D(loc.id) = (gets, puts, forks, fforks, nbforks);
  }
  return D;
}

config const
  memTrack: bool = false,
  memStats: bool = false,
  memLeaks: bool = false,
  memLeaksTable: bool = false,
  memMax: uint(64) = 0,
  memThreshold: uint(64) = 0,
  memLog: string = "";

pragma "no auto destroy"
config const
  memLeaksLog: string = "";

proc chpl_startTrackingMemory() {
  coforall r in Realms {
    if r.Locales(0) == here {
      coforall loc in r.Locales {
        if loc == here {
          __primitive("chpl_setMemFlags", memTrack, memStats, memLeaks, memLeaksTable, memMax, memThreshold, memLog, memLeaksLog);
        } else on loc {
            __primitive("chpl_setMemFlags", memTrack, memStats, memLeaks, memLeaksTable, memMax, memThreshold, memLog, memLeaksLog);
        }
      }
    } else {
      on r {
        coforall loc in r.Locales {
          if loc == here {
            __primitive("chpl_setMemFlags", memTrack, memStats, memLeaks, memLeaksTable, memMax, memThreshold, memLog, memLeaksLog);
          } else on loc {
              __primitive("chpl_setMemFlags", memTrack, memStats, memLeaks, memLeaksTable, memMax, memThreshold, memLog, memLeaksLog);
          }
        }
      }
    }
  }
}


Found some more cases where we'd want to use 'ref' declarations in this future

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


make fanout direct

make fanout direct

use Common, Logging, IO, Partitions;

config const buffersize = 1024;
config const dir_prefix = "/ssd/words";
config const use_partition_in_name: bool = false;

class PartitionIndexer {
  var partition: int;
  var indexFile: file;
  var indexWriter: channel(true, iokind.dynamic, true);

  proc PartitionIndexer(idx: int) {
    partition = idx;

    var name: string = dir_prefix;
    if (use_partition_in_name) {
      name += partition;
    }
    name += ".txt";
    info("opening ", name);
    indexFile = open(name, iomode.cwr);
    indexWriter = indexFile.writer();
  }

  proc writeEntry(indexRequest: IndexRequest) {
    indexWriter.writeln(indexRequest.word, "\t", indexRequest.docId);
  }
}

var indexers: [0..Partitions.size-1] PartitionIndexer;

proc initIndexer() {
  var t: Timer;
  t.start();
  for i in 0..Partitions.size-1 {
    on Partitions[i] {
      indexers[i] = new PartitionIndexer(i);
    }
  }
  t.stop();
  timing("initialized indexer in ",t.elapsed(TimeUnits.microseconds), " microseconds");
}

proc indexerForWord(word: string): PartitionIndexer {
  return indexers[partitionForWord(word)];
}

proc enqueueIndexRequest(indexRequest: IndexRequest) {
  debug("enqueuing ", indexRequest);
  var indexer = indexerForWord(indexRequest.word);
  // TODO: do we need to go onto the indexer locale for this?  or will it just automatically be on that locale?
  on indexer {
    indexer.writeEntry(indexRequest);
  }
}

proc main() {
  initPartitions();
  initIndexer();

  var t: Timer;
  t.start();

  var infile = open("words.txt", iomode.r);
  var reader = infile.reader();
  var word: string;
  var docId: DocId = 0;
  while (reader.readln(word)) {
    enqueueIndexRequest(new IndexRequest(word, docId));
    docId = (docId + 1) % 1000 + 1; // fake doc ids
  }

  t.stop();
  timing("partition fanout complete in ",t.elapsed(TimeUnits.microseconds), " microseconds");
}

use Common, Logging, IO, Partitions;

config const buffersize = 1024;
config const dir_prefix = "/ssd/words";
config const use_partition_in_name: bool = false;

class PartitionIndexer {
  var partition: int;
  var buff$: [0..buffersize-1] sync IndexRequest;
  var bufferIndex: atomic int;
  var release$: single bool;

  proc PartitionIndexer() {
    partition = 0;
    // via nextBufferIndex, this is incremented to zero before first use
    bufferIndex.write(-1);
  }

  proc PartitionIndexer(idx: int) {
    partition = idx;
    // via nextBufferIndex, this is incremented to zero before first use
    bufferIndex.write(-1);
  }

  proc startConsumer() {
    begin {
      consumer();
    }
  }

  proc nextBufferIndex(): int {
    var idx: int;
    var success = false;
    while (!success) {
      var originalValue = bufferIndex.read();
      idx = (originalValue + 1) % buffersize;
      success = bufferIndex.compareExchange(originalValue, idx);
    }
    return idx;
  }

  proc enqueueIndexRequest(indexRequest: IndexRequest) {
    const idx = nextBufferIndex();
    buff$(idx).writeEF(indexRequest);
    debug("enqueuing ", indexRequest);
  }

  proc waitForIndexer() {
    debug("waiting...");
    release$;
    debug("done waiting...");
  }

  proc markCompleteForIndexer() {
    debug("marking for completion");
    const idx = nextBufferIndex();
    buff$(idx).writeEF(nil);
    debug("halting consumer");
  }

  proc consumer() {
    var name: string = dir_prefix;
    if (use_partition_in_name) {
      name += partition;
    }
    name += ".txt";
    info("opening ", name);
    var indexFile = open(name, iomode.cwr);
    var writer = indexFile.writer();
    for indexRequest in readFromBuff() {
      writer.writeln(indexRequest.word, "\t", indexRequest.docId);
    }
  }

  iter readFromBuff() {
    var ind = 0;
    var nextVal = buff$(ind);

    while (nextVal != nil) {
      yield nextVal;

      ind = (ind + 1) % buffersize;
      nextVal = buff$(ind);
    }

    release$ = true;
  }
}

var indexers: [0..Partitions.size-1] PartitionIndexer;

proc initIndexer() {
  var t: Timer;
  t.start();
  for i in 0..Partitions.size-1 {
    on Partitions[i] {
      indexers[i] = new PartitionIndexer(i);
      indexers[i].startConsumer();
    }
  }
  t.stop();
  timing("initialized indexer in ",t.elapsed(TimeUnits.microseconds), " microseconds");
}

proc indexerForWord(word: string): PartitionIndexer {
  return indexers[partitionForWord(word)];
}

proc enqueueIndexRequest(indexRequest: IndexRequest) {
  debug("enqueuing ", indexRequest);
  var indexer = indexerForWord(indexRequest.word);
  // TODO: do we need to go onto the indexer locale for this?  or will it just automatically be on that locale?
  on indexer {
    indexer.enqueueIndexRequest(indexRequest);
  }
}

proc waitForIndexer() {
  markCompleteForIndexer();
  debug("waiting...");
  for indexer in indexers {
    // TODO: do we need to do this on the locale? or can we just call waitForIndexer and have it work?
    on indexer {
      indexer.waitForIndexer();
    }
  }
  debug("done waiting...");
}

proc markCompleteForIndexer() {
  debug("marking for completion");
  for indexer in indexers {
    // TODO: do we need to do this on the locale? or can we just call waitForIndexer and have it work?
    on indexer {
      indexer.markCompleteForIndexer();
    }
  }
  debug("halting consumer");
}

proc main() {
  initPartitions();
  initIndexer();

  var t: Timer;
  t.start();

  var infile = open("words.txt", iomode.r);
  var reader = infile.reader();
  var word: string;
  var docId: DocId = 0;
  while (reader.readln(word)) {
    enqueueIndexRequest(new IndexRequest(word, docId));
    docId = (docId + 1) % 1000 + 1; // fake doc ids
  }

  t.stop();
  timing("partition fanout complete in ",t.elapsed(TimeUnits.microseconds), " microseconds");

  waitForIndexer();
}


Add the "inline iterator" pragma to _square_tuple::lead_help().  This
was previously not getting inlined, which resulted in a goto with a
missing label (internal compiler error).

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

def *(param p: int, type t) type {
  var oneTuple: _build_tuple(t);
  def _fill(param p: int, x: _tuple) {
    if x.size == p then
      return x;
    else if 2*x.size <= p then
      return _fill(p, ((...x), (...x)));
    else
      return _fill(p, ((...x), (..._fill(p-x.size, oneTuple))));
  }
  if p <= 0 then
    compilerError("tuple must have positive size");
  return _fill(p, oneTuple);
}

def *(p: int, type t) type {
  compilerError("tuple size must be static");
}

pragma "tuple" record _tuple {
  param size : int;

  def this(i : int) var {  // for homogeneous tuples
    for param j in 1..size do
      if i == j then
        return this(j);
    halt("tuple indexing out-of-bounds error");
    return this(1);
  }
}

pragma "inline" def =(x : _tuple, y) {
  for param i in 1..x.size do
    x(i) = y(i);
  return x;
}

def ==( a: _tuple, b: _tuple): bool {
  if (a.size != b.size) then
    return false;
  else {
    for param i in 1..a.size do
      if (a(i) != b(i)) then
        return false;
    return true;
  }
}

def !=( a: _tuple, b: _tuple): bool {
  if (a.size != b.size) then
    return true;
  else {
    for param i in 1..a.size do
      if (a(i) != b(i)) then
        return true;
    return false;
  }
}

def _tuple.writeThis(f: Writer) {
  f.write("(", this(1));
  for param i in 2..size do
    f.write(", ", this(i));
  f.write(")");
}

pragma "inline" def _cast(type t, x: _tuple) where (t == complex(64)) && (x.size == 2) {
  var c: complex(64);
  c.re = x(1):real(32);
  c.im = x(2):real(32);
  return c;
}

pragma "inline" def _cast(type t, x: _tuple) where (t == complex(128)) && (x.size == 2) {
  var c: complex(128);
  c.re = x(1):real(64);
  c.im = x(2):real(64);
  return c;
}

pragma "inline" def +(a: _tuple) {
  return a;
}

pragma "inline" def -(a: _tuple) {
  for param i in 1..a.size do
    a(i) = -a(i);
  return a;
}

// def _isHomogeneous(t: _tuple) param {
//   def _isHomogeneousHelp(param i: int, t: _tuple) param {
//     if t(i).type != t(1).type then
//       return false;
//     else if i < t.size then
//       return _isHomogeneousHelp(i+1, t);
//     else
//       return true;
//   }
//   if t.size == 1 then
//     return true;
//   else
//     return _isHomogeneousHelp(2, t);
// }

pragma "inline" def +(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) + b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) + b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

    /*
pragma "inline" def +(a: _tuple, b) where _isHomogeneous(a) && b:a(1).type {
  var first = a(1) + b;
  var result: a.size*first.type;
  result(1) = first;
  for param i in 2..a.size do
    result(i) = a(i) + b;
  return result;
}

pragma "inline" def +(b, a: _tuple) where _isHomogeneous(a) && b:a(1).type {
  var first = b + a(1);
  var result: a.size*first.type;
  result(1) = first;
  for param i in 2..a.size do
    result(i) = b + a(i);
  return result;
}

pragma "inline" def +(a: _tuple, b: _tuple) where _isHomogeneous(a) && _isHomogeneous(b) && a.size == b.size {
  var first = a(1) + b(1);
  var result: a.size*first.type;
  result(1) = first;
  for param i in 2..a.size do
    result(i) = a(i) + b(i);
  return result;
}
    */

pragma "inline" def -(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) - b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) - b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def *(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) * b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) * b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def /(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) / b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) / b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def %(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) % b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) % b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def **(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) ** b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) ** b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def ~(a: _tuple) {
  for param i in 1..a.size do
    a(i) = ~a(i);
  return a;
}

pragma "inline" def &(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) & b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) & b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def |(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) | b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) | b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def ^(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) ^ b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) ^ b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def <<(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) << b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) << b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def >>(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) >> b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) >> b(i), (...rest));
    }
  }
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def !(a: _tuple) {
  var b: a.size * bool;
  for param i in 1..a.size do
    b(i) = !a(i);
  return b;
}

pragma "inline" def >(a: _tuple, b: _tuple) {
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  for param i in 1..a.size do
    if a(i) > b(i) then
      return true;
    else if a(i) < b(i) then
      return false;
  return false;
}

pragma "inline" def >=(a: _tuple, b: _tuple) {
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  for param i in 1..a.size do
    if a(i) > b(i) then
      return true;
    else if a(i) < b(i) then
      return false;
  return true;
}

pragma "inline" def <(a: _tuple, b: _tuple) {
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  for param i in 1..a.size do
    if a(i) < b(i) then
      return true;
    else if a(i) > b(i) then
      return false;
  return false;
}

pragma "inline" def <=(a: _tuple, b: _tuple) {
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  for param i in 1..a.size do
    if a(i) < b(i) then
      return true;
    else if a(i) > b(i) then
      return false;
  return true;
}

record _square_tuple {
  param size: int;
  var tuple;

  pragma "expand tuples with values"
  def these_help(param dim: int) {
    if dim == size - 1 {
      for i in tuple(dim) do
        for j in tuple(size) do
          yield _build_tuple_always_allow_ref(i, j);
    } else {
      for i in tuple(dim) do
        for j in these_help(dim+1) do
          yield _build_tuple_always_allow_ref(i, (...j));
    }
  }

  def these() {
    if size == 1 {
      for i in tuple(1) do
        yield i;
    } else {
      for i in these_help(1) do
        yield i;
    }
  }

  pragma "inline iterator"
  pragma "expand tuples with values"
  def lead_help(param dim: int) {
    if dim == size - 1 {
      for i in _toLeader(tuple(dim)) do
        for j in _toLeader(tuple(size)) do
          yield _build_tuple_always_allow_ref(i, j);
    } else {
      for i in _toLeader(tuple(dim)) do
        for j in lead_help(dim+1) do
          yield _build_tuple_always_allow_ref(i, (...j));
    }
  }

  def these(param tag: iterator) where tag == iterator.leader {
    if size == 1 {
      for i in _toLeader(tuple(1)) do
        yield i;
    } else {
      for i in lead_help(1) do
        yield i;
    }
  }

  pragma "expand tuples with values"
  def follow_help(param dim: int, follower) {
    if dim == size - 1 {
      for i in _toFollower(tuple(dim), follower(dim)) do
        for j in _toFollower(tuple(size), follower(size)) do
          yield _build_tuple_always_allow_ref(i, j);
    } else {
      for i in _toFollower(tuple(dim), follower(dim)) do
        for j in follow_help(dim+1) do
          yield _build_tuple_always_allow_ref(i, (...j));
    }
  }

  def these(param tag: iterator, follower) where tag == iterator.follower {
    if size == 1 {
      for i in _toFollower(tuple(1), follower) do
        yield i;
    } else {
      for i in follow_help(1, follower) do
        yield i;
    }
  }
}

def chpl__buildDomainExpr(x ...?size) where size > 1
  return new _square_tuple(size, x);

pragma "inline" def _build_tuple(x ...?size) {
  if size == 1 then
    return x(1);
  else
    return x;
}

pragma "inline" pragma "allow ref" def _build_tuple_always_allow_ref(x ...?size)
  return x;

pragma "inline" def _build_tuple(type t ...?size) type
  return t;

pragma "inline" def _build_tuple_always(x ...?size)
  return x;

pragma "inline" def tuple(x ...?size)
  return x;

def *(param p: int, type t) type {
  var oneTuple: _build_tuple(t);
  def _fill(param p: int, x: _tuple) {
    if x.size == p then
      return x;
    else if 2*x.size <= p then
      return _fill(p, ((...x), (...x)));
    else
      return _fill(p, ((...x), (..._fill(p-x.size, oneTuple))));
  }
  if p <= 0 then
    compilerError("tuple must have positive size");
  return _fill(p, oneTuple);
}

def *(p: int, type t) type {
  compilerError("tuple size must be static");
}

pragma "tuple" record _tuple {
  param size : int;

  def this(i : int) var {  // for homogeneous tuples
    for param j in 1..size do
      if i == j then
        return this(j);
    halt("tuple indexing out-of-bounds error");
    return this(1);
  }
}

pragma "inline" def =(x : _tuple, y) {
  for param i in 1..x.size do
    x(i) = y(i);
  return x;
}

def ==( a: _tuple, b: _tuple): bool {
  if (a.size != b.size) then
    return false;
  else {
    for param i in 1..a.size do
      if (a(i) != b(i)) then
        return false;
    return true;
  }
}

def !=( a: _tuple, b: _tuple): bool {
  if (a.size != b.size) then
    return true;
  else {
    for param i in 1..a.size do
      if (a(i) != b(i)) then
        return true;
    return false;
  }
}

def _tuple.writeThis(f: Writer) {
  f.write("(", this(1));
  for param i in 2..size do
    f.write(", ", this(i));
  f.write(")");
}

pragma "inline" def _cast(type t, x: _tuple) where (t == complex(64)) && (x.size == 2) {
  var c: complex(64);
  c.re = x(1):real(32);
  c.im = x(2):real(32);
  return c;
}

pragma "inline" def _cast(type t, x: _tuple) where (t == complex(128)) && (x.size == 2) {
  var c: complex(128);
  c.re = x(1):real(64);
  c.im = x(2):real(64);
  return c;
}

pragma "inline" def +(a: _tuple) {
  return a;
}

pragma "inline" def -(a: _tuple) {
  for param i in 1..a.size do
    a(i) = -a(i);
  return a;
}

// def _isHomogeneous(t: _tuple) param {
//   def _isHomogeneousHelp(param i: int, t: _tuple) param {
//     if t(i).type != t(1).type then
//       return false;
//     else if i < t.size then
//       return _isHomogeneousHelp(i+1, t);
//     else
//       return true;
//   }
//   if t.size == 1 then
//     return true;
//   else
//     return _isHomogeneousHelp(2, t);
// }

pragma "inline" def +(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) + b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) + b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

    /*
pragma "inline" def +(a: _tuple, b) where _isHomogeneous(a) && b:a(1).type {
  var first = a(1) + b;
  var result: a.size*first.type;
  result(1) = first;
  for param i in 2..a.size do
    result(i) = a(i) + b;
  return result;
}

pragma "inline" def +(b, a: _tuple) where _isHomogeneous(a) && b:a(1).type {
  var first = b + a(1);
  var result: a.size*first.type;
  result(1) = first;
  for param i in 2..a.size do
    result(i) = b + a(i);
  return result;
}

pragma "inline" def +(a: _tuple, b: _tuple) where _isHomogeneous(a) && _isHomogeneous(b) && a.size == b.size {
  var first = a(1) + b(1);
  var result: a.size*first.type;
  result(1) = first;
  for param i in 2..a.size do
    result(i) = a(i) + b(i);
  return result;
}
    */

pragma "inline" def -(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) - b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) - b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def *(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) * b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) * b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def /(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) / b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) / b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def %(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) % b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) % b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def **(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) ** b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) ** b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def ~(a: _tuple) {
  for param i in 1..a.size do
    a(i) = ~a(i);
  return a;
}

pragma "inline" def &(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) & b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) & b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def |(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) | b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) | b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def ^(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) ^ b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) ^ b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def <<(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) << b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) << b(i), (...rest));
    }
  }

  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def >>(a: _tuple, b: _tuple) {
  pragma "inline" def help(param i: int) {
    if i == a.size {
      var result = a(i) >> b(i);
      var onetuple: 1 * result.type;
      onetuple(1) = result;
      return onetuple;
    } else {
      var rest = help(i+1);
      return (a(i) >> b(i), (...rest));
    }
  }
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  return help(1);
}

pragma "inline" def !(a: _tuple) {
  var b: a.size * bool;
  for param i in 1..a.size do
    b(i) = !a(i);
  return b;
}

pragma "inline" def >(a: _tuple, b: _tuple) {
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  for param i in 1..a.size do
    if a(i) > b(i) then
      return true;
    else if a(i) < b(i) then
      return false;
  return false;
}

pragma "inline" def >=(a: _tuple, b: _tuple) {
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  for param i in 1..a.size do
    if a(i) > b(i) then
      return true;
    else if a(i) < b(i) then
      return false;
  return true;
}

pragma "inline" def <(a: _tuple, b: _tuple) {
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  for param i in 1..a.size do
    if a(i) < b(i) then
      return true;
    else if a(i) > b(i) then
      return false;
  return false;
}

pragma "inline" def <=(a: _tuple, b: _tuple) {
  if (a.size != b.size) then
    compilerError("Tuples must have the same size");

  for param i in 1..a.size do
    if a(i) < b(i) then
      return true;
    else if a(i) > b(i) then
      return false;
  return true;
}

record _square_tuple {
  param size: int;
  var tuple;

  pragma "expand tuples with values"
  def these_help(param dim: int) {
    if dim == size - 1 {
      for i in tuple(dim) do
        for j in tuple(size) do
          yield _build_tuple_always_allow_ref(i, j);
    } else {
      for i in tuple(dim) do
        for j in these_help(dim+1) do
          yield _build_tuple_always_allow_ref(i, (...j));
    }
  }

  def these() {
    if size == 1 {
      for i in tuple(1) do
        yield i;
    } else {
      for i in these_help(1) do
        yield i;
    }
  }

  pragma "expand tuples with values"
  def lead_help(param dim: int) {
    if dim == size - 1 {
      for i in _toLeader(tuple(dim)) do
        for j in _toLeader(tuple(size)) do
          yield _build_tuple_always_allow_ref(i, j);
    } else {
      for i in _toLeader(tuple(dim)) do
        for j in lead_help(dim+1) do
          yield _build_tuple_always_allow_ref(i, (...j));
    }
  }

  def these(param tag: iterator) where tag == iterator.leader {
    if size == 1 {
      for i in _toLeader(tuple(1)) do
        yield i;
    } else {
      for i in lead_help(1) do
        yield i;
    }
  }

  pragma "expand tuples with values"
  def follow_help(param dim: int, follower) {
    if dim == size - 1 {
      for i in _toFollower(tuple(dim), follower(dim)) do
        for j in _toFollower(tuple(size), follower(size)) do
          yield _build_tuple_always_allow_ref(i, j);
    } else {
      for i in _toFollower(tuple(dim), follower(dim)) do
        for j in follow_help(dim+1) do
          yield _build_tuple_always_allow_ref(i, (...j));
    }
  }

  def these(param tag: iterator, follower) where tag == iterator.follower {
    if size == 1 {
      for i in _toFollower(tuple(1), follower) do
        yield i;
    } else {
      for i in follow_help(1, follower) do
        yield i;
    }
  }
}

def chpl__buildDomainExpr(x ...?size) where size > 1
  return new _square_tuple(size, x);

pragma "inline" def _build_tuple(x ...?size) {
  if size == 1 then
    return x(1);
  else
    return x;
}

pragma "inline" pragma "allow ref" def _build_tuple_always_allow_ref(x ...?size)
  return x;

pragma "inline" def _build_tuple(type t ...?size) type
  return t;

pragma "inline" def _build_tuple_always(x ...?size)
  return x;

pragma "inline" def tuple(x ...?size)
  return x;


Took unnecessary piece of code out of test
to simplify it.

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

config const sourceText = "<ii>end</ii><none />";
const AllIndices: domain(1) = [1..length(sourceText)];
const AllPairs: domain(2) = [1..length(sourceText),
                             1..length(sourceText)];
var StartIndices: sparse subdomain(AllIndices);
var EndIndices: sparse subdomain(AllIndices);

def main {
  forall z in AllIndices do {
    if sourceText.substring[z] == '<' then {
      StartIndices += z;
      if z > 1 && sourceText.substring[z-1] != ">" then
      EndIndices += z-1;
    }
    else if sourceText.substring[z] == '>' then {
      EndIndices += z;
      if z < length(sourceText) &&
      sourceText.substring[z+1] != "<"  then StartIndices +=
      z+1;
    }
  }

  var A: [AllPairs] real;
  coforall (x,y) in [StartIndices, EndIndices] do {
    if (x <= y) {
      A[x, y] = x + y/10.0;
    }
  }
  writeln("A is:\n", A);
  return;
}

config const sourceText = "<ii>end</ii><none />";
const AllIndices: domain(1) = [1..length(sourceText)];
const AllPairs: domain(2) = [1..length(sourceText),
                             1..length(sourceText)];
var StartIndices: sparse subdomain(AllIndices);
var EndIndices: sparse subdomain(AllIndices);

def main {
  forall z in AllIndices do {
    if sourceText.substring[z] == '<' then {
      StartIndices += z;
      if z > 1 && sourceText.substring[z-1] != ">" then
      EndIndices += z-1;
    }
    else if sourceText.substring[z] == '>' then {
      EndIndices += z;
      if z < length(sourceText) &&
      sourceText.substring[z+1] != "<"  then StartIndices +=
      z+1;
    }
  }
  var D: sparse subdomain(AllPairs);
  for x in StartIndices {
    for y in EndIndices {
      D += (x, y);
    }
  }
  var A: [AllPairs] real;
  coforall (x,y) in [StartIndices, EndIndices] do {
    if (x <= y) {
      A[x, y] = x + y/10.0;
    }
  }
  writeln("A is:\n", A);
  return;
}