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
|