1 | class Complex < Numeric
|
---|
2 | def self.polar(abs, arg = 0)
|
---|
3 | Complex(abs * Math.cos(arg), abs * Math.sin(arg))
|
---|
4 | end
|
---|
5 |
|
---|
6 | def inspect
|
---|
7 | "(#{to_s})"
|
---|
8 | end
|
---|
9 |
|
---|
10 | def to_s
|
---|
11 | "#{real}#{'+' unless imaginary < 0}#{imaginary}i"
|
---|
12 | end
|
---|
13 |
|
---|
14 | def +@
|
---|
15 | Complex(real, imaginary)
|
---|
16 | end
|
---|
17 |
|
---|
18 | def -@
|
---|
19 | Complex(-real, -imaginary)
|
---|
20 | end
|
---|
21 |
|
---|
22 | def +(rhs)
|
---|
23 | if rhs.is_a? Complex
|
---|
24 | Complex(real + rhs.real, imaginary + rhs.imaginary)
|
---|
25 | elsif rhs.is_a? Numeric
|
---|
26 | Complex(real + rhs, imaginary)
|
---|
27 | end
|
---|
28 | end
|
---|
29 |
|
---|
30 | def -(rhs)
|
---|
31 | if rhs.is_a? Complex
|
---|
32 | Complex(real - rhs.real, imaginary - rhs.imaginary)
|
---|
33 | elsif rhs.is_a? Numeric
|
---|
34 | Complex(real - rhs, imaginary)
|
---|
35 | end
|
---|
36 | end
|
---|
37 |
|
---|
38 | def *(rhs)
|
---|
39 | if rhs.is_a? Complex
|
---|
40 | Complex(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary)
|
---|
41 | elsif rhs.is_a? Numeric
|
---|
42 | Complex(real * rhs, imaginary * rhs)
|
---|
43 | end
|
---|
44 | end
|
---|
45 |
|
---|
46 | def /(rhs)
|
---|
47 | if rhs.is_a? Complex
|
---|
48 | __div__(rhs)
|
---|
49 | elsif rhs.is_a? Numeric
|
---|
50 | Complex(real / rhs, imaginary / rhs)
|
---|
51 | end
|
---|
52 | end
|
---|
53 | alias_method :quo, :/
|
---|
54 |
|
---|
55 | def ==(rhs)
|
---|
56 | if rhs.is_a? Complex
|
---|
57 | real == rhs.real && imaginary == rhs.imaginary
|
---|
58 | elsif rhs.is_a? Numeric
|
---|
59 | imaginary == 0 && real == rhs
|
---|
60 | end
|
---|
61 | end
|
---|
62 |
|
---|
63 | def abs
|
---|
64 | Math.hypot imaginary, real
|
---|
65 | end
|
---|
66 | alias_method :magnitude, :abs
|
---|
67 |
|
---|
68 | def abs2
|
---|
69 | real * real + imaginary * imaginary
|
---|
70 | end
|
---|
71 |
|
---|
72 | def arg
|
---|
73 | Math.atan2 imaginary, real
|
---|
74 | end
|
---|
75 | alias_method :angle, :arg
|
---|
76 | alias_method :phase, :arg
|
---|
77 |
|
---|
78 | def conjugate
|
---|
79 | Complex(real, -imaginary)
|
---|
80 | end
|
---|
81 | alias_method :conj, :conjugate
|
---|
82 |
|
---|
83 | def fdiv(numeric)
|
---|
84 | Complex(real.to_f / numeric, imaginary.to_f / numeric)
|
---|
85 | end
|
---|
86 |
|
---|
87 | def polar
|
---|
88 | [abs, arg]
|
---|
89 | end
|
---|
90 |
|
---|
91 | def real?
|
---|
92 | false
|
---|
93 | end
|
---|
94 |
|
---|
95 | def rectangular
|
---|
96 | [real, imaginary]
|
---|
97 | end
|
---|
98 | alias_method :rect, :rectangular
|
---|
99 |
|
---|
100 | def to_r
|
---|
101 | raise RangeError.new "can't convert #{to_s} into Rational" unless imaginary.zero?
|
---|
102 | Rational(real, 1)
|
---|
103 | end
|
---|
104 |
|
---|
105 | alias_method :imag, :imaginary
|
---|
106 |
|
---|
107 | [Fixnum, Float].each do |cls|
|
---|
108 | [:+, :-, :*, :/, :==].each do |op|
|
---|
109 | cls.instance_eval do
|
---|
110 | original_operator_name = "__original_operator_#{op}_complex"
|
---|
111 | alias_method original_operator_name, op
|
---|
112 | define_method op do |rhs|
|
---|
113 | if rhs.is_a? Complex
|
---|
114 | Complex(self).__send__(op, rhs)
|
---|
115 | else
|
---|
116 | __send__(original_operator_name, rhs)
|
---|
117 | end
|
---|
118 | end
|
---|
119 | end
|
---|
120 | end
|
---|
121 | end
|
---|
122 | end
|
---|