Fix nondeterministic output from walkdir() by requesting sorted output

use Filerator;

for dir in walkdirs("subdir", sort=true) {
  writeln("dir ", dir, " contains:");
  for file in glob(dir+"/*") do
    writeln("  ", file);
}

use Filerator;

for dir in walkdirs("subdir") {
  writeln("dir ", dir, " contains:");
  for file in glob(dir+"/*") do
    writeln("  ", file);
}


Minor cleanup of producer consumer example.  It is nice and simple.  I
changed the parameters to config variables since they don't need to be
parameters and they are nice to vary (sleepTime, numIterations).

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

// Producer-consumer example. Producer thread slowly writes to sync variable
// s.  Child thread reads from s and outputs what was read.

use Time;

config var numIterations: int = 5;
config var sleepTime: uint = 2;

var s: sync int;

begin {  // fork consumer computation
  for c in 1..numIterations do
    writeln("consumer got ", s);
}

// producer computation
for p in 1..numIterations {
  sleep(sleepTime);
  s = p;
}

// Producer-consumer example. Producer thread slowly writes to sync variable
// s.  Child thread reads from s and outputs what was read.

use Time;

param iterations = 5;
param sleepTime  = 2;
var s: sync int;

begin {  // fork consumer computation
  for c in 1..iterations do
    writeln("consumer got ", s);
}

// producer computation
for p in 1..iterations {
  sleep(sleepTime);
  s = p;
}


Removed artificial upper bounds from
zippered iterations, using indefinite
notation that Steve just implemented.

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

// BLC: For certain inputs, not having a complex/real
// function can result in numerical instability.

// BLC: clean up complex arithmetic

// BLC: insert problem size computation based on memory size?

use BitOps;
use Random;
use Time;

// problem size configs
config const logN = 5;

param radix = 4;

// pseudo-random input configs
config const deterministic = false,
             seed = 314159265;

// verification configs
config const epsilon = 2.0 ** -51.0,
             threshold = 16.0;

// boolean configs
config const printTiming = true;

// BLC: control printing out of error value to avoid portability issues

def main() {
  // compute problem size
  const N = 1 << logN;

  // twiddle domain and arrays
  const TwiddleDom = [0..N/4);
  var Twiddles: [TwiddleDom] complex;

  computeTwiddles(Twiddles);
  bitReverseShuffle(Twiddles);

  // problem domain and arrays
  const ProblemDom = [0..N);
  var Z, z: [ProblemDom] complex;

  // generate pseudo-random input
  if deterministic then
    fillRandom(z, seed);
  else
    fillRandom(z);

  // conjugate input, storing result to work array
  Z = conjg(z);

  // TIMED SECTION
  var startTime = getCurrentTime();

  bitReverseShuffle(Z);
  dfft(Z, Twiddles);

  var execTime = getCurrentTime() - startTime;

  verifyResults(z, Z, execTime, Twiddles);
}

def computeTwiddles(W) {
  const n = W.numElements;
  const delta = 2.0 * atan(1.0) / n;

  W(0) = 1.0;
  W(n/2) = let x = cos(delta * n/2)
            in (x, x):complex;
  forall i in [1..n/2) {
    const x = cos(delta*i);
    const y = sin(delta*i);
    W(i)     = (x, y):complex;
    W(n - i) = (y, x):complex;
  }
}

def bitReverseShuffle(W: [?WD]) {
  const n = WD.numIndices;
  const reverse = lg(n);
  var V: [WD] W.elt_type;  // BLC: rename elt_type to remove underscore?
  // BLC: would like to use:
  //  var Perm: [i in WD] int = bitReverse(i:uint(64), numBits = reverse):int;
  var Perm: [WD] index(WD);
  [i in WD] Perm(i) = bitReverse(i, numBits = reverse);
  // BLC: would like to use:
  // V(Perm) = W;
  [i in WD] V(Perm(i)) = W(i);
  W = V;
}

// reverses numBits low-order bits of val
def bitReverse(val: ?valType, numBits = 64) {
  param mask: uint(64) = 0x0102040810204080;
  const valReverse64 = bitMatMultOr(mask, bitMatMultOr(val:uint(64), mask));
  const valReverse = bitRotLeft(valReverse64, numBits);
  return valReverse: valType;
}

def dfft(Z, W) {
  cft1st(Z, W);

  var span = radix;
  var lasti = 2;
  for i in radix..logN/2 by 2 {
    cftmd1(span, Z, W);
    span *= radix;
    lasti = i;
  }
  for i in [lasti+2..logN) by 2 {
    cftmd2(span, Z, W);
    span *= radix;
  }

  const n = Z.numElements;
  if (radix*span == n) {
    forall j in [0..span) {
      butterfly(1.0, 1.0, 1.0, Z[j..j+3*span by span]);
    }
  } else {
    forall j in [0..span) {
      var a = Z(j);
      var b = Z(j+span);
      Z(j) = a + b;
      Z(j+span) = a - b;
    }
  }
}

def verifyResults(z, Z, execTime, Twiddles) {
  const N = Z.numElements;

  // BLC: This line wants /(complex,real) to be implemented directly:
  Z = conjg(Z) / N;

  bitReverseShuffle(Z);
  dfft(Z, Twiddles);

  // BLC: need to check this against written spec
  var maxerr = max reduce sqrt((z.real - Z.real)**2 + (z.imag - Z.imag)**2);

  maxerr = maxerr / logN / epsilon;

  write(if (maxerr < threshold) then "SUCCESS" else "FAILURE");
  writeln(", error = ", maxerr);
  writeln();
  writeln("N      = ", N);
  if (printTiming) {
    writeln("Time   = ", execTime);
    const gflop = 5.0 * N * logN / 1000000000.0;
    writeln("GFlops = ", gflop / execTime);
  }
}

def cft1st(A, W) {
  const n = A.domain(1).length;
  var x0 = A(0) + A(1);
  var x1 = A(0) - A(1);
  var x2 = A(2) + A(3);
  var x3rot = (A(2) - A(3))*1.0i;

  const wk1r = W(1).real;

  A(0) = x0 + x2;
  A(2) = x0 - x2;
  A(1) = x1 + x3rot;
  A(3) = x1 - x3rot;

  x0 = A(4) + A(5);
  x1 = A(4) - A(5);
  x2 = A(6) + A(7);
  var x3 = A(6) - A(7);  // BLC: try to eliminate this
  x3rot = (A(6) - A(7))*1.0i;
  A(4) = x0 + x2;
  A(6) = (x2.imag - x0.imag, x0.real - x2.real):complex;
  x0 = x1 + x3rot;
  A(5) = wk1r * (x0.real - x0.imag, x0.real + x0.imag):complex;
  x0 = (x3.imag + x1.real, x3.real - x1.imag):complex;
  A(7) = wk1r * (x0.imag - x0.real, x0.imag + x0.real):complex;

  // BLC: would like to use an indefinite arithmetic array here
  // BLC: would also like to use () on both indices and zipping
  //      together of ranges
  forall j,k1 in ([8..n) by 8, 1..) {
    var wk2 = W(k1);
    var wk1 = W(2*k1);
    var wk3 = (wk1.real - 2* wk2.imag * wk1.imag,
               2 * wk2.imag * wk1.real - wk1.imag):complex;

    butterfly(wk1, wk2, wk3, A[j..j+3]);

    wk1 = W(2*k1+1);
    wk3 = (wk1.real - 2*wk2.real * wk1.imag,
           2*wk2.real * wk1.real - wk1.imag):complex;
    wk2 = wk2*1.0i;
    butterfly(wk1, wk2, wk3, A[j+4..j+7]);
  }
}

def cftmd0(span, A, W) {
  var wk1r = W(1).real;
  const m = radix*span;

  forall j in [0..span) {
    butterfly(1.0, 1.0, 1.0, A[j..j+3*span by span]);
  }

  forall j in [m..m+span) {
    butterfly((wk1r, wk1r):complex, 1.0i, (-wk1r, wk1r):complex,
              A[j..j+3*span by span]);
  }
}

def cftmd1(span, A, W) {
  const m = radix*span;
  const m2 = 2*m;
  const n = A.domain(1).length;

  cftmd0(span, A, W);
  forall k,k1 in ([m2..n) by m2, 1..) {
    var wk2 = W[k1];
    var wk1 = W[2*k1];
    var wk3 = (wk1.real - 2 * wk2.imag * wk1.imag,
               2 * wk2.imag * wk1.real - wk1.imag):complex;
    for j in [k..k+span) {
      butterfly(wk1, wk2, wk3, A[j..j+3*span by span]);
    }

    wk1 = W[2*k1+1];
    wk3 = (wk1.real - 2 * wk2.real * wk1.imag,
           2 * wk2.real * wk1.real - wk1.imag):complex;

    for j in [k+m..k+m+span) {
      butterfly(wk1, wk2*1.0i, wk3, A[j..j+3*span by span]);
    }
  }
}

def cftmd2(span, A, W) {
  var m = radix*span;
  var m2 = 2*m;
  const n = A.domain(1).length;

  cftmd0(span, A, W);
  if (m2 >= n) return;
  if (m2 >= n / 8) {
    cftmd21(span, A, W);
    return;
  }

  forall j in [0..span) {
    forall k,k1 in ([m2..n) by m2, 1..) {
      var wk2 = W[k1];
      var wk1 = W[k1 + k1];
      var wk3 = (wk1.real - 2*wk2.imag * wk1.imag,
                 2 * wk2.imag * wk1.real - wk1.imag):complex;
      butterfly(wk1, wk2, wk3, A[j+k..j+k+3*span by span]);
    }

    forall k,k1 in ([m2..n) by m2, 1..) {
      var wk2 = W[k1];
      var wk1 = W[2*k1 + 1];
      var wk3 = (wk1.real - 2*wk2.real * wk1.imag,
                 2*wk2.real * wk1.real - wk1.imag):complex;
      wk2 = wk2*1.0i;

      butterfly(wk1, wk2, wk3, A[j+k+m..j+k+m+3*span by span]);
    }
  }
}

def cftmd21(span, A, W) {
  const n = A.domain(1).length;
  var m = radix*span;
  var m2 = 2*m;

  for k,k1 in ([m2..n) by m2, 1..) {
    var wk2 = W[k1];
    var wk1 = W[2*k1];
    var wk3 = (wk1.real - 2*wk2.imag * wk1.imag,
               2* wk2.imag * wk1.real - wk1.imag):complex;

    forall j in [k..k+span) {
      butterfly(wk1, wk2, wk3, A[j..j+3*span by span]);
    }

    wk1 = W[2*k1 + 1];
    wk3 = (wk1.real - 2*wk2.real * wk1.imag,
           2*wk2.real * wk1.real - wk1.imag):complex;
    wk2 = wk2*1.0i;

    forall j in [k+m..k+m+span) {
      butterfly(wk1, wk2, wk3, A[j..j+3*span by span]);
    }
  }
}

def butterfly(wk1, wk2, wk3, inout A:[1..radix]) {
  var x0 = A[1] + A[2];
  var x1 = A[1] - A[2];
  var x2 = A[3] + A[4];
  var x3rot = (A[3] - A[4])*1.0i;

  A[1] = x0 + x2;
  x0 -= x2;
  A[3] = wk2 * x0;
  x0 = x1 + x3rot;
  A[2] = wk1 * x0;
  x0 = x1 - x3rot;
  A[4] = wk3 * x0;
}

// BLC: For certain inputs, not having a complex/real
// function can result in numerical instability.

// BLC: clean up complex arithmetic

// BLC: insert problem size computation based on memory size?

use BitOps;
use Random;
use Time;

// problem size configs
config const logN = 5;

param radix = 4;

// pseudo-random input configs
config const deterministic = false,
             seed = 314159265;

// verification configs
config const epsilon = 2.0 ** -51.0,
             threshold = 16.0;

// boolean configs
config const printTiming = true;

// BLC: control printing out of error value to avoid portability issues

def main() {
  // compute problem size
  const N = 1 << logN;

  // twiddle domain and arrays
  const TwiddleDom = [0..N/4);
  var Twiddles: [TwiddleDom] complex;

  computeTwiddles(Twiddles);
  bitReverseShuffle(Twiddles);

  // problem domain and arrays
  const ProblemDom = [0..N);
  var Z, z: [ProblemDom] complex;

  // generate pseudo-random input
  if deterministic then
    fillRandom(z, seed);
  else
    fillRandom(z);

  // conjugate input, storing result to work array
  Z = conjg(z);

  // TIMED SECTION
  var startTime = getCurrentTime();

  bitReverseShuffle(Z);
  dfft(Z, Twiddles);

  var execTime = getCurrentTime() - startTime;

  verifyResults(z, Z, execTime, Twiddles);
}

def computeTwiddles(W) {
  const n = W.numElements;
  const delta = 2.0 * atan(1.0) / n;

  W(0) = 1.0;
  W(n/2) = let x = cos(delta * n/2)
            in (x, x):complex;
  forall i in [1..n/2) {
    const x = cos(delta*i);
    const y = sin(delta*i);
    W(i)     = (x, y):complex;
    W(n - i) = (y, x):complex;
  }
}

def bitReverseShuffle(W: [?WD]) {
  const n = WD.numIndices;
  const reverse = lg(n);
  var V: [WD] W.elt_type;  // BLC: rename elt_type to remove underscore?
  // BLC: would like to use:
  //  var Perm: [i in WD] int = bitReverse(i:uint(64), numBits = reverse):int;
  var Perm: [WD] index(WD);
  [i in WD] Perm(i) = bitReverse(i, numBits = reverse);
  // BLC: would like to use:
  // V(Perm) = W;
  [i in WD] V(Perm(i)) = W(i);
  W = V;
}

// reverses numBits low-order bits of val
def bitReverse(val: ?valType, numBits = 64) {
  param mask: uint(64) = 0x0102040810204080;
  const valReverse64 = bitMatMultOr(mask, bitMatMultOr(val:uint(64), mask));
  const valReverse = bitRotLeft(valReverse64, numBits);
  return valReverse: valType;
}

def dfft(Z, W) {
  cft1st(Z, W);

  var span = radix;
  var lasti = 2;
  for i in radix..logN/2 by 2 {
    cftmd1(span, Z, W);
    span *= radix;
    lasti = i;
  }
  for i in [lasti+2..logN) by 2 {
    cftmd2(span, Z, W);
    span *= radix;
  }

  const n = Z.numElements;
  if (radix*span == n) {
    forall j in [0..span) {
      butterfly(1.0, 1.0, 1.0, Z[j..j+3*span by span]);
    }
  } else {
    forall j in [0..span) {
      var a = Z(j);
      var b = Z(j+span);
      Z(j) = a + b;
      Z(j+span) = a - b;
    }
  }
}

def verifyResults(z, Z, execTime, Twiddles) {
  const N = Z.numElements;

  // BLC: This line wants /(complex,real) to be implemented directly:
  Z = conjg(Z) / N;

  bitReverseShuffle(Z);
  dfft(Z, Twiddles);

  // BLC: need to check this against written spec
  var maxerr = max reduce sqrt((z.real - Z.real)**2 + (z.imag - Z.imag)**2);

  maxerr = maxerr / logN / epsilon;

  write(if (maxerr < threshold) then "SUCCESS" else "FAILURE");
  writeln(", error = ", maxerr);
  writeln();
  writeln("N      = ", N);
  if (printTiming) {
    writeln("Time   = ", execTime);
    const gflop = 5.0 * N * logN / 1000000000.0;
    writeln("GFlops = ", gflop / execTime);
  }
}

def cft1st(A, W) {
  const n = A.domain(1).length;
  var x0 = A(0) + A(1);
  var x1 = A(0) - A(1);
  var x2 = A(2) + A(3);
  var x3rot = (A(2) - A(3))*1.0i;

  const wk1r = W(1).real;

  A(0) = x0 + x2;
  A(2) = x0 - x2;
  A(1) = x1 + x3rot;
  A(3) = x1 - x3rot;

  x0 = A(4) + A(5);
  x1 = A(4) - A(5);
  x2 = A(6) + A(7);
  var x3 = A(6) - A(7);  // BLC: try to eliminate this
  x3rot = (A(6) - A(7))*1.0i;
  A(4) = x0 + x2;
  A(6) = (x2.imag - x0.imag, x0.real - x2.real):complex;
  x0 = x1 + x3rot;
  A(5) = wk1r * (x0.real - x0.imag, x0.real + x0.imag):complex;
  x0 = (x3.imag + x1.real, x3.real - x1.imag):complex;
  A(7) = wk1r * (x0.imag - x0.real, x0.imag + x0.real):complex;

  // BLC: would like to use an indefinite arithmetic array here
  // BLC: would also like to use () on both indices and zipping
  //      together of ranges
  forall j,k1 in ([8..n) by 8, 1..(n-8)/8) {
    var wk2 = W(k1);
    var wk1 = W(2*k1);
    var wk3 = (wk1.real - 2* wk2.imag * wk1.imag,
               2 * wk2.imag * wk1.real - wk1.imag):complex;

    butterfly(wk1, wk2, wk3, A[j..j+3]);

    wk1 = W(2*k1+1);
    wk3 = (wk1.real - 2*wk2.real * wk1.imag,
           2*wk2.real * wk1.real - wk1.imag):complex;
    wk2 = wk2*1.0i;
    butterfly(wk1, wk2, wk3, A[j+4..j+7]);
  }
}

def cftmd0(span, A, W) {
  var wk1r = W(1).real;
  const m = radix*span;

  forall j in [0..span) {
    butterfly(1.0, 1.0, 1.0, A[j..j+3*span by span]);
  }

  forall j in [m..m+span) {
    butterfly((wk1r, wk1r):complex, 1.0i, (-wk1r, wk1r):complex,
              A[j..j+3*span by span]);
  }
}

def cftmd1(span, A, W) {
  const m = radix*span;
  const m2 = 2*m;
  const n = A.domain(1).length;

  cftmd0(span, A, W);
  forall k,k1 in ([m2..n) by m2, 1..(n-m2)/m2) {
    var wk2 = W[k1];
    var wk1 = W[2*k1];
    var wk3 = (wk1.real - 2 * wk2.imag * wk1.imag,
               2 * wk2.imag * wk1.real - wk1.imag):complex;
    for j in [k..k+span) {
      butterfly(wk1, wk2, wk3, A[j..j+3*span by span]);
    }

    wk1 = W[2*k1+1];
    wk3 = (wk1.real - 2 * wk2.real * wk1.imag,
           2 * wk2.real * wk1.real - wk1.imag):complex;

    for j in [k+m..k+m+span) {
      butterfly(wk1, wk2*1.0i, wk3, A[j..j+3*span by span]);
    }
  }
}

def cftmd2(span, A, W) {
  var m = radix*span;
  var m2 = 2*m;
  const n = A.domain(1).length;

  cftmd0(span, A, W);
  if (m2 >= n) return;
  if (m2 >= n / 8) {
    cftmd21(span, A, W);
    return;
  }

  forall j in [0..span) {
    forall k,k1 in ([m2..n) by m2, 1..(n-m2)/m2) {
      var wk2 = W[k1];
      var wk1 = W[k1 + k1];
      var wk3 = (wk1.real - 2*wk2.imag * wk1.imag,
                 2 * wk2.imag * wk1.real - wk1.imag):complex;
      butterfly(wk1, wk2, wk3, A[j+k..j+k+3*span by span]);
    }

    forall k,k1 in ([m2..n) by m2, 1..(n-m2)/m2) {
      var wk2 = W[k1];
      var wk1 = W[2*k1 + 1];
      var wk3 = (wk1.real - 2*wk2.real * wk1.imag,
                 2*wk2.real * wk1.real - wk1.imag):complex;
      wk2 = wk2*1.0i;

      butterfly(wk1, wk2, wk3, A[j+k+m..j+k+m+3*span by span]);
    }
  }
}

def cftmd21(span, A, W) {
  const n = A.domain(1).length;
  var m = radix*span;
  var m2 = 2*m;

  for k,k1 in ([m2..n) by m2, 1..(n-m2)/m2) {
    var wk2 = W[k1];
    var wk1 = W[2*k1];
    var wk3 = (wk1.real - 2*wk2.imag * wk1.imag,
               2* wk2.imag * wk1.real - wk1.imag):complex;

    forall j in [k..k+span) {
      butterfly(wk1, wk2, wk3, A[j..j+3*span by span]);
    }

    wk1 = W[2*k1 + 1];
    wk3 = (wk1.real - 2*wk2.real * wk1.imag,
           2*wk2.real * wk1.real - wk1.imag):complex;
    wk2 = wk2*1.0i;

    forall j in [k+m..k+m+span) {
      butterfly(wk1, wk2, wk3, A[j..j+3*span by span]);
    }
  }
}

def butterfly(wk1, wk2, wk3, inout A:[1..radix]) {
  var x0 = A[1] + A[2];
  var x1 = A[1] - A[2];
  var x2 = A[3] + A[4];
  var x3rot = (A[3] - A[4])*1.0i;

  A[1] = x0 + x2;
  x0 -= x2;
  A[3] = wk2 * x0;
  x0 = x1 + x3rot;
  A[2] = wk1 * x0;
  x0 = x1 - x3rot;
  A[4] = wk3 * x0;
}


Change int(32) args in test to size_t args to match new interface

This commit raises questions about why the comm routiens take the
striding information as void*s rather than int32_t/size_t*s.  Looking
into that next.

//This tests directly call chpl_comm_get_strd to
// 1.- get some elements from B on locale 0 to A on locale 0
// 2.- put some elements from A on locale 0 to B on locale 0

proc TestGetsPuts(A:[], B:[])
{
  A._value.TestGetsPuts(B);
}

proc BlockArr.TestGetsPuts(B)
{
  param stridelevels=1;
  //Errors below if stridelevels=0 !!
  var dststrides:[1..#stridelevels] size_t;
  var srcstrides: [1..#stridelevels] size_t;
  var count: [1..#(stridelevels+1)] size_t;
  var lid=0; //local locale id

  on Locales[0] {
      dststrides[1]=4;
      srcstrides[1]=2;
      count[1]=2;
      count[2]=4;
      writeln();
      var dest = locArr[0].myElems._value.theData; // can this be myLocArr?
      var srcl = B._value.locArr[lid].myElems._value.theData;
      var dststr=dststrides._value.theData;
      var srcstr=srcstrides._value.theData;
      var cnt=count._value.theData;

// 1.- get some elements from B on locale 0 to A on locale 0
      __primitive("chpl_comm_get_strd",
      		  __primitive("array_get",dest,
      			      locArr[0].myElems._value.getDataIndex(24)),
      		  __primitive("array_get",dststr,dststrides._value.getDataIndex(1)),
      		  lid,
      		  __primitive("array_get",srcl,
      			      B._value.locArr[lid].myElems._value.getDataIndex(8)),
      		  __primitive("array_get",srcstr,srcstrides._value.getDataIndex(1)),
      		  __primitive("array_get",cnt, count._value.getDataIndex(1)),
      		  stridelevels);

      var src = locArr[0].myElems._value.theData; // can this be myLocArr?
      var destl = B._value.locArr[lid].myElems._value.theData;

// 2.- put some elements from A on locale 0 to B on locale 0
      __primitive("chpl_comm_put_strd",
      		  __primitive("array_get",destl,
			      B._value.locArr[lid].myElems._value.getDataIndex(16)),
      		  __primitive("array_get",dststr,dststrides._value.getDataIndex(1)),
      		  lid,
      		  __primitive("array_get",src,
      			      locArr[0].myElems._value.getDataIndex(2)),
      		  __primitive("array_get",srcstr,srcstrides._value.getDataIndex(1)),
      		  __primitive("array_get",cnt, count._value.getDataIndex(1)),
      		  stridelevels);

  }
}

use BlockDist;

const n: int=50*numLocales;
var Dist = new dmap(new Block({1..n}));

var Dom: domain(1,int) dmapped Dist = {1..n};

var A:[Dom] int(64); //real
var B:[Dom] int(64); //real

proc main(){

  /* write("A Distribution: "); */

  var a,b:int;
  var i:int;
  for (a,i) in zip(A,{1..n}) do a=i;
  for (b,i) in zip(B,{1..n}) do b=i*100;
  writeln("Original vector:");
  writeln("===================");
  writeln("A= ", A);
  writeln("B= ", B);

  TestGetsPuts(A,B);

  writeln("After gets and puts");

  writeln("A= ", A);
  writeln("B= ", B);

  writeln();

}

//This tests directly call chpl_comm_get_strd to
// 1.- get some elements from B on locale 0 to A on locale 0
// 2.- put some elements from A on locale 0 to B on locale 0

proc TestGetsPuts(A:[], B:[])
{
  A._value.TestGetsPuts(B);
}

proc BlockArr.TestGetsPuts(B)
{
  param stridelevels=1;
  //Errors below if stridelevels=0 !!
  var dststrides:[1..#stridelevels] int(32);
  var srcstrides: [1..#stridelevels] int(32);
  var count: [1..#(stridelevels+1)] int(32);
  var lid=0; //local locale id

  on Locales[0] {
      dststrides[1]=4;
      srcstrides[1]=2;
      count[1]=2;
      count[2]=4;
      writeln();
      var dest = locArr[0].myElems._value.theData; // can this be myLocArr?
      var srcl = B._value.locArr[lid].myElems._value.theData;
      var dststr=dststrides._value.theData;
      var srcstr=srcstrides._value.theData;
      var cnt=count._value.theData;

// 1.- get some elements from B on locale 0 to A on locale 0
      __primitive("chpl_comm_get_strd",
      		  __primitive("array_get",dest,
      			      locArr[0].myElems._value.getDataIndex(24)),
      		  __primitive("array_get",dststr,dststrides._value.getDataIndex(1)),
      		  lid,
      		  __primitive("array_get",srcl,
      			      B._value.locArr[lid].myElems._value.getDataIndex(8)),
      		  __primitive("array_get",srcstr,srcstrides._value.getDataIndex(1)),
      		  __primitive("array_get",cnt, count._value.getDataIndex(1)),
      		  stridelevels);

      var src = locArr[0].myElems._value.theData; // can this be myLocArr?
      var destl = B._value.locArr[lid].myElems._value.theData;

// 2.- put some elements from A on locale 0 to B on locale 0
      __primitive("chpl_comm_put_strd",
      		  __primitive("array_get",destl,
			      B._value.locArr[lid].myElems._value.getDataIndex(16)),
      		  __primitive("array_get",dststr,dststrides._value.getDataIndex(1)),
      		  lid,
      		  __primitive("array_get",src,
      			      locArr[0].myElems._value.getDataIndex(2)),
      		  __primitive("array_get",srcstr,srcstrides._value.getDataIndex(1)),
      		  __primitive("array_get",cnt, count._value.getDataIndex(1)),
      		  stridelevels);

  }
}

use BlockDist;

const n: int=50*numLocales;
var Dist = new dmap(new Block({1..n}));

var Dom: domain(1,int) dmapped Dist = {1..n};

var A:[Dom] int(64); //real
var B:[Dom] int(64); //real

proc main(){

  /* write("A Distribution: "); */

  var a,b:int;
  var i:int;
  for (a,i) in zip(A,{1..n}) do a=i;
  for (b,i) in zip(B,{1..n}) do b=i*100;
  writeln("Original vector:");
  writeln("===================");
  writeln("A= ", A);
  writeln("B= ", B);

  TestGetsPuts(A,B);

  writeln("After gets and puts");

  writeln("A= ", A);
  writeln("B= ", B);

  writeln();

}


Removing unnecessary var descriptor as arrays are already returned by reference

extern proc memcpy(a:[], b, len);

proc string.toBytes() {
   var b : [1..this.length] uint(8);
   memcpy(b, this, this.length);
   return b;
}

const pairs = "ATCGGCTAUAMKRYWWSSYRKMVBHDDHBVNN\n\n".toBytes();
var table : [1..128] uint(8);

proc main() {
  param newLineChar = 0x0A;
  param greaterThan = 0x3E;
  var inFile = openfd(0); // stdin
  const fileLen = inFile.length();
  var data : [1..fileLen] uint(8);
  var r = inFile.reader(locking=false);

  // initialize complement table
  for i in 1..pairs.size by 2 {
    table[pairs[i]] = pairs[i+1];      // uppercase
    if pairs[i] != newLineChar then
      table[pairs[i] + 32] = pairs[i+1]; // lowercase
  }

  var numRead  : int;
  var idx = 1;
  var start = 0;

  // sync statements wait for all tasks inside them to complete
  sync {
    while r.readline(data, numRead, idx) {

      // Look for the start of a section, and if possible
      // spawn a task to start work on the previous section.
      if data[idx] == greaterThan {
        if start == 0 then start = idx;
        else {
          begin process(data, start, idx-2);
          start = idx;
        }
      }
      idx += numRead;
    }

    // work on the last section
    process(data, start, idx-2);
  }

  // Open a binary writer to stdout
  var binout = openfd(1).writer(iokind.native, locking=false,
                                hints=QIO_CH_ALWAYS_UNBUFFERED);
  binout.write(data);
}

proc process(ref data : [], in from : int, end : int) {

  // Skip the header information
  while data[from] != 0xa do from += 1;
  from += 1;

  const len = end - from;
  const off = 60 - (len % 61);

  if off > 0 {
    var m = from + 60 - off;
    while m < end {
      for i in 0..off-1 by -1 do data[m+1+i] = data[m+i];
      data[m+1] = 0xa;
      m += 61;
    }
  }

  const middle = (end-from)/2;
  for i in 0 .. middle {
    const c = table[data[from+i]];
    data[from+i] = table[data[end-i]];
    data[end-i] = c;
  }
}

extern proc memcpy(a:[], b, len);

proc string.toBytes() var {
   var b : [1..this.length] uint(8);
   memcpy(b, this, this.length);
   return b;
}

const pairs = "ATCGGCTAUAMKRYWWSSYRKMVBHDDHBVNN\n\n".toBytes();
var table : [1..128] uint(8);

proc main() {
  param newLineChar = 0x0A;
  param greaterThan = 0x3E;
  var inFile = openfd(0); // stdin
  const fileLen = inFile.length();
  var data : [1..fileLen] uint(8);
  var r = inFile.reader(locking=false);

  // initialize complement table
  for i in 1..pairs.size by 2 {
    table[pairs[i]] = pairs[i+1];      // uppercase
    if pairs[i] != newLineChar then
      table[pairs[i] + 32] = pairs[i+1]; // lowercase
  }

  var numRead  : int;
  var idx = 1;
  var start = 0;

  // sync statements wait for all tasks inside them to complete
  sync {
    while r.readline(data, numRead, idx) {

      // Look for the start of a section, and if possible
      // spawn a task to start work on the previous section.
      if data[idx] == greaterThan {
        if start == 0 then start = idx;
        else {
          begin process(data, start, idx-2);
          start = idx;
        }
      }
      idx += numRead;
    }

    // work on the last section
    process(data, start, idx-2);
  }

  // Open a binary writer to stdout
  var binout = openfd(1).writer(iokind.native, locking=false,
                                hints=QIO_CH_ALWAYS_UNBUFFERED);
  binout.write(data);
}

proc process(ref data : [], in from : int, end : int) {

  // Skip the header information
  while data[from] != 0xa do from += 1;
  from += 1;

  const len = end - from;
  const off = 60 - (len % 61);

  if off > 0 {
    var m = from + 60 - off;
    while m < end {
      for i in 0..off-1 by -1 do data[m+1+i] = data[m+i];
      data[m+1] = 0xa;
      m += 61;
    }
  }

  const middle = (end-from)/2;
  for i in 0 .. middle {
    const c = table[data[from+i]];
    data[from+i] = table[data[end-i]];
    data[end-i] = c;
  }
}


Various types whose default values were compiler inserted but defined in the linked runtime code and thus capable of being referenced from the modules

// Types.chpl
//
// Standard type routines.
//

//
// type predicates
//
proc chpl__isType(type t) param return true;
proc chpl__isType(e) param return false;

pragma "no instantiation limit"
proc _isPrimitiveType(type t) param return
  _isBooleanType(t)  ||
  _isIntegralType(t) ||
  _isRealType(t)     ||
//To allow imag, need to define casts from primitive types into imag.
//_isImagType(t)     ||
  (t == c_string);

pragma "no instantiation limit"
proc _isSimpleScalarType(type t) param return
  _isBooleanType(t) | _isIntegralType(t) | _isFloatType(t);

pragma "no instantiation limit"
proc _isBooleanType(type t) param return
  (t == bool) | (t == bool(8)) | (t == bool(16)) | (t == bool(32)) | (t == bool(64));

pragma "no instantiation limit"
proc _isIntegralType(type t) param return
  _isSignedType(t) || _isUnsignedType(t);

pragma "no instantiation limit"
proc _isSignedType(type t) param return
  (t == int(8)) || (t == int(16)) || (t == int(32)) || (t == int(64));

pragma "no instantiation limit"
proc _isUnsignedType(type t) param return
  (t == uint(8)) || (t == uint(16)) || (t == uint(32)) || (t == uint(64));

pragma "no instantiation limit"
proc _isEnumeratedType(type t) param {
  proc isEnum(type t: enumerated) param return true;
  proc isEnum(type t) param return false;
  return isEnum(t);
}

pragma "no instantiation limit"
proc _isComplexType(type t) param return
  (t == complex(64)) | (t == complex(128));

pragma "no instantiation limit"
proc _isFloatType(type t) param return
  (t == real(32)) | (t == real(64)) |
  (t == imag(32)) | (t == imag(64));

pragma "no instantiation limit"
proc _isRealType(type t) param return
  (t == real(32)) | (t == real(64));

pragma "no instantiation limit"
proc _isImagType(type t) param return
  (t == imag(32)) | (t == imag(64));

// Returns the unsigned equivalent of the input type.
proc chpl__unsignedType(type t) type
{
  if ! _isIntegralType(t) then
    compilerError("range idxType is non-integral: ", typeToString(t));

  return uint(numBits(t));
}

// Returns the signed equivalent of the input type.
proc chpl__signedType(type t) type
{
  if ! _isIntegralType(t) then
    compilerError("range idxType is non-integral: ", typeToString(t));

  return int(numBits(t));
}

proc chpl__maxIntTypeSameSign(type t) type {
  if ! _isIntegralType(t) then
    compilerError("type t is non-integral: ", typeToString(t));

  if (_isSignedType(t)) then
    return int(64);
  else
    return uint(64);
}

//
// These procedures indicate whether or not a type t is a specific type
//
proc isRangeType(type t) param where   t: range  return true;
proc isRangeType(type t) param where !(t: range) return false;

proc isDmapType(type t) param where   t: _distribution  return true;
proc isDmapType(type t) param where !(t: _distribution) return false;

proc isDomainType(type t) param where   t: _domain  return true;
proc isDomainType(type t) param where !(t: _domain) return false;

proc isArrayType(type t) param where   t: _array  return true;
proc isArrayType(type t) param where !(t: _array) return false;

// Is 'sub' a subtype (or equal to) 'super'?
proc isSubtype(type sub, type super) param where   sub: super  return true;
proc isSubtype(type sub, type super) param where !(sub: super) return false;

// Is 'sub' a proper subtype of 'super'?
proc isProperSubtype(type sub, type super) param
  where isSubtype(sub, super) && sub != super
  return true;
proc isProperSubtype(type sub, type super) param
  return false;

// What follows are the type _defaultOf methods, used to initialize types
// Booleans
inline proc _defaultOf(type t) param where (_isBooleanType(t)) return false:t;

// String
// defaultStringValue lives in runtime/include/chpl-string.h
// strings will be records, so param is not possible for them
inline proc _defaultOf(type t) where t: string return defaultStringValue;

// ints, reals, imags, complexes
inline proc _defaultOf(type t) param where (_isIntegralType(t)) return 0:t;
// TODO: In order to make _defaultOf param for reals and imags we had to split
// the cases into their default size and a non-param case.  It is hoped that
// in the future, floating point numbers may be castable whilst param.  In that
// world, we can again shrink these calls into the size-ignorant case.
inline proc _defaultOf(type t) param where t == real(64) return 0.0:t;
inline proc _defaultOf(type t) where (_isRealType(t) && t != real(64)) return 0.0:t;
inline proc _defaultOf(type t) param where t == imag(64) return 0.0i:t;
inline proc _defaultOf(type t) where (_isImagType(t) && t != imag(64)) return 0.0i:t;
// Also, complexes cannot yet be parametized
inline proc _defaultOf(type t): t where (_isComplexType(t)) {
  var ret:t = noinit;
  param floatwidth = numBits(t)/2;
  ret.re = 0.0:real(floatwidth);
  ret.im = 0.0:real(floatwidth);
  return ret;
}

// Enums
inline proc _defaultOf(type t) param where (_isEnumeratedType(t)) {
  return _enum_first(t);
}

// Classes
inline proc _defaultOf(type t) where (isClassType(t)) return nil:t;

// Various types whose default value is known
inline proc _defaultOf(type t) param where t: void return _void;
inline proc _defaultOf(type t) param where t: c_string return "":c_string;
inline proc _defaultOf(type t) where t: opaque return _nullOpaque;
inline proc _defaultOf(type t) where t: chpl_taskID_t return chpl_nullTaskID;
inline proc _defaultOf(type t) where t: _sync_aux_t return _nullSyncVarAuxFields;
inline proc _defaultOf(type t) where t: _single_aux_t return _nullSingleVarAuxFields;
inline proc _defaultOf(type t) where t: _task_list return _nullTaskList;

// Returns true if it is legal to coerce t1 to t2, false otherwise.
proc chpl__legalIntCoerce(type t1, type t2) param
{
  if (_isSignedType(t2)) {
    if (_isSignedType(t1)) {
      return (numBits(t1) <= numBits(t2));
    } else {
      return (numBits(t1) < numBits(t2));
    }
  } else {
    if (_isSignedType(t1)) {
      return false;
    } else {
      return (numBits(t1) <= numBits(t2));
    }
  }
}

// Returns the type with which both s and t are compatible
// That is, both s and t can be coerced to the returned type.
proc chpl__commonType(type s, type t) type
{
  if ! _isIntegralType(s) then
    compilerError("Type ", typeToString(s) , " is non-integral: ");
  if ! _isIntegralType(t) then
    compilerError("Type ", typeToString(t) , " is non-integral: ");

  if numBits(s) > numBits(t) then return s;
  if numBits(s) < numBits(t) then return t;

  if _isSignedType(s) && ! _isSignedType(t) ||
     _isSignedType(t) && ! _isSignedType(s) then
    compilerError("Types ", typeToString(s) , " and ", typeToString(t), " are incompatible.");

  return s;
}

//
// numBits(type) -- returns the number of bits in a type
//

proc numBits(type t) param where t == bool {
  compilerError("default-width 'bool' does not have a well-defined size");
}
proc numBits(type t) param where t == bool(8) return 8;
proc numBits(type t) param where t == bool(16) return 16;
proc numBits(type t) param where t == bool(32) return 32;
proc numBits(type t) param where t == bool(64) return 64;
proc numBits(type t) param where t == int(8) return 8;
proc numBits(type t) param where t == int(16) return 16;
proc numBits(type t) param where t == int(32) return 32;
proc numBits(type t) param where t == int(64) return 64;
proc numBits(type t) param where t == uint(8) return 8;
proc numBits(type t) param where t == uint(16) return 16;
proc numBits(type t) param where t == uint(32) return 32;
proc numBits(type t) param where t == uint(64) return 64;
proc numBits(type t) param where t == real(32) return 32;
proc numBits(type t) param where t == real(64) return 64;
proc numBits(type t) param where t == imag(32) return 32;
proc numBits(type t) param where t == imag(64) return 64;
proc numBits(type t) param where t == complex(64) return 64;
proc numBits(type t) param where t == complex(128) return 128;

//
// numBytes(type) -- returns the number of bytes in a type
//

param bitsPerByte = 8;

proc numBytes(type t) param return numBits(t)/8;

//
// min(type) -- returns the minimum value a type can store
//

proc min(type t) where t == bool
  return false;

proc min(type t) where _isIntegralType(t) || _isFloatType(t)
  return __primitive( "_min", t);

proc min(type t) where _isComplexType(t) {
  var x: t;
  x.re = min(x.re.type);
  x.im = min(x.im.type);
  return x;
}

//
// max(type) -- returns the maximum value a type can store
//

proc max(type t) where t == bool
  return true;

proc max(type t) where _isIntegralType(t) || _isFloatType(t)
  return __primitive( "_max", t);

proc max(type t) where _isComplexType(t) {
  var x: t;
  x.re = max(x.re.type);
  x.im = max(x.im.type);
  return x;
}

iter chpl_enumerate(type t: enumerated) {
  const enumTuple = _enum_enumerate(t);
  for i in 1..enumTuple.size do
    yield enumTuple(i);
}

proc enum_minbits(type t: enumerated) param {
  return __primitive( "enum min bits", t);
}
proc enum_issigned(type t: enumerated) param {
  return __primitive( "enum is signed", t);
}
proc enum_mintype(type t: enumerated) type {
  param minbits = enum_minbits(t);
  param signed = enum_issigned(t);
  if signed {
    return int(minbits);
  } else {
    return uint(minbits);
  }
}

proc numBits(type t: enumerated) param {
  return numBits(enum_mintype(t));
}

//
// identity functions (for reductions)
//
inline proc _prod_id(type t) return 1:t;
inline proc _land_id(type t) return true;
inline proc _lor_id(type t) return false;
inline proc _lxor_id(type t) return false;
inline proc _band_id(type t) {
  // MPF - this doesn't really make sense for floating-point types,
  // but old code had it casting MAX_UINT to the same type...
  // I just moved it from the code generator since we don't need
  // a primitive to generate constants.
  if t == bool then return true;
  if t == int(8) then return -1:t;
  if t == int(16) then return -1:t;
  if t == int(32) then return -1:t;
  if t == int(64) then return -1:t;
  if t == real(32) then return max(uint(32)):t;
  if t == real(64) then return max(uint(64)):t;
  if t == imag(32) then return max(uint(32)):t;
  if t == imag(64) then return max(uint(64)):t;
  if t == complex(64) then return (max(uint(32)):real(32), max(uint(32)):real(32)):t;
  if t == complex(128) then return (max(uint(64)):real(64), max(uint(64)):real(64)):t;
  return max(t);
}
inline proc _bor_id(type t) return 0:t;
inline proc _bxor_id(type t) return 0:t;

// Types.chpl
//
// Standard type routines.
//

//
// type predicates
//
proc chpl__isType(type t) param return true;
proc chpl__isType(e) param return false;

pragma "no instantiation limit"
proc _isPrimitiveType(type t) param return
  _isBooleanType(t)  ||
  _isIntegralType(t) ||
  _isRealType(t)     ||
//To allow imag, need to define casts from primitive types into imag.
//_isImagType(t)     ||
  (t == c_string);

pragma "no instantiation limit"
proc _isSimpleScalarType(type t) param return
  _isBooleanType(t) | _isIntegralType(t) | _isFloatType(t);

pragma "no instantiation limit"
proc _isBooleanType(type t) param return
  (t == bool) | (t == bool(8)) | (t == bool(16)) | (t == bool(32)) | (t == bool(64));

pragma "no instantiation limit"
proc _isIntegralType(type t) param return
  _isSignedType(t) || _isUnsignedType(t);

pragma "no instantiation limit"
proc _isSignedType(type t) param return
  (t == int(8)) || (t == int(16)) || (t == int(32)) || (t == int(64));

pragma "no instantiation limit"
proc _isUnsignedType(type t) param return
  (t == uint(8)) || (t == uint(16)) || (t == uint(32)) || (t == uint(64));

pragma "no instantiation limit"
proc _isEnumeratedType(type t) param {
  proc isEnum(type t: enumerated) param return true;
  proc isEnum(type t) param return false;
  return isEnum(t);
}

pragma "no instantiation limit"
proc _isComplexType(type t) param return
  (t == complex(64)) | (t == complex(128));

pragma "no instantiation limit"
proc _isFloatType(type t) param return
  (t == real(32)) | (t == real(64)) |
  (t == imag(32)) | (t == imag(64));

pragma "no instantiation limit"
proc _isRealType(type t) param return
  (t == real(32)) | (t == real(64));

pragma "no instantiation limit"
proc _isImagType(type t) param return
  (t == imag(32)) | (t == imag(64));

// Returns the unsigned equivalent of the input type.
proc chpl__unsignedType(type t) type
{
  if ! _isIntegralType(t) then
    compilerError("range idxType is non-integral: ", typeToString(t));

  return uint(numBits(t));
}

// Returns the signed equivalent of the input type.
proc chpl__signedType(type t) type
{
  if ! _isIntegralType(t) then
    compilerError("range idxType is non-integral: ", typeToString(t));

  return int(numBits(t));
}

proc chpl__maxIntTypeSameSign(type t) type {
  if ! _isIntegralType(t) then
    compilerError("type t is non-integral: ", typeToString(t));

  if (_isSignedType(t)) then
    return int(64);
  else
    return uint(64);
}

//
// These procedures indicate whether or not a type t is a specific type
//
proc isRangeType(type t) param where   t: range  return true;
proc isRangeType(type t) param where !(t: range) return false;

proc isDmapType(type t) param where   t: _distribution  return true;
proc isDmapType(type t) param where !(t: _distribution) return false;

proc isDomainType(type t) param where   t: _domain  return true;
proc isDomainType(type t) param where !(t: _domain) return false;

proc isArrayType(type t) param where   t: _array  return true;
proc isArrayType(type t) param where !(t: _array) return false;

// Is 'sub' a subtype (or equal to) 'super'?
proc isSubtype(type sub, type super) param where   sub: super  return true;
proc isSubtype(type sub, type super) param where !(sub: super) return false;

// Is 'sub' a proper subtype of 'super'?
proc isProperSubtype(type sub, type super) param
  where isSubtype(sub, super) && sub != super
  return true;
proc isProperSubtype(type sub, type super) param
  return false;

// What follows are the type _defaultOf methods, used to initialize types
// Booleans
inline proc _defaultOf(type t) param where (_isBooleanType(t)) return false:t;

// String
// defaultStringValue lives in runtime/include/chpl-string.h
// strings will be records, so param is not possible for them
inline proc _defaultOf(type t) where t: string return defaultStringValue;

// ints, reals, imags, complexes
inline proc _defaultOf(type t) param where (_isIntegralType(t)) return 0:t;
// TODO: In order to make _defaultOf param for reals and imags we had to split
// the cases into their default size and a non-param case.  It is hoped that
// in the future, floating point numbers may be castable whilst param.  In that
// world, we can again shrink these calls into the size-ignorant case.
inline proc _defaultOf(type t) param where t == real(64) return 0.0:t;
inline proc _defaultOf(type t) where (_isRealType(t) && t != real(64)) return 0.0:t;
inline proc _defaultOf(type t) param where t == imag(64) return 0.0i:t;
inline proc _defaultOf(type t) where (_isImagType(t) && t != imag(64)) return 0.0i:t;
// Also, complexes cannot yet be parametized
inline proc _defaultOf(type t): t where (_isComplexType(t)) {
  var ret:t = noinit;
  param floatwidth = numBits(t)/2;
  ret.re = 0.0:real(floatwidth);
  ret.im = 0.0:real(floatwidth);
  return ret;
}

// Enums
inline proc _defaultOf(type t) param where (_isEnumeratedType(t)) {
  return _enum_first(t);
}

// Classes
inline proc _defaultOf(type t) where (isClassType(t)) return nil:t;

// Various types whose default value is known
inline proc _defaultOf(type t) param where t: c_string return "":c_string;

// Returns true if it is legal to coerce t1 to t2, false otherwise.
proc chpl__legalIntCoerce(type t1, type t2) param
{
  if (_isSignedType(t2)) {
    if (_isSignedType(t1)) {
      return (numBits(t1) <= numBits(t2));
    } else {
      return (numBits(t1) < numBits(t2));
    }
  } else {
    if (_isSignedType(t1)) {
      return false;
    } else {
      return (numBits(t1) <= numBits(t2));
    }
  }
}

// Returns the type with which both s and t are compatible
// That is, both s and t can be coerced to the returned type.
proc chpl__commonType(type s, type t) type
{
  if ! _isIntegralType(s) then
    compilerError("Type ", typeToString(s) , " is non-integral: ");
  if ! _isIntegralType(t) then
    compilerError("Type ", typeToString(t) , " is non-integral: ");

  if numBits(s) > numBits(t) then return s;
  if numBits(s) < numBits(t) then return t;

  if _isSignedType(s) && ! _isSignedType(t) ||
     _isSignedType(t) && ! _isSignedType(s) then
    compilerError("Types ", typeToString(s) , " and ", typeToString(t), " are incompatible.");

  return s;
}

//
// numBits(type) -- returns the number of bits in a type
//

proc numBits(type t) param where t == bool {
  compilerError("default-width 'bool' does not have a well-defined size");
}
proc numBits(type t) param where t == bool(8) return 8;
proc numBits(type t) param where t == bool(16) return 16;
proc numBits(type t) param where t == bool(32) return 32;
proc numBits(type t) param where t == bool(64) return 64;
proc numBits(type t) param where t == int(8) return 8;
proc numBits(type t) param where t == int(16) return 16;
proc numBits(type t) param where t == int(32) return 32;
proc numBits(type t) param where t == int(64) return 64;
proc numBits(type t) param where t == uint(8) return 8;
proc numBits(type t) param where t == uint(16) return 16;
proc numBits(type t) param where t == uint(32) return 32;
proc numBits(type t) param where t == uint(64) return 64;
proc numBits(type t) param where t == real(32) return 32;
proc numBits(type t) param where t == real(64) return 64;
proc numBits(type t) param where t == imag(32) return 32;
proc numBits(type t) param where t == imag(64) return 64;
proc numBits(type t) param where t == complex(64) return 64;
proc numBits(type t) param where t == complex(128) return 128;

//
// numBytes(type) -- returns the number of bytes in a type
//

param bitsPerByte = 8;

proc numBytes(type t) param return numBits(t)/8;

//
// min(type) -- returns the minimum value a type can store
//

proc min(type t) where t == bool
  return false;

proc min(type t) where _isIntegralType(t) || _isFloatType(t)
  return __primitive( "_min", t);

proc min(type t) where _isComplexType(t) {
  var x: t;
  x.re = min(x.re.type);
  x.im = min(x.im.type);
  return x;
}

//
// max(type) -- returns the maximum value a type can store
//

proc max(type t) where t == bool
  return true;

proc max(type t) where _isIntegralType(t) || _isFloatType(t)
  return __primitive( "_max", t);

proc max(type t) where _isComplexType(t) {
  var x: t;
  x.re = max(x.re.type);
  x.im = max(x.im.type);
  return x;
}

iter chpl_enumerate(type t: enumerated) {
  const enumTuple = _enum_enumerate(t);
  for i in 1..enumTuple.size do
    yield enumTuple(i);
}

proc enum_minbits(type t: enumerated) param {
  return __primitive( "enum min bits", t);
}
proc enum_issigned(type t: enumerated) param {
  return __primitive( "enum is signed", t);
}
proc enum_mintype(type t: enumerated) type {
  param minbits = enum_minbits(t);
  param signed = enum_issigned(t);
  if signed {
    return int(minbits);
  } else {
    return uint(minbits);
  }
}

proc numBits(type t: enumerated) param {
  return numBits(enum_mintype(t));
}

//
// identity functions (for reductions)
//
inline proc _prod_id(type t) return 1:t;
inline proc _land_id(type t) return true;
inline proc _lor_id(type t) return false;
inline proc _lxor_id(type t) return false;
inline proc _band_id(type t) {
  // MPF - this doesn't really make sense for floating-point types,
  // but old code had it casting MAX_UINT to the same type...
  // I just moved it from the code generator since we don't need
  // a primitive to generate constants.
  if t == bool then return true;
  if t == int(8) then return -1:t;
  if t == int(16) then return -1:t;
  if t == int(32) then return -1:t;
  if t == int(64) then return -1:t;
  if t == real(32) then return max(uint(32)):t;
  if t == real(64) then return max(uint(64)):t;
  if t == imag(32) then return max(uint(32)):t;
  if t == imag(64) then return max(uint(64)):t;
  if t == complex(64) then return (max(uint(32)):real(32), max(uint(32)):real(32)):t;
  if t == complex(128) then return (max(uint(64)):real(64), max(uint(64)):real(64)):t;
  return max(t);
}
inline proc _bor_id(type t) return 0:t;
inline proc _bxor_id(type t) return 0:t;


Minor wordsmithing on the procedures primer.

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

/*
 * Procedures Primer
 *
 * This primer covers procedures including overloading, argument
 * intents and dynamic dispatch.
 *
 * For examples of generic (template) functions, see generics.chpl.
 *
 */

//
// A procedure groups computations that can be called from another part
// of the program.
// The procedure can be defined with zero or more "formal" arguments.
// Each formal argument can have a default value associated with it.
//
// Formal arguments are supplied with values when the procedure is called.
// The arguments supplied at the call site are the "actual" arguments.
// If a name and '=' preceed an actual argument, the actual is assigned
// to the formal argument with that name.  Any remaining (unnamed) actual
// arguments are assigned to the remaining formal arguments in lexical order.
//
// A procedure can return zero, one or more values (as a tuple).
// The return value type can be specified after the formal argument list.
// If no explicit return value type is supplied, the Chapel compiler infers the
// return value type.
//

//
// Here is a procedure which takes an integer argument and returns and integer
// result.  It computes the factorial of the argument.
//
proc factorial(x: int) : int
{
  if x < 0 then
    halt("factorial -- Sorry, this is not the gamma procedure!");
  return if x == 0 then 1 else x * factorial(x-1);
}

writeln("A simple procedure");
writeln("6! is ", factorial(6));
writeln();

//
// Integers are somewhat small, so we might want to specify a larger return
// type.  Also, we can optimize a bit, compressing the call stack by a factor of 2.
// This version "overloads" the previous version of factorial.
// Upon a call to factorial(), the compiler will choose the best fit.
//
proc factorial(x: int(64)) : int(64)
{
  if x < 1 then
    halt("factorial -- Invalid operand.");
  if x < 3 then return x;
  return x * (x-1) * factorial(x-2);
}
//
// The argument type of this version must be different, so the two versions of
// factorial can be differentiated.
// We must also cast the actual argument to a 64-bit integer to select the "wide"
// version of factorial.
//
writeln("Another simple procedure");
writeln("33! is ", factorial(33: int(64)));
writeln();

//
// Procedure definitions allow you to overload operators, too.
//
record Point { var x, y: real; }

// Tell how to add two points together.
proc +(p1: Point, p2: Point)
{
  // Vector addition in 2-space.
  return new Point(p1.x + p2.x, p1.y + p2.y);
}

//
// We can also overload the writeThis() routine called by writeln.
//
proc Point.writeThis(w: Writer)
{
  // Writes it out as a coordinate pair.
  "(".writeThis(w);
  this.x.writeThis(w);
  ", ".writeThis(w);
  this.y.writeThis(w);
  ")".writeThis(w);
}

writeln("Using operator overloading");
var down = new Point(10.0, 0.0);
var over = new Point(0.0, -5.0);
writeln("down + over = ", down + over);
writeln();

//
// Using named actual arguments can prevent confusion.
//
class Circle {
  var center : Point;
  var radius : real;
}

proc create_circle(x = 0.0, y = 0.0, diameter = 0.0)
{
  var result = new Circle();
  result.radius = diameter / 2;
  result.center.x = x;
  result.center.y = y;
  return result;
}

writeln("Using named arguments");
// Creates a circle at (2.0, 0.0) with a radius of 1.5.
var c = create_circle(diameter=3.0,2.0);
writeln(c);
writeln();

//
// This configuration parameter allows automated tests to run faster
//  by skipping the sleep delays.
// You can try this yourself by adding -suseSleep=false as a compiler option.
//
config param useSleep = true;
use Time;

//
// Normal (blank) intent means that a formal argument cannot be modified
// in the body of a procedure.
// To allow changing the formal (but not the actual), use the "in" intent.
//
proc countDown(in n : uint = 10) : void
{
  while n > 0
  {
    writeln(n, " ...");
    if useSleep then sleep(1);
    n -= 1;
  }
  writeln("Blastoff!");
}

writeln("Using the \"in\" intent");
var s = 5 : uint;
countDown(s);
writeln("s is still ", s);	// 5
writeln();

//
// The inout intent will write back the final value of a formal parameter when
// the procedure exits.
//
proc countDownToZero(inout n : uint = 10) : void
{
  while n > 0
  {
    writeln(n, " ...");
    if useSleep then sleep(1);
    n -= 1;
  }
  writeln("Boink?");
}

writeln("Using the inout intent");
var t = 3 : uint;
countDownToZero(t);
writeln("t is now ", t);	// 0
writeln();

//
// The out intent causes the actual argument to be ignored when the procedure starts.
// The actual is assigned the value of the corresponding formal when the routine exits.
//
// This arctan routine puts the result in res and returns the number of
// iterations it needed to converge.
//
// atan x = x - x^3/3 + x^5/5 + sum_3^inf (-1)^i x^(2i+1)/(2i+1).
//
// This actually converges very slowly for x close to 1 in absolute value.
// So we set the error limit to be 3 significant digits.
//
proc atan(x : real, out result : real)
{
  result = 0.0;
  var count = 0;
  var lastresult = 0.0;
  for i in 1.. by 2
  {
    var twoIP1 = 2 * count + 1;
    var term = x ** twoIP1 / twoIP1;
    result += if count % 2 == 0 then term else -term;
    count += 1;
    if abs(result - lastresult) < 1.0e-3 then break;
    lastresult = result;
  }
  return count;
}

writeln("Using the out intent");
var theta : real;
var n = atan(1.0, theta);
writeln("Computed Pi as about ", 4.0 * theta, " in ", n, " iterations.");
writeln();

//
// A procedure can take a variable number of arguments -- of indeterminate type.
// It is expanded like a generic procedure, with the required number of arguments
// having types which match the actual arguments.
//
proc writeList(x ...?k) {
  var first = true;
  for param i in 1..k {
    if first then first = false; else write(" ");
    write(x(i));
  }
  writeln();
}

writeln("Using variable argument lists.");
writeList(1, "red", 8.72, 1..4);
writeln();

/*
 * Procedures Primer
 *
 * This primer covers procedures including overloading, argument
 * intents and dynamic dispatch.
 *
 * For examples of generic (template) functions, see generics.chpl.
 *
 */

//
// A procedure groups computations that can be called from another part
// of the program.
// The procedure can be defined with zero or more "formal" arguments.
// Each formal argument can have a default value associated with it.
//
// Formal arguments are supplied with values when the procedure is called.
// The arguments supplied at the call site are the "actual" parameters.
// If a name is supplied with an actual argument, the value is assigned
// to the formal argument with the same name.  Any remaining (unnamed) actual
// arguments are assigned to the remaining formal arguments in lexical order.
//
// A procedure can return zero, one or more values (as a tuple).
// The return value type can be specified after the formal argument list.
// If no explicit return value type is supplied, the Chapel compiler infers the
// return value type.
//

//
// Here is a procedure which takes an integer argument and returns and integer
// result.  It computes the factorial of the argument.
//
proc factorial(x: int) : int
{
  if x < 0 then
    halt("factorial -- Sorry, this is not the gamma procedure!");
  return if x == 0 then 1 else x * factorial(x-1);
}

writeln("A simple procedure");
writeln("6! is ", factorial(6));
writeln();

//
// Integers are somewhat small, so we might want to specify a larger return
// type.  Also, we can optimize a bit, compressing the call stack by a factor of 2.
//
proc factorial(x: int(64)) : int(64)
{
  if x < 1 then
    halt("factorial -- Invalid operand.");
  if x < 3 then return x;
  return x * (x-1) * factorial(x-2);
}
//
// The argument type of this version must be different, so the two versions of
// factorial can be differentiated.
// We must also cast the actual argument to a 64-bit integer to select the "wide"
// version of factorial.
//
writeln("Another simple procedure");
writeln("33! is ", factorial(33: int(64)));
writeln();

//
// Procedure definitions allow you to overload operators, too.
//
record Point { var x, y: real; }

// Tell how to add two points together.
proc +(p1: Point, p2: Point)
{
  // Vector addition in 2-space.
  return new Point(p1.x + p2.x, p1.y + p2.y);
}

//
// We can also overload the writeThis() routine called by writeln.
//
proc Point.writeThis(w: Writer)
{
  // Writes it out as a coordinate pair.
  "(".writeThis(w);
  this.x.writeThis(w);
  ", ".writeThis(w);
  this.y.writeThis(w);
  ")".writeThis(w);
}

writeln("Using operator overloading");
var down = new Point(10.0, 0.0);
var over = new Point(0.0, -5.0);
writeln("down + over = ", down + over);
writeln();

//
// Using named actual arguments can prevent confusion.
//
class Circle {
  var center : Point;
  var radius : real;
}

proc create_circle(x = 0.0, y = 0.0, diameter = 0.0)
{
  var result = new Circle();
  result.radius = diameter / 2;
  result.center.x = x;
  result.center.y = y;
  return result;
}

writeln("Using named arguments");
// Creates a circle at (2.0, 0.0) with a radius of 1.5.
var c = create_circle(diameter=3.0,2.0);
writeln(c);
writeln();

//
// This configuration parameter allows automated tests to run faster
//  by skipping the sleep delays.
// You can try this yourself by adding -suseSleep=false as a compiler option.
//
config param useSleep = true;
use Time;

//
// Normal (blank) intent means that a formal argument cannot be modified
// in the body of a procedure.
// To allow changing the formal (but not the actual), use the "in" intent.
//
proc countDown(in n : uint = 10) : void
{
  while n > 0
  {
    writeln(n, " ...");
    if useSleep then sleep(1);
    n -= 1;
  }
  writeln("Blastoff!");
}

writeln("Using the \"in\" intent");
var s = 5 : uint;
countDown(s);
writeln("s is still ", s);	// 5
writeln();

//
// The inout intent will write back the final value of a formal parameter when
// the procedure exits.
//
proc countDownToZero(inout n : uint = 10) : void
{
  while n > 0
  {
    writeln(n, " ...");
    if useSleep then sleep(1);
    n -= 1;
  }
  writeln("Boink?");
}

writeln("Using the inout intent");
var t = 3 : uint;
countDownToZero(t);
writeln("t is now ", t);	// 0
writeln();

//
// The out intent causes an argument to be ignored when the procedure starts,
// but its value is written back when the routine exits.
//
// This arctan routine puts the result in res and returns the number of
// iterations it needed to converge.
//
// atan x = x - x^3/3 + x^5/5 + sum_3^inf (-1)^i x^(2i+1)/(2i+1).
//
// This actually converges very slowly for x close to 1 in absolute value.
// So we set the error limit to be 3 significant digits.
//
proc atan(x : real, out result : real)
{
  result = 0.0;
  var count = 0;
  var lastresult = 0.0;
  for i in 1.. by 2
  {
    var twoIP1 = 2 * count + 1;
    var term = x ** twoIP1 / twoIP1;
    result += if count % 2 == 0 then term else -term;
    count += 1;
    if abs(result - lastresult) < 1.0e-3 then break;
    lastresult = result;
  }
  return count;
}

writeln("Using the out intent");
var theta : real;
var n = atan(1.0, theta);
writeln("Computed Pi as about ", 4.0 * theta, " in ", n, " iterations.");
writeln();

//
// A procedure can take a variable number of arguments -- of indeterminate type.
// It is expanded like a generic procedure, with the required number of arguments
// having types which match the actual arguments.
//
proc writeList(x ...?k) {
  var first = true;
  for param i in 1..k {
    if first then first = false; else write(" ");
    write(x(i));
  }
  writeln();
}

writeln("Using variable argument lists.");
writeList(1, "red", 8.72, 1..4);
writeln();