/
idlang
195 lines (131 loc) · 3.88 KB
/
idlang
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
; vim: set ts=4 sw=4 et ft=idlang:
;+
; Greatest common divisor function
;-
function gcd, a, b
compile_opt idl2, hidden
j = a & k = b
while (finite(k) and (k /= 0)) do begin
t = j mod k
j = k
k = t
endwhile
return, a
end
;+
; Least common multiple funcion
;-
function lcm, a, b
compile_opt idl2, hidden
return, abs(a * b) / gcd(a, b)
end
pro rat::normalize
compile_opt idl2, hidden
n = gcd(abs(self.numerator), abs(self.denominator))
; Note: This only works in IDL >= 8.3
new_numerator = (self.numerator / n) * $
signum(signum(self.numerator) * signum(self.denominator))
new_denominator = self.denominator / n
self.numerator = temporary(new_numerator)
self.denominator = temporary(new_denominator)
end
function rat::numerator
compile_opt idl2, hidden
return, self.numerator
end
function rat::denominator
compile_opt idl2, hidden
return, self.denominator
end
pro rat::add, q
compile_opt idl2, hidden
n = lcm(self.denominator, q->denominator())
new_numerator = (n / self.denominator) * self.numerator + $
(n / q->denominator()) * q->numerator()
new_denominator = n
self.numerator = temporary(new_numerator)
self.denominator = temporary(new_denominator)
self.normalize
end
pro rat::sub, q
compile_opt idl2, hidden
r = obj_new('rat', -q->numerator(), q->denominator())
self.add, r
obj_destroy, r
end
pro rat::mul, r, q
compile_opt idl2, hidden
self.numerator = self.numerator * q->numerator()
self.denominator = self.denominator * q->denominator()
self.normalize
end
pro rat::div, q
compile_opt idl2, hidden
r = obj_new('rat', q->denominator(), q->numerator())
self.mul, r
obj_destroy, r
end
function rat::INIT, numerator, denominator
compile_opt idl2, hidden
if (n_params() eq 2) then begin
self.numerator = numerator
self.denominator = denominator
endif $
else if (obj_valid(numerator)) then begin
; numerator is actually a "rat" object
self.numerator = numerator->numerator()
self.denominator = numerator->denominator()
endif
return, 1
end
pro rat__define, class
compile_opt idl2, hidden
class = { rat, $
numerator: 0., $
denominator: 0. $
}
end
pro print_bottle, n, verbose=verbose
compile_opt idl2
on_error, 2
verbose = keyword_set(verbose)
!quiet = ~verbose
if (verbose) then begin
case (n) of
2: begin
print, n, format='(I0, 1X, "bottles of beer on the wall,")'
print, n, format='(I0, 1X, "bottles of beer.")'
print, format='("Take one down, pass it around,")'
print, format='("one last bottle of beer on the wall.", /)'
end
1: begin
print, n, format='("One last bottle of beer on the wall,")'
print, n, format='("one last bottle of beer.")'
print, format='("Take one down, pass it around,")'
print, format='("no more bottles of beer on the wall.", /)'
end
default: begin
print, n, format='(I0, 1X, "bottles of beer on the wall,")'
print, n, format='(I0, 1X, "bottles of beer.")'
print, format='("Take one down, pass it around,")'
print, n - 1, format='(I0, 1X, "bottles of beer on the wall.", /)'
end
endcase
endif
end
pro bottles
compile_opt idl2
on_error, 2
towels = 'Don''t Panic!'
nbottles = 99S
r = obj_new('rat', 1, 2)
q = obj_new('rat', 1, 6)
while (nbottles gt '0'XULL) do begin
print_bottle, nbottles
nbottles -= 1
endwhile
print, (towels ne '') ? towels : 'Panic!'
stop
r->sub, q
print, r->numerator(), r->denominator(), format='(I0, "/", I0)'
end