180 lines
4.4 KiB
Chapel
180 lines
4.4 KiB
Chapel
/***********************************************************************
|
|
* Chapel implementation of "99 bottles of beer"
|
|
*
|
|
* by Brad Chamberlain and Steve Deitz
|
|
* 07/13/2006 in Knoxville airport while waiting for flight home from
|
|
* HPLS workshop
|
|
* compiles and runs with chpl compiler version 1.12.0
|
|
* for more information, contact: chapel_info@cray.com
|
|
*
|
|
*
|
|
* Notes:
|
|
* o as in all good parallel computations, boundary conditions
|
|
* constitute the vast bulk of complexity in this code (invite Brad to
|
|
* tell you about his zany boundary condition simplification scheme)
|
|
* o uses type inference for variables, arguments
|
|
* o relies on integer->string coercions
|
|
* o uses named argument passing (for documentation purposes only)
|
|
***********************************************************************/
|
|
|
|
// allow executable command-line specification of number of bottles
|
|
// (e.g., ./a.out -snumBottles=999999)
|
|
config const numBottles = 99;
|
|
const numVerses = numBottles+1;
|
|
|
|
// a domain to describe the space of lyrics
|
|
var LyricsSpace: domain(1) = {1..numVerses};
|
|
|
|
// array of lyrics
|
|
var Lyrics: [LyricsSpace] string;
|
|
|
|
// parallel computation of lyrics array
|
|
[verse in LyricsSpace] Lyrics(verse) = computeLyric(verse);
|
|
|
|
// as in any good parallel language, I/O to stdout is serialized.
|
|
// (Note that I/O to a file could be parallelized using a parallel
|
|
// prefix computation on the verse strings' lengths with file seeking)
|
|
writeln(Lyrics);
|
|
|
|
|
|
// HELPER FUNCTIONS:
|
|
|
|
proc computeLyric(verseNum) {
|
|
var bottleNum = numBottles - (verseNum - 1);
|
|
var nextBottle = (bottleNum + numVerses - 1)%numVerses;
|
|
return "\n" // disguise space used to separate elements in array I/O
|
|
+ describeBottles(bottleNum, startOfVerse=true) + " on the wall, "
|
|
+ describeBottles(bottleNum) + ".\n"
|
|
+ computeAction(bottleNum)
|
|
+ describeBottles(nextBottle) + " on the wall.\n";
|
|
}
|
|
|
|
|
|
proc describeBottles(bottleNum, startOfVerse:bool = false) {
|
|
// NOTE: bool should not be necessary here (^^^^); working around bug
|
|
var bottleDescription = if (bottleNum) then bottleNum:string
|
|
else (if startOfVerse then "N"
|
|
else "n")
|
|
+ "o more";
|
|
return bottleDescription
|
|
+ " bottle" + (if (bottleNum == 1) then "" else "s")
|
|
+ " of beer";
|
|
}
|
|
|
|
|
|
proc computeAction(bottleNum) {
|
|
return if (bottleNum == 0) then "Go to the store and buy some more, "
|
|
else "Take one down and pass it around, ";
|
|
}
|
|
|
|
|
|
// Modules...
|
|
module M1 {
|
|
var x = 10;
|
|
|
|
var y = 13.0;
|
|
}
|
|
|
|
module M2 {
|
|
use M1 except y;
|
|
use M1 only y;
|
|
proc main() {
|
|
writeln("M2 -> M1 -> x " + x);
|
|
}
|
|
}
|
|
|
|
|
|
// Classes, records, unions...
|
|
const PI: real = 3.14159;
|
|
|
|
record Point {
|
|
var x, y: real;
|
|
}
|
|
var p: Point;
|
|
writeln("Distance from origin: " + sqrt(p.x ** 2 + p.y ** 2));
|
|
p = new Point(1.0, 2.0);
|
|
writeln("Distance from origin: " + sqrt(p.x ** 2 + p.y ** 2));
|
|
|
|
class Circle {
|
|
var p: Point;
|
|
var r: real;
|
|
}
|
|
var c = new Circle(r=2.0);
|
|
proc Circle.area()
|
|
return PI * r ** 2;
|
|
writeln("Area of circle: " + c.area());
|
|
|
|
class Oval: Circle {
|
|
var r2: real;
|
|
}
|
|
proc Oval.area()
|
|
return PI * r * r2;
|
|
|
|
delete c;
|
|
c = nil;
|
|
c = new Oval(r=1.0, r2=2.0);
|
|
writeln("Area of oval: " + c.area());
|
|
|
|
// This is a valid decimal integer:
|
|
var x = 0000000000012;
|
|
|
|
union U {
|
|
var i: int;
|
|
var r: real;
|
|
}
|
|
|
|
// chapel ranges are awesome.
|
|
var r1 = 1..10, // 1 2 3 4 5 6 7 8 9 10
|
|
r2 = 10..1, // no values in this range
|
|
r3 = 1..10 by -1, // 10 9 8 7 6 5 4 3 2 1
|
|
r4 = 1..10 by 2, // 1 3 5 7 9
|
|
r5 = 1..10 by 2 align 0, // 2 4 6 8 10
|
|
r6 = 1..10 by 2 align 2, // 2 4 6 8 10
|
|
r7 = 1..10 # 3, // 1 2 3
|
|
r8 = 1..10 # -2, // 9 10
|
|
r9 = 1..100 # 10 by 2, // 1 3 5 7 9
|
|
ra = 1..100 by 2 # 10, // 1 3 5 7 9 11 13 15 17 19
|
|
rb = 1.. # 100 by 10; // 1 11 21 31 41 51 61 71 81 91
|
|
|
|
// create a variable with default initialization
|
|
var myVarWithoutInit: real = noinit;
|
|
myVarWithoutInit = 1.0;
|
|
|
|
// Chapel has <~> operator for read and write I/O operations.
|
|
class IntPair {
|
|
var x: int;
|
|
var y: int;
|
|
proc readWriteThis(f) {
|
|
f <~> x <~> new ioLiteral(",") <~> y <~> new ioNewline();
|
|
}
|
|
}
|
|
var ip = new IntPair(17,2);
|
|
write(ip);
|
|
|
|
var targetDom = {1..10},
|
|
target: [targetDom] int;
|
|
coforall i in targetDom with (ref target) {
|
|
target[i] = i ** 3;
|
|
}
|
|
|
|
var wideOpen = 0o777,
|
|
mememe = 0o600,
|
|
clique_y = 0O660,
|
|
zeroOct = 0o0,
|
|
minPosOct = 0O1;
|
|
|
|
private module M3 {
|
|
private proc foo() {
|
|
|
|
}
|
|
|
|
private iter bar() {
|
|
for i in 1..10 {
|
|
yield i;
|
|
}
|
|
}
|
|
|
|
private var x: int;
|
|
|
|
}
|