Style improvements

Style improvements

/* The Computer Language Benchmarks Game
 * http://benchmarksgame.alioth.debian.org/
 *
 * contributed by Ben Harshbarger
 * based on C++ RE2 implementation by Alexey Zolotov
 */

proc main() {
  var variants = [
    "agggtaaa|tttaccct",
    "[cgt]gggtaaa|tttaccc[acg]",
    "a[act]ggtaaa|tttacc[agt]t",
    "ag[act]gtaaa|tttac[agt]ct",
    "agg[act]taaa|ttta[agt]cct",
    "aggg[acg]aaa|ttt[cgt]ccct",
    "agggt[cgt]aa|tt[acg]accct",
    "agggta[cgt]a|t[acg]taccct",
    "agggtaa[cgt]|[acg]ttaccct"
  ];

  var subst = [
    ("B", "(c|g|t)"), ("D", "(a|g|t)"), ("H", "(a|c|t)"), ("K", "(g|t)"),
    ("M", "(a|c)"), ("N", "(a|c|g|t)"), ("R", "(a|g)"), ("S", "(c|g)"),
    ("V", "(a|c|g)"), ("W", "(a|t)"), ("Y", "(c|t)")
  ];

  var data, copy : string;
  stdin.readstring(data); // reads the entire file in
  const initLen = data.length;

  // remove newlines
  data = compile(">.*\n|\n").sub("", data);
  const noLineLen = data.length;

  copy = data; // grab a copy so we can replace in parallel

  var results : [variants.domain] int;

  // waits for tasks to finish
  sync {
    // fire off a thread to do replacing
    begin ref(copy) {
      for (f, r) in subst {
        const re = compile(f);
        copy = re.sub(r, copy);
      }
    }

    // count patterns
    forall (pattern, result) in zip(variants, results) do
      for m in compile(pattern).matches(data) do result += 1;
  }

  // print results
  for (p,r) in zip(variants, results) do writeln(p, " ", r);

  writeln("\n", initLen);
  writeln(noLineLen);
  writeln(copy.length);
}

/* The Computer Language Benchmarks Game
 * http://benchmarksgame.alioth.debian.org/
 *
 * contributed by Ben Harshbarger
 * based on C++ RE2 implementation by Alexey Zolotov
 */

proc main() {
  var variants = [
    "agggtaaa|tttaccct",
    "[cgt]gggtaaa|tttaccc[acg]",
    "a[act]ggtaaa|tttacc[agt]t",
    "ag[act]gtaaa|tttac[agt]ct",
    "agg[act]taaa|ttta[agt]cct",
    "aggg[acg]aaa|ttt[cgt]ccct",
    "agggt[cgt]aa|tt[acg]accct",
    "agggta[cgt]a|t[acg]taccct",
    "agggtaa[cgt]|[acg]ttaccct"
  ];

  var subst = [
    ("B", "(c|g|t)"), ("D", "(a|g|t)"), ("H", "(a|c|t)"), ("K", "(g|t)"),
    ("M", "(a|c)"), ("N", "(a|c|g|t)"), ("R", "(a|g)"), ("S", "(c|g)"),
    ("V", "(a|c|g)"), ("W", "(a|t)"), ("Y", "(c|t)")
  ];

  var total, copy : string;
  stdin.readstring(total); // reads the entire file in
  const initLen = total.length;

  // remove newlines
  var noLines = compile(">.*\n|\n");
  total = noLines.sub("", total);
  const noLineLen = total.length;

  copy = total; // grab a copy so we can replace in parallel

  var results : [variants.domain] int;

  var isDone : sync bool;

  // fire off a thread to do replacing
  begin ref(copy) {
    for (f, r) in subst {
      const re = compile(f);
      copy = re.sub(r, copy);
    }
    isDone = true; // set the 'full' state
  }

  // count patterns
  forall (pattern, result) in zip(variants, results) {
    var re = compile(pattern);
    for m in re.matches(total) do result += 1;
  }

  isDone; // waits for the 'full' state

  // print results
  for (p,r) in zip(variants, results) do writeln(p, " ", r);

  writeln("\n", initLen);
  writeln(noLineLen);
  writeln(copy.length);
}


Add additional 'yields' info

Add additional 'yields' info

/*
 * Copyright 2004-2015 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.
 */

/*
  This module contains several iterators that can be used to drive a ``forall``
  loop by performing dynamic and adaptive splitting of a range's iterations.

  For more information, see "User-Defined Parallel Zippered iterators
  in Chapel". Bradford L. Chamberlain, Sung-Eun Choi, Steven J. Deitz,
  Angeles Navarro. PGAS 2011: Fifth Conference on Partitioned Global
  Address Space Programming Models, October 2011.
*/
module AdvancedIters {

/*
   An atomic test-and-set lock.
*/
pragma "no doc"
record vlock {
  var l: atomic bool;
  proc lock() {
    on this do while l.testAndSet() != false do chpl_task_yield();
  }
  proc unlock() {
    l.write(false);
  }
}

/*
   Toggle debugging output.
*/
config param debugAdvancedIters:bool=false;

//************************* Dynamic iterator

/*
   The serial version of the dynamic iterator.
   Equivalent to serial iteration over the range ``c``.
*/
iter dynamic(c:range(?), chunkSize:int, numTasks:int=0) {

  if debugAdvancedIters then
    writeln("Serial dynamic Iterator. Working with range ", c);

  for i in c do yield i;
}

// Parallel iterator

/*
:arg c: The range to iterate over. The length of the range must be greater than zero.
:type c: range(?)
:arg chunkSize: The size of chunks to be yielded to each thread. Must be greater than zero.
:type chunkSize: int
:arg numTasks: The number of tasks to use. Must be >= zero. If this argument has the value 0, it will use the value indicated by ``dataParTasksPerLocale``.
:type numTasks: int

:yields: Indices in the range ``c``.

This iterator is equivalent to the dynamic scheduling approach of OpenMP.
Given an input range ``c``, each task is assigned chunks of size
``chunkSize`` from ``c`` (or the remaining iterations if there are fewer
than ``chunkSize``). This continues until there are no remaining iterations
in ``c``.

*/
iter dynamic(param tag:iterKind, c:range(?), chunkSize:int, numTasks:int=0)
where tag == iterKind.leader
{
  assert(chunkSize > 0); // caller's responsibility

  use UtilMath;
  // # of tasks the range can fill. (fast) ceil so all work is represented
  const chunkTasks = divceilpos(c.length, chunkSize): int;

  // Check if the number of tasks is 0, in that case it returns a default value
  const nTasks = min(chunkTasks, defaultNumTasks(numTasks));

  type rType=c.type;

  // We're going to have to densify at some point, might as well
  // do it early and make range slicing easier.
  const remain:rType=densify(c,c);

  // If the number of tasks is insufficient, yield in serial
  if c.length == 0 then halt("The range is empty");
  if nTasks == 1 then {
    if debugAdvancedIters then
      writeln("Dynamic Iterator: serial execution because there is not enough work");
    yield (remain,);
  } else {
    var moreWork : bool =true;
    var curIndex : atomic remain.low.type;
    curIndex.write(remain.low);

    coforall tid in 0..#nTasks with (ref remain, ref moreWork, ref curIndex) do {
      while moreWork do {
        // There is local work in remain
        const low = curIndex.fetchAdd(chunkSize);
        var high = low + chunkSize-1;

        if low > remain.high {
          break;
        } else if high > remain.high {
          high = remain.high;
          moreWork = false;
        }

        const current:rType = remain(low .. high);

        if high >= low then {
          if debugAdvancedIters then
            writeln("Parallel dynamic Iterator. Working at tid ", tid, " with range ", unDensify(current,c), " yielded as ", current);
          yield (current,);
        }
      }
    }
  }
}

// Follower
pragma "no doc"
iter dynamic(param tag:iterKind, c:range(?), chunkSize:int, numTasks:int, followThis)
where tag == iterKind.follower
{
  type rType=c.type;
  const current:rType=unDensify(followThis(1),c);
  if debugAdvancedIters then
    writeln("Follower received range ", followThis, " ; shifting to ", current);
  for i in current do {
    yield i;
  }
}

//************************* Guided iterator

/*
   The serial version of the guided iterator.
   Equivalent to serial iteration over the range ``c``.
*/
iter guided(c:range(?), numTasks:int=0) {

  if debugAdvancedIters then
    writeln("Serial guided Iterator. Working with range ", c);

  for i in c do yield i;
}

/*
  :arg c: The range to iterate over. Must have a length greater than zero.
  :type c: range(?)
  :arg numTasks: The number of tasks to use. Must be >= zero. If this argument has the value 0, it will use the value indicated by ``dataParTasksPerLocale``.
  :type numTasks: int

  :yields: Indices in the range ``c``.

  This iterator is equivalent to the guided policy of OpenMP: Given an input
  range ``c``, each task is assigned chunks of variable size, until there are
  no remaining iterations in ``c``. The size of each chunk is the number of
  unassigned iterations divided by the number of tasks, ``numTasks``. The size
  decreases approximately exponentially to 1. The splitting strategy is
  therefore adaptive.

*/
iter guided(param tag:iterKind, c:range(?), numTasks:int=0)
where tag == iterKind.leader
{
  // Check if the number of tasks is 0, in that case it returns a default value
  const nTasks=min(c.length, defaultNumTasks(numTasks));
  type rType=c.type;
  var remain:rType = densify(c,c);
  // If the number of tasks is insufficient, yield in serial
  if c.length == 0 then halt("The range is empty");
  if nTasks == 1 then {
    if debugAdvancedIters then
      writeln("Guided Iterator: serial execution because there is not enoguh work");
    yield (remain,);
  }

  else {
    var undone=true;
    const factor=nTasks;
    var lock : vlock;

    coforall tid in 0..#nTasks with (ref remain, ref undone, ref lock) do {
      while undone do {
        // There is local work in remain(tid)
        const current:rType=adaptSplit(remain, factor, undone, lock);
        if current.length !=0 then {
          if debugAdvancedIters then
            writeln("Parallel guided Iterator. Working at tid ", tid, " with range ", unDensify(current,c), " yielded as ", current);
          yield (current,);
        }
      }
    }
  }
}

// Follower
pragma "no doc"
iter guided(param tag:iterKind, c:range(?), numTasks:int, followThis)
where tag == iterKind.follower

{
  type rType=c.type;
  const current:rType=unDensify(followThis(1),c);
  if debugAdvancedIters then
    writeln("Follower received range ", followThis, " ; shifting to ", current);
  for i in current do {
    yield i;
  }
}

//************************* Adaptive work-stealing iterator
/*
   The serial version of the adaptive iterator.
   Equivalent to serial iteration over the range ``c``.
*/
iter adaptive(c:range(?), numTasks:int=0) {

  if debugAdvancedIters then
    writeln("Serial adaptive work-stealing Iterator. Working with range ", c);

  for i in c do yield i;

}

// Parallel iterator
/*
The enum used to represent adaptive methods.

- ``Whole``
  Each task without work tries to steal from its neighbor range
  until it exhausts that range. Then the task continues with the next
  neighbor range, and so on until there is no more work. This is the default
  policy.

- ``RoundRobin``
  Each task without work tries to steal once from its neighbor range, next
  from the following neighbor range and so on in a round-robin way until
  there is no more work.

- ``WholeTail``
  Similar to the ``Whole`` method, but now the splitting in the victim
  range is performed from its tail.
*/
enum Method {
  Whole = 0,
  RoundRobin = 1,
  WholeTail = 2
};

/*
  Used to select the adaptive stealing method. Defaults to ``Whole``.
  See :data:`Method` for more information.
*/
config param methodStealing = Method.Whole;

/*
  :arg c: The range to iterate over. Must have a length greater than zero.
  :type c: range(?)
  :arg numTasks: The number of tasks to use. Must be >= zero. If this argument has the value 0, it will use the value indicated by ``dataParTasksPerLocale``.
  :type numTasks: int

  :yields: Indices in the range ``c``.

  This iterator implements a naive adaptive binary splitting work-stealing
  strategy: Initially the leader iterator distributes the range to split, ``c``,
  evenly among the ``numTasks`` tasks.

  Then, each task performs adaptive splitting on its local sub-range's iterations.
  When a task exhausts its local iterations, it steals and splits from the
  range of another task (the victim). The splitting method on the local range
  and on the victim range is binary: i.e. the size of each chunk is computed as
  the number of unassigned iterations divided by 2. There are three stealing
  strategies that can be selected at compile time using the config param
  :param:`methodStealing`.
*/
iter adaptive(param tag:iterKind, c:range(?), numTasks:int=0)
where tag == iterKind.leader

{
  /*if (methodStealing != Method.Whole || methodStealing != Method.WholeTail) then
    compilerError("methodStealing value must be between 0 and 2");*/

  // Check if the number of tasks is 0, in that case it returns a default value
  const nTasks=min(c.length, defaultNumTasks(numTasks));
  type rType=c.type;

  // If the number of tasks is insufficient, yield in serial
  if c.length == 0 then halt("The range is empty");
  if nTasks == 1 then {
    if debugAdvancedIters then
      writeln("Adaptive work-stealing Iterator: serial execution because there is not enough work");
    yield (densify(c,c),);

  }
  else {
    const r:rType=densify(c,c);
    const SpaceThreads:domain(1)=0..#nTasks;
    var localWork:[SpaceThreads] rType; // The remaining range to split on each Thread
    var moreLocalWork:[SpaceThreads] bool=true; // bool var to signal there is still work on each local range
    var locks:[SpaceThreads] vlock; // sync var to control the splitting on each Thread
    const factor:int=2;

    const factorSteal:int=2;
    var moreWork:bool=true; // A global var to control the termination

    // Variables to put a barrier to ensure the initial range is computed on each Thread
    var barrier : atomic int;

    // Start the parallel work
    coforall tid in 0..#nTasks with (ref localWork, ref moreLocalWork, ref moreWork, ref r) do {

      // Step 1: Initial range per Thread/Task

      // Initial Local range in localWork[tid]
      const chunkSize = c.length/nTasks;
      localWork[tid]=
      if tid==nTasks-1 then
        r#(chunkSize*(nTasks-1)-r.length)
      else
        (r+tid*chunkSize)#chunkSize;
      barrier.add(1);

      if debugAdvancedIters then
        writeln("Parallel adaptive work-stealing Iterator. Working at tid ", tid, " with initial range ", localWork[tid]);

      // A barrier waiting for each thread to finish the initial assignment
      barrier.waitFor(nTasks);

      // Step 2: While there is work at tid, do splitting

      while moreLocalWork[tid] do {
        // There is local work
        // The current range we get after splitting locally
        const zeroBasedIters:rType=adaptSplit(localWork[tid], factorSteal, moreLocalWork[tid], locks[tid]);
        if zeroBasedIters.length !=0 then {
          if debugAdvancedIters then
            writeln("Parallel adaptive Iterator. Working locally at tid ", tid, " with range yielded as ", zeroBasedIters);
          yield (zeroBasedIters,);
        }
      }

      // Step3: Task tid finished its work, so it will try to steal from a neighbor

      var nVisitedVictims:int=0;
      var victim=(tid+1) % nTasks;
      var stealFailed:bool=false;

      while moreWork do {
        if debugAdvancedIters then
          writeln("Entering at Stealing phase in tid ", tid," with victim ", victim, " using method of Stealing ", methodStealing);

        // Perform the spliting at the victim remaining range

        if methodStealing == Method.RoundRobin {
          if moreLocalWork[victim] then {
            // There is work in victim
            const zeroBasedIters2:rType=adaptSplit(localWork[victim], factorSteal, moreLocalWork[victim], locks[victim]);
            if zeroBasedIters2.length !=0 then {
              if debugAdvancedIters then
                writeln("Range stealed at victim ", victim," yielded as ", zeroBasedIters2," by tid ", tid);
              yield (zeroBasedIters2,);
            }
          } else {
            stealFailed=true;
          }
        } else {
          while moreLocalWork[victim] do {
            // There is work in victim
            const zeroBasedIters2:rType=adaptSplit(localWork[victim], factorSteal, moreLocalWork[victim], locks[victim], methodStealing==Method.WholeTail);
                                          //after splitting from a victim range
            if zeroBasedIters2.length !=0 then {
              if debugAdvancedIters then
                writeln("Range stealed at victim ", victim," yielded as ", zeroBasedIters2," by tid ", tid);
              yield (zeroBasedIters2,);
            }
          }
        }

        // If here, then it can have failed the stealing intent at the victim (method 1),
        // or we have exhausted the victim range (methods 0, 2)

        if (methodStealing==Method.Whole || methodStealing==Method.WholeTail || (methodStealing==Method.RoundRobin && stealFailed)) then {
          nVisitedVictims += 1; // Signal that there is no more work in victim
          stealFailed=false;
          if debugAdvancedIters then
            writeln("Failed Stealing intent at tid ", tid," with victim ", victim, " and total no. of visited victims ", nVisitedVictims);
        }
        // Check if there is no more work
        if nVisitedVictims >= nTasks-1 then
          moreWork=false; // Signal that there is no more work in any victim
        else {  // There can be still work in other victim
          victim=(victim+1) % nTasks; // New victim to steal
          if methodStealing==Method.RoundRobin && victim==tid then
            victim=(victim+1) % nTasks;
        }
      }
    }
  }
}

// Follower
pragma "no doc"
iter adaptive(param tag:iterKind, c:range(?), numTasks:int, followThis)
where tag == iterKind.follower
{
  type rType=c.type;
  var current:rType=unDensify(followThis(1),c);
  if debugAdvancedIters then
    writeln("Follower received range ", followThis, " ; shifting to ", current);
  for i in current do {
    yield i;
  }
}

//************************* Helper functions
pragma "no doc"
proc defaultNumTasks(nTasks:int)
{
  var dnTasks=nTasks;
  if nTasks==0 then {
    if dataParTasksPerLocale==0 then dnTasks=here.maxTaskPar;
      else dnTasks=dataParTasksPerLocale;
  } else if nTasks<0 then {
    halt("'numTasks' is negative");
  }
  return dnTasks;
}

pragma "no doc"
proc adaptSplit(ref rangeToSplit:range(?), splitFactor:int, ref itLeft:bool, ref lock : vlock, splitTail:bool=false)
{
  type rType=rangeToSplit.type;
  type lenType=rangeToSplit.length.type;
  var totLen, size:lenType;
  const profThreshold=1;

  lock.lock();
  totLen=rangeToSplit.length;
  if totLen > profThreshold then
    size=max(totLen/splitFactor, profThreshold);
  else {
    size=totLen;
    itLeft=false;}
  const direction = if splitTail then -1 else 1;
  const firstRange:rType=rangeToSplit#(direction*size);
  rangeToSplit=rangeToSplit#(direction*(size-totLen));
  lock.unlock();
  return firstRange;
}

}

/*
 * Copyright 2004-2015 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.
 */

/*
  This module contains several iterators that can be used to drive a ``forall``
  loop by performing dynamic and adaptive splitting of a range's iterations.

  For more information, see "User-Defined Parallel Zippered iterators
  in Chapel". Bradford L. Chamberlain, Sung-Eun Choi, Steven J. Deitz,
  Angeles Navarro. PGAS 2011: Fifth Conference on Partitioned Global
  Address Space Programming Models, October 2011.
*/
module AdvancedIters {

/*
   An atomic test-and-set lock.
*/
pragma "no doc"
record vlock {
  var l: atomic bool;
  proc lock() {
    on this do while l.testAndSet() != false do chpl_task_yield();
  }
  proc unlock() {
    l.write(false);
  }
}

/*
   Toggle debugging output.
*/
config param debugAdvancedIters:bool=false;

//************************* Dynamic iterator

/*
   The serial version of the dynamic iterator.
   Equivalent to serial iteration over the range ``c``.
*/
iter dynamic(c:range(?), chunkSize:int, numTasks:int=0) {

  if debugAdvancedIters then
    writeln("Serial dynamic Iterator. Working with range ", c);

  for i in c do yield i;
}

// Parallel iterator

/*
:arg c: The range to iterate over. The length of the range must be greater than zero.
:type c: range(?)
:arg chunkSize: The size of chunks to be yielded to each thread. Must be greater than zero.
:type chunkSize: int
:arg numTasks: The number of tasks to use. Must be >= zero. If this argument has the value 0, it will use the value indicated by ``dataParTasksPerLocale``.
:type numTasks: int

:yields: Indices in the range ``c``.

This iterator is equivalent to the dynamic scheduling approach of OpenMP.
Given an input range ``c``, each task is assigned chunks of size
``chunkSize`` from ``c`` (or the remaining iterations if there are fewer
than ``chunkSize``). This continues until there are no remaining iterations
in ``c``.

*/
iter dynamic(param tag:iterKind, c:range(?), chunkSize:int, numTasks:int=0)
where tag == iterKind.leader
{
  assert(chunkSize > 0); // caller's responsibility

  use UtilMath;
  // # of tasks the range can fill. (fast) ceil so all work is represented
  const chunkTasks = divceilpos(c.length, chunkSize): int;

  // Check if the number of tasks is 0, in that case it returns a default value
  const nTasks = min(chunkTasks, defaultNumTasks(numTasks));

  type rType=c.type;

  // We're going to have to densify at some point, might as well
  // do it early and make range slicing easier.
  const remain:rType=densify(c,c);

  // If the number of tasks is insufficient, yield in serial
  if c.length == 0 then halt("The range is empty");
  if nTasks == 1 then {
    if debugAdvancedIters then
      writeln("Dynamic Iterator: serial execution because there is not enough work");
    yield (remain,);
  } else {
    var moreWork : bool =true;
    var curIndex : atomic remain.low.type;
    curIndex.write(remain.low);

    coforall tid in 0..#nTasks with (ref remain, ref moreWork, ref curIndex) do {
      while moreWork do {
        // There is local work in remain
        const low = curIndex.fetchAdd(chunkSize);
        var high = low + chunkSize-1;

        if low > remain.high {
          break;
        } else if high > remain.high {
          high = remain.high;
          moreWork = false;
        }

        const current:rType = remain(low .. high);

        if high >= low then {
          if debugAdvancedIters then
            writeln("Parallel dynamic Iterator. Working at tid ", tid, " with range ", unDensify(current,c), " yielded as ", current);
          yield (current,);
        }
      }
    }
  }
}

// Follower
pragma "no doc"
iter dynamic(param tag:iterKind, c:range(?), chunkSize:int, numTasks:int, followThis)
where tag == iterKind.follower
{
  type rType=c.type;
  const current:rType=unDensify(followThis(1),c);
  if debugAdvancedIters then
    writeln("Follower received range ", followThis, " ; shifting to ", current);
  for i in current do {
    yield i;
  }
}

//************************* Guided iterator

/*
   The serial version of the guided iterator.
   Equivalent to serial iteration over the range ``c``.
*/
iter guided(c:range(?), numTasks:int=0) {

  if debugAdvancedIters then
    writeln("Serial guided Iterator. Working with range ", c);

  for i in c do yield i;
}

/*
  :arg c: The range to iterate over. Must have a length greater than zero.
  :type c: range(?)
  :arg numTasks: The number of tasks to use. Must be >= zero. If this argument has the value 0, it will use the value indicated by ``dataParTasksPerLocale``.
  :type numTasks: int

  This iterator is equivalent to the guided policy of OpenMP: Given an input
  range ``c``, each task is assigned chunks of variable size, until there are
  no remaining iterations in ``c``. The size of each chunk is the number of
  unassigned iterations divided by the number of tasks, ``numTasks``. The size
  decreases approximately exponentially to 1. The splitting strategy is
  therefore adaptive.

*/
iter guided(param tag:iterKind, c:range(?), numTasks:int=0)
where tag == iterKind.leader
{
  // Check if the number of tasks is 0, in that case it returns a default value
  const nTasks=min(c.length, defaultNumTasks(numTasks));
  type rType=c.type;
  var remain:rType = densify(c,c);
  // If the number of tasks is insufficient, yield in serial
  if c.length == 0 then halt("The range is empty");
  if nTasks == 1 then {
    if debugAdvancedIters then
      writeln("Guided Iterator: serial execution because there is not enoguh work");
    yield (remain,);
  }

  else {
    var undone=true;
    const factor=nTasks;
    var lock : vlock;

    coforall tid in 0..#nTasks with (ref remain, ref undone, ref lock) do {
      while undone do {
        // There is local work in remain(tid)
        const current:rType=adaptSplit(remain, factor, undone, lock);
        if current.length !=0 then {
          if debugAdvancedIters then
            writeln("Parallel guided Iterator. Working at tid ", tid, " with range ", unDensify(current,c), " yielded as ", current);
          yield (current,);
        }
      }
    }
  }
}

// Follower
pragma "no doc"
iter guided(param tag:iterKind, c:range(?), numTasks:int, followThis)
where tag == iterKind.follower

{
  type rType=c.type;
  const current:rType=unDensify(followThis(1),c);
  if debugAdvancedIters then
    writeln("Follower received range ", followThis, " ; shifting to ", current);
  for i in current do {
    yield i;
  }
}

//************************* Adaptive work-stealing iterator
/*
   The serial version of the adaptive iterator.
   Equivalent to serial iteration over the range ``c``.
*/
iter adaptive(c:range(?), numTasks:int=0) {

  if debugAdvancedIters then
    writeln("Serial adaptive work-stealing Iterator. Working with range ", c);

  for i in c do yield i;

}

// Parallel iterator
/*
The enum used to represent adaptive methods.

- ``Whole``
  Each task without work tries to steal from its neighbor range
  until it exhausts that range. Then the task continues with the next
  neighbor range, and so on until there is no more work. This is the default
  policy.

- ``RoundRobin``
  Each task without work tries to steal once from its neighbor range, next
  from the following neighbor range and so on in a round-robin way until
  there is no more work.

- ``WholeTail``
  Similar to the ``Whole`` method, but now the splitting in the victim
  range is performed from its tail.
*/
enum Method {
  Whole = 0,
  RoundRobin = 1,
  WholeTail = 2
};

/*
  Used to select the adaptive stealing method. Defaults to ``Whole``.
  See :data:`Method` for more information.
*/
config param methodStealing = Method.Whole;

/*
  :arg c: The range to iterate over. Must have a length greater than zero.
  :type c: range(?)
  :arg numTasks: The number of tasks to use. Must be >= zero. If this argument has the value 0, it will use the value indicated by ``dataParTasksPerLocale``.
  :type numTasks: int

  This iterator implements a naive adaptive binary splitting work-stealing
  strategy: Initially the leader iterator distributes the range to split, ``c``,
  evenly among the ``numTasks`` tasks.

  Then, each task performs adaptive splitting on its local sub-range's iterations.
  When a task exhausts its local iterations, it steals and splits from the
  range of another task (the victim). The splitting method on the local range
  and on the victim range is binary: i.e. the size of each chunk is computed as
  the number of unassigned iterations divided by 2. There are three stealing
  strategies that can be selected at compile time using the config param
  :param:`methodStealing`.
*/
iter adaptive(param tag:iterKind, c:range(?), numTasks:int=0)
where tag == iterKind.leader

{
  /*if (methodStealing != Method.Whole || methodStealing != Method.WholeTail) then
    compilerError("methodStealing value must be between 0 and 2");*/

  // Check if the number of tasks is 0, in that case it returns a default value
  const nTasks=min(c.length, defaultNumTasks(numTasks));
  type rType=c.type;

  // If the number of tasks is insufficient, yield in serial
  if c.length == 0 then halt("The range is empty");
  if nTasks == 1 then {
    if debugAdvancedIters then
      writeln("Adaptive work-stealing Iterator: serial execution because there is not enough work");
    yield (densify(c,c),);

  }
  else {
    const r:rType=densify(c,c);
    const SpaceThreads:domain(1)=0..#nTasks;
    var localWork:[SpaceThreads] rType; // The remaining range to split on each Thread
    var moreLocalWork:[SpaceThreads] bool=true; // bool var to signal there is still work on each local range
    var locks:[SpaceThreads] vlock; // sync var to control the splitting on each Thread
    const factor:int=2;

    const factorSteal:int=2;
    var moreWork:bool=true; // A global var to control the termination

    // Variables to put a barrier to ensure the initial range is computed on each Thread
    var barrier : atomic int;

    // Start the parallel work
    coforall tid in 0..#nTasks with (ref localWork, ref moreLocalWork, ref moreWork, ref r) do {

      // Step 1: Initial range per Thread/Task

      // Initial Local range in localWork[tid]
      const chunkSize = c.length/nTasks;
      localWork[tid]=
      if tid==nTasks-1 then
        r#(chunkSize*(nTasks-1)-r.length)
      else
        (r+tid*chunkSize)#chunkSize;
      barrier.add(1);

      if debugAdvancedIters then
        writeln("Parallel adaptive work-stealing Iterator. Working at tid ", tid, " with initial range ", localWork[tid]);

      // A barrier waiting for each thread to finish the initial assignment
      barrier.waitFor(nTasks);

      // Step 2: While there is work at tid, do splitting

      while moreLocalWork[tid] do {
        // There is local work
        // The current range we get after splitting locally
        const zeroBasedIters:rType=adaptSplit(localWork[tid], factorSteal, moreLocalWork[tid], locks[tid]);
        if zeroBasedIters.length !=0 then {
          if debugAdvancedIters then
            writeln("Parallel adaptive Iterator. Working locally at tid ", tid, " with range yielded as ", zeroBasedIters);
          yield (zeroBasedIters,);
        }
      }

      // Step3: Task tid finished its work, so it will try to steal from a neighbor

      var nVisitedVictims:int=0;
      var victim=(tid+1) % nTasks;
      var stealFailed:bool=false;

      while moreWork do {
        if debugAdvancedIters then
          writeln("Entering at Stealing phase in tid ", tid," with victim ", victim, " using method of Stealing ", methodStealing);

        // Perform the spliting at the victim remaining range

        if methodStealing == Method.RoundRobin {
          if moreLocalWork[victim] then {
            // There is work in victim
            const zeroBasedIters2:rType=adaptSplit(localWork[victim], factorSteal, moreLocalWork[victim], locks[victim]);
            if zeroBasedIters2.length !=0 then {
              if debugAdvancedIters then
                writeln("Range stealed at victim ", victim," yielded as ", zeroBasedIters2," by tid ", tid);
              yield (zeroBasedIters2,);
            }
          } else {
            stealFailed=true;
          }
        } else {
          while moreLocalWork[victim] do {
            // There is work in victim
            const zeroBasedIters2:rType=adaptSplit(localWork[victim], factorSteal, moreLocalWork[victim], locks[victim], methodStealing==Method.WholeTail);
                                          //after splitting from a victim range
            if zeroBasedIters2.length !=0 then {
              if debugAdvancedIters then
                writeln("Range stealed at victim ", victim," yielded as ", zeroBasedIters2," by tid ", tid);
              yield (zeroBasedIters2,);
            }
          }
        }

        // If here, then it can have failed the stealing intent at the victim (method 1),
        // or we have exhausted the victim range (methods 0, 2)

        if (methodStealing==Method.Whole || methodStealing==Method.WholeTail || (methodStealing==Method.RoundRobin && stealFailed)) then {
          nVisitedVictims += 1; // Signal that there is no more work in victim
          stealFailed=false;
          if debugAdvancedIters then
            writeln("Failed Stealing intent at tid ", tid," with victim ", victim, " and total no. of visited victims ", nVisitedVictims);
        }
        // Check if there is no more work
        if nVisitedVictims >= nTasks-1 then
          moreWork=false; // Signal that there is no more work in any victim
        else {  // There can be still work in other victim
          victim=(victim+1) % nTasks; // New victim to steal
          if methodStealing==Method.RoundRobin && victim==tid then
            victim=(victim+1) % nTasks;
        }
      }
    }
  }
}

// Follower
pragma "no doc"
iter adaptive(param tag:iterKind, c:range(?), numTasks:int, followThis)
where tag == iterKind.follower
{
  type rType=c.type;
  var current:rType=unDensify(followThis(1),c);
  if debugAdvancedIters then
    writeln("Follower received range ", followThis, " ; shifting to ", current);
  for i in current do {
    yield i;
  }
}

//************************* Helper functions
pragma "no doc"
proc defaultNumTasks(nTasks:int)
{
  var dnTasks=nTasks;
  if nTasks==0 then {
    if dataParTasksPerLocale==0 then dnTasks=here.maxTaskPar;
      else dnTasks=dataParTasksPerLocale;
  } else if nTasks<0 then {
    halt("'numTasks' is negative");
  }
  return dnTasks;
}

pragma "no doc"
proc adaptSplit(ref rangeToSplit:range(?), splitFactor:int, ref itLeft:bool, ref lock : vlock, splitTail:bool=false)
{
  type rType=rangeToSplit.type;
  type lenType=rangeToSplit.length.type;
  var totLen, size:lenType;
  const profThreshold=1;

  lock.lock();
  totLen=rangeToSplit.length;
  if totLen > profThreshold then
    size=max(totLen/splitFactor, profThreshold);
  else {
    size=totLen;
    itLeft=false;}
  const direction = if splitTail then -1 else 1;
  const firstRange:rType=rangeToSplit#(direction*size);
  rangeToSplit=rangeToSplit#(direction*(size-totLen));
  lock.unlock();
  return firstRange;
}

}


Noticed that _init() was not overloaded for uint, which was
causing initializations of arrays of uints to try and use
the string _init() function instead.

As I check this in, I notice that it's also not defined for
complexes, but will test and check that in separately, since
complexes are weirder than uints (and I haven't tested it yet).

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

// _chpl_base module

pragma "inline" def _chpl_alloc(type t, description:string)
  return __primitive("chpl_alloc", t, description);

// Primitive functions and operators on bool
pragma "inline" def =(a: bool, b: bool) return b;
//pragma "inline" def _copy(a: bool) return a;
pragma "inline" def ~(a: bool) return __primitive("u~", a);
pragma "inline" def &(a: bool, b: bool) return __primitive("&", a, b);
pragma "inline" def |(a: bool, b: bool) return __primitive("|", a, b);
pragma "inline" def ^(a: bool, b: bool) return __primitive("^", a, b);
pragma "inline" def ==(a: bool, b: bool) return __primitive("==", a, b);
pragma "inline" def !=(a: bool, b: bool) return __primitive("!=", a, b);
pragma "inline" def <=(a: bool, b: bool) return __primitive("<=", a, b);
pragma "inline" def >=(a: bool, b: bool) return __primitive(">=", a, b);
pragma "inline" def <(a: bool, b: bool) return __primitive("<", a, b);
pragma "inline" def >(a: bool, b: bool) return __primitive(">", a, b);
pragma "inline" def !(a: bool) return __primitive("!", a);
pragma "inline" def &&(a: bool, b: bool) return __primitive("&&", a, b);
pragma "inline" def ||(a: bool, b: bool) return __primitive("||", a, b);

// Primitive functions and operators on int(8)
pragma "inline" def =(a: int(8), b: int) return b:int(8);
//pragma "inline" def _copy(a: int(8)) return a;
pragma "inline" def +(a: int(8)) return __primitive("u+", a);
pragma "inline" def -(a: int(8)) return __primitive("u-", a);
pragma "inline" def +(a: int(8), b: int(8)) return __primitive("+", a, b);
pragma "inline" def -(a: int(8), b: int(8)) return __primitive("-", a, b);
pragma "inline" def *(a: int(8), b: int(8)) return __primitive("*", a, b);
pragma "inline" def /(a: int(8), b: int(8)) return __primitive("/", a, b);
pragma "inline" def **(a: int(8), b: int(8)) return __primitive("**", a, b);
pragma "inline" def %(a: int(8), b: int(8)) return __primitive("%", a, b);
pragma "inline" def ~(a: int(8)) return __primitive("u~", a);
pragma "inline" def &(a: int(8), b: int(8)) return __primitive("&", a, b);
pragma "inline" def |(a: int(8), b: int(8)) return __primitive("|", a, b);
pragma "inline" def ^(a: int(8), b: int(8)) return __primitive("^", a, b);
pragma "inline" def <<(a: int(8), b: int(8)) return __primitive("<<", a, b);
pragma "inline" def >>(a: int(8), b: int(8)) return __primitive(">>", a, b);
pragma "inline" def ==(a: int(8), b: int(8)) return __primitive("==", a, b);
pragma "inline" def !=(a: int(8), b: int(8)) return __primitive("!=", a, b);
pragma "inline" def <=(a: int(8), b: int(8)) return __primitive("<=", a, b);
pragma "inline" def >=(a: int(8), b: int(8)) return __primitive(">=", a, b);
pragma "inline" def <(a: int(8), b: int(8)) return __primitive("<", a, b);
pragma "inline" def >(a: int(8), b: int(8)) return __primitive(">", a, b);
pragma "inline" def !(a: int(8)) return __primitive("!", a);
pragma "inline" def &&(a: int(8), b: int(8)) return __primitive("&&", a, b);
pragma "inline" def ||(a: int(8), b: int(8)) return __primitive("||", a, b);

// Primitive functions and operators on int(16)
pragma "inline" def =(a: int(16), b: int) return b:int(16);
//pragma "inline" def _copy(a: int(16)) return a;
pragma "inline" def +(a: int(16)) return __primitive("u+", a);
pragma "inline" def -(a: int(16)) return __primitive("u-", a);
pragma "inline" def +(a: int(16), b: int(16)) return __primitive("+", a, b);
pragma "inline" def -(a: int(16), b: int(16)) return __primitive("-", a, b);
pragma "inline" def *(a: int(16), b: int(16)) return __primitive("*", a, b);
pragma "inline" def /(a: int(16), b: int(16)) return __primitive("/", a, b);
pragma "inline" def **(a: int(16), b: int(16)) return __primitive("**", a, b);
pragma "inline" def %(a: int(16), b: int(16)) return __primitive("%", a, b);
pragma "inline" def ~(a: int(16)) return __primitive("u~", a);
pragma "inline" def &(a: int(16), b: int(16)) return __primitive("&", a, b);
pragma "inline" def |(a: int(16), b: int(16)) return __primitive("|", a, b);
pragma "inline" def ^(a: int(16), b: int(16)) return __primitive("^", a, b);
pragma "inline" def <<(a: int(16), b: int(16)) return __primitive("<<", a, b);
pragma "inline" def >>(a: int(16), b: int(16)) return __primitive(">>", a, b);
pragma "inline" def ==(a: int(16), b: int(16)) return __primitive("==", a, b);
pragma "inline" def !=(a: int(16), b: int(16)) return __primitive("!=", a, b);
pragma "inline" def <=(a: int(16), b: int(16)) return __primitive("<=", a, b);
pragma "inline" def >=(a: int(16), b: int(16)) return __primitive(">=", a, b);
pragma "inline" def <(a: int(16), b: int(16)) return __primitive("<", a, b);
pragma "inline" def >(a: int(16), b: int(16)) return __primitive(">", a, b);
pragma "inline" def !(a: int(16)) return __primitive("!", a);
pragma "inline" def &&(a: int(16), b: int(16)) return __primitive("&&", a, b);
pragma "inline" def ||(a: int(16), b: int(16)) return __primitive("||", a, b);

// Primitive functions and operators on int(32)
pragma "inline" def =(a: int(32), b: int) return b:int(32);
//pragma "inline" def _copy(a: int(32)) return a;
pragma "inline" def +(a: int(32)) return __primitive("u+", a);
pragma "inline" def -(a: int(32)) return __primitive("u-", a);
pragma "inline" def +(a: int(32), b: int(32)) return __primitive("+", a, b);
pragma "inline" def -(a: int(32), b: int(32)) return __primitive("-", a, b);
pragma "inline" def *(a: int(32), b: int(32)) return __primitive("*", a, b);
pragma "inline" def /(a: int(32), b: int(32)) return __primitive("/", a, b);
pragma "inline" def **(a: int(32), b: int(32)) return __primitive("**", a, b);
pragma "inline" def %(a: int(32), b: int(32)) return __primitive("%", a, b);
pragma "inline" def ~(a: int(32)) return __primitive("u~", a);
pragma "inline" def &(a: int(32), b: int(32)) return __primitive("&", a, b);
pragma "inline" def |(a: int(32), b: int(32)) return __primitive("|", a, b);
pragma "inline" def ^(a: int(32), b: int(32)) return __primitive("^", a, b);
pragma "inline" def <<(a: int(32), b: int(32)) return __primitive("<<", a, b);
pragma "inline" def >>(a: int(32), b: int(32)) return __primitive(">>", a, b);
pragma "inline" def ==(a: int(32), b: int(32)) return __primitive("==", a, b);
pragma "inline" def !=(a: int(32), b: int(32)) return __primitive("!=", a, b);
pragma "inline" def <=(a: int(32), b: int(32)) return __primitive("<=", a, b);
pragma "inline" def >=(a: int(32), b: int(32)) return __primitive(">=", a, b);
pragma "inline" def <(a: int(32), b: int(32)) return __primitive("<", a, b);
pragma "inline" def >(a: int(32), b: int(32)) return __primitive(">", a, b);
pragma "inline" def !(a: int(32)) return __primitive("!", a);
pragma "inline" def &&(a: int(32), b: int(32)) return __primitive("&&", a, b);
pragma "inline" def ||(a: int(32), b: int(32)) return __primitive("||", a, b);

// Primitive functions and operators on int(64)
pragma "inline" def =(a: int(64), b: int(64)) return b;
//pragma "inline" def _copy(a: int(64)) return a;
pragma "inline" def +(a: int(64)) return __primitive("u+", a);
pragma "inline" def -(a: int(64)) return __primitive("u-", a);
pragma "inline" def +(a: int(64), b: int(64)) return __primitive("+", a, b);
pragma "inline" def -(a: int(64), b: int(64)) return __primitive("-", a, b);
pragma "inline" def *(a: int(64), b: int(64)) return __primitive("*", a, b);
pragma "inline" def /(a: int(64), b: int(64)) return __primitive("/", a, b);
pragma "inline" def **(a: int(64), b: int(64)) return __primitive("**", a, b);
pragma "inline" def %(a: int(64), b: int(64)) return __primitive("%", a, b);
pragma "inline" def ~(a: int(64)) return __primitive("u~", a);
pragma "inline" def &(a: int(64), b: int(64)) return __primitive("&", a, b);
pragma "inline" def |(a: int(64), b: int(64)) return __primitive("|", a, b);
pragma "inline" def ^(a: int(64), b: int(64)) return __primitive("^", a, b);
pragma "inline" def <<(a: int(64), b: int(64)) return __primitive("<<", a, b);
pragma "inline" def >>(a: int(64), b: int(64)) return __primitive(">>", a, b);
pragma "inline" def ==(a: int(64), b: int(64)) return __primitive("==", a, b);
pragma "inline" def !=(a: int(64), b: int(64)) return __primitive("!=", a, b);
pragma "inline" def <=(a: int(64), b: int(64)) return __primitive("<=", a, b);
pragma "inline" def >=(a: int(64), b: int(64)) return __primitive(">=", a, b);
pragma "inline" def <(a: int(64), b: int(64)) return __primitive("<", a, b);
pragma "inline" def >(a: int(64), b: int(64)) return __primitive(">", a, b);
pragma "inline" def !(a: int(64)) return __primitive("!", a);
pragma "inline" def &&(a: int(64), b: int(64)) return __primitive("&&", a, b);
pragma "inline" def ||(a: int(64), b: int(64)) return __primitive("||", a, b);

// Primitive functions and operators on uint(8)
pragma "inline" def =(a: uint(8), b: uint) return b:uint(8);
//pragma "inline" def _copy(a: uint(8)) return a;
pragma "inline" def +(a: uint(8)) return __primitive("u+", a);
pragma "inline" def -(a: uint(8)) return __primitive("u-", a);
pragma "inline" def +(a: uint(8), b: uint(8)) return __primitive("+", a, b);
pragma "inline" def -(a: uint(8), b: uint(8)) return __primitive("-", a, b);
pragma "inline" def *(a: uint(8), b: uint(8)) return __primitive("*", a, b);
pragma "inline" def /(a: uint(8), b: uint(8)) return __primitive("/", a, b);
pragma "inline" def **(a: uint(8), b: uint(8)) return __primitive("**", a, b);
pragma "inline" def %(a: uint(8), b: uint(8)) return __primitive("%", a, b);
pragma "inline" def ~(a: uint(8)) return __primitive("u~", a);
pragma "inline" def &(a: uint(8), b: uint(8)) return __primitive("&", a, b);
pragma "inline" def |(a: uint(8), b: uint(8)) return __primitive("|", a, b);
pragma "inline" def ^(a: uint(8), b: uint(8)) return __primitive("^", a, b);
pragma "inline" def <<(a: uint(8), b: uint(8)) return __primitive("<<", a, b);
pragma "inline" def >>(a: uint(8), b: uint(8)) return __primitive(">>", a, b);
pragma "inline" def ==(a: uint(8), b: uint(8)) return __primitive("==", a, b);
pragma "inline" def !=(a: uint(8), b: uint(8)) return __primitive("!=", a, b);
pragma "inline" def <=(a: uint(8), b: uint(8)) return __primitive("<=", a, b);
pragma "inline" def >=(a: uint(8), b: uint(8)) return __primitive(">=", a, b);
pragma "inline" def <(a: uint(8), b: uint(8)) return __primitive("<", a, b);
pragma "inline" def >(a: uint(8), b: uint(8)) return __primitive(">", a, b);
pragma "inline" def !(a: uint(8)) return __primitive("!", a);
pragma "inline" def &&(a: uint(8), b: uint(8)) return __primitive("&&", a, b);
pragma "inline" def ||(a: uint(8), b: uint(8)) return __primitive("||", a, b);

// Primitive functions and operators on uint(16)
pragma "inline" def =(a: uint(16), b: uint) return b:uint(16);
//pragma "inline" def _copy(a: uint(16)) return a;
pragma "inline" def +(a: uint(16)) return __primitive("u+", a);
pragma "inline" def -(a: uint(16)) return __primitive("u-", a);
pragma "inline" def +(a: uint(16), b: uint(16)) return __primitive("+", a, b);
pragma "inline" def -(a: uint(16), b: uint(16)) return __primitive("-", a, b);
pragma "inline" def *(a: uint(16), b: uint(16)) return __primitive("*", a, b);
pragma "inline" def /(a: uint(16), b: uint(16)) return __primitive("/", a, b);
pragma "inline" def **(a: uint(16), b: uint(16)) return __primitive("**", a, b);
pragma "inline" def %(a: uint(16), b: uint(16)) return __primitive("%", a, b);
pragma "inline" def ~(a: uint(16)) return __primitive("u~", a);
pragma "inline" def &(a: uint(16), b: uint(16)) return __primitive("&", a, b);
pragma "inline" def |(a: uint(16), b: uint(16)) return __primitive("|", a, b);
pragma "inline" def ^(a: uint(16), b: uint(16)) return __primitive("^", a, b);
pragma "inline" def <<(a: uint(16), b: uint(16)) return __primitive("<<", a, b);
pragma "inline" def >>(a: uint(16), b: uint(16)) return __primitive(">>", a, b);
pragma "inline" def ==(a: uint(16), b: uint(16)) return __primitive("==", a, b);
pragma "inline" def !=(a: uint(16), b: uint(16)) return __primitive("!=", a, b);
pragma "inline" def <=(a: uint(16), b: uint(16)) return __primitive("<=", a, b);
pragma "inline" def >=(a: uint(16), b: uint(16)) return __primitive(">=", a, b);
pragma "inline" def <(a: uint(16), b: uint(16)) return __primitive("<", a, b);
pragma "inline" def >(a: uint(16), b: uint(16)) return __primitive(">", a, b);
pragma "inline" def !(a: uint(16)) return __primitive("!", a);
pragma "inline" def &&(a: uint(16), b: uint(16)) return __primitive("&&", a, b);
pragma "inline" def ||(a: uint(16), b: uint(16)) return __primitive("||", a, b);

// Primitive functions and operators on uint(32)
pragma "inline" def =(a: uint(32), b: uint) return b:uint(32);
//pragma "inline" def _copy(a: uint(32)) return a;
pragma "inline" def +(a: uint(32)) return __primitive("u+", a);
pragma "inline" def -(a: uint(32)) return __primitive("u-", a);
pragma "inline" def +(a: uint(32), b: uint(32)) return __primitive("+", a, b);
pragma "inline" def -(a: uint(32), b: uint(32)) return __primitive("-", a, b);
pragma "inline" def *(a: uint(32), b: uint(32)) return __primitive("*", a, b);
pragma "inline" def /(a: uint(32), b: uint(32)) return __primitive("/", a, b);
pragma "inline" def **(a: uint(32), b: uint(32)) return __primitive("**", a, b);
pragma "inline" def %(a: uint(32), b: uint(32)) return __primitive("%", a, b);
pragma "inline" def ~(a: uint(32)) return __primitive("u~", a);
pragma "inline" def &(a: uint(32), b: uint(32)) return __primitive("&", a, b);
pragma "inline" def |(a: uint(32), b: uint(32)) return __primitive("|", a, b);
pragma "inline" def ^(a: uint(32), b: uint(32)) return __primitive("^", a, b);
pragma "inline" def <<(a: uint(32), b: uint(32)) return __primitive("<<", a, b);
pragma "inline" def >>(a: uint(32), b: uint(32)) return __primitive(">>", a, b);
pragma "inline" def ==(a: uint(32), b: uint(32)) return __primitive("==", a, b);
pragma "inline" def !=(a: uint(32), b: uint(32)) return __primitive("!=", a, b);
pragma "inline" def <=(a: uint(32), b: uint(32)) return __primitive("<=", a, b);
pragma "inline" def >=(a: uint(32), b: uint(32)) return __primitive(">=", a, b);
pragma "inline" def <(a: uint(32), b: uint(32)) return __primitive("<", a, b);
pragma "inline" def >(a: uint(32), b: uint(32)) return __primitive(">", a, b);
pragma "inline" def !(a: uint(32)) return __primitive("!", a);
pragma "inline" def &&(a: uint(32), b: uint(32)) return __primitive("&&", a, b);
pragma "inline" def ||(a: uint(32), b: uint(32)) return __primitive("||", a, b);

// Primitive functions and operators on uint(64)
pragma "inline" def =(a: uint(64), b: uint(64)) return b;
//pragma "inline" def _copy(a: uint(64)) return a;
pragma "inline" def +(a: uint(64)) return __primitive("u+", a);
pragma "inline" def -(a: uint(64)) return __primitive("u-", a);
pragma "inline" def +(a: uint(64), b: uint(64)) return __primitive("+", a, b);
pragma "inline" def -(a: uint(64), b: uint(64)) return __primitive("-", a, b);
pragma "inline" def *(a: uint(64), b: uint(64)) return __primitive("*", a, b);
pragma "inline" def /(a: uint(64), b: uint(64)) return __primitive("/", a, b);
pragma "inline" def **(a: uint(64), b: uint(64)) return __primitive("**", a, b);
pragma "inline" def %(a: uint(64), b: uint(64)) return __primitive("%", a, b);
pragma "inline" def ~(a: uint(64)) return __primitive("u~", a);
pragma "inline" def &(a: uint(64), b: uint(64)) return __primitive("&", a, b);
pragma "inline" def |(a: uint(64), b: uint(64)) return __primitive("|", a, b);
pragma "inline" def ^(a: uint(64), b: uint(64)) return __primitive("^", a, b);
pragma "inline" def <<(a: uint(64), b: uint(64)) return __primitive("<<", a, b);
pragma "inline" def >>(a: uint(64), b: uint(64)) return __primitive(">>", a, b);
pragma "inline" def ==(a: uint(64), b: uint(64)) return __primitive("==", a, b);
pragma "inline" def !=(a: uint(64), b: uint(64)) return __primitive("!=", a, b);
pragma "inline" def <=(a: uint(64), b: uint(64)) return __primitive("<=", a, b);
pragma "inline" def >=(a: uint(64), b: uint(64)) return __primitive(">=", a, b);
pragma "inline" def <(a: uint(64), b: uint(64)) return __primitive("<", a, b);
pragma "inline" def >(a: uint(64), b: uint(64)) return __primitive(">", a, b);
pragma "inline" def !(a: uint(64)) return __primitive("!", a);
pragma "inline" def &&(a: uint(64), b: uint(64)) return __primitive("&&", a, b);
pragma "inline" def ||(a: uint(64), b: uint(64)) return __primitive("||", a, b);

// Primitive functions and operators on float(32)
pragma "inline" def =(a: float(32), b: float) return b:float(32);
//pragma "inline" def _copy(a: float(32)) return a;
pragma "inline" def +(a: float(32)) return __primitive("u+", a);
pragma "inline" def -(a: float(32)) return __primitive("u-", a);
pragma "inline" def +(a: float(32), b: float(32)) return __primitive("+", a, b);
pragma "inline" def -(a: float(32), b: float(32)) return __primitive("-", a, b);
pragma "inline" def *(a: float(32), b: float(32)) return __primitive("*", a, b);
pragma "inline" def /(a: float(32), b: float(32)) return __primitive("/", a, b);
pragma "inline" def **(a: float(32), b: float(32)) return __primitive("**", a, b);
pragma "inline" def ==(a: float(32), b: float(32)) return __primitive("==", a, b);
pragma "inline" def !=(a: float(32), b: float(32)) return __primitive("!=", a, b);
pragma "inline" def <=(a: float(32), b: float(32)) return __primitive("<=", a, b);
pragma "inline" def >=(a: float(32), b: float(32)) return __primitive(">=", a, b);
pragma "inline" def <(a: float(32), b: float(32)) return __primitive("<", a, b);
pragma "inline" def >(a: float(32), b: float(32)) return __primitive(">", a, b);
pragma "inline" def !(a: float(32)) return __primitive("!", a);
pragma "inline" def &&(a: float(32), b: float(32)) return __primitive("&&", a, b);
pragma "inline" def ||(a: float(32), b: float(32)) return __primitive("||", a, b);

// Primitive functions and operators on float(64)
pragma "inline" def =(a: float(64), b: float(64)) return b;
//pragma "inline" def _copy(a: float(64)) return a;
pragma "inline" def +(a: float(64)) return __primitive("u+", a);
pragma "inline" def -(a: float(64)) return __primitive("u-", a);
pragma "inline" def +(a: float(64), b: float(64)) return __primitive("+", a, b);
pragma "inline" def -(a: float(64), b: float(64)) return __primitive("-", a, b);
pragma "inline" def *(a: float(64), b: float(64)) return __primitive("*", a, b);
pragma "inline" def /(a: float(64), b: float(64)) return __primitive("/", a, b);
pragma "inline" def **(a: float(64), b: float(64)) return __primitive("**", a, b);
pragma "inline" def ==(a: float(64), b: float(64)) return __primitive("==", a, b);
pragma "inline" def !=(a: float(64), b: float(64)) return __primitive("!=", a, b);
pragma "inline" def <=(a: float(64), b: float(64)) return __primitive("<=", a, b);
pragma "inline" def >=(a: float(64), b: float(64)) return __primitive(">=", a, b);
pragma "inline" def <(a: float(64), b: float(64)) return __primitive("<", a, b);
pragma "inline" def >(a: float(64), b: float(64)) return __primitive(">", a, b);
pragma "inline" def !(a: float(64)) return __primitive("!", a);
pragma "inline" def &&(a: float(64), b: float(64)) return __primitive("&&", a, b);
pragma "inline" def ||(a: float(64), b: float(64)) return __primitive("||", a, b);

// Primitive functions and operators on string
pragma "inline" def =(a: string, b: string) return __primitive("string_copy", b);
//pragma "inline" def _copy(x : string) {
//  var y : string;
//  y = x;
//  return y;
//}
pragma "inline" def ==(a: string, b: string) return __primitive("string_equal", a, b);
pragma "inline" def !=(a: string, b: string) return !(a == b);
pragma "inline" def +(a: string, b: string) return __primitive("string_concat", a, b);
pragma "inline" def length(a: string) return __primitive("string_length", a);
pragma "inline" def string.this(i: int) return __primitive("string_index", this, i);

pragma "inline" def _string_contains(a: string, b: string)
  return __primitive("string_contains", a, b);

pragma "inline" def _tostring(x : bool, format : string)
  return __primitive("to_string", format, x);

pragma "inline" def _tostring(x : int, format : string)
  return __primitive("to_string", format, x);

pragma "inline" def _tostring(x : float, format : string)
  return __primitive("to_string", format, x);

pragma "inline" def ascii(a: string) return __primitive("ascii", a);

//
// Primitive funs for objects
//
pragma "inline" def ==(a: object, b: object) return __primitive("ptr_eq", a, b);
pragma "inline" def !=(a: object, b: object) return __primitive("ptr_neq", a, b);
pragma "inline" def =(a, b:object) return b:a.type;
pragma "inline" def _copy(a) return a;

//
// _init
//
pragma "inline" def _init(x : bool) return false;
pragma "inline" def _init(x : int) return 0;
pragma "inline" def _init(x : uint) return 0u;
pragma "inline" def _init(x : float) return 0.0;
pragma "inline" def _init(x : string) return "";
pragma "inline" def _init(x) return nil:x;

// identity functions (for reduction operations)
pragma "inline" def _prod_id( type t) return __primitive( "_prod_id", t);
pragma "inline" def _land_id( type t) return __primitive( "_land_id", t);
pragma "inline" def _lor_id( type t) return __primitive( "_lor_id", t);
pragma "inline" def _lxor_id( type t) return __primitive( "_lxor_id", t);
pragma "inline" def _band_id( type t) return __primitive( "_band_id", t);
pragma "inline" def _bor_id( type t) return __primitive( "_bor_id", t);
pragma "inline" def _bxor_id( type t) return __primitive( "_bxor_id", t);

// predefined functions
pragma "inline" def _min( type t) return __primitive( "_min", t);
pragma "inline" def _max( type t) return __primitive( "_max", t);

//
// More primitive funs
//
pragma "no codegen" pragma "rename _chpl_exit" def exit(status : int) {
  __primitive("exit");
}

pragma "no codegen" pragma "rename fflush" def fflush(fp: _file) : int {
  return __primitive("fflush", fp);
}

def init_elts(x, s, e) {
  for i in 1..s {
    var y : e.type;
    x(i-1) = y;
  }
}

// dynamic data block class
pragma "data class"
class _ddata {
  type elt_type;
  var size : int;
  var _element : elt_type;
  pragma "inline" def init() {
    __primitive("array_init", this, size);
    init_elts(this, size, _element);
  }
  pragma "inline" def this(i : int) {
    return __primitive("array_get", this, i);
  }
  pragma "inline" def =this(i : int, val : elt_type) {
    __primitive("array_set", this, i, val);
  }
}

// synch variable support
pragma "inline" def _init( cv: _mutex_p) return __primitive( "mutex_new");
pragma "inline" def =( a: _mutex_p, b: _mutex_p) return b;
pragma "inline" def _init( cv: _condvar_p) return __primitive( "condvar_new");
pragma "inline" def =( a: _condvar_p, b: _condvar_p) return b;

// synch variable
pragma "sync var" pragma "no default functions"
record _syncvar {
  type t;
  var  value: t;             // actual data
  var  is_full: bool;
  var  lock: _mutex_p;       // need to acquire before accessing this record
  var  cv_empty: _condvar_p; // wait for empty, signal this when empty
  var  cv_full: _condvar_p;  // wait for full, signal this when full

  def initialize() {
    is_full = false;
    lock = __primitive( "mutex_new");
    cv_empty = __primitive( "condvar_new");
    cv_full = __primitive( "condvar_new");
  }
}

def _init( sv:_syncvar) {
  return _syncvar( sv.value.type);
}

// The operations are:
//  = (i.e., write_wait_empty_leave_full)
//  writeFE - wait full, leave empty
//  writeXF - no wait, leave full
//  writeXE - no wait, leave empty
//  readFE - wait full, leave empty
//  readFF - wait full, leave full
//  readXF - no wait, leave full
//  readXX - no wait, leave F/E unchanged

// wait for empty, leaves full. This is the default write on sync vars.
def =( sv:_syncvar, value:sv.t) {
  __primitive( "syncvar_lock", sv);
  if (sv.is_full) {
    __primitive( "syncvar_wait_empty", sv);
  }
  sv.value = value;
  sv.is_full = true;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
  return sv;
}

// wait full, leave empty.
def writeFE( sv:_syncvar, value:sv.t) {
  __primitive( "syncvar_lock", sv);
  if (!sv.is_full) {
    __primitive( "syncvar_wait_full", sv);
  }
  sv.value = value;
  sv.is_full = false;
  __primitive( "syncvar_signal_empty", sv);
  __primitive( "syncvar_unlock", sv);
  return sv;
}

// no wait, leave full.
def writeXF( sv:_syncvar, value:sv.t) {
  __primitive( "syncvar_lock", sv);
  sv.value = value;
  sv.is_full = true;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
}

// no wait, leave empty. One use of this is with using sync var as a lock.
def writeXE( sv:_syncvar, value:sv.t) {
  __primitive( "syncvar_lock", sv);
  sv.value = value;
  sv.is_full = false;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
}

// wait for full, leave empty. This is the default read on sync vars.
def readFE( sv:_syncvar) {
  var ret: sv.t;
  __primitive( "syncvar_lock", sv);
  if (!sv.is_full) {
    __primitive( "syncvar_wait_full", sv);
  }
  ret = sv.value;
  sv.is_full = false;
  __primitive( "syncvar_signal_empty", sv);
  __primitive( "syncvar_unlock", sv);
  return ret;
}

// wait for full, leave full.
def readFF( sv:_syncvar) {
  var ret: sv.t;
  __primitive( "syncvar_lock", sv);
  if (!sv.is_full) {
    __primitive( "syncvar_wait_full", sv);
  }
  ret = sv.value;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
  return ret;
}

// no wait, leave full.
def readXF( sv:_syncvar) {
  var ret: sv.t;
  __primitive( "syncvar_lock", sv);
  ret = sv.value;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
  return ret;
}

// read value.  No state change or signals
def readXX( sv:_syncvar) {
  var ret: sv.t;
  __primitive( "syncvar_lock", sv);
  ret = sv.value;
  __primitive( "syncvar_unlock", sv);
  return ret;
}

def isFull( sv:_syncvar) {
  var isfull: bool;
  __primitive( "syncvar_lock", sv);
  isfull = sv.is_full;
  __primitive( "syncvar_unlock", sv);
  return isfull;
}

//
// MOVE THESE, maybe to a memory module?
//
pragma "no codegen" def _chpl_memtest_printMemTable();
pragma "no codegen" def _chpl_memtest_printMemStat();
pragma "no codegen" def _chpl_memtest_resetMemStat();
pragma "no codegen" def _chpl_memtest_allocAndFree();
pragma "no codegen" def _chpl_memtest_freedMalloc();
pragma "no codegen" def _chpl_memtest_freedWithoutMalloc();
pragma "no codegen" def _chpl_memtest_reallocWithoutMalloc();
pragma "no codegen" def _chpl_memtest_reallocZeroSize();
pragma "no codegen" def _chpl_memtest_mallocOutOfMemory();
pragma "no codegen" def _chpl_memtest_reallocOutOfMemory();

pragma "no codegen" def startTrackingMem();

// _chpl_base module

pragma "inline" def _chpl_alloc(type t, description:string)
  return __primitive("chpl_alloc", t, description);

// Primitive functions and operators on bool
pragma "inline" def =(a: bool, b: bool) return b;
//pragma "inline" def _copy(a: bool) return a;
pragma "inline" def ~(a: bool) return __primitive("u~", a);
pragma "inline" def &(a: bool, b: bool) return __primitive("&", a, b);
pragma "inline" def |(a: bool, b: bool) return __primitive("|", a, b);
pragma "inline" def ^(a: bool, b: bool) return __primitive("^", a, b);
pragma "inline" def ==(a: bool, b: bool) return __primitive("==", a, b);
pragma "inline" def !=(a: bool, b: bool) return __primitive("!=", a, b);
pragma "inline" def <=(a: bool, b: bool) return __primitive("<=", a, b);
pragma "inline" def >=(a: bool, b: bool) return __primitive(">=", a, b);
pragma "inline" def <(a: bool, b: bool) return __primitive("<", a, b);
pragma "inline" def >(a: bool, b: bool) return __primitive(">", a, b);
pragma "inline" def !(a: bool) return __primitive("!", a);
pragma "inline" def &&(a: bool, b: bool) return __primitive("&&", a, b);
pragma "inline" def ||(a: bool, b: bool) return __primitive("||", a, b);

// Primitive functions and operators on int(8)
pragma "inline" def =(a: int(8), b: int) return b:int(8);
//pragma "inline" def _copy(a: int(8)) return a;
pragma "inline" def +(a: int(8)) return __primitive("u+", a);
pragma "inline" def -(a: int(8)) return __primitive("u-", a);
pragma "inline" def +(a: int(8), b: int(8)) return __primitive("+", a, b);
pragma "inline" def -(a: int(8), b: int(8)) return __primitive("-", a, b);
pragma "inline" def *(a: int(8), b: int(8)) return __primitive("*", a, b);
pragma "inline" def /(a: int(8), b: int(8)) return __primitive("/", a, b);
pragma "inline" def **(a: int(8), b: int(8)) return __primitive("**", a, b);
pragma "inline" def %(a: int(8), b: int(8)) return __primitive("%", a, b);
pragma "inline" def ~(a: int(8)) return __primitive("u~", a);
pragma "inline" def &(a: int(8), b: int(8)) return __primitive("&", a, b);
pragma "inline" def |(a: int(8), b: int(8)) return __primitive("|", a, b);
pragma "inline" def ^(a: int(8), b: int(8)) return __primitive("^", a, b);
pragma "inline" def <<(a: int(8), b: int(8)) return __primitive("<<", a, b);
pragma "inline" def >>(a: int(8), b: int(8)) return __primitive(">>", a, b);
pragma "inline" def ==(a: int(8), b: int(8)) return __primitive("==", a, b);
pragma "inline" def !=(a: int(8), b: int(8)) return __primitive("!=", a, b);
pragma "inline" def <=(a: int(8), b: int(8)) return __primitive("<=", a, b);
pragma "inline" def >=(a: int(8), b: int(8)) return __primitive(">=", a, b);
pragma "inline" def <(a: int(8), b: int(8)) return __primitive("<", a, b);
pragma "inline" def >(a: int(8), b: int(8)) return __primitive(">", a, b);
pragma "inline" def !(a: int(8)) return __primitive("!", a);
pragma "inline" def &&(a: int(8), b: int(8)) return __primitive("&&", a, b);
pragma "inline" def ||(a: int(8), b: int(8)) return __primitive("||", a, b);

// Primitive functions and operators on int(16)
pragma "inline" def =(a: int(16), b: int) return b:int(16);
//pragma "inline" def _copy(a: int(16)) return a;
pragma "inline" def +(a: int(16)) return __primitive("u+", a);
pragma "inline" def -(a: int(16)) return __primitive("u-", a);
pragma "inline" def +(a: int(16), b: int(16)) return __primitive("+", a, b);
pragma "inline" def -(a: int(16), b: int(16)) return __primitive("-", a, b);
pragma "inline" def *(a: int(16), b: int(16)) return __primitive("*", a, b);
pragma "inline" def /(a: int(16), b: int(16)) return __primitive("/", a, b);
pragma "inline" def **(a: int(16), b: int(16)) return __primitive("**", a, b);
pragma "inline" def %(a: int(16), b: int(16)) return __primitive("%", a, b);
pragma "inline" def ~(a: int(16)) return __primitive("u~", a);
pragma "inline" def &(a: int(16), b: int(16)) return __primitive("&", a, b);
pragma "inline" def |(a: int(16), b: int(16)) return __primitive("|", a, b);
pragma "inline" def ^(a: int(16), b: int(16)) return __primitive("^", a, b);
pragma "inline" def <<(a: int(16), b: int(16)) return __primitive("<<", a, b);
pragma "inline" def >>(a: int(16), b: int(16)) return __primitive(">>", a, b);
pragma "inline" def ==(a: int(16), b: int(16)) return __primitive("==", a, b);
pragma "inline" def !=(a: int(16), b: int(16)) return __primitive("!=", a, b);
pragma "inline" def <=(a: int(16), b: int(16)) return __primitive("<=", a, b);
pragma "inline" def >=(a: int(16), b: int(16)) return __primitive(">=", a, b);
pragma "inline" def <(a: int(16), b: int(16)) return __primitive("<", a, b);
pragma "inline" def >(a: int(16), b: int(16)) return __primitive(">", a, b);
pragma "inline" def !(a: int(16)) return __primitive("!", a);
pragma "inline" def &&(a: int(16), b: int(16)) return __primitive("&&", a, b);
pragma "inline" def ||(a: int(16), b: int(16)) return __primitive("||", a, b);

// Primitive functions and operators on int(32)
pragma "inline" def =(a: int(32), b: int) return b:int(32);
//pragma "inline" def _copy(a: int(32)) return a;
pragma "inline" def +(a: int(32)) return __primitive("u+", a);
pragma "inline" def -(a: int(32)) return __primitive("u-", a);
pragma "inline" def +(a: int(32), b: int(32)) return __primitive("+", a, b);
pragma "inline" def -(a: int(32), b: int(32)) return __primitive("-", a, b);
pragma "inline" def *(a: int(32), b: int(32)) return __primitive("*", a, b);
pragma "inline" def /(a: int(32), b: int(32)) return __primitive("/", a, b);
pragma "inline" def **(a: int(32), b: int(32)) return __primitive("**", a, b);
pragma "inline" def %(a: int(32), b: int(32)) return __primitive("%", a, b);
pragma "inline" def ~(a: int(32)) return __primitive("u~", a);
pragma "inline" def &(a: int(32), b: int(32)) return __primitive("&", a, b);
pragma "inline" def |(a: int(32), b: int(32)) return __primitive("|", a, b);
pragma "inline" def ^(a: int(32), b: int(32)) return __primitive("^", a, b);
pragma "inline" def <<(a: int(32), b: int(32)) return __primitive("<<", a, b);
pragma "inline" def >>(a: int(32), b: int(32)) return __primitive(">>", a, b);
pragma "inline" def ==(a: int(32), b: int(32)) return __primitive("==", a, b);
pragma "inline" def !=(a: int(32), b: int(32)) return __primitive("!=", a, b);
pragma "inline" def <=(a: int(32), b: int(32)) return __primitive("<=", a, b);
pragma "inline" def >=(a: int(32), b: int(32)) return __primitive(">=", a, b);
pragma "inline" def <(a: int(32), b: int(32)) return __primitive("<", a, b);
pragma "inline" def >(a: int(32), b: int(32)) return __primitive(">", a, b);
pragma "inline" def !(a: int(32)) return __primitive("!", a);
pragma "inline" def &&(a: int(32), b: int(32)) return __primitive("&&", a, b);
pragma "inline" def ||(a: int(32), b: int(32)) return __primitive("||", a, b);

// Primitive functions and operators on int(64)
pragma "inline" def =(a: int(64), b: int(64)) return b;
//pragma "inline" def _copy(a: int(64)) return a;
pragma "inline" def +(a: int(64)) return __primitive("u+", a);
pragma "inline" def -(a: int(64)) return __primitive("u-", a);
pragma "inline" def +(a: int(64), b: int(64)) return __primitive("+", a, b);
pragma "inline" def -(a: int(64), b: int(64)) return __primitive("-", a, b);
pragma "inline" def *(a: int(64), b: int(64)) return __primitive("*", a, b);
pragma "inline" def /(a: int(64), b: int(64)) return __primitive("/", a, b);
pragma "inline" def **(a: int(64), b: int(64)) return __primitive("**", a, b);
pragma "inline" def %(a: int(64), b: int(64)) return __primitive("%", a, b);
pragma "inline" def ~(a: int(64)) return __primitive("u~", a);
pragma "inline" def &(a: int(64), b: int(64)) return __primitive("&", a, b);
pragma "inline" def |(a: int(64), b: int(64)) return __primitive("|", a, b);
pragma "inline" def ^(a: int(64), b: int(64)) return __primitive("^", a, b);
pragma "inline" def <<(a: int(64), b: int(64)) return __primitive("<<", a, b);
pragma "inline" def >>(a: int(64), b: int(64)) return __primitive(">>", a, b);
pragma "inline" def ==(a: int(64), b: int(64)) return __primitive("==", a, b);
pragma "inline" def !=(a: int(64), b: int(64)) return __primitive("!=", a, b);
pragma "inline" def <=(a: int(64), b: int(64)) return __primitive("<=", a, b);
pragma "inline" def >=(a: int(64), b: int(64)) return __primitive(">=", a, b);
pragma "inline" def <(a: int(64), b: int(64)) return __primitive("<", a, b);
pragma "inline" def >(a: int(64), b: int(64)) return __primitive(">", a, b);
pragma "inline" def !(a: int(64)) return __primitive("!", a);
pragma "inline" def &&(a: int(64), b: int(64)) return __primitive("&&", a, b);
pragma "inline" def ||(a: int(64), b: int(64)) return __primitive("||", a, b);

// Primitive functions and operators on uint(8)
pragma "inline" def =(a: uint(8), b: uint) return b:uint(8);
//pragma "inline" def _copy(a: uint(8)) return a;
pragma "inline" def +(a: uint(8)) return __primitive("u+", a);
pragma "inline" def -(a: uint(8)) return __primitive("u-", a);
pragma "inline" def +(a: uint(8), b: uint(8)) return __primitive("+", a, b);
pragma "inline" def -(a: uint(8), b: uint(8)) return __primitive("-", a, b);
pragma "inline" def *(a: uint(8), b: uint(8)) return __primitive("*", a, b);
pragma "inline" def /(a: uint(8), b: uint(8)) return __primitive("/", a, b);
pragma "inline" def **(a: uint(8), b: uint(8)) return __primitive("**", a, b);
pragma "inline" def %(a: uint(8), b: uint(8)) return __primitive("%", a, b);
pragma "inline" def ~(a: uint(8)) return __primitive("u~", a);
pragma "inline" def &(a: uint(8), b: uint(8)) return __primitive("&", a, b);
pragma "inline" def |(a: uint(8), b: uint(8)) return __primitive("|", a, b);
pragma "inline" def ^(a: uint(8), b: uint(8)) return __primitive("^", a, b);
pragma "inline" def <<(a: uint(8), b: uint(8)) return __primitive("<<", a, b);
pragma "inline" def >>(a: uint(8), b: uint(8)) return __primitive(">>", a, b);
pragma "inline" def ==(a: uint(8), b: uint(8)) return __primitive("==", a, b);
pragma "inline" def !=(a: uint(8), b: uint(8)) return __primitive("!=", a, b);
pragma "inline" def <=(a: uint(8), b: uint(8)) return __primitive("<=", a, b);
pragma "inline" def >=(a: uint(8), b: uint(8)) return __primitive(">=", a, b);
pragma "inline" def <(a: uint(8), b: uint(8)) return __primitive("<", a, b);
pragma "inline" def >(a: uint(8), b: uint(8)) return __primitive(">", a, b);
pragma "inline" def !(a: uint(8)) return __primitive("!", a);
pragma "inline" def &&(a: uint(8), b: uint(8)) return __primitive("&&", a, b);
pragma "inline" def ||(a: uint(8), b: uint(8)) return __primitive("||", a, b);

// Primitive functions and operators on uint(16)
pragma "inline" def =(a: uint(16), b: uint) return b:uint(16);
//pragma "inline" def _copy(a: uint(16)) return a;
pragma "inline" def +(a: uint(16)) return __primitive("u+", a);
pragma "inline" def -(a: uint(16)) return __primitive("u-", a);
pragma "inline" def +(a: uint(16), b: uint(16)) return __primitive("+", a, b);
pragma "inline" def -(a: uint(16), b: uint(16)) return __primitive("-", a, b);
pragma "inline" def *(a: uint(16), b: uint(16)) return __primitive("*", a, b);
pragma "inline" def /(a: uint(16), b: uint(16)) return __primitive("/", a, b);
pragma "inline" def **(a: uint(16), b: uint(16)) return __primitive("**", a, b);
pragma "inline" def %(a: uint(16), b: uint(16)) return __primitive("%", a, b);
pragma "inline" def ~(a: uint(16)) return __primitive("u~", a);
pragma "inline" def &(a: uint(16), b: uint(16)) return __primitive("&", a, b);
pragma "inline" def |(a: uint(16), b: uint(16)) return __primitive("|", a, b);
pragma "inline" def ^(a: uint(16), b: uint(16)) return __primitive("^", a, b);
pragma "inline" def <<(a: uint(16), b: uint(16)) return __primitive("<<", a, b);
pragma "inline" def >>(a: uint(16), b: uint(16)) return __primitive(">>", a, b);
pragma "inline" def ==(a: uint(16), b: uint(16)) return __primitive("==", a, b);
pragma "inline" def !=(a: uint(16), b: uint(16)) return __primitive("!=", a, b);
pragma "inline" def <=(a: uint(16), b: uint(16)) return __primitive("<=", a, b);
pragma "inline" def >=(a: uint(16), b: uint(16)) return __primitive(">=", a, b);
pragma "inline" def <(a: uint(16), b: uint(16)) return __primitive("<", a, b);
pragma "inline" def >(a: uint(16), b: uint(16)) return __primitive(">", a, b);
pragma "inline" def !(a: uint(16)) return __primitive("!", a);
pragma "inline" def &&(a: uint(16), b: uint(16)) return __primitive("&&", a, b);
pragma "inline" def ||(a: uint(16), b: uint(16)) return __primitive("||", a, b);

// Primitive functions and operators on uint(32)
pragma "inline" def =(a: uint(32), b: uint) return b:uint(32);
//pragma "inline" def _copy(a: uint(32)) return a;
pragma "inline" def +(a: uint(32)) return __primitive("u+", a);
pragma "inline" def -(a: uint(32)) return __primitive("u-", a);
pragma "inline" def +(a: uint(32), b: uint(32)) return __primitive("+", a, b);
pragma "inline" def -(a: uint(32), b: uint(32)) return __primitive("-", a, b);
pragma "inline" def *(a: uint(32), b: uint(32)) return __primitive("*", a, b);
pragma "inline" def /(a: uint(32), b: uint(32)) return __primitive("/", a, b);
pragma "inline" def **(a: uint(32), b: uint(32)) return __primitive("**", a, b);
pragma "inline" def %(a: uint(32), b: uint(32)) return __primitive("%", a, b);
pragma "inline" def ~(a: uint(32)) return __primitive("u~", a);
pragma "inline" def &(a: uint(32), b: uint(32)) return __primitive("&", a, b);
pragma "inline" def |(a: uint(32), b: uint(32)) return __primitive("|", a, b);
pragma "inline" def ^(a: uint(32), b: uint(32)) return __primitive("^", a, b);
pragma "inline" def <<(a: uint(32), b: uint(32)) return __primitive("<<", a, b);
pragma "inline" def >>(a: uint(32), b: uint(32)) return __primitive(">>", a, b);
pragma "inline" def ==(a: uint(32), b: uint(32)) return __primitive("==", a, b);
pragma "inline" def !=(a: uint(32), b: uint(32)) return __primitive("!=", a, b);
pragma "inline" def <=(a: uint(32), b: uint(32)) return __primitive("<=", a, b);
pragma "inline" def >=(a: uint(32), b: uint(32)) return __primitive(">=", a, b);
pragma "inline" def <(a: uint(32), b: uint(32)) return __primitive("<", a, b);
pragma "inline" def >(a: uint(32), b: uint(32)) return __primitive(">", a, b);
pragma "inline" def !(a: uint(32)) return __primitive("!", a);
pragma "inline" def &&(a: uint(32), b: uint(32)) return __primitive("&&", a, b);
pragma "inline" def ||(a: uint(32), b: uint(32)) return __primitive("||", a, b);

// Primitive functions and operators on uint(64)
pragma "inline" def =(a: uint(64), b: uint(64)) return b;
//pragma "inline" def _copy(a: uint(64)) return a;
pragma "inline" def +(a: uint(64)) return __primitive("u+", a);
pragma "inline" def -(a: uint(64)) return __primitive("u-", a);
pragma "inline" def +(a: uint(64), b: uint(64)) return __primitive("+", a, b);
pragma "inline" def -(a: uint(64), b: uint(64)) return __primitive("-", a, b);
pragma "inline" def *(a: uint(64), b: uint(64)) return __primitive("*", a, b);
pragma "inline" def /(a: uint(64), b: uint(64)) return __primitive("/", a, b);
pragma "inline" def **(a: uint(64), b: uint(64)) return __primitive("**", a, b);
pragma "inline" def %(a: uint(64), b: uint(64)) return __primitive("%", a, b);
pragma "inline" def ~(a: uint(64)) return __primitive("u~", a);
pragma "inline" def &(a: uint(64), b: uint(64)) return __primitive("&", a, b);
pragma "inline" def |(a: uint(64), b: uint(64)) return __primitive("|", a, b);
pragma "inline" def ^(a: uint(64), b: uint(64)) return __primitive("^", a, b);
pragma "inline" def <<(a: uint(64), b: uint(64)) return __primitive("<<", a, b);
pragma "inline" def >>(a: uint(64), b: uint(64)) return __primitive(">>", a, b);
pragma "inline" def ==(a: uint(64), b: uint(64)) return __primitive("==", a, b);
pragma "inline" def !=(a: uint(64), b: uint(64)) return __primitive("!=", a, b);
pragma "inline" def <=(a: uint(64), b: uint(64)) return __primitive("<=", a, b);
pragma "inline" def >=(a: uint(64), b: uint(64)) return __primitive(">=", a, b);
pragma "inline" def <(a: uint(64), b: uint(64)) return __primitive("<", a, b);
pragma "inline" def >(a: uint(64), b: uint(64)) return __primitive(">", a, b);
pragma "inline" def !(a: uint(64)) return __primitive("!", a);
pragma "inline" def &&(a: uint(64), b: uint(64)) return __primitive("&&", a, b);
pragma "inline" def ||(a: uint(64), b: uint(64)) return __primitive("||", a, b);

// Primitive functions and operators on float(32)
pragma "inline" def =(a: float(32), b: float) return b:float(32);
//pragma "inline" def _copy(a: float(32)) return a;
pragma "inline" def +(a: float(32)) return __primitive("u+", a);
pragma "inline" def -(a: float(32)) return __primitive("u-", a);
pragma "inline" def +(a: float(32), b: float(32)) return __primitive("+", a, b);
pragma "inline" def -(a: float(32), b: float(32)) return __primitive("-", a, b);
pragma "inline" def *(a: float(32), b: float(32)) return __primitive("*", a, b);
pragma "inline" def /(a: float(32), b: float(32)) return __primitive("/", a, b);
pragma "inline" def **(a: float(32), b: float(32)) return __primitive("**", a, b);
pragma "inline" def ==(a: float(32), b: float(32)) return __primitive("==", a, b);
pragma "inline" def !=(a: float(32), b: float(32)) return __primitive("!=", a, b);
pragma "inline" def <=(a: float(32), b: float(32)) return __primitive("<=", a, b);
pragma "inline" def >=(a: float(32), b: float(32)) return __primitive(">=", a, b);
pragma "inline" def <(a: float(32), b: float(32)) return __primitive("<", a, b);
pragma "inline" def >(a: float(32), b: float(32)) return __primitive(">", a, b);
pragma "inline" def !(a: float(32)) return __primitive("!", a);
pragma "inline" def &&(a: float(32), b: float(32)) return __primitive("&&", a, b);
pragma "inline" def ||(a: float(32), b: float(32)) return __primitive("||", a, b);

// Primitive functions and operators on float(64)
pragma "inline" def =(a: float(64), b: float(64)) return b;
//pragma "inline" def _copy(a: float(64)) return a;
pragma "inline" def +(a: float(64)) return __primitive("u+", a);
pragma "inline" def -(a: float(64)) return __primitive("u-", a);
pragma "inline" def +(a: float(64), b: float(64)) return __primitive("+", a, b);
pragma "inline" def -(a: float(64), b: float(64)) return __primitive("-", a, b);
pragma "inline" def *(a: float(64), b: float(64)) return __primitive("*", a, b);
pragma "inline" def /(a: float(64), b: float(64)) return __primitive("/", a, b);
pragma "inline" def **(a: float(64), b: float(64)) return __primitive("**", a, b);
pragma "inline" def ==(a: float(64), b: float(64)) return __primitive("==", a, b);
pragma "inline" def !=(a: float(64), b: float(64)) return __primitive("!=", a, b);
pragma "inline" def <=(a: float(64), b: float(64)) return __primitive("<=", a, b);
pragma "inline" def >=(a: float(64), b: float(64)) return __primitive(">=", a, b);
pragma "inline" def <(a: float(64), b: float(64)) return __primitive("<", a, b);
pragma "inline" def >(a: float(64), b: float(64)) return __primitive(">", a, b);
pragma "inline" def !(a: float(64)) return __primitive("!", a);
pragma "inline" def &&(a: float(64), b: float(64)) return __primitive("&&", a, b);
pragma "inline" def ||(a: float(64), b: float(64)) return __primitive("||", a, b);

// Primitive functions and operators on string
pragma "inline" def =(a: string, b: string) return __primitive("string_copy", b);
//pragma "inline" def _copy(x : string) {
//  var y : string;
//  y = x;
//  return y;
//}
pragma "inline" def ==(a: string, b: string) return __primitive("string_equal", a, b);
pragma "inline" def !=(a: string, b: string) return !(a == b);
pragma "inline" def +(a: string, b: string) return __primitive("string_concat", a, b);
pragma "inline" def length(a: string) return __primitive("string_length", a);
pragma "inline" def string.this(i: int) return __primitive("string_index", this, i);

pragma "inline" def _string_contains(a: string, b: string)
  return __primitive("string_contains", a, b);

pragma "inline" def _tostring(x : bool, format : string)
  return __primitive("to_string", format, x);

pragma "inline" def _tostring(x : int, format : string)
  return __primitive("to_string", format, x);

pragma "inline" def _tostring(x : float, format : string)
  return __primitive("to_string", format, x);

pragma "inline" def ascii(a: string) return __primitive("ascii", a);

//
// Primitive funs for objects
//
pragma "inline" def ==(a: object, b: object) return __primitive("ptr_eq", a, b);
pragma "inline" def !=(a: object, b: object) return __primitive("ptr_neq", a, b);
pragma "inline" def =(a, b:object) return b:a.type;
pragma "inline" def _copy(a) return a;

//
// _init
//
pragma "inline" def _init(x : bool) return false;
pragma "inline" def _init(x : int) return 0;
pragma "inline" def _init(x : float) return 0.0;
pragma "inline" def _init(x : string) return "";
pragma "inline" def _init(x) return nil:x;

// identity functions (for reduction operations)
pragma "inline" def _prod_id( type t) return __primitive( "_prod_id", t);
pragma "inline" def _land_id( type t) return __primitive( "_land_id", t);
pragma "inline" def _lor_id( type t) return __primitive( "_lor_id", t);
pragma "inline" def _lxor_id( type t) return __primitive( "_lxor_id", t);
pragma "inline" def _band_id( type t) return __primitive( "_band_id", t);
pragma "inline" def _bor_id( type t) return __primitive( "_bor_id", t);
pragma "inline" def _bxor_id( type t) return __primitive( "_bxor_id", t);

// predefined functions
pragma "inline" def _min( type t) return __primitive( "_min", t);
pragma "inline" def _max( type t) return __primitive( "_max", t);

//
// More primitive funs
//
pragma "no codegen" pragma "rename _chpl_exit" def exit(status : int) {
  __primitive("exit");
}

pragma "no codegen" pragma "rename fflush" def fflush(fp: _file) : int {
  return __primitive("fflush", fp);
}

def init_elts(x, s, e) {
  for i in 1..s {
    var y : e.type;
    x(i-1) = y;
  }
}

// dynamic data block class
pragma "data class"
class _ddata {
  type elt_type;
  var size : int;
  var _element : elt_type;
  pragma "inline" def init() {
    __primitive("array_init", this, size);
    init_elts(this, size, _element);
  }
  pragma "inline" def this(i : int) {
    return __primitive("array_get", this, i);
  }
  pragma "inline" def =this(i : int, val : elt_type) {
    __primitive("array_set", this, i, val);
  }
}

// synch variable support
pragma "inline" def _init( cv: _mutex_p) return __primitive( "mutex_new");
pragma "inline" def =( a: _mutex_p, b: _mutex_p) return b;
pragma "inline" def _init( cv: _condvar_p) return __primitive( "condvar_new");
pragma "inline" def =( a: _condvar_p, b: _condvar_p) return b;

// synch variable
pragma "sync var" pragma "no default functions"
record _syncvar {
  type t;
  var  value: t;             // actual data
  var  is_full: bool;
  var  lock: _mutex_p;       // need to acquire before accessing this record
  var  cv_empty: _condvar_p; // wait for empty, signal this when empty
  var  cv_full: _condvar_p;  // wait for full, signal this when full

  def initialize() {
    is_full = false;
    lock = __primitive( "mutex_new");
    cv_empty = __primitive( "condvar_new");
    cv_full = __primitive( "condvar_new");
  }
}

def _init( sv:_syncvar) {
  return _syncvar( sv.value.type);
}

// The operations are:
//  = (i.e., write_wait_empty_leave_full)
//  writeFE - wait full, leave empty
//  writeXF - no wait, leave full
//  writeXE - no wait, leave empty
//  readFE - wait full, leave empty
//  readFF - wait full, leave full
//  readXF - no wait, leave full
//  readXX - no wait, leave F/E unchanged

// wait for empty, leaves full. This is the default write on sync vars.
def =( sv:_syncvar, value:sv.t) {
  __primitive( "syncvar_lock", sv);
  if (sv.is_full) {
    __primitive( "syncvar_wait_empty", sv);
  }
  sv.value = value;
  sv.is_full = true;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
  return sv;
}

// wait full, leave empty.
def writeFE( sv:_syncvar, value:sv.t) {
  __primitive( "syncvar_lock", sv);
  if (!sv.is_full) {
    __primitive( "syncvar_wait_full", sv);
  }
  sv.value = value;
  sv.is_full = false;
  __primitive( "syncvar_signal_empty", sv);
  __primitive( "syncvar_unlock", sv);
  return sv;
}

// no wait, leave full.
def writeXF( sv:_syncvar, value:sv.t) {
  __primitive( "syncvar_lock", sv);
  sv.value = value;
  sv.is_full = true;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
}

// no wait, leave empty. One use of this is with using sync var as a lock.
def writeXE( sv:_syncvar, value:sv.t) {
  __primitive( "syncvar_lock", sv);
  sv.value = value;
  sv.is_full = false;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
}

// wait for full, leave empty. This is the default read on sync vars.
def readFE( sv:_syncvar) {
  var ret: sv.t;
  __primitive( "syncvar_lock", sv);
  if (!sv.is_full) {
    __primitive( "syncvar_wait_full", sv);
  }
  ret = sv.value;
  sv.is_full = false;
  __primitive( "syncvar_signal_empty", sv);
  __primitive( "syncvar_unlock", sv);
  return ret;
}

// wait for full, leave full.
def readFF( sv:_syncvar) {
  var ret: sv.t;
  __primitive( "syncvar_lock", sv);
  if (!sv.is_full) {
    __primitive( "syncvar_wait_full", sv);
  }
  ret = sv.value;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
  return ret;
}

// no wait, leave full.
def readXF( sv:_syncvar) {
  var ret: sv.t;
  __primitive( "syncvar_lock", sv);
  ret = sv.value;
  __primitive( "syncvar_signal_full", sv);
  __primitive( "syncvar_unlock", sv);
  return ret;
}

// read value.  No state change or signals
def readXX( sv:_syncvar) {
  var ret: sv.t;
  __primitive( "syncvar_lock", sv);
  ret = sv.value;
  __primitive( "syncvar_unlock", sv);
  return ret;
}

def isFull( sv:_syncvar) {
  var isfull: bool;
  __primitive( "syncvar_lock", sv);
  isfull = sv.is_full;
  __primitive( "syncvar_unlock", sv);
  return isfull;
}

//
// MOVE THESE, maybe to a memory module?
//
pragma "no codegen" def _chpl_memtest_printMemTable();
pragma "no codegen" def _chpl_memtest_printMemStat();
pragma "no codegen" def _chpl_memtest_resetMemStat();
pragma "no codegen" def _chpl_memtest_allocAndFree();
pragma "no codegen" def _chpl_memtest_freedMalloc();
pragma "no codegen" def _chpl_memtest_freedWithoutMalloc();
pragma "no codegen" def _chpl_memtest_reallocWithoutMalloc();
pragma "no codegen" def _chpl_memtest_reallocZeroSize();
pragma "no codegen" def _chpl_memtest_mallocOutOfMemory();
pragma "no codegen" def _chpl_memtest_reallocOutOfMemory();

pragma "no codegen" def startTrackingMem();


To avoid PGI warnings about divide by zero when trying to fold the literal
expression 1.0 / 0.0, add const zero:real = 0.0, and replace the literal 0.0s
with the zero const.

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

var f: real;
var c: complex;
const zero: real = 0.0; // To avoid C compiler folding of 1.0 / 0.0

f = 1.0 / zero;
writeln("f is: ", f);

f = sqrt(-1.0);
writeln("f is: ", f);

f = -1.0 / zero;
writeln("f is: ", f);

f = -1.0 / max(real);
f = f / max(real);
writeln("f is: ", f);
writeln();

c.re = 1.0 / zero;
writeln("c is: ", c);

c.re = sqrt(-1.0);
writeln("c is: ", c);

c.re = -1.0 / zero;
writeln("c is: ", c);

c.re = -1.0 / max(real);
c.re = c.re / max(real);
writeln("c is: ", c);
writeln();

c = 0.0 + 0.0i;

c.im = 1.0 / zero;
writeln("c is: ", c);

c.im = sqrt(-1.0);
writeln("c is: ", c);

c.im = -1.0 / zero;
writeln("c is: ", c);

c.im = -1.0 / max(real);
c.im = c.im / max(real);
writeln("c is: ", c);
writeln();

var f: real;
var c: complex;

f = 1.0 / 0.0;
writeln("f is: ", f);

f = sqrt(-1.0);
writeln("f is: ", f);

f = -1.0 / 0.0;
writeln("f is: ", f);

f = -1.0 / max(real);
f = f / max(real);
writeln("f is: ", f);
writeln();

c.re = 1.0 / 0.0;
writeln("c is: ", c);

c.re = sqrt(-1.0);
writeln("c is: ", c);

c.re = -1.0 / 0.0;
writeln("c is: ", c);

c.re = -1.0 / max(real);
c.re = c.re / max(real);
writeln("c is: ", c);
writeln();

c = 0.0 + 0.0i;

c.im = 1.0 / 0.0;
writeln("c is: ", c);

c.im = sqrt(-1.0);
writeln("c is: ", c);

c.im = -1.0 / 0.0;
writeln("c is: ", c);

c.im = -1.0 / max(real);
c.im = c.im / max(real);
writeln("c is: ", c);
writeln();