diff --git a/labs/lab2-reductions-and-prefix-sums/README.md b/labs/lab2-reductions-and-prefix-sums/README.md new file mode 100755 index 0000000000000000000000000000000000000000..42240bb9256fa9b23d95cca6cd67e4e47427f562 --- /dev/null +++ b/labs/lab2-reductions-and-prefix-sums/README.md @@ -0,0 +1,355 @@ +# Reductions and Prefix Sums + +Use the following commands to make a fresh clone of your repository: + +``` +git clone -b reductions git@gitlab.epfl.ch:lamp/student-repositories-s21/cs206-GASPAR.git cs206-reductions +``` + +## Useful links + + * [A guide to the Scala parallel collections](https://docs.scala-lang.org/overviews/parallel-collections/overview.html) + * [The API documentation of the Scala parallel collections](https://www.javadoc.io/doc/org.scala-lang.modules/scala-parallel-collections_2.13/latest/scala/collection/index.html) + * [The API documentation of the Scala standard library](https://www.scala-lang.org/files/archive/api/2.13.4) + * [The API documentation of the Java standard library](https://docs.oracle.com/en/java/javase/15/docs/api/index.html) + +**If you have issues with the IDE, try [reimporting the +build](https://gitlab.epfl.ch/lamp/cs206/-/blob/master/labs/example-lab.md#ide-features-like-type-on-hover-or-go-to-definition-do-not-work), +if you still have problems, use `compile` in sbt instead.** + +## Introduction + +In this assignment, you will implement several variants of reduction and prefix +sum algorithms. Each of the three parts of the assignment will exercise a +different aspect of parallel programming: + +- choosing the right parallelization threshold +- identifying the correct reduction operator +- identifying the correct prefix sum operator + +We will use the `parallel` construct, defined in the file `package.scala`, as in the lecture to start parallel +computations. Every `parallel` construct invocation takes two tasks as input and +outputs the corresponding results as a tuple of two elements. You are not allowed +to use the `task` construct in this assignment. + +## Parallel Counting Change + +If you took the course Functional Programming in Scala, you surely recall the +assignment in which you had to count the number of ways in which you can make +the change for a given amount of money. +The text of that assignment was as follows: + +> Write a recursive function that counts how many different ways you can +> make change for an amount, given a list of coin denominations. For +> example, there are 3 ways to give change for 4 if you have coins with +> denomination 1 and 2: 1+1+1+1, 1+1+2, 2+2. + +In this assignment, you will repeat the same task, but this time, your +implementation will be parallel. +Start with the sequential version of this problem once more -- the `countChange` +function takes the amount of money and the list of different coin denominations. +It returns the total number of different ways you can give change: + +```scala +def countChange(money: Int, coins: List[Int]): Int +``` + +Note that the solution to this problem is recursive. +In every recursive call, we either decide to continue subtracting the next coin +in the `coins` list from the `money` amount, or we decide to drop the coin from the list of coins. +For example, if we have 4 CHF, and coin denominations of 1 and 2, the call +graph, in which every node depicts one invocation of the `countChange` method, +is as follows: + + 4,[1, 2] + 3,[1, 2] + 4,[2] + 2,[1, 2] + 3,[2] 2,[2] + 4,[] + 1,[1, 2] + 2,[2] 1,[2] + 3,[] 0,[2] + 2,[] 0 + 0,[1, 2] + 1,[2] 1 0 0 1 0 + 1 0 + +We can take advantage of this recursive structure by evaluating different +subtrees in parallel. +This is the next part of the assignment -- implement the method `parCountChange` +that counts the amount of change in parallel: + +```scala +def parCountChange(money: Int, coins: List[Int], threshold: Threshold): Int +``` + +As we learned in the lectures, the `parCountChange` should not spawn parallel +computations after reaching the leaf in the call graph -- the synchronization +costs of doing this are way too high. +Instead, we need to *agglomerate* parts of the computation. +We do this by calling the sequential `countChange` method when we decide that +the amount of work is lower than a certain value, called the *threshold*. +To separate the concern of deciding on the threshold value from the +implementation of our parallel algorithm, we implement the threshold +functionality in a separate function, described by the `Threshold` type alias: + +```scala +type Threshold = (Int, List[Int]) => Boolean +``` + +When a `threshold` function returns `true` for a given amount of money and the +given list of coins, the sequential `countChange` implementation must be called. + +Implement `parCountChange`! + +Now that we have the `parCountChange` method, we ask ourselves what is the right +implementation of the `threshold` function? +Recall the examples from the lectures, such as summing the array values and +computing the norm, where this was easy -- we exactly knew the amount of work +required to traverse a subrange of the array, so `threshold` could return `true` +when the length of the subrange was smaller than a certain value. + +Sadly, the total amount of work for a given `parCountChange` invocation is hard +to evaluate from the remaining amount of money and a list of coins. +In fact, the amount of work directly corresponds to the count that +`parCountChange` returns, which is the value that we are trying to compute. +Counting change is a canonical example of a task-parallel problem in which the +partitioning the workload across processors is *solution-driven* -- to know how +to optimally partition the work, we would first need to solve the problem +itself. + +For this reason, many parallel algorithms in practice rely on heuristics to +assess the amount of work in a subtask. +We will implement several such heuristics in this exercise, and assess the +effect on performance. +First, implement the `moneyThreshold` method, which creates a threshold function +that returns `true` when the amount of money is less than or equal to `2 / 3` of +the starting amount: + +```scala +def moneyThreshold(startingMoney: Int): Threshold +``` + +Remember that `a / b` will return the integer division of `a` and `b` when both +operands are `Int`s. To avoid this problem, be sure to always do the multiplication of +`startingMoney` by `2` before doing the division by `3`. + +Now run the `ParallelCountChange` application in sbt and observe the speedup: + +``` +> runMain reductions.ParallelCountChangeRunner +``` + +The previous heuristic did not take into account how many coins were left on the +coins list, so try two other heuristics. +Implement the method `totalCoinsThreshold`, which returns a threshold function +that returns `true` when the number of coins is less than or equal to the `2 / 3` of the +initial number of coins: + +```scala +def totalCoinsThreshold(totalCoins: Int): Threshold +``` + +Again, be careful about the order of operations. + +Then, implement the method `combinedThreshold`, which returns a threshold +function that returns `true` when the amount of money multiplied with the number +of remaining coins is less than or equal to the starting money multiplied with +the initial number of coins divided by `2`: + +```scala +def combinedThreshold(startingMoney: Int, allCoins: List[Int]): Threshold +``` + +Which of the three threshold heuristics gives the best speedup? +Can you think of a heuristic that improves performance even more? + + +## Parallel Parentheses Balancing + +In this part of the assignment, we recall the Parenthesis Balancing assignment +that might be familiar to you from the Functional Programming in Scala course. +Here, the task is to, given an array of characters, decide if the parentheses in +the array are balanced. + +Let us recall a few examples of strings in which parentheses are correctly +balanced: + +``` +(if (zero? x) max (/ 1 x)) +I told him (that it's not (yet) done). (But he wasn't listening) +``` + +Similarly, the parentheses in the following strings are not balanced: + +``` +(o_() +:-) +())( +``` + +Implement a sequential function `balance`, which returns `true` iff the +parentheses in the array are balanced: + +```scala +def balance(chars: Array[Char]): Boolean +``` + +Next, you will implement a parallel version of this method. +By now, you're already an expert at implementing the structure of a reduction +algorithm, so you should have no problem there. +The tricky part in parallel parentheses balancing is choosing the reduction +operator -- you probably implemented `balance` by keeping an integer +accumulator, incrementing it for left parentheses and decrementing it for the +right ones, taking care that this accumulator does not drop below zero. +Parallel parentheses balancing will require a bit more ingenuity on your part, +so we will give you a hint -- you will need two integer values for the +accumulator. + +Implement the `parBalance` method, which checks if the parentheses in the input +array are balanced using two helper methods `reduce` and `traverse`. +These methods implement the parallel reduction and the sequential traversal +part, respectively: + +```scala +def parBalance(chars: Array[Char], threshold: Int): Boolean = { + def traverse(idx: Int, until: Int, _???_: Int, _???_: Int): ??? + + def reduce(from: Int, until: Int): ??? = ??? + + reduce(0, chars.length) == ??? +} +``` + +In this case, we again use the fixed threshold parameter, as we did in the +lectures. Sections with size smaller or equal to the threshold should be processed sequentially. +For maximum performance, use a `while` loop in the `traverse` method, or make +`traverse` tail-recursive -- do not use a `Range`. + +Now, run the `ParallelParenthesesBalancing` application from sbt: + +``` +> runMain reductions.ParallelParenthesesBalancingRunner +``` + +How large was your speedup? + +If you are looking for additional challenges, prove that your reduction operator +is associative! + + +## Line of Sight + +In the last part of the exercise, you will be implementing an entirely new +parallel algorithm -- you will apply the prefix sum algorithm to computing the +line-of-sight in two-dimensional terrain. + +Imagine that you are standing at the zero of a coordinate system. +The curve to your right describes the terrain that you are facing. +This is shown in the following figure: + + + +The task of the line-of-sight algorithm is to compute the visibility of each +point of the terrain, as shown in the following figure, where the visible area +is above of the full line, and the obscured terrain is shown with a dotted +line. + + + +What is the necessary and sufficient condition for a point on the terrain to be +visibile from the zero of the coordinate system, where you are standing? +Imagine that the terrain heights are represented with an array of numbers. +We can compute (the tangent of) the viewing angle of each point on the terrain by dividing the +height of the terrain `xs(i)` with the distance from the viewing point `i`, +as shown in the following figure: + + + +It turns out that if the viewing angle of some point B is **lower** than the +viewing angle of an earlier point A, then the point B is not visible, as shown +in the following figure: + + + +This simple realization allows us to easily compute the line-of-sight on the +terrain -- if you were a sequential programmer, you would traverse the array of +height values from the beginning to the end, and write the maximum angle seen so +far into the output array. + +Implement the sequential `lineOfSight` method, which, for each height entry in +the `input` array (except for input(0) which is the location of the observer and +is always zero), writes the maximum angle until that point into the `output` +array (output(0) should be 0): + +```scala +def lineOfSight(input: Array[Float], output: Array[Float]): Unit +``` + +We keep things simple -- instead of outputting an array of booleans denoting the +visibilities, we only output the angles. + +Note that what we call an angle in this assignment is actually the tangent +of the angle. Indeed, `xs(i)` is the opposing side of the angle and `i` the adjacent side. +The ratio `xs(i) / i` that you compute is in fact the tangent of the angle! +Since the tangent of an angle is strictly increasing between +0° and 90°, it is a perfectly good replacement for the actual angle in our use case. +Keep this in mind and make sure that you do not apply any trigonometic functions on the tangent! + +When we see a sequential algorithm that produces a sequence of values by +traversing the input from left to right, this is an indication that the +algorithm might have a parallel prefix sum variant. +So let's try to implement one! + +Recall what you learned in the lectures -- the first phase of the parallel +prefix sum algorithm is the *upsweep* phase. +Here, the algorithm constructs the reduction tree by traversing parts of the +input array in parallel. +Implement the method `upsweepSequential`, which returns the maximum angle in a +given part of the array, and the method `upsweep`, which returns the reduction +tree over parts of the input array. If the length of the given part of the input +array is less than or equal to `threshold`, then `upsweep` calls `upsweepSequential`. +Note that the part of the input array that needs to traversed is represented +using indices 'from' (inclusive) and 'until' (or 'end') (exclusive). + +```scala +def upsweepSequential(input: Array[Float], from: Int, until: Int): Float +``` + +```scala +def upsweep(input: Array[Float], from: Int, end: Int, threshold: Int): Tree +``` + +The `Tree` data type is either a `Leaf` or an inner `Node`, and it contains the +maximum angle in the corresponding part of the array. +Note that when the number of elements in a part of the input array, +which is `(end - from)`, is smaller or equal to the threshold, the sequential `upsweepSequential` +has to be invoked, and you should return a `Leaf`. +Otherwise, you should process the part of the input array in parallel, and return +a `Node`. Make sure that the work is evenly distributed between the parallel computations. + +The second phase is called *downsweep* -- here, the algorithm uses the tree to +push the maximum angle in the corresponding *prefix* of the array to the leaves +of the tree, and outputs the values. +Implement the methods `downsweep` which processes parts of the tree in parallel, +and the method `downsweepSequential`, which traverses the parts of the array +corresponding to leaves of the tree and writes the final angles into the +`output` array: + +```scala +def downsweep(input: Array[Float], output: Array[Float], + startingAngle: Float, tree: Tree): Unit + +def downsweepSequential(input: Array[Float], output: Array[Float], + startingAngle: Float, from: Int, until: Int): Unit +``` + +Finally, implement `parLineOfSight` using the `upsweep` and `downsweep` methods: + +```scala +def parLineOfSight(input: Array[Float], output: Array[Float], + threshold: Int): Unit +``` + +Now, run the `LineOfSight` application in sbt and observe the relative speedups: + +``` +> runMain reductions.LineOfSightRunner +``` + +How large is the speedup compared to the number of cores in your processor? +Can you explain your results? diff --git a/labs/lab2-reductions-and-prefix-sums/angle-example-2.svg b/labs/lab2-reductions-and-prefix-sums/angle-example-2.svg new file mode 100755 index 0000000000000000000000000000000000000000..bd478938260a921b527b14d622e57d7f951c8da3 --- /dev/null +++ b/labs/lab2-reductions-and-prefix-sums/angle-example-2.svg @@ -0,0 +1,209 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + viewBox="0 0 744.09448819 1052.3622047" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="angle-example-2.svg" + inkscape:export-filename="C:\cygwin\home\axel22\workspaces\scala\progfun\instructions\angle2.png" + inkscape:export-xdpi="32.263699" + inkscape:export-ydpi="32.263699"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path4146" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lend" + style="overflow:visible;" + inkscape:isstock="true"> + <path + id="path4149" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) rotate(180) translate(12.5,0)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.9899495" + inkscape:cx="488.53326" + inkscape:cy="701.51987" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1600" + inkscape:window-height="877" + inkscape:window-x="-4" + inkscape:window-y="-4" + inkscape:window-maximized="1" + inkscape:snap-text-baseline="false" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart)" + d="m 142.85714,101.50506 0,298.57143" + id="path3336" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.8496573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend)" + d="m 142.85714,399.21935 668.06991,0" + id="path3340" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:3,3;stroke-dashoffset:0" + d="m 143.44166,399.80366 c 88.89343,-20.20305 105.05587,-39.39595 105.05587,-39.39595" + id="path4640" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,3;stroke-opacity:1;stroke-dashoffset:0" + d="m 248.24499,360.5773 c 0,0 34.72027,-23.20876 57.95379,-32.30013 39.28467,-15.37226 57.45614,8.89703 57.45614,8.89703 19.69797,32.32488 43.43656,27.27412 55.55839,8.08122 l 12.12183,-19.1929 0,0 c 40.4061,-86.87311 77.78174,-113.13708 77.78174,-113.13708 0,0 18.22571,-16.58543 45.38508,0.61276 28.26715,17.89967 41.48804,62.0167 41.48804,62.0167" + id="path4642" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cscscccsc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,3;stroke-opacity:1;stroke-dashoffset:0" + d="m 595.70683,274.55743 c 0,0 12.08157,73.3608 31.09283,77.76906 28.85051,6.68975 48.99239,-25.75889 48.99239,-25.75889 0,0 17.42513,-17.42513 27.27412,-14.89975 9.84899,2.52538 30.50526,33.55149 30.50526,33.55149" + id="path4752" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cscsc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 142.85714,398.79078 500,221.64792" + id="path4832" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:6,3;stroke-dashoffset:0" + d="m 501.03566,222.01682 0,176.77669" + id="path5388" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path5390" + d="m 142.43151,219.99652 358.60415,-1e-5" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:6, 3;stroke-dashoffset:0;stroke-opacity:1" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="310.11682" + y="200.8036" + id="text5392" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan5394" + x="310.11682" + y="200.8036">i</tspan></text> + <text + sodipodi:linespacing="125%" + id="text5396" + y="293.73761" + x="504.0661" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="293.73761" + x="504.0661" + id="tspan5398" + sodipodi:role="line">xs(i)</tspan></text> + <path + inkscape:connector-curvature="0" + id="path3357" + d="m 632.35549,355.35695 0,41.41625" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:6,3;stroke-dashoffset:0;stroke-opacity:1" /> + <path + sodipodi:nodetypes="cc" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.48477578;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:6.96955149, 3.48477574;stroke-dashoffset:0;stroke-opacity:1" + d="m 148.49243,353.35696 483.86306,-1e-5" + id="path3359" + inkscape:connector-curvature="0" /> + <text + sodipodi:linespacing="125%" + id="text3361" + y="347.29602" + x="458.60925" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="347.29602" + x="458.60925" + id="tspan3363" + sodipodi:role="line">i'</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="637.40619" + y="385.66147" + id="text3365" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan3367" + x="637.40619" + y="385.66147">xs(i')</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="486.89352" + y="201.81377" + id="text4181" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4183" + x="486.89352" + y="201.81377">A</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="625.28442" + y="344.24527" + id="text4185" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4187" + x="625.28442" + y="344.24527">B</tspan></text> + </g> +</svg> diff --git a/labs/lab2-reductions-and-prefix-sums/angle-example.svg b/labs/lab2-reductions-and-prefix-sums/angle-example.svg new file mode 100755 index 0000000000000000000000000000000000000000..fd674128904de49c6b165b094b478f33c029f64b --- /dev/null +++ b/labs/lab2-reductions-and-prefix-sums/angle-example.svg @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + viewBox="0 0 744.09448819 1052.3622047" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="angle-example.svg" + inkscape:export-filename="C:\cygwin\home\axel22\workspaces\scala\progfun\instructions\angle.png" + inkscape:export-xdpi="32.263699" + inkscape:export-ydpi="32.263699"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path4146" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lend" + style="overflow:visible;" + inkscape:isstock="true"> + <path + id="path4149" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) rotate(180) translate(12.5,0)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.9899495" + inkscape:cx="488.53326" + inkscape:cy="701.51987" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1600" + inkscape:window-height="877" + inkscape:window-x="-4" + inkscape:window-y="-4" + inkscape:window-maximized="1" + inkscape:snap-text-baseline="false" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart)" + d="m 142.85714,101.50506 0,298.57143" + id="path3336" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.8496573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend)" + d="m 142.85714,399.21935 668.06991,0" + id="path3340" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:3,3;stroke-dashoffset:0" + d="m 143.44166,399.80366 c 88.89343,-20.20305 105.05587,-39.39595 105.05587,-39.39595" + id="path4640" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,3;stroke-opacity:1;stroke-dashoffset:0" + d="m 248.24499,360.5773 c 0,0 34.72027,-23.20876 57.95379,-32.30013 39.28467,-15.37226 57.45614,8.89703 57.45614,8.89703 19.69797,32.32488 43.43656,27.27412 55.55839,8.08122 l 12.12183,-19.1929 0,0 c 40.4061,-86.87311 77.78174,-113.13708 77.78174,-113.13708 0,0 18.22571,-16.58543 45.38508,0.61276 28.26715,17.89967 41.48804,62.0167 41.48804,62.0167" + id="path4642" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cscscccsc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,3;stroke-opacity:1;stroke-dashoffset:0" + d="m 595.70683,274.55743 c 0,0 12.08157,73.3608 31.09283,77.76906 28.85051,6.68975 48.99239,-25.75889 48.99239,-25.75889 0,0 17.42513,-17.42513 27.27412,-14.89975 9.84899,2.52538 30.50526,33.55149 30.50526,33.55149" + id="path4752" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cscsc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 142.85714,398.79078 500,221.64792" + id="path4832" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:6,3;stroke-dashoffset:0" + d="m 501.03566,222.01682 0,176.77669" + id="path5388" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path5390" + d="m 142.43151,219.99652 358.60415,-1e-5" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:6, 3;stroke-dashoffset:0;stroke-opacity:1" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="310.11682" + y="200.8036" + id="text5392" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan5394" + x="310.11682" + y="200.8036">i</tspan></text> + <text + sodipodi:linespacing="125%" + id="text5396" + y="326.0625" + x="506.0864" + style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="326.0625" + x="506.0864" + id="tspan5398" + sodipodi:role="line">xs(i)</tspan></text> + </g> +</svg> diff --git a/labs/lab2-reductions-and-prefix-sums/angle.png b/labs/lab2-reductions-and-prefix-sums/angle.png new file mode 100755 index 0000000000000000000000000000000000000000..50a8cc00497fa82cbb7442ac40ddd56b88dc9885 Binary files /dev/null and b/labs/lab2-reductions-and-prefix-sums/angle.png differ diff --git a/labs/lab2-reductions-and-prefix-sums/angle2.png b/labs/lab2-reductions-and-prefix-sums/angle2.png new file mode 100755 index 0000000000000000000000000000000000000000..d5b4fccface66a660bcee7539458198423fb674e Binary files /dev/null and b/labs/lab2-reductions-and-prefix-sums/angle2.png differ diff --git a/labs/lab2-reductions-and-prefix-sums/terrain.png b/labs/lab2-reductions-and-prefix-sums/terrain.png new file mode 100755 index 0000000000000000000000000000000000000000..11ba1b6f55b18bdd7d93e73c3e751739eaf1be32 Binary files /dev/null and b/labs/lab2-reductions-and-prefix-sums/terrain.png differ diff --git a/labs/lab2-reductions-and-prefix-sums/terrain.svg b/labs/lab2-reductions-and-prefix-sums/terrain.svg new file mode 100755 index 0000000000000000000000000000000000000000..d9073e066c7e53114119200db0a88d9084909c11 --- /dev/null +++ b/labs/lab2-reductions-and-prefix-sums/terrain.svg @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + viewBox="0 0 744.09448819 1052.3622047" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="terain.svg"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path4146" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lend" + style="overflow:visible;" + inkscape:isstock="true"> + <path + id="path4149" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) rotate(180) translate(12.5,0)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.49497475" + inkscape:cx="363.63782" + inkscape:cy="644.8613" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1600" + inkscape:window-height="877" + inkscape:window-x="-4" + inkscape:window-y="-4" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart)" + d="m 142.85714,101.50506 0,298.57143" + id="path3336" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.8496573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend)" + d="m 142.85714,399.21935 668.06991,0" + id="path3340" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="m 143.44166,399.80366 c 88.89343,-20.20305 105.05587,-39.39595 105.05587,-39.39595" + id="path4640" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 248.24499,360.5773 c 0,0 34.72027,-23.20876 57.95379,-32.30013 39.28467,-15.37226 57.45614,8.89703 57.45614,8.89703 19.69797,32.32488 43.43656,27.27412 55.55839,8.08122 l 12.12183,-19.1929 0,0 c 40.4061,-86.87311 77.78174,-113.13708 77.78174,-113.13708 0,0 18.22571,-16.58543 45.38508,0.61276 28.26715,17.89967 41.48804,62.0167 41.48804,62.0167" + id="path4642" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cscscccsc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 595.70683,274.55743 c 0,0 12.08157,73.3608 31.09283,77.76906 28.85051,6.68975 48.99239,-25.75889 48.99239,-25.75889 0,0 17.42513,-17.42513 27.27412,-14.89975 9.84899,2.52538 30.50526,33.55149 30.50526,33.55149" + id="path4752" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cscsc" /> + </g> +</svg> diff --git a/labs/lab2-reductions-and-prefix-sums/visibility.png b/labs/lab2-reductions-and-prefix-sums/visibility.png new file mode 100755 index 0000000000000000000000000000000000000000..9a26107e64f77f3a6d217f5ea80e0cffdb8127d8 Binary files /dev/null and b/labs/lab2-reductions-and-prefix-sums/visibility.png differ diff --git a/labs/lab2-reductions-and-prefix-sums/visibility.svg b/labs/lab2-reductions-and-prefix-sums/visibility.svg new file mode 100755 index 0000000000000000000000000000000000000000..e4f1882336cea5d065a7d1f96c00e5de991a77ae --- /dev/null +++ b/labs/lab2-reductions-and-prefix-sums/visibility.svg @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + viewBox="0 0 744.09448819 1052.3622047" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="visibility.svg"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path4146" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lend" + style="overflow:visible;" + inkscape:isstock="true"> + <path + id="path4149" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) rotate(180) translate(12.5,0)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.98994949" + inkscape:cx="450.29691" + inkscape:cy="792.75432" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1600" + inkscape:window-height="877" + inkscape:window-x="-4" + inkscape:window-y="-4" + inkscape:window-maximized="1" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Lstart)" + d="m 142.85714,101.50506 0,298.57143" + id="path3336" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.8496573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Lend)" + d="m 142.85714,399.21935 668.06991,0" + id="path3340" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 143.44166,399.80366 C 229.1208,389.60061 247.60467,362.19342 247.60467,362.19342" + id="path4640" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 247.12126,362.59389 c 0,0 35.844,-25.22535 59.07752,-34.31672 50.7702,-20.12943 91.36602,-35.89748 158.70779,-62.92894 2.54896,-14.01596 48.13888,-55.27993 48.13888,-55.27993" + id="path4642" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1" + d="m 594.1916,275.56758 c 0,0 12.08157,73.3608 31.09283,77.76906 28.85051,6.68975 48.99239,-25.75889 48.99239,-25.75889 0,0 17.42513,-17.42513 27.27412,-14.89975 9.84899,2.52538 30.50526,33.55149 30.50526,33.55149" + id="path4752" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cscsc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 312.07723,326.23693 465.71429,265.21935" + id="path4754" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 511.25,211.11221 742.85714,79.505061" + id="path4756" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + sodipodi:nodetypes="cscscccsc" + inkscape:connector-curvature="0" + id="path4758" + d="m 245.5023,364.2185 c 0,0 35.844,-25.22535 59.07752,-34.31672 39.28467,-15.37226 57.45614,8.89703 57.45614,8.89703 19.69797,32.32488 43.43656,27.27412 55.55839,8.08122 l 12.12183,-19.1929 0,0 c 40.4061,-86.87311 77.78174,-113.13708 77.78174,-113.13708 0,0 18.22571,-16.58543 45.38508,0.61276 28.26715,17.89967 41.48804,62.0167 41.48804,62.0167" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1" /> + </g> +</svg>