summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--chapel.html.markdown276
1 files changed, 145 insertions, 131 deletions
diff --git a/chapel.html.markdown b/chapel.html.markdown
index ecbab2a2..8b41dc32 100644
--- a/chapel.html.markdown
+++ b/chapel.html.markdown
@@ -25,29 +25,30 @@ writeln( "World!" );
// each thing is printed right next to each other, so include your spacing!
writeln( "There are ", 3, " commas (\",\") in this line of code" );
// Different output channels
-stdout.writeln( "This goes to standard output (just like plain writeln() does)");
+stdout.writeln( "This goes to standard output (just like plain writeln( ) does)");
stderr.writeln( "This goes to standard error" );
// Variables dont have to be explicitly typed as long as
// the compiler can figure out the type that it will hold.
var myVar = 10; // 10 is an int, so myVar is implicitly an int
myVar = -10;
+var mySecondVar = myVar;
// var anError; // this would be a compile time error.
// We can (and should) explicitly type things
-var mySecondVar: real; // define mySecondVar as a real
-var myThirdVar: real = -1.234;
-mySecondVar = myThirdVar;
+var myThirdVar: real; // define mySecondVar as a real
+var myFourthVar: real = -1.234;
+myThirdVar = myFourthVar;
// There are a number of basic types.
-var myInt: int = -1000; // signed ints
-var myUint: uint = 1234; // unsigned ints
-var myReal: real = 9.876; // floating point numbers
-var myImag: imag = 5.0i; // imaginary numbers
-var myCplx: complex = 10 + 9i; // complex numbers
-myCplx = myInt + myImag ; // another way to form complex numbers
-var myBool: bool = false; // booleans
-var myStr: string = "Some string..."; // strings
+var myInt: int = -1000; // Signed ints
+var myUint: uint = 1234; // Unsigned ints
+var myReal: real = 9.876; // Floating point numbers
+var myImag: imag = 5.0i; // Imaginary numbers
+var myCplx: complex = 10 + 9i; // Complex numbers
+myCplx = myInt + myImag ; // Another way to form complex numbers
+var myBool: bool = false; // Booleans
+var myStr: string = "Some string..."; // Strings
// Some types can have sizes
var my8Int: int(8) = 10; // 8 bit (one byte) sized int;
@@ -59,6 +60,7 @@ var intFromReal2: int = myReal : int;
// consts are constants, they cannot be changed after set in runtime
const almostPi: real = 22.0/7.0;
+
// params are constants whose value must be known statically at compile time
// Like consts, they cannot be changed during runtime
param compileTimeConst: int = 16;
@@ -68,47 +70,47 @@ param compileTimeConst: int = 16;
// config vars and consts can be changed through the command line at run time
config var varCmdLineArg: int = -123;
config const constCmdLineArg: int = 777;
-// set with --VarName=Value or --VarName Value at run time
+// Set with --VarName=Value or --VarName Value at run time
// config params can be set at compile time
config param paramCmdLineArg: bool = false;
writeln( varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg );
-//set config with --set paramCmdLineArg=value at compile time
+// Set config with --set paramCmdLineArg=value at compile time
// Math operators
var a: int, thisInt = 1234, thatInt = 5678;
a = thisInt + thatInt; // Addition
a = thisInt * thatInt; // Multiplication
a = thisInt - thatInt; // Subtraction
-a = thisInt / thatInt; // division
-a = thisInt ** thatInt; // exponentiation
-a = thisInt % thatInt; // remainder (modulo)
+a = thisInt / thatInt; // Division
+a = thisInt ** thatInt; // Exponentiation
+a = thisInt % thatInt; // Remainder (modulo)
// Logical Operators
var b: bool, thisBool = false, thatBool = true;
-b = thisBool && thatBool; // logical and
-b = thisBool || thatBool; // logical or
-b = !thisBool; // logical negation
+b = thisBool && thatBool; // Logical and
+b = thisBool || thatBool; // Logical or
+b = !thisBool; // Logical negation
// Relational Operators
-b = thisInt > thatInt; // greater-than
-b = thisInt >= thatInt; // greater-than-or-equal-to
-b = thisInt < a && a <= thatInt; // less-than, and, less-than-or-equal-to
-b = thisInt != thatInt; // not-equal-to
-b = thisInt == thatInt; // equal-to
+b = thisInt > thatInt; // Greater-than
+b = thisInt >= thatInt; // Greater-than-or-equal-to
+b = thisInt < a && a <= thatInt; // Less-than, and, less-than-or-equal-to
+b = thisInt != thatInt; // Not-equal-to
+b = thisInt == thatInt; // Equal-to
// Bitwise operations
-a = thisInt << 10; // left-bit-shift by 10 bits;
-a = thatInt >> 5; // right-bit-shift by 5 bits;
-a = ~thisInt; // bitwise-negation
-a = thisInt ^ thatInt; // bitwise exclusive-or
+a = thisInt << 10; // Left-bit-shift by 10 bits;
+a = thatInt >> 5; // Right-bit-shift by 5 bits;
+a = ~thisInt; // Bitwise-negation
+a = thisInt ^ thatInt; // Bitwise exclusive-or
// Compound assignment operations
-a += thisInt; // addition-equals ( a = a + thisInt;)
-a *= thatInt; // times-equals ( a = a * thatInt; )
-b &&= thatBool; // logical-and-equals ( b = b && thatBool; )
-a <<= 3; // left-bit-shift-equals ( a = a << 10; )
-// and so on...
+a += thisInt; // Addition-equals ( a = a + thisInt;)
+a *= thatInt; // Times-equals ( a = a * thatInt; )
+b &&= thatBool; // Logical-and-equals ( b = b && thatBool; )
+a <<= 3; // LEft-bit-shift-equals ( a = a << 10; )
+// and many, many more.
// Unlike other C family languages there are no
// pre/post-increment/decrement operators like
// ++j, --j, j++, j--
@@ -119,8 +121,7 @@ var old_that = thatInt;
thisInt <=> thatInt; // Swap the values of thisInt and thatInt
writeln( (old_this == thatInt) && (old_that == thisInt) );
-// We can also define operator overloads,
-// which we'll cover with procedures.
+// Operator overloads can also be defined, as we'll see with procedures
// Tuples can be of the same type
var sameTup: 2*int = (10,-1);
@@ -128,25 +129,29 @@ var sameTup2 = (11, -6);
// or different types
var diffTup: (int,real,complex) = (5, 1.928, myCplx);
var diffTupe2 = ( 7, 5.64, 6.0+1.5i );
+
// Accessed using array bracket notation
// However, tuples are all 1-indexed
writeln( "(", sameTup[1], ",", sameTup[2], ")" );
writeln( diffTup );
+
// Tuples can also be written into.
diffTup[1] = -1;
+
// Can expand tuple values into their own variables
var (tupInt, tupReal, tupCplx) = diffTup;
writeln( diffTup == (tupInt, tupReal, tupCplx) );
+
// Useful for writing a list of variables ( as is common in debugging)
writeln( (a,b,thisInt,thatInt,thisBool,thatBool) );
// Type aliasing
-type chroma = int; // type of a single hue
-type RGBColor = 3*chroma; // type representing a full color
+type chroma = int; // Type of a single hue
+type RGBColor = 3*chroma; // Type representing a full color
var black: RGBColor = ( 0,0,0 );
var white: RGBColor = ( 255, 255, 255 );
-// if-then-else works just like any other C-family language
+// If-then-else works just like any other C-family language
if 10 < 100 then
writeln( "All is well" );
@@ -193,16 +198,16 @@ select( inputOption ){
}
}
-// While loops and Do-While loops are basically the same in every language.
+// While and Do-While loops are basically the same in every language.
var j: int = 1;
var jSum: int = 0;
while( j <= 1000 ){
jSum += j;
- j += 1; // there are no ++j, --j, j++, j--, operators
+ j += 1;
}
writeln( jSum );
-// basic Do-While loop
+// Do-While loop
do{
jSum += j;
j += 1;
@@ -213,7 +218,7 @@ writeln( jSum );
// Ranges themselves are types, and can be stuffed into variables
// (more about that later)
for i in 1..10 do write( i , ", ") ;
-writeln();
+writeln( );
var iSum: int = 0;
for i in 1..1000 {
@@ -225,7 +230,7 @@ for x in 1..10 {
for y in 1..10 {
write( (x,y), "\t" );
}
- writeln();
+ writeln( );
}
// Ranges and Domains
@@ -238,14 +243,16 @@ for x in 1..10 {
var range1to10: range = 1..10; // 1, 2, 3, ..., 10
var range2to11 = 2..11; // 2, 3, 4, ..., 11
var rangeThistoThat: range = thisInt..thatInt; // using variables
-var rangeEmpty: range = 100..-100 ; // this is a valid, but empty range
+var rangeEmpty: range = 100..-100 ; // this is valid but contains no indices
-//ranges can be unbounded
-var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ; // 1, 2, 3, 4, 5, ...
-var rangeNegInfto1 = ..1; // ..., -4, -3, -2, -1, 0, 1
+// Ranges can be unbounded
+var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ;
+// 1, 2, 3, 4, 5, ...
// Note: the range(boundedType= ... ) is only
// necessary if we explicitly type the variable
+var rangeNegInfto1 = ..1; // ..., -4, -3, -2, -1, 0, 1
+
// Ranges can be strided using the 'by' operator.
var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10
// Note: the range(stridable=true) is only
@@ -280,24 +287,23 @@ var threeDims: domain(3) = {thirdDim, 1..10, 5..10}; // using a range variable
// Can iterate over the indices as tuples
for idx in twoDimensions do
write( idx , ", ");
-writeln();
+writeln( );
-// Or can deconstruct the tuple
+// or can deconstruct the tuple
for (x,y) in twoDimensions {
write( "(", x, ", ", y, ")", ", " );
}
-writeln();
+writeln( );
// Associative domains act like sets
var stringSet: domain(string); // empty set of strings
stringSet += "a";
stringSet += "b";
stringSet += "c";
-stringSet += "a"; // redundant add "a"
-stringSet -= "c"; // remove "c"
+stringSet += "a"; // Redundant add "a"
+stringSet -= "c"; // Remove "c"
writeln( stringSet );
-
// Array are similar to those of other languages.
// Their sizes are defined using domains that represent their indices
var intArray: [1..10] int;
@@ -307,35 +313,35 @@ var intArray2: [{1..10}] int; //equivalent
for i in 1..10 do
intArray[i] = -i;
writeln( intArray );
-// we cannot access intArray[0] because it exists outside
-// of the index set, {1..10}, we defined it to have
+// We cannot access intArray[0] because it exists outside
+// of the index set, {1..10}, we defined it to have.
// intArray[11] is illegal for the same reason.
var realDomain: domain(2) = {1..5,1..7};
var realArray: [realDomain] real;
-var realArray2: [1..5,1..7] real; // equivalent
-var realArray3: [{1..5,1..7}] real; // equivalent
+var realArray2: [1..5,1..7] real; // Equivalent
+var realArray3: [{1..5,1..7}] real; // Equivalent
for i in 1..5 {
- for j in realDomain.dim(2) { // only use the 2nd dimension of the domain
- realArray[i,j] = -1.61803 * i + 0.5 * j; // access using index list
- var idx: 2*int = (i,j); // note: 'index' is a keyword
- realArray[idx] = - realArray[(i,j)]; // index using tuples
+ for j in realDomain.dim(2) { // Only use the 2nd dimension of the domain
+ realArray[i,j] = -1.61803 * i + 0.5 * j; // Access using index list
+ var idx: 2*int = (i,j); // Note: 'index' is a keyword
+ realArray[idx] = - realArray[(i,j)]; // Index using tuples
}
}
-// arrays have domains as members that we can iterate over
-for idx in realArray.domain { // again, idx is a 2*int tuple
- realArray[idx] = 1 / realArray[idx[1],idx[2]]; // access by tuple and list
+// Arrays have domains as members that we can iterate over
+for idx in realArray.domain { // Again, idx is a 2*int tuple
+ realArray[idx] = 1 / realArray[idx[1],idx[2]]; // Access by tuple and list
}
writeln( realArray );
-// can also iterate over the values of an array
+// Can also iterate over the values of an array
var rSum: real = 0;
for value in realArray {
- rSum += value; // read a value
- value = rSum; // write a value
+ rSum += value; // Read a value
+ value = rSum; // Write a value
}
writeln( rSum, "\n", realArray );
@@ -351,12 +357,12 @@ proc fibonacci( n : int ) : int {
return fibonacci( n-1 ) + fibonacci( n-2 );
}
-// input parameters can be untyped (a generic procedure)
+// Input parameters can be untyped (a generic procedure)
proc doublePrint( thing ): void {
write( thing, " ", thing, "\n");
}
-// return type can be inferred (as long as the compiler can figure it out)
+// Return type can be inferred (as long as the compiler can figure it out)
proc addThree( n ) {
return n + 3;
}
@@ -372,12 +378,12 @@ proc maxOf( x ...?k ) {
}
writeln( maxOf( 1, -10, 189, -9071982, 5, 17, 20001, 42 ) );
-// the ? operator is called the query operator, and is used to take
+// The ? operator is called the query operator, and is used to take
// undetermined values (like tuple or array sizes, and generic types).
// Taking arrays as parameters.
// The query operator is used to determine the domain of A.
-// this is important to define the return type (if you wanted to)
+// This is important to define the return type (if you wanted to)
proc invertArray( A: [?D] int ): [D] int{
for a in A do a = -a;
return A;
@@ -396,7 +402,7 @@ writeln( defaultsProc( x=11 ) );
writeln( defaultsProc( x=12, y=5.432 ) );
writeln( defaultsProc( y=9.876, x=13 ) );
-// intent modifiers on the arguments convey how
+// Intent modifiers on the arguments convey how
// those arguments are passed to the procedure
// in: copy arg in, but not out
// out: copy arg out, but not in
@@ -426,7 +432,7 @@ proc makeArray( elems: int, startNumber: int ) ref : [1..#elems] int {
return array;
}
writeln( makeArray( 10, -1 ) );
-// this makes more practical sense for class methods where references to
+// This makes more practical sense for class methods where references to
// elements in a data-structure are returned via a method or iterator
// We can query the type of arguments to generic procedures
@@ -462,17 +468,17 @@ whereProc( 10 );
whereProc( -1 );
// whereProc( 0 ) would result in a compiler error because there
// are no functions that satisfy the where clause's condition.
-// We could have defined a whereProc without a where clause that would
-// then have been called.
+// We could have defined a whereProc without a where clause that would then have
+// served as a catch all for all the other cases (of which there is only one).
-// Operator definitions are through procedures as well
-// we can define the unary operators:
+// Operator definitions are through procedures as well.
+// We can define the unary operators:
// + - ! ~
// and the binary operators:
// + - * / % ** == <= >= < > << >> & | ˆ by
// += -= *= /= %= **= &= |= ˆ= <<= >>= <=>
-// boolean exclusive or operator
+// Boolean exclusive or operator
proc ^( left : bool, right : bool ): bool {
return (left || right) && !( left && right );
}
@@ -487,8 +493,8 @@ proc *( left : ?ltype, right : ?rtype): ( ltype, rtype ){
return (left, right );
}
-writeln( 1 * "a" ); // uses our * operator
-writeln( 1 * 2 ); // uses the original * operator
+writeln( 1 * "a" ); // Uses our * operator
+writeln( 1 * 2 ); // Uses the default * operator
/*
Note: You could break everything if you get careless with your overloads.
@@ -498,24 +504,21 @@ proc +( left: int, right: int ): int{
}
*/
-// iterators are a close cousin to the procedure.
+// Iterators are a sisters to the procedure, and almost
+// everything about procedures also applies to iterators
// However, instead of returning a single value,
// iterators yield many values to a loop.
// This is useful when a complicated set or order of iterations is needed but
// allows the code defining the iterations to be separate from the loop body.
iter oddsThenEvens( N: int ): int {
- for i in 1..N by 2 {
+ for i in 1..N by 2 do
yield i; // yield values instead of returning.
- }
-
- for i in 2..N by 2 {
+ for i in 2..N by 2 do
yield i;
- }
}
for i in oddsThenEvens( 10 ) do write( i, ", " );
-writeln();
-
+writeln( );
// Classes are similar to those in C++ and Java.
// They currently lack privatization
@@ -548,7 +551,7 @@ class MyClass {
return this.memberInt;
}
- proc getMemberBool(): bool {
+ proc getMemberBool( ): bool {
return this.memberBool;
}
@@ -556,30 +559,30 @@ class MyClass {
// Construct using default constructor, using default values
var myObject = new MyClass( 10 );
- myObject = new MyClass( memberInt = 10 ); // equivalent
-writeln( myObject.getMemberInt() );
+ myObject = new MyClass( memberInt = 10 ); // Equivalent
+writeln( myObject.getMemberInt( ) );
// ... using our values
var myDiffObject = new MyClass( -1, true );
myDiffObject = new MyClass( memberInt = -1,
- memberBool = true ); // equivalent
+ memberBool = true ); // Equivalent
writeln( myDiffObject );
// Construct using written constructor
var myOtherObject = new MyClass( 1.95 );
- myOtherObject = new MyClass( val = 1.95 ); // equivalent
-writeln( myOtherObject.getMemberInt() );
+ myOtherObject = new MyClass( val = 1.95 ); // Equivalent
+writeln( myOtherObject.getMemberInt( ) );
// We can define an operator on our class as well but
// the definition has to be outside the class definition
proc +( A : MyClass, B : MyClass) : MyClass {
- return new MyClass( memberInt = A.getMemberInt() + B.getMemberInt(),
- memberBool = A.getMemberBool() || B.getMemberBool() );
+ return new MyClass( memberInt = A.getMemberInt( ) + B.getMemberInt( ),
+ memberBool = A.getMemberBool( ) || B.getMemberBool( ) );
}
var plusObject = myObject + myDiffObject;
writeln( plusObject );
-// destruction
+// Destruction
delete myObject;
delete myDiffObject;
delete myOtherObject;
@@ -620,10 +623,10 @@ class GenericClass {
return this.classArray[ i ];
}
- // Define an iterator for the class to
- // yield values from the array to a loop
+ // Define an implicit iterator for the class
+ // to yield values from the array to a loop
// i.e. for i in objVar do ....
- iter these() ref : classType {
+ iter these( ) ref : classType {
for i in this.classDomain do
yield this[i];
}
@@ -635,19 +638,19 @@ var realList = new GenericClass( real, 10 );
// notation that we defined ( proc this( i: int ){ ... } )
for i in realList.classDomain do realList[i] = i + 1.0;
// We can iterate over the values in our list with the iterator
-// we defined ( iter these(){ ... } )
+// we defined ( iter these( ){ ... } )
for value in realList do write( value, ", " );
-writeln();
+writeln( );
// Make a copy of realList using the copy constructor
var copyList = new GenericClass( realList );
for value in copyList do write( value, ", " );
-writeln();
+writeln( );
-// make a copy of realList and change the type, also using the copy constructor
+// Make a copy of realList and change the type, also using the copy constructor
var copyNewTypeList = new GenericClass( realList, int );
for value in copyNewTypeList do write( value, ", " );
-writeln();
+writeln( );
// Parallelism
// In other languages, parallelism is typically this is done with
@@ -655,14 +658,14 @@ writeln();
// Chapel has it baked right into the language.
// A begin statement will spin the body of that statement off into one new task.
-// a sync statement will ensure that the progress of the
-// main task will not progress until the children have synced back up.
+// A sync statement will ensure that the progress of the main
+// task will not progress until the children have synced back up.
sync {
- begin { // start of new task's body
+ begin { // Start of new task's body
var a = 0;
for i in 1..1000 do a += 1;
writeln( "Done: ", a);
- } // end of new tasks body
+ } // End of new tasks body
writeln( "spun off a task!");
}
writeln( "Back together" );
@@ -671,13 +674,13 @@ proc printFibb( n: int ){
writeln( "fibonacci(",n,") = ", fibonacci( n ) );
}
-// a cobegin statement will spin each statement of the body into one new task
+// A cobegin statement will spin each statement of the body into one new task
cobegin {
printFibb( 20 ); // new task
printFibb( 10 ); // new task
printFibb( 5 ); // new task
{
- // this is a nested statement body and thus is a single statement
+ // This is a nested statement body and thus is a single statement
// to the parent statement and is executed by a single task
writeln( "this gets" );
writeln( "executed as" );
@@ -700,41 +703,41 @@ coforall taskID in 1..#num_tasks {
forall i in 1..100 {
write( i, ", ");
}
-writeln();
+writeln( );
// Here we see that there are sections that are in order, followed by
-// a section that would not follow ( e.g. 1, 2, 3, 7, 8, 9, 4, 5, 6, )
-// this is because each task is taking on a chunk of the range 1..10
+// a section that would not follow ( e.g. 1, 2, 3, 7, 8, 9, 4, 5, 6, ).
+// This is because each task is taking on a chunk of the range 1..10
// (1..3, 4..6, or 7..9) doing that chunk serially, but each task happens
// in parallel.
// Your results may depend on your machine and configuration
-// For both the forall and coforall loops, the execution of the parent task
-// will not continue until all the children sync up.
+// For both the forall and coforall loops, the execution of the
+// parent task will not continue until all the children sync up.
-// forall loops are particularly useful for parallel iteration over arrays
+// forall loops are particularly useful for parallel iteration over arrays.
// Lets run an experiment to see how much faster a parallel loop is
use Time; // Import the Time module to use Timer objects
var timer: Timer;
-var myBigArray: [{1..4000,1..4000}] real; // large array we will write into
+var myBigArray: [{1..4000,1..4000}] real; // Large array we will write into
// Serial Experiment
-timer.start(); // start timer
-for (x,y) in myBigArray.domain { // serial iteration
+timer.start( ); // Start timer
+for (x,y) in myBigArray.domain { // Serial iteration
myBigArray[x,y] = (x:real) / (y:real);
}
-timer.stop(); // stop timer
-writeln( "Serial: ", timer.elapsed() ); // print elapsed time
-timer.clear(); // clear timer for parallel loop
+timer.stop( ); // Stop timer
+writeln( "Serial: ", timer.elapsed( ) ); // Print elapsed time
+timer.clear( ); // Clear timer for parallel loop
// Parallel Experiment
-timer.start(); // start timer
-forall (x,y) in myBigArray.domain { // parallel iteration
+timer.start( ); // start timer
+forall (x,y) in myBigArray.domain { // Parallel iteration
myBigArray[x,y] = (x:real) / (y:real);
}
-timer.stop(); // stop timer
-writeln( "Parallel: ", timer.elapsed() ); // print elapsed time
-timer.clear();
-// you may have noticed that (depending on how many cores you have) that
-// the parallel loop went faster than the serial loop
+timer.stop( ); // Stop timer
+writeln( "Parallel: ", timer.elapsed( ) ); // Print elapsed time
+timer.clear( );
+// You may have noticed that (depending on how many cores you have)
+// that the parallel loop went faster than the serial loop
// A succinct way of writing a forall loop over an array:
// iterate over values
@@ -750,6 +753,17 @@ Refer to the [language specification](http://chapel.cray.com/language.html) and
Occasionally check back here and on the [Chapel site](http://chapel.cray.com) to see if more topics have been added or more tutorials created.
+### What this tutorial is lacking:
+ * Modules and standard modules
+ * Synchronize and atomic variables
+ * Multiple Locales (distributed memory system)
+ * proc main(){ ... }
+ * Records
+ * Whole/sliced array assignment
+ * Reductions and scans
+ * Range and domain slicing
+ * Parallel iterators
+
Your input, questions, and discoveries are important to the developers!
-----------------------------------------------------------------------
The Chapel language is still in-development (version 1.11.0), so there are occasional hiccups with performance and language features.