Can't see why 1D and 3D should be treated differently here.

config const debugInit = false;

// Configs if we're init-ing from a file

config const filename = "";
const initFromFile = (filename != "");

// Configs if we're computing the input set

config const elemsPerEdge = 0;
config const initialWidth = 1.125;

// Verify that configs are set appropriately

if initFromFile {
  if elemsPerEdge != 0 then
    writeln("WARNING: --elemsPerEdge has no effect when using an input file");
}  else {
  if elemsPerEdge == 0 then
    halt("you must either set --filename or --elemsPerEdge to run LULESH");
}

// Helper variables for reading from a file

var infile: file;
var reader: channel(false, iokind.dynamic, true);

if initFromFile {
  infile = open(filename, iomode.r);
  reader = infile.reader();
}

// Helper variables for computing the index set

param numDims = 3;

const nodesPerEdge = elemsPerEdge + 1,
      DimNodeRange = 0..#nodesPerEdge,
      DimNodeFace  = {DimNodeRange, DimNodeRange};

// read/compute the problem size

proc initProblemSize() {
  const (numElems, numNodes) = if (initFromFile) then
                                 reader.read(int, int)
                               else
                                 (elemsPerEdge**numDims, nodesPerEdge**numDims);

  if (debugInit) then
    writeln(numElems, " ", numNodes);

  return (numElems, numNodes);
}

// read/compute the coordinates

proc initCoordinates(X, Y, Z) {
  if (initFromFile) {
    for (x,y,z) in zip(X,Y,Z) do
      reader.read(x, y, z);
  } else {
    forall (num, x, y, z) in zip(X.domain, X, Y, Z) {
      const (i,j,k) = nodeIdxTo3D(num);
      x = initialWidth * k / elemsPerEdge;
      y = initialWidth * j / elemsPerEdge;
      z = initialWidth * i / elemsPerEdge;
    }
  }

  if debugInit then
    for (x,y,z) in zip(X,Y,Z) do
      writef("%6dr %6dr %6dr\n", x, y, z);
}

// read/compute the element-to-node mapping

proc initElemToNodeMapping(elemToNode: [?D]) {
  if (initFromFile) {
    param nodesPerElem = elemToNode[D.low].size;
    for nodelist in elemToNode do
      for i in 1..nodesPerElem do
        reader.read(nodelist[i]);

    if debugInit {
      writeln("elemToNode mappings are:");
      for nodelist in elemToNode do
        writeln(nodelist);
    }
  } else {
    forall (num, nodelist) in zip(elemToNode.domain, elemToNode) {
      const (i,j,k) = elemIdxTo3D(num);
      nodelist[1] = node3DToIdx(D.rank, i,   j,   k  );
      nodelist[2] = node3DToIdx(D.rank, i,   j,   k+1);
      nodelist[3] = node3DToIdx(D.rank, i,   j+1, k+1);
      nodelist[4] = node3DToIdx(D.rank, i,   j+1, k  );
      nodelist[5] = node3DToIdx(D.rank, i+1, j,   k  );
      nodelist[6] = node3DToIdx(D.rank, i+1, j,   k+1);
      nodelist[7] = node3DToIdx(D.rank, i+1, j+1, k+1);
      nodelist[8] = node3DToIdx(D.rank, i+1, j+1, k  );
    }
  }

  if debugInit then
    for nodelist in elemToNode {
      for i in 1..nodelist.size do
        write(nodelist(i), " ");
      writeln();
    }
}

// read/compute the greek variables

proc initGreekVars(lxim, lxip, letam, letap, lzetam, lzetap) {
  param elemRank = lxim.domain.rank;
  if (initFromFile) {
    for (xm,xp,em,ep,zm,zp) in zip(lxim, lxip, letam, letap, lzetam, lzetap) do
      reader.read(xm,xp,em,ep,zm,zp);
  } else {
    forall num in lxim.domain {
      const (i,j,k) = elemIdxTo3D(num);

      lxim[num] = if (k == 0)
                    then num
                    else elem3DToIdx(elemRank,i,j,k-1);

      lxip[num] = if (k == elemsPerEdge-1)
                    then num
                      else elem3DToIdx(elemRank,i,j,k+1);

      letam[num] = if (j == 0)
                    then num
                      else elem3DToIdx(elemRank,i,j-1,k);

      letap[num] = if (j == elemsPerEdge-1)
                    then num
                    else elem3DToIdx(elemRank,i,j+1,k);

      lzetam[num] = if (i == 0)
                    then num
                    else elem3DToIdx(elemRank,i-1,j,k);

      lzetap[num] = if (i == elemsPerEdge-1)
                    then num
                    else elem3DToIdx(elemRank,i+1,j,k);
    }
  }
  if (debugInit) then
    for (xm,xp,em,ep,zm,zp) in zip(lxim, lxip, letam, letap, lzetam, lzetap) do
      writeln(xm, " ", xp, " ", em, " ", ep, " ", zm, " ", zp);
}

// read/compute the X, Y, Z symmetry planes

enum dim { X = 3, Y = 2, Z = 1 };

inline proc initSyms(Sym, dir) {
  if (initFromFile) {
    readNodeset(Sym);
  } else {
    for ij in DimNodeFace do
      Sym += node2DToIdx(Sym.rank, ij, dir, 0);
  }

  if debugInit {
    writeln(Sym.numIndices);
    for n in Sym do
      writeln(n);
  }

  return (Sym.numIndices, Sym);
}

inline proc initXSyms(XSym) {
  initSyms(XSym, dim.X);
}

inline proc initYSyms(YSym) {
  initSyms(YSym, dim.Y);
}

inline proc initZSyms(ZSym) {
  initSyms(ZSym, dim.Z);
}

// read/compute the free surface

inline proc initFreeSurface(freeSurface) {
  if (initFromFile) {
    readNodeset(freeSurface);
    reader.assertEOF("Input file format error (extra data at EOF)");
  } else {
    for ij in DimNodeFace do
      freeSurface += node2DToIdx(freeSurface.rank, ij, dim.X, nodesPerEdge-1);

    for ij in DimNodeFace do
      freeSurface += node2DToIdx(freeSurface.rank, ij, dim.Y, nodesPerEdge-1);

    for ij in DimNodeFace do
      freeSurface += node2DToIdx(freeSurface.rank, ij, dim.Z, nodesPerEdge-1);
  }

  if debugInit {
    use Sort;

    const size = freeSurface.size;
    var sortedSurface: [0..#size] if (freeSurface.rank == 1)
                                    then freeSurface.idxType
                                    else freeSurface.rank*freeSurface.idxType;

    for (a,b) in zip(sortedSurface, freeSurface) do a = b;
    QuickSort(sortedSurface);

    writeln(size);
    for b in sortedSurface do
      writeln(b);
  }
  return (freeSurface.numIndices, freeSurface);
}

// Helper routines for reading from a file

/* This is a helper routine to read a size and array from a file and
   return it */

proc readNodeset(nodeset) {
  if (nodeset.rank == 1) {
    const arrSize = reader.read(int);

    for a in 0..#arrSize do
      nodeset += reader.read(int);
  } else {
    halt("We shouldn't get here -- no file I/O with the 3D representation");
  }
}

// Helper routines for computing the cube input set

inline proc idx3DTo1D((i,j,k), len) {
  return i*len*len + j*len + k;
}

inline proc node3DToIdx(param idxRank, i, j, k) {
  if (idxRank == 3) then
    return (i, j, k);
  else
    return idx3DTo1D((i, j, k), nodesPerEdge);
}

inline proc elem3DToIdx(param idxRank, i,j,k) {
  if (idxRank == 3) then
    return (i,j,k);
  else
    return idx3DTo1D((i,j,k), elemsPerEdge);
}

inline proc idx1DTo3D(ind, len) {
  return (ind/(len*len), (ind/len)%len, ind%len);
}

inline proc nodeIdxTo3D(ind) {
  if isTuple(ind) then
    return ind;
  else
    return idx1DTo3D(ind, nodesPerEdge);
}

inline proc elemIdxTo3D(ind) {
  if isTuple(ind) then
    return ind;
  else
    return idx1DTo3D(ind, elemsPerEdge);
}

/* Turn a 2D node index into a 3D index by inserting the value
   'newval' in diemnsion 'newdim' */

inline proc node2DToIdx(param rank, ij, newdim, newval) {
  var ijk: 3*int;
  for i in 1..numDims do
    ijk[i] = if (i==newdim) then newval else ij[i - (i>newdim):int];
  return node3DToIdx(rank, (...ijk));
}

config const debugInit = false;

// Configs if we're init-ing from a file

config const filename = "";
const initFromFile = (filename != "");

// Configs if we're computing the input set

config const elemsPerEdge = 0;
config const initialWidth = 1.125;

// Verify that configs are set appropriately

if initFromFile {
  if elemsPerEdge != 0 then
    writeln("WARNING: --elemsPerEdge has no effect when using an input file");
}  else {
  if elemsPerEdge == 0 then
    halt("you must either set --filename or --elemsPerEdge to run LULESH");
}

// Helper variables for reading from a file

var infile: file;
var reader: channel(false, iokind.dynamic, true);

if initFromFile {
  infile = open(filename, iomode.r);
  reader = infile.reader();
}

// Helper variables for computing the index set

param numDims = 3;

const nodesPerEdge = elemsPerEdge + 1,
      DimNodeRange = 0..#nodesPerEdge,
      DimNodeFace  = {DimNodeRange, DimNodeRange};

// read/compute the problem size

proc initProblemSize() {
  const (numElems, numNodes) = if (initFromFile) then
                                 reader.read(int, int)
                               else
                                 (elemsPerEdge**numDims, nodesPerEdge**numDims);

  if (debugInit) then
    writeln(numElems, " ", numNodes);

  return (numElems, numNodes);
}

// read/compute the coordinates

proc initCoordinates(X, Y, Z) {
  if (initFromFile) {
    for (x,y,z) in zip(X,Y,Z) do
      reader.read(x, y, z);
  } else {
    forall (num, x, y, z) in zip(X.domain, X, Y, Z) {
      const (i,j,k) = nodeIdxTo3D(num);
      x = initialWidth * k / elemsPerEdge;
      y = initialWidth * j / elemsPerEdge;
      z = initialWidth * i / elemsPerEdge;
    }
  }

  if debugInit then
    for (x,y,z) in zip(X,Y,Z) do
      writef("%6dr %6dr %6dr\n", x, y, z);
}

// read/compute the element-to-node mapping

proc initElemToNodeMapping(elemToNode: [?D]) {
  if (initFromFile) {
    param nodesPerElem = elemToNode[D.low].size;
    for nodelist in elemToNode do
      for i in 1..nodesPerElem do
        reader.read(nodelist[i]);

    if debugInit {
      writeln("elemToNode mappings are:");
      for nodelist in elemToNode do
        writeln(nodelist);
    }
  } else {
    forall (num, nodelist) in zip(elemToNode.domain, elemToNode) {
      const (i,j,k) = elemIdxTo3D(num);
      nodelist[1] = node3DToIdx(D.rank, i,   j,   k  );
      nodelist[2] = node3DToIdx(D.rank, i,   j,   k+1);
      nodelist[3] = node3DToIdx(D.rank, i,   j+1, k+1);
      nodelist[4] = node3DToIdx(D.rank, i,   j+1, k  );
      nodelist[5] = node3DToIdx(D.rank, i+1, j,   k  );
      nodelist[6] = node3DToIdx(D.rank, i+1, j,   k+1);
      nodelist[7] = node3DToIdx(D.rank, i+1, j+1, k+1);
      nodelist[8] = node3DToIdx(D.rank, i+1, j+1, k  );
    }
  }

  if debugInit then
    for nodelist in elemToNode {
      for i in 1..nodelist.size do
        write(nodelist(i), " ");
      writeln();
    }
}

// read/compute the greek variables

proc initGreekVars(lxim, lxip, letam, letap, lzetam, lzetap) {
  param elemRank = lxim.domain.rank;
  param indices3D = isTupleType(lxim.eltType);
  if (initFromFile) {
    for (xm,xp,em,ep,zm,zp) in zip(lxim, lxip, letam, letap, lzetam, lzetap) do
      reader.read(xm,xp,em,ep,zm,zp);
  } else {
    forall num in lxim.domain {
      const (i,j,k) = elemIdxTo3D(num);

      lxim[num] = if (indices3D && k == 0)
                    then num
                    else elem3DToIdx(elemRank,i,j,k-1);

      lxip[num] = if (indices3D && k == elemsPerEdge-1)
                    then num
                      else elem3DToIdx(elemRank,i,j,k+1);

      letam[num] = if (indices3D && j == 0)
                    then num
                      else elem3DToIdx(elemRank,i,j-1,k);

      letap[num] = if (indices3D && j == elemsPerEdge-1)
                    then num
                    else elem3DToIdx(elemRank,i,j+1,k);

      lzetam[num] = if (indices3D && i == 0)
                    then num
                    else elem3DToIdx(elemRank,i-1,j,k);

      lzetap[num] = if (indices3D && i == elemsPerEdge-1)
                    then num
                    else elem3DToIdx(elemRank,i+1,j,k);
    }
  }
  if (debugInit) then
    for (xm,xp,em,ep,zm,zp) in zip(lxim, lxip, letam, letap, lzetam, lzetap) do
      writeln(xm, " ", xp, " ", em, " ", ep, " ", zm, " ", zp);
}

// read/compute the X, Y, Z symmetry planes

enum dim { X = 3, Y = 2, Z = 1 };

inline proc initSyms(Sym, dir) {
  if (initFromFile) {
    readNodeset(Sym);
  } else {
    for ij in DimNodeFace do
      Sym += node2DToIdx(Sym.rank, ij, dir, 0);
  }

  if debugInit {
    writeln(Sym.numIndices);
    for n in Sym do
      writeln(n);
  }

  return (Sym.numIndices, Sym);
}

inline proc initXSyms(XSym) {
  initSyms(XSym, dim.X);
}

inline proc initYSyms(YSym) {
  initSyms(YSym, dim.Y);
}

inline proc initZSyms(ZSym) {
  initSyms(ZSym, dim.Z);
}

// read/compute the free surface

inline proc initFreeSurface(freeSurface) {
  if (initFromFile) {
    readNodeset(freeSurface);
    reader.assertEOF("Input file format error (extra data at EOF)");
  } else {
    for ij in DimNodeFace do
      freeSurface += node2DToIdx(freeSurface.rank, ij, dim.X, nodesPerEdge-1);

    for ij in DimNodeFace do
      freeSurface += node2DToIdx(freeSurface.rank, ij, dim.Y, nodesPerEdge-1);

    for ij in DimNodeFace do
      freeSurface += node2DToIdx(freeSurface.rank, ij, dim.Z, nodesPerEdge-1);
  }

  if debugInit {
    use Sort;

    const size = freeSurface.size;
    var sortedSurface: [0..#size] if (freeSurface.rank == 1)
                                    then freeSurface.idxType
                                    else freeSurface.rank*freeSurface.idxType;

    for (a,b) in zip(sortedSurface, freeSurface) do a = b;
    QuickSort(sortedSurface);

    writeln(size);
    for b in sortedSurface do
      writeln(b);
  }
  return (freeSurface.numIndices, freeSurface);
}

// Helper routines for reading from a file

/* This is a helper routine to read a size and array from a file and
   return it */

proc readNodeset(nodeset) {
  if (nodeset.rank == 1) {
    const arrSize = reader.read(int);

    for a in 0..#arrSize do
      nodeset += reader.read(int);
  } else {
    halt("We shouldn't get here -- no file I/O with the 3D representation");
  }
}

// Helper routines for computing the cube input set

inline proc idx3DTo1D((i,j,k), len) {
  return i*len*len + j*len + k;
}

inline proc node3DToIdx(param idxRank, i, j, k) {
  if (idxRank == 3) then
    return (i, j, k);
  else
    return idx3DTo1D((i, j, k), nodesPerEdge);
}

inline proc elem3DToIdx(param idxRank, i,j,k) {
  if (idxRank == 3) then
    return (i,j,k);
  else
    return idx3DTo1D((i,j,k), elemsPerEdge);
}

inline proc idx1DTo3D(ind, len) {
  return (ind/(len*len), (ind/len)%len, ind%len);
}

inline proc nodeIdxTo3D(ind) {
  if isTuple(ind) then
    return ind;
  else
    return idx1DTo3D(ind, nodesPerEdge);
}

inline proc elemIdxTo3D(ind) {
  if isTuple(ind) then
    return ind;
  else
    return idx1DTo3D(ind, elemsPerEdge);
}

/* Turn a 2D node index into a 3D index by inserting the value
   'newval' in diemnsion 'newdim' */

inline proc node2DToIdx(param rank, ij, newdim, newval) {
  var ijk: 3*int;
  for i in 1..numDims do
    ijk[i] = if (i==newdim) then newval else ij[i - (i>newdim):int];
  return node3DToIdx(rank, (...ijk));
}


Changed format() to writef()

Changed format() to writef()

/*
   NPB Integer Sort
   Chapel parallel version: multi-task, multi-locale
     based on bucket sort (same as NPB reference version)

   Originally written by Margaret Cahir (Cray, Inc.)

   NOTES on the Block version:
     Limitations:
       - works with 32-bit integers only
       - tested on 1, 2 and 4 locales, Classes S, A, B and C (not D)

   NOTES on the BlockCyclic version:
     Still need to
     - adjust to solve for Class D (means adjusting for int64)
     - can gen keys be made a little cleaner? (see note)
     - can a backwards index be made to work? see note in fullVerify
  	var mype: int = i / nkeys_per_pe;  //  can this be i >> log2nkeys_per_pe?
     - loop2: can we use scan in line below

   Modifications [sungeun@cray.com]: 12/2011

   - Combined Block and BlockCyclic versions

*/

// Problem size parameters
enum  classVals {S=0, W=1, A=2, B=3, C=4};
const Classes: domain(classVals);
const ClassNkeys:  [Classes] int = ( 16, 20, 23, 25, 27 ),
      ClassRanges: [Classes] int = ( 11, 16, 19, 21, 23 );

// Set of config constants that control size of problem and output options
config const probClass = classVals.S;	 // default to Sample class
config const maxIterations = 10;	 // can be dialed down for devel runs
config const DEBUG:        bool = false; // shows progress and summary info
config param printLoopTimings: bool = false; // prints timing info
config param printArrays:  bool = false; // prints out arrays (can be long)
config const printTime    = false;	 // turn off for test verification

// Standard modules
use Time, Random, BlockDist, BlockCycDist;
enum ISDistType { block, blockcyclic };
config param distType = ISDistType.block;

// Comparison numbers for partial verification (these are given)
var testD: domain(2) =  {0..4, 0..4};	// # of Classes, # of keys to verify
var testIndexArray: [testD] int = (	( 48427,17148,23627,62548,4431),
					( 357773,934767,875723,898999,404505),
					( 2112377,662041,5336171,3642833,4250760),
					( 41869,812306,5102857,18232239,26860214),
					( 44172927,72999161,74326391,129606274,21736814) );
const testRankArray: [testD]  int = (   ( 0,18,346,64917,65463),
					( 1249,11698,1039987,1043896,1048018),
					( 104,17523,123928,8288932,8388264),
					( 33422937,10244,59149,33135281,99),
					( 61147,882988,266290,133997595,133525895) );

var passedVerifications = 0;		// verification counter

// Set problem sizes and storage requirements
const log2range = ClassRanges(probClass);
const log2nkeys = ClassNkeys (probClass);
var range:    int = 1 << log2range;	// left shift for power of 2 values
var nkeys:    int = 1 << log2nkeys;
var npes:     int = numLocales*(if dataParTasksPerLocale==0
                                then here.maxTaskPar
                                  else dataParTasksPerLocale);  // npes is the total number of tasks
var nbuckets: int = if distType==ISDistType.block then npes else 4*npes;

var keybuff_pe: real = 3*nkeys/npes;
var keybuffsz:  int  = keybuff_pe:int;

// Domains for main arrays
const keySpace:    domain(1)= {0..#nkeys};

// mcahir: Alas, it seems a block cyclic dist array has to be 2D so ended up making countSpace a 2D domain
const countSpace = if distType==ISDistType.block then {0..#range}
                                                 else {0..#range, 0..0};
const bucketSpace: domain(2)= {0..#npes,0..#nbuckets};
const buffSpace:   domain(2)= {0..#nbuckets,0..#keybuffsz};

// ... block a 2D space into horizontal slabs
const MyLocaleView = {0..#numLocales, 1..1};
const MyLocales: [MyLocaleView] locale = reshape(Locales, MyLocaleView);
const bucketDom = bucketSpace dmapped Block(boundingBox=bucketSpace, targetLocales=MyLocales);
const buffDom = if distType==ISDistType.block
  then buffSpace dmapped Block(boundingBox=buffSpace, targetLocales=MyLocales)
  else buffSpace dmapped BlockCyclic (startIdx=buffSpace.low,
                                      blocksize=(dataParTasksPerLocale,
                                                 keybuffsz),
                                      targetLocales=MyLocales);

// Map domains to locales
const keyDom   = keySpace dmapped Block(boundingBox=keySpace);
const countDom = if distType==ISDistType.block
  then countSpace dmapped Block(boundingBox=countSpace)
  else countSpace dmapped BlockCyclic(startIdx=countSpace.low,
                                      blocksize=(dataParTasksPerLocale,1),
                                      targetLocales=MyLocales);

// Now declare the main distributed arrays
var key:      [keyDom] int;	// random numbers between 0 and range -1
var rank:     [keyDom] int;	// store ranks here
var sortkey:  [keyDom] int;	// used for verification
var keybuff:  [buffDom]int;	// used for remote storage
var keycount: [countDom] int = 0;	// store #occurrences of values
var keycountbuf: [countDom] int = 0;	// buffer for pre-fix scan

// these counter arrays are also distributed
var bucket_cnts: [bucketDom] int;	// there is a row here for each pe (rank, locale)
var bucket_ptrs: [bucketDom] int;  // similarly, a row for each pe, a column for each bucket

// Timers
var tsetup, tsort, tverif: Timer;
var tloops: [1..5] Timer;

// Compute log of the number of pes and num keys per pe
var log2npes: int = 0;
while (1<<log2npes < npes) do {log2npes += 1; }
var nkeys_per_pe: int = nkeys >> log2npes;
var log2nbuckets: int = 0;
while (1<<log2nbuckets < nbuckets) do {log2nbuckets += 1; }

proc main () {

  tsetup.start();

  writef ("NAS Parallel Benchmarks 2.4 -- IS Benchmark\n" );
  writef (" Size:                       #########  (class %t)\n", nkeys, probClass);
  writef (" Iterations:                 #########\n",maxIterations);
  writef (" Number of locales:          #########\n",numLocales);
  writef (" Number of tasks per locale: #########\n",dataParTasksPerLocale);
  writef (" \n");

  // initialize key values
  gen_keys();

  tsetup.stop();
  if (printTime)
    {writeln ("Elapsed time for setup    =",tsetup.elapsed()," seconds");}

  if (DEBUG) then writeln("npes =",npes," log2npes=",log2npes);
  // ," log2nbuckets=", if ISDistType==block then "N/A" else log2nbuckets);

  tsort.start();				// start the timed section
						// main iteration loop
  for iteration in 1..maxIterations {

    if (probClass != classVals.S) then writeln (iteration," Iteration ");

    key[iteration] = iteration;
    key[iteration+maxIterations] = range - iteration;

    rank_keys ( iteration );

    partialVerification(iteration, keycountbuf);

  }						// end main iteration loop

  tsort.stop();					// end the timed section
  if (printTime) {
    writeln ("Elapsed time for key sort =", tsort.elapsed()," seconds");}
  if (printTime) {
    writeln ("Time for individual loops");
    for i in 1..5 do writeln("  Loop ",i,"  ",tloops(i).elapsed()," seconds"); }

  tverif.start();  				// full verification (full sort)
  keycount = keycountbuf;
  fullVerify();
  tverif.stop();
  if (printTime)
    {writeln ("Elapsed time for full verify =",tverif.elapsed()," seconds");}

  // Now complete output

  writef("\n\n IS Benchmark Completed\n");
  writef(" Class           =                         %t\n",probClass);
  writef(" Size            = #########################\n",nkeys);
  writef(" Iterations      = #########################\n",maxIterations);
  if (printTime) {
      writef(" Time in seconds = ######################.##\n",
        tsort.elapsed(TimeUnits.seconds));
      writef(" Mop/s total     = ######################.##\n",
        (maxIterations*nkeys)/tsort.elapsed(TimeUnits.seconds)/1000000 );
  }
  writeln(" Operation type  = ","              keys ranked");
  if (passedVerifications ==  (maxIterations*5+1) ) then
    writeln(" Verification    =                SUCCESSFUL");
  else
    writeln(" Verification    =              UNSUCCESSFUL");

} // end of main program

proc rank_keys ( iteration ) {

  bucket_cnts = 0;			// initialize bucket_cnts and bucket_ptrs
  bucket_ptrs = 0;			//   for each iteration
  keycount    = 0;

  // count the number of occurrences of each key value (each pe can do their share independently)

  tloops(1).start();
  forall (k,i) in zip(key, keyDom) do {
    on k do {
      var ibucket: int = k >> (log2range-log2nbuckets);  // this is equivalent to (key(i)/range)*nbuckets
      var mype: int = i / nkeys_per_pe;
      if false {
        writeln("mype=",mype," i=",i," key=",k," ibucket=",ibucket);
      }
      bucket_cnts[mype, ibucket] += 1;
    }
  }

  tloops(1).stop();
  if (printLoopTimings) then writeln("time for first loop =",tloops(1).elapsed());
  if (DEBUG) {
    var totbucket: [0..nbuckets-1] int;
    for ibucket in 0..nbuckets-1 {
      totbucket[ibucket] = + reduce (bucket_cnts[0..npes-1,ibucket]);
    }
    writeln ("total # keys by bucket= ",totbucket);
  }
  if (printArrays) { writeln("bucket_cnts"); writeln (bucket_cnts); }

  // need to synchronize here - co/forall construct above takes care of that for us

  // figure out pointers for keybuff -- even though these are remote references,
  // each pe can pre-fix scan a column independently

  var hi0 = if distType==ISDistType.block then 0..npes-1
    else 0..nbuckets-1;
  var hi1 = if distType==ISDistType.block then 1..nbuckets-1
    else 1..npes-1;
  tloops(2).start();
  forall b in hi0 do {
    for i in hi1 {
      bucket_ptrs[i, b] = bucket_ptrs[i-1, b] + bucket_cnts[i-1, b];
      if false then writeln("bucket_ptrs", (i,b), "=", bucket_ptrs[i, b]);
    }
  }

  tloops(2).stop();
  if (printLoopTimings) then writeln("time for second loop =",tloops(2).elapsed());
  if (printArrays) { writeln ("bucket_ptrs"); writeln (bucket_ptrs); }

  // now send off the keys -- there are remote references here, but there are no race conditions,
  //                          that is, each pe can work independently
  tloops(3).start();
  forall (k,i) in zip(key, keyDom) do {
    on k do {
      var mype: int = i / nkeys_per_pe;   // change this to a shift?
      var ibucket: int;
      ibucket = k >> (log2range-log2nbuckets);
      if false {writeln("2 mype=",mype," i=",i," key=",k," ibucket=",ibucket);}
      if false then writeln("2 bucket_ptrs", (mype,ibucket), "=", bucket_ptrs[mype,ibucket]);
      keybuff(ibucket, bucket_ptrs[mype,ibucket]) = k;
      bucket_ptrs[mype, ibucket] += 1;
    }
  }
  tloops(3).stop();
  if (printLoopTimings) then writeln("time for 3rd loop =",tloops(3).elapsed());
  if (printArrays) { writeln ("keybuff");     writeln (keybuff); }
  if (printArrays) { writeln ("bucket_ptrs"); writeln (bucket_ptrs); }

  // need to sychronize here - implicit sync of coforall takes care of it for us

  // now think of operating in an alternate domain
  // each pe does this bit
  tloops(4).start();
  forall b in 0..nbuckets-1 do {
    on keybuff[b,0] do     {			// is this necessary?
      var mykeys: int = bucket_ptrs[npes-1, b];
      for i in 0..mykeys-1 {
        var bindx = if distType==ISDistType.block then keybuff[b,i]
          else (keybuff[b,i], 0);
        keycount[bindx] += 1;
      }
    }
  }
  tloops(4).stop();
  if (printLoopTimings) then writeln("time for 4th loop =",tloops(4).elapsed());
  if (printArrays) {writeln ("keycount"); writeln (keycount);}

  // prefix scan the keycount array - this is a global operation, everyone participates
  tloops(5).start();
  keycountbuf = + scan (keycount);
  /*
  if distType==ISDistType.block {
    for i in 1..range-1 {
      keycount[i] += keycount[i-1];
    }
    keycountbuf = keycount;
  } else {
  }
  // keycountbuf = + scan (keycount);
  */
  tloops(5).stop();
  if printLoopTimings then writeln("time for 5th loop =",tloops(5).elapsed());
  if printArrays { writeln ("scanned keycountbuf"); writeln (keycountbuf); }

}

proc partialVerification(iteration: int, keyBuff1 /*:[countDom]int*/ ) {

  //  Performs a partial verification after each iteration.
  //  This code is pretty much a straight translation from the C reference
  //  version except that we use enums to access the comparison values directly.

  for i in 0..4 {
    var k = key(testIndexArray(probClass,i));
    var kbidx = if distType==ISDistType.block then k-1 else (k-1,0);
    select probClass {
      when classVals.S do {
        if (i <= 2) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i)+iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i)-iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
      when classVals.W do {
        if (i < 2) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) + (iteration-2)) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) - iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
      when classVals.A do {
        if (i <= 2) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) + (iteration-1)) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) - (iteration-1)) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
      when classVals.B do {
        if (i == 1 || i == 2 || i == 4) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) + iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) - iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
      when classVals.C do {
        if (i <= 2) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) + iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) - iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
    }
  }
  if (DEBUG) {writeln("After partial verification, passedVerifications=",passedVerifications); }
}	// end partial verification

proc fullVerify () {

  // Perform a full verification after all iterations are complete.
  // Since the keys were never actually sorted, we need to do that first.

  for mype in 0..nbuckets-1 do {
    var mykeys: int = bucket_ptrs[npes-1, mype];
    var val: int;
    for i in 0..mykeys-1 {
      var val = if distType==ISDistType.block then keybuff[mype,i]
        else (keybuff[mype,i],0);
      keycount[val] -= 1;
      keybuff[mype,i] = keycount[val];  // keycount is now the row, reuse keybuff for local storage
    }
  }
  if (printArrays) {writeln ("keycount"); writeln (keycount);}
  if (printArrays) {writeln ("keybuff "); writeln (keybuff);}

  // store the ranks in the rank array -- think of being back on the orginal domain
  // first, adjust the bucketptr array

  forall mype in 0..npes-1 do {
    var first: int = mype*nkeys_per_pe;
    var last:  int = first+nkeys_per_pe-1;
    var ibucket: int;
    // var r = last..first by -1;
    var i: int = last;
    for ii in first..last {			// going backwards
      ibucket = key(i) >> (log2range-log2nbuckets);
      bucket_ptrs[mype,ibucket] -= 1;
      if (DEBUG) {writeln(" indx=",i," key=",key(i)," ibucket=",ibucket,
                          " bucket_ptr=", bucket_ptrs[mype,ibucket],
                          " keybuff =",  keybuff[ibucket, bucket_ptrs[mype,ibucket]]); }
      rank[i] = keybuff[ibucket, bucket_ptrs[mype,ibucket]];
      i = i -1;
    }                         // end for
  }                           // end coforall

  // Finally, sort the keys
  for i in 0..nkeys-1 { sortkey[rank[i]] = key[i]; }

  if (printArrays) {writeln ("Rank "); writeln (rank);}
  if (printArrays) {writeln ("Sortd="); writeln(sortkey);}

  // Verify that the keys are sorted correctly
  if ( && reduce ( sortkey[0..nkeys-2] <= sortkey[1..nkeys-1] ) ) then {passedVerifications += 1;}
  if (DEBUG) {writeln ("full Verify: passedVerifications=",passedVerifications);}

}

proc gen_keys () {
  // initialize key values - do this on each rank or locale such that the key values
  // are the same no matter how many locales or ranks are used
  // -- come back later and see if this can be simplified w/ a local range

  coforall loc in Locales do {
    on loc do {
      var tmpreals: [1..4] real;
      var seed: int(64) = 314159265;

      var mype:  int = here.id;
      var first: int = mype*(nkeys/numLocales);
      var last : int = first+(nkeys/numLocales) - 1;

      var rs = new RandomStream(seed);
      rs.skipToNth(first*4+1);
      for i in first..last {
        rs.fillRandom(tmpreals);
        key(i) = ( (range>>2)*(+ reduce tmpreals ) ): int;
      }
      delete rs;
    }
  }
}

/*
   NPB Integer Sort
   Chapel parallel version: multi-task, multi-locale
     based on bucket sort (same as NPB reference version)

   Originally written by Margaret Cahir (Cray, Inc.)

   NOTES on the Block version:
     Limitations:
       - works with 32-bit integers only
       - tested on 1, 2 and 4 locales, Classes S, A, B and C (not D)

   NOTES on the BlockCyclic version:
     Still need to
     - adjust to solve for Class D (means adjusting for int64)
     - can gen keys be made a little cleaner? (see note)
     - can a backwards index be made to work? see note in fullVerify
  	var mype: int = i / nkeys_per_pe;  //  can this be i >> log2nkeys_per_pe?
     - loop2: can we use scan in line below

   Modifications [sungeun@cray.com]: 12/2011

   - Combined Block and BlockCyclic versions

*/

// Problem size parameters
enum  classVals {S=0, W=1, A=2, B=3, C=4};
const Classes: domain(classVals);
const ClassNkeys:  [Classes] int = ( 16, 20, 23, 25, 27 ),
      ClassRanges: [Classes] int = ( 11, 16, 19, 21, 23 );

// Set of config constants that control size of problem and output options
config const probClass = classVals.S;	 // default to Sample class
config const maxIterations = 10;	 // can be dialed down for devel runs
config const DEBUG:        bool = false; // shows progress and summary info
config param printLoopTimings: bool = false; // prints timing info
config param printArrays:  bool = false; // prints out arrays (can be long)
config const printTime    = false;	 // turn off for test verification

// Standard modules
use Time, Random, BlockDist, BlockCycDist;
enum ISDistType { block, blockcyclic };
config param distType = ISDistType.block;

// Comparison numbers for partial verification (these are given)
var testD: domain(2) =  {0..4, 0..4};	// # of Classes, # of keys to verify
var testIndexArray: [testD] int = (	( 48427,17148,23627,62548,4431),
					( 357773,934767,875723,898999,404505),
					( 2112377,662041,5336171,3642833,4250760),
					( 41869,812306,5102857,18232239,26860214),
					( 44172927,72999161,74326391,129606274,21736814) );
const testRankArray: [testD]  int = (   ( 0,18,346,64917,65463),
					( 1249,11698,1039987,1043896,1048018),
					( 104,17523,123928,8288932,8388264),
					( 33422937,10244,59149,33135281,99),
					( 61147,882988,266290,133997595,133525895) );

var passedVerifications = 0;		// verification counter

// Set problem sizes and storage requirements
const log2range = ClassRanges(probClass);
const log2nkeys = ClassNkeys (probClass);
var range:    int = 1 << log2range;	// left shift for power of 2 values
var nkeys:    int = 1 << log2nkeys;
var npes:     int = numLocales*(if dataParTasksPerLocale==0
                                then here.maxTaskPar
                                  else dataParTasksPerLocale);  // npes is the total number of tasks
var nbuckets: int = if distType==ISDistType.block then npes else 4*npes;

var keybuff_pe: real = 3*nkeys/npes;
var keybuffsz:  int  = keybuff_pe:int;

// Domains for main arrays
const keySpace:    domain(1)= {0..#nkeys};

// mcahir: Alas, it seems a block cyclic dist array has to be 2D so ended up making countSpace a 2D domain
const countSpace = if distType==ISDistType.block then {0..#range}
                                                 else {0..#range, 0..0};
const bucketSpace: domain(2)= {0..#npes,0..#nbuckets};
const buffSpace:   domain(2)= {0..#nbuckets,0..#keybuffsz};

// ... block a 2D space into horizontal slabs
const MyLocaleView = {0..#numLocales, 1..1};
const MyLocales: [MyLocaleView] locale = reshape(Locales, MyLocaleView);
const bucketDom = bucketSpace dmapped Block(boundingBox=bucketSpace, targetLocales=MyLocales);
const buffDom = if distType==ISDistType.block
  then buffSpace dmapped Block(boundingBox=buffSpace, targetLocales=MyLocales)
  else buffSpace dmapped BlockCyclic (startIdx=buffSpace.low,
                                      blocksize=(dataParTasksPerLocale,
                                                 keybuffsz),
                                      targetLocales=MyLocales);

// Map domains to locales
const keyDom   = keySpace dmapped Block(boundingBox=keySpace);
const countDom = if distType==ISDistType.block
  then countSpace dmapped Block(boundingBox=countSpace)
  else countSpace dmapped BlockCyclic(startIdx=countSpace.low,
                                      blocksize=(dataParTasksPerLocale,1),
                                      targetLocales=MyLocales);

// Now declare the main distributed arrays
var key:      [keyDom] int;	// random numbers between 0 and range -1
var rank:     [keyDom] int;	// store ranks here
var sortkey:  [keyDom] int;	// used for verification
var keybuff:  [buffDom]int;	// used for remote storage
var keycount: [countDom] int = 0;	// store #occurrences of values
var keycountbuf: [countDom] int = 0;	// buffer for pre-fix scan

// these counter arrays are also distributed
var bucket_cnts: [bucketDom] int;	// there is a row here for each pe (rank, locale)
var bucket_ptrs: [bucketDom] int;  // similarly, a row for each pe, a column for each bucket

// Timers
var tsetup, tsort, tverif: Timer;
var tloops: [1..5] Timer;

// Compute log of the number of pes and num keys per pe
var log2npes: int = 0;
while (1<<log2npes < npes) do {log2npes += 1; }
var nkeys_per_pe: int = nkeys >> log2npes;
var log2nbuckets: int = 0;
while (1<<log2nbuckets < nbuckets) do {log2nbuckets += 1; }

proc main () {

  tsetup.start();

  writeln ("NAS Parallel Benchmarks 2.4 -- IS Benchmark" );
  writeln (" Size:                       ", format("#########",nkeys),"  (class ",probClass,")");
  writeln (" Iterations:                 ", format("#########",maxIterations));
  writeln (" Number of locales:          ", format("#########",numLocales));
  writeln (" Number of tasks per locale: ", format("#########",dataParTasksPerLocale));
  writeln (" ");

  // initialize key values
  gen_keys();

  tsetup.stop();
  if (printTime)
    {writeln ("Elapsed time for setup    =",tsetup.elapsed()," seconds");}

  if (DEBUG) then writeln("npes =",npes," log2npes=",log2npes);
  // ," log2nbuckets=", if ISDistType==block then "N/A" else log2nbuckets);

  tsort.start();				// start the timed section
						// main iteration loop
  for iteration in 1..maxIterations {

    if (probClass != classVals.S) then writeln (iteration," Iteration ");

    key[iteration] = iteration;
    key[iteration+maxIterations] = range - iteration;

    rank_keys ( iteration );

    partialVerification(iteration, keycountbuf);

  }						// end main iteration loop

  tsort.stop();					// end the timed section
  if (printTime) {
    writeln ("Elapsed time for key sort =", tsort.elapsed()," seconds");}
  if (printTime) {
    writeln ("Time for individual loops");
    for i in 1..5 do writeln("  Loop ",i,"  ",tloops(i).elapsed()," seconds"); }

  tverif.start();  				// full verification (full sort)
  keycount = keycountbuf;
  fullVerify();
  tverif.stop();
  if (printTime)
    {writeln ("Elapsed time for full verify =",tverif.elapsed()," seconds");}

  // Now complete output

  writeln("\n\n IS Benchmark Completed");
  writeln(" Class           = ","                        ",probClass);
  writeln(" Size            = ", format("#########################",nkeys));
  writeln(" Iterations      = ", format("#########################",maxIterations));
  if (printTime) {
      writeln(" Time in seconds = ", format("######################.##",
        tsort.elapsed(TimeUnits.seconds)) );
      writeln(" Mop/s total     = ", format("######################.##",
        (maxIterations*nkeys)/tsort.elapsed(TimeUnits.seconds)/1000000 ) );
  }
  writeln(" Operation type  = ","              keys ranked");
  if (passedVerifications ==  (maxIterations*5+1) ) then
    writeln(" Verification    =                SUCCESSFUL");
  else
    writeln(" Verification    =              UNSUCCESSFUL");

} // end of main program

proc rank_keys ( iteration ) {

  bucket_cnts = 0;			// initialize bucket_cnts and bucket_ptrs
  bucket_ptrs = 0;			//   for each iteration
  keycount    = 0;

  // count the number of occurrences of each key value (each pe can do their share independently)

  tloops(1).start();
  forall (k,i) in zip(key, keyDom) do {
    on k do {
      var ibucket: int = k >> (log2range-log2nbuckets);  // this is equivalent to (key(i)/range)*nbuckets
      var mype: int = i / nkeys_per_pe;
      if false {
        writeln("mype=",mype," i=",i," key=",k," ibucket=",ibucket);
      }
      bucket_cnts[mype, ibucket] += 1;
    }
  }

  tloops(1).stop();
  if (printLoopTimings) then writeln("time for first loop =",tloops(1).elapsed());
  if (DEBUG) {
    var totbucket: [0..nbuckets-1] int;
    for ibucket in 0..nbuckets-1 {
      totbucket[ibucket] = + reduce (bucket_cnts[0..npes-1,ibucket]);
    }
    writeln ("total # keys by bucket= ",totbucket);
  }
  if (printArrays) { writeln("bucket_cnts"); writeln (bucket_cnts); }

  // need to synchronize here - co/forall construct above takes care of that for us

  // figure out pointers for keybuff -- even though these are remote references,
  // each pe can pre-fix scan a column independently

  var hi0 = if distType==ISDistType.block then 0..npes-1
    else 0..nbuckets-1;
  var hi1 = if distType==ISDistType.block then 1..nbuckets-1
    else 1..npes-1;
  tloops(2).start();
  forall b in hi0 do {
    for i in hi1 {
      bucket_ptrs[i, b] = bucket_ptrs[i-1, b] + bucket_cnts[i-1, b];
      if false then writeln("bucket_ptrs", (i,b), "=", bucket_ptrs[i, b]);
    }
  }

  tloops(2).stop();
  if (printLoopTimings) then writeln("time for second loop =",tloops(2).elapsed());
  if (printArrays) { writeln ("bucket_ptrs"); writeln (bucket_ptrs); }

  // now send off the keys -- there are remote references here, but there are no race conditions,
  //                          that is, each pe can work independently
  tloops(3).start();
  forall (k,i) in zip(key, keyDom) do {
    on k do {
      var mype: int = i / nkeys_per_pe;   // change this to a shift?
      var ibucket: int;
      ibucket = k >> (log2range-log2nbuckets);
      if false {writeln("2 mype=",mype," i=",i," key=",k," ibucket=",ibucket);}
      if false then writeln("2 bucket_ptrs", (mype,ibucket), "=", bucket_ptrs[mype,ibucket]);
      keybuff(ibucket, bucket_ptrs[mype,ibucket]) = k;
      bucket_ptrs[mype, ibucket] += 1;
    }
  }
  tloops(3).stop();
  if (printLoopTimings) then writeln("time for 3rd loop =",tloops(3).elapsed());
  if (printArrays) { writeln ("keybuff");     writeln (keybuff); }
  if (printArrays) { writeln ("bucket_ptrs"); writeln (bucket_ptrs); }

  // need to sychronize here - implicit sync of coforall takes care of it for us

  // now think of operating in an alternate domain
  // each pe does this bit
  tloops(4).start();
  forall b in 0..nbuckets-1 do {
    on keybuff[b,0] do     {			// is this necessary?
      var mykeys: int = bucket_ptrs[npes-1, b];
      for i in 0..mykeys-1 {
        var bindx = if distType==ISDistType.block then keybuff[b,i]
          else (keybuff[b,i], 0);
        keycount[bindx] += 1;
      }
    }
  }
  tloops(4).stop();
  if (printLoopTimings) then writeln("time for 4th loop =",tloops(4).elapsed());
  if (printArrays) {writeln ("keycount"); writeln (keycount);}

  // prefix scan the keycount array - this is a global operation, everyone participates
  tloops(5).start();
  keycountbuf = + scan (keycount);
  /*
  if distType==ISDistType.block {
    for i in 1..range-1 {
      keycount[i] += keycount[i-1];
    }
    keycountbuf = keycount;
  } else {
  }
  // keycountbuf = + scan (keycount);
  */
  tloops(5).stop();
  if printLoopTimings then writeln("time for 5th loop =",tloops(5).elapsed());
  if printArrays { writeln ("scanned keycountbuf"); writeln (keycountbuf); }

}

proc partialVerification(iteration: int, keyBuff1 /*:[countDom]int*/ ) {

  //  Performs a partial verification after each iteration.
  //  This code is pretty much a straight translation from the C reference
  //  version except that we use enums to access the comparison values directly.

  for i in 0..4 {
    var k = key(testIndexArray(probClass,i));
    var kbidx = if distType==ISDistType.block then k-1 else (k-1,0);
    select probClass {
      when classVals.S do {
        if (i <= 2) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i)+iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i)-iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
      when classVals.W do {
        if (i < 2) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) + (iteration-2)) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) - iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
      when classVals.A do {
        if (i <= 2) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) + (iteration-1)) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) - (iteration-1)) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
      when classVals.B do {
        if (i == 1 || i == 2 || i == 4) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) + iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) - iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
      when classVals.C do {
        if (i <= 2) {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) + iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        } else {
          if (keyBuff1(kbidx) != testRankArray(probClass,i) - iteration) {
            writeln("Failed partial verification: iteration ",
                    iteration, ", test key ", i);
          } else {
            passedVerifications += 1;
          }
        }
      }
    }
  }
  if (DEBUG) {writeln("After partial verification, passedVerifications=",passedVerifications); }
}	// end partial verification

proc fullVerify () {

  // Perform a full verification after all iterations are complete.
  // Since the keys were never actually sorted, we need to do that first.

  for mype in 0..nbuckets-1 do {
    var mykeys: int = bucket_ptrs[npes-1, mype];
    var val: int;
    for i in 0..mykeys-1 {
      var val = if distType==ISDistType.block then keybuff[mype,i]
        else (keybuff[mype,i],0);
      keycount[val] -= 1;
      keybuff[mype,i] = keycount[val];  // keycount is now the row, reuse keybuff for local storage
    }
  }
  if (printArrays) {writeln ("keycount"); writeln (keycount);}
  if (printArrays) {writeln ("keybuff "); writeln (keybuff);}

  // store the ranks in the rank array -- think of being back on the orginal domain
  // first, adjust the bucketptr array

  forall mype in 0..npes-1 do {
    var first: int = mype*nkeys_per_pe;
    var last:  int = first+nkeys_per_pe-1;
    var ibucket: int;
    // var r = last..first by -1;
    var i: int = last;
    for ii in first..last {			// going backwards
      ibucket = key(i) >> (log2range-log2nbuckets);
      bucket_ptrs[mype,ibucket] -= 1;
      if (DEBUG) {writeln(" indx=",i," key=",key(i)," ibucket=",ibucket,
                          " bucket_ptr=", bucket_ptrs[mype,ibucket],
                          " keybuff =",  keybuff[ibucket, bucket_ptrs[mype,ibucket]]); }
      rank[i] = keybuff[ibucket, bucket_ptrs[mype,ibucket]];
      i = i -1;
    }                         // end for
  }                           // end coforall

  // Finally, sort the keys
  for i in 0..nkeys-1 { sortkey[rank[i]] = key[i]; }

  if (printArrays) {writeln ("Rank "); writeln (rank);}
  if (printArrays) {writeln ("Sortd="); writeln(sortkey);}

  // Verify that the keys are sorted correctly
  if ( && reduce ( sortkey[0..nkeys-2] <= sortkey[1..nkeys-1] ) ) then {passedVerifications += 1;}
  if (DEBUG) {writeln ("full Verify: passedVerifications=",passedVerifications);}

}

proc gen_keys () {
  // initialize key values - do this on each rank or locale such that the key values
  // are the same no matter how many locales or ranks are used
  // -- come back later and see if this can be simplified w/ a local range

  coforall loc in Locales do {
    on loc do {
      var tmpreals: [1..4] real;
      var seed: int(64) = 314159265;

      var mype:  int = here.id;
      var first: int = mype*(nkeys/numLocales);
      var last : int = first+(nkeys/numLocales) - 1;

      var rs = new RandomStream(seed);
      rs.skipToNth(first*4+1);
      for i in first..last {
        rs.fillRandom(tmpreals);
        key(i) = ( (range>>2)*(+ reduce tmpreals ) ): int;
      }
      delete rs;
    }
  }
}


Remove "use Sort;" from chapel_code.chpl.

Nothing from the Sort module is used in the chapel_code module, so don't
include it with a use statement.

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

use ChapelBase;
use ChapelIO;
use ChapelTuple;
use ChapelRange;
use ChapelArray;
use DefaultArithmetic;
use DefaultAssociative;
use Containers;

/*
   This code keeps track of thread identifiers, along with the current
   running and pending tasks and where these tasks spawned from.

   The thread ID information is used for thread teardown at the end of
   program execution.

   The taks information is used to generate a task report (optionally
   displayed when the user Ctrl+C's out of the program).

   The type chpl_threadID_t is a primitve type defined in the include
   files for each threading layer.

*/

// Represents a currently running task
record chpldev_Task {
    var lineno    : uint(32);
    var filename  : string;
}

var chpldev_taskTableD : domain(chpl_threadID_t);
var chpldev_taskTable : [chpldev_taskTableD] Vector(chpldev_Task);

pragma "export" def chpldev_taskTable_addThread( threadID : chpl_threadID_t )
{
  if(!chpldev_taskTableD.member(threadID)) {
    chpldev_taskTableD.add(threadID);
  }
}

pragma "export" def chpldev_taskTable_add(
    threadID : chpl_threadID_t,
    lineno   : uint(32),
    filename : string)
{

  // make sure this thread ID is in the domain.
  chpldev_taskTable_addThread(threadID);

  // make sure a task vector exits for this thread ID.
  if (chpldev_taskTable[threadID] == nil) {
    chpldev_taskTable[threadID] = new Vector(chpldev_Task);
  }

  // add task to table; set it to be pending
  chpldev_taskTable[threadID].push(
    new chpldev_Task(lineno, filename));
}

pragma "export" def chpldev_taskTable_remove(threadID : chpl_threadID_t)
{
    chpldev_taskTable[threadID].pop();
}

pragma "export" def chpldev_taskTable_print()
{
  for threadID in chpldev_taskTableD {
    for task in chpldev_taskTable[threadID] {
      stderr.writeln("- ", task.filename, ":", task.lineno,
		     " on ", threadID : uint(64));
     }
  }
}

// callbacks to C part of runtime for thread cleanup.
_extern def chpl_thread_cancel(threadID : chpl_threadID_t );
_extern def chpl_thread_join  (threadID : chpl_threadID_t );

pragma "export" def chpldev_endAllThreads() : void
{
  for thread in chpldev_taskTableD do
    chpl_thread_cancel(thread);
  for thread in chpldev_taskTableD do
    chpl_thread_join(thread);
}

use ChapelBase;
use ChapelIO;
use ChapelTuple;
use ChapelRange;
use ChapelArray;
use DefaultArithmetic;
use DefaultAssociative;
use Containers;
use Sort;

/*
   This code keeps track of thread identifiers, along with the current
   running and pending tasks and where these tasks spawned from.

   The thread ID information is used for thread teardown at the end of
   program execution.

   The taks information is used to generate a task report (optionally
   displayed when the user Ctrl+C's out of the program).

   The type chpl_threadID_t is a primitve type defined in the include
   files for each threading layer.

*/

// Represents a currently running task
record chpldev_Task {
    var lineno    : uint(32);
    var filename  : string;
}

var chpldev_taskTableD : domain(chpl_threadID_t);
var chpldev_taskTable : [chpldev_taskTableD] Vector(chpldev_Task);

pragma "export" def chpldev_taskTable_addThread( threadID : chpl_threadID_t )
{
  if(!chpldev_taskTableD.member(threadID)) {
    chpldev_taskTableD.add(threadID);
  }
}

pragma "export" def chpldev_taskTable_add(
    threadID : chpl_threadID_t,
    lineno   : uint(32),
    filename : string)
{

  // make sure this thread ID is in the domain.
  chpldev_taskTable_addThread(threadID);

  // make sure a task vector exits for this thread ID.
  if (chpldev_taskTable[threadID] == nil) {
    chpldev_taskTable[threadID] = new Vector(chpldev_Task);
  }

  // add task to table; set it to be pending
  chpldev_taskTable[threadID].push(
    new chpldev_Task(lineno, filename));
}

pragma "export" def chpldev_taskTable_remove(threadID : chpl_threadID_t)
{
    chpldev_taskTable[threadID].pop();
}

pragma "export" def chpldev_taskTable_print()
{
  for threadID in chpldev_taskTableD {
    for task in chpldev_taskTable[threadID] {
      stderr.writeln("- ", task.filename, ":", task.lineno,
		     " on ", threadID : uint(64));
     }
  }
}

// callbacks to C part of runtime for thread cleanup.
_extern def chpl_thread_cancel(threadID : chpl_threadID_t );
_extern def chpl_thread_join  (threadID : chpl_threadID_t );

pragma "export" def chpldev_endAllThreads() : void
{
  for thread in chpldev_taskTableD do
    chpl_thread_cancel(thread);
  for thread in chpldev_taskTableD do
    chpl_thread_join(thread);
}


Shortened iteration expression

Shortened iteration expression

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