diff --git a/www/Makefile b/www/Makefile index 752cfc7e..4a97e8a6 100644 --- a/www/Makefile +++ b/www/Makefile @@ -15,9 +15,9 @@ $(course): ++xref-in setup/xref load-collections-xref \ --redirect-main http://docs.racket-lang.org/ \ $(course).scrbl - mkdir -p $(course)/code/ + mkdir -p $(course)/code/ cd notes ; \ - tar -c `git ls-files -X .gitignore intro abscond blackmail con dupe extort fraud hustle iniquity jig knock loot mug` | \ + tar -c `git ls-files -X .gitignore intro abscond blackmail con dupe extort fraud hustle iniquity jig knock loot mug fp project.pdf` | \ (cd ../main/code ; tar -x) ; cd ../.. clean: diff --git a/www/info.rkt b/www/info.rkt new file mode 100644 index 00000000..1a064da8 --- /dev/null +++ b/www/info.rkt @@ -0,0 +1,2 @@ +#lang info +(define test-omit-paths '("notes/fp/sieve.rkt")) \ No newline at end of file diff --git a/www/notes/fp/sieve.rkt b/www/notes/fp/sieve.rkt new file mode 100644 index 00000000..b79f33cc --- /dev/null +++ b/www/notes/fp/sieve.rkt @@ -0,0 +1,127 @@ +#lang racket + +(begin + ;; sieve for computing primes, based on GT Benchmarks + + ;;-------------------------------------------------------------------------------------------------- + ;; streams + + (define (stream hd thunk) + (cons hd thunk)) + + (define (stream-first s) + (car s)) + + (define (stream-rest s) + (cdr s)) + + ;(: make-stream (-> Natural (-> stream) stream)) + (define (make-stream hd thunk) + (stream hd thunk)) + + ;; Destruct a stream into its first value and the new stream produced by de-thunking the tail + ;(: stream-unfold (-> stream (cons Natural stream))) + (define (stream-unfold st) + (cons (stream-first st) ((stream-rest st)))) + + ;; [stream-get st i] Get the [i]-th element from the stream [st] + ;(: stream-get (-> stream Natural Natural)) + (define (stream-get st i) + (match (stream-unfold st) + [(cons hd tl) + (cond [(= i 0) hd] + [else (stream-get tl (sub1 i))])])) + + ;; [stream-take st n] Collect the first [n] elements of the stream [st]. + ;(: stream-take (-> stream Natural (Listof Natural))) + (define (stream-take st n) + (cond [(= n 0) '()] + [else (match (stream-unfold st) + [(cons hd tl) + (cons hd (stream-take tl (sub1 n)))])])) + + ;;-------------------------------------------------------------------------------------------------- + ;; sieve + + ;; `count-from n` Build a stream of integers starting from `n` and iteratively adding 1 + ;(: count-from (-> Natural stream)) + (define (count-from n) + (make-stream n (λ () (count-from (add1 n))))) + + ;; `sift n st` Filter all elements in `st` that are equal to `n`. + ;; Return a new stream. + ;(: sift (-> Natural stream stream)) + (define (sift n st) + (match (stream-unfold st) + [(cons hd tl) + (cond [(= 0 (modulo hd n)) (sift n tl)] + [else (make-stream hd (λ () (sift n tl)))])])) + + ;; `sieve st` Sieve of Eratosthenes + ;(: sieve (-> stream stream)) + (define (sieve st) + (match (stream-unfold st) + [(cons hd tl) + (make-stream hd (λ () (sieve (sift hd tl))))])) + + ;; stream of prime numbers + ;(: primes (-> stream) + (define (primes) (sieve (count-from 2))) + + ;;-------------------------------------------------------------------------------------------------- + ;; reading numbers + + (define (* n m) + (match n + [0 0] + [1 m] + [n (+ m (* (sub1 n) m))])) + + (define (expt n m) + (match m + [0 1] + [1 n] + [m (* n (expt n (sub1 m)))])) + + (define (read-number) + (digits->number (read-digits))) + + (define (read-digits) + (let ((c (read-char))) + (if (eof-object? c) + '() + (if (eq? #\newline c) + '() + (cons c (read-digits)))))) + + (define (digits->number ds) + (match ds + ['() 0] + [(cons d ds) + (+ (* (digit->number d) + (expt 10 (length ds))) + (digits->number ds))])) + + (define (digit->number d) + (match d + [#\0 0] + [#\1 1] + [#\2 2] + [#\3 3] + [#\4 4] + [#\5 5] + [#\6 6] + [#\7 7] + [#\8 8] + [#\9 9])) + + ;;-------------------------------------------------------------------------------------------------- + (define (modulo n m) + (if (< n m) + n + (modulo (- n m) m))) + + ;;-------------------------------------------------------------------------------------------------- + ;; computes nth prim + + (stream-get (primes) (sub1 (read-number)))) diff --git a/www/notes/project.pdf b/www/notes/project.pdf new file mode 100644 index 00000000..de9a0471 Binary files /dev/null and b/www/notes/project.pdf differ diff --git a/www/project.scrbl b/www/project.scrbl index be94856f..c468d7cc 100644 --- a/www/project.scrbl +++ b/www/project.scrbl @@ -1,6 +1,6 @@ #lang scribble/manual @(require "defns.rkt") -@title[#:style '(toc unnumbered)]{Project} +@title[#:style '(unnumbered)]{Project} There will be a final course project to be completed over the last several weeks of the course. The project will involve extending the @@ -19,6 +19,8 @@ learned over the semester to complete a full-featured compiler. Project repository: @centered{@link[repo repo]} +@link["code/project.pdf"]{Slides} from lecture on the project. + You are given a working compiler for an extension of the language we have been developing all semester. @@ -62,6 +64,38 @@ in the compiler. There will be a garbage collector provided by the second round of benchmarks which you will need to incorporate in to your compiler. +@section[#:tag-prefix "fp-" #:style 'unnumbered]{Measuring run-times} + +Let's look at an example of how to measure the run-time performance of +the code your compiler generates. + +First, let's start with fairly computationally intensive program. +Here is a @link["code/fp/sieve.rkt"]{program} that computes the +@emph{n}th prime number using the ancient +@link["https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes"]{Sieve of +Eratosthenes} method. + +Save it to the directory where your compiler lives and run @tt{make +sieve.run}. This will run the compiler to generate the @tt{sieve.run} +executable. This program expects to read a number from the standard +input port. + +Run: + +@centered{@tt{echo -n 100 | ./sieve.run}} + +to compute the 100th prime number. + +To measure the time it takes, add the time command: + +@centered{@tt{echo -n 100 | time ./sieve.run}} + +This will run the program and show the result @emph{and} timing +information. We will be concerned with improving the real time it +takes to run the program. + + +@section[#:tag-prefix "fp-" #:style 'unnumbered]{Testing} @bold{There is separate a repository for tests.} When you push your code, Travis will automatically run your code against the tests. If