1require 'test/unit' 2 3class ComplexRational_Test < Test::Unit::TestCase 4 5 def test_rat_srat 6 skip unless defined?(Rational) 7 8 c = SimpleRat(1,3) 9 cc = Rational(3,2) 10 11 assert_kind_of(Numeric, c) 12 assert_kind_of(Numeric, cc) 13 14 assert_instance_of(SimpleRat, c) 15 assert_instance_of(Rational, cc) 16 17 assert_equal(SimpleRat(1,3), +c) 18 assert_equal(SimpleRat(-1,3), -c) 19 20 assert_equal(SimpleRat(7,3), c + 2) 21 assert_equal(SimpleRat(-5,3), c - 2) 22 assert_equal(SimpleRat(2,3), c * 2) 23 assert_equal(SimpleRat(1,6), c / 2) 24 assert_equal(SimpleRat(1,9), c ** 2) 25 assert_equal(-1, c <=> 2) 26 27 assert_equal(SimpleRat(7,3), 2 + c) 28 assert_equal(SimpleRat(5,3), 2 - c) 29 assert_equal(SimpleRat(2,3), 2 * c) 30 assert_equal(SimpleRat(6,1), 2 / c) 31 assert_in_delta(1.2599, 2 ** c, 0.001) 32 assert_equal(1, 2 <=> c) 33 34 assert_equal(SimpleRat(11,6), c + cc) 35 assert_equal(SimpleRat(-7,6), c - cc) 36 assert_equal(SimpleRat(1,2), c * cc) 37 assert_equal(SimpleRat(2,9), c / cc) 38 assert_in_delta(0.1924, c ** cc, 0.001) 39 assert_equal(-1, c <=> cc) 40 41 assert_equal(SimpleRat(11,6), cc + c) 42 assert_equal(SimpleRat(7,6), cc - c) 43 assert_equal(SimpleRat(1,2), cc * c) 44 assert_equal(SimpleRat(9,2), cc / c) 45 assert_in_delta(1.1447, cc ** c, 0.001) 46 assert_equal(1, cc <=> c) 47 48 assert_equal(SimpleRat, (+c).class) 49 assert_equal(SimpleRat, (-c).class) 50 51 assert_equal(SimpleRat, (c + 2).class) 52 assert_equal(SimpleRat, (c - 2).class) 53 assert_equal(SimpleRat, (c * 2).class) 54 assert_equal(SimpleRat, (c / 2).class) 55 assert_equal(SimpleRat, (c ** 2).class) 56 57 assert_equal(SimpleRat, (2 + c).class) 58 assert_equal(SimpleRat, (2 - c).class) 59 assert_equal(SimpleRat, (2 * c).class) 60 assert_equal(SimpleRat, (2 / c).class) 61 assert_equal(Float, (2 ** c).class) 62 63 assert_equal(SimpleRat, (c + cc).class) 64 assert_equal(SimpleRat, (c - cc).class) 65 assert_equal(SimpleRat, (c * cc).class) 66 assert_equal(SimpleRat, (c / cc).class) 67 assert_equal(Float, (c ** cc).class) 68 69 assert_equal(SimpleRat, (cc + c).class) 70 assert_equal(SimpleRat, (cc - c).class) 71 assert_equal(SimpleRat, (cc * c).class) 72 assert_equal(SimpleRat, (cc / c).class) 73 assert_equal(Float, (cc ** c).class) 74 75 assert_equal(0, Rational(2,3) <=> SimpleRat(2,3)) 76 assert_equal(0, SimpleRat(2,3) <=> Rational(2,3)) 77 assert(Rational(2,3) == SimpleRat(2,3)) 78 assert(SimpleRat(2,3) == Rational(2,3)) 79 80 assert_equal(SimpleRat, (c + 0).class) 81 assert_equal(SimpleRat, (c - 0).class) 82 assert_equal(SimpleRat, (c * 0).class) 83 assert_equal(SimpleRat, (c * 1).class) 84 assert_equal(SimpleRat, (0 + c).class) 85 assert_equal(SimpleRat, (0 - c).class) 86 assert_equal(SimpleRat, (0 * c).class) 87 assert_equal(SimpleRat, (1 * c).class) 88 end 89 90 def test_comp_srat 91 skip unless defined?(Rational) 92 93 c = Complex(SimpleRat(2,3),SimpleRat(1,2)) 94 cc = Complex(Rational(3,2),Rational(2,1)) 95 96 assert_equal(Complex(SimpleRat(2,3),SimpleRat(1,2)), +c) 97 assert_equal(Complex(SimpleRat(-2,3),SimpleRat(-1,2)), -c) 98 99 assert_equal(Complex(SimpleRat(8,3),SimpleRat(1,2)), c + 2) 100 assert_equal(Complex(SimpleRat(-4,3),SimpleRat(1,2)), c - 2) 101 assert_equal(Complex(SimpleRat(4,3),SimpleRat(1,1)), c * 2) 102 assert_equal(Complex(SimpleRat(1,3),SimpleRat(1,4)), c / 2) 103 assert_equal(Complex(SimpleRat(7,36),SimpleRat(2,3)), c ** 2) 104 assert_raise(NoMethodError){c <=> 2} 105 106 assert_equal(Complex(SimpleRat(8,3),SimpleRat(1,2)), 2 + c) 107 assert_equal(Complex(SimpleRat(4,3),SimpleRat(-1,2)), 2 - c) 108 assert_equal(Complex(SimpleRat(4,3),SimpleRat(1,1)), 2 * c) 109 assert_equal(Complex(SimpleRat(48,25),SimpleRat(-36,25)), 2 / c) 110 r = 2 ** c 111 assert_in_delta(1.4940, r.real, 0.001) 112 assert_in_delta(0.5392, r.imag, 0.001) 113 assert_raise(NoMethodError){2 <=> c} 114 115 assert_equal(Complex(SimpleRat(13,6),SimpleRat(5,2)), c + cc) 116 assert_equal(Complex(SimpleRat(-5,6),SimpleRat(-3,2)), c - cc) 117 assert_equal(Complex(SimpleRat(0,1),SimpleRat(25,12)), c * cc) 118 assert_equal(Complex(SimpleRat(8,25),SimpleRat(-7,75)), c / cc) 119 r = c ** cc 120 assert_in_delta(0.1732, r.real, 0.001) 121 assert_in_delta(0.1186, r.imag, 0.001) 122 assert_raise(NoMethodError){c <=> cc} 123 124 assert_equal(Complex(SimpleRat(13,6),SimpleRat(5,2)), cc + c) 125 assert_equal(Complex(SimpleRat(5,6),SimpleRat(3,2)), cc - c) 126 assert_equal(Complex(SimpleRat(0,1),SimpleRat(25,12)), cc * c) 127 assert_equal(Complex(SimpleRat(72,25),SimpleRat(21,25)), cc / c) 128 r = cc ** c 129 assert_in_delta(0.5498, r.real, 0.001) 130 assert_in_delta(1.0198, r.imag, 0.001) 131 assert_raise(NoMethodError){cc <=> c} 132 133 assert_equal([SimpleRat,SimpleRat], 134 (+c).instance_eval{[real.class, imag.class]}) 135 assert_equal([SimpleRat,SimpleRat], 136 (-c).instance_eval{[real.class, imag.class]}) 137 138 assert_equal([SimpleRat,SimpleRat], 139 (c + 2).instance_eval{[real.class, imag.class]}) 140 assert_equal([SimpleRat,SimpleRat], 141 (c - 2).instance_eval{[real.class, imag.class]}) 142 assert_equal([SimpleRat,SimpleRat], 143 (c * 2).instance_eval{[real.class, imag.class]}) 144 assert_equal([SimpleRat,SimpleRat], 145 (c / 2).instance_eval{[real.class, imag.class]}) 146 assert_equal([SimpleRat,SimpleRat], 147 (c ** 2).instance_eval{[real.class, imag.class]}) 148 149 assert_equal([SimpleRat,SimpleRat], 150 (c + cc).instance_eval{[real.class, imag.class]}) 151 assert_equal([SimpleRat,SimpleRat], 152 (c - cc).instance_eval{[real.class, imag.class]}) 153 assert_equal([SimpleRat,SimpleRat], 154 (c * cc).instance_eval{[real.class, imag.class]}) 155 assert_equal([SimpleRat,SimpleRat], 156 (c / cc).instance_eval{[real.class, imag.class]}) 157 assert_equal([Float,Float], 158 (c ** cc).instance_eval{[real.class, imag.class]}) 159 160 assert_equal([SimpleRat,SimpleRat], 161 (cc + c).instance_eval{[real.class, imag.class]}) 162 assert_equal([SimpleRat,SimpleRat], 163 (cc - c).instance_eval{[real.class, imag.class]}) 164 assert_equal([SimpleRat,SimpleRat], 165 (cc * c).instance_eval{[real.class, imag.class]}) 166 assert_equal([SimpleRat,SimpleRat], 167 (cc / c).instance_eval{[real.class, imag.class]}) 168 assert_equal([Float,Float], 169 (cc ** c).instance_eval{[real.class, imag.class]}) 170 171 assert(Complex(SimpleRat(2,3),SimpleRat(3,2)) == 172 Complex(Rational(2,3),Rational(3,2))) 173 assert(Complex(Rational(2,3),Rational(3,2)) == 174 Complex(SimpleRat(2,3),SimpleRat(3,2))) 175 176 assert_equal([SimpleRat,SimpleRat], 177 (c + 0).instance_eval{[real.class, imag.class]}) 178 assert_equal([SimpleRat,SimpleRat], 179 (c - 0).instance_eval{[real.class, imag.class]}) 180 assert_equal([SimpleRat,SimpleRat], 181 (c * 0).instance_eval{[real.class, imag.class]}) 182 assert_equal([SimpleRat,SimpleRat], 183 (c * 1).instance_eval{[real.class, imag.class]}) 184 assert_equal([SimpleRat,SimpleRat], 185 (0 + c).instance_eval{[real.class, imag.class]}) 186 assert_equal([SimpleRat,SimpleRat], 187 (0 - c).instance_eval{[real.class, imag.class]}) 188 assert_equal([SimpleRat,SimpleRat], 189 (0 * c).instance_eval{[real.class, imag.class]}) 190 assert_equal([SimpleRat,SimpleRat], 191 (1 * c).instance_eval{[real.class, imag.class]}) 192 end 193 194end 195 196def SimpleRat(*a) SimpleRat.new(*a) end 197 198class SimpleRat < Numeric 199 200 def initialize(num, den = 1) 201 if den == 0 202 raise ZeroDivisionError, "divided by zero" 203 end 204 if den < 0 205 num = -num 206 den = -den 207 end 208 gcd = num.gcd(den) 209 @num = num.div(gcd) 210 @den = den.div(gcd) 211 end 212 213 def numerator() @num end 214 def denominator() @den end 215 216 def +@ () self end 217 def -@ () self.class.new(-@num, @den) end 218 219 def + (o) 220 case o 221 when SimpleRat, Rational 222 a = @num * o.denominator 223 b = o.numerator * @den 224 self.class.new(a + b, @den * o.denominator) 225 when Integer 226 self + self.class.new(o) 227 when Float 228 to_f + o 229 else 230 x, y = o.coerce(self) 231 x + y 232 end 233 end 234 235 def - (o) 236 case o 237 when SimpleRat, Rational 238 a = @num * o.denominator 239 b = o.numerator * @den 240 self.class.new(a - b, @den * o.denominator) 241 when Integer 242 self - self.class.new(o) 243 when Float 244 to_f - o 245 else 246 x, y = o.coerce(self) 247 x - y 248 end 249 end 250 251 def * (o) 252 case o 253 when SimpleRat, Rational 254 a = @num * o.numerator 255 b = @den * o.denominator 256 self.class.new(a, b) 257 when Integer 258 self * self.class.new(o) 259 when Float 260 to_f * o 261 else 262 x, y = o.coerce(self) 263 x * y 264 end 265 end 266 267 def quo(o) 268 case o 269 when SimpleRat, Rational 270 a = @num * o.denominator 271 b = @den * o.numerator 272 self.class.new(a, b) 273 when Integer 274 if o == 0 275 raise raise ZeroDivisionError, "divided by zero" 276 end 277 self.quo(self.class.new(o)) 278 when Float 279 to_f.quo(o) 280 else 281 x, y = o.coerce(self) 282 x.quo(y) 283 end 284 end 285 286 alias / quo 287 288 def floor 289 @num.div(@den) 290 end 291 292 def ceil 293 -((-@num).div(@den)) 294 end 295 296 def truncate 297 if @num < 0 298 return -((-@num).div(@den)) 299 end 300 @num.div(@den) 301 end 302 303 alias to_i truncate 304 305 def round 306 if @num < 0 307 num = -@num 308 num = num * 2 + @den 309 den = @den * 2 310 -(num.div(den)) 311 else 312 num = @num * 2 + @den 313 den = @den * 2 314 num.div(den) 315 end 316 end 317 318 def div(o) (self / o).floor end 319 def quot(o) (self / o).truncate end 320 321 def modulo(o) 322 q = div(o) 323 self - o * q 324 end 325 326 def remainder(o) 327 q = quot(o) 328 self - o * q 329 end 330 331 alias % modulo 332 333 def divmod(o) [div(o), modulo(o)] end 334 def quotrem(o) [quot(o), remainder(o)] end 335 336 def ** (o) 337 case o 338 when SimpleRat, Rational 339 Float(self) ** o 340 when Integer 341 if o > 0 342 a = @num ** o 343 b = @den ** o 344 elsif o < 0 345 a = @den ** -o 346 b = @num ** -o 347 else 348 a = b = 1 349 end 350 self.class.new(a, b) 351 when Float 352 to_f ** o 353 else 354 x, y = o.coerce(self) 355 x ** y 356 end 357 end 358 359 def <=> (o) 360 case o 361 when SimpleRat, Rational 362 a = @num * o.denominator 363 b = o.numerator * @den 364 return a <=> b 365 when Integer 366 self <=> self.class.new(o) 367 when Float 368 to_f <=> o 369 else 370 x, y = o.coerce(self) 371 x <=> y 372 end 373 end 374 375 def == (o) 376 begin 377 (self <=> o) == 0 378 rescue 379 false 380 end 381 end 382 383 def coerce(o) 384 case o 385 when Rational 386 [self.class.new(o.numerator, o.denominator), self] 387 when Integer 388 [self.class.new(o), self] 389 when Float 390 [o, self.to_f] 391 else 392 super 393 end 394 end 395 396 def hash() @num.hash ^ @den.hash end 397 398 def to_f() @num.to_f / @den.to_f end 399 def to_r() self end 400 def to_s() format('%s/%s', @num, @den) end 401 402 def inspect() format('#SR(%s)', to_s) end 403 404 def marshal_dump() [@num, @den] end 405 def marshal_load(a) @num, @den = a end 406 407end 408