forked from The-Royal-We/mu-cs424-f2015
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlecture-05.scm
151 lines (129 loc) · 3.66 KB
/
lecture-05.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
;;; Scheme
;;; Tail Recursion
;;; Bad terminology, but hey that's the English language.
;;; http://www.explainxkcd.com/wiki/index.php/1270:_Functional
;;; Functional programming combines the flexibility and power of abstract mathematics
;;; with the intuitive clarity of abstract mathematics.
;;; Sussman and Steele, "Lambda the Ultimate X", (the "lambda papers")
;;; http://lambda-the-ultimate.org/papers
;; Source Language:
;; foo(x,y,z)
;; ...
;; Assembly Language:
;; push z # marshal the arguments
;; push y
;; push x
;; push L17
;; jump foo
;; L17: ...
;; foo: ...
;; jump address-on-top-of-stack-and-pop-it
;; Source:
;; return foo(x,y,z) // This is a "tail recursive call"
;; Assembly Language:
;; push z # marshal the arguments
;; push y
;; push x
;; push L17
;; jump foo
;; L17: jump address-on-top-of-stack-and-pop-it
;;; Like forwarding a letter from me to you, back to me, then to 'Joe'.
;;; Three things are needed for the procedure call
;;; 1. marshal the arguments
;;; 2. branch to return
;;; 3. push return address
;; Assembly Language OPTIMIZED WITH TAIL RECURSION
;; push z # marshal the arguments
;; push y
;; push x
;; jump foo
;;; Cut out the waste and just forward the letter straight to 'Joe'.
;; Use this trick to mechanically transform code gotos into procedure calls
;; // add up sqrt of all prime numbers between n1 and n2
;;; Fortran code - the horror
;; double ssp(int n1, int n2) {
;; int t = 0;
;; i = n1;
;; top: if (i>n2) {
;; goto bot;
;; } else {
;; if (prime(i)) {
;; t = t+sqrt(i);
;; i = i+1;
;; goto top;
;; } else {
;; i = i+1;
;; goto top;
;; }
;; }
;; bot: return t;
;; }
;;; The hated goto, considered harmful
;;; See https://en.wikipedia.org/wiki/Fortran#Humor
;;; Translation of the above Fortran code
(define ssp (λ (n1 n2) (ssp-top n1 n2 0 n1)))
(define ssp-top
(λ (n1 n2 t i)
(if (> i n2)
(ssp-bot t)
(if (prime? i)
(ssp-top n1 n2 (+ t (sqrt i)) (+ i 1))
(ssp-top n1 n2 t (+ i 1))))))
(define ssp-bot (λ (t) t))
;;; GPU's are horrible
;;; Adding labels is like adding a programming/break point
;;; we can stop at any point and look at our live variables
;; double ssp(int n1, int n2) {
;; int t = 0;
;; t1: i = n1;
;; top: if (i>n2) {
;; t1a: goto bot;
;; } else {
;; t2: if (prime(i)) {
;; t3: t = t+sqrt(i);
;; t4: i = i+1;
;; t5: goto top;
;; } else {
;; t6: i = i+1;
;; t7: goto top;
;; }
;; }
;; bot: return t;
;; }
(define ttp (λ (n1 n2) (t1 n1 n2 0)))
(define t1 (λ (n1 n2 t) (top n1 n2 t n1)))
(define ttop (λ (n1 n2 t i) (if (> i n2) (t1a n1 n2 t i) (t2 n1 n2 t i))))
(define t1a (λ (n1 n2 t i) (tbot t)))
(define t2 (λ (n1 n2 t i) (if (prime? i) (t3 n1 n2 t i) (t6 n1 n2 t i))))
(define t3 (λ (n1 n2 t i) (t4 n1 n2 (+ t (sqrt i)) i)))
(define t4 (λ (n1 n2 t i) (t5 n1 n2 t (+ i 1))))
(define t5 (λ (n1 n2 t i) (ttop n1 n2 t i)))
(define t6 (λ (n1 n2 t i) (t7 n1 n2 t (+ i 1))))
(define t7 (λ (n1 n2 t i) (ttop n1 n2 t i)))
(define tbot (λ (t) t))
;;; Horrible to read but it happens inside the compiler (possibly even more horrible in reality)
;;; What's pretty cool about Tail Recursion - pretty clear loops
;;; sum_i={0,n} sqrt(i)
(define ssqrt1
(λ (n)
(if (zero? n)
0
(+ (sqrt n)
(ssqrt1 (- n 1))))))
;;; This will stack overflow in C/Java on large inputs
;;; Scheme tries to optimise for tail recursion so it doesn't blow the stack
;;; sum_i={0,n} sqrt(i)
(define ssqrt2
(λ (n)
(ssqrt2-loop 0 n)))
;;; t + sum_i={0,n} sqrt(i)
(define ssqrt2-loop
(λ (t n)
(if (zero? n)
t
(ssqrt2-loop (+ t (sqrt n)) (- n 1)))))
;; (define ssqrt2-loop
;; (λ (t n)
;; (if (NONTR:zero? n)
;; t
;; (TR:ssqrt2-loop (NONTR:+ t (NONTR:sqrt n)) (NONTR:- n 1)))))